Skip to content

Commit c45833a

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 c45833a

File tree

9 files changed

+189
-3
lines changed

9 files changed

+189
-3
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: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3239,6 +3239,11 @@ static int lfs2_file_rawsync(lfs2_t *lfs2, lfs2_file_t *file) {
32393239
}
32403240
#endif
32413241

3242+
#ifdef MICROPY_DFU
3243+
extern uint32_t dfu_blks[256];
3244+
extern uint8_t dfu_offs[256];
3245+
extern int dfu_nblks;
3246+
#endif
32423247
static lfs2_ssize_t lfs2_file_flushedread(lfs2_t *lfs2, lfs2_file_t *file,
32433248
void *buffer, lfs2_size_t size) {
32443249
uint8_t *data = buffer;
@@ -3260,6 +3265,12 @@ static lfs2_ssize_t lfs2_file_flushedread(lfs2_t *lfs2, lfs2_file_t *file,
32603265
int err = lfs2_ctz_find(lfs2, NULL, &file->cache,
32613266
file->ctz.head, file->ctz.size,
32623267
file->pos, &file->block, &file->off);
3268+
#ifdef MICROPY_DFU
3269+
if(dfu_nblks==0 || (dfu_nblks>0 && dfu_blks[(dfu_nblks-1)%256]!=file->block)){ // DFU hook
3270+
dfu_blks[dfu_nblks%256] = file->block;
3271+
dfu_offs[(dfu_nblks++)%256] = file->off;
3272+
}
3273+
#endif
32633274
if (err) {
32643275
return err;
32653276
}

ports/esp8266/Makefile

Lines changed: 1 addition & 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

ports/esp8266/boards/ESP8266_GENERIC/mpconfigboard.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define MICROPY_VFS (1)
1515

1616
#define MICROPY_PY_CRYPTOLIB (1)
17+
#define MICROPY_DFU (1)
1718

1819
#elif defined(MICROPY_ESP8266_1M)
1920

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: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,138 @@ 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+
uint32_t dfu_blks[256];
381+
uint8_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){SPIEraseSector(sector);break;}
390+
}
391+
void MP_FASTCODE(DFU)(char *dfu_buf, int n_fwblks, int n_erase) {
392+
for(int x=0; x<n_fwblks; x++){
393+
erase_sector(x);
394+
// uart_tx_one_char(0, 'E');
395+
}
396+
397+
int cur_write_pos = 0;
398+
int cur_write_sz;
399+
int remaining_sz = dfu_fwsize;
400+
401+
for(int x=0; x<dfu_nblks && remaining_sz>0; x++){
402+
cur_write_sz = FLASH_SEC_SIZE - dfu_offs[x];
403+
if(remaining_sz<cur_write_sz) cur_write_sz = remaining_sz;
404+
405+
Cache_Read_Disable_2();
406+
SPIRead(1048576+FLASH_SEC_SIZE*dfu_blks[x]+dfu_offs[x], (uint32_t *)dfu_buf, cur_write_sz);
407+
Cache_Read_Enable_2();
408+
// uart_tx_one_char(0, 'R');
409+
if(x==0) dfu_buf[3] = 64;
410+
SPIWrite(cur_write_pos, (uint32_t *)dfu_buf, cur_write_sz);
411+
// uart_tx_one_char(0, 'W');
412+
413+
cur_write_pos += cur_write_sz;
414+
remaining_sz -= cur_write_sz;
415+
wdt_feed();
416+
}
417+
418+
for(int x=n_fwblks; x<n_erase; x++){
419+
erase_sector(x);
420+
// uart_tx_one_char(0, 'E');
421+
}
422+
423+
asm ("memw");
424+
asm ("isync");
425+
// rom_phy_reset_req();
426+
system_restart_core();
427+
// return cur_write_pos;
428+
}
429+
STATIC mp_obj_t esp_DFU(mp_obj_t erase_all) {
430+
extern char flashchip;
431+
SpiFlashChip *flash = (SpiFlashChip *)(&flashchip + 4);
432+
char *buf = malloc(FLASH_SEC_SIZE);
433+
if(buf==NULL){
434+
mp_raise_OSError(MP_ENOMEM);
435+
return mp_const_none;
436+
}
437+
438+
ets_wdt_disable();
439+
disable_irq();
440+
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);
441+
442+
// It will NEVER reach here even if flash failed
443+
// enable_irq(state);
444+
// ets_wdt_enable();
445+
446+
return mp_const_none;
447+
}
448+
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_DFU_obj, esp_DFU);
449+
450+
STATIC mp_obj_t esp_set_dfu(mp_obj_t counter, mp_obj_t fsize) {
451+
dfu_nblks = mp_obj_get_int(counter);
452+
dfu_fwsize = mp_obj_get_int(fsize);
453+
return mp_const_none;
454+
}
455+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_set_dfu_obj, esp_set_dfu);
456+
457+
STATIC mp_obj_t esp_get_blks() {
458+
if(dfu_nblks<=0)
459+
return mp_obj_new_list(0, NULL), mp_obj_new_list(0, NULL);
460+
mp_obj_t ret1 = mp_obj_new_list(0, NULL);
461+
mp_obj_t ret2 = mp_obj_new_list(0, NULL);
462+
for(int x=0; x<dfu_nblks; x++){
463+
mp_obj_list_append(ret1, mp_obj_new_int(dfu_blks[x]));
464+
mp_obj_list_append(ret2, mp_obj_new_int(dfu_offs[x]));
465+
}
466+
mp_obj_t ret = mp_obj_new_list(0, NULL);
467+
mp_obj_list_append(ret, ret1);
468+
mp_obj_list_append(ret, ret2);
469+
return ret;
470+
}
471+
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_get_blks_obj, esp_get_blks);
472+
#endif
473+
342474
STATIC const mp_rom_map_elem_t esp_module_globals_table[] = {
343475
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp) },
344476

@@ -351,6 +483,14 @@ STATIC const mp_rom_map_elem_t esp_module_globals_table[] = {
351483
{ MP_ROM_QSTR(MP_QSTR_flash_erase), MP_ROM_PTR(&esp_flash_erase_obj) },
352484
{ MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&esp_flash_size_obj) },
353485
{ MP_ROM_QSTR(MP_QSTR_flash_user_start), MP_ROM_PTR(&esp_flash_user_start_obj) },
486+
487+
#ifdef MICROPY_DFU
488+
{ MP_ROM_QSTR(MP_QSTR_DFU), MP_ROM_PTR(&esp_DFU_obj) },
489+
// { MP_ROM_QSTR(MP_QSTR_showMemory), MP_ROM_PTR(&esp_showMemory_obj) },
490+
{ MP_ROM_QSTR(MP_QSTR_set_dfu), MP_ROM_PTR(&esp_set_dfu_obj) },
491+
{ MP_ROM_QSTR(MP_QSTR_get_blks), MP_ROM_PTR(&esp_get_blks_obj) },
492+
#endif
493+
354494
#if MICROPY_ESP8266_APA102
355495
{ MP_ROM_QSTR(MP_QSTR_apa102_write), MP_ROM_PTR(&esp_apa102_write_obj) },
356496
#endif

ports/esp8266/modules/inisetup.py

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

55

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

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