From 9bf6ce8b64f3f945cff256e4744e3bd2ddc7e6bf Mon Sep 17 00:00:00 2001 From: Guillaume Revaillot Date: Sat, 4 Apr 2020 08:07:05 +0200 Subject: [PATCH] stm32g0: flash: add erase/program stuff probably can be refactored with other chips, did not really looked yet. --- include/libopencm3/stm32/g0/flash.h | 18 ++++ lib/stm32/g0/flash.c | 141 +++++++++++++++++++++++++++- 2 files changed, 158 insertions(+), 1 deletion(-) diff --git a/include/libopencm3/stm32/g0/flash.h b/include/libopencm3/stm32/g0/flash.h index 46617221..2de4bc51 100644 --- a/include/libopencm3/stm32/g0/flash.h +++ b/include/libopencm3/stm32/g0/flash.h @@ -258,6 +258,24 @@ BEGIN_DECLS +void flash_clear_progerr_flag(void); +void flash_clear_pgserr_flag(void); +void flash_clear_size_flag(void); +void flash_clear_pgaerr_flag(void); +void flash_clear_wrperr_flag(void); +void flash_clear_operr_flag(void); +void flash_clear_eop_flag(void); + +void flash_clear_status_flags(void); + +void flash_wait_for_last_operation(void); + +void flash_program_double_word(uint32_t address, uint64_t data); +void flash_program(uint32_t address, uint8_t *data, uint32_t len); + +void flash_erase_page(uint32_t page); +void flash_erase_all_pages(void); + /** Enable instruction cache */ void flash_icache_enable(void); /** Disable instruction cache */ diff --git a/lib/stm32/g0/flash.c b/lib/stm32/g0/flash.c index 74ecf5d0..9b40c0fd 100644 --- a/lib/stm32/g0/flash.c +++ b/lib/stm32/g0/flash.c @@ -30,6 +30,145 @@ #include +/** @brief Wait until Last Flash Operation has Ended */ +void flash_wait_for_last_operation(void) +{ + while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY); +} + +/** @brief Program a 64bits word to FLASH + * + * Program a 64bit word to FLASH memory. + * Flash programing error must be checked and cleared if needed + * before starting programming. + * + * @param[in] address Address in FLASH + * @param[in] data Double word to write + */ +void flash_program_double_word(uint32_t address, uint64_t data) +{ + flash_wait_for_last_operation(); + + FLASH_CR |= FLASH_CR_PG; + + MMIO32(address) = (uint32_t)data; + MMIO32(address+4) = (uint32_t)(data >> 32); + + flash_wait_for_last_operation(); + + FLASH_CR &= ~FLASH_CR_PG; +} + +/** @brief Program a Data Block to FLASH + * + * This programs an arbitrary length data block to FLASH memory. + * The program error flag should be checked separately for the event that memory + * was not properly erased. + * + * @param[in] address Starting address in Flash. + * @param[in] data Pointer to start of data block. + * @param[in] len Length of data block in bytes (multiple of 8). + **/ +void flash_program(uint32_t address, uint8_t *data, uint32_t len) +{ + for (uint32_t i = 0; i < len; i += 8) { + flash_program_double_word(address+i, *(uint64_t*)(data + i)); + } +} + +/** @brief Erase a page of FLASH + * @param[in] page + */ +void flash_erase_page(uint32_t page) +{ + flash_wait_for_last_operation(); + + uint32_t reg = FLASH_CR; + reg &= ~(FLASH_CR_PNB_MASK << FLASH_CR_PNB_SHIFT); + reg |= (page & FLASH_CR_PNB_MASK) << FLASH_CR_PNB_SHIFT; + reg |= FLASH_CR_PER; + reg |= FLASH_CR_STRT; + + FLASH_CR = reg; + + flash_wait_for_last_operation(); + + FLASH_CR &= ~FLASH_CR_PER; +} + +/** @brief Erase All FLASH + * This performs all operations necessary to erase all sectors in the FLASH + * memory. + */ +void flash_erase_all_pages(void) +{ + flash_wait_for_last_operation(); + + FLASH_CR |= FLASH_CR_MER; + FLASH_CR |= FLASH_CR_STRT; + + flash_wait_for_last_operation(); + FLASH_CR &= ~FLASH_CR_MER; +} + +/** @brief Clear the Programming Sequence Error Flag */ +void flash_clear_pgserr_flag(void) +{ + FLASH_SR |= FLASH_SR_PGSERR; +} + +/** @brief Clear the End of Operation Flag */ +void flash_clear_eop_flag(void) +{ + FLASH_SR |= FLASH_SR_EOP; +} + +/** @brief Clear programming size error flag */ +void flash_clear_size_flag(void) +{ + FLASH_SR |= FLASH_SR_SIZERR; +} + +/** @brief Clear the Programming Alignment Error Flag + */ +void flash_clear_pgaerr_flag(void) +{ + FLASH_SR |= FLASH_SR_PGAERR; +} + +/** @brief Clear the Write Protected Error Flag + */ +void flash_clear_wrperr_flag(void) +{ + FLASH_SR |= FLASH_SR_WRPERR; +} + +/** @brief Clear the Programming Error Status Flag + */ +void flash_clear_progerr_flag(void) +{ + FLASH_SR |= FLASH_SR_PROGERR; +} + +/** @brief Clear the Operation Error Status Flag + */ +void flash_clear_operr_flag(void) +{ + FLASH_SR |= FLASH_SR_OPERR; +} + +/** @brief Clear All Status Flags */ +void flash_clear_status_flags(void) +{ + flash_clear_pgserr_flag(); + flash_clear_size_flag(); + flash_clear_pgaerr_flag(); + flash_clear_wrperr_flag(); + flash_clear_progerr_flag(); + flash_clear_eop_flag(); + flash_clear_operr_flag(); +} + void flash_icache_enable(void) { FLASH_ACR |= FLASH_ACR_ICEN; @@ -73,4 +212,4 @@ void flash_lock(void) flash_lock_progmem(); } -/**@}*/ \ No newline at end of file +/**@}*/