diff --git a/cpu/stm32_common/periph/flash_common.c b/cpu/stm32_common/periph/flash_common.c index 34f92e75f06f..61c6d8d10fd6 100644 --- a/cpu/stm32_common/periph/flash_common.c +++ b/cpu/stm32_common/periph/flash_common.c @@ -38,8 +38,8 @@ void _unlock(void) { - DEBUG("[flash-common] unlocking the flash module\n"); if (CNTRL_REG & CNTRL_REG_LOCK) { + DEBUG("[flash-common] unlocking the flash module\n"); KEY_REG = FLASH_KEY1; KEY_REG = FLASH_KEY2; } @@ -47,6 +47,8 @@ void _unlock(void) void _lock(void) { - DEBUG("[flash-common] locking the flash module\n"); - CNTRL_REG |= CNTRL_REG_LOCK; + if (!(CNTRL_REG & CNTRL_REG_LOCK)) { + DEBUG("[flash-common] locking the flash module\n"); + CNTRL_REG |= CNTRL_REG_LOCK; + } } diff --git a/cpu/stm32_common/periph/flashpage.c b/cpu/stm32_common/periph/flashpage.c index e4454b18183b..9bbebd36ad5f 100644 --- a/cpu/stm32_common/periph/flashpage.c +++ b/cpu/stm32_common/periph/flashpage.c @@ -65,6 +65,17 @@ static void _unlock_flash(void) #endif } +static void _wait_for_pending_operations(void) +{ + DEBUG("[flashpage] waiting for any pending operation to finish\n"); + while (FLASH->SR & FLASH_SR_BSY) {} + + /* Clear 'end of operation' bit in status register */ + if (FLASH->SR & FLASH_SR_EOP) { + FLASH->SR &= ~(FLASH_SR_EOP); + } +} + static void _erase_page(void *page_addr) { #if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1) @@ -77,12 +88,12 @@ static void _erase_page(void *page_addr) stmclk_enable_hsi(); #endif - /* unlock the flash module */ + /* unlock the flash module */ _unlock_flash(); /* make sure no flash operation is ongoing */ - DEBUG("[flashpage] erase: waiting for any operation to finish\n"); - while (FLASH->SR & FLASH_SR_BSY) {} + _wait_for_pending_operations(); + /* set page erase bit and program page address */ DEBUG("[flashpage] erase: setting the erase bit\n"); CNTRL_REG |= FLASH_CR_PER; @@ -97,8 +108,9 @@ static void _erase_page(void *page_addr) DEBUG("[flashpage] erase: trigger the page erase\n"); CNTRL_REG |= FLASH_CR_STRT; #endif - DEBUG("[flashpage] erase: wait as long as device is busy\n"); - while (FLASH->SR & FLASH_SR_BSY) {} + /* wait as long as device is busy */ + _wait_for_pending_operations(); + /* reset PER bit */ DEBUG("[flashpage] erase: resetting the page erase bit\n"); CNTRL_REG &= ~(FLASH_CR_PER); @@ -140,10 +152,10 @@ void flashpage_write_raw(void *target_addr, const void *data, size_t len) stmclk_enable_hsi(); #endif - DEBUG("[flashpage_raw] unlocking the flash module\n"); + /* unlock the flash module */ _unlock_flash(); - DEBUG("[flashpage] write: now writing the data\n"); + DEBUG("[flashpage_raw] write: now writing the data\n"); #if !(defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1)) /* set PG bit and program page to flash */ CNTRL_REG |= FLASH_CR_PG; @@ -151,14 +163,15 @@ void flashpage_write_raw(void *target_addr, const void *data, size_t len) for (size_t i = 0; i < (len / FLASHPAGE_DIV); i++) { DEBUG("[flashpage_raw] writing %c to %p\n", (char)data_addr[i], dst); *dst++ = data_addr[i]; - while (FLASH->SR & FLASH_SR_BSY) {} + /* wait as long as device is busy */ + _wait_for_pending_operations(); } /* clear program bit again */ CNTRL_REG &= ~(FLASH_CR_PG); - DEBUG("[flashpage] write: done writing data\n"); + DEBUG("[flashpage_raw] write: done writing data\n"); - DEBUG("flashpage_raw] now locking the flash module again\n"); + /* lock the flash module again */ _lock(); #if !(defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32L1))