diff --git a/boards/arm/b_u585i_iot02a/b_u585i_iot02a-common.dtsi b/boards/arm/b_u585i_iot02a/b_u585i_iot02a-common.dtsi index f2dd82f9ad12..1aa1d94e7555 100644 --- a/boards/arm/b_u585i_iot02a/b_u585i_iot02a-common.dtsi +++ b/boards/arm/b_u585i_iot02a/b_u585i_iot02a-common.dtsi @@ -131,11 +131,10 @@ stm32_lp_tick_source: &lptim1 { status = "okay"; - mx25lm51245: ospi-nor-flash@0 { + mx25lm51245: ospi-nor-flash@70000000 { compatible = "st,stm32-ospi-nor"; - reg = <0>; + reg = <0x70000000 DT_SIZE_M(64)>; /* 512 Mbits */ ospi-max-frequency = ; - size = ; /* 64 MBytes */ spi-bus-width = ; data-rate = ; four-byte-opcodes; @@ -146,8 +145,10 @@ stm32_lp_tick_source: &lptim1 { #address-cells = <1>; #size-cells = <1>; - partition@0 { - reg = <0x00000000 DT_SIZE_M(64)>; + /* put image at the offset of slot1 */ + slot1_partition:partition@100000 { + label = "image-1"; + reg = <0x00100000 DT_SIZE_K(416)>; }; }; }; diff --git a/boards/arm/b_u585i_iot02a/b_u585i_iot02a.dts b/boards/arm/b_u585i_iot02a/b_u585i_iot02a.dts index f8a826b1b6ed..42a9f89b5ce9 100644 --- a/boards/arm/b_u585i_iot02a/b_u585i_iot02a.dts +++ b/boards/arm/b_u585i_iot02a/b_u585i_iot02a.dts @@ -16,7 +16,6 @@ zephyr,shell-uart = &usart1; zephyr,sram = &sram0; zephyr,flash = &flash0; - zephyr,code-partition = &slot0_partition; }; aliases { @@ -45,10 +44,7 @@ label = "image-0"; reg = <0x00010000 DT_SIZE_K(416)>; }; - slot1_partition: partition@78000 { - label = "image-1"; - reg = <0x00078000 DT_SIZE_K(416)>; - }; + scratch_partition: partition@e0000 { label = "image-scratch"; reg = <0x000e0000 DT_SIZE_K(64)>; diff --git a/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts b/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts index 514047c8a55b..3e485892fb9f 100644 --- a/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts +++ b/boards/arm/stm32h747i_disco/stm32h747i_disco_m7.dts @@ -111,6 +111,16 @@ #address-cells = <1>; #size-cells = <1>; + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(64)>; + }; + + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 DT_SIZE_K(416)>; + }; + /* Set 2KB of storage at the end of first 1MB flash */ storage_partition: partition@ff800 { label = "storage"; @@ -232,11 +242,10 @@ zephyr_udc0: &usbotg_hs { pinctrl-names = "default"; status = "okay"; - mt25ql512ab1: qspi-nor-flash-1@0 { + mt25ql512ab1: qspi-nor-flash-1@90000000 { compatible = "st,stm32-qspi-nor"; - reg = <0>; + reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ qspi-max-frequency = <72000000>; - size = ; /* 64 MBytes */ spi-bus-width = <4>; status = "okay"; @@ -245,17 +254,18 @@ zephyr_udc0: &usbotg_hs { #address-cells = <1>; #size-cells = <1>; - partition@0 { - reg = <0x0 DT_SIZE_M(64)>; - }; + /* put image at offset 0 in slot1 */ + slot1_partition:partition@0 { + label = "image-1"; + reg = <0x00000000 DT_SIZE_K(416)>; + }; }; }; - mt25ql512ab2: qspi-nor-flash-2@0 { + mt25ql512ab2: qspi-nor-flash-2@90000000 { compatible = "st,stm32-qspi-nor"; - reg = <0>; + reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ qspi-max-frequency = <72000000>; - size = ; /* 64 MBytes */ status = "okay"; }; }; diff --git a/boards/arm/stm32h750b_dk/stm32h750b_dk.dts b/boards/arm/stm32h750b_dk/stm32h750b_dk.dts index efe4b7b27434..da80a4a45944 100644 --- a/boards/arm/stm32h750b_dk/stm32h750b_dk.dts +++ b/boards/arm/stm32h750b_dk/stm32h750b_dk.dts @@ -18,7 +18,6 @@ zephyr,shell-uart = &usart3; zephyr,sram = &sram0; zephyr,flash = &flash0; - zephyr,flash-controller = &mt25ql512ab1; }; sdram2: sdram@d0000000 { @@ -85,6 +84,30 @@ d3ppre = <2>; }; +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(64)>; + }; + + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 DT_SIZE_K(416)>; + }; + + /* Set 2KB of storage at the end of first 1MB flash */ + storage_partition: partition@ff800 { + label = "storage"; + reg = <0x000ff800 DT_SIZE_K(2)>; + }; + }; +}; + &usart3 { pinctrl-0 = <&usart3_tx_pb10 &usart3_rx_pb11>; pinctrl-names = "default"; @@ -99,14 +122,12 @@ &quadspi_bk1_io2_pf7 &quadspi_bk1_io3_pf6 &quadspi_bk2_io0_ph2 &quadspi_bk2_io1_ph3 &quadspi_bk2_io2_pg9 &quadspi_bk2_io3_pg14>; - flash-id = <1>; status = "okay"; - mt25ql512ab1: qspi-nor-flash-1@0 { + mt25ql512ab1: qspi-nor-flash-1@90000000 { compatible = "st,stm32-qspi-nor"; - reg = <0>; + reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ qspi-max-frequency = <72000000>; - size = ; /* 64 MBytes */ spi-bus-width = <4>; status = "okay"; @@ -115,17 +136,18 @@ #address-cells = <1>; #size-cells = <1>; - partition@0 { - reg = <0x0 DT_SIZE_M(64)>; - }; + /* put image at offset 0 in slot1 */ + slot1_partition:partition@0 { + label = "image-1"; + reg = <0x00000000 DT_SIZE_K(416)>; + }; }; }; - mt25ql512ab2: qspi-nor-flash-2@1 { + mt25ql512ab2: qspi-nor-flash-2@90000000 { compatible = "st,stm32-qspi-nor"; - reg = <1>; + reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ qspi-max-frequency = <72000000>; - size = ; /* 64 MBytes */ status = "okay"; }; }; diff --git a/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.dts b/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.dts index b8b781b3fa10..36861f3d5633 100644 --- a/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.dts +++ b/boards/arm/stm32h7b3i_dk/stm32h7b3i_dk.dts @@ -242,6 +242,35 @@ def-back-color-blue = <0xFF>; }; +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(64)>; + read-only; + }; + + /* + * The flash starting at offset 0x10000 and ending at + * offset 0x1ffff is reserved for use by the application. + */ + + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 DT_SIZE_K(800)>; + }; + + scratch_partition: partition@f8000 { + label = "image-scratch"; + reg = <0x000F8000 DT_SIZE_K(16)>; + }; + }; +}; + &octospi1 { pinctrl-0 = <&octospim_p1_clk_pb2 &octospim_p1_ncs_pg6 &octospim_p1_io0_pd11 &octospim_p1_io1_pf9 @@ -253,11 +282,10 @@ status = "okay"; - mx25lm51245: ospi-nor-flash@0 { + mx25lm51245: ospi-nor-flash@90000000 { compatible = "st,stm32-ospi-nor"; - reg = <0>; + reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Megabits */ ospi-max-frequency = ; - size = ; /* 512 Megabits */ spi-bus-width = ; data-rate = ; status = "okay"; @@ -267,9 +295,10 @@ #address-cells = <1>; #size-cells = <1>; - partition@0 { - label = "nor"; - reg = <0x00000000 DT_SIZE_M(4)>; + /* put image at offset 0 in slot1 */ + slot1_partition:partition@0 { + label = "image-1"; + reg = <0x00000000 DT_SIZE_K(800)>; }; }; }; diff --git a/boards/arm/stm32h7b3i_dk/support/openocd.cfg b/boards/arm/stm32h7b3i_dk/support/openocd.cfg index a078b4b8c978..114bd25b797d 100644 --- a/boards/arm/stm32h7b3i_dk/support/openocd.cfg +++ b/boards/arm/stm32h7b3i_dk/support/openocd.cfg @@ -20,3 +20,10 @@ set CORE_RESET 0 source [find target/stm32h7x.cfg] +# Due to the use of connect_assert_srst, running gdb requires +# to reset halt just after openocd init. +rename init old_init +proc init {} { + old_init + reset halt +} diff --git a/boards/arm/stm32l496g_disco/stm32l496g_disco.dts b/boards/arm/stm32l496g_disco/stm32l496g_disco.dts index 977e70142efe..a03ed8b0a2a1 100644 --- a/boards/arm/stm32l496g_disco/stm32l496g_disco.dts +++ b/boards/arm/stm32l496g_disco/stm32l496g_disco.dts @@ -103,6 +103,28 @@ apb2-prescaler = <1>; }; +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(64)>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 DT_SIZE_K(416)>; + }; + /* Set 2KB of storage at the end of first 1MB flash */ + storage_partition: partition@ff800 { + label = "storage"; + reg = <0x000ff800 DT_SIZE_K(2)>; + }; + }; +}; + &usart1 { pinctrl-0 = <&usart1_tx_pb6 &usart1_rx_pg10>; pinctrl-names = "default"; @@ -201,13 +223,24 @@ zephyr_udc0: &usbotg_fs { flash-id = <1>; status = "okay"; - mx25r6435: qspi-nor-flash@0 { + mx25r6435: qspi-nor-flash@90000000 { compatible = "st,stm32-qspi-nor"; - reg = <0>; + reg = <0x90000000 DT_SIZE_M(8)>; qspi-max-frequency = <8000000>; - size = ; /* 8 MBytes */ status = "okay"; spi-bus-width = <4>; writeoc = "PP_1_4_4"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* put image at offset 0 in slot1 */ + slot1_partition:partition@0 { + label = "image-1"; + reg = <0x00000000 DT_SIZE_K(416)>; + }; + }; }; }; diff --git a/drivers/clock_control/clock_stm32_ll_h7.c b/drivers/clock_control/clock_stm32_ll_h7.c index 9d76004c92fd..04865c8c6e79 100644 --- a/drivers/clock_control/clock_stm32_ll_h7.c +++ b/drivers/clock_control/clock_stm32_ll_h7.c @@ -666,6 +666,12 @@ __unused static int set_up_plls(void) { #if defined(STM32_PLL_ENABLED) || defined(STM32_PLL2_ENABLED) || defined(STM32_PLL3_ENABLED) + + /* Skip if PLL1 is already configured */ + if (LL_RCC_PLL1_IsReady()) { + return 0; + } + int r; uint32_t vco_input_range; uint32_t vco_output_range; diff --git a/drivers/flash/Kconfig.stm32 b/drivers/flash/Kconfig.stm32 index a452ab8b98d0..d431b76cbe19 100644 --- a/drivers/flash/Kconfig.stm32 +++ b/drivers/flash/Kconfig.stm32 @@ -72,4 +72,11 @@ config FLASH_STM32_BLOCK_REGISTERS registers improves system security, because flash content (or protection settings) can't be changed even when exploit was found. +config STM32_MEMMAP + bool "NOR Flash in MemoryMapped for XiP" + depends on XIP + help + This option enables the XIP mode for the external NOR flash + mounted on STM32 boards. + endif # SOC_FLASH_STM32 diff --git a/drivers/flash/flash_stm32.c b/drivers/flash/flash_stm32.c index 36e3103c56d3..2dcf63f32089 100644 --- a/drivers/flash/flash_stm32.c +++ b/drivers/flash/flash_stm32.c @@ -157,7 +157,7 @@ static void flash_stm32_flush_caches(const struct device *dev, regs->ACR |= FLASH_ACR_DCEN; } #elif defined(CONFIG_SOC_SERIES_STM32F7X) - SCB_InvalidateDCache_by_Addr((uint32_t *)(CONFIG_FLASH_BASE_ADDRESS + SCB_InvalidateDCache_by_Addr((uint32_t *)(FLASH_STM32_BASE_ADDRESS + offset), len); #endif } @@ -178,7 +178,7 @@ static int flash_stm32_read(const struct device *dev, off_t offset, LOG_DBG("Read offset: %ld, len: %zu", (long int) offset, len); - memcpy(data, (uint8_t *) CONFIG_FLASH_BASE_ADDRESS + offset, len); + memcpy(data, (uint8_t *) FLASH_STM32_BASE_ADDRESS + offset, len); return 0; } @@ -562,7 +562,8 @@ static int stm32_flash_init(const struct device *dev) flash_stm32_sem_init(dev); - LOG_DBG("Flash initialized. BS: %zu", + LOG_DBG("Flash @0x%x initialized. BS: %zu", + FLASH_STM32_BASE_ADDRESS, flash_stm32_parameters.write_block_size); /* Check Flash configuration */ diff --git a/drivers/flash/flash_stm32.h b/drivers/flash/flash_stm32.h index e0fba89a5503..3583a1379c6c 100644 --- a/drivers/flash/flash_stm32.h +++ b/drivers/flash/flash_stm32.h @@ -17,6 +17,9 @@ #include #endif +/* Get the base address of the flash from the DTS node */ +#define FLASH_STM32_BASE_ADDRESS DT_REG_ADDR(DT_INST(0, st_stm32_nv_flash)) + struct flash_stm32_priv { FLASH_TypeDef *regs; #if DT_NODE_HAS_PROP(DT_INST(0, st_stm32_flash_controller), clocks) || \ diff --git a/drivers/flash/flash_stm32_ospi.c b/drivers/flash/flash_stm32_ospi.c index 9d2ed2412dc5..83d4275fd9a0 100644 --- a/drivers/flash/flash_stm32_ospi.c +++ b/drivers/flash/flash_stm32_ospi.c @@ -36,6 +36,9 @@ LOG_MODULE_REGISTER(flash_stm32_ospi, CONFIG_FLASH_LOG_LEVEL); (_CONCAT(HAL_OSPIM_, DT_STRING_TOKEN(STM32_OSPI_NODE, prop))), \ ((default_value))) +/* Get the base address of the flash from the DTS node */ +#define STM32_OSPI_BASE_ADDRESS DT_REG_ADDR(DT_INST(0, st_stm32_ospi_nor)) + #define STM32_OSPI_RESET_GPIO DT_INST_NODE_HAS_PROP(0, reset_gpios) #define STM32_OSPI_DLYB_BYPASSED DT_PROP(STM32_OSPI_NODE, dlyb_bypass) @@ -955,11 +958,150 @@ static int stm32_ospi_mem_reset(const struct device *dev) return 0; } +#ifdef CONFIG_STM32_MEMMAP +/* Function to configure the octoflash in MemoryMapped mode */ +static int stm32_ospi_set_memorymap(const struct device *dev) +{ + HAL_StatusTypeDef ret; + const struct flash_stm32_ospi_config *dev_cfg = dev->config; + struct flash_stm32_ospi_data *dev_data = dev->data; + OSPI_RegularCmdTypeDef s_command; + OSPI_MemoryMappedTypeDef s_MemMappedCfg = {0}; + + /* Configure octoflash in MemoryMapped mode */ + if ((dev_cfg->data_mode == OSPI_SPI_MODE) && + (stm32_ospi_hal_address_size(dev) == HAL_OSPI_ADDRESS_24_BITS)) { + /* OPI mode and 3-bytes address size not supported by memory */ + LOG_ERR("OSPI_SPI_MODE in 3Bytes addressing is not supported"); + return -EIO; + } + + /* Initialize the read command */ + s_command.OperationType = HAL_OSPI_OPTYPE_READ_CFG; + s_command.FlashId = HAL_OSPI_FLASH_ID_1; + s_command.InstructionMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? ((dev_cfg->data_mode == OSPI_SPI_MODE) + ? HAL_OSPI_INSTRUCTION_1_LINE + : HAL_OSPI_INSTRUCTION_8_LINES) + : HAL_OSPI_INSTRUCTION_8_LINES; + s_command.InstructionDtrMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? HAL_OSPI_INSTRUCTION_DTR_DISABLE + : HAL_OSPI_INSTRUCTION_DTR_ENABLE; + s_command.InstructionSize = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? ((dev_cfg->data_mode == OSPI_SPI_MODE) + ? HAL_OSPI_INSTRUCTION_8_BITS + : HAL_OSPI_INSTRUCTION_16_BITS) + : HAL_OSPI_INSTRUCTION_16_BITS; + s_command.Instruction = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? ((dev_cfg->data_mode == OSPI_SPI_MODE) + ? ((stm32_ospi_hal_address_size(dev) == + HAL_OSPI_ADDRESS_24_BITS) + ? SPI_NOR_CMD_READ_FAST + : SPI_NOR_CMD_READ_FAST_4B) + : dev_data->read_opcode) + : SPI_NOR_OCMD_DTR_RD; + s_command.AddressMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? ((dev_cfg->data_mode == OSPI_SPI_MODE) + ? HAL_OSPI_ADDRESS_1_LINE + : HAL_OSPI_ADDRESS_8_LINES) + : HAL_OSPI_ADDRESS_8_LINES; + s_command.AddressDtrMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? HAL_OSPI_ADDRESS_DTR_DISABLE + : HAL_OSPI_ADDRESS_DTR_ENABLE; + s_command.AddressSize = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? stm32_ospi_hal_address_size(dev) + : HAL_OSPI_ADDRESS_32_BITS; + s_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? ((dev_cfg->data_mode == OSPI_SPI_MODE) + ? HAL_OSPI_DATA_1_LINE + : HAL_OSPI_DATA_8_LINES) + : HAL_OSPI_DATA_8_LINES; + s_command.DataDtrMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? HAL_OSPI_DATA_DTR_DISABLE + : HAL_OSPI_DATA_DTR_ENABLE; + s_command.DummyCycles = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? ((dev_cfg->data_mode == OSPI_SPI_MODE) + ? SPI_NOR_DUMMY_RD + : SPI_NOR_DUMMY_RD_OCTAL) + : SPI_NOR_DUMMY_RD_OCTAL_DTR; + s_command.DQSMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? HAL_OSPI_DQS_DISABLE + : HAL_OSPI_DQS_ENABLE; + + s_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; + + ret = HAL_OSPI_Command(&dev_data->hospi, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE); + if (ret != HAL_OK) { + LOG_ERR("%d: Failed to set memory map", ret); + return -EIO; + } + + /* Initialize the program command */ + s_command.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG; + if (dev_cfg->data_rate == OSPI_STR_TRANSFER) { + s_command.Instruction = (dev_cfg->data_mode == OSPI_SPI_MODE) + ? ((stm32_ospi_hal_address_size(dev) == + HAL_OSPI_ADDRESS_24_BITS) + ? SPI_NOR_CMD_PP + : SPI_NOR_CMD_PP_4B) + : SPI_NOR_OCMD_PAGE_PRG; + } else { + s_command.Instruction = SPI_NOR_OCMD_PAGE_PRG; + } + s_command.DQSMode = HAL_OSPI_DQS_DISABLE; + s_command.DummyCycles = 0U; + + ret = HAL_OSPI_Command(&dev_data->hospi, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE); + if (ret != HAL_OK) { + LOG_ERR("%d: Failed to set memory mapped", ret); + return -EIO; + } + + /* Enable the memory-mapping */ + s_MemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE; + + ret = HAL_OSPI_MemoryMapped(&dev_data->hospi, &s_MemMappedCfg); + if (ret != HAL_OK) { + LOG_ERR("%d: Failed to enable memory mapped", ret); + return -EIO; + } + + LOG_DBG("MemoryMap mode enabled"); + return 0; +} + +/* Function to return true if the octoflash is in MemoryMapped else false */ +static bool stm32_ospi_is_memorymap(const struct device *dev) +{ + struct flash_stm32_ospi_data *dev_data = dev->data; + + return ((READ_BIT(dev_data->hospi.Instance->CR, + OCTOSPI_CR_FMODE) == OCTOSPI_CR_FMODE) ? + true : false); +} + +/* Abort the Memorymapped Mode so that erasing is possible */ +static int stm32_ospi_abort_memmap(const struct device *dev) +{ + struct flash_stm32_ospi_data *dev_data = dev->data; + + if (HAL_OSPI_Abort(&dev_data->hospi) != HAL_OK) { + LOG_ERR("MemoryMap abort failed"); + return -EIO; + } + LOG_DBG("MemoryMap mode disabled"); + + return 0; +} +#endif /* CONFIG_STM32_MEMMAP */ + /* * Function to erase the flash : chip or sector with possible OSPI/SPI and STR/DTR * to erase the complete chip (using dedicated command) : * set size >= flash size * set addr = 0 + * NOTE: cannot erase in MemoryMapped mode */ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, size_t size) @@ -989,6 +1131,17 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, return -ENOTSUP; } +#ifdef CONFIG_STM32_MEMMAP + if (stm32_ospi_is_memorymap(dev)) { + /* If the Flash is in MemoryMapped mode, abort it and continue */ + LOG_INF("MemoryMap : disable before erase"); + if (stm32_ospi_abort_memmap(dev) != 0) { + LOG_ERR("MemoryMap not aborted correctly"); + return -EIO; + } + } +#endif /* CONFIG_STM32_MEMMAP */ + OSPI_RegularCmdTypeDef cmd_erase = { .OperationType = HAL_OSPI_OPTYPE_COMMON_CFG, .FlashId = HAL_OSPI_FLASH_ID_1, @@ -1003,9 +1156,9 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, if (stm32_ospi_mem_ready(&dev_data->hospi, dev_cfg->data_mode, dev_cfg->data_rate) != 0) { - ospi_unlock_thread(dev); LOG_ERR("Erase failed : flash busy"); - return -EBUSY; + ret = -EBUSY; + goto end_erase; } cmd_erase.InstructionMode = (dev_cfg->data_mode == OSPI_OPI_MODE) @@ -1115,6 +1268,7 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, } +end_erase: ospi_unlock_thread(dev); return ret; @@ -1139,6 +1293,25 @@ static int flash_stm32_ospi_read(const struct device *dev, off_t addr, return 0; } +#ifdef CONFIG_STM32_MEMMAP + /* If not MemMapped then configure it */ + if (!stm32_ospi_is_memorymap(dev)) { + if (stm32_ospi_set_memorymap(dev) != 0) { + LOG_ERR("READ failed: cannot enable MemoryMap"); + return -EIO; + } + } + LOG_INF("MemoryMap : enable before read"); + if (stm32_ospi_is_memorymap(dev)) { + LOG_DBG("MemoryMapped Read offset: 0x%lx, len: %zu", + (long)(STM32_OSPI_BASE_ADDRESS + addr), + size); + memcpy(data, (uint8_t *)STM32_OSPI_BASE_ADDRESS + addr, size); + + return 0; + } +#endif /* CONFIG_STM32_MEMMAP */ + OSPI_RegularCmdTypeDef cmd = ospi_prepare_cmd(dev_cfg->data_mode, dev_cfg->data_rate); if (dev_cfg->data_mode != OSPI_OPI_MODE) { @@ -1207,7 +1380,10 @@ static int flash_stm32_ospi_read(const struct device *dev, off_t addr, return ret; } -/* Function to write the flash (page program) : with possible OSPI/SPI and STR/DTR */ +/* + * Function to write the flash (page program) : with possible OSPI/SPI and STR/DTR + * NOTE: writing in MemoryMapped mode is not guaranted + */ static int flash_stm32_ospi_write(const struct device *dev, off_t addr, const void *data, size_t size) { @@ -1227,6 +1403,28 @@ static int flash_stm32_ospi_write(const struct device *dev, off_t addr, return 0; } +#ifdef CONFIG_STM32_MEMMAP + if (stm32_ospi_is_memorymap(dev)) { + /* If the Flash is in MemoryMapped mode, abort it and continue */ + LOG_INF("MemoryMap : disable before write"); + if (stm32_ospi_abort_memmap(dev) != 0) { + LOG_ERR("MemoryMap not aborted correctly"); + return -EIO; + } + } + if (stm32_ospi_is_memorymap(dev)) { + /* + * If the Flash is in MemoryMapped mode, write by memcopy + * should not due to previous operation + */ + LOG_DBG("MemoryMapped Write offset: 0x%lx, len: %zu", + (long)(STM32_OSPI_BASE_ADDRESS + addr), + size); + memcpy((uint8_t *)STM32_OSPI_BASE_ADDRESS + addr, data, size); + + return 0; + } +#endif /* CONFIG_STM32_MEMMAP */ /* page program for STR or DTR mode */ OSPI_RegularCmdTypeDef cmd_pp = ospi_prepare_cmd(dev_cfg->data_mode, dev_cfg->data_rate); @@ -1891,6 +2089,16 @@ static int flash_stm32_ospi_init(const struct device *dev) return -ENODEV; } +#ifdef CONFIG_STM32_MEMMAP + /* If MemoryMapped then configure skip init */ + if (stm32_ospi_is_memorymap(dev)) { + LOG_INF("NOR init'd in MemMapped mode\n"); + /* Force HAL instance in correct state */ + dev_data->hospi.State = HAL_OSPI_STATE_BUSY_MEM_MAPPED; + return 0; + } +#endif /* CONFIG_STM32_MEMMAP */ + #if STM32_OSPI_USE_DMA /* * DMA configuration @@ -2235,6 +2443,18 @@ static int flash_stm32_ospi_init(const struct device *dev) } #endif /* CONFIG_FLASH_PAGE_LAYOUT */ +#ifdef CONFIG_STM32_MEMMAP + /* Now configure the octo Flash in MemoryMapped (access by address) */ + ret = stm32_ospi_set_memorymap(dev); + if (ret != 0) { + LOG_ERR("Error (%d): setting NOR in MemoryMapped mode", ret); + return -EINVAL; + } + LOG_INF("NOR in MemoryMapped mode at 0x%lx (0x%x bytes)", + (long)(STM32_OSPI_BASE_ADDRESS), + dev_cfg->flash_size); + +#endif /* CONFIG_STM32_MEMMAP */ return 0; } @@ -2300,7 +2520,7 @@ static const struct flash_stm32_ospi_config flash_stm32_ospi_cfg = { .enr = DT_CLOCKS_CELL_BY_NAME(STM32_OSPI_NODE, ospi_mgr, bits)}, #endif .irq_config = flash_stm32_ospi_irq_config_func, - .flash_size = DT_INST_PROP(0, size) / 8U, + .flash_size = DT_REG_ADDR_BY_IDX(DT_INST(0, st_stm32_ospi_nor), 1), .max_frequency = DT_INST_PROP(0, ospi_max_frequency), .data_mode = DT_INST_PROP(0, spi_bus_width), /* SPI or OPI */ .data_rate = DT_INST_PROP(0, data_rate), /* DTR or STR */ diff --git a/drivers/flash/flash_stm32_qspi.c b/drivers/flash/flash_stm32_qspi.c index 6a9f8a585573..1aa82f344ec3 100644 --- a/drivers/flash/flash_stm32_qspi.c +++ b/drivers/flash/flash_stm32_qspi.c @@ -29,6 +29,9 @@ #define STM32_QSPI_USE_QUAD_IO 0 #endif +/* Get the base address of the flash from the DTS node */ +#define STM32_QSPI_BASE_ADDRESS DT_REG_ADDR(DT_INST(0, st_stm32_qspi_nor)) + #define STM32_QSPI_RESET_GPIO DT_INST_NODE_HAS_PROP(0, reset_gpios) #define STM32_QSPI_RESET_CMD DT_INST_NODE_HAS_PROP(0, reset_cmd) @@ -382,6 +385,53 @@ static bool qspi_address_is_valid(const struct device *dev, off_t addr, return (addr >= 0) && ((uint64_t)addr + (uint64_t)size <= flash_size); } +#ifdef CONFIG_STM32_MEMMAP +/* Function to return true if the quad-NOR flash is in MemoryMapped else false */ +static bool qspi_is_memorymap(const struct device *dev) +{ + struct flash_stm32_qspi_data *dev_data = dev->data; + + return ((READ_BIT(dev_data->hqspi.Instance->CCR, + QUADSPI_CCR_FMODE) == QUADSPI_CCR_FMODE) ? + true : false); +} + + +/* Function to configure the memmapped mode */ +static int qspi_set_memorymap(const struct device *dev) +{ + HAL_StatusTypeDef ret; + struct flash_stm32_qspi_data *dev_data = dev->data; + QSPI_CommandTypeDef s_command = {0}; + QSPI_MemoryMappedTypeDef s_memmap_cfg; + + /* Reading sequence */ + s_command.Instruction = SPI_NOR_CMD_4READ; /* 0x6B also supported */ + s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE; + s_command.AddressMode = QSPI_ADDRESS_4_LINES; + s_command.AddressSize = QSPI_ADDRESS_32_BITS; /* valid for stm32H7 and stm32L4 */ + s_command.DataMode = QSPI_DATA_4_LINES; +#ifdef CONFIG_SOC_SERIES_STM32H7X + s_command.DummyCycles = SPI_NOR_DUMMY_RD_QUAD; /* other value than 10 is wrong */ +#else + s_command.DummyCycles = 4;/* other value than 4 is wrong */ +#endif /* CONFIG_SOC_SERIES_STM32H7X */ + s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; + + /* Enable the memory-mapping */ + s_memmap_cfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE; + s_memmap_cfg.TimeOutPeriod = 0; + + ret = HAL_QSPI_MemoryMapped(&dev_data->hqspi, &s_command, &s_memmap_cfg); + if (ret != HAL_OK) { + LOG_ERR("%d: Failed to set memory map", ret); + return -EIO; + } + + return 0; +} +#endif /* CONFIG_STM32_MEMMAP */ + static int flash_stm32_qspi_read(const struct device *dev, off_t addr, void *data, size_t size) { @@ -398,6 +448,15 @@ static int flash_stm32_qspi_read(const struct device *dev, off_t addr, return 0; } +#ifdef CONFIG_STM32_MEMMAP + if (qspi_is_memorymap(dev)) { + LOG_DBG("MemoryMapped Read offset: 0x%lx, len: %zu", + (long)(STM32_QSPI_BASE_ADDRESS + addr), size); + memcpy(data, (uint8_t *)STM32_QSPI_BASE_ADDRESS + addr, size); + + return 0; + } +#endif /* CONFIG_STM32_MEMMAP */ QSPI_CommandTypeDef cmd = { .Instruction = SPI_NOR_CMD_READ, .Address = addr, @@ -457,6 +516,16 @@ static int flash_stm32_qspi_write(const struct device *dev, off_t addr, return 0; } +#ifdef CONFIG_STM32_MEMMAP + if (qspi_is_memorymap(dev)) { + LOG_DBG("MemoryMapped Write offset: 0x%lx, len: %zu", + (long)(STM32_QSPI_BASE_ADDRESS + addr), size); + memcpy((uint8_t *)STM32_QSPI_BASE_ADDRESS + addr, data, size); + + return 0; + } +#endif /* CONFIG_STM32_MEMMAP */ + QSPI_CommandTypeDef cmd_write_en = { .Instruction = SPI_NOR_CMD_WREN, .InstructionMode = QSPI_INSTRUCTION_1_LINE, @@ -538,6 +607,13 @@ static int flash_stm32_qspi_erase(const struct device *dev, off_t addr, return 0; } +#ifdef CONFIG_STM32_MEMMAP + if (qspi_is_memorymap(dev)) { + LOG_INF("MemoryMapped : cannot erase"); + return 0; + } +#endif /* CONFIG_STM32_MEMMAP */ + QSPI_CommandTypeDef cmd_write_en = { .Instruction = SPI_NOR_CMD_WREN, .InstructionMode = QSPI_INSTRUCTION_1_LINE, @@ -910,6 +986,7 @@ static int qspi_write_status_register(const struct device *dev, uint8_t reg_num, return qspi_write_access(dev, &cmd, regs_p, size); } +/* Function send a Write Enable and wait it is effective. */ static int qspi_write_enable(const struct device *dev) { uint8_t reg; @@ -1185,6 +1262,17 @@ static int flash_stm32_qspi_init(const struct device *dev) return ret; } + +#ifdef CONFIG_STM32_MEMMAP + /* If MemoryMapped then configure skip init */ + if (qspi_is_memorymap(dev)) { + LOG_INF("NOR init'd in MemMapped mode\n"); + /* Force HAL instance in correct state */ + dev_data->hqspi.State = HAL_QSPI_STATE_BUSY_MEM_MAPPED; + return 0; + } +#endif /* CONFIG_STM32_MEMMAP */ + #if STM32_QSPI_RESET_GPIO flash_stm32_qspi_gpio_reset(dev); #endif @@ -1277,7 +1365,12 @@ static int flash_stm32_qspi_init(const struct device *dev) dev_data->hqspi.Init.ClockPrescaler = prescaler; /* Give a bit position from 0 to 31 to the HAL init minus 1 for the DCR1 reg */ dev_data->hqspi.Init.FlashSize = find_lsb_set(dev_cfg->flash_size) - 2; - +#if ! DT_NODE_HAS_PROP(DT_NODELABEL(quadspi), flash_id) + /* That means Dual Flash configuration : FlashID is meaningless */ + dev_data->hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE; + /* Set Dual Flash Mode only on MemoryMapped */ + dev_data->hqspi.Init.FlashID = QSPI_FLASH_ID_1; +#endif HAL_QSPI_Init(&dev_data->hqspi); #if DT_NODE_HAS_PROP(DT_NODELABEL(quadspi), flash_id) @@ -1364,6 +1457,27 @@ static int flash_stm32_qspi_init(const struct device *dev) } #endif /* CONFIG_FLASH_PAGE_LAYOUT */ +#ifdef CONFIG_STM32_MEMMAP +#if ! DT_NODE_HAS_PROP(DT_NODELABEL(quadspi), flash_id) + /* Force Dual Flash mode now */ + MODIFY_REG(dev_data->hqspi.Instance->CR, (QUADSPI_CR_DFM), QSPI_DUALFLASH_ENABLE); + LOG_DBG("Dual Flash Mode"); +#else + LOG_ERR("Cannot set MemoryMapped mode if DualFlash is off"); +#endif + + ret = qspi_set_memorymap(dev); + + if (ret != 0) { + LOG_ERR("Error (%d): setting NOR in MemoryMapped mode", ret); + return -EINVAL; + } + LOG_INF("NOR in MemoryMapped mode at 0x%lx (0x%x bytes)", + (long)(STM32_QSPI_BASE_ADDRESS), + dev_cfg->flash_size); + +#endif /* CONFIG_STM32_MEMMAP */ + return 0; } @@ -1420,7 +1534,7 @@ static const struct flash_stm32_qspi_config flash_stm32_qspi_cfg = { .bus = DT_CLOCKS_CELL(STM32_QSPI_NODE, bus) }, .irq_config = flash_stm32_qspi_irq_config_func, - .flash_size = DT_INST_PROP(0, size) / 8U, + .flash_size = DT_REG_ADDR_BY_IDX(DT_INST(0, st_stm32_qspi_nor), 1), .max_frequency = DT_INST_PROP(0, qspi_max_frequency), .pcfg = PINCTRL_DT_DEV_CONFIG_GET(STM32_QSPI_NODE), #if STM32_QSPI_RESET_GPIO diff --git a/drivers/flash/flash_stm32f1x.c b/drivers/flash/flash_stm32f1x.c index 0c54d3f69fef..9a2c0bb4a903 100644 --- a/drivers/flash/flash_stm32f1x.c +++ b/drivers/flash/flash_stm32f1x.c @@ -62,7 +62,7 @@ static void erase_page_begin(FLASH_TypeDef *regs, unsigned int page) { /* Set the PER bit and select the page you wish to erase */ regs->CR |= FLASH_CR_PER; - regs->AR = CONFIG_FLASH_BASE_ADDRESS + page * FLASH_PAGE_SIZE; + regs->AR = FLASH_STM32_BASE_ADDRESS + page * FLASH_PAGE_SIZE; barrier_dsync_fence_full(); @@ -99,7 +99,7 @@ static void write_disable(FLASH_TypeDef *regs) static void erase_page_begin(FLASH_TypeDef *regs, unsigned int page) { volatile flash_prg_t *page_base = (flash_prg_t *)( - CONFIG_FLASH_BASE_ADDRESS + page * FLASH_PAGE_SIZE); + FLASH_STM32_BASE_ADDRESS + page * FLASH_PAGE_SIZE); /* Enable programming in erase mode. An erase is triggered by * writing 0 to the first word of a page. */ @@ -123,7 +123,7 @@ static int write_value(const struct device *dev, off_t offset, flash_prg_t val) { volatile flash_prg_t *flash = (flash_prg_t *)( - offset + CONFIG_FLASH_BASE_ADDRESS); + offset + FLASH_STM32_BASE_ADDRESS); FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); int rc; diff --git a/drivers/flash/flash_stm32f2x.c b/drivers/flash/flash_stm32f2x.c index f3781855f576..a525aa8e90f0 100644 --- a/drivers/flash/flash_stm32f2x.c +++ b/drivers/flash/flash_stm32f2x.c @@ -76,7 +76,7 @@ static int write_byte(const struct device *dev, off_t offset, uint8_t val) /* flush the register write */ tmp = regs->CR; - *((uint8_t *) offset + CONFIG_FLASH_BASE_ADDRESS) = val; + *((uint8_t *) offset + FLASH_STM32_BASE_ADDRESS) = val; /* Wait until the BSY bit is cleared */ rc = flash_stm32_wait_flash_idle(dev); diff --git a/drivers/flash/flash_stm32f4x.c b/drivers/flash/flash_stm32f4x.c index 4261c26a5890..ddc882747ccb 100644 --- a/drivers/flash/flash_stm32f4x.c +++ b/drivers/flash/flash_stm32f4x.c @@ -101,7 +101,7 @@ static int write_byte(const struct device *dev, off_t offset, uint8_t val) /* flush the register write */ tmp = regs->CR; - *((uint8_t *) offset + CONFIG_FLASH_BASE_ADDRESS) = val; + *((uint8_t *) offset + FLASH_STM32_BASE_ADDRESS) = val; rc = flash_stm32_wait_flash_idle(dev); regs->CR &= (~FLASH_CR_PG); diff --git a/drivers/flash/flash_stm32f7x.c b/drivers/flash/flash_stm32f7x.c index b65bf25a0791..324b66d81979 100644 --- a/drivers/flash/flash_stm32f7x.c +++ b/drivers/flash/flash_stm32f7x.c @@ -60,7 +60,7 @@ static int write_byte(const struct device *dev, off_t offset, uint8_t val) barrier_dsync_fence_full(); /* write the data */ - *((uint8_t *) offset + CONFIG_FLASH_BASE_ADDRESS) = val; + *((uint8_t *) offset + FLASH_STM32_BASE_ADDRESS) = val; /* flush the register write */ barrier_dsync_fence_full(); diff --git a/drivers/flash/flash_stm32g0x.c b/drivers/flash/flash_stm32g0x.c index 41a0e1da3bf8..5c232dacc64c 100644 --- a/drivers/flash/flash_stm32g0x.c +++ b/drivers/flash/flash_stm32g0x.c @@ -56,7 +56,7 @@ static inline void flush_cache(FLASH_TypeDef *regs) static int write_dword(const struct device *dev, off_t offset, uint64_t val) { - volatile uint32_t *flash = (uint32_t *)(offset + CONFIG_FLASH_BASE_ADDRESS); + volatile uint32_t *flash = (uint32_t *)(offset + FLASH_STM32_BASE_ADDRESS); FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); uint32_t tmp; int rc; diff --git a/drivers/flash/flash_stm32g4x.c b/drivers/flash/flash_stm32g4x.c index 8f11e21c20e9..631268a70c6a 100644 --- a/drivers/flash/flash_stm32g4x.c +++ b/drivers/flash/flash_stm32g4x.c @@ -75,7 +75,7 @@ static inline void flush_cache(FLASH_TypeDef *regs) static int write_dword(const struct device *dev, off_t offset, uint64_t val) { - volatile uint32_t *flash = (uint32_t *)(offset + CONFIG_FLASH_BASE_ADDRESS); + volatile uint32_t *flash = (uint32_t *)(offset + FLASH_STM32_BASE_ADDRESS); FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); #if defined(FLASH_STM32_DBANK) bool dcache_enabled = false; diff --git a/drivers/flash/flash_stm32h7x.c b/drivers/flash/flash_stm32h7x.c index 61394164c1bd..271bb413194c 100644 --- a/drivers/flash/flash_stm32h7x.c +++ b/drivers/flash/flash_stm32h7x.c @@ -307,7 +307,7 @@ static int write_ndwords(const struct device *dev, uint8_t n) { volatile uint64_t *flash = (uint64_t *)(offset - + CONFIG_FLASH_BASE_ADDRESS); + + FLASH_STM32_BASE_ADDRESS); int rc; int i; struct flash_stm32_sector_t sector = get_sector(dev, offset); @@ -451,7 +451,7 @@ static void flash_stm32h7_flush_caches(const struct device *dev, return; /* Cache not enabled */ } - SCB_InvalidateDCache_by_Addr((uint32_t *)(CONFIG_FLASH_BASE_ADDRESS + SCB_InvalidateDCache_by_Addr((uint32_t *)(FLASH_STM32_BASE_ADDRESS + offset), len); } #endif /* CONFIG_CPU_CORTEX_M7 */ @@ -574,7 +574,7 @@ static int flash_stm32h7_read(const struct device *dev, off_t offset, barrier_dsync_fence_full(); barrier_isync_fence_full(); - memcpy(data, (uint8_t *) CONFIG_FLASH_BASE_ADDRESS + offset, len); + memcpy(data, (uint8_t *) FLASH_STM32_BASE_ADDRESS + offset, len); __set_FAULTMASK(0); SCB->CCR &= ~SCB_CCR_BFHFNMIGN_Msk; diff --git a/drivers/flash/flash_stm32l4x.c b/drivers/flash/flash_stm32l4x.c index e82bf1db3039..d9b0fbbcbee2 100644 --- a/drivers/flash/flash_stm32l4x.c +++ b/drivers/flash/flash_stm32l4x.c @@ -69,7 +69,7 @@ static unsigned int get_page(off_t offset) static int write_dword(const struct device *dev, off_t offset, uint64_t val) { - volatile uint32_t *flash = (uint32_t *)(offset + CONFIG_FLASH_BASE_ADDRESS); + volatile uint32_t *flash = (uint32_t *)(offset + FLASH_STM32_BASE_ADDRESS); FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); #ifdef CONTROL_DCACHE bool dcache_enabled = false; diff --git a/drivers/flash/flash_stm32l5x.c b/drivers/flash/flash_stm32l5x.c index 5e4c096dceae..59b649731e94 100644 --- a/drivers/flash/flash_stm32l5x.c +++ b/drivers/flash/flash_stm32l5x.c @@ -161,7 +161,7 @@ static int write_nwords(const struct device *dev, off_t offset, const uint32_t * { FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); volatile uint32_t *flash = (uint32_t *)(offset - + CONFIG_FLASH_BASE_ADDRESS); + + FLASH_STM32_BASE_ADDRESS); bool full_zero = true; uint32_t tmp; int rc; diff --git a/drivers/flash/flash_stm32wba_fm.c b/drivers/flash/flash_stm32wba_fm.c index 2628f650dccf..ff42c2643c53 100644 --- a/drivers/flash/flash_stm32wba_fm.c +++ b/drivers/flash/flash_stm32wba_fm.c @@ -93,7 +93,7 @@ static int flash_stm32_read(const struct device *dev, off_t offset, flash_stm32_sem_take(dev); - memcpy(data, (uint8_t *) CONFIG_FLASH_BASE_ADDRESS + offset, len); + memcpy(data, (uint8_t *) FLASH_STM32_BASE_ADDRESS + offset, len); flash_stm32_sem_give(dev); @@ -153,7 +153,7 @@ static int flash_stm32_write(const struct device *dev, off_t offset, LOG_DBG("Write offset: %p, len: %zu", (void *)offset, len); rc = FM_Write((uint32_t *)data, - (uint32_t *)(CONFIG_FLASH_BASE_ADDRESS + offset), + (uint32_t *)(FLASH_STM32_BASE_ADDRESS + offset), (int32_t)len/4, &cb_ptr); if (rc == 0) { k_sem_take(&flash_busy, K_FOREVER); diff --git a/drivers/flash/flash_stm32wbax.c b/drivers/flash/flash_stm32wbax.c index 0796b9a5be40..db158f71a9a2 100644 --- a/drivers/flash/flash_stm32wbax.c +++ b/drivers/flash/flash_stm32wbax.c @@ -109,7 +109,7 @@ static int write_qword(const struct device *dev, off_t offset, const uint32_t *b { FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); volatile uint32_t *flash = (uint32_t *)(offset - + CONFIG_FLASH_BASE_ADDRESS); + + FLASH_STM32_BASE_ADDRESS); uint32_t tmp; int rc; diff --git a/drivers/flash/flash_stm32wbx.c b/drivers/flash/flash_stm32wbx.c index e72fddf756f7..293d9c5a54ee 100644 --- a/drivers/flash/flash_stm32wbx.c +++ b/drivers/flash/flash_stm32wbx.c @@ -60,7 +60,7 @@ static inline void flush_cache(FLASH_TypeDef *regs) static int write_dword(const struct device *dev, off_t offset, uint64_t val) { - volatile uint32_t *flash = (uint32_t *)(offset + CONFIG_FLASH_BASE_ADDRESS); + volatile uint32_t *flash = (uint32_t *)(offset + FLASH_STM32_BASE_ADDRESS); FLASH_TypeDef *regs = FLASH_STM32_REGS(dev); uint32_t tmp; int ret, rc; diff --git a/drivers/flash/spi_nor.h b/drivers/flash/spi_nor.h index 8d54cc615089..82147baac532 100644 --- a/drivers/flash/spi_nor.h +++ b/drivers/flash/spi_nor.h @@ -60,6 +60,9 @@ #define SPI_NOR_CMD_PP_1_1_4_4B 0x34 /* Quad Page program (1-1-4) 4 Byte Address */ #define SPI_NOR_CMD_PP_1_4_4_4B 0x3e /* Quad Page program (1-4-4) 4 Byte Address */ +#define SPI_NOR_CMD_RD_VOL_CFG 0x85 /* Read Volatile configuration register */ +#define SPI_NOR_CMD_WR_VOL_CFG 0x81 /* Write Volatile configuration register */ + /* Flash octal opcodes */ #define SPI_NOR_OCMD_SE 0x21DE /* Octal Sector erase */ #define SPI_NOR_OCMD_CE 0xC738 /* Octal Chip erase */ @@ -94,6 +97,7 @@ /* Flash Dummy Cycles values */ #define SPI_NOR_DUMMY_RD 8U +#define SPI_NOR_DUMMY_RD_QUAD 10U #define SPI_NOR_DUMMY_RD_OCTAL 6U #define SPI_NOR_DUMMY_RD_OCTAL_DTR 6U #define SPI_NOR_DUMMY_REG_OCTAL 4U diff --git a/dts/arm/st/h7/stm32h7.dtsi b/dts/arm/st/h7/stm32h7.dtsi index 64ccfbf7241a..10880c62e0ed 100644 --- a/dts/arm/st/h7/stm32h7.dtsi +++ b/dts/arm/st/h7/stm32h7.dtsi @@ -46,10 +46,11 @@ }; quadspi_memory: memory@90000000 { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x90000000 DT_SIZE_M(256)>; + compatible = "zephyr,memory-region"; + reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ zephyr,memory-region = "QSPI"; - zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_EXTMEM) )>; + /* The ATTR_MPU_EXTMEM attribut causing a MPU FAULT */ + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; }; clocks { diff --git a/dts/bindings/flash_controller/st,stm32-ospi-nor.yaml b/dts/bindings/flash_controller/st,stm32-ospi-nor.yaml index f8f84020f6a1..25dce9c07694 100644 --- a/dts/bindings/flash_controller/st,stm32-ospi-nor.yaml +++ b/dts/bindings/flash_controller/st,stm32-ospi-nor.yaml @@ -25,13 +25,11 @@ on-bus: ospi properties: reg: required: true + description: Flash Memory base address and size in bytes ospi-max-frequency: type: int required: true description: Maximum clock frequency of device's OSPI interface in Hz - size: - required: true - description: Flash Memory size in bits reset-gpios: type: phandle-array description: RESETn pin diff --git a/dts/bindings/flash_controller/st,stm32-qspi-nor.yaml b/dts/bindings/flash_controller/st,stm32-qspi-nor.yaml index 6d7bf5105e63..e556d5a1639a 100644 --- a/dts/bindings/flash_controller/st,stm32-qspi-nor.yaml +++ b/dts/bindings/flash_controller/st,stm32-qspi-nor.yaml @@ -26,13 +26,11 @@ on-bus: qspi properties: reg: required: true + description: Flash Memory base address and size in bytes qspi-max-frequency: type: int required: true description: Maximum clock frequency of device's QSPI interface in Hz - size: - required: true - description: Flash Memory size in bits reset-gpios: type: phandle-array description: RESETn pin diff --git a/dts/bindings/qspi/st,stm32-qspi.yaml b/dts/bindings/qspi/st,stm32-qspi.yaml index 04aa6e4d0208..cea2f66a70eb 100644 --- a/dts/bindings/qspi/st,stm32-qspi.yaml +++ b/dts/bindings/qspi/st,stm32-qspi.yaml @@ -66,5 +66,7 @@ properties: QSPI GPIO banks (defined as 'quadspi_bk[12]' in pinctrl property) to communicate with flash memory. + When NOT set, it means Dual Flash Mode. + For example flash-id = <2>; diff --git a/samples/subsys/fs/littlefs/boards/b_u585i_iot02a.conf b/samples/subsys/fs/littlefs/boards/b_u585i_iot02a.conf index c5f2188e4d31..d906422678e6 100644 --- a/samples/subsys/fs/littlefs/boards/b_u585i_iot02a.conf +++ b/samples/subsys/fs/littlefs/boards/b_u585i_iot02a.conf @@ -5,3 +5,5 @@ # CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=8192 + +CONFIG_STM32_MEMMAP=y diff --git a/samples/subsys/fs/littlefs/boards/b_u585i_iot02a.overlay b/samples/subsys/fs/littlefs/boards/b_u585i_iot02a.overlay index b4996d707100..311f3fce09df 100644 --- a/samples/subsys/fs/littlefs/boards/b_u585i_iot02a.overlay +++ b/samples/subsys/fs/littlefs/boards/b_u585i_iot02a.overlay @@ -5,6 +5,10 @@ */ / { + chosen { + zephyr,code-partition = &slot1_partition; + }; + fstab { compatible = "zephyr,fstab"; lfs1: lfs1 { @@ -21,13 +25,10 @@ }; }; -&mx25lm51245 { +&flash0 { partitions { - /delete-node/ partition; - - /* Use the whole flash for the filesystem. */ - lfs1_partition: partition@0 { - reg = <0x00000000 DT_SIZE_M(64)>; + lfs1_partition: partition@d0000 { + reg = <0x000d0000 DT_SIZE_K(64)>; }; }; }; diff --git a/samples/subsys/fs/littlefs/boards/stm32h747i_disco_m7.overlay b/samples/subsys/fs/littlefs/boards/stm32h747i_disco_m7.overlay index cf1c30e2e87b..c2945675ddec 100644 --- a/samples/subsys/fs/littlefs/boards/stm32h747i_disco_m7.overlay +++ b/samples/subsys/fs/littlefs/boards/stm32h747i_disco_m7.overlay @@ -4,6 +4,35 @@ * SPDX-License-Identifier: Apache-2.0 */ +/ { + chosen { + zephyr,code-partition = &slot1_partition; + }; + + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <4096>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&lfs1_partition>; + mount-point = "/lfs1"; + automount; + }; + }; +}; + +&flash0 { + partitions { + lfs1_partition: partition@e0000 { + reg = <0x000e0000 DT_SIZE_K(64)>; + }; + }; +}; + &sdmmc1 { sdmmc { compatible = "zephyr,sdmmc-disk"; diff --git a/samples/subsys/fs/littlefs/boards/stm32h750b_dk.conf b/samples/subsys/fs/littlefs/boards/stm32h750b_dk.conf new file mode 100644 index 000000000000..8bc2e5b8df52 --- /dev/null +++ b/samples/subsys/fs/littlefs/boards/stm32h750b_dk.conf @@ -0,0 +1,3 @@ +CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=8192 + +CONFIG_STM32_MEMMAP=y diff --git a/samples/subsys/fs/littlefs/boards/stm32h750b_dk.overlay b/samples/subsys/fs/littlefs/boards/stm32h750b_dk.overlay new file mode 100644 index 000000000000..5eae5f067538 --- /dev/null +++ b/samples/subsys/fs/littlefs/boards/stm32h750b_dk.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + + chosen { + zephyr,code-partition = &slot1_partition; + }; + + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <4096>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&lfs1_partition>; + mount-point = "/lfs1"; + automount; + }; + }; +}; + +&flash0 { + partitions { + lfs1_partition: partition@e0000 { + reg = <0x000e0000 DT_SIZE_K(64)>; + }; + }; +}; diff --git a/samples/subsys/fs/littlefs/boards/stm32h7b3i_dk.conf b/samples/subsys/fs/littlefs/boards/stm32h7b3i_dk.conf new file mode 100644 index 000000000000..8bc2e5b8df52 --- /dev/null +++ b/samples/subsys/fs/littlefs/boards/stm32h7b3i_dk.conf @@ -0,0 +1,3 @@ +CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=8192 + +CONFIG_STM32_MEMMAP=y diff --git a/samples/subsys/fs/littlefs/boards/stm32h7b3i_dk.overlay b/samples/subsys/fs/littlefs/boards/stm32h7b3i_dk.overlay new file mode 100644 index 000000000000..25568e8b76db --- /dev/null +++ b/samples/subsys/fs/littlefs/boards/stm32h7b3i_dk.overlay @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 OS Systems + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + + chosen { + zephyr,code-partition = &slot1_partition; + }; + + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <4096>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&lfs1_partition>; + mount-point = "/lfs1"; + automount; + }; + }; +}; + +&flash0 { + partitions { + lfs1_partition: partition@e0000 { + reg = <0x000e0000 DT_SIZE_K(64)>; + }; + }; +}; diff --git a/samples/subsys/fs/littlefs/boards/stm32l496g_disco.overlay b/samples/subsys/fs/littlefs/boards/stm32l496g_disco.overlay new file mode 100644 index 000000000000..6d29d31c4aa6 --- /dev/null +++ b/samples/subsys/fs/littlefs/boards/stm32l496g_disco.overlay @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,code-partition = &slot1_partition; + }; + + fstab { + compatible = "zephyr,fstab"; + lfs1: lfs1 { + compatible = "zephyr,fstab,littlefs"; + read-size = <256>; + prog-size = <256>; + cache-size = <4096>; + lookahead-size = <256>; + block-cycles = <512>; + partition = <&lfs1_partition>; + mount-point = "/lfs1"; + automount; + }; + }; +}; + +&flash0 { + partitions { + lfs1_partition: partition@e0000 { + reg = <0x000e0000 DT_SIZE_K(64)>; + }; + }; +}; diff --git a/soc/arm/st_stm32/stm32u5/soc.c b/soc/arm/st_stm32/stm32u5/soc.c index d25fec9c680d..68df79d620b5 100644 --- a/soc/arm/st_stm32/stm32u5/soc.c +++ b/soc/arm/st_stm32/stm32u5/soc.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,10 @@ static int stm32u5_init(void) LL_ICACHE_SetMode(LL_ICACHE_1WAY); LL_ICACHE_Enable(); + /* Enable data cache (master port write access) */ + LL_DCACHE_SetReadBurstType(DCACHE1, LL_DCACHE_READ_BURST_INCR); + LL_DCACHE_Enable(DCACHE1); + /* Update CMSIS SystemCoreClock variable (HCLK) */ /* At reset, system core clock is set to 4 MHz from MSIS */ SystemCoreClock = 4000000;