NXP

RT1052 SEMC控制

2019-07-12 11:51发布

SEMC

Smart External Memory Controller
它可以用于驱动包括SRAM、SDRAM、
NorFlash、NAND Flash 等类型的存储器以及使用8080 接口协议(DBI 接口)的显示器和设备
SEMC 控制逻辑块

通讯引脚

SEMC引脚名称 对应SDRAM引脚名 说明 SEMC_DM[1:0] LDQM,UDQM 数据掩码信号 SEMC_ADDR[12:0] A[12:0] 行/列地址线 SEMC_BA[1:0] BS[1:0] Bank地址线 SEMC_DA[15:0] DQ[15:0] 数据线 SEMC_CLK CLK 同步时钟信号 SEMC_WE WE# 写入使能 SEMC_CKE CKE 时钟使能信号 SEMC_CS0 CS# 芯片的片选信号 SEMC_CSX [3:0] 同上 同上 SEMC_RAS RAS# 行地址选通信号 SEMC_CAS CAS# 列地址选通信号 SEMC_DQS - 数据选通信号

SEMC_CS/CSX

  • 片选信号
  • SEMC 外设把SDRAM的控制分成了Region#0/1/2/3 四个区域
    • 每个区域有一个对应的片选信号CS0/1/2/3
    • 访问某一个区域的时候,对应的片选信号使能外部SDRAM
  • RT1052 提供了可软件定制信号的引脚SEMC_CSX0/1/2/3
    • 它们中的任意一个引脚都可以“变形”成CS1/2/3 中的任意一个信号(实际上还可以设置成NAND Flash 等存储设备的片选信号)
    • 而CS0 片选信号只能使用SEMC_CS0 引脚
对应的SDRAM存储区域 片选信号 具体可以使用的RT1052引脚 Region#0 CS0 SEMC_CS0 Region#1 CS1 SEMC_CSX[3:0]任一引脚 Region#2 CS2 SEMC_CSX[3:0]任一引脚 Region#3 CS3 SEMC_CSX[3:0]任一引脚
  • 假如使用Region#0区域控制SDRAM。则必须使用SEMC_CS0引脚
  • 若是使用Region#1区域控制SDRAM。则可以从SEMC_CSX[3:0]中任选一引脚
    • 然后在寄存器上配置即可。

IP 命令和AXI 命令

  • FlexSPI 拥有IP命令与AHB命令
  • SEMC 拥有IP命令与AXI命令两种格式
    • Advanced eXtensible Interface
    • AXI 属于 ARM 公司 AMBA协议的一部分

IP命令

  • IP 命令访问实际上就是通过向相应的寄存器写入配置。不用做数据传输,仅用作参数的配置
  • SEMC_SendIPCommand函数是NXP提供的库函数。用来初始化SEMC
    • SEMC_SendIPCommand 被封装在 SEMC_ConfigureSDRAM函数里面了

AXI 命令

  • 0x8000 0000~0xDFFF FFFF 的1.5GB 空间是分配给SEMC 的外部
    存储器的映射区域
  • SEMC 控制的SDRAM、NOR、 PSRAM、NAND 以及 8080 接口的设备共用该空间,在初始化存储设备参数的时候可在该区域指定具体映射的基地址
    • 例如指定SDRAM使用0x8000 0000 作为基地址,NAND Flash 使用0x9000 0000 作为基地址。
  • AXI命令 只能触发对外部存储器的读写访问,其它控制指令只能通过IP 命令的方式发送。

初始化使用IP命令,读写使用AHB命令

SEMC驱动时钟

  • SEMC_CLKSEMC_CLK_ROOT提供
    SEMC Clock block
  • SEMC设备拥有3个可选时钟来源
    • PLL2 PFD2 :该时钟常规配置为396MHz,fireGe配置为316.8MHz
    • PLL3 PFD1 :该时钟常规配置为454.74MHz
    • PERIPH CLK :AHB_CLK_ROOT 的时钟源。PERIPH CLK 分频后得到AHB_CLK_ROOT
      • SEMC 也可以使用这个时钟源AHB_CLK_ROOT
  • 选择得到的时钟源经过一个3 位的分频器,它可对时钟进行1~8 分频,分频后得到
    SEMC 根时钟SEMC_CLK_ROOT。

NXP提供的库函数

_semc_config_t结构

//fsl_semc.h typedef struct _semc_config_t { semc_dqs_mode_t dqsMode; /*!< Dummy read strobe mode: use enum in "semc_dqs_mode_t". */ uint8_t cmdTimeoutCycles; /*!< Command execution timeout cycles. */ uint8_t busTimeoutCycles; /*!< Bus timeout cycles. */ semc_axi_queueweight_t queueWeight; /*!< AXI queue weight. */ } semc_config_t;

_semc_sdram_config结构

typedef struct _semc_sdram_config{ ... sem_sdram_burst_len_t burstLen;//突发长度 在 014-SDRAM.md中有提到 ... semc_caslatency_t casLatency; //选通延迟 只有读时才有。写时不存在 uint8_t tPrecharge2Act_Ns;//预充电到行有效或刷新命令之间的延迟 即tRP uint8_t tAct2ReadWrite_Ns; //active 与读写之间的延迟 即tRCD参数 uint8_t tRefreshRecovery_Ns;//配置刷新命令(REFRESH) 到行有效命令(ACTIVE)间的延迟,tRFC 和 tXSR uint8_t tWriteRecovery_Ns;// 写恢复时间 ... uint8_t tCkeOff_Ns; //CKE off minimum time uint8_t tAct2Prechage_Ns; // Active to precharge 即 tRAS ...

SEMC配置

semc_config_t config; semc_sdram_config_t sdramconfig; SEMC_GetDefaultConfig(&config); SEMC_Init(SEMC, &config); .../*sdramconfig 结构配置*/ SEMC_ConfigureSDRAM(SEMC, kSEMC_SDRAM_CS0, &sdramconfig, clockFrq); 这段程序就是获得SEMC默认配置。然后初始化sdramconfig结构。SEMC_ConfigureSDRAM函数将configsdramconfig绑定起来。

SDRAM初始化

status_t SEMC_ConfigureSDRAM(SEMC_Type *base, semc_sdram_cs_t cs, semc_sdram_config_t *config, uint32_t clkSrc_Hz) { ... result = SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, kSEMC_SDRAMCM_Prechargeall, 0, NULL);//发送IP命令 SDRAM precharge all result = SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, kSEMC_SDRAMCM_AutoRefresh, 0, NULL);// SDRAM auto-refresh result = SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, kSEMC_SDRAMCM_AutoRefresh, 0, NULL);// SDRAM auto-refresh ... result = SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address, kSEMC_SDRAMCM_Modeset, mode, NULL);// SDRAM MODE SET /* Enables refresh */ base->SDRAMCR3 |= SEMC_SDRAMCR3_REN_MASK; return kStatus_Success; } 由上面就可以知道初始化SDRAM的过程
  • 1 预充电
  • 2 第一个自刷新
  • 3 第二个自刷新
  • 4 加载寄存器配置
  • 5 最后使能 refresh
SEMC_ConfigureSDRAM函数调用之后就可以使用AXI命令来进行读写了

参考资料

[野火®]新增eLCDIF-液晶章节《i.MX RT库开发实战指南》2018_07_30.pdf
[RT1052] 简要分析RT1052操作NandFlash
痞子衡嵌入式:飞思卡尔i.MX RT系列MCU启动那些事(8)- 从Raw NAND启动