Skip to content

Conversation

mariopaja
Copy link
Contributor

@mariopaja mariopaja commented Jun 30, 2025

Add STM32 OSPI PSRAM driver support in memory mapped mode

Current driver configuration based on aps6408l

Test application 1

https://github.com/mariopaja/hello_psram

Custom U575 Board:

Memory region         Used Size  Region Size  %age Used
           FLASH:       23572 B         2 MB      1.12%
             RAM:        4864 B       768 KB      0.62%
           PSRAM:       2000 KB         8 MB     24.41%
        IDT_LIST:          0 GB        32 KB      0.00%

b_u585i_iot02a:

Memory region         Used Size  Region Size  %age Used
           FLASH:       34680 B         2 MB      1.65%
             RAM:        6960 B       768 KB      0.89%
           PSRAM:       8000 KB         8 MB     97.66%
          EXTMEM:          0 GB        64 MB      0.00%
        IDT_LIST:          0 GB        32 KB      0.00%
Hello STM32 OSPI PSRAM!
Verifying PSRAM Buffer size: 2048000 ...
PSRAM verification successful!
[00:00:00.000,000] <dbg> memc_stm32_ospi_psram: memc_stm32_ospi_psram_init: OSPI AHB clock frequency: 160000000 Hz
[00:00:00.000,000] <dbg> memc_stm32_ospi_psram: memc_stm32_ospi_psram_init: OSPI max frequency: 133000000 Hz
[00:00:00.000,000] <dbg> memc_stm32_ospi_psram: memc_stm32_ospi_psram_init: clk: 80000000, prescaler: 2
[00:00:00.000,000] <dbg> memc_stm32_ospi_psram: memc_stm32_ospi_psram_init: MSB set: 23
*** Booting Zephyr OS build v4.2.0-rc1-130-gd97aff3f8f32 ***

Test application 2

tests/drivers/memc/ram

Memory region         Used Size  Region Size  %age Used
           FLASH:       36384 B         2 MB      1.73%
             RAM:        5984 B       768 KB      0.76%
           PSRAM:          8 MB         8 MB    100.00%
          EXTMEM:          0 GB        64 MB      0.00%
        IDT_LIST:          0 GB        32 KB      0.00%
*** Booting Zephyr OS build v4.2.0-3146-gea283133abd3 ***
Running TESTSUITE test_ram
===================================================================
START - test_psram
 PASS - test_psram in 0.138 seconds
===================================================================
START - test_ram0
 SKIP - test_ram0 in 0.001 seconds
===================================================================
START - test_sdram1
 SKIP - test_sdram1 in 0.001 seconds
===================================================================
START - test_sdram2
 SKIP - test_sdram2 in 0.001 seconds
===================================================================
START - test_sram1
 SKIP - test_sram1 in 0.001 seconds
===================================================================
START - test_sram2
 SKIP - test_sram2 in 0.001 seconds
===================================================================
TESTSUITE test_ram succeeded

------ TESTSUITE SUMMARY START ------

SUITE PASS - 100.00% [test_ram]: pass = 1, fail = 0, skip = 5, total = 6 duration = 0.143 seconds
 - PASS - [test_ram.test_psram] duration = 0.138 seconds
 - SKIP - [test_ram.test_ram0] duration = 0.001 seconds
 - SKIP - [test_ram.test_sdram1] duration = 0.001 seconds
 - SKIP - [test_ram.test_sdram2] duration = 0.001 seconds
 - SKIP - [test_ram.test_sram1] duration = 0.001 seconds
 - SKIP - [test_ram.test_sram2] duration = 0.001 seconds

------ TESTSUITE SUMMARY END ------

===================================================================
PROJECT EXECUTION SUCCESSFUL

@mariopaja mariopaja force-pushed the memc_stm32_ospi_psram branch 2 times, most recently from 752b380 to 3e5e735 Compare June 30, 2025 08:52
@dkouba-atym
Copy link

Thank you Mario! Could you tag this for backport into v4.1?

@mariopaja
Copy link
Contributor Author

Thank you Mario! Could you tag this for backport into v4.1?

@dkouba-atym I dont think I can or am allowed to. I dont really see any relevance of this driver for v4.1.

@mariopaja mariopaja force-pushed the memc_stm32_ospi_psram branch 5 times, most recently from 8b0fd92 to 6efb10f Compare July 4, 2025 11:39
@JarmouniA
Copy link
Contributor

Thank you Mario! Could you tag this for backport into v4.1?

Only fixes are backported.

@mariopaja mariopaja force-pushed the memc_stm32_ospi_psram branch 5 times, most recently from 17525a8 to 823d932 Compare July 8, 2025 06:57
@mariopaja mariopaja marked this pull request as ready for review July 8, 2025 08:20
@erwango erwango added this to the v4.3.0 milestone Jul 8, 2025
@bilibb
Copy link

bilibb commented Jul 9, 2025

I was able to integrate the driver with an STM32U5A9J overlay and successfully write and read an APS6408L-3OBM-BA using the supplied test program.

Copy link
Contributor

@etienne-lms etienne-lms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a short sentence in the commit message like the below?

Add an overlay DTSI in tests/drivers/memc/ram for that board to pass this test
over its PSRAM only.

@JarmouniA
Copy link
Contributor

Otherwise I could have a look into test/drivers/memc/ram :)

Better to extend the test.

@etienne-lms
Copy link
Contributor

Otherwise I could have a look into test/drivers/memc/ram :)

Better to extend the test.

Maybe simply get the RAM size from the DT to extended tested RAM locations.

@mariopaja mariopaja force-pushed the memc_stm32_ospi_psram branch from 712c1ed to 7bc7a79 Compare September 3, 2025 13:36
@Ductapemaster
Copy link

Ductapemaster commented Sep 3, 2025

Is there a reason why we are explicitly naming the linker regions in the .ld file rather than letting the device tree label define it? Other boards let me use the label provided directly.

For example, this is a code snippet I use:

     #elif defined(CONFIG_BOARD_MIMXRT1064_EVK)
         __attribute__((section("SDRAM"), aligned(32)))
     #elif defined(CONFIG_BOARD_B_U585I_IOT02A)
         __attribute__((section(".stm32_psram"), aligned(32)))

On the RT1064, there is no associated .ld file in the board config and the section SDRAM is generated automatically. It helpfully matches the section names printed out in the memory + flash summary after a build.

However, on the U585, the name printed out in the memory + flash summary is PSRAM, but the linker region is .stm32_psram as defined in the provided .ld. You cannot link against the section name PSRAM.

Took a bunch of digging to figure out the difference here, and I would suggest using the way Zephyr automatically assigns names over a custom .ld. We plan to replace the code above with device tree macros and it would be helpful to have everything we need to come from there.

@mariopaja mariopaja force-pushed the memc_stm32_ospi_psram branch 2 times, most recently from 7fe13b5 to 26b2866 Compare September 9, 2025 06:05
@JarmouniA
Copy link
Contributor

I would suggest using the way Zephyr automatically assigns names over a custom .ld.

@mariopaja see #95299

@mariopaja mariopaja force-pushed the memc_stm32_ospi_psram branch 2 times, most recently from 6fecc43 to e37608e Compare September 9, 2025 08:05
@mariopaja
Copy link
Contributor Author

mariopaja commented Sep 15, 2025

I would suggest using the way Zephyr automatically assigns names over a custom .ld.

@mariopaja see #95299

It seems like removing .ld does not cause any build issues. I will push the changes once I have tested them

Add a driver for STM32 OSPI PSRAM in memory mapped mode.
Enable OSPI PSRAM on b_u585i_iot02a.

Signed-off-by: Mario Paja <[email protected]>
@mariopaja mariopaja force-pushed the memc_stm32_ospi_psram branch from e37608e to 4371901 Compare September 16, 2025 06:02
Copy link

@Piziwate
Copy link
Contributor

Unfortunately, I’ve found that the provided driver isn’t compatible with the STM32H735 SoC. I’m trying to use the RAM on the stm32h735g_disco. Do you think it would be possible to support it as well?

@mariopaja
Copy link
Contributor Author

mariopaja commented Sep 18, 2025

Hi @Piziwate,
I dont have the HW. I cannot do tests or provide input :/

BTW is uses 128-Mbit HyperRAM™ based on STM32H735G-DK

@Piziwate
Copy link
Contributor

Hi @Piziwate, I dont have the HW. I cannot do tests or provide input :/

BTW is uses 128-Mbit HyperRAM™ based on STM32H735G-DK

Yes, I know—and that’s exactly my problem. This MCU is interesting for our project, and using HyperRAM makes for a simple design. Unfortunately, I’m not quite sure how to integrate it with Zephyr. I thought Octo PSRAM was similar. I tried using the driver from this PR, but I’m getting errors like: ‘error: unknown type name ‘HAL_OSPI_DLYB_CfgTypeDef’.’
I'm happy to run tests, but I have to admit I don't know the STM32 HAL well enough to develop a new driver.

@mariopaja
Copy link
Contributor Author

Yes, I know—and that’s exactly my problem. This MCU is interesting for our project, and using HyperRAM makes for a simple design. Unfortunately, I’m not quite sure how to integrate it with Zephyr. I thought Octo PSRAM was similar. I tried using the driver from this PR, but I’m getting errors like: ‘error: unknown type name ‘HAL_OSPI_DLYB_CfgTypeDef’.’
I'm happy to run tests, but I have to admit I don't know the STM32 HAL well enough to develop a new driver.

I think HAL_OSPI_DLYB_CfgTypeDef is U5xx specific

@Piziwate
Copy link
Contributor

Yes, I know—and that’s exactly my problem. This MCU is interesting for our project, and using HyperRAM makes for a simple design. Unfortunately, I’m not quite sure how to integrate it with Zephyr. I thought Octo PSRAM was similar. I tried using the driver from this PR, but I’m getting errors like: ‘error: unknown type name ‘HAL_OSPI_DLYB_CfgTypeDef’.’
I'm happy to run tests, but I have to admit I don't know the STM32 HAL well enough to develop a new driver.

I think HAL_OSPI_DLYB_CfgTypeDef is U5xx specific

Okay, that makes more sense! In that case, shouldn’t you add a dependency at the Kconfig level to prevent it from being (unsuccessfully) used on other STM32s?

@mariopaja
Copy link
Contributor Author

Yes, I know—and that’s exactly my problem. This MCU is interesting for our project, and using HyperRAM makes for a simple design. Unfortunately, I’m not quite sure how to integrate it with Zephyr. I thought Octo PSRAM was similar. I tried using the driver from this PR, but I’m getting errors like: ‘error: unknown type name ‘HAL_OSPI_DLYB_CfgTypeDef’.’
I'm happy to run tests, but I have to admit I don't know the STM32 HAL well enough to develop a new driver.

I think HAL_OSPI_DLYB_CfgTypeDef is U5xx specific

Okay, that makes more sense! In that case, shouldn’t you add a dependency at the Kconfig level to prevent it from being (unsuccessfully) used on other STM32s?

Perhaps you are right

Copy link
Member

@erwango erwango left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pushing this !

#include <zephyr/device.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/stm32_clock_control.h>
#include <zephyr/drivers/gpio.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look required.

Comment on lines +77 to +78
OSPIM_CfgTypeDef sOspiManagerCfg;
HAL_OSPI_DLYB_CfgTypeDef HAL_OSPI_DLYB_Cfg_Struct;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use zephyr style for new variables

Suggested change
OSPIM_CfgTypeDef sOspiManagerCfg;
HAL_OSPI_DLYB_CfgTypeDef HAL_OSPI_DLYB_Cfg_Struct;
OSPIM_CfgTypeDef ospim_cfg;
HAL_OSPI_DLYB_CfgTypeDef dlyb_cfg;


static int ap_memory_write_reg(OSPI_HandleTypeDef *hospi, uint32_t address, uint8_t *value)
{
OSPI_RegularCmdTypeDef sCommand = {0};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
OSPI_RegularCmdTypeDef sCommand = {0};
OSPI_RegularCmdTypeDef cmd = {0};

uint32_t latency_cycles)
{

OSPI_RegularCmdTypeDef sCommand = {0};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

struct memc_stm32_ospi_psram_data *dev_data = dev->data;
OSPI_HandleTypeDef *hospi = &dev_data->hospi;
OSPI_RegularCmdTypeDef sCommand = {0};
OSPI_MemoryMappedTypeDef sMemMappedCfg = {0};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
OSPI_MemoryMappedTypeDef sMemMappedCfg = {0};
OSPI_MemoryMappedTypeDef mem_mapped_cfg = {0};

Comment on lines +51 to +52
select USE_STM32_HAL_DMA_EX
select USE_STM32_HAL_DMA
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these required by OSPI HAL ?
Otherwise not required

@JarmouniA
Copy link
Contributor

JarmouniA commented Sep 18, 2025

I tried using the driver from this PR, but I’m getting errors like: ‘error: unknown type name ‘HAL_OSPI_DLYB_CfgTypeDef’.’ I'm happy to run tests, but I have to admit I don't know the STM32 HAL well enough to develop a new driver.

@Piziwate As a naive fix, that's unlikely to work correctly, try guarding HAL_OSPI_DLYB.... calls with #ifdef CONFIG_SOC_SERIES_STM32U5X... #endif and modify driver config to select USE_STM32_LL_DLYB if SOC_SERIES_STM32U5X

@mariopaja
Copy link
Contributor Author

Okay, that makes more sense! In that case, shouldn’t you add a dependency at the Kconfig level to prevent it from being (unsuccessfully) used on other STM32s?

@JarmouniA @erwango should I make it U5xx specific, or should I do the following:

As a naive fix, that's unlikely to work correctly, try guarding HAL_OSPI_DLYB.... calls with #ifdef CONFIG_SOC_SERIES_STM32U5X... #endif and modify driver config to select USE_STM32_LL_DLYB if SOC_SERIES_STM32U5X

@erwango
Copy link
Member

erwango commented Sep 18, 2025

IMO , we should focus on U5 for now and expansion to a new series should be kept for a future PR. Otherwise we'll lose ourselves in workarounds

@JarmouniA
Copy link
Contributor

IMO , we should focus on U5 for now and expansion to a new series should be kept for a future PR. Otherwise we'll lose ourselves in workarounds

Then the driver config should have depends on SOC_SERIES_STM32U5X to avoid mis-usage.

Copy link
Contributor

@etienne-lms etienne-lms left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there should be 1 commit for the driver part (incl. the DT bindings addition), 1 for board b_u585i_iot02a and a last one to enable test on that board, which may request to add memc tag in the supported list in the board YAML file. Maybe these 2 last commits could be squashed together.

STM32 OSPI PSRAM memory controller.
Provides a communication interface allowing the microcontroller
to communicate with an external PSRAM memory via the OSPI peripheral.
The PSRAM can be configured as memory mapped and allow read/write
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The PSRAM can be configured as memory mapped and allow read/write
The PSRAM can be configured as memory mapped and allows read/write

#define STM32_OSPI_NODE DT_INST_PARENT(0)

#ifdef CONFIG_SHARED_MULTI_HEAP
struct shared_multi_heap_region smh_psram = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static const?

#define WRITE_CMD 0x8080
/* Read Operations */
#define READ_CMD 0x0000
/* Default dummy clocks cycles */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add an empty line above?

- 4
- 5

refresh-rate:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The property name is a bit ambiguous. How about adaptive-refresh-rate or auto-adjust-refresh-rate?

type: int
default: 0
description: |
Refresh coverage:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For readability (of pasr property name acronym), I would suggest Partial Array Self-Refresh coverage:

device will continually wrap within.
If enabled, the device will burst through the initial wrapped burst length
once, then continue to burst incrementally up to maximum column address
(1K) before wrapping around within the entire column address space
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(1K) before wrapping around within the entire column address space
(1K) before wrapping around within the entire column address space.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants