Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 3 additions & 2 deletions drivers/flash/Kconfig.stm32
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ config SOC_FLASH_STM32
default y
select FLASH_PAGE_LAYOUT
select FLASH_HAS_PAGE_LAYOUT
select FLASH_HAS_EX_OP if SOC_SERIES_STM32F4X
select MPU_ALLOW_FLASH_WRITE if ARM_MPU
help
Enable flash driver for STM32 series
Expand All @@ -24,6 +23,7 @@ if SOC_FLASH_STM32
config FLASH_STM32_WRITE_PROTECT
bool "Extended operation for flash write protection control"
depends on SOC_SERIES_STM32F4X
select FLASH_HAS_EX_OP
default n
help
Enables flash extended operation for enabling/disabling flash write
Expand All @@ -39,7 +39,8 @@ config FLASH_STM32_WRITE_PROTECT_DISABLE_PREVENTION

config FLASH_STM32_READOUT_PROTECTION
bool "Extended operation for flash readout protection control"
depends on SOC_SERIES_STM32F4X
depends on SOC_SERIES_STM32F4X || SOC_SERIES_STM32L4X
select FLASH_HAS_EX_OP
default n
help
Enables flash extended operation for enabling/disabling flash readout
Expand Down
2 changes: 1 addition & 1 deletion drivers/flash/flash_stm32.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ int flash_stm32_option_bytes_lock(const struct device *dev, bool enable)
return 0;
}

#if defined(CONFIG_FLASH_STM32_BLOCK_REGISTERS)
#if defined(CONFIG_FLASH_EX_OP_ENABLED) && defined(CONFIG_FLASH_STM32_BLOCK_REGISTERS)
static int flash_stm32_control_register_disable(const struct device *dev)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
Expand Down
16 changes: 7 additions & 9 deletions drivers/flash/flash_stm32f4x.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,7 @@ int flash_stm32_update_rdp(const struct device *dev, bool enable,
switch (current_level) {
case FLASH_STM32_RDP2:
if (!enable || !permanent) {
__ASSERT(false, "RDP level 2 is permanent and can't be "
"changed!");
LOG_ERR("RDP level 2 is permanent and can't be changed!");
return -ENOTSUP;
}
break;
Expand All @@ -304,9 +303,8 @@ int flash_stm32_update_rdp(const struct device *dev, bool enable,
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
target_level = FLASH_STM32_RDP2;
#else
__ASSERT(false,
"Permanent readout protection (RDP "
"level 0 -> 2) not allowed");
LOG_ERR("Permanent readout protection (RDP "
"level 0 -> 2) not allowed");
return -ENOTSUP;
#endif
}
Expand All @@ -317,17 +315,17 @@ int flash_stm32_update_rdp(const struct device *dev, bool enable,
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
target_level = FLASH_STM32_RDP2;
#else
__ASSERT(false, "Permanent readout protection (RDP "
"level 1 -> 2) not allowed");
LOG_ERR("Permanent readout protection (RDP "
"level 1 -> 2) not allowed");
return -ENOTSUP;
#endif
}
if (!enable) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_DISABLE_ALLOW)
target_level = FLASH_STM32_RDP0;
#else
__ASSERT(false, "Disabling readout protection (RDP "
"level 1 -> 0) not allowed");
LOG_ERR("Disabling readout protection (RDP "
"level 1 -> 0) not allowed");
return -EACCES;
#endif
}
Expand Down
152 changes: 152 additions & 0 deletions drivers/flash/flash_stm32l4x.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ LOG_MODULE_REGISTER(LOG_DOMAIN);
#include <zephyr/device.h>
#include <string.h>
#include <zephyr/drivers/flash.h>
#include <zephyr/sys/barrier.h>
#include <zephyr/init.h>
#include <soc.h>

Expand Down Expand Up @@ -244,6 +245,157 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset,
return rc;
}

static __unused int write_optb(const struct device *dev, uint32_t mask,
uint32_t value)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
int rc;

if (regs->CR & FLASH_CR_OPTLOCK) {
return -EIO;
}

if ((regs->OPTR & mask) == value) {
return 0;
}

rc = flash_stm32_wait_flash_idle(dev);
if (rc < 0) {
return rc;
}

regs->OPTR = (regs->OPTR & ~mask) | value;
regs->CR |= FLASH_CR_OPTSTRT;

/* Make sure previous write is completed. */
barrier_dsync_fence_full();

rc = flash_stm32_wait_flash_idle(dev);
if (rc < 0) {
return rc;
}

return 0;
}

#if defined(CONFIG_FLASH_STM32_WRITE_PROTECT)

/*
* Remark for future development implementing Write Protection for the L4 parts:
*
* STM32L4 allows for 2 write protected memory areas, c.f. FLASH_WEP1AR, FLASH_WRP1BR
* which are defined by their start and end pages.
*
* Other STM32 parts (i.e. F4 series) uses bitmask to select sectors.
*
* To implement Write Protection for L4 one should thus add a new EX_OP like
* FLASH_STM32_EX_OP_SECTOR_WP_RANGED in stm32_flash_api_extensions.h
*/

#endif /* CONFIG_FLASH_STM32_WRITE_PROTECT */

#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION)
int flash_stm32_update_rdp(const struct device *dev, bool enable,
bool permanent)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
uint8_t current_level, target_level;

current_level =
(regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos;
target_level = current_level;

/*
* 0xAA = RDP level 0 (no protection)
* 0xCC = RDP level 2 (permanent protection)
* others = RDP level 1 (protection active)
*/
switch (current_level) {
case FLASH_STM32_RDP2:
if (!enable || !permanent) {
LOG_ERR("RDP level 2 is permanent and can't be changed!");
return -ENOTSUP;
}
break;
case FLASH_STM32_RDP0:
if (enable) {
target_level = FLASH_STM32_RDP1;
if (permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
target_level = FLASH_STM32_RDP2;
#else
LOG_ERR("Permanent readout protection (RDP "
"level 0 -> 2) not allowed");
return -ENOTSUP;
#endif
}
}
break;
default: /* FLASH_STM32_RDP1 */
if (enable && permanent) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW)
target_level = FLASH_STM32_RDP2;
#else
LOG_ERR("Permanent readout protection (RDP "
"level 1 -> 2) not allowed");
return -ENOTSUP;
#endif
}
if (!enable) {
#if defined(CONFIG_FLASH_STM32_READOUT_PROTECTION_DISABLE_ALLOW)
target_level = FLASH_STM32_RDP0;
#else
LOG_ERR("Disabling readout protection (RDP "
"level 1 -> 0) not allowed");
return -EACCES;
#endif
}
}

/* Update RDP level if needed */
if (current_level != target_level) {
LOG_INF("RDP changed from 0x%02x to 0x%02x", current_level,
target_level);

write_optb(dev, FLASH_OPTR_RDP_Msk,
(uint32_t)target_level << FLASH_OPTR_RDP_Pos);
}
return 0;
}

int flash_stm32_get_rdp(const struct device *dev, bool *enabled,
bool *permanent)
{
FLASH_TypeDef *regs = FLASH_STM32_REGS(dev);
uint8_t current_level;

current_level =
(regs->OPTR & FLASH_OPTR_RDP_Msk) >> FLASH_OPTR_RDP_Pos;

/*
* 0xAA = RDP level 0 (no protection)
* 0xCC = RDP level 2 (permanent protection)
* others = RDP level 1 (protection active)
*/
switch (current_level) {
case FLASH_STM32_RDP2:
*enabled = true;
*permanent = true;
break;
case FLASH_STM32_RDP0:
*enabled = false;
*permanent = false;
break;
default: /* FLASH_STM32_RDP1 */
*enabled = true;
*permanent = false;
}
return 0;
}
#endif /* CONFIG_FLASH_STM32_READOUT_PROTECTION */



void flash_stm32_page_layout(const struct device *dev,
const struct flash_pages_layout **layout,
size_t *layout_size)
Expand Down