diff --git a/src/platform/stm32wl/LittleFS.cpp b/src/platform/stm32wl/LittleFS.cpp index e23470799..1f2bcc8f2 100644 --- a/src/platform/stm32wl/LittleFS.cpp +++ b/src/platform/stm32wl/LittleFS.cpp @@ -23,41 +23,46 @@ */ #include "LittleFS.h" +#include "stm32wlxx_hal_flash.h" /********************************************************************************************************************** * Macro definitions **********************************************************************************************************************/ /** This macro is used to suppress compiler messages about a parameter not being used in a function. */ -#define PARAMETER_NOT_USED(p) (void)((p)) +#define LFS_UNUSED(p) (void)((p)) -#define STM32WL_SECTOR_SIZE 0x800 /* 2K */ -#define STM32WL_SECTOR_COUNT 14 +#define STM32WL_PAGE_SIZE (FLASH_PAGE_SIZE) +#define STM32WL_PAGE_COUNT (FLASH_PAGE_NB) +#define STM32WL_FLASH_BASE (FLASH_BASE) -#define LFS_FLASH_TOTAL_SIZE (STM32WL_SECTOR_COUNT * STM32WL_SECTOR_SIZE) -#define LFS_BLOCK_SIZE 128 +/* FLASH_SIZE from stm32wle5xx.h will read the actual FLASH size from the chip */ +/* use the last 1/4 of the FLASH */ +#define LFS_FLASH_TOTAL_SIZE (FLASH_SIZE / 4) +#define LFS_BLOCK_SIZE (128) +#define LFS_FLASH_ADDR_END (FLASH_END_ADDR) +#define LFS_FLASH_ADDR_BASE (LFS_FLASH_ADDR_END - (FLASH_SIZE / 4) + 1) -#define LFS_FLASH_ADDR (262144 - LFS_FLASH_TOTAL_SIZE) +#if !CFG_DEBUG +#define _LFS_DBG(fmt, ...) +#else +#define _LFS_DBG(fmt, ...) printf("%s:%d (%s): " fmt "\n", __FILE__, __LINE__, __func__, __VA_ARGS__) +#endif //--------------------------------------------------------------------+ // LFS Disk IO //--------------------------------------------------------------------+ -static inline uint32_t lba2addr(uint32_t block) -{ - return ((uint32_t)LFS_FLASH_ADDR) + block * LFS_BLOCK_SIZE; -} - static int _internal_flash_read(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, void *buffer, lfs_size_t size) { - PARAMETER_NOT_USED(c); + LFS_UNUSED(c); + if (!buffer || !size) { - printf("%s Invalid parameter!\r\n", __func__); + _LFS_DBG("%s Invalid parameter!\r\n", __func__); return LFS_ERR_INVAL; } - lfs_block_t address = LFS_FLASH_ADDR + (block * STM32WL_SECTOR_SIZE + off); - // printf("+%s(Addr 0x%06lX, Len 0x%04lX)\r\n",__func__,address,size); - // hexdump((void *)address,size); + lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE + off); + memcpy(buffer, (void *)address, size); return LFS_ERR_OK; @@ -68,38 +73,38 @@ static int _internal_flash_read(const struct lfs_config *c, lfs_block_t block, l // May return LFS_ERR_CORRUPT if the block should be considered bad. static int _internal_flash_prog(const struct lfs_config *c, lfs_block_t block, lfs_off_t off, const void *buffer, lfs_size_t size) { - // (void) c; - - // uint32_t addr = lba2addr(block) + off; - // VERIFY( flash_nrf5x_write(addr, buffer, size), -1) - - // return 0; - PARAMETER_NOT_USED(c); - lfs_block_t address = LFS_FLASH_ADDR + (block * STM32WL_SECTOR_SIZE + off); + lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE + off); HAL_StatusTypeDef hal_rc = HAL_OK; uint32_t block_count = size / 8; + uint64_t *bufp = (uint64_t *) buffer; - // printf("+%s(Addr 0x%06lX, Len 0x%04lX)\r\n",__func__,address,size); - // hexdump((void *)address,size); - /* Program the user Flash area word by word - (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/ - - uint64_t data_source; + LFS_UNUSED(c); + if(HAL_FLASH_Unlock() != HAL_OK) + { + return LFS_ERR_IO; + } for (uint32_t i = 0; i < block_count; i++) { - memcpy(&data_source, buffer, 8); // load the 64-bit source from the buffer - hal_rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data_source); - if (hal_rc == HAL_OK) { - address += 8; - buffer = (uint8_t *)buffer + 8; - } else { + if((address < LFS_FLASH_ADDR_BASE) || (address > LFS_FLASH_ADDR_END)) + { + _LFS_DBG("Wanted to program out of bound of FLASH: 0x%08x.\n", address); + HAL_FLASH_Lock(); + return LFS_ERR_INVAL; + } + hal_rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *bufp); + if (hal_rc != HAL_OK) { /* Error occurred while writing data in Flash memory. - User can add here some code to deal with this error */ - printf("Program Error, 0x%X\n", hal_rc); - - } // else - } // for - // printf("-%s\n",__func__); + * User can add here some code to deal with this error. + */ + _LFS_DBG("Program error at (0x%08x), 0x%X, error: 0x%08x\n", address, hal_rc, HAL_FLASH_GetError()); + } + address += 8; + bufp += 8; + } + if(HAL_FLASH_Lock() != HAL_OK) + { + return LFS_ERR_IO; + } return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO; // If HAL_OK, return LFS_ERR_OK, else return LFS_ERR_IO } @@ -110,38 +115,28 @@ static int _internal_flash_prog(const struct lfs_config *c, lfs_block_t block, l // May return LFS_ERR_CORRUPT if the block should be considered bad. static int _internal_flash_erase(const struct lfs_config *c, lfs_block_t block) { - // (void) c; - - // uint32_t addr = lba2addr(block); - - // // implement as write 0xff to whole block address - // for(int i=0; i LFS_FLASH_ADDR_END)) + { + _LFS_DBG("Wanted to erase out of bound of FLASH: 0x%08x.\n", address); + return LFS_ERR_INVAL; + } + /* calculate the absolute page, i.e. what the ST wants */ + EraseInitStruct.Page = (address - STM32WL_FLASH_BASE) / STM32WL_PAGE_SIZE; + _LFS_DBG("Erasing block %d at 0x%08x... ", block, address); + HAL_FLASH_Unlock(); + hal_rc = HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError); + HAL_FLASH_Lock(); return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO; // If HAL_OK, return LFS_ERR_OK, else return LFS_ERR_IO } @@ -150,33 +145,31 @@ static int _internal_flash_erase(const struct lfs_config *c, lfs_block_t block) // are propogated to the user. static int _internal_flash_sync(const struct lfs_config *c) { - // (void) c; - // flash_nrf5x_flush(); - // return 0; - PARAMETER_NOT_USED(c); + LFS_UNUSED(c); // write function performs no caching. No need for sync. - // printf("+%s()\r\n",__func__); + return LFS_ERR_OK; - // return LFS_ERR_IO; } -static struct lfs_config _InternalFSConfig = {.context = NULL, +static struct lfs_config _InternalFSConfig = { + .context = NULL, - .read = _internal_flash_read, - .prog = _internal_flash_prog, - .erase = _internal_flash_erase, - .sync = _internal_flash_sync, + .read = _internal_flash_read, + .prog = _internal_flash_prog, + .erase = _internal_flash_erase, + .sync = _internal_flash_sync, - .read_size = LFS_BLOCK_SIZE, - .prog_size = LFS_BLOCK_SIZE, - .block_size = LFS_BLOCK_SIZE, - .block_count = LFS_FLASH_TOTAL_SIZE / LFS_BLOCK_SIZE, - .lookahead = 128, + .read_size = LFS_BLOCK_SIZE, + .prog_size = LFS_BLOCK_SIZE, + .block_size = LFS_BLOCK_SIZE, + .block_count = LFS_FLASH_TOTAL_SIZE / LFS_BLOCK_SIZE, + .lookahead = 128, - .read_buffer = NULL, - .prog_buffer = NULL, - .lookahead_buffer = NULL, - .file_buffer = NULL}; + .read_buffer = NULL, + .prog_buffer = NULL, + .lookahead_buffer = NULL, + .file_buffer = NULL +}; LittleFS InternalFS; @@ -188,11 +181,11 @@ LittleFS::LittleFS(void) : STM32_LittleFS(&_InternalFSConfig) {} bool LittleFS::begin(void) { - // failed to mount, erase all sector then format and mount again + // failed to mount, erase all pages then format and mount again if (!STM32_LittleFS::begin()) { - // Erase all sectors of internal flash region for Filesystem. - for (uint32_t addr = LFS_FLASH_ADDR; addr < LFS_FLASH_ADDR + LFS_FLASH_TOTAL_SIZE; addr += STM32WL_SECTOR_SIZE) { - _internal_flash_erase(&_InternalFSConfig, (addr - LFS_FLASH_ADDR) / STM32WL_SECTOR_SIZE); + // Erase all pages of internal flash region for Filesystem. + for (uint32_t addr = LFS_FLASH_ADDR_BASE; addr < (LFS_FLASH_ADDR_END + 1); addr += STM32WL_PAGE_SIZE) { + _internal_flash_erase(&_InternalFSConfig, (addr - LFS_FLASH_ADDR_BASE) / STM32WL_PAGE_SIZE); } // lfs format diff --git a/src/platform/stm32wl/STM32_LittleFS.h b/src/platform/stm32wl/STM32_LittleFS.h index a6d897930..8aec8e7a5 100644 --- a/src/platform/stm32wl/STM32_LittleFS.h +++ b/src/platform/stm32wl/STM32_LittleFS.h @@ -97,7 +97,7 @@ class STM32_LittleFS #define PRINT_LFS_ERR(_err) \ do { \ if (_err) { \ - VERIFY_MESS((long int)_err, dbg_strerr_lfs); \ + printf("%s:%d, LFS error: %d\n", __FILE__, __LINE__, _err); \ } \ } while (0) // LFS_ERR are of type int, VERIFY_MESS expects long_int