From f1253574a384d8da3319fa43bb47f51b7225f3f8 Mon Sep 17 00:00:00 2001 From: Hashem Hashem Date: Tue, 17 Oct 2023 16:33:06 +0200 Subject: [PATCH] feat(stm32-common): add SPI flash driver with littlefs support --- libs/stm32-common/include/spi-flash.h | 16 ++++++++ libs/stm32-common/meson.build | 1 + libs/stm32-common/src/spi-flash.c | 55 +++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 libs/stm32-common/include/spi-flash.h diff --git a/libs/stm32-common/include/spi-flash.h b/libs/stm32-common/include/spi-flash.h new file mode 100644 index 00000000..d5deaf55 --- /dev/null +++ b/libs/stm32-common/include/spi-flash.h @@ -0,0 +1,16 @@ +#ifndef SPI_FLASH_H +#define SPI_FLASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lfs.h" + +const struct lfs_config *get_spi_flash_lfs_config(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SPI_FLASH_H */ diff --git a/libs/stm32-common/meson.build b/libs/stm32-common/meson.build index 9aa7309e..116049be 100644 --- a/libs/stm32-common/meson.build +++ b/libs/stm32-common/meson.build @@ -8,6 +8,7 @@ stm32_lib_src = files( 'src' / 'error.c', 'src' / 'flash.c', 'src' / 'print.c', + 'src' / 'spi-flash.c', ) stm32_startup_src = files( diff --git a/libs/stm32-common/src/spi-flash.c b/libs/stm32-common/src/spi-flash.c index faaf6754..40d5dc04 100644 --- a/libs/stm32-common/src/spi-flash.c +++ b/libs/stm32-common/src/spi-flash.c @@ -1,3 +1,5 @@ +#include "spi-flash.h" + #include #include @@ -10,6 +12,9 @@ #include "FreeRTOS.h" #include "task.h" +// littlefs +#include "lfs.h" + #define READ_DATA_COMMAND 0x03 #define READ_SR1_COMMAND 0x05 #define WRITE_ENABLE_COMMAND 0x06 @@ -35,6 +40,56 @@ static int read(uint32_t address, uint8_t *data, size_t size); static int wait_until_ready(void); static int write_enable(void); +// Statically allocate buffers for littelfs +static uint8_t lfs_read_buf[PAGE_SIZE]; +static uint8_t lfs_prog_buf[PAGE_SIZE]; +static uint8_t lfs_lookahead_buf[PAGE_SIZE]; + +// Functions required by littlefs +static int spi_flash_read(const struct lfs_config *config, lfs_block_t block, + lfs_off_t offset, void *buffer, lfs_size_t size) { + return read(block * config->block_size + offset, buffer, size); +} + +static int spi_flash_prog(const struct lfs_config *config, lfs_block_t block, + lfs_off_t offset, const void *buffer, + lfs_size_t size) { + return program(block * config->block_size + offset, (uint8_t *)buffer, size); +} + +static int spi_flash_erase(const struct lfs_config *config, lfs_block_t block) { + return erase(block * config->block_size); +} + +static int spi_flash_sync(const struct lfs_config *config) { + (void)config; + return APP_OK; +} + +static const struct lfs_config lfs_cfg = { + // Operations + .read = spi_flash_read, + .prog = spi_flash_prog, + .erase = spi_flash_erase, + .sync = spi_flash_sync, + + // Configuration + .read_size = 1, + .prog_size = 1, + .block_size = SECTOR_SIZE, // Flash is sector-erasable + .block_count = SECTOR_COUNT, + .block_cycles = 100, // Optimize for wear leveling + + .cache_size = sizeof(lfs_read_buf), + .read_buffer = lfs_read_buf, + .prog_buffer = lfs_prog_buf, + + .lookahead_size = sizeof(lfs_lookahead_buf), + .lookahead_buffer = lfs_lookahead_buf, +}; + +const struct lfs_config *get_spi_flash_lfs_config(void) { return &lfs_cfg; } + static int wait_until_ready(void) { common_peripherals_t *peripherals = get_common_peripherals(); uint8_t cmd = READ_SR1_COMMAND;