diff options
author | Damien George <damien@micropython.org> | 2024-11-15 11:18:09 +1100 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2025-03-06 12:52:35 +1100 |
commit | 75ff8e5465c766bad0c79d1a5d98170f27f7070b (patch) | |
tree | 4af333457a9efeec2b74bd0680d3b24238a57296 | |
parent | 0255cb77ccbdf09894e59523aecff24f2caa6352 (diff) |
esp8266: Implement vfs.rom_ioctl with support for external flash.
Not enabled by default on any board. For a board to enable ROMFS it must:
- Add `#define MICROPY_VFS_ROM (1)` to its `mpconfigboard.h` file.
- Add a FLASH_ROMFS partition to the linker script and expose the partition
with:
_micropy_hw_romfs_start = ORIGIN(FLASH_ROMFS);
_micropy_hw_romfs_size = LENGTH(FLASH_ROMFS);
Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r-- | ports/esp8266/Makefile | 1 | ||||
-rw-r--r-- | ports/esp8266/boards/esp8266_common.ld | 1 | ||||
-rw-r--r-- | ports/esp8266/modesp.c | 9 | ||||
-rw-r--r-- | ports/esp8266/vfs_rom_ioctl.c | 89 |
4 files changed, 99 insertions, 1 deletions
diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index 1721075ea..1c9de0150 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -134,6 +134,7 @@ SRC_C = \ fatfs_port.c \ posix_helpers.c \ hspi.c \ + vfs_rom_ioctl.c \ $(wildcard $(BOARD_DIR)/*.c) \ ifeq ($(MICROPY_PY_ESPNOW),1) diff --git a/ports/esp8266/boards/esp8266_common.ld b/ports/esp8266/boards/esp8266_common.ld index cf4883acc..206c3f14b 100644 --- a/ports/esp8266/boards/esp8266_common.ld +++ b/ports/esp8266/boards/esp8266_common.ld @@ -170,6 +170,7 @@ SECTIONS *modonewire.o(.literal* .text*) *network_wlan.o(.literal* .text*) *esp_mphal.o(.literal* .text*) + *vfs_rom_ioctl.o(.literal* .text*) /* we put as much rodata as possible in this section */ /* note that only rodata accessed as a machine word is allowed here */ diff --git a/ports/esp8266/modesp.c b/ports/esp8266/modesp.c index f303da1a3..c88022945 100644 --- a/ports/esp8266/modesp.c +++ b/ports/esp8266/modesp.c @@ -164,9 +164,16 @@ static MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size); #define IS_OTA_FIRMWARE() ((*(uint32_t *)0x40200000 & 0xff00) == 0x100) extern byte _firmware_size[]; +#if MICROPY_VFS_ROM_IOCTL +extern uint8_t _micropy_hw_romfs_size; +#endif static mp_obj_t esp_flash_user_start(void) { - return MP_OBJ_NEW_SMALL_INT((uint32_t)_firmware_size); + uint32_t flash_user_start = (uint32_t)_firmware_size; + #if MICROPY_VFS_ROM_IOCTL + flash_user_start += (uint32_t)&_micropy_hw_romfs_size; + #endif + return MP_OBJ_NEW_SMALL_INT(flash_user_start); } static MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_user_start_obj, esp_flash_user_start); diff --git a/ports/esp8266/vfs_rom_ioctl.c b/ports/esp8266/vfs_rom_ioctl.c new file mode 100644 index 000000000..c7528375b --- /dev/null +++ b/ports/esp8266/vfs_rom_ioctl.c @@ -0,0 +1,89 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024-2025 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/mperrno.h" +#include "py/objarray.h" +#include "extmod/vfs.h" +#include "ets_alt_task.h" +#include "user_interface.h" + +#if MICROPY_VFS_ROM_IOCTL + +#define FLASH_MEM_BASE (0x40200000) +#define FLASH_PAGE_SIZE (4096) + +#define MICROPY_HW_ROMFS_BASE (uintptr_t)(&_micropy_hw_romfs_start) +#define MICROPY_HW_ROMFS_BYTES (uintptr_t)(&_micropy_hw_romfs_size) + +#define ROMFS_SPI_FLASH_OFFSET (MICROPY_HW_ROMFS_BASE - FLASH_MEM_BASE) + +extern uint8_t _micropy_hw_romfs_start; +extern uint8_t _micropy_hw_romfs_size; + +static const MP_DEFINE_MEMORYVIEW_OBJ(romfs_obj, 'B', 0, MICROPY_HW_ROMFS_BYTES, (void *)MICROPY_HW_ROMFS_BASE); + +mp_obj_t mp_vfs_rom_ioctl(size_t n_args, const mp_obj_t *args) { + switch (mp_obj_get_int(args[0])) { + case MP_VFS_ROM_IOCTL_GET_NUMBER_OF_SEGMENTS: + return MP_OBJ_NEW_SMALL_INT(1); + + case MP_VFS_ROM_IOCTL_GET_SEGMENT: + return MP_OBJ_FROM_PTR(&romfs_obj); + + case MP_VFS_ROM_IOCTL_WRITE_PREPARE: { + uint32_t dest = ROMFS_SPI_FLASH_OFFSET; + uint32_t dest_max = dest + mp_obj_get_int(args[2]); + while (dest < dest_max) { + ets_loop_iter(); // flash access takes time so run any pending tasks + SpiFlashOpResult res = spi_flash_erase_sector(dest / FLASH_PAGE_SIZE); + ets_loop_iter(); + if (res != SPI_FLASH_RESULT_OK) { + return MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? -MP_ETIMEDOUT : -MP_EIO); + } + dest += FLASH_PAGE_SIZE; + } + return MP_OBJ_NEW_SMALL_INT(4); // minimum write size + } + + case MP_VFS_ROM_IOCTL_WRITE: { + mp_int_t offset = ROMFS_SPI_FLASH_OFFSET + mp_obj_get_int(args[2]); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[3], &bufinfo, MP_BUFFER_READ); + ets_loop_iter(); // flash access takes time so run any pending tasks + SpiFlashOpResult res = spi_flash_write(offset, bufinfo.buf, (bufinfo.len + 3) & ~3); + ets_loop_iter(); + if (res == SPI_FLASH_RESULT_OK) { + return MP_OBJ_NEW_SMALL_INT(0); + } + return MP_OBJ_NEW_SMALL_INT(res == SPI_FLASH_RESULT_TIMEOUT ? -MP_ETIMEDOUT : -MP_EIO); + } + + default: + return MP_OBJ_NEW_SMALL_INT(-MP_EINVAL); + } +} + +#endif // MICROPY_VFS_ROM_IOCTL |