Skip to content

Commit 45a6156

Browse files
committed
esp8266: Enable native emitter for Xtensa arch.
This patch allows esp8266 to use @micropython.native and @micropython.viper function decorators. By default the executable machine code is written to the space at the end of the iram1 region. The user can call esp.set_native_code_location() to make the code go to flash instead.
1 parent 8e5aced commit 45a6156

4 files changed

Lines changed: 106 additions & 3 deletions

File tree

esp8266/main.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ STATIC void mp_reset(void) {
5858
MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
5959
MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
6060
MP_STATE_PORT(dupterm_arr_obj) = MP_OBJ_NULL;
61+
#if MICROPY_EMIT_XTENSA
62+
extern void esp_native_code_init(void);
63+
esp_native_code_init();
64+
#endif
6165
pin_init0();
6266
readline_init0();
6367
dupterm_task_init();

esp8266/modesp.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,99 @@ STATIC mp_obj_t esp_esf_free_bufs(mp_obj_t idx_in) {
699699
}
700700
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_esf_free_bufs_obj, esp_esf_free_bufs);
701701

702+
#if MICROPY_EMIT_XTENSA
703+
704+
// We provide here a way of committing executable data to a region from
705+
// which it can be executed by the CPU. There are 2 such writable regions:
706+
// - iram1, which may have some space left at the end of it
707+
// - memory-mapped flash rom
708+
//
709+
// By default the iram1 region (the space at the end of it) is used. The
710+
// user can select iram1 or a section of flash by calling the
711+
// esp.set_native_code_location() function; see below. If flash is selected
712+
// then it is erased as needed.
713+
714+
#define IRAM1_END (0x40108000)
715+
#define FLASH_START (0x40200000)
716+
#define FLASH_END (0x40300000)
717+
#define FLASH_SEC_SIZE (4096)
718+
719+
#define ESP_NATIVE_CODE_IRAM1 (0)
720+
#define ESP_NATIVE_CODE_FLASH (1)
721+
722+
extern uint32_t _lit4_end;
723+
STATIC uint32_t esp_native_code_location;
724+
STATIC uint32_t esp_native_code_start;
725+
STATIC uint32_t esp_native_code_end;
726+
STATIC uint32_t esp_native_code_cur;
727+
STATIC uint32_t esp_native_code_erased;
728+
729+
void esp_native_code_init(void) {
730+
esp_native_code_location = ESP_NATIVE_CODE_IRAM1;
731+
esp_native_code_start = (uint32_t)&_lit4_end;
732+
esp_native_code_end = IRAM1_END;
733+
esp_native_code_cur = esp_native_code_start;
734+
esp_native_code_erased = 0;
735+
}
736+
737+
void *esp_native_code_commit(void *buf, size_t len) {
738+
//printf("COMMIT(buf=%p, len=%u, start=%08x, cur=%08x, end=%08x, erased=%08x)\n", buf, len, esp_native_code_start, esp_native_code_cur, esp_native_code_end, esp_native_code_erased);
739+
740+
len = (len + 3) & ~3;
741+
if (esp_native_code_cur + len > esp_native_code_end) {
742+
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError,
743+
"memory allocation failed, allocating %u bytes for native code", (uint)len));
744+
}
745+
746+
void *dest;
747+
if (esp_native_code_location == ESP_NATIVE_CODE_IRAM1) {
748+
dest = (void*)esp_native_code_cur;
749+
memcpy(dest, buf, len);
750+
} else {
751+
SpiFlashOpResult res;
752+
while (esp_native_code_erased < esp_native_code_cur + len) {
753+
res = spi_flash_erase_sector(esp_native_code_erased / FLASH_SEC_SIZE);
754+
if (res != SPI_FLASH_RESULT_OK) {
755+
break;
756+
}
757+
esp_native_code_erased += FLASH_SEC_SIZE;
758+
}
759+
if (res == SPI_FLASH_RESULT_OK) {
760+
res = spi_flash_write(esp_native_code_cur, buf, len);
761+
}
762+
if (res != SPI_FLASH_RESULT_OK) {
763+
mp_raise_OSError(res == SPI_FLASH_RESULT_TIMEOUT ? MP_ETIMEDOUT : MP_EIO);
764+
}
765+
dest = (void*)(FLASH_START + esp_native_code_cur);
766+
}
767+
768+
esp_native_code_cur += len;
769+
770+
return dest;
771+
}
772+
773+
STATIC mp_obj_t esp_set_native_code_location(mp_obj_t start_in, mp_obj_t len_in) {
774+
if (start_in == mp_const_none && len_in == mp_const_none) {
775+
// use end of iram1 region
776+
esp_native_code_init();
777+
} else {
778+
// use flash; input params are byte offsets from start of flash
779+
esp_native_code_location = ESP_NATIVE_CODE_FLASH;
780+
esp_native_code_start = mp_obj_get_int(start_in);
781+
esp_native_code_end = esp_native_code_start + mp_obj_get_int(len_in);
782+
esp_native_code_cur = esp_native_code_start;
783+
esp_native_code_erased = esp_native_code_start;
784+
// memory-mapped flash is limited in extents to 1MByte
785+
if (esp_native_code_end > FLASH_END - FLASH_START) {
786+
mp_raise_ValueError("flash location must be below 1MByte");
787+
}
788+
}
789+
return mp_const_none;
790+
}
791+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_set_native_code_location_obj, esp_set_native_code_location);
792+
793+
#endif
794+
702795
STATIC const mp_map_elem_t esp_module_globals_table[] = {
703796
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_esp) },
704797

@@ -729,6 +822,9 @@ STATIC const mp_map_elem_t esp_module_globals_table[] = {
729822
{ MP_OBJ_NEW_QSTR(MP_QSTR_malloc), (mp_obj_t)&esp_malloc_obj },
730823
{ MP_OBJ_NEW_QSTR(MP_QSTR_free), (mp_obj_t)&esp_free_obj },
731824
{ MP_OBJ_NEW_QSTR(MP_QSTR_esf_free_bufs), (mp_obj_t)&esp_esf_free_bufs_obj },
825+
#if MICROPY_EMIT_XTENSA
826+
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_native_code_location), (mp_obj_t)&esp_set_native_code_location_obj },
827+
#endif
732828

733829
#if MODESP_INCLUDE_CONSTANTS
734830
{ MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP_NONE),

esp8266/mpconfigport.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@
1010
#define MICROPY_ALLOC_PARSE_RESULT_INC (8)
1111
#define MICROPY_ALLOC_PARSE_CHUNK_INIT (64)
1212
#define MICROPY_PERSISTENT_CODE_LOAD (1)
13-
#define MICROPY_EMIT_X64 (0)
14-
#define MICROPY_EMIT_THUMB (0)
15-
#define MICROPY_EMIT_INLINE_THUMB (0)
13+
#define MICROPY_EMIT_XTENSA (1)
1614
#define MICROPY_MEM_STATS (0)
1715
#define MICROPY_DEBUG_PRINTERS (1)
1816
#define MICROPY_DEBUG_PRINTER_DEST mp_debug_print
@@ -131,6 +129,8 @@ typedef uint32_t sys_prot_t; // for modlwip
131129
#include <sys/types.h>
132130

133131
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
132+
void *esp_native_code_commit(void*, size_t);
133+
#define MP_PLAT_COMMIT_EXEC(buf, len) esp_native_code_commit(buf, len)
134134

135135
#define mp_type_fileio fatfs_type_fileio
136136
#define mp_type_textio fatfs_type_textio

esp8266/mpconfigport_512k.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#include <mpconfigport.h>
22

3+
#undef MICROPY_EMIT_XTENSA
4+
#define MICROPY_EMIT_XTENSA (0)
5+
36
#undef MICROPY_FSUSERMOUNT
47
#define MICROPY_FSUSERMOUNT (0)
58
#undef MICROPY_VFS_FAT

0 commit comments

Comments
 (0)