diff --git a/cpu/stm32_common/periph/flash_common.c b/cpu/stm32_common/periph/flash_common.c index 61c6d8d10f..e254b99486 100644 --- a/cpu/stm32_common/periph/flash_common.c +++ b/cpu/stm32_common/periph/flash_common.c @@ -31,6 +31,10 @@ #define CNTRL_REG_LOCK (FLASH_PECR_PELOCK) #define KEY_REG (FLASH->PEKEYR) #else +#if defined(CPU_FAM_STM32L4) +#define FLASH_KEY1 ((uint32_t)0x45670123) +#define FLASH_KEY2 ((uint32_t)0xCDEF89AB) +#endif #define CNTRL_REG (FLASH->CR) #define CNTRL_REG_LOCK (FLASH_CR_LOCK) #define KEY_REG (FLASH->KEYR) diff --git a/cpu/stm32_common/periph/flashpage.c b/cpu/stm32_common/periph/flashpage.c index 9bbebd36ad..f7b8296902 100644 --- a/cpu/stm32_common/periph/flashpage.c +++ b/cpu/stm32_common/periph/flashpage.c @@ -41,9 +41,13 @@ #define FLASH_CR_PG (FLASH_PECR_FPRG | FLASH_PECR_PROG) #define FLASHPAGE_DIV (4U) /* write 4 bytes in one go */ #else +#if defined(CPU_FAM_STM32L4) +#define FLASHPAGE_DIV (8U) +#else +#define FLASHPAGE_DIV (2U) +#endif #define CNTRL_REG (FLASH->CR) #define CNTRL_REG_LOCK (FLASH_CR_LOCK) -#define FLASHPAGE_DIV (2U) #endif extern void _lock(void); @@ -78,7 +82,8 @@ static void _wait_for_pending_operations(void) static void _erase_page(void *page_addr) { -#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) +#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) || \ + defined(CPU_FAM_STM32L4) uint32_t *dst = page_addr; #else uint16_t *dst = page_addr; @@ -101,7 +106,25 @@ static void _erase_page(void *page_addr) #if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) DEBUG("[flashpage] erase: trigger the page erase\n"); *dst = (uint32_t)0; +#elif defined(CPU_FAM_STM32L4) + DEBUG("[flashpage] erase: setting the page address\n"); + CNTRL_REG |= FLASH_CR_PER; + uint8_t pn; +#if FLASHPAGE_NUMOF <= 256 + pn = (uint8_t)flashpage_page(dst); #else + uint16_t page = flashpage_page(dst); + if (page > 255) { + CNTRL_REG |= FLASH_CR_BKER; + } + else { + CNTRL_REG &= ~FLASH_CR_BKER; + } + pn = (uint8_t)page; +#endif + CNTRL_REG |= (uint32_t)(pn << FLASH_CR_PNB_Pos); + CNTRL_REG |= FLASH_CR_STRT; +#else /* CPU_FAM_STM32F0 || CPU_FAM_STM32F1 */ DEBUG("[flashpage] erase: setting the page address\n"); FLASH->AR = (uint32_t)dst; /* trigger the page erase and wait for it to be finished */ @@ -118,7 +141,8 @@ static void _erase_page(void *page_addr) /* lock the flash module again */ _lock(); -#if !(defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)) +#if !(defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) || \ + defined(CPU_FAM_STM32L4)) /* restore the HSI state */ if (!hsi_state) { stmclk_disable_hsi(); @@ -143,6 +167,9 @@ void flashpage_write_raw(void *target_addr, const void *data, size_t len) #if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) uint32_t *dst = target_addr; const uint32_t *data_addr = data; +#elif defined(CPU_FAM_STM32L4) + uint64_t *dst = target_addr; + const uint64_t *data_addr = data; #else uint16_t *dst = (uint16_t *)target_addr; const uint16_t *data_addr = data; @@ -174,7 +201,8 @@ void flashpage_write_raw(void *target_addr, const void *data, size_t len) /* lock the flash module again */ _lock(); -#if !(defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)) +#if !(defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) || \ + defined(CPU_FAM_STM32L4)) /* restore the HSI state */ if (!hsi_state) { stmclk_disable_hsi(); @@ -189,6 +217,8 @@ void flashpage_write(int page, const void *data) #if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) /* STM32L0/L1 only supports word sizes */ uint32_t *page_addr = flashpage_addr(page); +#elif defined(CPU_FAM_STM32L4) + uint64_t *page_addr = flashpage_addr(page); #else /* Default is to support half-word sizes */ uint16_t *page_addr = flashpage_addr(page); diff --git a/cpu/stm32l4/Makefile.features b/cpu/stm32l4/Makefile.features index c51e0186eb..f4388f2759 100644 --- a/cpu/stm32l4/Makefile.features +++ b/cpu/stm32l4/Makefile.features @@ -1,3 +1,6 @@ +FEATURES_PROVIDED += periph_flash_common +FEATURES_PROVIDED += periph_flashpage +FEATURES_PROVIDED += periph_flashpage_raw FEATURES_PROVIDED += periph_hwrng -include $(RIOTCPU)/stm32_common/Makefile.features diff --git a/cpu/stm32l4/include/cpu_conf.h b/cpu/stm32l4/include/cpu_conf.h index a8212c862f..b820a8de3f 100644 --- a/cpu/stm32l4/include/cpu_conf.h +++ b/cpu/stm32l4/include/cpu_conf.h @@ -57,6 +57,27 @@ extern "C" { #endif /** @} */ +/** + * @name Flash page configuration + * @{ + */ +#define FLASHPAGE_SIZE (2048U) + +#if defined(CPU_MODEL_STM32L432KC) || defined(CPU_MODEL_STM32L433RC) +#define FLASHPAGE_NUMOF (128U) +#elif defined(CPU_MODEL_STM32L452RE) +#define FLASHPAGE_NUMOF (256U) +#else +#define FLASHPAGE_NUMOF (512U) +#endif +/* The minimum block size which can be written is 8B. However, the erase + * block is always FLASHPAGE_SIZE. + */ +#define FLASHPAGE_RAW_BLOCKSIZE (8U) +/* Writing should be always 8 bytes aligned */ +#define FLASHPAGE_RAW_ALIGNMENT (8U) +/** @} */ + #ifdef __cplusplus } #endif diff --git a/tests/periph_flashpage/main.c b/tests/periph_flashpage/main.c index 947c58c726..f79f08086e 100644 --- a/tests/periph_flashpage/main.c +++ b/tests/periph_flashpage/main.c @@ -28,25 +28,28 @@ #define LINE_LEN (16) -/** - * @brief Allocate space for 1 flash page in RAM - */ -static uint8_t page_mem[FLASHPAGE_SIZE]; - +/* When writing raw bytes on flash, data must be correctly aligned. */ #ifdef MODULE_PERIPH_FLASHPAGE_RAW +#define ALIGNMENT_ATTR __attribute__ ((aligned (FLASHPAGE_RAW_ALIGNMENT))) + /* * @brief Allocate an aligned buffer for raw writings */ -static char raw_buf[64] __attribute__ ((aligned (FLASHPAGE_RAW_ALIGNMENT))); - -static uint32_t getaddr(const char *str) -{ - uint32_t addr = strtol(str, NULL, 16); - - return addr; -} +static char raw_buf[64] ALIGNMENT_ATTR; +#else +#define ALIGNMENT_ATTR #endif +/** + * @brief Allocate space for 1 flash page in RAM + * + * @note The flash page in RAM must be correctly aligned, even in RAM, when + * using flashpage_raw. This is because some architecture uses + * 32 bit alignment implicitly and there are cases (stm32l4) that + * requires 64 bit alignment. + */ +static uint8_t page_mem[FLASHPAGE_SIZE] ALIGNMENT_ATTR; + static int getpage(const char *str) { int page = atoi(str); @@ -180,6 +183,13 @@ static int cmd_write(int argc, char **argv) } #ifdef MODULE_PERIPH_FLASHPAGE_RAW +static uint32_t getaddr(const char *str) +{ + uint32_t addr = strtol(str, NULL, 16); + + return addr; +} + static int cmd_write_raw(int argc, char **argv) { uint32_t addr;