From c93c3e46d69c7912b81c183a8abc8554f6330b05 Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Tue, 10 Nov 2020 15:06:24 +0100 Subject: [PATCH 1/2] flashpage: Support non uniform flashpage sizes --- drivers/include/periph/flashpage.h | 45 ++++++++++++++++++++++++++---- drivers/periph_common/flashpage.c | 4 +-- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/drivers/include/periph/flashpage.h b/drivers/include/periph/flashpage.h index ae7ab3cc9c..2153b84f95 100644 --- a/drivers/include/periph/flashpage.h +++ b/drivers/include/periph/flashpage.h @@ -84,6 +84,27 @@ extern "C" { #ifdef DOXYGEN #define FLASHPAGE_WRITE_BLOCK_ALIGNMENT #endif + +/** + * @def PERIPH_FLASHPAGE_CUSTOM_PAGESIZES + * + * @brief Defined to signal that the peripheral has non-uniform flash page + * sizes. These devices do not define FLASHPAGE_SIZE and do not + * implement the pagewise api. + */ +#ifdef DOXYGEN +#define PERIPH_FLASHPAGE_CUSTOM_PAGESIZES +#endif + +/** + * @brief Return values used in this interface + */ +enum { + FLASHPAGE_OK = 0, /**< everything succeeded */ + FLASHPAGE_NOMATCH = -1 /**< page differs from target data */ +}; + +#if !defined(PERIPH_FLASHPAGE_CUSTOM_PAGESIZES) || defined(DOXYGEN) /** * @def FLASHPAGE_SIZE * @@ -97,12 +118,17 @@ extern "C" { #endif /** - * @brief Return values used in this interface + * @brief Get the page size of the given page number + * + * @param[in] page page number to get the size for + * + * @return Page size of the given page */ -enum { - FLASHPAGE_OK = 0, /**< everything succeeded */ - FLASHPAGE_NOMATCH = -1 /**< page differs from target data */ -}; +static inline size_t flashpage_size(unsigned page) +{ + (void)page; + return FLASHPAGE_SIZE; +} /** * @brief Translate the given page number into the page's starting address @@ -135,6 +161,15 @@ static inline unsigned flashpage_page(void *addr) return (((intptr_t)addr - CPU_FLASH_BASE) / FLASHPAGE_SIZE); } +#else + +/* Bare prototypes for the above functions. See above for the documentation */ +size_t flashpage_size(unsigned page); +void *flashpage_addr(unsigned page); +unsigned flashpage_page(void *addr); + +#endif + /** * @brief Erase the given page * diff --git a/drivers/periph_common/flashpage.c b/drivers/periph_common/flashpage.c index 3ef346eaec..8d0f4a4640 100644 --- a/drivers/periph_common/flashpage.c +++ b/drivers/periph_common/flashpage.c @@ -37,7 +37,7 @@ void flashpage_read(unsigned page, void *data) assert(page < (FLASH->SFR & FLASH_SFR_SFSA)); #endif - memcpy(data, flashpage_addr(page), FLASHPAGE_SIZE); + memcpy(data, flashpage_addr(page), flashpage_size(page)); } int flashpage_verify(unsigned page, const void *data) @@ -48,7 +48,7 @@ int flashpage_verify(unsigned page, const void *data) assert(page < (int)(FLASH->SFR & FLASH_SFR_SFSA)); #endif - if (memcmp(flashpage_addr(page), data, FLASHPAGE_SIZE) == 0) { + if (memcmp(flashpage_addr(page), data, flashpage_size(page)) == 0) { return FLASHPAGE_OK; } else { From 5b0eaf7cd8bc4419b27f993b68d03ad440ef7a22 Mon Sep 17 00:00:00 2001 From: Koen Zandberg Date: Mon, 1 Feb 2021 12:55:26 +0100 Subject: [PATCH 2/2] riotboot/flashwrite: Remove last dependencies on flashpage size --- sys/riotboot/flashwrite.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/sys/riotboot/flashwrite.c b/sys/riotboot/flashwrite.c index a9d102dbda..e5ef3134ae 100644 --- a/sys/riotboot/flashwrite.c +++ b/sys/riotboot/flashwrite.c @@ -49,9 +49,15 @@ size_t riotboot_flashwrite_slotsize( int riotboot_flashwrite_init_raw(riotboot_flashwrite_t *state, int target_slot, size_t offset) { +#ifdef FLASHPAGE_SIZE assert(offset <= FLASHPAGE_SIZE); /* the flashpage size must be a multiple of the riotboot flashpage buffer */ static_assert(!(FLASHPAGE_SIZE % RIOTBOOT_FLASHPAGE_BUFFER_SIZE)); +#else + /* The flashpage buffer must be a multiple of the write block size */ + static_assert(!(RIOTBOOT_FLASHPAGE_BUFFER_SIZE % FLASHPAGE_WRITE_BLOCK_SIZE)); +#endif + LOG_INFO(LOG_PREFIX "initializing update to target slot %i\n", target_slot); @@ -103,15 +109,20 @@ int riotboot_flashwrite_putbytes(riotboot_flashwrite_t *state, LOG_DEBUG(LOG_PREFIX "processing bytes %u-%u\n", state->offset, state->offset + len - 1); while (len) { - size_t flashpage_pos = state->offset % FLASHPAGE_SIZE; + /* Position within the page, calculated from state->offset by + * subtracting the start offset of the current page */ + size_t flashpage_pos = state->offset - + (flashpage_addr(state->flashpage) - (void*)riotboot_slot_get_hdr(state->target_slot)); size_t flashwrite_buffer_pos = state->offset % RIOTBOOT_FLASHPAGE_BUFFER_SIZE; size_t flashpage_avail = RIOTBOOT_FLASHPAGE_BUFFER_SIZE - flashwrite_buffer_pos; size_t to_copy = min(flashpage_avail, len); - if (CONFIG_RIOTBOOT_FLASHWRITE_RAW && flashpage_pos == 0) { + if (CONFIG_RIOTBOOT_FLASHWRITE_RAW && + flashpage_pos == flashpage_size(state->flashpage)) { /* Erase the next page */ state->flashpage++; + flashpage_pos = 0; flashpage_erase(state->flashpage); } if (CONFIG_RIOTBOOT_FLASHWRITE_RAW &&