Skip to content

Commit 6347a3f

Browse files
authored
Merge pull request #3812 from microDev1/ota-s2
Support for OTA update
2 parents df8cba1 + 4512290 commit 6347a3f

File tree

11 files changed

+356
-0
lines changed

11 files changed

+356
-0
lines changed

locale/circuitpython.pot

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,10 @@ msgstr ""
936936
msgid "Filters too complex"
937937
msgstr ""
938938

939+
#: ports/esp32s2/common-hal/dualbank/__init__.c
940+
msgid "Firmware image is invalid"
941+
msgstr ""
942+
939943
#: ports/cxd56/common-hal/camera/Camera.c
940944
msgid "Format not supported"
941945
msgstr ""
@@ -1983,6 +1987,10 @@ msgstr ""
19831987
msgid "Unsupported pull value."
19841988
msgstr ""
19851989

1990+
#: ports/esp32s2/common-hal/dualbank/__init__.c
1991+
msgid "Update Failed"
1992+
msgstr ""
1993+
19861994
#: ports/nrf/common-hal/_bleio/Characteristic.c
19871995
#: ports/nrf/common-hal/_bleio/Descriptor.c
19881996
msgid "Value length != required fixed length"
@@ -3211,6 +3219,10 @@ msgstr ""
32113219
msgid "offset is too large"
32123220
msgstr ""
32133221

3222+
#: shared-bindings/dualbank/__init__.c
3223+
msgid "offset must be >= 0"
3224+
msgstr ""
3225+
32143226
#: py/objstr.c py/objstrunicode.c
32153227
msgid "offset out of bounds"
32163228
msgstr ""

ports/esp32s2/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ INC += -isystem esp-idf/components/heap/include
106106
INC += -isystem esp-idf/components/esp_system/include
107107
INC += -isystem esp-idf/components/spi_flash/include
108108
INC += -isystem esp-idf/components/nvs_flash/include
109+
INC += -isystem esp-idf/components/app_update/include
110+
INC += -isystem esp-idf/components/bootloader_support/include
109111
INC += -I$(BUILD)/esp-idf/config
110112

111113
CFLAGS += -DHAVE_CONFIG_H \
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 microDev
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#include "common-hal/dualbank/__init__.h"
28+
#include "shared-bindings/dualbank/__init__.h"
29+
30+
#include <string.h>
31+
32+
#include "esp_log.h"
33+
#include "esp_ota_ops.h"
34+
35+
static const esp_partition_t *update_partition = NULL;
36+
static esp_ota_handle_t update_handle = 0;
37+
38+
static const char *TAG = "dualbank";
39+
40+
void dualbank_reset(void) {
41+
// should use `abort` instead of `end`
42+
// but not in idf v4.2
43+
// esp_ota_abort(update_handle);
44+
if (esp_ota_end(update_handle) == ESP_OK) {
45+
update_handle = 0;
46+
update_partition = NULL;
47+
}
48+
}
49+
50+
static void __attribute__((noreturn)) task_fatal_error(void) {
51+
ESP_LOGE(TAG, "Exiting task due to fatal error...");
52+
mp_raise_RuntimeError(translate("Update Failed"));
53+
}
54+
55+
void common_hal_dualbank_flash(const void *buf, const size_t len, const size_t offset) {
56+
esp_err_t err;
57+
58+
const esp_partition_t *running = esp_ota_get_running_partition();
59+
const esp_partition_t *last_invalid = esp_ota_get_last_invalid_partition();
60+
61+
if (update_partition == NULL) {
62+
update_partition = esp_ota_get_next_update_partition(NULL);
63+
64+
ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)",
65+
running->type, running->subtype, running->address);
66+
67+
ESP_LOGI(TAG, "Writing partition type %d subtype %d (offset 0x%08x)\n",
68+
update_partition->type, update_partition->subtype, update_partition->address);
69+
70+
assert(update_partition != NULL);
71+
}
72+
73+
if (update_handle == 0) {
74+
if (len > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) {
75+
esp_app_desc_t new_app_info;
76+
memcpy(&new_app_info, &((char *)buf)[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t));
77+
ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version);
78+
79+
esp_app_desc_t running_app_info;
80+
if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) {
81+
ESP_LOGI(TAG, "Running firmware version: %s", running_app_info.version);
82+
}
83+
84+
esp_app_desc_t invalid_app_info;
85+
if (esp_ota_get_partition_description(last_invalid, &invalid_app_info) == ESP_OK) {
86+
ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version);
87+
}
88+
89+
// check new version with running version
90+
if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) {
91+
ESP_LOGW(TAG, "New version is the same as running version.");
92+
task_fatal_error();
93+
}
94+
95+
// check new version with last invalid partition
96+
if (last_invalid != NULL) {
97+
if (memcmp(new_app_info.version, invalid_app_info.version, sizeof(new_app_info.version)) == 0) {
98+
ESP_LOGW(TAG, "New version is the same as invalid version.");
99+
task_fatal_error();
100+
}
101+
}
102+
103+
err = esp_ota_begin(update_partition, OTA_WITH_SEQUENTIAL_WRITES, &update_handle);
104+
if (err != ESP_OK) {
105+
ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err));
106+
task_fatal_error();
107+
}
108+
} else {
109+
ESP_LOGE(TAG, "received package is not fit len");
110+
task_fatal_error();
111+
}
112+
}
113+
114+
if (offset == 0) {
115+
err = esp_ota_write(update_handle, buf, len);
116+
} else {
117+
err = esp_ota_write_with_offset(update_handle, buf, len, offset);
118+
}
119+
if (err != ESP_OK) {
120+
ESP_LOGE(TAG, "esp_ota_write failed (%s)", esp_err_to_name(err));
121+
task_fatal_error();
122+
}
123+
}
124+
125+
void common_hal_dualbank_switch(void) {
126+
if (esp_ota_end(update_handle) == ESP_OK) {
127+
update_handle = 0;
128+
update_partition = NULL;
129+
}
130+
esp_err_t err = esp_ota_set_boot_partition(esp_ota_get_next_update_partition(NULL));
131+
if (err != ESP_OK) {
132+
if (err == ESP_ERR_OTA_VALIDATE_FAILED) {
133+
ESP_LOGE(TAG, "Image validation failed, image is corrupted");
134+
mp_raise_RuntimeError(translate("Firmware image is invalid"));
135+
}
136+
ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err));
137+
task_fatal_error();
138+
}
139+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2020 microDev
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef MICROPY_INCLUDED_ESP32S2_COMMON_HAL_DUALBANK___INIT___H
28+
#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_DUALBANK___INIT___H
29+
30+
extern void dualbank_reset(void);
31+
32+
#endif //MICROPY_INCLUDED_ESP32S2_COMMON_HAL_DUALBANK___INIT___H

ports/esp32s2/mpconfigport.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ CIRCUITPY_AUDIOBUSIO = 0
1919
CIRCUITPY_AUDIOIO = 0
2020
CIRCUITPY_CANIO = 1
2121
CIRCUITPY_COUNTIO = 1
22+
CIRCUITPY_DUALBANK = 1
2223
CIRCUITPY_FREQUENCYIO = 1
2324
CIRCUITPY_I2CPERIPHERAL = 0
2425
CIRCUITPY_ROTARYIO = 1

ports/esp32s2/supervisor/port.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "common-hal/busio/I2C.h"
4242
#include "common-hal/busio/SPI.h"
4343
#include "common-hal/busio/UART.h"
44+
#include "common-hal/dualbank/__init__.h"
4445
#include "common-hal/ps2io/Ps2.h"
4546
#include "common-hal/pulseio/PulseIn.h"
4647
#include "common-hal/pwmio/PWMOut.h"
@@ -123,6 +124,10 @@ void reset_port(void) {
123124
analogout_reset();
124125
#endif
125126

127+
#if CIRCUITPY_DUALBANK
128+
dualbank_reset();
129+
#endif
130+
126131
#if CIRCUITPY_PS2IO
127132
ps2_reset();
128133
#endif

py/circuitpy_defns.mk

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@ endif
205205
ifeq ($(CIRCUITPY_OS),1)
206206
SRC_PATTERNS += os/%
207207
endif
208+
ifeq ($(CIRCUITPY_DUALBANK),1)
209+
SRC_PATTERNS += dualbank/%
210+
endif
208211
ifeq ($(CIRCUITPY_PIXELBUF),1)
209212
SRC_PATTERNS += _pixelbuf/%
210213
endif
@@ -348,6 +351,7 @@ SRC_COMMON_HAL_ALL = \
348351
nvm/ByteArray.c \
349352
nvm/__init__.c \
350353
os/__init__.c \
354+
dualbank/__init__.c \
351355
ps2io/Ps2.c \
352356
ps2io/__init__.c \
353357
pulseio/PulseIn.c \

py/circuitpy_mpconfig.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,13 @@ extern const struct _mp_obj_module_t os_module;
539539
#define OS_MODULE_ALT_NAME
540540
#endif
541541

542+
#if CIRCUITPY_DUALBANK
543+
extern const struct _mp_obj_module_t dualbank_module;
544+
#define DUALBANK_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_dualbank), (mp_obj_t)&dualbank_module },
545+
#else
546+
#define DUALBANK_MODULE
547+
#endif
548+
542549
#if CIRCUITPY_PEW
543550
extern const struct _mp_obj_module_t pew_module;
544551
#define PEW_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR__pew),(mp_obj_t)&pew_module },
@@ -827,6 +834,7 @@ extern const struct _mp_obj_module_t wifi_module;
827834
NETWORK_MODULE \
828835
SOCKET_MODULE \
829836
WIZNET_MODULE \
837+
DUALBANK_MODULE \
830838
PEW_MODULE \
831839
PIXELBUF_MODULE \
832840
PS2IO_MODULE \

py/circuitpy_mpconfig.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ CFLAGS += -DCIRCUITPY_NVM=$(CIRCUITPY_NVM)
179179
CIRCUITPY_OS ?= 1
180180
CFLAGS += -DCIRCUITPY_OS=$(CIRCUITPY_OS)
181181

182+
CIRCUITPY_DUALBANK ?= 0
183+
CFLAGS += -DCIRCUITPY_DUALBANK=$(CIRCUITPY_DUALBANK)
184+
182185
CIRCUITPY_PIXELBUF ?= $(CIRCUITPY_FULL_BUILD)
183186
CFLAGS += -DCIRCUITPY_PIXELBUF=$(CIRCUITPY_PIXELBUF)
184187

0 commit comments

Comments
 (0)