基于RT1052的SEMC的SDRAM读写测试
注:1、对 SDRAM 存储空间的数据操作都要在 SDRAM_Init 初始化 SEMC 之后
2、当前这种方式不适用于系统启动后就需要 SDRAM 的应用
/*
bsp_sdram.c
*/
#include "bsp_sdram.h"
//SDRAM起始地址
#define SEMC_SDRAM_START_ADDRESS (0x80000000U)
//SDRAM大小,32M字节
#define SEMC_SDRAM_MEM_LENGTH (32*1024*1024)
//读和写的数据的长度
#define SEMC_SDRAM_WRDATALEN (0x1000U)
//读和写次数
#define SEMC_SDRAM_WRTIMES (1000U)
uint32_t sdram_writeBuffer[SEMC_SDRAM_WRDATALEN];
uint32_t sdram_readBuffer[SEMC_SDRAM_WRDATALEN];
//SEMC_SDRAM_START_ADDRESS+SEMC_SDRAM_MEM_LENGTH都表示SDRAM的存储空间,访问这些地址就能直接访问SDRAM
//指针方式访问SDRAM
/*
* uint32_t temp;
* 向SDRAM写入8位数据
* *(uint8_t*)(SEMC_SDRAM_START_ADDRESS) = (uint8_t)0xAA;
* 从SDRAM读数据
* temp = *(uint8_t*)(SEMC_SDRAM_START_ADDRESS);
* 写/读16位数据
* *(uint16_t*)(SEMC_SDRAM_START_ADDRESS+10) = (uint16_t)0xAABB;
* temp = *(uint16_t*)(SEMC_SDRAM_START_ADDRESS+10);
* 写/读16位数据
* *(uint32_t*)(SEMC_SDRAM_START_ADDRESS+20) = (uint32_t)0xAABBCCDD;
* temp = *(uint32_t*)(SEMC_SDRAM_START_ADDRESS+20);
*/
// /* 绝对定位方式访问 SDRAM, 这种方式必须定义成全局变量 */
// 必须在函数外把它定义成全局变量,才可以存储到指定地址上
/*
uint8_t testValue __attribute__((at(SDRAM_START_ADDRESS)));//使用关键字“__attribute__((at()))”来指定变量的地址
testValue = 0xDD;
*/
//初始化SDRAM相关IOMUXC的MUX复用配置
static void SDRAM_IOMUXC_Config(void)
{
//所有引脚均不开启SION功能
//DATA信号线DATA00-DATA15
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_00_SEMC_DATA00,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_01_SEMC_DATA01,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_02_SEMC_DATA02,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_03_SEMC_DATA03,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_04_SEMC_DATA04,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_05_SEMC_DATA05,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_06_SEMC_DATA06,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_07_SEMC_DATA07,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_30_SEMC_DATA08,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_31_SEMC_DATA09,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_32_SEMC_DATA10,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_33_SEMC_DATA11,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_34_SEMC_DATA12,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_35_SEMC_DATA13,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_36_SEMC_DATA14,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_37_SEMC_DATA15,0);
//DQS信号线 必须使能SION功能
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_39_SEMC_DQS,1);
//ADDR信号线 ADDR00-ADDR12
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_09_SEMC_ADDR00,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_10_SEMC_ADDR01,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_11_SEMC_ADDR02,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_12_SEMC_ADDR03,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_13_SEMC_ADDR04,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_14_SEMC_ADDR05,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_15_SEMC_ADDR06,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_16_SEMC_ADDR07,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_17_SEMC_ADDR08,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_18_SEMC_ADDR09,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_23_SEMC_ADDR10,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_19_SEMC_ADDR11,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_20_SEMC_ADDR12,0);
//BA0 BA1
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_21_SEMC_BA0,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_22_SEMC_BA1,0);
//RAS CAS信号
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_25_SEMC_RAS,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_24_SEMC_CAS,0);
//WE CS0信号
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_28_SEMC_WE,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_29_SEMC_CS0,0);
//DM0 DM1信号
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_08_SEMC_DM00,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_38_SEMC_DM01,0);
//CLK CKE信号
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_26_SEMC_CLK,0);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_27_SEMC_CKE,0);
}
static void SDRAM_IOMUXC_PAD_Config(void)
{
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_00_SEMC_DATA00,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_01_SEMC_DATA01,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_02_SEMC_DATA02,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_03_SEMC_DATA03,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_04_SEMC_DATA04,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_05_SEMC_DATA05,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_06_SEMC_DATA06,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_07_SEMC_DATA07,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_30_SEMC_DATA08,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_31_SEMC_DATA09,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_32_SEMC_DATA10,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_33_SEMC_DATA11,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_34_SEMC_DATA12,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_35_SEMC_DATA13,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_36_SEMC_DATA14,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_37_SEMC_DATA15,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_39_SEMC_DQS,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_09_SEMC_ADDR00,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_10_SEMC_ADDR01,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_11_SEMC_ADDR02,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_12_SEMC_ADDR03,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_13_SEMC_ADDR04,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_14_SEMC_ADDR05,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_15_SEMC_ADDR06,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_16_SEMC_ADDR07,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_17_SEMC_ADDR08,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_18_SEMC_ADDR09,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_23_SEMC_ADDR10,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_19_SEMC_ADDR11,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_20_SEMC_ADDR12,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_21_SEMC_BA0,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_22_SEMC_BA1,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_25_SEMC_RAS,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_24_SEMC_CAS,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_28_SEMC_WE,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_29_SEMC_CS0,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_08_SEMC_DM00,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_38_SEMC_DM01,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_26_SEMC_CLK,SEMC_SDRAM_PAD_CONFIG_DATA);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_27_SEMC_CKE,SEMC_SDRAM_PAD_CONFIG_DATA);
}
//初始化SDRAM相关的SEMC配置
static status_t SDRAM_SEMC_Config(void)
{
status_t status=kStatus_Fail;
semc_config_t config;
semc_sdram_config_t sdramconfig;
uint32_t clockFrq = SEMC_SDRAM_CLK_FREQ;
//清空结构体
memset(&config,0,sizeof(semc_config_t));
memset(&sdramconfig,0,sizeof(semc_sdram_config_t));
//使用默认配置初始化SEMC
SEMC_GetDefaultConfig(&config);
config.dqsMode = kSEMC_Loopbackdqspad;
SEMC_Init(SEMC,&config);
//配置SDRAM
sdramconfig.csxPinMux = kSEMC_MUXCSX0;
sdramconfig.address = SEMC_SDRAM_START_ADDRESS;
sdramconfig.memsize_kbytes = 32*1024;
sdramconfig.portSize = kSEMC_PortSize16Bit;
sdramconfig.burstLen = kSEMC_Sdram_BurstLen8;
sdramconfig.columnAddrBitNum = kSEMC_SdramColunm_9bit;
sdramconfig.casLatency = kSEMC_LatencyTwo;
sdramconfig.tPrecharge2Act_Ns = 15;
sdramconfig.tAct2ReadWrite_Ns = 15;
sdramconfig.tRefreshRecovery_Ns = 72;
sdramconfig.tWriteRecovery_Ns = 2 * (1000000000/clockFrq);
sdramconfig.tCkeOff_Ns = 1 * (1000000000/clockFrq);
sdramconfig.tAct2Prechage_Ns = 42;
sdramconfig.tSelfRefRecovery_Ns = 72;
sdramconfig.tRefresh2Refresh_Ns = 60;
sdramconfig.tAct2Act_Ns = 60;
sdramconfig.tPrescalePeriod_Ns = 160 * (1000000000/clockFrq);
sdramconfig.refreshPeriod_nsPerRow = 64*1000000/8192;
sdramconfig.refreshUrgThreshold = sdramconfig.refreshPeriod_nsPerRow;
sdramconfig.refreshBurstLen = 1;
status = SEMC_ConfigureSDRAM(SEMC,kSEMC_SDRAM_CS0,&sdramconfig,clockFrq);
return status;
}
//这种初始化方式 不适合 于系统启动后就需要 SDRAM 的应用
status_t SDRAM_SEMC_Init(void)
{
status_t status=kStatus_Fail;
//配置SDRAM的时钟
/* 0: Periph_clk
1: SEMC alternative clock
使用 SEMC alternative clock */
CLOCK_SetMux(kCLOCK_SemcMux,1);
/* 0: PLL2 PFD2 PLL2 PFD2 will be selected as alternative clock for SEMC root clock
1: PLL3 PFD1 PLL3 PFD1 will be selected as alternative clock for SEMC root clock
alternative clock 使用 PLL2 PFD2 */
CLOCK_SetMux(kCLOCK_SemcAltMux, 0);
/* 分频后得到 SEMC_CLK_ROOT,
SEMC_CLK_ROOT = PLL2 PFD2/(1+1) */ // fSEMC_CLK_ROOT = fPLL2 PFD2/(1+1)=528*18/30/2=158.4MHz
CLOCK_SetDiv(kCLOCK_SemcDiv,1);
SDRAM_IOMUXC_Config();
SDRAM_IOMUXC_PAD_Config();
status = SDRAM_SEMC_Config();
return status;
}
//使用32bit指针进行访问SDRAM测试
//注意对 SDRAM 存储空间的数据操作都要在 SDRAM_Init 初始化 SEMC 之后,否则数据是无法正常存储的
void SEMC_SDRAMReadWrite32Bit(void)
{
uint32_t index;
uint32_t datalen = SEMC_SDRAM_WRDATALEN;
/*
指向SDRAM测试的起始地址
对该指针指向的地址赋值会触发向SDRAM的写入
对该指针指向的地址赋值会触发向SDRAM的读取
*/
uint32_t *sdram = (uint32_t*)SEMC_SDRAM_START_ADDRESS;
bool result = true;
PRINTF("Write data in 32-bit mode The starting address 0x%x Write the length %d\r\n",sdram,datalen);
//向SDRAM写入数据
for(index = 0; index<datalen;index++){
sdram_writeBuffer[index] = index;
sdram[index] = sdram_writeBuffer[index];
}
PRINTF("Read data in 32-bit mode The starting address 0x%x Read the length %d\r\n",sdram,datalen);
for(index = 0; index<datalen;index++){
sdram_readBuffer[index] = sdram[index];
}
PRINTF("Start comparing written and read data\r\n");
while(datalen--){
if(sdram_writeBuffer[datalen]!=sdram_readBuffer[datalen]){
result = false;
break;
}
}
if(result){
PRINTF("Consistent read and write results\r\n");
}else{
PRINTF("The read/write result is inconsistent\r\n");
}
}
/*
bsp_sdram.h
*/
#ifndef __BSP_SDRAM_H__
#define __BSP_SDRAM_H__
#include "fsl_debug_console.h"
#include "fsl_common.h"
#include "fsl_iomuxc.h"
#include "fsl_gpio.h"
#include "pad_config.h"
#include "fsl_semc.h"
//SEMC_CLK_ROOT频率
#define SEMC_SDRAM_CLK_FREQ CLOCK_GetFreq(kCLOCK_SemcClk)
#define SEMC_SDRAM_PAD_CONFIG_DATA (SRE_1_FAST_SLEW_RATE | \
DSE_7_R0_7 | \
SPEED_3_MAX_200MHz | \
ODE_0_OPEN_DRAIN_DISABLED | \
PKE_1_PULL_KEEPER_ENABLED | \
PUE_0_KEEPER_SELECTED | \
PUS_0_100K_OHM_PULL_DOWN | \
HYS_1_HYSTERESIS_ENABLED)
status_t SDRAM_SEMC_Init(void);
void SEMC_SDRAMReadWrite32Bit(void);
#endif
//main.c
...
SDRAM_SEMC_Init();
SEMC_SDRAMReadWrite32Bit();
...