各位专家好,目前我正采用TMS320F28386S的EMIF连接三星公司型号为K4S641632H-TC70,大小为64Mb的SDRAM芯片(1M×16bit×4bank),作为外部数据缓存,引脚连接设计图如下
程序配置如下
//--------------------------------------------------------------------------- // @functions: void InitEMIF1Gpio(Uint16 cpu_sel) // @description: 配置EMIF1的I/O引脚为16bit同步模式 Setup EMIF1 Pinmux Sync 16Bit // @Return value:NONE // @Parameters: cpu_sel - CPU选择 //--------------------------------------------------------------------------- void InitEMIF1Gpio(Uint16 cpu_sel) { //对照芯片手册P1646 table15-7 GPIO_SetupPinMux(29,cpu_sel,2); //SDCKE GPIO_SetupPinMux(30,cpu_sel,2); //CLK GPIO_SetupPinMux(31,cpu_sel,2); //WEN GPIO_SetupPinMux(32,cpu_sel,2); //CS0N GPIO_SetupPinMux(33,cpu_sel,9); //EMIF1_BA0 GPIO_SetupPinMux(34,cpu_sel,9); //EMIF1_BA1 GPIO_SetupPinMux(35,cpu_sel,9); //EMIF1_A0 GPIO_SetupPinMux(36,cpu_sel,9); //EMIF1_A1 GPIO_SetupPinMux(40,cpu_sel,2); //EMIF1_A2 GPIO_SetupPinMux(41,cpu_sel,2); //EMIF1_A3 GPIO_SetupPinMux(44,cpu_sel,2); //EMIF1_A4 GPIO_SetupPinMux(45,cpu_sel,2); //EMIF1_A5 GPIO_SetupPinMux(46,cpu_sel,2); //EMIF1_A6 GPIO_SetupPinMux(47,cpu_sel,2); //EMIF1_A7 GPIO_SetupPinMux(48,cpu_sel,2); //EMIF1_A8 GPIO_SetupPinMux(49,cpu_sel,2); //EMIF1_A9 GPIO_SetupPinMux(50,cpu_sel,2); //EMIF1_A10 GPIO_SetupPinMux(51,cpu_sel,2); //EMIF1_A11 GPIO_SetupPinMux(69,cpu_sel,2); //EMIF1_D15 GPIO_SetupPinMux(70,cpu_sel,2); //EMIF1_D14 GPIO_SetupPinMux(71,cpu_sel,2); //EMIF1_D13 GPIO_SetupPinMux(72,cpu_sel,2); //EMIF1_D12 GPIO_SetupPinMux(73,cpu_sel,2); //EMIF1_D11 GPIO_SetupPinMux(74,cpu_sel,2); //EMIF1_D10 GPIO_SetupPinMux(75,cpu_sel,2); //EMIF1_D9 GPIO_SetupPinMux(76,cpu_sel,2); //EMIF1_D8 GPIO_SetupPinMux(77,cpu_sel,2); //EMIF1_D7 GPIO_SetupPinMux(78,cpu_sel,2); //EMIF1_D6 GPIO_SetupPinMux(79,cpu_sel,2); //EMIF1_D5 GPIO_SetupPinMux(80,cpu_sel,2); //EMIF1_D4 GPIO_SetupPinMux(81,cpu_sel,2); //EMIF1_D3 GPIO_SetupPinMux(82,cpu_sel,2); //EMIF1_D2 GPIO_SetupPinMux(83,cpu_sel,2); //EMIF1_D1 GPIO_SetupPinMux(85,cpu_sel,2); //EMIF1_D0 GPIO_SetupPinMux(86,cpu_sel,3); //EMIF1_CAS GPIO_SetupPinMux(22,cpu_sel,10); //EMIF1_RAS GPIO_SetupPinMux(88,cpu_sel,3); //EMIF1_DQM0 GPIO_SetupPinMux(89,cpu_sel,3); //EMIF1_DQM1 // //configure Data pins for Async mode //GPIO_PULLUP | GPIO_ASYNC = (1 << 0)|(0x3 << 4) GPIO_SetupPinOptions(69,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D15 GPIO_SetupPinOptions(70,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D14 GPIO_SetupPinOptions(71,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D13 GPIO_SetupPinOptions(72,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D12 GPIO_SetupPinOptions(73,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D11 GPIO_SetupPinOptions(74,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D10 GPIO_SetupPinOptions(75,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D9 GPIO_SetupPinOptions(76,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D8 GPIO_SetupPinOptions(77,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D7 GPIO_SetupPinOptions(78,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D6 GPIO_SetupPinOptions(79,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D5 GPIO_SetupPinOptions(80,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D4 GPIO_SetupPinOptions(81,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D3 GPIO_SetupPinOptions(82,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D2 GPIO_SetupPinOptions(83,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D1 GPIO_SetupPinOptions(85,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_D0 GPIO_SetupPinOptions(88,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_DQM0 GPIO_SetupPinOptions(89,GPIO_INPUT,GPIO_PULLUP | GPIO_ASYNC); //EMIF1_DQM1 }
//--------------------------------------------------------------------------- // @functions: void InitEMIF1Reg(void) // @description: 配置EMIF1模块相关寄存器 // @Return value:NONE // @Parameters: NONE //--------------------------------------------------------------------------- void InitEMIF1Reg(void) { //配置EMIF过程描述TMS320F28386手册P1429 Section 12.3.2 和 P1406 Section 12.2.5.5 EALLOW; //Before configure the EMIF1CLKDIV field, the SDRAM should be placed in self-refresh mode //by setting the SR bit in the SDRAM configuration register. //TMS320F28386手册P1429 Section 12.3.2.1.1 //TMS320F28386手册P1404 Section Table 12-8 // Emif1Regs.SDRAM_CR.bit.SR = 0x01; //Configure to run EMIF1 on half Rate (EMIF1CLK = CPU1SYSCLK/2), //PLLSYSCLK = (XTAL_OSC) * (IMULT) /((REFDIV) * (ODIV) * (PLLSYSCLKDIV)) //PLLSYSCLK = 25M*32/(2*2*1)=200M //0 —— /1 of CPU1.SYSCLK is selected //1 —— /2 of CPU1.SYSCLK is selected //TMS320F28386手册P242 Table 3-52 和 Figure 3-50 // ClkCfgRegs.PERCLKDIVSEL.bit.EMIF1CLKDIV = 0x1; // Once the EM1CLK frequency has been configured, remove the SDRAM from //self-refresh by clearing the SR bit in SDRAM_CR. //TMS320F28386手册P1429 Section 12.3.2.1.1 // Emif1Regs.SDRAM_CR.bit.SR = 0x00; // Grab EMIF1 For CPU1 //TMS320F28386手册P1465 Table 12-55 和 Figure 12-40 //从bit4~bit31必须写入0x93A5CE7,仅有bit0~bit1选择CPU,所以这个值肯定是0x93A5CE7X,X=0001b表示CPU1 is master // Emif1ConfigRegs.EMIF1MSEL.all = MSEL_EMIF1_CPU1; // Disable Access Protection (CPU_FETCH/CPU_WR/DMA_WR) bit0~bit2 //TMS320F28386手册P1466 Table 12-56 和 Figure 12-41 // Emif1ConfigRegs.EMIF1ACCPROT0.all = 0x0; // content of EMIF1ACCPROT0 register can't be changed.bit0 //TMS320F28386手册P1464 Table 12-54 和 Figure 12-39 // Emif1ConfigRegs.EMIF1COMMIT.all = 0x1; // Lock the configuration so that EMIF1COMMIT register can't be changed any more.bit0 //TMS320F28386手册P1463 Table 12-53 和 Figure 12-38 //bit0 = 1 表示 Write to ACCPROT and Mselect fields are blocked. //相当于上上上个寄存器EMIF1MSEL和上上个寄存器EMIF1ACCPROT0锁住了,一步到位 // Emif1ConfigRegs.EMIF1LOCK.all = 0x1; }
//--------------------------------------------------------------------------- // @functions: void InitEMIF1SDRAMReg(void) // @description: 根据实际SDRAM芯片参数,配置EMIF1的SDRAM功能的寄存器 // @Return value:NONE // @Parameters: NONE //--------------------------------------------------------------------------- void InitEMIF1SDRAMReg(void) { EMIF_SyncConfig sdConfig; EMIF_SyncTimingParams tParam; // //Configure SDRAM control registers // EALLOW; // Need to be programmed based on SDRAM Data-Sheet. //K4S640432H-TC70 手册PDF的第10页,“OPERATING AC PARAMETER” //T_RFC = 68ns = 0x6(T_RFC = T_RC) //T_RP = 20ns = 0x1 //T_RCD = 20ns = 0x1 //T_WR = 2CLK = 20 ns = 0x1 //T_RAS = 49ns = 0x4 //T_RC = 68ns = 0x6 //T_RRD = 14ns = 0x1 //TMS320F28386手册P1431 Table 12-27 和 Figure 12-16 // Emif1Regs.SDRAM_TR.all = 0x61114610; // Emif1Regs.SDRAM_TR.all = 0x72225720; //Txsr = T_RC = 68ns = 0x6 //TMS320F28386手册P1432, Table 12-28 和 Figure 12-17 // Emif1Regs.SDR_EXT_TMNG.all = 0x6; // Emif1Regs.SDR_EXT_TMNG.all = 0x7; //Tref = 64ms for 4096 ROW, RR = 64000*100(Tfrq)/4096 = 1562 (0x061A) //TMS320F28386手册P1432, Table 12-29 和 Figure 12-18 // Emif1Regs.SDRAM_RCR.all = 0x061A; //SR = 0, NM = 1 (16bit), CL = 3, BIT11_9LOCK = 1, IBANK = 2 (4 BANK), PAGESIZE=0 (256 elements per ROW,CA0~CA7) //TMS320F28386手册P1433, Table 12-30 和 Figure 12-19 // Emif1Regs.SDRAM_CR.all = 0x4720; }
在man()函数中,初始化的顺序是
InitEMIF1Gpio(GPIO_MUX_CPU1); //Configure GPIO pins for EMIF1 InitEMIF1Reg(); //Configure registers of EMIF1 InitEMIF1SDRAMReg(); //Configure registers of EMIF1 SDRAM function
CMD中关于SDRAM的配置如下
MEMORY { EMIF1_CS0n : origin = 0x80000000, length = 0x400000 /* Samsung SDRAM = 1M x 16Bit x 4 Banks = 64Mbit */ EMIF1_CS2n : origin = 0x00100000, length = 0x00100000 EMIF1_CS0_CS2n : origin = 0x00200000, length = 0x00100000 EMIF1_CS3n : origin = 0x00300000, length = 0x00080000 EMIF1_CS4n : origin = 0x00380000, length = 0x00060000 EMIF2_CS0n : origin = 0x90000000, length = 0x10000000 EMIF2_CS2n : origin = 0x00002000, length = 0x00001000 } SECTIONS { emif_cs0_nonfar : > EMIF1_CS0_CS2n .farbss : > EMIF1_CS0n .farconst : > EMIF1_CS0n .em1_cs0 : > EMIF1_CS0n .em1_cs2 : > EMIF1_CS2n | EMIF1_CS0_CS2n .em1_cs3 : > EMIF1_CS3n .em1_cs4 : > EMIF1_CS4n .em2_cs0 : > EMIF2_CS0n .em2_cs2 : > EMIF2_CS2n } /* //=========================================================================== // End of file. //=========================================================================== */
并且在程序中,成功初始化了需要的数组
#define Ads1ForSpiaChnNum 16 #define Ads2ForSpibChnNum 16 #define Ads3ForSpicChnNum 16 #define WordsNumPerChn 30000 #define Ads1WordsMemBufSize ((Uint32)Ads1ForSpiaChnNum*WordsNumPerChn) #define Ads2WordsMemBufSize ((Uint32)Ads2ForSpibChnNum*WordsNumPerChn) #define Ads3WordsMemBufSize ((Uint32)Ads3ForSpicChnNum*WordsNumPerChn) __attribute__((far)) volatile Uint16 Ads1SDRAMBuf[Ads1WordsMemBufSize]; __attribute__((far)) volatile Uint16 Ads2SDRAMBuf[Ads2WordsMemBufSize]; __attribute__((far)) volatile Uint16 Ads3SDRAMBuf[Ads3WordsMemBufSize];
然后在main()函数中对这三个数组进行赋值写入操作
for(i = 0; i < Ads1WordsMemBufSize; i++) { Ads1SDRAMBuf[i] = 0x0101; Ads2SDRAMBuf[i] = 0x0202; Ads3SDRAMBuf[i] = 0x0303; DELAY_US(1); }
最后用for循环和memcpy两种读取方法,通过IPC+以太网的传输方式把数据发送到PC上
LenPerTx = 500; TxTotalLen = Ads1WordsMemBufSize; for(i=0;i<TxTotalLen/LenPerTx;i++) { // memcpy(&IPCTxBuff[0],(Ads1SDRAMBuf+i*LenPerTx),LenPerTx*sizeof(Uint16)); for(j=0;j<LenPerTx;j++) { IPCTxBuff[j] = Ads1SDRAMBuf[i*LenPerTx+j]; } IpcGlobalVar.TxBufLen = LenPerTx; //发送帧的字节长度 IpcTxStart((Uint32)IPCTxBuff,IpcGlobalVar.TxBufLen); //发送处理函数 DELAY_US(3500); }
LenPerTx = 500; TxTotalLen = Ads2WordsMemBufSize; for(i=0;i<TxTotalLen/LenPerTx;i++) { memcpy(&IPCTxBuff[0],(Ads2SDRAMBuf+i*LenPerTx),LenPerTx*sizeof(Uint16)); IpcGlobalVar.TxBufLen = LenPerTx; //发送帧的字节长度 IpcTxStart((Uint32)IPCTxBuff,IpcGlobalVar.TxBufLen); //发送处理函数 DELAY_US(3000); }
上述两种方法得到一样的结果,出现一段一段的数据混乱,如下图所示
麻烦TI的专家帮忙看一下,是不是哪里配置出了问题,导致SDRAM写入读取时部分数据正确,部分数据不正确的情况,十分感谢!
另附上,K4S641632H-TC70的时间参数表