Skip to content

Commit bbbd842

Browse files
committed
drivers/flash: enable memory-mapped mode for STM32 QSPI
This puts the QSPI peripheral into memory-mapped mode when CONFIG_STM32_MEMMAP is set. Writes and erase put it back into indirect write mode. Signed-off-by: Armin Brauns <[email protected]>
1 parent 998d5b0 commit bbbd842

File tree

1 file changed

+123
-0
lines changed

1 file changed

+123
-0
lines changed

drivers/flash/flash_stm32_qspi.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@
1212
#include <zephyr/kernel.h>
1313
#include <zephyr/toolchain.h>
1414
#include <zephyr/arch/common/ffs.h>
15+
#include <zephyr/sys/__assert.h>
1516
#include <zephyr/sys/util.h>
1617
#include <soc.h>
18+
#include <string.h>
1719
#include <zephyr/drivers/pinctrl.h>
1820
#include <zephyr/drivers/clock_control/stm32_clock_control.h>
1921
#include <zephyr/drivers/clock_control.h>
@@ -385,6 +387,66 @@ static bool qspi_address_is_valid(const struct device *dev, off_t addr,
385387
return (addr >= 0) && ((uint64_t)addr + (uint64_t)size <= flash_size);
386388
}
387389

390+
#ifdef CONFIG_STM32_MEMMAP
391+
/* Must be called inside qspi_lock_thread(). */
392+
static int stm32_qspi_set_memory_mapped(const struct device *dev)
393+
{
394+
int ret;
395+
HAL_StatusTypeDef hal_ret;
396+
struct flash_stm32_qspi_data *dev_data = dev->data;
397+
398+
QSPI_CommandTypeDef cmd = {
399+
.Instruction = SPI_NOR_CMD_READ,
400+
.Address = 0,
401+
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
402+
.AddressMode = QSPI_ADDRESS_1_LINE,
403+
.DataMode = QSPI_DATA_1_LINE,
404+
};
405+
406+
qspi_set_address_size(dev, &cmd);
407+
if (IS_ENABLED(STM32_QSPI_USE_QUAD_IO)) {
408+
ret = qspi_prepare_quad_read(dev, &cmd);
409+
if (ret < 0) {
410+
return ret;
411+
}
412+
}
413+
414+
QSPI_MemoryMappedTypeDef mem_mapped = {
415+
.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE,
416+
};
417+
418+
hal_ret = HAL_QSPI_MemoryMapped(&dev_data->hqspi, &cmd, &mem_mapped);
419+
if (hal_ret != 0) {
420+
LOG_ERR("%d: Failed to enable memory mapped", hal_ret);
421+
return -EIO;
422+
}
423+
424+
LOG_DBG("MemoryMap mode enabled");
425+
return 0;
426+
}
427+
428+
static bool stm32_qspi_is_memory_mapped(const struct device *dev)
429+
{
430+
struct flash_stm32_qspi_data *dev_data = dev->data;
431+
432+
return READ_BIT(dev_data->hqspi.Instance->CCR, QUADSPI_CCR_FMODE) == QUADSPI_CCR_FMODE;
433+
}
434+
435+
static int stm32_qspi_abort(const struct device *dev)
436+
{
437+
struct flash_stm32_qspi_data *dev_data = dev->data;
438+
HAL_StatusTypeDef hal_ret;
439+
440+
hal_ret = HAL_QSPI_Abort(&dev_data->hqspi);
441+
if (hal_ret != HAL_OK) {
442+
LOG_ERR("%d: QSPI abort failed", hal_ret);
443+
return -EIO;
444+
}
445+
446+
return 0;
447+
}
448+
#endif
449+
388450
static int flash_stm32_qspi_read(const struct device *dev, off_t addr,
389451
void *data, size_t size)
390452
{
@@ -401,6 +463,27 @@ static int flash_stm32_qspi_read(const struct device *dev, off_t addr,
401463
return 0;
402464
}
403465

466+
#ifdef CONFIG_STM32_MEMMAP
467+
qspi_lock_thread(dev);
468+
469+
/* Do reads through memory-mapping instead of indirect */
470+
if (!stm32_qspi_is_memory_mapped(dev)) {
471+
ret = stm32_qspi_set_memory_mapped(dev);
472+
if (ret != 0) {
473+
LOG_ERR("READ: failed to set memory mapped");
474+
goto end;
475+
}
476+
}
477+
478+
__ASSERT_NO_MSG(stm32_qspi_is_memory_mapped(dev));
479+
480+
uintptr_t mmap_addr = STM32_QSPI_BASE_ADDRESS + addr;
481+
482+
LOG_DBG("Memory-mapped read from 0x%08lx, len %zu", mmap_addr, size);
483+
memcpy(data, (void *)mmap_addr, size);
484+
ret = 0;
485+
goto end;
486+
#else
404487
QSPI_CommandTypeDef cmd = {
405488
.Instruction = SPI_NOR_CMD_READ,
406489
.Address = addr,
@@ -420,7 +503,10 @@ static int flash_stm32_qspi_read(const struct device *dev, off_t addr,
420503
qspi_lock_thread(dev);
421504

422505
ret = qspi_read_access(dev, &cmd, data, size);
506+
goto end;
507+
#endif
423508

509+
end:
424510
qspi_unlock_thread(dev);
425511

426512
return ret;
@@ -482,6 +568,17 @@ static int flash_stm32_qspi_write(const struct device *dev, off_t addr,
482568

483569
qspi_lock_thread(dev);
484570

571+
#ifdef CONFIG_STM32_MEMMAP
572+
if (stm32_qspi_is_memory_mapped(dev)) {
573+
/* Abort ongoing transfer to force CS high/BUSY deasserted */
574+
ret = stm32_qspi_abort(dev);
575+
if (ret != 0) {
576+
LOG_ERR("Failed to abort memory-mapped access before write");
577+
goto end;
578+
}
579+
}
580+
#endif
581+
485582
while (size > 0) {
486583
size_t to_write = size;
487584

@@ -517,7 +614,9 @@ static int flash_stm32_qspi_write(const struct device *dev, off_t addr,
517614
break;
518615
}
519616
}
617+
goto end;
520618

619+
end:
521620
qspi_unlock_thread(dev);
522621

523622
return ret;
@@ -555,6 +654,17 @@ static int flash_stm32_qspi_erase(const struct device *dev, off_t addr,
555654
qspi_set_address_size(dev, &cmd_erase);
556655
qspi_lock_thread(dev);
557656

657+
#ifdef CONFIG_STM32_MEMMAP
658+
if (stm32_qspi_is_memory_mapped(dev)) {
659+
/* Abort ongoing transfer to force CS high/BUSY deasserted */
660+
ret = stm32_qspi_abort(dev);
661+
if (ret != 0) {
662+
LOG_ERR("Failed to abort memory-mapped access before erase");
663+
goto end;
664+
}
665+
}
666+
#endif
667+
558668
while ((size > 0) && (ret == 0)) {
559669
cmd_erase.Address = addr;
560670
qspi_send_cmd(dev, &cmd_write_en);
@@ -596,7 +706,9 @@ static int flash_stm32_qspi_erase(const struct device *dev, off_t addr,
596706
}
597707
qspi_wait_until_ready(dev);
598708
}
709+
goto end;
599710

711+
end:
600712
qspi_unlock_thread(dev);
601713

602714
return ret;
@@ -1367,9 +1479,20 @@ static int flash_stm32_qspi_init(const struct device *dev)
13671479
}
13681480
#endif /* CONFIG_FLASH_PAGE_LAYOUT */
13691481

1482+
#ifdef CONFIG_STM32_MEMMAP
1483+
ret = stm32_qspi_set_memory_mapped(dev);
1484+
if (ret != 0) {
1485+
LOG_ERR("Failed to enable memory-mapped mode: %d", ret);
1486+
return ret;
1487+
}
1488+
LOG_INF("Memory-mapped NOR quad-flash at 0x%lx (0x%x bytes)",
1489+
(long)(STM32_QSPI_BASE_ADDRESS),
1490+
dev_cfg->flash_size);
1491+
#else
13701492
LOG_INF("NOR quad-flash at 0x%lx (0x%x bytes)",
13711493
(long)(STM32_QSPI_BASE_ADDRESS),
13721494
dev_cfg->flash_size);
1495+
#endif
13731496

13741497
return 0;
13751498
}

0 commit comments

Comments
 (0)