Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

esp32: make use of wear levelling from IDF #4999

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions ports/esp32/Makefile
Expand Up @@ -104,6 +104,8 @@ INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps
INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/mbedtls/include
INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include
INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/include
INC_ESPCOMP += -I$(ESPCOMP)/wear_levelling/include
INC_ESPCOMP += -I$(ESPCOMP)/wear_levelling/private_include
INC_ESPCOMP += -I$(ESPCOMP)/ulp/include
INC_ESPCOMP += -I$(ESPCOMP)/vfs/include
INC_ESPCOMP += -I$(ESPCOMP)/xtensa-debug-module/include
Expand Down Expand Up @@ -327,6 +329,10 @@ ESPIDF_SPI_FLASH_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/spi_flash/*.c))

ESPIDF_ULP_O = $(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/ulp/*.c))

ESPIDF_WEAR_LEVELLING_O = \
$(patsubst %.c,%.o,$(wildcard $(ESPCOMP)/wear_levelling/*.c)) \
$(patsubst %.cpp,%.o,$(wildcard $(ESPCOMP)/wear_levelling/*.cpp))

$(BUILD)/$(ESPCOMP)/lwip/%.o: CFLAGS += -Wno-address -Wno-unused-variable -Wno-unused-but-set-variable
ESPIDF_LWIP_O = $(patsubst %.c,%.o,\
$(wildcard $(ESPCOMP)/lwip/apps/dhcpserver/*.c) \
Expand Down Expand Up @@ -387,6 +393,7 @@ $(eval $(call gen_espidf_lib_rule,newlib,$(ESPIDF_NEWLIB_O)))
$(eval $(call gen_espidf_lib_rule,nvs_flash,$(ESPIDF_NVS_FLASH_O)))
$(eval $(call gen_espidf_lib_rule,smartconfig_ack,$(ESPIDF_SMARTCONFIG_ACK_O)))
$(eval $(call gen_espidf_lib_rule,spi_flash,$(ESPIDF_SPI_FLASH_O)))
$(eval $(call gen_espidf_lib_rule,wear_levelling,$(ESPIDF_WEAR_LEVELLING_O)))
$(eval $(call gen_espidf_lib_rule,ulp,$(ESPIDF_ULP_O)))
$(eval $(call gen_espidf_lib_rule,lwip,$(ESPIDF_LWIP_O)))
$(eval $(call gen_espidf_lib_rule,mbedtls,$(ESPIDF_MBEDTLS_O)))
Expand Down
40 changes: 34 additions & 6 deletions ports/esp32/modesp.c
Expand Up @@ -32,6 +32,7 @@
#include "rom/gpio.h"
#include "esp_log.h"
#include "esp_spi_flash.h"
#include "wear_levelling.h"

#include "py/runtime.h"
#include "py/mperrno.h"
Expand All @@ -56,11 +57,23 @@ STATIC mp_obj_t esp_osdebug(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_osdebug_obj, 1, 2, esp_osdebug);

STATIC wl_handle_t fs_handle = WL_INVALID_HANDLE; // not initialized
STATIC size_t wl_sect_size = 4096; // will be set to actual size after initialization
STATIC const esp_partition_t fs_part = {
ESP_PARTITION_TYPE_DATA, // type
ESP_PARTITION_SUBTYPE_DATA_FAT, // subtype
MICROPY_WEARLEVEL_PART_START, // address
MICROPY_WEARLEVEL_PART_SIZE, // size
"micropython", // label
MICROPY_WEARLEVEL_PART_ENCRYPTED // encrypted
};

STATIC mp_obj_t esp_flash_read(mp_obj_t offset_in, mp_obj_t buf_in) {
mp_int_t offset = mp_obj_get_int(offset_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
esp_err_t res = spi_flash_read(offset, bufinfo.buf, bufinfo.len);

esp_err_t res = wl_read(fs_handle, offset, bufinfo.buf, bufinfo.len);
if (res != ESP_OK) {
mp_raise_OSError(MP_EIO);
}
Expand All @@ -72,7 +85,8 @@ STATIC mp_obj_t esp_flash_write(mp_obj_t offset_in, mp_obj_t buf_in) {
mp_int_t offset = mp_obj_get_int(offset_in);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
esp_err_t res = spi_flash_write(offset, bufinfo.buf, bufinfo.len);

esp_err_t res = wl_write(fs_handle, offset, bufinfo.buf, bufinfo.len);
if (res != ESP_OK) {
mp_raise_OSError(MP_EIO);
}
Expand All @@ -82,7 +96,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_flash_write_obj, esp_flash_write);

STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) {
mp_int_t sector = mp_obj_get_int(sector_in);
esp_err_t res = spi_flash_erase_sector(sector);

esp_err_t res = wl_erase_range(fs_handle, sector * wl_sect_size, wl_sect_size);
if (res != ESP_OK) {
mp_raise_OSError(MP_EIO);
}
Expand All @@ -91,12 +106,24 @@ STATIC mp_obj_t esp_flash_erase(mp_obj_t sector_in) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_flash_erase_obj, esp_flash_erase);

STATIC mp_obj_t esp_flash_size(void) {
return mp_obj_new_int_from_uint(spi_flash_get_chip_size());
if (fs_handle == WL_INVALID_HANDLE) {
esp_err_t res = wl_mount(&fs_part, &fs_handle);
if (res != ESP_OK) {
return mp_obj_new_int_from_uint(0);
}
wl_sect_size = wl_sector_size(fs_handle);
}
return mp_obj_new_int_from_uint(wl_size(fs_handle));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size);

STATIC mp_obj_t esp_flash_user_start(void) {
return MP_OBJ_NEW_SMALL_INT(0x200000);
STATIC mp_obj_t esp_flash_sec_size() {
return mp_obj_new_int_from_uint(wl_sect_size);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_sec_size_obj, esp_flash_sec_size);

STATIC IRAM_ATTR mp_obj_t esp_flash_user_start(void) {
return MP_OBJ_NEW_SMALL_INT(0);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_user_start_obj, esp_flash_user_start);

Expand Down Expand Up @@ -132,6 +159,7 @@ STATIC const mp_rom_map_elem_t esp_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_flash_erase), MP_ROM_PTR(&esp_flash_erase_obj) },
{ MP_ROM_QSTR(MP_QSTR_flash_size), MP_ROM_PTR(&esp_flash_size_obj) },
{ MP_ROM_QSTR(MP_QSTR_flash_user_start), MP_ROM_PTR(&esp_flash_user_start_obj) },
{ MP_ROM_QSTR(MP_QSTR_flash_sec_size), MP_ROM_PTR(&esp_flash_sec_size_obj) },

{ MP_ROM_QSTR(MP_QSTR_gpio_matrix_in), MP_ROM_PTR(&esp_gpio_matrix_in_obj) },
{ MP_ROM_QSTR(MP_QSTR_gpio_matrix_out), MP_ROM_PTR(&esp_gpio_matrix_out_obj) },
Expand Down
12 changes: 6 additions & 6 deletions ports/esp32/modules/flashbdev.py
Expand Up @@ -2,11 +2,12 @@

class FlashBdev:

SEC_SIZE = 4096
FS_SIZE = esp.flash_size()
SEC_SIZE = esp.flash_sec_size()
START_SEC = esp.flash_user_start() // SEC_SIZE

def __init__(self, blocks):
self.blocks = blocks
def __init__(self):
self.blocks = self.FS_SIZE // self.SEC_SIZE

def readblocks(self, n, buf):
#print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf)))
Expand All @@ -26,9 +27,8 @@ def ioctl(self, op, arg):
return self.SEC_SIZE

size = esp.flash_size()
if size < 1024*1024:
if size < 512*1024:
Copy link
Contributor

@nevercast nevercast Aug 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you including the wear level size here? I'm not sure I see that.
#3576 (comment)
https://www.esp32.com/viewtopic.php?t=1897

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uhm... not really sure... but I guess this should be the minimum partition size, so this should be 528k... have to check this again, to be really sure

# flash too small for a filesystem
bdev = None
else:
# for now we use a fixed size for the filesystem
bdev = FlashBdev(2048 * 1024 // FlashBdev.SEC_SIZE)
bdev = FlashBdev()
5 changes: 5 additions & 0 deletions ports/esp32/mpconfigport.h
Expand Up @@ -161,6 +161,11 @@
#define mp_type_fileio mp_type_vfs_fat_fileio
#define mp_type_textio mp_type_vfs_fat_textio

// internal flash file system configuration
#define MICROPY_WEARLEVEL_PART_START (0x200000)
#define MICROPY_WEARLEVEL_PART_SIZE (0x200000)
#define MICROPY_WEARLEVEL_PART_ENCRYPTED (0)

// use vfs's functions for import stat and builtin open
#define mp_import_stat mp_vfs_import_stat
#define mp_builtin_open mp_vfs_open
Expand Down