Skip to content

Commit 8c97ba8

Browse files
niedzwiecki-dawidkartben
authored andcommitted
drivers: flash: stm32h7: ensure option bytes write
Make sure to submit a change of option bytes and wait for the end of the operation. It is done by checking the OPT_BUSY bit. Signed-off-by: Dawid Niedzwiecki <[email protected]>
1 parent f205b57 commit 8c97ba8

File tree

1 file changed

+42
-16
lines changed

1 file changed

+42
-16
lines changed

drivers/flash/flash_stm32h7x.c

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ LOG_MODULE_REGISTER(LOG_DOMAIN);
3333
/* Let's wait for double the max erase time to be sure that the operation is
3434
* completed.
3535
*/
36-
#define STM32H7_FLASH_TIMEOUT (2 * DT_PROP(DT_INST(0, st_stm32_nv_flash), max_erase_time))
36+
#define STM32H7_FLASH_TIMEOUT (2 * DT_PROP(DT_INST(0, st_stm32_nv_flash), max_erase_time))
37+
/* No information in documentation about that. */
38+
#define STM32H7_FLASH_OPT_TIMEOUT_MS 800
3739

3840
#define STM32H7_M4_FLASH_SIZE DT_PROP_OR(DT_INST(0, st_stm32_nv_flash), bank2_flash_size, 0)
3941
#ifdef CONFIG_CPU_CORTEX_M4
@@ -62,41 +64,65 @@ struct flash_stm32_sector_t {
6264
volatile uint32_t *sr;
6365
};
6466

65-
static __unused int write_optsr(const struct device *dev, uint32_t mask, uint32_t value)
67+
static __unused int commit_optb(const struct device *dev)
6668
{
6769
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
68-
int rc;
70+
int64_t timeout_time = k_uptime_get() + STM32H7_FLASH_OPT_TIMEOUT_MS;
71+
72+
regs->OPTCR |= FLASH_OPTCR_OPTSTART;
73+
barrier_dsync_fence_full();
74+
while (regs->OPTSR_CUR & FLASH_OPTSR_OPT_BUSY) {
75+
if (k_uptime_get() > timeout_time) {
76+
LOG_ERR("Timeout writing option bytes.");
77+
return -ETIMEDOUT;
78+
}
79+
}
80+
81+
return 0;
82+
}
83+
84+
static __unused int write_opt(const struct device *dev, uint32_t mask, uint32_t value,
85+
uintptr_t cur, bool commit)
86+
{
87+
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
88+
/* PRG register always follows CUR register. */
89+
uintptr_t prg = cur + 4;
90+
int rc = 0;
6991

7092
if (regs->OPTCR & FLASH_OPTCR_OPTLOCK) {
7193
LOG_ERR("Option bytes locked");
7294
return -EIO;
7395
}
7496

75-
if ((regs->OPTSR_CUR & mask) == value) {
76-
/* Done already */
77-
return 0;
78-
}
79-
8097
rc = flash_stm32_wait_flash_idle(dev);
8198
if (rc < 0) {
8299
LOG_ERR("Err flash no idle");
83100
return rc;
84101
}
85102

86-
regs->OPTSR_PRG = (regs->OPTSR_CUR & ~mask) | value;
87-
regs->OPTCR |= FLASH_OPTCR_OPTSTART;
88-
/* Make sure previous write is completed. */
89-
barrier_dsync_fence_full();
103+
if ((sys_read32(cur) & mask) == value) {
104+
return 0;
105+
}
90106

91-
rc = flash_stm32_wait_flash_idle(dev);
92-
if (rc < 0) {
93-
LOG_ERR("Err flash no idle");
94-
return rc;
107+
sys_write32((sys_read32(cur) & ~mask) | value, prg);
108+
109+
if (commit) {
110+
/* Make sure previous write is completed before committing option bytes. */
111+
barrier_dsync_fence_full();
112+
rc = commit_optb(dev);
95113
}
96114

97115
return rc;
98116
}
99117

118+
static __unused int write_optsr(const struct device *dev, uint32_t mask, uint32_t value)
119+
{
120+
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
121+
uintptr_t cur = (uintptr_t)regs + offsetof(FLASH_TypeDef, OPTSR_CUR);
122+
123+
return write_opt(dev, mask, value, cur, true);
124+
}
125+
100126
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
101127
uint8_t flash_stm32_get_rdp_level(const struct device *dev)
102128
{

0 commit comments

Comments
 (0)