From 7042b56917fe6b3a6388d969716ce373e47f1f74 Mon Sep 17 00:00:00 2001 From: Tahsin Mutlugun Date: Thu, 26 Dec 2024 17:18:05 +0300 Subject: [PATCH 1/6] soc: adi: max32: Use fixed MPU regions Default MPU configuration marks whole flash area as cacheable. When reading from an erased section of flash, cache controller may fill cache lines with ECC corrected data. To prevent this, disable caching on storage section so that ECC workaround can be applied during reads and correct data is returned. Signed-off-by: Tahsin Mutlugun --- soc/adi/max32/CMakeLists.txt | 2 ++ soc/adi/max32/Kconfig | 1 + soc/adi/max32/mpu_regions.c | 49 ++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 soc/adi/max32/mpu_regions.c diff --git a/soc/adi/max32/CMakeLists.txt b/soc/adi/max32/CMakeLists.txt index 0d22dfc71b39a..9042d934feeaa 100644 --- a/soc/adi/max32/CMakeLists.txt +++ b/soc/adi/max32/CMakeLists.txt @@ -5,6 +5,8 @@ zephyr_include_directories(${ZEPHYR_BASE}/drivers) zephyr_include_directories(common) zephyr_sources(soc.c) +zephyr_library_sources_ifdef(CONFIG_CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS mpu_regions.c) + zephyr_library_sources_ifdef(CONFIG_PM power.c) zephyr_linker_sources_ifdef(CONFIG_SOC_FLASH_MAX32 SECTIONS flash.ld) if(CONFIG_SOC_MAX78000 OR CONFIG_SOC_MAX78002) diff --git a/soc/adi/max32/Kconfig b/soc/adi/max32/Kconfig index a1627e311312f..de64ed40b8738 100644 --- a/soc/adi/max32/Kconfig +++ b/soc/adi/max32/Kconfig @@ -13,6 +13,7 @@ config SOC_FAMILY_MAX32_M33 select ARM select CPU_CORTEX_M_HAS_SYSTICK select CPU_HAS_ARM_MPU + select CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS select CPU_HAS_FPU select CLOCK_CONTROL select CPU_CORTEX_M33 diff --git a/soc/adi/max32/mpu_regions.c b/soc/adi/max32/mpu_regions.c new file mode 100644 index 0000000000000..fd5c56a47e3b4 --- /dev/null +++ b/soc/adi/max32/mpu_regions.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/* + * Define noncacheable flash region attributes using noncacheable SRAM memory + * attribute index. + */ +#define MAX32_FLASH_NON_CACHEABLE(base, size) \ + { \ + .rbar = RO_Msk | NON_SHAREABLE_Msk, \ + .mair_idx = MPU_MAIR_INDEX_SRAM_NOCACHE, \ + .r_limit = REGION_LIMIT_ADDR(base, size), \ + } + +#define MAX32_MPU_REGION(name, base, attr, size) MPU_REGION_ENTRY(name, (base), attr((base), size)) + +/* + * The MPU regions are defined in the following way: + * - Cacheable flash region + * - Non-cacheable flash region, i.e., storage area at the end of the flash + * - SRAM region + * If the storage partition is not defined, the flash region spans the whole + * flash. + */ +static const struct arm_mpu_region mpu_regions[] = { +#if FIXED_PARTITION_EXISTS(storage_partition) +#define STORAGE_ADDR (CONFIG_FLASH_BASE_ADDRESS + FIXED_PARTITION_OFFSET(storage_partition)) +#define STORAGE_SIZE (FIXED_PARTITION_SIZE(storage_partition) >> 10) + MAX32_MPU_REGION("FLASH", CONFIG_FLASH_BASE_ADDRESS, REGION_FLASH_ATTR, + KB(CONFIG_FLASH_SIZE - STORAGE_SIZE)), + MAX32_MPU_REGION("STORAGE", STORAGE_ADDR, MAX32_FLASH_NON_CACHEABLE, KB(STORAGE_SIZE)), +#else + MAX32_MPU_REGION("FLASH", CONFIG_FLASH_BASE_ADDRESS, REGION_FLASH_ATTR, + KB(CONFIG_FLASH_SIZE)), +#endif + MAX32_MPU_REGION("SRAM", CONFIG_SRAM_BASE_ADDRESS, REGION_RAM_ATTR, KB(CONFIG_SRAM_SIZE)), +}; + +const struct arm_mpu_config mpu_config = { + .num_regions = ARRAY_SIZE(mpu_regions), + .mpu_regions = mpu_regions, +}; From f8620692ba2e94afc6ffc2cee71e08036ae54ad3 Mon Sep 17 00:00:00 2001 From: Tahsin Mutlugun Date: Mon, 7 Apr 2025 15:10:13 +0300 Subject: [PATCH 2/6] soc: adi: max32: Move .flashprog into RAMFUNC section Move functions in .flashprog section into RAMFUNC so that they can be executed from SRAM. Signed-off-by: Tahsin Mutlugun --- soc/adi/max32/CMakeLists.txt | 2 +- soc/adi/max32/flash.ld | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/soc/adi/max32/CMakeLists.txt b/soc/adi/max32/CMakeLists.txt index 9042d934feeaa..74b3b29698bf9 100644 --- a/soc/adi/max32/CMakeLists.txt +++ b/soc/adi/max32/CMakeLists.txt @@ -8,7 +8,7 @@ zephyr_sources(soc.c) zephyr_library_sources_ifdef(CONFIG_CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS mpu_regions.c) zephyr_library_sources_ifdef(CONFIG_PM power.c) -zephyr_linker_sources_ifdef(CONFIG_SOC_FLASH_MAX32 SECTIONS flash.ld) +zephyr_linker_sources_ifdef(CONFIG_SOC_FLASH_MAX32 RAMFUNC_SECTION flash.ld) if(CONFIG_SOC_MAX78000 OR CONFIG_SOC_MAX78002) zephyr_linker_sources(SECTIONS max7800x.ld) endif() diff --git a/soc/adi/max32/flash.ld b/soc/adi/max32/flash.ld index 2014e209ea740..3ec1ab99dfb78 100644 --- a/soc/adi/max32/flash.ld +++ b/soc/adi/max32/flash.ld @@ -1,10 +1,7 @@ /* - * Copyright (c) 2023 Analog Devices, Inc. + * Copyright (c) 2023-2025 Analog Devices, Inc. * * SPDX-License-Identifier: Apache-2.0 */ -SECTION_DATA_PROLOGUE(.flashprog,, SUBALIGN(4)) -{ - KEEP(*(.flashprog*)) /* Flash program */ -} +KEEP(*(.flashprog*)) /* Flash program */ From ecc9feeaded08ee1912afee4ba637d6631f702ca Mon Sep 17 00:00:00 2001 From: Tahsin Mutlugun Date: Fri, 20 Dec 2024 14:35:03 +0300 Subject: [PATCH 3/6] drivers: flash: max32: Disable interrupts before accessing flash Disable interrupts during flash operations to prevent unintended jumps. Interrupts are now disabled before read, erase, and write operations to avoid accidental jumps to other flash sections while working on a specific section. Signed-off-by: Tahsin Mutlugun --- drivers/flash/flash_max32.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/flash/flash_max32.c b/drivers/flash/flash_max32.c index 7dc462698b4a8..fe145479aced3 100644 --- a/drivers/flash/flash_max32.c +++ b/drivers/flash/flash_max32.c @@ -52,9 +52,16 @@ static inline void max32_sem_give(const struct device *dev) static int api_read(const struct device *dev, off_t address, void *buffer, size_t length) { const struct max32_flash_dev_config *const cfg = dev->config; + unsigned int key = 0; address += cfg->flash_base; + + key = irq_lock(); + MXC_FLC_Read(address, buffer, length); + + irq_unlock(key); + return 0; } @@ -62,12 +69,18 @@ static int api_write(const struct device *dev, off_t address, const void *buffer { const struct max32_flash_dev_config *const cfg = dev->config; int ret = 0; + unsigned int key = 0; max32_sem_take(dev); address += cfg->flash_base; + + key = irq_lock(); + ret = MXC_FLC_Write(address, length, (uint32_t *)buffer); + irq_unlock(key); + max32_sem_give(dev); return ret != 0 ? -EIO : 0; @@ -79,9 +92,11 @@ static int api_erase(const struct device *dev, off_t start, size_t len) uint32_t page_size = cfg->flash_erase_blk_sz; uint32_t addr = (start + cfg->flash_base); int ret = 0; + unsigned int key = 0; max32_sem_take(dev); + key = irq_lock(); while (len) { ret = MXC_FLC_PageErase(addr); if (ret) { @@ -95,6 +110,7 @@ static int api_erase(const struct device *dev, off_t start, size_t len) len = 0; } } + irq_unlock(key); max32_sem_give(dev); From ba04a059a87330e7af91da573c9873b90f805577 Mon Sep 17 00:00:00 2001 From: Furkan Akkiz Date: Sat, 18 Jan 2025 09:50:22 +0300 Subject: [PATCH 4/6] drivers: flash: Add wrap version of flash write function To fix MAX32690 flash problems, I created a wrap version of MXC_FLC_Write(...) function which disables ICC before calling write function and enables ICC after this function. Signed-off-by: Furkan Akkiz --- drivers/flash/flash_max32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/flash/flash_max32.c b/drivers/flash/flash_max32.c index fe145479aced3..522775f3a6539 100644 --- a/drivers/flash/flash_max32.c +++ b/drivers/flash/flash_max32.c @@ -11,7 +11,7 @@ #include #include -#include "flc.h" +#include "wrap_max32_flc.h" struct max32_flash_dev_config { uint32_t flash_base; @@ -77,7 +77,7 @@ static int api_write(const struct device *dev, off_t address, const void *buffer key = irq_lock(); - ret = MXC_FLC_Write(address, length, (uint32_t *)buffer); + ret = Wrap_MXC_FLC_Write(address, length, (uint32_t *)buffer); irq_unlock(key); From a00ca8d9e4338d999b68b3067a075a9451091aef Mon Sep 17 00:00:00 2001 From: Tahsin Mutlugun Date: Mon, 21 Jul 2025 12:55:47 +0300 Subject: [PATCH 5/6] manifest: Update hal_adi to get ECC-backed read function Update hal_adi to include the new flash read function that checks for false-positive ECC failures and applies a workaround if needed. Signed-off-by: Tahsin Mutlugun --- west.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/west.yml b/west.yml index 97bc3f50dbf9f..5aa45652f17b8 100644 --- a/west.yml +++ b/west.yml @@ -144,7 +144,7 @@ manifest: groups: - fs - name: hal_adi - revision: 16829b77264678f31a2d077a870af7bdca2d39bd + revision: d2886b8b8e3f71058a221f6351a8200fba80f229 path: modules/hal/adi groups: - hal From 4282649b8c4a9f836c2c46f8e316c1f47184b1df Mon Sep 17 00:00:00 2001 From: Tahsin Mutlugun Date: Mon, 7 Apr 2025 15:41:19 +0300 Subject: [PATCH 6/6] drivers: flash: max32: Wrap flash read to utilize ECC workaround Use wrapper function for read operations to allow using the new HAL function that handles ECC checks and erased page detection. Signed-off-by: Tahsin Mutlugun --- drivers/flash/flash_max32.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/flash/flash_max32.c b/drivers/flash/flash_max32.c index 522775f3a6539..e1204660966ff 100644 --- a/drivers/flash/flash_max32.c +++ b/drivers/flash/flash_max32.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023-2024 Analog Devices, Inc. + * Copyright (c) 2023-2025 Analog Devices, Inc. * * SPDX-License-Identifier: Apache-2.0 */ @@ -52,17 +52,18 @@ static inline void max32_sem_give(const struct device *dev) static int api_read(const struct device *dev, off_t address, void *buffer, size_t length) { const struct max32_flash_dev_config *const cfg = dev->config; + int ret = 0; unsigned int key = 0; address += cfg->flash_base; key = irq_lock(); - MXC_FLC_Read(address, buffer, length); + ret = Wrap_MXC_FLC_Read(address, buffer, length); irq_unlock(key); - return 0; + return ret != 0 ? -EIO : 0; } static int api_write(const struct device *dev, off_t address, const void *buffer, size_t length)