SEMC
Smart External Memory Controller
它可以用于驱动包括SRAM、SDRAM、
NorFlash、NAND Flash 等类型的存储器以及使用8080 接口协议(DBI 接口)的显示器和设备
通讯引脚
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_CLK 由 SEMC_CLK_ROOT提供
- 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结构
typedef struct _semc_config_t
{
semc_dqs_mode_t dqsMode;
uint8_t cmdTimeoutCycles;
uint8_t busTimeoutCycles;
semc_axi_queueweight_t queueWeight;
} semc_config_t;
_semc_sdram_config结构
typedef struct _semc_sdram_config{
...
sem_sdram_burst_len_t burstLen;
...
semc_caslatency_t casLatency;
uint8_t tPrecharge2Act_Ns;
uint8_t tAct2ReadWrite_Ns;
uint8_t tRefreshRecovery_Ns;
uint8_t tWriteRecovery_Ns;
...
uint8_t tCkeOff_Ns;
uint8_t tAct2Prechage_Ns;
...
SEMC配置
semc_config_t config;
semc_sdram_config_t sdramconfig;
SEMC_GetDefaultConfig(&config);
SEMC_Init(SEMC, &config);
...
SEMC_ConfigureSDRAM(SEMC, kSEMC_SDRAM_CS0, &sdramconfig, clockFrq);
这段程序就是获得SEMC默认配置。然后初始化
sdramconfig结构。SEMC_ConfigureSDRAM函数将
config和
sdramconfig绑定起来。
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);
result = SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address,
kSEMC_SDRAMCM_AutoRefresh, 0, NULL);
result = SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address,
kSEMC_SDRAMCM_AutoRefresh, 0, NULL);
...
result = SEMC_SendIPCommand(base, kSEMC_MemType_SDRAM, config->address,
kSEMC_SDRAMCM_Modeset, mode, NULL);
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启动