This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28386S: 通过EMIF1接口写入和读取SDRAM(三星K4S641632H-TC70)的数据时出现部分数据混乱的情况

Part Number: TMS320F28386S

各位专家好,目前我正采用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的时间参数表

  • 哪位大神可以帮助一下我么?这个问题任然没有解决。

  • 您好

    您是否已经解决了 EMIF 问题? 在我看来、K4S641632H-TC70的时序参数可能未正确设置。

  • 您好!感谢您的关注与回复。

    这个问题还没有解决。

    EMIF的寄存器参数配置是参考《TMS320F2838x Real-Time Microcontrollers With Connectivity Manager TRM (Rev. D)》 12.3.2.1.2章节配置的,手册里给的Demo也是这颗三星的SDRAM芯片。

    我一开始以为是IPC或者以太网出问题,后来我在存储查看器(Memory Browser)中观察数据,也是一样的问题。另外,我也试着在存储查看器中直接修改数据,发现所在地址的数据改变后,其他位置的数据也会改变。