diff --git a/cpu/sam0_common/periph/flashpage.c b/cpu/sam0_common/periph/flashpage.c index 3481229870fb..d128e88f0d77 100644 --- a/cpu/sam0_common/periph/flashpage.c +++ b/cpu/sam0_common/periph/flashpage.c @@ -64,7 +64,7 @@ static inline void wait_nvm_is_ready(void) #endif } -static unsigned _unlock(void) +static void _unlock(void) { /* remove peripheral access lock for the NVMCTRL peripheral */ #ifdef REG_PAC_WRCTRL @@ -73,10 +73,14 @@ static unsigned _unlock(void) PAC1->WPCLR.reg = PAC1_WPROT_DEFAULT_VAL; #endif - return irq_disable(); + /* NVM reads could be corrupted when mixing NVM reads with Page Buffer writes. */ +#ifdef NVMCTRL_CTRLA_CACHEDIS1 + _NVMCTRL->CTRLA.reg |= NVMCTRL_CTRLA_CACHEDIS0 + | NVMCTRL_CTRLA_CACHEDIS1; +#endif } -static void _lock(unsigned state) +static void _lock(void) { wait_nvm_is_ready(); @@ -87,12 +91,15 @@ static void _lock(unsigned state) PAC1->WPSET.reg = PAC1_WPROT_DEFAULT_VAL; #endif +#ifdef NVMCTRL_CTRLA_CACHEDIS1 + _NVMCTRL->CTRLA.reg &= ~NVMCTRL_CTRLA_CACHEDIS0 + & ~NVMCTRL_CTRLA_CACHEDIS1; +#endif + /* cached flash contents may have changed - invalidate cache */ #ifdef CMCC CMCC->MAINT0.reg |= CMCC_MAINT0_INVALL; #endif - - irq_restore(state); } static void _cmd_clear_page_buffer(void) @@ -229,7 +236,7 @@ static void _write_page(void* dst, const void *data, size_t len, void (*cmd_writ /* word align destination address */ uint32_t *dst32 = (void*)((uintptr_t)dst & ~0x3); - unsigned state = _unlock(); + _unlock(); _cmd_clear_page_buffer(); /* write the first, unaligned bytes */ @@ -256,7 +263,7 @@ static void _write_page(void* dst, const void *data, size_t len, void (*cmd_writ } cmd_write(); - _lock(state); + _lock(); } static void _erase_page(void* page, void (*cmd_erase)(void)) @@ -264,7 +271,7 @@ static void _erase_page(void* page, void (*cmd_erase)(void)) uintptr_t page_addr = (uintptr_t)page; /* erase given page (the ADDR register uses 16-bit addresses) */ - unsigned state = _unlock(); + _unlock(); /* ADDR drives the hardware (16-bit) address to the NVM when a command is executed using CMDEX. * 8-bit addresses must be shifted one bit to the right before writing to this register. @@ -277,7 +284,7 @@ static void _erase_page(void* page, void (*cmd_erase)(void)) _NVMCTRL->ADDR.reg = page_addr; cmd_erase(); - _lock(state); + _lock(); } static void _write_row(uint8_t *dst, const void *_data, size_t len, size_t chunk_size,