diff --git a/drivers/flash/flash_stm32h7x.c b/drivers/flash/flash_stm32h7x.c index d83dd7677ce..7c0e1ad1e23 100644 --- a/drivers/flash/flash_stm32h7x.c +++ b/drivers/flash/flash_stm32h7x.c @@ -242,6 +242,70 @@ int flash_stm32_get_wp_sectors(const struct device *dev, uint64_t *protected_sec } #endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */ +#ifdef CONFIG_FLASH_STM32_BLOCK_REGISTERS +int flash_stm32_control_register_disable(const struct device *dev) +{ + FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); + + /* + * Access to control register can be disabled by writing wrong key to + * the key register. Option register will remain disabled until reset. + * Writing wrong key causes a bus fault, so we need to set FAULTMASK to + * disable faults, and clear bus fault pending bit before enabling them + * again. + */ + regs->CR1 |= FLASH_CR_LOCK; +#ifdef DUAL_BANK + regs->CR2 |= FLASH_CR_LOCK; +#endif /* DUAL_BANK */ + + __set_FAULTMASK(1); + regs->KEYR1 = 0xffffffff; + +#ifdef DUAL_BANK + regs->KEYR2 = 0xffffffff; +#endif /* DUAL_BANK */ + /* Make sure that the fault occurs before we clear it. */ + barrier_dsync_fence_full(); + + /* Clear Bus Fault pending bit */ + SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk; + /* Make sure to clear the fault before changing the fault mask. */ + barrier_dsync_fence_full(); + + __set_FAULTMASK(0); + + return 0; +} + +int flash_stm32_option_bytes_disable(const struct device *dev) +{ + FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); + + /* + * Access to option register can be disabled by writing wrong key to + * the key register. Option register will remain disabled until reset. + * Writing wrong key causes a bus fault, so we need to set FAULTMASK to + * disable faults, and clear bus fault pending bit before enabling them + * again. + */ + regs->OPTCR |= FLASH_OPTCR_OPTLOCK; + + __set_FAULTMASK(1); + regs->OPTKEYR = 0xffffffff; + /* Make sure that the fault occurs before we clear it. */ + barrier_dsync_fence_full(); + + /* Clear Bus Fault pending bit */ + SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk; + /* Make sure to clear the fault before changing the fault mask. */ + barrier_dsync_fence_full(); + __set_FAULTMASK(0); + + return 0; +} +#endif /* CONFIG_FLASH_STM32_BLOCK_REGISTERS */ + int flash_stm32_option_bytes_lock(const struct device *dev, bool enable) { FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); diff --git a/tests/drivers/flash/stm32/src/main.c b/tests/drivers/flash/stm32/src/main.c index 9356535f8d9..8b47a64b1a9 100644 --- a/tests/drivers/flash/stm32/src/main.c +++ b/tests/drivers/flash/stm32/src/main.c @@ -10,6 +10,7 @@ #include #include #include +#include #define TEST_AREA storage_partition #define TEST_AREA_OFFSET FIXED_PARTITION_OFFSET(TEST_AREA) @@ -200,15 +201,46 @@ static void flash_cr_unlock(void) { FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG; +#ifdef CONFIG_SOC_SERIES_STM32H7X + regs->KEYR1 = FLASH_KEY1; + regs->KEYR1 = FLASH_KEY2; +#ifdef DUAL_BANK + regs->KEYR2 = FLASH_KEY1; + regs->KEYR2 = FLASH_KEY2; +#endif /* DUAL_BANK */ +#else /* CONFIG_SOC_SERIES_STM32H7X */ regs->KEYR = FLASH_KEY1; regs->KEYR = FLASH_KEY2; +#endif /* CONFIG_SOC_SERIES_STM32H7X */ + barrier_dsync_fence_full(); } -static bool flash_cr_locked(void) +static bool flash_cr_is_locked(void) { FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG; +#ifdef CONFIG_SOC_SERIES_STM32H7X + return regs->CR1 & FLASH_CR_LOCK; +#ifdef DUAL_BANK + return (regs->CR1 & FLASH_CR_LOCK) && (regs->CR2 & FLASH_CR_LOCK); +#endif /* DUAL_BANK */ +#else /* CONFIG_SOC_SERIES_STM32H7X */ return regs->CR & FLASH_CR_LOCK; +#endif /* CONFIG_SOC_SERIES_STM32H7X */ +} + +static bool flash_cr_is_unlocked(void) +{ + FLASH_TypeDef *regs = (FLASH_TypeDef *)TEST_AREA_DEVICE_REG; + +#ifdef CONFIG_SOC_SERIES_STM32H7X + return !(regs->CR1 & FLASH_CR_LOCK); +#ifdef DUAL_BANK + return !((regs->CR1 & FLASH_CR_LOCK) || (regs->CR2 & FLASH_CR_LOCK)); +#endif /* DUAL_BANK */ +#else /* CONFIG_SOC_SERIES_STM32H7X */ + return !(regs->CR & FLASH_CR_LOCK); +#endif /* CONFIG_SOC_SERIES_STM32H7X */ } ZTEST(flash_stm32, test_stm32_block_registers) @@ -227,24 +259,27 @@ ZTEST(flash_stm32, test_stm32_block_registers) flash_stm32_option_bytes_lock(flash_dev, false); /* Clear Bus Fault pending bit */ SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk; + barrier_dsync_fence_full(); __set_FAULTMASK(0); zassert_true(flash_opt_locked(), "OPT unlocked after being blocked"); /* Test CR lock. */ - zassert_true(flash_cr_locked(), "CR should be locked by default"); + zassert_true(flash_cr_is_locked(), "CR should be locked by default"); TC_PRINT("Unlocking CR\n"); flash_cr_unlock(); - zassert_false(flash_cr_locked(), "Unable to unlock CR"); + zassert_true(flash_cr_is_unlocked(), "Unable to unlock CR"); TC_PRINT("Blocking CR\n"); flash_ex_op(flash_dev, FLASH_STM32_EX_OP_BLOCK_CONTROL_REG, (uintptr_t)NULL, NULL); - zassert_true(flash_cr_locked(), "Blocking CR didn't lock CR"); + zassert_true(flash_cr_is_locked(), "Blocking CR didn't lock CR"); __set_FAULTMASK(1); TC_PRINT("Try to unlock blocked CR\n"); flash_cr_unlock(); /* Clear Bus Fault pending bit */ SCB->SHCSR &= ~SCB_SHCSR_BUSFAULTPENDED_Msk; + barrier_dsync_fence_full(); __set_FAULTMASK(0); - zassert_true(flash_cr_locked(), "CR unlocked after being blocked"); + /* Make sure previous write is completed. */ + zassert_true(flash_cr_is_locked(), "CR unlocked after being blocked"); } #endif diff --git a/tests/drivers/flash/stm32/testcase.yaml b/tests/drivers/flash/stm32/testcase.yaml index acfc4897882..b7715bb069a 100644 --- a/tests/drivers/flash/stm32/testcase.yaml +++ b/tests/drivers/flash/stm32/testcase.yaml @@ -54,3 +54,12 @@ tests: - CONFIG_FLASH_STM32_WRITE_PROTECT=y filter: dt_compat_enabled("st,stm32h7-flash-controller") and dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions") + drivers.flash.stm32.h7.block_registers: + platform_allow: + - nucleo_h743zi + - google_icetower + extra_configs: + - CONFIG_FLASH_STM32_BLOCK_REGISTERS=y + filter: dt_compat_enabled("st,stm32h7-flash-controller") and + dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions") and + CONFIG_SOC_SERIES_STM32H7X