5.25 SDRAM 使用说明

本章说明 N32H49x 标准外设库中 SDRAM 驱动的文件组成与 24 个公开函数,以及 DataReadWrite、DataReadWrite_DMA 两个示例。SDRAM 控制器负责把外部同步动态存储器映射到芯片的存储空间,供程序直接读写;器件地址、时序、刷新与上电初始化序列需要与所用 SDRAM 颗粒的参数一致,配置原则请配合用户手册的“外部存储器控制器(SDRAM)”章节阅读。

5.25.1 相关文件

相对路径 作用
firmware/n32h49x_std_periph_driver/inc/n32h49x_sdram.h 定义总线宽度、突发长度、CAS 延迟、地址配置等取值,声明 24 个公开函数
firmware/n32h49x_std_periph_driver/src/n32h49x_sdram.c 实现上述 24 个函数:时序与刷新配置、器件地址与使能、总线参数、初始化操作序列
projects/n32h49x_EVAL/examples/SDRAM/ SDRAM 示例根目录,含 DataReadWrite、DataReadWrite_DMA 2 个示例
projects/n32h49x_EVAL/examples/SDRAM/DataReadWrite/ 该示例的工程目录组成:MDK-ARM/、EWARM/、inc/、src/、readme.txt
projects/n32h49x_EVAL/bsp/ 该示例引用的公共板级文件:串口日志与延时函数

5.25.2 API 参考

搜索 API共 24 个函数

以下 24 个公开函数按 n32h49x_sdram.h 的声明顺序分为 4 组;每个条目给出功能摘要与 n32h49x_sdram.c 中该函数正上方的注释原文。

模块与器件基础

SDRAM_DeInit、SDRAM_SetDeviceAddress、SDRAM_EnableDevice、SDRAM_EnableClock、SDRAM_ConfigAddressRemap

时序、刷新与采样

SDRAM_TimingInit、SDRAM_RefreshIntervalInit、SDRAM_ConfigSampleDelay

器件特性

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

初始化操作序列

SDRAM_SetOperationCode、SDRAM_SetDeviceSelect、SDRAM_SetBank、SDRAM_SetAddress、SDRAM_OperationInit、SDRAM_ConfigurationInit

void SDRAM_DeInit(void)将 SDRAM 模块恢复为默认复位值。
源码注释
name    SDRAM_DeInit.
fun     Deinitializes the SDRAM module to their default reset values.
param   none
return  none
void SDRAM_TimingInit(SDRAM_TimingType *Timing)SDRAM 时序寄存器配置。
源码注释
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)配置刷新间隔参数。
源码注释
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 基地址与屏蔽地址。
源码注释
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

使用提示: 源码注释的 name 字段写作 SDRAM_SetAddress.,与函数名 SDRAM_SetDeviceAddress 不一致,按函数名调用即可。

void SDRAM_EnableDevice(SDRAM_DeviceType DeviceNo, FunctionalState Cmd)SDRAM 器件使能。
源码注释
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 刷新。
源码注释
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 自动预充电。
源码注释
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 预取读。
源码注释
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 未命中存储(SOM)。
源码注释
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 存储体交错。
源码注释
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)配置所选器件的 SDRAM 总线宽度。
源码注释
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)配置所选器件的 SDRAM 突发长度。
源码注释
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)配置所选器件的 SDRAM CAS 延迟。
源码注释
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)配置所选器件的 SDRAM 地址。
源码注释
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 时钟使能。
源码注释
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)设置 SDRAM 操作码。
源码注释
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)设置 SDRAM 器件。
源码注释
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)设置 SDRAM 存储体。
源码注释
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)设置 SDRAM 存储体。
源码注释
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)使能所选器件的写保护。
源码注释
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)增大 SDRAM 采样时钟延迟。
源码注释
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.

使用提示: 源码注释的 name 字段写作 SDRAM_ConfigSampleDelay .,与函数名 SDRAM_ConfigSampleDelay 不一致,按函数名调用即可。

void SDRAM_ConfigAddressRemap(uint32_t map_sel)配置 SDRAM1 与 SDRAM2 的地址范围。
源码注释
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)使用预充电所有存储体、自动刷新与加载模式寄存器来初始化 SDRAM。
源码注释
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)配置 SDRAM1 或 SDRAM2 的总线宽度、突发长度、延迟等信息。
源码注释
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 示例说明

本节说明 SDRAM 的 2 个示例:DataReadWrite 以 CPU 逐字读写并回读校验外部 SDRAM,DataReadWrite_DMA 改用 DMA 完成同样的写入与回读。

5.25.3.1 DataReadWrite SDRAM 读写校验

工程目录: projects/n32h49x_EVAL/examples/SDRAM/DataReadWrite/

配置系统与 SDRAM 时钟→把 SDRAM 信号引脚设为复用功能→初始化 SDRAM 器件与时序→向 SDRAM 写入缓冲区数据→回读并逐字比较校验

项目 源码解读
功能 通过 SDRAM 控制器向外部 SDRAM 写入一段数据,再逐字回读比较;
读取数据与写入数据一致时串口打印通过,否则打印不一致的字数。
源码组成 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:头文件;
src/n32h49x_it.c:中断服务函数(仅异常处理);
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 时钟:系统时钟 240 MHz,RCC_ConfigSDRAMClk(RCC_SDRAM_HCLK_DIV3) 使 SDRAM 时钟为 80 MHz,并使能 SDRAM 时钟与 0.5 周期采样延迟;
引脚:地址、数据、BA0/BA1、NCE0、NWE、NRAS、NCAS、DQM0/DQM1、CKE0、CLK 全部复用为 SDRAM 功能;
器件:基地址 0x98000000、地址掩码 0xFF800000,总线宽度 16 位、突发长度 4、CAS 延迟 3、地址配置 SDRAM_BANK4_ROW4096_COL256。
程序与数据路径 main 依次调用 SDRAM_RCC_Configuration、SDRAM_GPIO_Init、SDRAM_DeviceInit;
SDRAM_DeviceInit 先写器件地址、刷新间隔、时序寄存器与配置寄存器,再执行预充电、两次自动刷新与加载模式寄存器;
随后 main 用 0xA244250F 填充写缓冲区并逐个地址写入 SDRAM,再回读与写入比较。
主要 API SDRAM_SetDeviceAddress、SDRAM_RefreshIntervalInit、SDRAM_TimingInit、SDRAM_ConfigurationInit、SDRAM_OperationInit、SDRAM_ConfigSampleDelay
验证方法 编译下载复位运行后,从 USART1(TX PA9、波特率 115200)观察打印;
回读与写入一致时打印 sdram test pass,否则打印 sdram test fail 及不一致的字数。
使用提示 硬件平台为全功能板 N32H497ZGL7_EVB V1.0;
开发环境为 KEIL MDK-ARM 5.34 或 IAR EWARM 8.50.1;
实测使用 SDRAM 型号 M12L64164A(1M×16bit×4Bank,4096 行×256 列);
引脚定义集中在 inc/bsp_sdram.h,移植时按板卡连线修改。
核心代码解读与移植

示例先配置系统与 SDRAM 时钟、把 SDRAM 信号引脚设为复用功能,再初始化 SDRAM 器件参数并执行上电序列,最后写入一段缓冲区并回读比较。

数据路径: SDRAM_RCC_Configuration 使能 GPIO 与 SDRAM 时钟 → SDRAM_GPIO_Init 把信号引脚设为复用 → SDRAM_DeviceInit 写入器件地址、时序与配置并执行上电序列 → main 写入并回读比较缓冲区

1. 配置时钟与采样延迟。 SDRAM_RCC_Configuration 使能 GPIOA~GPIOH 与 AFIO 时钟,把 HCLK 三分频作为 SDRAM 时钟,并使能 SDRAM 时钟与 0.5 周期采样延迟。

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);

SDRAM 时钟由 HCLK 分频得到,RCC_SDRAM_HCLK_DIV3 对应 240 MHz 三分频后的 80 MHz,移植时要保证该频率不超过所用颗粒的限制。

2. 配置器件地址与时序。 SDRAM_DeviceInit 先写入器件基地址与掩码、刷新间隔,再逐项设置行激活时间、行周期等时序寄存器。

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);

地址掩码按容量计算,基地址与掩码一起决定 SDRAM 在存储空间的映射范围;时序取值必须与颗粒手册一致。

3. 执行上电初始化序列。 配置完成后,SDRAM_DeviceInit 依次执行预充电所有存储体、两次自动刷新与加载模式寄存器,并延时至少 300 µs 才能使用。

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);

加载模式寄存器里的突发长度与 CAS 延迟必须和前面的 SDRAM_Configuration 保持一致,否则读写数据会错位。

4. 写入并回读比较。 main 用固定值填充写缓冲区,逐地址写入 SDRAM,延时后回读并统计不一致的字数。

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 为 SDRAM 的访问基地址,每个字占 4 字节,回读地址与写入地址一一对应,比较结果通过 wr_status 统计。

对应源码: src/main.c、src/bsp_sdram.c

5.25.3.2 DataReadWrite_DMA SDRAM DMA 读写校验

工程目录: projects/n32h49x_EVAL/examples/SDRAM/DataReadWrite_DMA/

配置系统与 SDRAM 时钟→初始化 SDRAM 器件与时序→配置 DMA 通道与中断→启动 DMA 写入并等待完成→启动 DMA 回读并逐字比较

项目 源码解读
功能 通过 DMA 把内存缓冲区数据写入外部 SDRAM,再通过 DMA 回读到另一缓冲区;
传输完成后逐字比较,一致时串口打印通过,否则打印不一致的字数。
源码组成 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:头文件;
src/n32h49x_it.c:中断服务函数;
readme.txt:功能、环境与使用说明;
MDK-ARM/、EWARM/:Keil 与 IAR 工程。
关键配置 时钟:系统时钟 240 MHz、SDRAM 时钟 80 MHz,另使能 DMA 时钟;
引脚:SDRAM 信号引脚全部复用为 SDRAM 功能,USART1 TX PA9;
传输:DMA 字宽 32 位、外设与内存地址均自增、普通模式、高优先级、存储器到存储器模式,并配置传输完成中断。
程序与数据路径 main 先做 SDRAM 时钟、引脚与器件初始化,再使能 DMA 时钟并配置两个通道;
DMA 写通道把 tx_buffer 搬到 SDRAM,读通道把 SDRAM 搬回 rx_buffer;
两个通道的传输完成中断分别置位 TX_TransferCompleteFlag、RX_TransferCompleteFlag,main 等待标志后逐字比较。
主要 API SDRAM_ConfigSampleDelay、SDRAM_ConfigurationInit、SDRAM_OperationInit
验证方法 编译下载复位运行后,从 USART1(TX PA9、波特率 115200)观察打印;
回读与写入一致时打印 sdram test DMA pass,否则打印失败计数。
使用提示 硬件平台为全功能板 N32H497ZGL7_EVB V1.0;
开发环境为 KEIL MDK-ARM 5.34 或 IAR EWARM 8.50.1;
存储器到存储器传输需要调用 DMA_RequestRemap 配置保留的请求映射;
SDRAM 型号为 M12L64164A(1M×16bit×4Bank,4096 行×256 列)。
核心代码解读与移植

示例沿用 SDRAM 的时钟、引脚与器件初始化,额外配置两个 DMA 通道,用写通道把缓冲区写入 SDRAM、读通道把 SDRAM 搬回内存,最后由中断标志驱动比较。

数据路径: SDRAM_RCC_Configuration、SDRAM_GPIO_Init、SDRAM_DeviceInit 完成 SDRAM 初始化 → NVIC_Configuration 使能两个 DMA 通道中断 → main 配置并启动 DMA 写通道与读通道 → 传输完成中断置位标志 → main 比较缓冲区

1. 初始化 SDRAM。 与 DataReadWrite 示例一致,先使能 GPIO 与 SDRAM 时钟、把信号引脚设为复用,再写入器件地址、时序与配置并执行上电序列。

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);

移植时保持地址掩码与器件容量一致,时序数值与颗粒手册一致。

2. 配置 DMA 通道。 main 使能 DMA 时钟并配置两个通道:写通道以外设为目的、读通道以外设为源,均按 32 位字传输。

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);

写通道把外设地址设为 SDRAM 基地址、内存地址设为 tx_buffer;读通道只需改方向与外设、内存地址即可复用同一套参数。

3. 启动传输并等待完成。 使能传输完成中断后,main 依次启动写通道与读通道,并分别等待两个中断标志置位。

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++;
        }
    }

传输完成标志在 DMA_TX_IRQ_HANDLER、DMA_RX_IRQ_HANDLER 中置位,等待循环依赖中断回调,移植时要确保对应中断向量已使能。

对应源码: src/main.c、src/bsp_sdram.c

5.25.4 注意与排障

场景 检查与建议 来源
SDRAM 时钟频率 AHB 总线域最高 240 MHz,fSDRAM_CLK 最高 120 MHz;
当 fSDRAM_CLK 大于 80 MHz 时可按需配置 AFIO_ANAEN_CFG4.CLKINVEN 把时钟取反,并提高引脚驱动能力。
用户手册
上电初始化的电源稳定阶段 复位后 CKE 为高、DQM 为高、其余引脚处于非活动状态,须确保该状态至少保持 200 µs 后再进入下一步。 用户手册
突发长度与 CAS 延迟一致性 突发长度等于 64 除以存储器总线宽度;
SDRAM_CFGx 与设备模式寄存器须设置为相同的突发长度,CAS 延迟设置也必须与设备模式寄存器一致。
用户手册
片选地址范围 不要把基地址与地址掩码编程为使片选地址范围与其他 SDRAM 器件重叠的值,重叠区域访问会导致错误操作。 用户手册
刷新间隔寄存器设置 刷新间隔等于刷新周期除以行数再除以内存时钟周期,建议取略低于计算值的余量;
两个器件刷新周期要求不同时取较小值。
用户手册
SDRAM 挂起序列 访问期间不要禁用 SDRAM 器件;
须先清 SDRAMEN 位并等待至少 32 个存储器时钟周期,再刷新写缓冲区并使读缓冲区失效。
用户手册
SDRAM 唤醒序列 须满足最小自刷新时间后退出自刷新,至少发出一个 NOP 命令;
并向所有连接的器件至少发出一个自动刷新命令。
用户手册
国民技术开发套件文档中心

按芯片系列在线查阅国民技术 MCU 开发套件的芯片资料、SDK、驱动 API 与 Demo 示例说明。

© 2026 国民技术股份有限公司 版权所有粤ICP备11069485号本站使用不含 Cookie 的匿名访问统计