Skip to content

Commit d6e431c

Browse files
committed
esp8266: Add support for firmware update from a file on LFS2 filesystem.
lib/littlefs/lfs2.c: installed a hook in LFS2 to dig sectors for DFU. ports/esp8266/modesp.c: core functions for DFU. ports/esp8266/modules/inisetup.py: user functions for DFU. ports/esp8266/main.c: more heap memory (tested working). ports/esp8266/esppwm.c: higher PWM frequency limit for IR control. ports/.../esp8266_common.ld: migrated 3 functions for more IRAM space. ports/.../mpconfigboard.h: this DFU is only for ESP8266 2MB+ Signed-off-by: Wang Xuancong <xuancong84@gmail.com>
1 parent dc99840 commit d6e431c

File tree

9 files changed

+977
-769
lines changed

9 files changed

+977
-769
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ user.props
2323

2424
# MacOS desktop metadata files
2525
.DS_Store
26+
ports/esp8266/modules/*.py

lib/littlefs/lfs2.c

Lines changed: 782 additions & 766 deletions
Large diffs are not rendered by default.

ports/esp8266/Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \
7171
-Wl,-EL -mlongcalls -mtext-section-literals -mforce-l32 \
7272
-DLWIP_OPEN_SRC
7373

74-
CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
74+
CFLAGS += $(INC) -Wall -Wpointer-arith -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
7575
$(CFLAGS_XTENSA) $(COPT) $(CFLAGS_EXTRA) -I$(BOARD_DIR)
7676

7777
LD_FILES ?= boards/esp8266_2m.ld
@@ -83,6 +83,10 @@ CFLAGS += -DMICROPY_ESPNOW=1
8383
LIBS += -lespnow
8484
endif
8585

86+
ifeq ($(MICROPY_DFU),1)
87+
CFLAGS += -DMICROPY_DFU
88+
endif
89+
8690
LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
8791
LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc
8892

ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.mk

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ MICROPY_ESPNOW ?= 1
55
MICROPY_PY_BTREE ?= 1
66
MICROPY_VFS_FAT ?= 1
77
MICROPY_VFS_LFS2 ?= 1
8+
MICROPY_DFU ?= 1
89

910
# Add asyncio and extra micropython-lib packages (in addition to the port manifest).
1011
FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest_2MiB.py

ports/esp8266/boards/esp8266_common.ld

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ SECTIONS
182182

183183
/* for -mforce-l32 */
184184
*/*.o(.rodata*)
185+
*modespnow.o(.text.espnow_del_peer .text.espnow_add_peer .text.espnow_config)
185186

186187
_irom0_text_end = ABSOLUTE(.);
187188
} >irom0_0_seg :irom0_0_phdr

ports/esp8266/esppwm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
#define PWM_CHANNEL 8
2828
#define PWM_DEPTH 1023
29-
#define PWM_FREQ_MAX 1000
29+
#define PWM_FREQ_MAX 60000
3030
#define PWM_1S 1000000
3131

3232
struct pwm_single_param {

ports/esp8266/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
#include "modespnow.h"
5050
#endif
5151

52-
STATIC char heap[38 * 1024];
52+
STATIC char heap[45 * 1024];
5353

5454
STATIC void mp_reset(void) {
5555
mp_stack_set_top((void *)0x40000000);

ports/esp8266/modesp.c

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,147 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_set_native_code_location_obj, esp_set_nativ
339339

340340
#endif
341341

342+
/*
343+
#include <stdarg.h>
344+
int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args);
345+
STATIC void _strncat(char *data, const char *str, size_t len){
346+
int len_data = strlen(data);
347+
memcpy(&data[len_data], str, len);
348+
data[len_data+len] = 0;
349+
}
350+
351+
STATIC int _sprintf(char *_buf, const char *fmt, ...) {
352+
mp_print_t buf = {(void*)_buf, _strncat};
353+
va_list ap;
354+
va_start(ap, fmt);
355+
int ret = mp_vprintf(&buf, fmt, ap);
356+
va_end(ap);
357+
return ret;
358+
}
359+
360+
STATIC void showMemory(char *ptr, size_t size){
361+
char buf[16];
362+
for(int x=0; x<size;){
363+
buf[0] = 0;
364+
_sprintf(&buf[0], "%02x ", ptr[x++]);
365+
if(x%32==0)_sprintf(&buf[0], "\r\n");
366+
else if(x%16==0)_sprintf(&buf[0], " ");
367+
else if(x%8==0)_sprintf(&buf[0], " ");
368+
mp_hal_stdout_tx_str(&buf[0]);
369+
ets_loop_iter();
370+
}
371+
mp_hal_stdout_tx_str("\r\n");
372+
}
373+
STATIC mp_obj_t esp_showMemory(mp_obj_t _start, mp_obj_t _size) {
374+
showMemory((char*)mp_obj_get_int(_start), mp_obj_get_int(_size));
375+
return mp_const_none;
376+
}
377+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_showMemory_obj, esp_showMemory);
378+
*/
379+
#ifdef MICROPY_DFU
380+
uint16_t dfu_blks[256];
381+
uint16_t dfu_offs[256];
382+
int dfu_nblks = -1;
383+
uint32_t dfu_fwsize = 0;
384+
385+
/* Firmware update codes must be put into IRAM, or will crash while flashing halfway! */
386+
void MP_FASTCODE(erase_sector)(int sector) {
387+
char *ptr = FLASH_START + sector * FLASH_SEC_SIZE;
388+
for (char *PTR = ptr + FLASH_SEC_SIZE; ptr < PTR; ptr++) {
389+
if (*ptr != 0xff) {
390+
SPIEraseSector(sector);
391+
break;
392+
}
393+
}
394+
}
395+
void MP_FASTCODE(DFU)(char *dfu_buf, int n_fwblks, int n_erase) {
396+
for (int x = 0; x < n_fwblks; x++) {
397+
erase_sector(x);
398+
// uart_tx_one_char(0, 'E');
399+
}
400+
401+
int cur_write_pos = 0;
402+
int cur_write_sz;
403+
int remaining_sz = dfu_fwsize;
404+
405+
for (int x = 0; x < dfu_nblks && remaining_sz > 0; x++) {
406+
cur_write_sz = FLASH_SEC_SIZE - dfu_offs[x];
407+
if (remaining_sz < cur_write_sz) {
408+
cur_write_sz = remaining_sz;
409+
}
410+
411+
Cache_Read_Disable_2();
412+
SPIRead(1048576 + FLASH_SEC_SIZE * dfu_blks[x] + dfu_offs[x], (uint32_t *)dfu_buf, cur_write_sz);
413+
Cache_Read_Enable_2();
414+
// uart_tx_one_char(0, 'R');
415+
if (x == 0) {
416+
dfu_buf[3] = 64;
417+
}
418+
SPIWrite(cur_write_pos, (uint32_t *)dfu_buf, cur_write_sz);
419+
// uart_tx_one_char(0, 'W');
420+
421+
cur_write_pos += cur_write_sz;
422+
remaining_sz -= cur_write_sz;
423+
wdt_feed();
424+
}
425+
426+
for (int x = n_fwblks; x < n_erase; x++) {
427+
erase_sector(x);
428+
// uart_tx_one_char(0, 'E');
429+
}
430+
431+
asm ("memw");
432+
asm ("isync");
433+
// rom_phy_reset_req();
434+
system_restart_core();
435+
// return cur_write_pos;
436+
}
437+
STATIC mp_obj_t esp_DFU(mp_obj_t erase_all) {
438+
extern char flashchip;
439+
SpiFlashChip *flash = (SpiFlashChip *)(&flashchip + 4);
440+
char *buf = malloc(FLASH_SEC_SIZE);
441+
if (buf == NULL) {
442+
mp_raise_OSError(MP_ENOMEM);
443+
return mp_const_none;
444+
}
445+
446+
ets_wdt_disable();
447+
disable_irq();
448+
DFU(buf, dfu_fwsize / FLASH_SEC_SIZE + (dfu_fwsize % FLASH_SEC_SIZE?1:0), mp_obj_is_true(erase_all)?(flash->chip_size / FLASH_SEC_SIZE):0);
449+
450+
// It will NEVER reach here even if flash failed
451+
// enable_irq(state);
452+
// ets_wdt_enable();
453+
454+
return mp_const_none;
455+
}
456+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_DFU_obj, esp_DFU);
457+
458+
STATIC mp_obj_t esp_set_dfu(mp_obj_t counter, mp_obj_t fsize) {
459+
dfu_nblks = mp_obj_get_int(counter);
460+
dfu_fwsize = mp_obj_get_int(fsize);
461+
return mp_const_none;
462+
}
463+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_set_dfu_obj, esp_set_dfu);
464+
465+
STATIC mp_obj_t esp_get_blks() {
466+
if (dfu_nblks <= 0) {
467+
return mp_const_none;
468+
}
469+
mp_obj_t ret1 = mp_obj_new_list(0, NULL);
470+
mp_obj_t ret2 = mp_obj_new_list(0, NULL);
471+
for (int x = 0; x < dfu_nblks; x++) {
472+
mp_obj_list_append(ret1, mp_obj_new_int(dfu_blks[x]));
473+
mp_obj_list_append(ret2, mp_obj_new_int(dfu_offs[x]));
474+
}
475+
mp_obj_t ret = mp_obj_new_list(0, NULL);
476+
mp_obj_list_append(ret, ret1);
477+
mp_obj_list_append(ret, ret2);
478+
return ret;
479+
}
480+
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_get_blks_obj, esp_get_blks);
481+
#endif
482+
342483
STATIC const mp_rom_map_elem_t esp_module_globals_table[] = {
343484
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp) },
344485

@@ -351,6 +492,14 @@ STATIC const mp_rom_map_elem_t esp_module_globals_table[] = {
351492
{ MP_ROM_QSTR(MP_QSTR_flash_erase), MP_ROM_PTR(&esp_flash_erase_obj) },
352493
{ MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&esp_flash_size_obj) },
353494
{ MP_ROM_QSTR(MP_QSTR_flash_user_start), MP_ROM_PTR(&esp_flash_user_start_obj) },
495+
496+
#ifdef MICROPY_DFU
497+
{ MP_ROM_QSTR(MP_QSTR_DFU), MP_ROM_PTR(&esp_DFU_obj) },
498+
// { MP_ROM_QSTR(MP_QSTR_showMemory), MP_ROM_PTR(&esp_showMemory_obj) },
499+
{ MP_ROM_QSTR(MP_QSTR_set_dfu), MP_ROM_PTR(&esp_set_dfu_obj) },
500+
{ MP_ROM_QSTR(MP_QSTR_get_blks), MP_ROM_PTR(&esp_get_blks_obj) },
501+
#endif
502+
354503
#if MICROPY_ESP8266_APA102
355504
{ MP_ROM_QSTR(MP_QSTR_apa102_write), MP_ROM_PTR(&esp_apa102_write_obj) },
356505
#endif

ports/esp8266/modules/inisetup.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,42 @@
33
from flashbdev import bdev
44

55

6+
def fwupdate(fn, erase_all=False, safe_check=True, verbose=True):
7+
import esp
8+
9+
fw_size = rem_fs = os.stat(fn)[6]
10+
esp.set_dfu(0, fw_size)
11+
with open(fn, "rb") as fp:
12+
while fp.read(4096):
13+
pass
14+
15+
if safe_check:
16+
blks = esp.get_blks()
17+
if blks is None:
18+
raise Exception(f"No blocks data found for the file {fn}")
19+
blks, offs = blks
20+
esp.set_dfu(-1, fw_size)
21+
if verbose:
22+
print(f"Verifying sector data:{blks} {offs}")
23+
with open(fn, "rb") as fp:
24+
for ii, blkid in enumerate(blks):
25+
sz = min(rem_fs, 4096 - offs[ii])
26+
L2 = esp.flash_read(esp.flash_user_start() + blkid * 4096 + offs[ii], sz)
27+
L1 = fp.read(sz)
28+
if L1 != L2:
29+
raise Exception("Data is different at N={ii} blkid={blkid}")
30+
del L1, L2
31+
rem_fs -= sz
32+
if verbose:
33+
print(f"{ii}/{len(blks)}", end="\r")
34+
esp.set_dfu(len(blks), fw_size)
35+
del blks, offs
36+
if verbose:
37+
print("Success, starting firmware update ...")
38+
39+
esp.DFU(erase_all)
40+
41+
642
def wifi():
743
import binascii
844

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy