Skip to content

Commit 3d372c0

Browse files
niedzwiecki-dawidkartben
authored andcommitted
drivers: flash: stm32h7: add support for blocking registers
Add support for blocking flash control registers and option bytes for STM32H7 chips. Signed-off-by: Dawid Niedzwiecki <[email protected]>
1 parent def973f commit 3d372c0

File tree

3 files changed

+113
-5
lines changed

3 files changed

+113
-5
lines changed

drivers/flash/flash_stm32h7x.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,70 @@ int flash_stm32_get_wp_sectors(const struct device *dev, uint64_t *protected_sec
242242
}
243243
#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */
244244

245+
#ifdef CONFIG_FLASH_STM32_BLOCK_REGISTERS
246+
int flash_stm32_control_register_disable(const struct device *dev)
247+
{
248+
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
249+
250+
/*
251+
* Access to control register can be disabled by writing wrong key to
252+
* the key register. Option register will remain disabled until reset.
253+
* Writing wrong key causes a bus fault, so we need to set FAULTMASK to
254+
* disable faults, and clear bus fault pending bit before enabling them
255+
* again.
256+
*/
257+
regs->CR1 |= FLASH_CR_LOCK;
258+
#ifdef DUAL_BANK
259+
regs->CR2 |= FLASH_CR_LOCK;
260+
#endif /* DUAL_BANK */
261+
262+
__set_FAULTMASK(1);
263+
regs->KEYR1 = 0xffffffff;
264+
265+
#ifdef DUAL_BANK
266+
regs->KEYR2 = 0xffffffff;
267+
#endif /* DUAL_BANK */
268+
/* Make sure that the fault occurs before we clear it. */
269+
barrier_dsync_fence_full();
270+
271+
/* Clear Bus Fault pending bit */
272+
SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
273+
/* Make sure to clear the fault before changing the fault mask. */
274+
barrier_dsync_fence_full();
275+
276+
__set_FAULTMASK(0);
277+
278+
return 0;
279+
}
280+
281+
int flash_stm32_option_bytes_disable(const struct device *dev)
282+
{
283+
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
284+
285+
/*
286+
* Access to option register can be disabled by writing wrong key to
287+
* the key register. Option register will remain disabled until reset.
288+
* Writing wrong key causes a bus fault, so we need to set FAULTMASK to
289+
* disable faults, and clear bus fault pending bit before enabling them
290+
* again.
291+
*/
292+
regs->OPTCR |= FLASH_OPTCR_OPTLOCK;
293+
294+
__set_FAULTMASK(1);
295+
regs->OPTKEYR = 0xffffffff;
296+
/* Make sure that the fault occurs before we clear it. */
297+
barrier_dsync_fence_full();
298+
299+
/* Clear Bus Fault pending bit */
300+
SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
301+
/* Make sure to clear the fault before changing the fault mask. */
302+
barrier_dsync_fence_full();
303+
__set_FAULTMASK(0);
304+
305+
return 0;
306+
}
307+
#endif /* CONFIG_FLASH_STM32_BLOCK_REGISTERS */
308+
245309
int flash_stm32_option_bytes_lock(const struct device *dev, bool enable)
246310
{
247311
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);

tests/drivers/flash/stm32/src/main.c

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <zephyr/drivers/flash/stm32_flash_api_extensions.h>
1111
#include <zephyr/devicetree.h>
1212
#include <zephyr/storage/flash_map.h>
13+
#include <zephyr/sys/barrier.h>
1314

1415
#define TEST_AREA storage_partition
1516
#define TEST_AREA_OFFSET FIXED_PARTITION_OFFSET(TEST_AREA)
@@ -200,15 +201,46 @@ static void flash_cr_unlock(void)
200201
{
201202
FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG;
202203

204+
#ifdef CONFIG_SOC_SERIES_STM32H7X
205+
regs->KEYR1 = FLASH_KEY1;
206+
regs->KEYR1 = FLASH_KEY2;
207+
#ifdef DUAL_BANK
208+
regs->KEYR2 = FLASH_KEY1;
209+
regs->KEYR2 = FLASH_KEY2;
210+
#endif /* DUAL_BANK */
211+
#else /* CONFIG_SOC_SERIES_STM32H7X */
203212
regs->KEYR = FLASH_KEY1;
204213
regs->KEYR = FLASH_KEY2;
214+
#endif /* CONFIG_SOC_SERIES_STM32H7X */
215+
barrier_dsync_fence_full();
205216
}
206217

207-
static bool flash_cr_locked(void)
218+
static bool flash_cr_is_locked(void)
208219
{
209220
FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG;
210221

222+
#ifdef CONFIG_SOC_SERIES_STM32H7X
223+
return regs->CR1 & FLASH_CR_LOCK;
224+
#ifdef DUAL_BANK
225+
return (regs->CR1 & FLASH_CR_LOCK) && (regs->CR2 & FLASH_CR_LOCK);
226+
#endif /* DUAL_BANK */
227+
#else /* CONFIG_SOC_SERIES_STM32H7X */
211228
return regs->CR & FLASH_CR_LOCK;
229+
#endif /* CONFIG_SOC_SERIES_STM32H7X */
230+
}
231+
232+
static bool flash_cr_is_unlocked(void)
233+
{
234+
FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG;
235+
236+
#ifdef CONFIG_SOC_SERIES_STM32H7X
237+
return !(regs->CR1 & FLASH_CR_LOCK);
238+
#ifdef DUAL_BANK
239+
return !((regs->CR1 & FLASH_CR_LOCK) || (regs->CR2 & FLASH_CR_LOCK));
240+
#endif /* DUAL_BANK */
241+
#else /* CONFIG_SOC_SERIES_STM32H7X */
242+
return !(regs->CR & FLASH_CR_LOCK);
243+
#endif /* CONFIG_SOC_SERIES_STM32H7X */
212244
}
213245

214246
ZTEST(flash_stm32, test_stm32_block_registers)
@@ -227,24 +259,27 @@ ZTEST(flash_stm32, test_stm32_block_registers)
227259
flash_stm32_option_bytes_lock(flash_dev, false);
228260
/* Clear Bus Fault pending bit */
229261
SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
262+
barrier_dsync_fence_full();
230263
__set_FAULTMASK(0);
231264
zassert_true(flash_opt_locked(), "OPT unlocked after being blocked");
232265

233266
/* Test CR lock. */
234-
zassert_true(flash_cr_locked(), "CR should be locked by default");
267+
zassert_true(flash_cr_is_locked(), "CR should be locked by default");
235268
TC_PRINT("Unlocking CR\n");
236269
flash_cr_unlock();
237-
zassert_false(flash_cr_locked(), "Unable to unlock CR");
270+
zassert_true(flash_cr_is_unlocked(), "Unable to unlock CR");
238271
TC_PRINT("Blocking CR\n");
239272
flash_ex_op(flash_dev, FLASH_STM32_EX_OP_BLOCK_CONTROL_REG, (uintptr_t)NULL, NULL);
240-
zassert_true(flash_cr_locked(), "Blocking CR didn't lock CR");
273+
zassert_true(flash_cr_is_locked(), "Blocking CR didn't lock CR");
241274
__set_FAULTMASK(1);
242275
TC_PRINT("Try to unlock blocked CR\n");
243276
flash_cr_unlock();
244277
/* Clear Bus Fault pending bit */
245278
SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk;
279+
barrier_dsync_fence_full();
246280
__set_FAULTMASK(0);
247-
zassert_true(flash_cr_locked(), "CR unlocked after being blocked");
281+
/* Make sure previous write is completed. */
282+
zassert_true(flash_cr_is_locked(), "CR unlocked after being blocked");
248283
}
249284
#endif
250285

tests/drivers/flash/stm32/testcase.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,12 @@ tests:
5454
- CONFIG_FLASH_STM32_WRITE_PROTECT=y
5555
filter: dt_compat_enabled("st,stm32h7-flash-controller") and
5656
dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions")
57+
drivers.flash.stm32.h7.block_registers:
58+
platform_allow:
59+
- nucleo_h743zi
60+
- google_icetower
61+
extra_configs:
62+
- CONFIG_FLASH_STM32_BLOCK_REGISTERS=y
63+
filter: dt_compat_enabled("st,stm32h7-flash-controller") and
64+
dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions") and
65+
CONFIG_SOC_SERIES_STM32H7X

0 commit comments

Comments
 (0)