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

enable LittleFS and encryption on STM32 platform (wio-e5) #6071

Open
wants to merge 10 commits into
base: stm32wl-fs
Choose a base branch
from
16 changes: 5 additions & 11 deletions arch/stm32/stm32.ini
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,8 @@ extra_scripts =
post:extra_scripts/extra_stm32.py
build_type = release

;board_build.flash_offset = 0x08000000

build_flags =
build_flags =
${arduino_base.build_flags}
-Wl,--undefined=vTaskSwitchContext
-flto
-Isrc/platform/stm32wl -g
-DMESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
Expand All @@ -21,25 +18,22 @@ build_flags =
-DMESHTASTIC_EXCLUDE_SCREEN
-DMESHTASTIC_EXCLUDE_MQTT
-DMESHTASTIC_EXCLUDE_BLUETOOTH
-DMESHTASTIC_EXCLUDE_PKI
-DMESHTASTIC_EXCLUDE_GPS
; -DVECT_TAB_OFFSET=0x08000000
-DconfigUSE_CMSIS_RTOS_V2=1
; -DSPI_MODE_0=SPI_MODE0
-DDEBUG_MUTE
-fmerge-all-constants
-ffunction-sections
-fdata-sections
build_src_filter =

build_src_filter =
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/api/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<input> -<buzz> -<modules/RemoteHardwareModule.cpp> -<platform/nrf52> -<platform/portduino> -<platform/rp2xx0> -<mesh/raspihttp>

board_upload.offset_address = 0x08000000
upload_protocol = stlink
debug_tool = stlink

lib_deps =
${env.lib_deps}
${radiolib_base.lib_deps}
stm32duino/STM32duino FreeRTOS@^10.3.2
https://github.com/caveman99/Crypto.git#eae9c768054118a9399690f8af202853d1ae8516

lib_ignore =
Expand Down
2 changes: 1 addition & 1 deletion src/freertosinc.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include <freertos/task.h>
#endif

#if defined(ARDUINO_NRF52_ADAFRUIT) || defined(ARDUINO_ARCH_RP2040) || defined(STM32WLE5xx)
#if defined(ARDUINO_NRF52_ADAFRUIT) || defined(ARDUINO_ARCH_RP2040)
#define HAS_FREE_RTOS

#include <FreeRTOS.h>
Expand Down
2 changes: 2 additions & 0 deletions src/modules/Modules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
#include "input/SerialKeyboardImpl.h"
#include "input/TrackballInterruptImpl1.h"
#include "input/UpDownInterruptImpl1.h"
#if !MESHTASTIC_EXCLUDE_I2C
#include "input/cardKbI2cImpl.h"
#endif
#include "input/kbMatrixImpl.h"
#endif
#if !MESHTASTIC_EXCLUDE_ADMIN
Expand Down
198 changes: 100 additions & 98 deletions src/platform/stm32wl/LittleFS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,41 +23,49 @@
*/

#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.
* FLASH_END_ADDR is calculated from FLASH_SIZE.
* Use the last 28 KiB of the FLASH
*/
#define LFS_FLASH_TOTAL_SIZE (14 * 2048) /* needs to be a multiple of LFS_BLOCK_SIZE */
#define LFS_BLOCK_SIZE (2048)
#define LFS_FLASH_ADDR_END (FLASH_END_ADDR)
#define LFS_FLASH_ADDR_BASE (LFS_FLASH_ADDR_END - LFS_FLASH_TOTAL_SIZE + 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;
Expand All @@ -68,38 +76,39 @@ 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;
lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE + off);
HAL_StatusTypeDef hal_rc = HAL_OK;
uint32_t dw_count = size / 8;
uint64_t *bufp = (uint64_t *) buffer;

// uint32_t addr = lba2addr(block) + off;
// VERIFY( flash_nrf5x_write(addr, buffer, size), -1)
LFS_UNUSED(c);

// return 0;
PARAMETER_NOT_USED(c);
lfs_block_t address = LFS_FLASH_ADDR + (block * STM32WL_SECTOR_SIZE + off);
HAL_StatusTypeDef hal_rc = HAL_OK;
uint32_t block_count = size / 8;

// 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;

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 {
_LFS_DBG("Programming %d bytes/%d doublewords at address 0x%08x/block %d, offset %d.", size, dw_count, address, block, off);
if (HAL_FLASH_Unlock() != HAL_OK)
{
return LFS_ERR_IO;
}
for (uint32_t i = 0; i < dw_count; i++) {
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 += 1;
}
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
}
Expand All @@ -110,38 +119,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_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);

lfs_block_t address = LFS_FLASH_ADDR_BASE + (block * STM32WL_PAGE_SIZE);
HAL_StatusTypeDef hal_rc;
FLASH_EraseInitTypeDef EraseInitStruct;
FLASH_EraseInitTypeDef EraseInitStruct = {
.TypeErase = FLASH_TYPEERASE_PAGES,
.Page = 0,
.NbPages = 1
};
uint32_t PAGEError = 0;

/* Fill EraseInit structure*/
EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
EraseInitStruct.Page = (address - FLASH_BASE) / STM32WL_SECTOR_SIZE;
EraseInitStruct.NbPages = 1;
hal_rc = HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError);
// if (hal_rc != HAL_OK)
// {
// printf("%s ERROR 0x%X\n",__func__,hal_rc);
// }
// else
// printf("%s SUCCESS\n",__func__);
LFS_UNUSED(c);

if((address < LFS_FLASH_ADDR_BASE) || (address > 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
}
Expand All @@ -150,33 +149,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;

Expand All @@ -188,11 +185,16 @@ LittleFS::LittleFS(void) : STM32_LittleFS(&_InternalFSConfig) {}

bool LittleFS::begin(void)
{
// failed to mount, erase all sector then format and mount again
if(FLASH_BASE >= LFS_FLASH_ADDR_BASE)
{
/* There is not enough space on this device for a filesystem. */
return false;
}
// 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
Expand Down
1 change: 0 additions & 1 deletion src/platform/stm32wl/STM32_LittleFS.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ STM32_LittleFS::STM32_LittleFS(struct lfs_config *cfg)
varclr(&_lfs);
_lfs_cfg = cfg;
_mounted = false;
_mutex = xSemaphoreCreateMutexStatic(&this->_MutexStorageSpace);
}

STM32_LittleFS::~STM32_LittleFS() {}
Expand Down
10 changes: 3 additions & 7 deletions src/platform/stm32wl/STM32_LittleFS.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,13 @@ class STM32_LittleFS
* code. User should not call these directly
*------------------------------------------------------------------*/
lfs_t *_getFS(void) { return &_lfs; }
void _lockFS(void) { xSemaphoreTake(_mutex, portMAX_DELAY); }
void _unlockFS(void) { xSemaphoreGive(_mutex); }
void _lockFS(void) { /* no-op */ }
void _unlockFS(void) { /* no-op */ }

protected:
bool _mounted;
struct lfs_config *_lfs_cfg;
lfs_t _lfs;
SemaphoreHandle_t _mutex;

private:
StaticSemaphore_t _MutexStorageSpace;
};

#if !CFG_DEBUG
Expand All @@ -97,7 +93,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

Expand Down
6 changes: 2 additions & 4 deletions src/platform/stm32wl/littlefs/lfs_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,7 @@ void lfs_crc(uint32_t *crc, const void *buffer, size_t size);
static inline void *lfs_malloc(size_t size)
{
#ifndef LFS_NO_MALLOC
extern void *pvPortMalloc(size_t xWantedSize);
return pvPortMalloc(size);
return malloc(size);
#else
(void)size;
return NULL;
Expand All @@ -186,8 +185,7 @@ static inline void *lfs_malloc(size_t size)
static inline void lfs_free(void *p)
{
#ifndef LFS_NO_MALLOC
extern void vPortFree(void *pv);
vPortFree(p);
free(p);
#else
(void)p;
#endif
Expand Down
2 changes: 2 additions & 0 deletions src/shutdown.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ void powerCommandsCheck()
delete screen;
LOG_DEBUG("final reboot!");
reboot();
#elif defined(ARCH_STM32WL)
HAL_NVIC_SystemReset();
#else
rebootAtMsec = -1;
LOG_WARN("FIXME implement reboot for this platform. Note that some settings require a restart to be applied");
Expand Down
Loading