Skip to content

Commit 2320973

Browse files
vaussardgalak
authored andcommitted
flash: stm32l4: disable dcache before writting
Disable the data cache before writing to Flash, in order to workaround silicon errata 2.2.3: "Data cache might be corrupted during Flash memory read-while-write operation". The data cache is conditionally re-enabled once the write is completed. This silicon bug has been encountered while stress testing the implementation. Here are the events leading to the fault: - Code is executing from Flash bank 1 - A write to Flash bank 2 is initiated - The Cortex SysTick interrupt fires while waiting for Flash write completion In that case, the Flash controller will perform a read-while-write operation in order to execute the ISR code. As the data cache is enabled by default after reset, a corruption occurs due to the silicon bug, leading to bizarre data bus faults or unaligned access faults inside _timer_int_handler() or one of the functions called by the ISR. Applying the workaround devised by ST fixes the problem. Signed-off-by: Florian Vaussard <[email protected]>
1 parent 29cc3b5 commit 2320973

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

drivers/flash/flash_stm32l4x.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ static int write_dword(struct device *dev, off_t offset, u64_t val)
4848
{
4949
volatile u32_t *flash = (u32_t *)(offset + CONFIG_FLASH_BASE_ADDRESS);
5050
struct stm32l4x_flash *regs = FLASH_STM32_REGS(dev);
51+
#ifdef FLASH_OPTR_DUALBANK
52+
bool dcache_enabled = false;
53+
#endif /* FLASH_OPTR_DUALBANK */
5154
u32_t tmp;
5255
int rc;
5356

@@ -68,6 +71,17 @@ static int write_dword(struct device *dev, off_t offset, u64_t val)
6871
return -EIO;
6972
}
7073

74+
#ifdef FLASH_OPTR_DUALBANK
75+
/*
76+
* Disable the data cache to avoid the silicon errata 2.2.3:
77+
* "Data cache might be corrupted during Flash memory read-while-write operation"
78+
*/
79+
if (regs->acr.val & FLASH_ACR_DCEN) {
80+
dcache_enabled = true;
81+
regs->acr.val &= (~FLASH_ACR_DCEN);
82+
}
83+
#endif /* FLASH_OPTR_DUALBANK */
84+
7185
/* Set the PG bit */
7286
regs->cr |= FLASH_CR_PG;
7387

@@ -84,6 +98,15 @@ static int write_dword(struct device *dev, off_t offset, u64_t val)
8498
/* Clear the PG bit */
8599
regs->cr &= (~FLASH_CR_PG);
86100

101+
#ifdef FLASH_OPTR_DUALBANK
102+
/* Reset/enable the data cache if previously enabled */
103+
if (dcache_enabled) {
104+
regs->acr.val |= FLASH_ACR_DCRST;
105+
regs->acr.val &= (~FLASH_ACR_DCRST);
106+
regs->acr.val |= FLASH_ACR_DCEN;
107+
}
108+
#endif /* FLASH_OPTR_DUALBANK */
109+
87110
return rc;
88111
}
89112

0 commit comments

Comments
 (0)