5.25 SDRAM Guide

This chapter describes the file composition and 24 public functions of the SDRAM driver in the N32H49x standard peripheral library, together with the DataReadWrite and DataReadWrite_DMA examples. The SDRAM controller maps an external synchronous dynamic memory into the chip address space so that the program can access it directly; the device address, timing, refresh and power-up sequence must match the parameters of the SDRAM part in use, and the configuration rules are described in the “External memory controller (SDRAM)” chapter of the user manual.

5.25.1 Related files

Relative path Purpose
firmware/n32h49x_std_periph_driver/inc/n32h49x_sdram.h Defines the bus width, burst length, CAS latency and address options, and declares the 24 public functions
firmware/n32h49x_std_periph_driver/src/n32h49x_sdram.c Implements the 24 functions above: timing and refresh configuration, device address and enable, bus parameters, and the initialization sequence
projects/n32h49x_EVAL/examples/SDRAM/ SDRAM example root directory, containing the DataReadWrite and DataReadWrite_DMA examples
projects/n32h49x_EVAL/examples/SDRAM/DataReadWrite/ Project directory composition of this example: MDK-ARM/, EWARM/, inc/, src/, readme.txt
projects/n32h49x_EVAL/bsp/ Common board files referenced by this example: the UART log and delay functions

5.25.2 API reference

Search API24 functions

The following 24 public functions are listed in the declaration order of n32h49x_sdram.h in 4 groups; each entry gives a summary and the original comment above the function in n32h49x_sdram.c.

Module and device basics

SDRAM_DeInit, SDRAM_SetDeviceAddress, SDRAM_EnableDevice, SDRAM_EnableClock, SDRAM_ConfigAddressRemap

Timing, refresh and sampling

SDRAM_TimingInit, SDRAM_RefreshIntervalInit, SDRAM_ConfigSampleDelay

Device features

SDRAM_EnableRefreshCMD, SDRAM_EnableAutoPrecharge, SDRAM_EnablePrefetchRead, SDRAM_EnableSOM, SDRAM_EnableBankInterleave, SDRAM_ConfigBusWidth, SDRAM_ConfigBurstLength, SDRAM_ConfigCASLatency, SDRAM_ConfigAddress, SDRAM_EnableWriteProtection

Initialization sequence

SDRAM_SetOperationCode, SDRAM_SetDeviceSelect, SDRAM_SetBank, SDRAM_SetAddress, SDRAM_OperationInit, SDRAM_ConfigurationInit

void SDRAM_DeInit(void)Deinitializes the SDRAM module to their default reset values.
Source comment
name    SDRAM_DeInit.
fun     Deinitializes the SDRAM module to their default reset values.
param   none
return  none
void SDRAM_TimingInit(SDRAM_TimingType *Timing)SDRAM Timing Registers Configuration.
Source comment
name    SDRAM_TimingInit.
fun     SDRAM Timing Registers Configuration.
param   Timing: The parameter range is as follows
            - RowActiveTime       : from 1 to 64
            - RowCycleTime        : from 1 to 64
            - RowActToRowActDelay : from 1 to 64
            - PrechargeTime       : from 1 to 64
            - WriteRecoveryTime   : from 1 to 64
            - RefreshCycleTime    : from 1 to 64
            - RAStoCASDelay       : from 1 to 16
return  none
void SDRAM_RefreshIntervalInit(uint32_t RefreshIntervalTime)Configure the refresh interval parameter.
Source comment
name    SDRAM_RefreshIntervalInit.
fun     Configure the refresh interval parameter.
param   The input parameters must be the following values:
          - RefreshIntervalTime: from 1 to 16777216
return  none
void SDRAM_SetDeviceAddress(SDRAM_DeviceType DeviceNo, uint32_t BaseAddr, uint32_t AddrMask)SDRAM set Base Address and mask address.
Source comment
name    SDRAM_SetAddress.
fun     SDRAM set Base Address and mask address.
param   The input parameters must be the following values:
          - DeviceNo:
               - SDRAM_DEVICE_1
               - SDRAM_DEVICE_2
          - BaseAddr
               - 0xC0000000    Default value for SDRAM1
               - 0xD0000000    Default value for SDRAM2
          - AddrMask
               - (0xFFFFFFFF-(SDRAM SIZE-1))
return  none

Use note: The name field in the source comment is written as SDRAM_SetAddress. and differs from the function name SDRAM_SetDeviceAddress; call it by the function name.

void SDRAM_EnableDevice(SDRAM_DeviceType DeviceNo, FunctionalState Cmd)SDRAM Device enable.
Source comment
name    SDRAM_EnableDevice.
fun     SDRAM Device enable.
param   The input parameters must be the following values:
          - DeviceNo:
               - SDRAM_DEVICE_1
               - SDRAM_DEVICE_2
          - Cmd:
               - ENABLE
               - DISABLE
return  none
void SDRAM_EnableRefreshCMD(SDRAM_DeviceType DeviceNo, FunctionalState Cmd)SDRAM Refresh enable of the selected device.
Source comment
name    SDRAM_EnableRefreshCMD.
fun     SDRAM Refresh enable of the selected device.
param   The input parameters must be the following values:
          - DeviceNo:
               - SDRAM_DEVICE_1
               - SDRAM_DEVICE_2
          - Cmd:
               - ENABLE
               - DISABLE
return  none
void SDRAM_EnableAutoPrecharge(SDRAM_DeviceType DeviceNo, FunctionalState Cmd)SDRAM Auto Precharge enable of the selected device.
Source comment
name    SDRAM_EnableAutoPrecharge.
fun     SDRAM Auto Precharge enable of the selected device.
param   The input parameters must be the following values:
          - DeviceNo:
               - SDRAM_DEVICE_1
               - SDRAM_DEVICE_2
          - Cmd:
               - ENABLE
               - DISABLE
return  none
void SDRAM_EnablePrefetchRead(SDRAM_DeviceType DeviceNo, FunctionalState Cmd)SDRAM Prefetch Read enable of the selected device.
Source comment
name    SDRAM_EnablePrefetchRead.
fun     SDRAM Prefetch Read enable of the selected device.
param   The input parameters must be the following values:
          - DeviceNo:
               - SDRAM_DEVICE_1
               - SDRAM_DEVICE_2
          - Cmd:
               - ENABLE
               - DISABLE
return  none
void SDRAM_EnableSOM(SDRAM_DeviceType DeviceNo, FunctionalState Cmd)SDRAM Store On Miss(SOM) enable of the selected device.
Source comment
name    SDRAM_EnableSOM.
fun     SDRAM Store On Miss(SOM) enable of the selected device.
param   The input parameters must be the following values:
          - DeviceNo:
               - SDRAM_DEVICE_1
               - SDRAM_DEVICE_2
          - Cmd:
               - ENABLE
               - DISABLE
return  none
void SDRAM_EnableBankInterleave(SDRAM_DeviceType DeviceNo, FunctionalState Cmd)SDRAM BankInterleave enable of the selected device.
Source comment
name    SDRAM_EnableBankInterleave.
fun     SDRAM BankInterleave enable of the selected device.
param   The input parameters must be the following values:
          - DeviceNo:
               - SDRAM_DEVICE_1
               - SDRAM_DEVICE_2
          - Cmd:
               - ENABLE
               - DISABLE
return  none
void SDRAM_ConfigBusWidth(SDRAM_DeviceType DeviceNo, uint32_t BusWidth)Configures the SDRAM Bus Width of the selected device.
Source comment
name    SDRAM_ConfigBusWidth.
fun     Configures the SDRAM Bus Width of the selected device.
param   The input parameters must be the following values:
          - DeviceNo:
               - SDRAM_DEVICE_1
               - SDRAM_DEVICE_2
          - BusWidth:
               - SDRAM_DEVICE_BUSWID_8BITS
               - SDRAM_DEVICE_BUSWID_16BITS
               - SDRAM_DEVICE_BUSWID_32BITS
return  none
void SDRAM_ConfigBurstLength(SDRAM_DeviceType DeviceNo, uint32_t BurstLength)Configures the SDRAM Burst Length of the selected device.
Source comment
name    SDRAM_ConfigBurstLength.
fun     Configures the SDRAM Burst Length of the selected device.
param   The input parameters must be the following values:
          - DeviceNo:
               - SDRAM_DEVICE_1
               - SDRAM_DEVICE_2
          - BurstLength:
               - SDRAM_DEVICE_BURSTLEN_1
               - SDRAM_DEVICE_BURSTLEN_2
               - SDRAM_DEVICE_BURSTLEN_4
               - SDRAM_DEVICE_BURSTLEN_8
return  none
void SDRAM_ConfigCASLatency(SDRAM_DeviceType DeviceNo, uint32_t Latency)Configures the SDRAM CAS Latency of the selected device.
Source comment
name    SDRAM_ConfigCASLatency.
fun     Configures the SDRAM CAS Latency of the selected device.
param   The input parameters must be the following values:
          - DeviceNo:
               - SDRAM_DEVICE_1
               - SDRAM_DEVICE_2
          - CASLatency:
               - SDRAM_DEVICE_CASLTCY_0
               - SDRAM_DEVICE_CASLTCY_1
               - SDRAM_DEVICE_CASLTCY_2
               - SDRAM_DEVICE_CASLTCY_3
return  none
void SDRAM_ConfigAddress(SDRAM_DeviceType DeviceNo, uint32_t Address)Configures the SDRAM Address of the selected device.
Source comment
name    SDRAM_ConfigAddress.
fun     Configures the SDRAM Address of the selected device.
param   The input parameters must be the following values:
          - DeviceNo:
               - SDRAM_DEVICE_1
               - SDRAM_DEVICE_2
          - Address:
               - SDRAM_BANK4_ROW4096_COL256
               - SDRAM_BANK4_ROW4096_COL512
               - SDRAM_BANK4_ROW4096_COL1024
               - SDRAM_BANK4_ROW4096_COL2048
               - SDRAM_BANK4_ROW8192_COL256
               - SDRAM_BANK4_ROW8192_COL512
               - SDRAM_BANK4_ROW8192_COL1024
               - SDRAM_BANK4_ROW8192_COL2048
               - SDRAM_BANK4_ROW2048_COL256
               - SDRAM_BANK4_ROW2048_COL512
               - SDRAM_BANK4_ROW2048_COL1024
               - SDRAM_BANK4_ROW2048_COL2048
return  none
void SDRAM_EnableClock(FunctionalState Cmd)SDRAM Clock enable.
Source comment
name    SDRAM_EnableClock.
fun     SDRAM Clock enable.
param   The input parameters must be the following values:
          - Cmd:
               - ENABLE
               - DISABLE
return  none
void SDRAM_SetOperationCode(uint32_t OperationCode)Set the SDRAM Operation Code.
Source comment
name    SDRAM_SetOperationCode.
fun     Set the SDRAM Operation Code.
param   The input parameters must be the following values:
          - OperationCode:
               - SDRAM_OPCODE_NONE
               - SDRAM_OPCODE_PRECHRG
               - SDRAM_OPCODE_REFRESH
               - SDRAM_OPCODE_LOADMODE
return  none
void SDRAM_SetDeviceSelect(uint32_t ChipSelect)Set the SDRAM Device.
Source comment
name    SDRAM_SetDeviceSelect.
fun     Set the SDRAM Device.
param   The input parameters must be the following values:
          - ChipSelect:
               - SDRAM_CS_ALL
               - SDRAM_CS_SDRAM2_ONLY
               - SDRAM_CS_SDRAM1_ONLY
               - SDRAM_CS_NONE
return  none
void SDRAM_SetBank(uint32_t BankNo)Set the SDRAM Bank.
Source comment
name    SDRAM_SetBank.
fun     Set the SDRAM Bank.
param   The input parameters must be the following values:
          - BankNo:
               - SDRAM_BANKADD_1
               - SDRAM_BANKADD_2
               - SDRAM_BANKADD_3
               - SDRAM_BANKADD_4
return  none
void SDRAM_SetAddress(uint32_t Address)Set the SDRAM Bank.
Source comment
name    SDRAM_SetAddress.
fun     Set the SDRAM Bank.
param   The input parameters must be the following values:
          - Address:
return  none
void SDRAM_EnableWriteProtection(SDRAM_DeviceType DeviceNo, FunctionalState Cmd)Write protection enable of the selected device.
Source comment
name    SDRAM_EnableWriteProtection.
fun     Write protection enable of the selected device.
param   The input parameters must be the following values:
          - DeviceNo:
               - SDRAM_DEVICE_1
               - SDRAM_DEVICE_2
          - Cmd:
               - ENABLE
               - DISABLE
return  none
void SDRAM_ConfigSampleDelay(uint32_t CLK_delay)Increase SDRAM sample clock latency.
Source comment
name   SDRAM_ConfigSampleDelay .
fun    Increase SDRAM sample clock latency.
param  CLK_delay
       - SDRAM_DELAY_NONE          Delay bypass
       - SDRAM_DELAY_0_5_PERIOD    Delay 0.5 sdram_clk period
       - SDRAM_DELAY_1_PERIOD      Delay 1 sdram_clk period
       - SDRAM_DELAY_1_5_PERIOD    Delay 1.5 sdram_clk period
       - SDRAM_DELAY_2_PERIOD      Delay 2 sdram_clk period
       - SDRAM_DELAY_2_5_PERIOD    Delay 2.5 sdram_clk period
       - SDRAM_DELAY_3_PERIOD      Delay 3 sdram_clk period
       - SDRAM_DELAY_3_5_PERIOD    Delay 3.5 sdram_clk period
       - SDRAM_DELAY_4_PERIOD      Delay 4 sdram_clk period
return none.

Use note: The name field in the source comment is written as SDRAM_ConfigSampleDelay . and differs from the function name SDRAM_ConfigSampleDelay; call it by the function name.

void SDRAM_ConfigAddressRemap(uint32_t map_sel)Config SDRAM1 and SDRAM2 address range.
Source comment
name    SDRAM_ConfigAddressRemap.
fun     Config SDRAM1 and SDRAM2 address range.
param  map_sel
       - SDRAM1_64MB_SDRAM2_64MB     SDRAM1 range is 0x98000000~0x9BFFFFFF; SDRAM2 range is 0x9C000000~0x9FFFFFFF
       - SDRAM1_128MB_SDRAM2_NONE    SDRAM1 range is 0x98000000~0x9FFFFFFF; SDRAM2 is unavailable
return  none
void SDRAM_OperationInit(SDRAM_OperationInitType SDRAM_OS)Initialization SDRAM using Precharge all banks, auto-refresh and load mode register
Source comment
name    SDRAM_OperationInit.
fun     Initialization SDRAM using Precharge all banks, auto-refresh and load mode register
param   The input parameters must be the following values:
          - SDRAM_OS:
               - ClockEnable:
                   - ENABLE
                   - DISABLE
               - OperationCode:
                   - NO_OPERATION
                   - PRECHARGE_ALL_DEVICE
                   - REFRESH(when ClockEnable = ENABLE is auto refresh; when  ClockEnable = DISABLE is self refresh)
                   - LOAD_MODE_REGISTER
               - ChipSelect:
                   - SDRAM_CS_ALL
                   - SDRAM_CS_SDRAM2_ONLY
                   - SDRAM_CS_SDRAM1_ONLY
                   - SDRAM_CS_NONE
               - BankAddress:
               - Address: load mode register parameters
                   - BurstLen : 3;
                   - BurstType : 1;
                   - CASLatency : 3;
                   - OpMode : 2;
                   - WBMode : 1;
return  none
void SDRAM_ConfigurationInit(SDRAM_DeviceType DeviceNo, SDRAM_ConfigurationInitType SDRAM_CFG)Configure SDRAM1 or 2 bus width, burst length, latency, and other information
Source comment
name    SDRAM_ConfigurationInit.
fun     Configure SDRAM1 or 2 bus width, burst length, latency, and other information
param   The input parameters must be the following values:
          - DeviceNo:
               - SDRAM_DEVICE_1
               - SDRAM_DEVICE_2
          - SDRAM_CFG:
               - SdramEnable:
                   - ENABLE
                   - DISABLE
               - RefreshEnable:
                   - ENABLE
                   - DISABLE
               - AutoPrechargeEnable:
                   - ENABLE
                   - DISABLE
               - PrefetchReadEnable:
                   - ENABLE
                   - DISABLE
               - SOM_Enable:
                   - ENABLE
                   - DISABLE
               - BankInterleavEnable:
                   - ENABLE
                   - DISABLE
               - BusWidth:
                   - SDRAM_DEVICE_BUSWID_8BITS
                   - SDRAM_DEVICE_BUSWID_16BITS
                   - SDRAM_DEVICE_BUSWID_32BITS
               - BurstLength:
                   - SDRAM_DEVICE_BURSTLEN_1
                   - SDRAM_DEVICE_BURSTLEN_2
                   - SDRAM_DEVICE_BURSTLEN_4
                   - SDRAM_DEVICE_BURSTLEN_8
               - CAS_Latency:
                   - SDRAM_DEVICE_CASLTCY_0
                   - SDRAM_DEVICE_CASLTCY_1
                   - SDRAM_DEVICE_CASLTCY_2
                   - SDRAM_DEVICE_CASLTCY_3
               - AddressConfig:
                   - SDRAM_BANK4_ROW4096_COL256
                   - SDRAM_BANK4_ROW4096_COL512
                   - SDRAM_BANK4_ROW4096_COL1024
                   - SDRAM_BANK4_ROW4096_COL2048
                   - SDRAM_BANK4_ROW8192_COL256
                   - SDRAM_BANK4_ROW8192_COL512
                   - SDRAM_BANK4_ROW8192_COL1024
                   - SDRAM_BANK4_ROW8192_COL2048
                   - SDRAM_BANK4_ROW2048_COL256
                   - SDRAM_BANK4_ROW2048_COL512
                   - SDRAM_BANK4_ROW2048_COL1024
                   - SDRAM_BANK4_ROW2048_COL2048
return  none

5.25.3 Demo descriptions

This section describes the two SDRAM examples: DataReadWrite reads and writes the external SDRAM word by word and checks the result, and DataReadWrite_DMA performs the same write and read-back with DMA.

5.25.3.1 DataReadWrite SDRAM read/write check

Example directory: projects/n32h49x_EVAL/examples/SDRAM/DataReadWrite/

Configure the system and SDRAM clocks→Set the SDRAM signal pins to alternate function→Initialize the SDRAM device and timing→Write the buffer data to the SDRAM→Read back word by word and compare

Item Source analysis
Function Writes a block of data to the external SDRAM through the SDRAM controller and reads it back word by word for comparison;
when the read data matches the written data the UART prints a pass message, otherwise it prints the mismatch count.
Source files src/main.c: main, Fill_Buffer_32;
src/bsp_sdram.c: SDRAM_RCC_Configuration, SDRAM_GPIO_Init, SDRAM_DeviceInit;
inc/main.h, inc/bsp_sdram.h, inc/n32h49x_it.h: header files;
src/n32h49x_it.c: interrupt service routines (exception handlers only);
readme.txt: function, environment and usage notes;
MDK-ARM/, EWARM/: Keil and IAR projects.
Key configuration Clock: the system clock is 240 MHz, RCC_ConfigSDRAMClk(RCC_SDRAM_HCLK_DIV3) sets the SDRAM clock to 80 MHz, and the SDRAM clock and a 0.5-period sample delay are enabled;
Pins: address, data, BA0/BA1, NCE0, NWE, NRAS, NCAS, DQM0/DQM1, CKE0 and CLK are all muxed to the SDRAM function;
Device: base address 0x98000000, address mask 0xFF800000, bus width 16 bits, burst length 4, CAS latency 3 and address configuration SDRAM_BANK4_ROW4096_COL256.
Program and data path main calls SDRAM_RCC_Configuration, SDRAM_GPIO_Init and SDRAM_DeviceInit in turn;
SDRAM_DeviceInit first writes the device address, refresh interval, timing registers and configuration register, then runs precharge, two auto-refreshes and load mode register;
main then fills the write buffer with 0xA244250F, writes it word by word to the SDRAM and reads it back for comparison.
Main APIs SDRAM_SetDeviceAddress, SDRAM_RefreshIntervalInit, SDRAM_TimingInit, SDRAM_ConfigurationInit, SDRAM_OperationInit, SDRAM_ConfigSampleDelay
Verification After building, downloading and running, watch the print from USART1 (TX PA9, baud rate 115200);
when the read-back matches the written data it prints sdram test pass, otherwise it prints sdram test fail and the mismatch count.
Use note The hardware platform is the full-featured board N32H497ZGL7_EVB V1.0;
the development environment is KEIL MDK-ARM 5.34 or IAR EWARM 8.50.1;
the example uses SDRAM part M12L64164A (1M×16bit×4Bank, 4096 rows×256 columns);
the pin definitions are collected in inc/bsp_sdram.h, which must be adapted to the board wiring when porting.
Core-code walkthrough and porting

The example first configures the system and SDRAM clocks and sets the SDRAM signal pins to alternate function, then initializes the SDRAM device parameters and runs the power-up sequence, and finally writes a buffer and reads it back for comparison.

Data path: SDRAM_RCC_Configuration enables the GPIO and SDRAM clocks → SDRAM_GPIO_Init sets the signal pins to alternate function → SDRAM_DeviceInit writes the device address, timing and configuration and runs the power-up sequence → main writes and reads back the buffer

1. Configure the clock and sample delay. SDRAM_RCC_Configuration enables the GPIOA to GPIOH and AFIO clocks, uses HCLK divided by three as the SDRAM clock, and enables the SDRAM clock and a 0.5-period sample delay.

src/bsp_sdram.csrc/bsp_sdram.c · SDRAM_RCC_Configuration
    /* Enable GPIO clock*/
    RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOA|RCC_AHB_PERIPHEN_GPIOB|RCC_AHB_PERIPHEN_GPIOC|RCC_AHB_PERIPHEN_GPIOD, ENABLE);;
    RCC_EnableAHB1PeriphClk(RCC_AHB_PERIPHEN_GPIOE|RCC_AHB_PERIPHEN_GPIOF|RCC_AHB_PERIPHEN_GPIOG|RCC_AHB_PERIPHEN_GPIOH, ENABLE);
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPHEN_AFIO, ENABLE);

    /* hclk = 240M, sdram_clk = 80M */
    RCC_ConfigSDRAMClk(RCC_SDRAM_HCLK_DIV3);
    /* Enable SDRAM clock*/
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPHEN_SDRAM, ENABLE);
    /* Enable SDRAM clock delay*/
    SDRAM_ConfigSampleDelay(SDRAM_DELAY_0_5_PERIOD);

The SDRAM clock is derived from HCLK; RCC_SDRAM_HCLK_DIV3 gives 80 MHz from the 240 MHz HCLK, and when porting make sure this frequency stays within the limit of the part in use.

2. Configure the device address and timing. SDRAM_DeviceInit first writes the device base address and mask and the refresh interval, then sets the row-active and row-cycle timing registers.

src/bsp_sdram.csrc/bsp_sdram.c · SDRAM_DeviceInit
     /* Set SDRAM address: BaseAddr = 0x98000000, AddrMask = 0xFFFFFFFF-(SDRAMSIZI-1)*/
    SDRAM_SetDeviceAddress(SDRAM_DEVICE_1, 0x98000000, 0xFF800000);//AddrMask=0xFFFFFFFF-(8Mbyte-1)
    /* Set SDRAM Refresh Interval=(Refresh Period / Number of Rows / Mem clock Period)*/
    SDRAM_RefreshIntervalInit(0x4A0);//64000000ns/4096rows/(1/80M=12.5)ns =0x4E2,whichever is smaller

    /* Set SDRAM Timing registers*/
    /* Needs to be consistent with SDRAM device characteristics */
    SDRAM_Timing.RowActiveTime       = 0x7;
    SDRAM_Timing.RowCycleTime        = 0x9;
    SDRAM_Timing.RowActToRowActDelay = 0x3;
    SDRAM_Timing.PrechargeTime       = 0x4;
    SDRAM_Timing.WriteRecoveryTime   = 0x3;
    SDRAM_Timing.RefreshCycleTime    = 0x9;
    SDRAM_Timing.RAStoCASDelay       = 0x4;
    SDRAM_TimingInit(&SDRAM_Timing);

The address mask follows the capacity; the base address and mask together decide the address range the SDRAM occupies, and the timing values must match the part datasheet.

3. Run the power-up initialization sequence. After configuration, SDRAM_DeviceInit runs precharge-all-banks, two auto-refreshes and load mode register, and then delays at least 300 µs before the device can be used.

src/bsp_sdram.csrc/bsp_sdram.c · SDRAM_DeviceInit
    /* Precharge all banks, auto-refresh, load mode register */
    /* Precharge all banks */
    SDRAM_Operation.ClockEnable   = ENABLE;
    SDRAM_Operation.OperationCode = SDRAM_OPCODE_PRECHRG;
    SDRAM_Operation.ChipSelect    = SDRAM_CS_SDRAMx;
    SDRAM_Operation.BankAddress   = SDRAM_BANKADD_1;
    SDRAM_Operation.Address.cmd   = 0x00;
    SDRAM_OperationInit(SDRAM_Operation);

    /* auto-refresh */
    for(uint8_t i = 0; i < 2; i++)
    {
        SDRAM_Operation.ClockEnable   = ENABLE;
        SDRAM_Operation.OperationCode = SDRAM_OPCODE_REFRESH;
        SDRAM_Operation.ChipSelect    = SDRAM_CS_SDRAMx;
        SDRAM_Operation.BankAddress   = SDRAM_BANKADD_1;
        SDRAM_Operation.Address.cmd   = 0x00;
        SDRAM_OperationInit(SDRAM_Operation);
    }

    /* load mode register */
    SDRAM_Operation.ClockEnable   = ENABLE;
    SDRAM_Operation.OperationCode = SDRAM_OPCODE_LOADMODE;
    SDRAM_Operation.ChipSelect    = SDRAM_CS_SDRAMx;
    SDRAM_Operation.BankAddress   = SDRAM_BANKADD_1;
    SDRAM_Operation.Address.Bits.BurstLen = LOADMODE_BURSTLEN_4;
    SDRAM_Operation.Address.Bits.BurstType = LOADMODE_BURSTTYP_SEQUENTIAL;
    SDRAM_Operation.Address.Bits.CASLatency = LOADMODE_CASLATENCY_3;
    SDRAM_Operation.Address.Bits.OpMode = LOADMODE_STANDARD;
    SDRAM_Operation.Address.Bits.WBMode = LOADMODE_WRITE_BURST;
    SDRAM_OperationInit(SDRAM_Operation);

    /* wait at least 300us*/
    systick_delay_us(500);

The burst length and CAS latency in the mode register must match the earlier SDRAM_Configuration, otherwise read and write data will be misaligned.

4. Write and read back for comparison. main fills the write buffer with a fixed value, writes it address by address, and after a delay reads it back and counts the mismatches.

src/main.csrc/main.c · main
    /* Fill the buffer to write */
    Fill_Buffer_32(tx_buffer, BUFFER_SIZE, 0xA244250F);

    /* Fill the Read buffer */
    Fill_Buffer_32(rx_buffer, BUFFER_SIZE, 0xAAAAAAAA);

    log_info("write to sdram\r\n");
    /* Write data to the SDRAM memory */
    for (index = 0; index < BUFFER_SIZE; index++)
    {
        *(__IO uint32_t*) (SDRAM_ACCESS_BASEADD + WRITE_READ_ADDR + 4*index) = tx_buffer[index];
    }

    for(uint32_t delaytime = 0; delaytime < 10000; delaytime++);

    /* Read back data from the SDRAM memory */
    log_info("read back from sdram\r\n");
    for (index = 0; index < BUFFER_SIZE; index++)
    {
        rx_buffer[index] = *(__IO uint32_t*) (SDRAM_ACCESS_BASEADD + WRITE_READ_ADDR + 4*index);
    }

SDRAM_ACCESS_BASEADD is the SDRAM access base address and each word occupies four bytes, so read-back addresses correspond one-to-one to written addresses and the result is counted in wr_status.

Corresponding source files: src/main.c, src/bsp_sdram.c

5.25.3.2 DataReadWrite_DMA SDRAM DMA read/write check

Example directory: projects/n32h49x_EVAL/examples/SDRAM/DataReadWrite_DMA/

Configure the system and SDRAM clocks→Initialize the SDRAM device and timing→Configure the DMA channels and interrupts→Start the DMA write and wait for completion→Start the DMA read-back and compare

Item Source analysis
Function Writes a memory buffer to the external SDRAM with DMA and reads it back into another buffer with DMA;
after the transfer it compares word by word, printing a pass message on match or the mismatch count otherwise.
Source files src/main.c: main, Fill_Buffer_32, NVIC_Configuration, DMA_TX_IRQ_HANDLER, DMA_RX_IRQ_HANDLER;
src/bsp_sdram.c: SDRAM_RCC_Configuration, SDRAM_GPIO_Init, SDRAM_DeviceInit;
inc/main.h, inc/bsp_sdram.h, inc/n32h49x_it.h: header files;
src/n32h49x_it.c: interrupt service routines;
readme.txt: function, environment and usage notes;
MDK-ARM/, EWARM/: Keil and IAR projects.
Key configuration Clock: system clock 240 MHz, SDRAM clock 80 MHz, and the DMA clock enabled;
Pins: the SDRAM signal pins are all muxed to the SDRAM function, USART1 TX PA9;
Transfer: DMA word width 32 bits, peripheral and memory addresses both incremented, normal mode, high priority and memory-to-memory mode, with the transfer-complete interrupt enabled.
Program and data path main first initializes the SDRAM clock, pins and device, then enables the DMA clock and configures the two channels;
the DMA write channel moves tx_buffer to the SDRAM and the read channel moves the SDRAM back to rx_buffer;
the transfer-complete interrupts set TX_TransferCompleteFlag and RX_TransferCompleteFlag, and main waits for the flags and compares word by word.
Main APIs SDRAM_ConfigSampleDelay, SDRAM_ConfigurationInit, SDRAM_OperationInit
Verification After building, downloading and running, watch the print from USART1 (TX PA9, baud rate 115200);
when the read-back matches the written data it prints sdram test DMA pass, otherwise it prints the mismatch count.
Use note The hardware platform is the full-featured board N32H497ZGL7_EVB V1.0;
the development environment is KEIL MDK-ARM 5.34 or IAR EWARM 8.50.1;
a memory-to-memory transfer requires DMA_RequestRemap to set the reserved request mapping;
the SDRAM part is M12L64164A (1M×16bit×4Bank, 4096 rows×256 columns).
Core-code walkthrough and porting

The example reuses the SDRAM clock, pin and device initialization, adds two DMA channels, uses the write channel to move a buffer to the SDRAM and the read channel to move the SDRAM back to memory, and finally compares under interrupt-flag control.

Data path: SDRAM_RCC_Configuration, SDRAM_GPIO_Init and SDRAM_DeviceInit complete the SDRAM initialization → NVIC_Configuration enables the two DMA channel interrupts → main configures and starts the DMA write and read channels → the transfer-complete interrupts set the flags → main compares the buffers

1. Initialize the SDRAM. As in the DataReadWrite example, the example first enables the GPIO and SDRAM clocks and sets the signal pins to alternate function, then writes the device address, timing and configuration and runs the power-up sequence.

src/bsp_sdram.csrc/bsp_sdram.c · SDRAM_DeviceInit
     /* Set SDRAM address: BaseAddr = 0x98000000, AddrMask = 0xFFFFFFFF-(SDRAMSIZI-1)*/
    SDRAM_SetDeviceAddress(SDRAM_DEVICE_1, 0x98000000, 0xFF800000);//AddrMask=0xFFFFFFFF-(8Mbyte-1)
    /* Set SDRAM Refresh Interval=(Refresh Period / Number of Rows / Mem clock Period)*/
    SDRAM_RefreshIntervalInit(0x4A0);//64000000ns/4096rows/(1/80M=12.5)ns =0x4E2,whichever is smaller

    /* Set SDRAM Timing registers*/
    /* Needs to be consistent with SDRAM device characteristics */
    SDRAM_Timing.RowActiveTime       = 0x7;
    SDRAM_Timing.RowCycleTime        = 0x9;
    SDRAM_Timing.RowActToRowActDelay = 0x3;
    SDRAM_Timing.PrechargeTime       = 0x4;
    SDRAM_Timing.WriteRecoveryTime   = 0x3;
    SDRAM_Timing.RefreshCycleTime    = 0x9;
    SDRAM_Timing.RAStoCASDelay       = 0x4;
    SDRAM_TimingInit(&SDRAM_Timing);

When porting, keep the address mask consistent with the device capacity and the timing values consistent with the datasheet.

2. Configure the DMA channels. main enables the DMA clock and configures the two channels: the write channel targets the peripheral and the read channel sources from it, both transferring 32-bit words.

src/main.csrc/main.c · main
    /* Enable DMA x clock */
    RCC_EnableAHBPeriphClk(DMA_CLK, ENABLE);
    /* NVIC configuration */
    NVIC_Configuration();

    /* Fill the buffer to write */
    Fill_Buffer_32(tx_buffer, BUFFER_SIZE, 0xA244250F);

    /* Fill the Read buffer */
    Fill_Buffer_32(rx_buffer, BUFFER_SIZE, 0xAAAAAAAA);

    /* DMA x channel y configuration */
    DMA_DeInit(DMA_TX_CHANNEL_USED);
    DMA_StructInit(&DMA_InitStructure);
    DMA_InitStructure.PeriphAddr     = (uint32_t)SDRAM_ACCESS_BASEADD;
    DMA_InitStructure.MemAddr        = (uint32_t)tx_buffer;
    DMA_InitStructure.Direction      = DMA_DIR_PERIPH_DST;
    DMA_InitStructure.BufSize        = BUFFER_SIZE;
    DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_ENABLE;
    DMA_InitStructure.MemoryInc      = DMA_MEM_INC_ENABLE;
    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_WIDTH_WORD;
    DMA_InitStructure.MemDataSize    = DMA_MEM_DATA_WIDTH_WORD;
    DMA_InitStructure.CircularMode   = DMA_MODE_NORMAL;
    DMA_InitStructure.Priority       = DMA_PRIORITY_HIGH;
    DMA_InitStructure.Mem2Mem        = DMA_M2M_ENABLE;
    DMA_Init(DMA_TX_CHANNEL_USED, &DMA_InitStructure);

The write channel sets the peripheral address to the SDRAM base address and the memory address to tx_buffer; the read channel only changes the direction and the peripheral and memory addresses.

3. Start the transfers and wait for completion. After enabling the transfer-complete interrupts, main starts the write and read channels and waits for the two interrupt flags.

src/main.csrc/main.c · main
    /* Enable DMA x Channel y Transfer Complete interrupt */
    DMA_ConfigInt(DMA_TX_CHANNEL_USED, DMA_INT_TXC, ENABLE);
    DMA_ConfigInt(DMA_RX_CHANNEL_USED, DMA_INT_TXC, ENABLE);

    log_info("write to sdram\r\n");
    /* Enable DMA x Channel y transfer */
    DMA_EnableChannel(DMA_TX_CHANNEL_USED, ENABLE);
    /* Wait the end of transmission */
    while (TX_TransferCompleteFlag == 0)
    {
    }

    log_info("read back from sdram\r\n");
    /* Enable DMA x Channel y transfer */
    DMA_EnableChannel(DMA_RX_CHANNEL_USED, ENABLE);
    /* Wait the end of transmission */
    while (RX_TransferCompleteFlag == 0)
    {
    }

    /* Read back SDRAM memory and check content correctness */
    for (index = 0x00; index < BUFFER_SIZE; index++)
    {
        if (rx_buffer[index] != tx_buffer[index])
        {
            wr_status++;
        }
    }

The transfer-complete flags are set in DMA_TX_IRQ_HANDLER and DMA_RX_IRQ_HANDLER; the wait loops depend on these interrupt callbacks, so make sure the corresponding interrupt vectors are enabled when porting.

Corresponding source files: src/main.c, src/bsp_sdram.c

5.25.4 Notes and troubleshooting

Scenario Check & action Source
SDRAM clock frequency The maximum AHB clock is 240 MHz and the maximum fSDRAM_CLK is 120 MHz;
when fSDRAM_CLK is above 80 MHz, configure AFIO_ANAEN_CFG4.CLKINVEN to invert the clock as needed and raise the pin drive strength.
User manual
Power stabilization before power-up init After reset CKE is high, DQM is high and the other pins are inactive, and this state must be held for at least 200 µs before the next step. User manual
Burst length and CAS latency match The burst length equals 64 divided by the memory bus width;
SDRAM_CFGx and the device mode register must use the same burst length, and the CAS latency must match the device mode register.
User manual
Chip-select address range Do not program the base address and address mask so that the chip-select range overlaps another SDRAM device;
accesses to an overlapping region cause incorrect operation.
User manual
Refresh interval register The refresh interval equals the refresh period divided by the number of rows and then by the memory clock period, and should be set slightly below the computed value for margin;
when the two devices require different refresh periods, use the smaller one.
User manual
SDRAM suspend sequence Do not disable the SDRAM device while it is being accessed;
first clear SDRAMEN and wait at least 32 memory clock cycles, then refresh the write buffer and invalidate the read buffer.
User manual
SDRAM wake-up sequence Exit self-refresh only after the minimum self-refresh time is met, issuing at least one NOP command;
and issue at least one auto-refresh command to all connected devices.
User manual
Nations Technologies DevKit Docs

Datasheets, SDK, driver APIs and demo guides for Nations Technologies MCU development kits, organized by chip series.

© 2026 Nations Technologies Inc. All rights reserved.粤ICP备11069485号This site uses cookie-free anonymous analytics.