Skip to main content
Visitor II
March 25, 2025
Solved

extremely slow sdram read write performance

  • March 25, 2025
  • 1 reply
  • 834 views

Hi,

I am using STM32H563ZI to design a new product, there is a SDRAM(W9825G6KH-6) connected to the MCU with 16bit width bus. The SDCLK is 125MHz while the MCU running at 250MHz.  The read and write to SDRAM address space are both OK. But the read write performance is extremely slow, roughly 11MB/s for read and 14MB/s for write. I had configured the MPU and I-Cache/D-cache,

 

The speed is unsatisfied and unbelievable because I had a board with STM32H750 and the same SDRAM (SDCLK running at 100MHz, 16bit bus width), both read and write speed are around 100MB/s with cache on.

 

Could anyone give me some hints?

 

mpu_attributes.png

mpu_regions.png

fmc_sdram_config.png

    This topic has been closed for replies.
    Best answer by mƎALLEm

    I don't know how CubeMx generated that code but to me the region N3 was set after N4. So the attributes that was set to the region 3 was net set for the region 4.

    So in your MPU region 4 config add manually the MPU attribute as for the region 3 and test.

    1 reply

    Technical Moderator
    March 25, 2025

    Hello,

    1- STM32H750 is running at the same frequency as STM32H5: 250MHz?

    2- Did you set the same SDRAM timing for both?

    3- The SDRAM address region is located at 0xC000 0000 to 0xDFFF FFFF:  

    RM0481:

    mALLEm_0-1742890799716.png

    Which is a Non-cacheable region by default:

    PM0264:

    mALLEm_1-1742890928052.png

    You said you configured the MPU, but did you set the SDRAM region as cacheable?

    jasonj2Author
    Visitor II
    March 25, 2025

    1- STM32H750 is running at the same frequency as STM32H5: 250MHz?

    no, STM32H750 is running at 400Mhz, the STM32H5 running at 250MHz. Also I had changed the clock of STM32H5 to 200Mhz to make SDCLK at 100Mhz. The results are roughly the same. The SDRAM read write speed should not had so much differences.

    2- Did you set the same SDRAM timing for both?

    yes. Here is the timing data.

    // SDRAM clk = 100MHz, 10ns
    // Exit Self-Refresh Delay, TXSR = 72ns, 8clk
    // Self-Refresh Time, TRAS = 42ns, 5clk
    // Common Row Cycle Delay, TRC = 60ns, 6clk
    // Common Row Precharge Delay, TRP = 15ns, 2clk
    // Row to Column Delay, TRCD = 15ns, 2clk
    // Write Recovery Time, TWR = 2
    //
    // 8192 rows, refresh rate = 64ms/8192 = 7.81us
    // refresh counter = (7.81 * 100) - 20 = 761

    3- The SDRAM address region is located at 0xC000 0000 to 0xDFFF FFFF:  

    I use SDRAM bank2 on STM32H5, I think the base address is 0xD000_0000.

    -------------------------------------------------------------------------------------------------------------------

    I tried to disable MPU, the SDRAM read/write speed looks boost to 21MB/s for read and 23MB/s for write. But it still not good enough.

    while when MPU is enabled, the SDRAM read/write speed looks boost to 11MB/s for read and 11MB/s for write.

    -------------------------------------------------------------------------------------------------------------------

    Here is the MPU_Config(), I referred AN4838 Table 9 to set MPU regions for internal SRAM, internal Flash, and Peripherals. MPU region 4 and MPU attribute 3 are used for SDRAM (0xD000_0000 to 0xD1FFF_FFFF). The region is set to instruction disable,  inner-sharable, normal-cachable, write-back, transit, and rw-allocate.

    void MPU_Config(void)
    {
     MPU_Region_InitTypeDef MPU_InitStruct = {0};
     MPU_Attributes_InitTypeDef MPU_AttributesInit = {0};
    
     /* Disables the MPU */
     HAL_MPU_Disable();
    
     /** Initializes and configures the Region 0 and the memory to be protected
     */
     MPU_InitStruct.Enable = MPU_REGION_ENABLE;
     MPU_InitStruct.Number = MPU_REGION_NUMBER0;
     MPU_InitStruct.BaseAddress = 0x20000000;
     MPU_InitStruct.LimitAddress = 0x2009FFFF;
     MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
     MPU_InitStruct.AccessPermission = MPU_REGION_ALL_RW;
     MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
     MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
    
     HAL_MPU_ConfigRegion(&MPU_InitStruct);
    
     /** Initializes and configures the Region 1 and the memory to be protected
     */
     MPU_InitStruct.Number = MPU_REGION_NUMBER1;
     MPU_InitStruct.BaseAddress = 0x08000000;
     MPU_InitStruct.LimitAddress = 0x081FFFFF;
     MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER1;
    
     HAL_MPU_ConfigRegion(&MPU_InitStruct);
    
     /** Initializes and configures the Region 2 and the memory to be protected
     */
     MPU_InitStruct.Number = MPU_REGION_NUMBER2;
     MPU_InitStruct.BaseAddress = 0x40000000;
     MPU_InitStruct.LimitAddress = 0x5FFFFFFF;
     MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER2;
     MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
    
     HAL_MPU_ConfigRegion(&MPU_InitStruct);
    
     /** Initializes and configures the Region 3 and the memory to be protected
     */
     MPU_InitStruct.Number = MPU_REGION_NUMBER3;
     MPU_InitStruct.BaseAddress = 0x80000000;
     MPU_InitStruct.LimitAddress = 0x8FFFFFFF;
     MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
    
     HAL_MPU_ConfigRegion(&MPU_InitStruct);
    
     /** Initializes and configures the Region 4 and the memory to be protected
     */
     MPU_InitStruct.Number = MPU_REGION_NUMBER4;
     MPU_InitStruct.BaseAddress = 0xD0000000;
     MPU_InitStruct.LimitAddress = 0xD1FFFFFF;
     MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER3;
     MPU_InitStruct.IsShareable = MPU_ACCESS_INNER_SHAREABLE;
    
     HAL_MPU_ConfigRegion(&MPU_InitStruct);
    
     /** Initializes and configures the Region 7 and the memory to be protected
     */
     MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
     HAL_MPU_ConfigRegion(&MPU_InitStruct);
    
     /** Initializes and configures the Attribute 0 and the memory to be protected
     */
     MPU_AttributesInit.Number = MPU_ATTRIBUTES_NUMBER0;
     MPU_AttributesInit.Attributes = INNER_OUTER(MPU_NOT_CACHEABLE);
    
     HAL_MPU_ConfigMemoryAttributes(&MPU_AttributesInit);
    
     /** Initializes and configures the Attribute 1 and the memory to be protected
     */
     MPU_AttributesInit.Number = MPU_ATTRIBUTES_NUMBER1;
     MPU_AttributesInit.Attributes = INNER_OUTER(MPU_WRITE_THROUGH|MPU_TRANSIENT
     |MPU_NO_ALLOCATE);
    
     HAL_MPU_ConfigMemoryAttributes(&MPU_AttributesInit);
    
     /** Initializes and configures the Attribute 2 and the memory to be protected
     */
     MPU_AttributesInit.Number = MPU_ATTRIBUTES_NUMBER2;
     MPU_AttributesInit.Attributes = MPU_DEVICE_nGnRE;
    
     HAL_MPU_ConfigMemoryAttributes(&MPU_AttributesInit);
    
     /** Initializes and configures the Attribute 3 and the memory to be protected
     */
     MPU_AttributesInit.Number = MPU_ATTRIBUTES_NUMBER3;
     MPU_AttributesInit.Attributes = INNER_OUTER(MPU_WRITE_BACK|MPU_TRANSIENT
     |MPU_RW_ALLOCATE);
    
     HAL_MPU_ConfigMemoryAttributes(&MPU_AttributesInit);
     /* Enables the MPU */
     HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
    }

     

     

    Technical Moderator
    March 25, 2025

    1- For the performance comparison you need to set the system at the same config (compare like with like): same clock, same timings etc ..

    2- As I can see, you didn't set the region 0xDxxx xxxx cacheable:

     /** Initializes and configures the Region 4 and the memory to be protected
     */
     MPU_InitStruct.Number = MPU_REGION_NUMBER4;
     MPU_InitStruct.BaseAddress = 0xD0000000;
     MPU_InitStruct.LimitAddress = 0xD1FFFFFF;
     MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER3;
     MPU_InitStruct.IsShareable = MPU_ACCESS_INNER_SHAREABLE;
    
     HAL_MPU_ConfigRegion(&MPU_InitStruct);

    You didn't set the parameter MPU_AttributesInit.Attributes for that region to be cacheable and you didn't set it before. So 0xDxxx xxxx still not cacheable.