Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cpu/sam0_common: flashpage: disable cache while writing #21043

Merged
merged 2 commits into from
Dec 15, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions cpu/sam0_common/periph/flashpage.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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();

Expand All @@ -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)
Expand Down Expand Up @@ -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 */
Expand All @@ -256,15 +263,15 @@ 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))
{
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.
Expand All @@ -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,
Expand Down
Loading