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.

(F28377D) 32 bit EMIF reading/writing problem, ask for help

Hi,

I'm using the TMX320F28377D development tools with an external SDRAM.  I can write/read the SDRAM -- but a problem comes out:

The all values I read are same, example:I wrote 0x00@0x8000_0000, 0x01@0x8000_0000... and 0xff@0x8000_00ff; but when I read them back, I got 0xff@8000_0000, 0xff@8000_0001... and 0xff@0x8000_00ff. In another words, whatever the last data I wrote in, I can only read the last data back.

To me, I think the problem is the that when I change the address, the address didn't change in real. --- so every data wrote to one address, and read back from the same address.

I think the physical connection between the CPU to SDRAM should be good("The connection between
EMIF and the SDRAM is straightforward"), so there must be a problem about configuration.

I used two way to do such loopback reading -- DMA, and directly write/read function. Both have the same result.

I'm using 32bit mode to read/write.

The SDRAM is AS4C2M32S-5TCN (200MHz).

Thanks for anyone who can take a time to read this problem.


Regards,

King

Following is the code about the directly reading/writing by CPU:

#include "F28x_Project.h"     // Device Headerfile and Examples Include File
#include "F2837xD_Emif.h"
#include "F2837xD_struct.h"
#include <stdio.h>



void Emif_sdram_config(void);
void Emif_sdram_gpio(void);
void error(void);


// variables
#define RESULTS_BUFFER_SIZE 256

// Attention! The DMA not access every memory.
// It can access the GS(global shared memory).
#pragma DATA_SECTION(DMABuf1,"SecureRam0");
volatile Uint32 DMABuf1[RESULTS_BUFFER_SIZE]; //DMA buffer to write to EMIF
#pragma DATA_SECTION(DMABuf2,"SecureRam0");
volatile Uint32 DMABuf2[RESULTS_BUFFER_SIZE]; //DMA buffer for read back



/********************************************************************************/
main()
{
    InitSysCtrl();

    EALLOW;
    ClkCfgRegs.PERCLKDIVSEL.bit.EPWMCLKDIV = 1;
    EDIS;

    InitGpio();
    InitPieCtrl();
    IER = 0x0000;// Disable CPU interrupts and clear all CPU interrupt flags:
    IFR = 0x0000;
    InitPieVectTable();
    // Map ISR functions


   Emif_sdram_gpio();
   Emif_sdram_config();

   Uint32 i;

   // Initialize results buffer
   for(i = 0; i < RESULTS_BUFFER_SIZE; i++)
   {
       DMABuf1[i] = 0xffff0000+i; // write to external RAM using DMA
       DMABuf2[i] = 0x0000ffff; // read from external RAM using DMA
   }

   
   // write DMABuf1 to EMIF
   for(i = 0; i < RESULTS_BUFFER_SIZE; i++)
   {
       __addr32_write_uint32((unsigned long) (0x80000000+i), (unsigned long)DMABuf1[i]);
   }

   // read EMIF to DMABuf2
   for(i = 0; i < RESULTS_BUFFER_SIZE; i++)
   {
       DMABuf2[i] = (unsigned long) __addr32_read_uint32((unsigned long) (i+0x80000000));
   }
   ESTOP0;

	// compare results.
    for(i = 0; i < RESULTS_BUFFER_SIZE; i++)
    {
    if (DMABuf2[i] != DMABuf1[i])
        error();
    }
    ESTOP0;
    while(1);

}


///////////////////////////////////////////

void Emif_sdram_gpio(void)
{
    EALLOW;

  GpioCtrlRegs.GPAMUX2.bit.GPIO29 = 2;//GPIO29 EM1SDCKE
  GpioCtrlRegs.GPAMUX2.bit.GPIO30 = 2;//CLK
  GpioCtrlRegs.GPAMUX2.bit.GPIO31 = 2;//WE
  GpioCtrlRegs.GPBMUX1.bit.GPIO32 = 2;//CS0  GPIO B Mux 1 Register (GPIO32 to 47)
  GpioCtrlRegs.GPBMUX1.bit.GPIO38 = 2;//A0
  GpioCtrlRegs.GPBMUX1.bit.GPIO39 = 2;//A1
  GpioCtrlRegs.GPBMUX1.bit.GPIO40 = 2;//A2
  GpioCtrlRegs.GPBMUX1.bit.GPIO41 = 2;//A3
  GpioCtrlRegs.GPBMUX1.bit.GPIO44 = 2;//A4
  GpioCtrlRegs.GPBMUX1.bit.GPIO45 = 2;//A5
  GpioCtrlRegs.GPBMUX1.bit.GPIO46 = 2;//A6
  GpioCtrlRegs.GPBMUX1.bit.GPIO47 = 2;//A7
  GpioCtrlRegs.GPBMUX2.bit.GPIO48 = 2;//A8 GPIO B Mux 2 Register (GPIO48 to 63)
  GpioCtrlRegs.GPBMUX2.bit.GPIO49 = 2;//A9
  GpioCtrlRegs.GPBMUX2.bit.GPIO50 = 2;//A10

  GpioCtrlRegs.GPBMUX2.bit.GPIO53 = 2;//D31
  GpioCtrlRegs.GPBMUX2.bit.GPIO54 = 2;//D30
  GpioCtrlRegs.GPBMUX2.bit.GPIO55 = 2;//D29
  GpioCtrlRegs.GPBMUX2.bit.GPIO56 = 2;//D28
  GpioCtrlRegs.GPBMUX2.bit.GPIO57 = 2;//D27
  GpioCtrlRegs.GPBMUX2.bit.GPIO58 = 2;//D26
  GpioCtrlRegs.GPBMUX2.bit.GPIO59 = 2;//D25
  GpioCtrlRegs.GPBMUX2.bit.GPIO60 = 2;//D24
  GpioCtrlRegs.GPBMUX2.bit.GPIO61 = 2;//D23
  GpioCtrlRegs.GPBMUX2.bit.GPIO62 = 2;//D22
  GpioCtrlRegs.GPBMUX2.bit.GPIO63 = 2;//D21
  GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 2;//D20
  GpioCtrlRegs.GPCMUX1.bit.GPIO65 = 2;//D19
  GpioCtrlRegs.GPCMUX1.bit.GPIO66 = 2;//D18
  GpioCtrlRegs.GPCMUX1.bit.GPIO67 = 2;//D17
  GpioCtrlRegs.GPCMUX1.bit.GPIO68 = 2;//D16

  GpioCtrlRegs.GPCMUX1.bit.GPIO69 = 2;//D15
  GpioCtrlRegs.GPCMUX1.bit.GPIO70 = 2;//D14
  GpioCtrlRegs.GPCMUX1.bit.GPIO71 = 2;//D13
  GpioCtrlRegs.GPCMUX1.bit.GPIO72 = 2;//D12
  GpioCtrlRegs.GPCMUX1.bit.GPIO73 = 2;//D11
  GpioCtrlRegs.GPCMUX1.bit.GPIO74 = 2;//D10
  GpioCtrlRegs.GPCMUX1.bit.GPIO75 = 2;//D9
  GpioCtrlRegs.GPCMUX1.bit.GPIO76 = 2;//D8
  GpioCtrlRegs.GPCMUX1.bit.GPIO77 = 2;//D7
  GpioCtrlRegs.GPCMUX1.bit.GPIO78 = 2;//D6
  GpioCtrlRegs.GPCMUX1.bit.GPIO79 = 2;//D5
  GpioCtrlRegs.GPCMUX2.bit.GPIO80 = 2;//D4
  GpioCtrlRegs.GPCMUX2.bit.GPIO81 = 2;//D3
  GpioCtrlRegs.GPCMUX2.bit.GPIO82 = 2;//D2
  GpioCtrlRegs.GPCMUX2.bit.GPIO83 = 2;//D1
  GpioCtrlRegs.GPCMUX2.bit.GPIO85 = 2;//D0

  GpioCtrlRegs.GPCMUX2.bit.GPIO86 = 3;//CAS
  GpioCtrlRegs.GPCMUX2.bit.GPIO87 = 3;//RAS
  GpioCtrlRegs.GPCMUX2.bit.GPIO88 = 3;//DQM0
  GpioCtrlRegs.GPCMUX2.bit.GPIO89 = 3;//DQM1
  GpioCtrlRegs.GPCMUX2.bit.GPIO90 = 3;//DQM2
  GpioCtrlRegs.GPCMUX2.bit.GPIO91 = 3;//DQM3
  GpioCtrlRegs.GPCMUX2.bit.GPIO92 = 3;//BA1
  GpioCtrlRegs.GPCMUX2.bit.GPIO93 = 3;//BA0

  //set GPIO Direction as output

  EDIS;
}

void Emif_sdram_config(void)
{

    //STEP 1 SDRAM should be placed in Self-Refresh Mode by setting the SR bit in
    //the SDRAM configuration register (SDCR). The SR bit should be set using a byte-write to the upper byte
    //of the SDCR to avoid triggering the SDRAM Initialization Sequence
    Emif1Regs.SDRAM_CR.bit.SR = 1;

      //STEP 2 The device global clock module (GCM) should first be programmed to select the desired EMIF_CLK frequency
    // EMIFx can be configured in SDRAM mode or ASRAM mode.
    // For SDRAM mode, max operational frq is 100MHz and for ASRAM 200 MHz.
    // http://e2e.ti.com/support/microcontrollers/c2000/f/171/p/328275/1143419.aspx#1143419
    ClkCfgRegs.PERCLKDIVSEL.bit.EMIF1CLKDIV = 1; // EMIF1CLK = PLLSYSCLK / (EMIF1CLKDIV+1) = PLLSYSCLK = 100MHz

    //STEP 3 selecting the appropriate clock source for the VCLK3 domain

    //STEP 4 remove the SDRAM from Self-Refresh by clearing the SR bit in SDCR, again with a byte-write.
    Emif1Regs.SDRAM_CR.bit.SR = 0;
    //STEP 5
    Emif1Regs.SDRAM_TR.all = 0x5b338b20; //SDRAM Timing Register 0101-1 011 -0 011 -0 011 -1000 -1011 -0 010 -0000
    // T_RFC >= (tRFC × fEM1CLK) - 1  ; tRC = 60ns, 60*(10^-9) x 0.2*(10^9) - 1 = 11 (27-31)
    // T_RP >= (tRP × fEM1CLK) - 1 ; tRP = 18ns, 18 x 0.2 - 1 = 2.6 = 3 (24-26)
    // T_RCD >= (tRCD × fEM1CLK) - 1 ; tRCD = 18ns, 18 x 0.2 -1 = 3 (20-22)
    // T_WR >= (tWR × fEM1CLK) - 1 ; tWR = 2tCK = 2 x 10ns(CL=2), 20 x 0.2 -1 = 3 (16-18)
    // T_RAS >= (tRAS × fEM1CLK) - 1 ; tRAS = 42ns, 42 x 0.2 -1 = 8 (12-15)
    // T_RC >= (tRC × fEM1CLK) - 1 ; tRC = 60ns, 60 x 0.2 -1 = 11 (8-11)
    // T_RRD >= (tRRD × fEM1CLK) - 1 ; tRRD = 12ns, 12 x 0.2 -1 = 2 (4-6)

    Emif1Regs.SDR_EXT_TMNG.all = 0x0c; //self refresh exit timing register
    // T_XS >= (tXSR × fEM1CLK) - 1 ; tXSR=tRC+tIS=60+1.5=61.5ns, 61.5 x 0.2 - 1 = 12 (0-4)

    Emif1Regs.SDRAM_RCR.all = 0x0c35; //Refresh Control Register
    // RR = fEM1CLK × tRefresh Period / ncycles ; tRefresh Period = 64 ms; ncycles = 4096; = 3125 (0-12)

    Emif1Regs.SDRAM_CR.all = 0x0520;// 0x0520; //configuration register
    // SR 0 To avoid placing the EMIF into the self-refresh state
    // NM 0 To configure the EMIF for a 32-bit data bus
    // CL 010b To select a CAS latency of 2
    // BIT11_9LOCK 1 To allow the CL field to be written
    // IBANK 010b To select 4 internal SDRAM banks
    // PAGESIZE 0 To select a page size of 256 words
    // 000 00000 000000 0 0 0(15) 0(NM) 0 0 010 1(8) 0 010 0 000
    // 0000 0000 0000  0000            0000     0101  0010  0000
    // 00 00 0520
}


void error(void)
{
  asm("     ESTOP0");                      // Test failed!! Stop!
   for (;;);
}


  • Hi,

    One thing I oberved in your code is that while changing the EMIF clock divide value by code  "ClkCfgRegs.PERCLKDIVSEL.bit.EMIF1CLKDIV = 1;" you are not using the EALLOW so this write will not work. This should not cause issue becasue the value written in this code is default value at reset but could you double check through memory watch window that value of this field is indeed '1'.

    Regards,

    Vivek Singh

  • Dear Vivek,

    Thanks for your reading. I checked the register, that field is '1'.

    By the way, I need to update the clock/time-delay part, because the old one was based on 200MHz clock -- but the below, based on 100MHz clock, still has the same result with 200MHz clock one, or same as I posted previous.

    void Emif_sdram_config(void)
    {
    
        //STEP 1 SDRAM should be placed in Self-Refresh Mode by setting the SR bit in
        //the SDRAM configuration register (SDCR). The SR bit should be set using a byte-write to the upper byte
        //of the SDCR to avoid triggering the SDRAM Initialization Sequence
        Emif1Regs.SDRAM_CR.bit.SR = 1;
    
          //STEP 2 The device global clock module (GCM) should first be programmed to select the desired EMIF_CLK frequency
        // EMIFx can be configured in SDRAM mode or ASRAM mode.
        // For SDRAM mode, max operational frq is 100MHz and for ASRAM 200 MHz.
        // http://e2e.ti.com/support/microcontrollers/c2000/f/171/p/328275/1143419.aspx#1143419
        ClkCfgRegs.PERCLKDIVSEL.bit.EMIF1CLKDIV = 1; // EMIF1CLK = PLLSYSCLK / (EMIF1CLKDIV+1) = PLLSYSCLK = 100MHz
    
        //STEP 3 selecting the appropriate clock source for the VCLK3 domain
    
        //STEP 4 remove the SDRAM from Self-Refresh by clearing the SR bit in SDCR, again with a byte-write.
        Emif1Regs.SDRAM_CR.bit.SR = 0;
        //STEP 5
        Emif1Regs.SDRAM_TR.all =0x29114510;// 0x5b338b20; //SDRAM Timing Register
        //                      0010-1 001 -0 001 -0 001 -0100 -0101 -0 001 -0000
        // T_RFC >= (tRFC × fEM1CLK) - 1  ; tRC = 60ns, 60*(10^-9) x 0.1*(10^9) - 1 = 5 (27-31)
        // T_RP >= (tRP × fEM1CLK) - 1 ; tRP = 18ns, 18 x 0.1 - 1 = 1 (24-26)
        // T_RCD >= (tRCD × fEM1CLK) - 1 ; tRCD = 18ns, 18 x 0.1 -1 = 1 (20-22)
        // T_WR >= (tWR × fEM1CLK) - 1 ; tWR = 2tCK = 2 x 10ns(CL=2), 20 x 0.1 -1 = 1 (16-18)
        // T_RAS >= (tRAS × fEM1CLK) - 1 ; tRAS = 42ns, 42 x 0.1 -1 = 4 (12-15)
        // T_RC >= (tRC × fEM1CLK) - 1 ; tRC = 60ns, 60 x 0.1 -1 = 5 (8-11)
        // T_RRD >= (tRRD × fEM1CLK) - 1 ; tRRD = 12ns, 12 x 0.1 -1 = 1 (4-6)
    
        Emif1Regs.SDR_EXT_TMNG.all = 0x06; //0x0c; //self refresh exit timing register
        // T_XS >= (tXSR × fEM1CLK) - 1 ; tXSR=tRC+tIS=60+1.5=61.5ns, 61.5 x 0.1 - 1 = 6 (0-4)
    
        Emif1Regs.SDRAM_RCR.all = 0x061a;//0x0c35; //Refresh Control Register
        // RR ≤ fEM1CLK × tRefresh Period / ncycles ; tRefresh Period = 64 ms; ncycles = 4096; = 3125 (0-12)
    
        Emif1Regs.SDRAM_CR.all = 0x0520;// 0x0520; //configuration register
        // SR 0 To avoid placing the EMIF into the self-refresh state
        // NM 0 To configure the EMIF for a 32-bit data bus
        // CL 010b To select a CAS latency of 2
        // BIT11_9LOCK 1 To allow the CL field to be written
        // IBANK 010b To select 4 internal SDRAM banks
        // PAGESIZE 0 To select a page size of 256 words
        // 000 00000 000000 0 0 0(15) 0(NM) 0 0 010 1(8) 0 010 0 000
        // 0000 0000 0000  0000            0000     0101  0010  0000
        // 00 00 0520
    }

  • Hi King,

    Did you trying writting into this address space using CCS Memory Watch window? If not then can you try this and let me know if that works?

    Run your code till completion of  Emif_sdram_config() function and then write into SDRAM address space from CCS Memory Watch window.

    Regards,

    Vivek Singh 

  • Good morning Vivek,

    I did what you suggested, and here is the result:

    When never I change a 32bit data at one address, all address's values are changed at the same time, and be all same.

    Example: I wrote 0x12345678 to address 0x80000000, all addresses' value will become to 0x12341234.

    0x80000000: 12341234

    0x80000002: 12341234

    ....

    If I use the function __addr32_write_uint32() to write data 0x12345678, all address' value will be 0x12345678. -- in the following loop I can see it step by step.

       for(i = 0; i < RESULTS_BUFFER_SIZE; i++)
       {
           __addr32_write_uint32((unsigned long) (0x80000000+i), (unsigned short)i);
       }

    Regards,

    King

  • Dear Vivek,

    I read the RCSR Register (offset = 0h) [reset = 40000205h], and the MODULE_ID=0h(EMIF module ID.0x0000: EMIF_24.     0x000E: EMIF_24 SDRAM.  0x000F: EMIF_24 ASYNC.) 

    The EMIF module is EMIF_24, not EMIF_24 SDRAM, is that OK to me to use the 32bit SDRAM?

    Bests,

    King

  • Hi King,

    The value in RCSR register is correct. EMIF_24 means it supports SDRAM as well as ASYNC so that is ok to use SDRAM.

      Example: I wrote 0x12345678 to address 0x80000000, all addresses' value will become to 0x12341234.

    Having same value in lower and upper half word is CCS specifc. We'll look into it.

    On other issue, how many locations in memory return the same value as 0x12345678 ? Did you try different ROW address?  Is it possible to probe few address lines along with control singals and clock on this board to check the timing waveform?

    Regards,

    Vivek Singh

      

  • Dear Vivek,


    Thanks again for helping.

    As far as I can see, all the addresses on the EMIF have the same value (from 0x80000000 to 0x80010A5A), so I would assume that all addresses I try to read were imaged to only one address, and probably same as the writing.

    The SDRAM I'm using 64Mbits (512k * 32bit * 4 banks).

    I tried different ROW address, same thing happened.

    Unfortunately I haven't a powerful oscilloscope to probe the address/control-signal lines, very sorry about it.

    I double checked the connection, the docking board with SDRAM has no problem to mount the development controlcard, and every pin of the SDRAM is connected to the controlcard correctly.

    Is that possible for you to post an "unofficial example code" of any SDRAM?

    Sincerely,

    King

  • Hi King,

    Sorry for late reply. We are wokring on releasing the example in controlSUITE. It should be available in next controlSUITE release which is planned in mid November.

    Regards,

    Vivek Singh