mirror of
https://github.com/meshtastic/firmware.git
synced 2025-09-21 09:13:42 +00:00
correctly translate memory address/block from LFS to STM32 HAL
Reading and writing FLASH works!
This commit is contained in:
parent
2f6f786f73
commit
f60ccc545d
@ -23,41 +23,46 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "LittleFS.h"
|
#include "LittleFS.h"
|
||||||
|
#include "stm32wlxx_hal_flash.h"
|
||||||
|
|
||||||
/**********************************************************************************************************************
|
/**********************************************************************************************************************
|
||||||
* Macro definitions
|
* Macro definitions
|
||||||
**********************************************************************************************************************/
|
**********************************************************************************************************************/
|
||||||
/** This macro is used to suppress compiler messages about a parameter not being used in a function. */
|
/** 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_PAGE_SIZE (FLASH_PAGE_SIZE)
|
||||||
#define STM32WL_SECTOR_COUNT 14
|
#define STM32WL_PAGE_COUNT (FLASH_PAGE_NB)
|
||||||
|
#define STM32WL_FLASH_BASE (FLASH_BASE)
|
||||||
|
|
||||||
#define LFS_FLASH_TOTAL_SIZE (STM32WL_SECTOR_COUNT * STM32WL_SECTOR_SIZE)
|
/* FLASH_SIZE from stm32wle5xx.h will read the actual FLASH size from the chip */
|
||||||
#define LFS_BLOCK_SIZE 128
|
/* 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
|
// 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)
|
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) {
|
if (!buffer || !size) {
|
||||||
printf("%s Invalid parameter!\r\n", __func__);
|
_LFS_DBG("%s Invalid parameter!\r\n", __func__);
|
||||||
return LFS_ERR_INVAL;
|
return LFS_ERR_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
// printf("+%s(Addr 0x%06lX, Len 0x%04lX)\r\n",__func__,address,size);
|
|
||||||
// hexdump((void *)address,size);
|
|
||||||
memcpy(buffer, (void *)address, size);
|
memcpy(buffer, (void *)address, size);
|
||||||
|
|
||||||
return LFS_ERR_OK;
|
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.
|
// 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)
|
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;
|
lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE + off);
|
||||||
|
|
||||||
// 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);
|
|
||||||
HAL_StatusTypeDef hal_rc = HAL_OK;
|
HAL_StatusTypeDef hal_rc = HAL_OK;
|
||||||
uint32_t block_count = size / 8;
|
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);
|
LFS_UNUSED(c);
|
||||||
// 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;
|
|
||||||
|
|
||||||
|
if(HAL_FLASH_Unlock() != HAL_OK)
|
||||||
|
{
|
||||||
|
return LFS_ERR_IO;
|
||||||
|
}
|
||||||
for (uint32_t i = 0; i < block_count; i++) {
|
for (uint32_t i = 0; i < block_count; i++) {
|
||||||
memcpy(&data_source, buffer, 8); // load the 64-bit source from the buffer
|
if((address < LFS_FLASH_ADDR_BASE) || (address > LFS_FLASH_ADDR_END))
|
||||||
hal_rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data_source);
|
{
|
||||||
if (hal_rc == HAL_OK) {
|
_LFS_DBG("Wanted to program out of bound of FLASH: 0x%08x.\n", address);
|
||||||
address += 8;
|
HAL_FLASH_Lock();
|
||||||
buffer = (uint8_t *)buffer + 8;
|
return LFS_ERR_INVAL;
|
||||||
} else {
|
}
|
||||||
|
hal_rc = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, *bufp);
|
||||||
|
if (hal_rc != HAL_OK) {
|
||||||
/* Error occurred while writing data in Flash memory.
|
/* Error occurred while writing data in Flash memory.
|
||||||
User can add here some code to deal with this error */
|
* User can add here some code to deal with this error.
|
||||||
printf("Program Error, 0x%X\n", hal_rc);
|
*/
|
||||||
|
_LFS_DBG("Program error at (0x%08x), 0x%X, error: 0x%08x\n", address, hal_rc, HAL_FLASH_GetError());
|
||||||
} // else
|
}
|
||||||
} // for
|
address += 8;
|
||||||
// printf("-%s\n",__func__);
|
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
|
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.
|
// 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)
|
static int _internal_flash_erase(const struct lfs_config *c, lfs_block_t block)
|
||||||
{
|
{
|
||||||
// (void) c;
|
lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE);
|
||||||
|
|
||||||
// uint32_t addr = lba2addr(block);
|
|
||||||
|
|
||||||
// // implement as write 0xff to whole block address
|
|
||||||
// for(int i=0; i <LFS_BLOCK_SIZE; i++)
|
|
||||||
// {
|
|
||||||
// flash_nrf5x_write8(addr + i, 0xFF);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // flash_nrf5x_flush();
|
|
||||||
|
|
||||||
// return 0;
|
|
||||||
PARAMETER_NOT_USED(c);
|
|
||||||
lfs_block_t address = LFS_FLASH_ADDR + (block * STM32WL_SECTOR_SIZE);
|
|
||||||
// printf("+%s(Addr 0x%06lX)\r\n",__func__,address);
|
|
||||||
|
|
||||||
HAL_StatusTypeDef hal_rc;
|
HAL_StatusTypeDef hal_rc;
|
||||||
FLASH_EraseInitTypeDef EraseInitStruct;
|
FLASH_EraseInitTypeDef EraseInitStruct = {
|
||||||
|
.TypeErase = FLASH_TYPEERASE_PAGES,
|
||||||
|
.Page = 0,
|
||||||
|
.NbPages = 1
|
||||||
|
};
|
||||||
uint32_t PAGEError = 0;
|
uint32_t PAGEError = 0;
|
||||||
|
|
||||||
/* Fill EraseInit structure*/
|
LFS_UNUSED(c);
|
||||||
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
|
|
||||||
EraseInitStruct.Page = (address - FLASH_BASE) / STM32WL_SECTOR_SIZE;
|
if((address < LFS_FLASH_ADDR_BASE) || (address > LFS_FLASH_ADDR_END))
|
||||||
EraseInitStruct.NbPages = 1;
|
{
|
||||||
|
_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_rc = HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
|
||||||
// if (hal_rc != HAL_OK)
|
HAL_FLASH_Lock();
|
||||||
// {
|
|
||||||
// printf("%s ERROR 0x%X\n",__func__,hal_rc);
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// printf("%s SUCCESS\n",__func__);
|
|
||||||
|
|
||||||
return hal_rc == HAL_OK ? LFS_ERR_OK : LFS_ERR_IO; // If HAL_OK, return LFS_ERR_OK, else 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
|
||||||
}
|
}
|
||||||
@ -150,17 +145,14 @@ static int _internal_flash_erase(const struct lfs_config *c, lfs_block_t block)
|
|||||||
// are propogated to the user.
|
// are propogated to the user.
|
||||||
static int _internal_flash_sync(const struct lfs_config *c)
|
static int _internal_flash_sync(const struct lfs_config *c)
|
||||||
{
|
{
|
||||||
// (void) c;
|
LFS_UNUSED(c);
|
||||||
// flash_nrf5x_flush();
|
|
||||||
// return 0;
|
|
||||||
PARAMETER_NOT_USED(c);
|
|
||||||
// write function performs no caching. No need for sync.
|
// write function performs no caching. No need for sync.
|
||||||
// printf("+%s()\r\n",__func__);
|
|
||||||
return LFS_ERR_OK;
|
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,
|
.read = _internal_flash_read,
|
||||||
.prog = _internal_flash_prog,
|
.prog = _internal_flash_prog,
|
||||||
@ -176,7 +168,8 @@ static struct lfs_config _InternalFSConfig = {.context = NULL,
|
|||||||
.read_buffer = NULL,
|
.read_buffer = NULL,
|
||||||
.prog_buffer = NULL,
|
.prog_buffer = NULL,
|
||||||
.lookahead_buffer = NULL,
|
.lookahead_buffer = NULL,
|
||||||
.file_buffer = NULL};
|
.file_buffer = NULL
|
||||||
|
};
|
||||||
|
|
||||||
LittleFS InternalFS;
|
LittleFS InternalFS;
|
||||||
|
|
||||||
@ -188,11 +181,11 @@ LittleFS::LittleFS(void) : STM32_LittleFS(&_InternalFSConfig) {}
|
|||||||
|
|
||||||
bool LittleFS::begin(void)
|
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()) {
|
if (!STM32_LittleFS::begin()) {
|
||||||
// Erase all sectors of internal flash region for Filesystem.
|
// Erase all pages 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) {
|
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) / STM32WL_SECTOR_SIZE);
|
_internal_flash_erase(&_InternalFSConfig, (addr - LFS_FLASH_ADDR_BASE) / STM32WL_PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// lfs format
|
// lfs format
|
||||||
|
@ -97,7 +97,7 @@ class STM32_LittleFS
|
|||||||
#define PRINT_LFS_ERR(_err) \
|
#define PRINT_LFS_ERR(_err) \
|
||||||
do { \
|
do { \
|
||||||
if (_err) { \
|
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
|
} while (0) // LFS_ERR are of type int, VERIFY_MESS expects long_int
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user