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.

TMS320F28375D: Memory Display EMIF and External SDRAM

Part Number: TMS320F28375D
Other Parts Discussed in Thread: CONTROLSUITE

Will the code composer memory window properly read and write memory to external SDRAM through EMIF in the memory window?  ie: if I write a value to 0x80000000 will it write/read the data to the External SDRAM properly?  Or can I only access external SDRAM through proper coding?

  • Hi Rob,

    It'll read/write properly as long as EMIF is configured properly to operate in SDRAM mode. Are you seeing some issue?

    Vivek Singh
  • We just received the new SDRAM version, so I am debugging it, but I wanted to be sure the code composer would work properly assuming everything is setup correctly.  At this point it doesn't, but just wanted to be sure what to expect from code composer, will let you know if this problem persists once I've had a chance to try and determine what is currently incorrect.

    Thanks.

  • Just to clairify: section 7.2 in www.ti.com/.../spruhm8f.pdf... when we are configuring the GPIO for EMIF1 the input/output & input and output lines are fixed, correct? we don't have to specify as an input or an output...

    However from section 25.2 it implies that I still need to set the input qualification to async and add pull up resistors to input lines if we haven't done so externally... correct?

    In the case of EMIF1 the only input lines are the data I/O lines.  Do I explicitly have to set these to ASYNC?  or is their functionality hard coded (built into the hardware) into the EMIF?

  • Rob,

    Just to clairify: section 7.2 in www.ti.com/.../spruhm8f.pdf... when we are configuring the GPIO for EMIF1 the input/output & input and output lines are fixed, correct? we don't have to specify as an input or an output...

    This is correct. You don't have set the input/output when any pin is selected as peripheral function.

    However from section 25.2 it implies that I still need to set the input qualification to async and add pull up resistors to input lines if we haven't done so externally... correct?

    This is also correct. If you are using the pinmux function from controlSUITE then it takes care of this.

    Vivek Singh

  • CPUGPIO_SetupPinMux is just your GPIO_SetupPinMux function in f2837xD_GPIO.c

    I basically: set ownership to CPU2, select the appropriate 2,3 from table 7-8 for the associated pins.

    Then I do the associated EMIF setup as per the manual. code snippets below:

    DO you see anything obvious I may have missed in setup?

    The current status is, I am seeing what looks like a WE low pulse on the scope in response to when I write some test code to write to memory.... I can generate this WE (write enable) low through the code composer memory window writing to some memory at 0x80000000 range (SDRAM) or through writing some code to write to it... however I can't yet read back data.

    I remembered to use the appropriate far declaration on the global memory in sdram and linked it to 0x80000000.

    I just want to be sure I haven't forgotten any setup steps in software before I pull out the logic analyzer and start looking at the bus cycle in hardware.

    Is there anything obvious I'm forgetting to setup that might be affecting it?

    Thanks.

    /*
    * Configure the EMIF GPIO Pins
    */

    // Data Lines for EMIF1
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 85, GPIO_MUX_CPU2, 2); // D0
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 83, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 82, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 81, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 80, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 79, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 78, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 77, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 76, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 75, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 74, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 73, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 72, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 71, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 70, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 69, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 68, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 67, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 66, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 65, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 64, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 63, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 62, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 61, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 60, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 59, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 58, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 57, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 56, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 55, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 54, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 53, GPIO_MUX_CPU2, 2); // D32

    // Address Lines
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 38, GPIO_MUX_CPU2, 2); // A0
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 39, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 40, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 41, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 44, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 45, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 46, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 47, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 48, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 49, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 50, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 51, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 52, GPIO_MUX_CPU2, 2); // A12

    // EM1CAS
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 86, GPIO_MUX_CPU2, 3);
    // EM1RAS
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 87, GPIO_MUX_CPU2, 3);
    // Other control lines
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 88, GPIO_MUX_CPU2, 3);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 89, GPIO_MUX_CPU2, 3);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 90, GPIO_MUX_CPU2, 3);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 91, GPIO_MUX_CPU2, 3);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 92, GPIO_MUX_CPU2, 3);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 93, GPIO_MUX_CPU2, 3);

    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 29, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 30, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 31, GPIO_MUX_CPU2, 2);
    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 32, GPIO_MUX_CPU2, 2);
    *********************************************************************************
    *********************************************************************************
    *********************************************************************************
    *********************************************************************************
    *********************************************************************************
    //
    // GPIO_SetupPinMux - Set the peripheral muxing for the specified pin. The
    // appropriate parameters can be found in the GPIO Muxed
    // Pins table(4.4) in the datasheet. Use the GPIO index
    // row (0 to 15) to select a muxing option for the GPIO.
    //
    void GPIO_SetupPinMux(Uint16 pin, Uint16 cpu, Uint16 peripheral)
    {
    volatile Uint32 *gpioBaseAddr;
    volatile Uint32 *mux, *gmux, *csel;
    Uint16 pin32, pin16, pin8;

    pin32 = pin % 32;
    pin16 = pin % 16;
    pin8 = pin % 8;
    gpioBaseAddr = (Uint32 *)&GpioCtrlRegs + (pin/32)*GPY_CTRL_OFFSET;

    //
    //Sanity check for valid cpu and peripheral values
    //
    if (cpu > GPIO_MUX_CPU2CLA || peripheral > 0xF)
    return;

    //
    //Create pointers to the appropriate registers. This is a workaround
    //for the way GPIO registers are defined. The standard definition
    //in the header file makes it very easy to do named accesses of one
    //register or bit, but hard to do arbitrary numerical accesses. It's
    //easier to have an array of GPIO modules with identical registers,
    //including arrays for multi-register groups like GPyCSEL1-4. But
    //the header file doesn't define anything we can turn into an array,
    //so manual pointer arithmetic is used instead.
    //
    mux = gpioBaseAddr + GPYMUX + pin32/16;
    gmux = gpioBaseAddr + GPYGMUX + pin32/16;
    csel = gpioBaseAddr + GPYCSEL + pin32/8;

    //
    //Now for the actual function
    //
    EALLOW;

    //
    //To change the muxing, set the peripheral mux to 0/GPIO first to avoid
    //glitches, then change the group mux, then set the peripheral mux to
    //its target value. Finally, set the CPU select. This procedure is
    //described in the TRM. Unfortunately, since we don't know the pin in
    //advance we can't hardcode a bitfield reference, so there's some
    //tricky bit twiddling here.
    //
    *mux &= ~(0x3UL << (2*pin16));
    *gmux &= ~(0x3UL << (2*pin16));
    *gmux |= (Uint32)((peripheral >> 2) & 0x3UL) << (2*pin16);
    *mux |= (Uint32)(peripheral & 0x3UL) << (2*pin16);

    *csel &= ~(0x3L << (4*pin8));
    *csel |= (Uint32)(cpu & 0x3L) << (4*pin8);

    //
    //WARNING: This code does not touch the analog mode select registers,
    //which are needed to give the USB module control of its IOs.
    //
    EDIS;
    }

    *********************************************************************************
    *********************************************************************************
    *********************************************************************************
    *********************************************************************************
    *********************************************************************************

    I then follow this with EMIF init of:

    // This is following Procedure B section 25.3.5.5 for EMIF1 startup

    // Set the Clock frequency to /2 or 100MHz
    EALLOW;
    ClkCfgRegs.PERCLKDIVSEL.bit.EMIF1CLKDIV = 1;
    EDIS;

    // Tell the EMIF what the SDRAM timing requirements are so it can better schedule and meet SDRAM TIMINGS
    // NOTE: these values should come from data sheet of selected SDRAM
    // NOTE: these are from data sheet for AS4C4M32S
    Emif1Regs.SDRAM_TR.bit.T_RAS = 42;
    Emif1Regs.SDRAM_TR.bit.T_RC = 60;
    Emif1Regs.SDRAM_TR.bit.T_RCD = 18;
    // NOTE: as per item 12 in SDRAM data sheet (auto refresh command) RGC is reall RC min, so we have two duplicate entries
    Emif1Regs.SDRAM_TR.bit.T_RFC = 60;
    Emif1Regs.SDRAM_TR.bit.T_RP = 18;
    Emif1Regs.SDRAM_TR.bit.T_RRD = 12;
    Emif1Regs.SDRAM_TR.bit.T_WR = 2;

    Emif1Regs.SDR_EXT_TMNG.bit.T_XS = 61.5;

    // NOTE: this is a startup refresh rate, altered again later in this very same init routine
    // Set the refresh rate of the SDRAM
    // data sheet says 4096 refresh cycles per 64 ms so computation is:
    // 100MHz (EMIF clock) * 64ms/ 4096 = 1563 cycles
    // However for this first setting they require RR*x/100MHz > 200us so 2501 or higher to meet constraint, we will ust 2510
    Emif1Regs.SDRAM_RCR.bit.REFRESH_RATE = 2510;

    // NOTE: the following 4 variables need to be set with the .all setting if we desire only ONE auto restart cycle.
    // if we write them individually they will cause it to happen 4 times.
    // Set bus width to 32 bits
    // Emif1Regs.SDRAM_CR.bit.NM = 0;

    // Set the CAS latency for read cycles
    // Emif1Regs.SDRAM_CR.bit.CL = 2;

    // Set the parameters of the chosen memory
    // Emif1Regs.SDRAM_CR.bit.IBANK = 4;
    // we have 8 column address bits
    // Emif1Regs.SDRAM_CR.bit.PAGESIGE = 0;

    // Set all four of the above at one time
    Emif1Regs.SDRAM_CR.all = 0x00000520;

    // Read memory from the SDRAM or perform 200us delay, we choose to read memory
    EMIF1_StartupReadSDRAM( theEMIF1 );

    // Set the refresh rate of the SDRAM
    Emif1Regs.SDRAM_RCR.bit.REFRESH_RATE = 1563;

    *********************************************************************************
    *********************************************************************************
    *********************************************************************************
    *********************************************************************************
    *********************************************************************************


    ;******************************************************************************
    ;------------------------------------------------------------------------------
    ; _EMIF1_StartupReadSDRAMASM
    ;
    ; Cycle Count:
    ; NOTE: not counting cycles C/C++ code uses to PUSH/POP to make the call
    ;------------------------------------------------------------------------------
    ;******************************************************************************
    _EMIF1_StartupReadSDRAMASM:
    ; ( void * SDRAMPtr )
    ;
    ; Translates to:
    ;
    ; XAR4 = &SDRAMPtr
    ;
    ; NOTE: the return value is placed at *-SP[2] (32 or 2 word value)

    ;-----------
    ; Main Loop
    ;-----------
    MOV32 R0H, *XAR4 ; do a dummy read of SDRAM for startup

    LRETR ;return
  • We have had a chance to look into this further... at present we see for a write cycle the RAS/CAS and WE control signals, but the data that we are writing doesn't appear on the data bus?  We are investigating hardware reasons, but from a software perspective I call the configureation:

    CPUGPIO_SetupPinMux( &theCPU->theCPUGPIO, 85, GPIO_MUS_CPU2, 2);

    which just calls:

    void CPUGPIO_SetupPinMux( CPUGPIO * theCPUGPIO, unsigned long pin, unsigned long cpu, unsigned long peripheral ) {

    #ifdef CPU1

    GPIO_SetupPinMux(pin, cpu, peripheral);

    #endif

    }

    which then just calls a cut and paste version of your TI supplied.

    The problem does appear like its simply not putting data on the data lines... So I can read ALL zeros (because the data lines are indeed all zeros...)

    We are investigating if the SDRAM is somehow driving the bus low, but would appreciate any input from the TI part side, in case it's simply a misconfigured case.

    Thanks.

  • Rob,

    Are you trying to access EMIF from CPU2? If yes then you need to configure EMIF1MSEL (refer Table 25-51. EMIF1_CONFIG_REGS Registers in TRM) to enable EMIF access from CPU2.

    Regards,

    Vivek Singh
  • Thanks

    // Assign ownership of EMIF1 or SDRAM to CPU2
    Emif1ConfigRegs.EMIF1MSEL.all = 0x93a5ce72;

    I had already caught that, so I have already assigned ownership of EMIF1 to CPU2 and wrote the special funny sequence it required as shown above.

    We are also seeing something weird... it turns out that even though I program NM = 0 for 32 bit data bus... and we are verifying any other causes (hardware etc.) if I write to the high hex bits, so in 0xffff0000 then it reads back 0xffffffff in the code composer window, for all 0x80000000 and above memory...

    I think the point of the above is it doesn't appear to be co-ordinating the 32 bit data... ie: I'm seeing patterns of 16 bit data...

    If I write 0xf0ff0000 then it reads back 0xf0fff0ff 0xf0fff0ff ... for all memory ...

    I recall asking a question on how it adjusts the address lines for the 32 bit memory, could this have something to do with it? ie: if in hardware the address lines are not connected to account for how the EMIF1 generates the 32 bit addresses... perhaps the reason I'm seeing 16 bit replicas and having to write to the high bits, is because when the read cycle is generated maybe the address it reads somehow is misaligned?

    The good news is it's reading back some data... the bad news is it's scrambled... need to descramble and determine the cause...

    Could you send us an updated table 25-14... Since this is bank size of 4 and page size of 0, we don't have the proper diagram for the address lines...

    Thanks..
  • Further to table 25-14, just above the table it states:

    The EMIF uses the EM1DQM[1:0] pins during a WRT command to mask out selected bytes or entire
    words. The EM1DQM[1:0] pins are always low during a READ command.

    Could you expand on this? Since we are seeing the 'lower word' of the data we are writing being lost, but the read cycle is reading duplicate values of what we write to the high data, this sounds like this might be what we are observing.

    Please expand on this.

    Thanks.
  • Actually that's a typo. It should have been EM1DQM[3:0] instead of EM1DQM[1:0]. I am assuming that you have connected all 4 DQM pin from EMIF to SDRAM device. As long as that is there, it's good. We'll correct this typo in next release.

    On NM bit configuration, have you checked the configuration in CCS register view to make sure it's indeed '0'?

    Vivek Singh
  • Rob,

    Are you observing this only from CCS debug window or from actual code as well? If you have not tried the code then I would recommend to use the code to access SDRAM and see if that is working fine.

    Vivek Singh
  • From what you have explained, it look like SDRAM device is not responding to the commands from EMIF. In that case you'll see issue of data repeating on all the addresses because write data remains on the bus and it get captured during the READ commands.
    Have you checked that SDRAM device is powered up properly?
  • Yes we have all four connected in hardware.

    I checked the CCS register view, it appears that it's not changing to what I program it to... however the default is 0 for NM which according to table 25-8 it says that 1 = 16 bit data bus and 0 is 32 bit data bus...

    I assign ownership of EMIF1 on CPU on startup, then I run the EMIF1 startup on CPU2... but as I'm seeing, the SDRAM_CR register is not updating on CPU2... I set it to:

    // Set all four of the above at one time
    Emif1Regs.SDRAM_CR.all = 0x00000440;

    however when I look at the code composer register view it's still at the default values... CL = 3 and banks =2 not banks = 4 CL = 2 that I'm trying to set... but NM is 0 in either case.

    It doesn't say this is an EALLOW register, do I need EALLOW/DIS? If I assigned ownership on CPU1 on startup, then I have the EMIF1 startup sequence on CPU2... it should be able to access these registers correct?
  • ---Deleted the response since it was not correct ------

    Regards,

    Vivek Singh

  • I'm trying to determine exactly what we see in code, but I can say it is not correct. ie: we don't see what we write out, when we read it back... I'll try and quantify what pattern we see when I perform write and read cycles via code... I'm not sure yet what I'm seeing through regular coding... Let me be sure it's either the same as what we see with code composer or something different... I will try and narrow it down, but I can say If I write something to memory in code, it doesn't read back the same.
  • Okay, that might explain it. I will move the initialization code of EMIF1 to CPU1, since that's the case then the initialization sequence of the EMIF1 has not successfully been run and the SDRAM is uninitialized (mode register not set etc.) So that is likely the problem...

    Thanks... I'll let you know if this resolves the issue.
  • Rob,

    Let me take it back. We have another device where configuration registers are accessible from only master CPU but on this device, CPU2 should be able to configure the EMIF1 registers. Can you check if all the writes are failing or only some?

    Regards,
    Vivek Singh
  • I'm having issues setting them from either CPU... When I moved the initialization to CPU1, I read back all zeros from the register window... ie: CL and ibank are reading zero, so they are not default or what I set it to.. when I leave the initialization on CPU2 it itleast maintains the default values... When I initialize it on CPU1 I see no activity when reading or writing through the code composer memory window... So I think I should definitely focus on the proper initialization of the EMIF1 / SDRAM... Any input?

    What do you mean if all the writes are failing? or only some?

    If I initialize it on CPU1, do I have to set the ownership before/after the initialization? currently I change ownership to CPU2 after I initialize the EMIF on CPU1.
  • After EMIF1 configuration, what is the value you are seeing in the configuration register in CCS register view (or expression view) ?
  • If you are seeing the reset value in all the fields then you may not be updating the CL field correctly. To update CL field you also need to write '1' to bit 8 (BIT_11_9_LOCK). It may be good idea to write SDRAM register as 32bit instead of individual bits because some of bit write start SDRAM initialization sequence.

    Also I am assuming that you are doing the GPIO setting from CPU1 only and not from CPU2 because that is not supported from CPU2. If you could send the detail of sequence done from CPU1 code and CPU2, it'll be helpful.

    Vivek Singh
  • This is what it currently looks like taking all you informed me of yesterday.

    Yes, your correct in assuming I am setting GPIO on CPU1.

    First can I clairify:

    For the setting of the TIMING values, T_RP, T_RC etc in SDRAM_TR register, the manual states it's to be programmed in clock cycles.  if the data sheet lists say 18 ns and the external clock is 100MHz or 10ns, do we input a value of 2?  ie: round 18 up to 20, then divide by 10ns to get 2?

    Also they all say minus 1... so in the above example would I then program 1?

    So if the timing was 60ns, then this would be 6 clock cycles, but because the minus 1 we should enter 5?  correct?

    NEXT:

    This is what I'm observing, in the setting of ownership, the documents state 00 = CPU1 but CPU2 can grab, and 01, CPU1 owns EMIF and 02 CPU2 owns EMIF1 and 11 CPU1 but CPU2 can grab...

    I observe that if I try and set this while on CPU1 to let CPU2 own it... it doesn't do anything... but if I 'grab' the EMIF by setting this same register ON CPU2, then CPU2 grabs it...  Also, if I did set this regiser on CPU1, and set it to CPU1 then CPU2 is not able to grab it...

    The point being... is it wasn't clear that I had to SET this register while ON CPU2, to 'grab' the ownership of the EMIF...  all your other ownership (memory etc.) I have performed on CPU1, thinking, I set this to let CPU2 OWN it... but in this one case it appears you MUST grab (meaning set the ownership) from CPU2...

    Can you confirm this is the correct behavoiur?

    So I essentially need to put this line in CPU2 to have it grab ownership of the EMIF1.

     Emif1ConfigRegs.EMIF1MSEL.all = 0x93a5ce72;

    This solves one mystery, I can now set all the registers from CPU2 and observe their proper settings.



  • Upon further testing, it is performing better, but I need the answer to the clairification on how to set the timing registers with regard to the clock and the minus 1. Also note on WR one it says 'for SDR' while on all the others it just says:

    WR
    For SDR, this is equal to minimum number of EMxCLK cycles from
    last Write transfer to Precharge, minus one.

    RC (and all others follow this format)
    Minimum number of EMxCLK cycles from Activate to Activate minus
    one.

    what is meant by 'For SDR'?

    SUMMARY;
    Is the procedure to take the timing values in ns from the part data sheet, divide by the 100MHz in our case or 10ns clock, then subtract one for ALL these values?

    I can already tell you that if I do this I don't see correct write bus cycle... If I do the above I see Ras, then Cas, then wE.... So I need to be clear how to set them. Thanks.

    Thanks very much for your support, it helped me find the problem much quicker.

  • Hi Rob,

    Good to know it is working fine. As mention in the definition EMIF1MSEL register bit, the control for EMIF need to be grabbed by individual masters. This is different compare to other master ownership control.

    About the register setting, your understanding is correct. All the values are in cycles and you need to round the number in multiple of EMIF clock cycles and then subtract 1 to get configuration value. There is an example given in "Table 25-27. SDRAM_TR Field Calculations for EMIF". Please refer the same.

    RC (and all others follow this format)
    Minimum number of EMxCLK cycles from Activate to Activate minus
    one.

    what is meant by 'For SDR'?

    SDR is for SDRAM setting (not for DDR).

    Regards,

    Vivek Singh

  • Thanks for the help so far.

    Unfortunately it's still not completely working.

    I need to ask you for your insight on what might be set wrong on the TI part.

    I can capture the autoinitialization sequence on the scope and it looks perfect as per the description in 25.3.5.4

    All that needed to be changed was where I put the ownership of the EMIF (moved it to CPU2) to achieve this.

    I have verified by the example that I am setting the registers correctly for the selected memory.

    Emif1Regs.SDRAM_TR.bit.T_RAS = 4;

    Emif1Regs.SDRAM_TR.bit.T_RC = 5;

    Emif1Regs.SDRAM_TR.bit.T_RCD = 1;

     Emif1Regs.SDRAM_TR.bit.T_RFC = 5;

    Emif1Regs.SDRAM_TR.bit.T_RP = 1;

    Emif1Regs.SDRAM_TR.bit.T_RRD = 1;

    Emif1Regs.SDRAM_TR.bit.T_WR = 1;

    Emif1Regs.SDR_EXT_TMNG.bit.T_XS = 6;

     

    Now when I write some data out in code, I see the code composer window update with that data at all addresses 0x80000000 and onwards, the full 32 bits though.

    However I currently do a sample test:  (where theMatrixUI->theArrayUI[0] = 0x80000000

    for (;;) {

    theMatrixUI->theArrayUI[0] = 2882342889; // hex 0xabcd0fe9

    theMatrixUI->theArrayUI[1] = 0;

    theMatrixUI->theArrayUI[2] = 1;

    theMatrixUI->theArrayUI[3] = 2;

    theMatrixUI->theArrayUI[4] = 3;

    values[0] = theMatrixUI->theArrayUI[0];

    values[1] = theMatrixUI->theArrayUI[1];

    values[2] = theMatrixUI->theArrayUI[2];

    values[3] = theMatrixUI->theArrayUI[3];

    values[4] = theMatrixUI->theArrayUI[4];

    i = theMatrixUI->theArrayUI[0];

    if ( i == 2882342889 ) {

    asm(" ESTOP0");

    values[0] = i;

    }

    theMatrixUI->theArrayUI[0] = 47;

    i = theMatrixUI->theArrayUI[3];

    if ( i == 2 ) {

    asm(" ESTOP0");

    values[3] = i;

    }

    }

    If it correctly reads the data, it should hit my ESTOP0 when running at full speed, and it never does...

     

    I structured the test based on your statement that the data bus will hold the last value written...  naturally, if I change the above program to include something like:

    theMatrixUI->theArrayUI[whateverIndex] = someNumber;

    i = theMatrixUI->theArrayUI[whateverIndex];

    if ( i == someNumber ) {

    asm(" ESTOP0");

    Then it of course works, because some number is the very last thing I wrote to the bus... ie: it hits the ESTOP0,

     

    SO that is why I structured the code above to not test the value that was just written...  to test if it's really reading it...

     

    Now when I look at the write cycle on the scope, it doesn't entirely look correct.  The main thing is the Ras occurs first, then cas, then WE...  but WE is supposed to occur at the same time as cas correct?  WE is starting to drop 1 clock cycle after the CAS line, so it's one cycle late...

     

    So the question is, with the values that I have programed for timings, why is the TI part apparently generating a slightly perturbed write cycle...

     

    Does this have anything to do with the debugger?

     

    Also, with these settings when I write with the Code composer memory window I still see the 16 bit replication as opposed to the 32 bit replication I see when I write with code...

     

    Any thoughts on:

    1.  Why the we could be delayed on the write cycle,

    2.  why I'm essentially only able to read what was last put on the bus?  (I assume this is because the write cycle is incorrect, so it's not actually writing to memory, and While I haven't checked the read cycle I imagine that something must be wrong there, cause if it was correct it should read whatever is stored in SDRAM and drive the bus accordingly...

     3.  Is it possible I am asking it to exceed some max/min limit so the EMIF is unable to generate the proper cycle because I'm 'out of bounds'

    Thanks.

  • Thanks Vivek.

    I looked at your F2837xD_Emif.c file and need to ask some clarifying questions.

    I am finally able to read and write to SDRAM, and I can do so in code, and through the code composer memory window... but the following things need clairification:

    in F2837xD_Emif.c under version 200 (I haven't started using your 210 version yet) there is a function setup_emif1_pinmux_sdram_32bit

    in this function you setup the GPIO pins as I was, calling your GPIO_SetupPinMux...

    This is identical to what I do EXCEPT... you call GPIO_SetupPinMus(94  ...

    Clairification 1:

    why do you setup pin 94?  In the table 7-8 pin94 has now EMIF specific function...  In fact on our board we have assigned a specific purpose to GPIO94...

    So I just need to clarify that pin 94 is being used for something else perhaps in that sample application and has nothing to do with EMIF1.

    Clairification 2:

    You then proceed to call GPIO_SetupPinOptions for the data lines and the EM1DQM0-3 lines....  you set them to an input with pullup and ASYNC mode (the 0 is input, and 0x31 is async ored with pullup)

    I find this a bit confusing.  Section 25.2 does state that that we should set inputs to async, and talks about setting the pullups...  but the data lines are I/O and the EM1DQM0-3 are listed as outputs?  SO the clarification is:  HOw would I possibly know to set these as they are doing in that sample?  Since the direction register is input OR output not INPUT AND OUTPUT this is a bit confusing from that perspective...  and since the EM1DQM0-3 are listed as output, why am I setting them as input with pullup and async?  (pins 88-91)

    Clairification 3:

    On the scope, I now see the WE pulse low at the same time as CAS as it should, it's wide for a longer period...

    Reviewing how the same file sets the timing registers (emif_32bit_sdram.c) for it's particular part...

    //

    //Configure SDRAM control registers

    //

    // Need to be programmed based on SDRAM Data-Sheet.

    //T_RFC = 60ns = 0x6

    //T_RP = 18ns = 0x1

    //T_RCD = 18ns = 0x1

    //T_WR = 1CLK + 6 ns = 0x1

    //T_RAS = 42ns = 0x4

    //T_RC = 60ns = 0x6

    //T_RRD = 12ns = 0x1

    based on what we discussed, I would read this as T_RFC should be set to 5 or 60ns/10ns clock = 6 -1 = 5, but here he sets it to 6?

    T_WR why does he put 1clk plus? is that specific to the part used in this example... if so it's okay,

    The point is T_RC and T_RFC are set differently by 1 clock that what I am understanding...  what is the correct way to compute these two?

    Clairification 4:

    protection registers set?  I assume since the one register looks like a set ONCE feature, the idea here is to lock these settings in the part, likely since once you have SDRAM assigned you won't want to have it accidentally change...  so we don't have to set it, its just optional.

    //

    // Grab EMIF1 For CPU1

    //

    Emif1ConfigRegs.EMIF1MSEL.all = 0x93A5CE71;

    if(Emif1ConfigRegs.EMIF1MSEL.all != 0x1)

    {

    ErrCount++;

    }

    //

    //Disable Access Protection (CPU_FETCH/CPU_WR/DMA_WR)

    //

    Emif1ConfigRegs.EMIF1ACCPROT0.all = 0x0;

    if(Emif1ConfigRegs.EMIF1ACCPROT0.all != 0x0)

    {

    ErrCount++;

    }

    //

    // Commit the configuration related to protection. Till this bit remains

    // set content of EMIF1ACCPROT0 register can't be changed.

    //

    Emif1ConfigRegs.EMIF1COMMIT.all = 0x1;

    if(Emif1ConfigRegs.EMIF1COMMIT.all != 0x1)

    {

    ErrCount++;

    }

    //

    // Lock the configuration so that EMIF1COMMIT register can't be changed

    // any more.

    //

    Emif1ConfigRegs.EMIF1LOCK.all = 0x1;

    if(Emif1ConfigRegs.EMIF1LOCK.all != 1)

    {

    ErrCount++;

    }

    Clairification 5:

    I see the WE pulse go low AFTER CAS on a read request... the timing diagram shows it as staying high?  While this doesn't appear to be causing any issue, the question is more why is the part generating a low WE on a read cycle at all?  Could this have something to do with my apparent double width WE pulse on a write cycle? could this be related to the setting of the registers differences that I see (T_RC & T_RFC) such that whatever is causing the double width WE pulse might be why we see the 2nd cycle on the read cycle as well?

    Thanks.

  • Hi Rob,

    Good to know you got it working.

    Clairification 1:

    why do you setup pin 94?  In the table 7-8 pin94 has now EMIF specific function...  In fact on our board we have assigned a specific purpose to GPIO94...

    GPIO94 is not needed. You can use it for whatever other function needed.

    Clairification 2:

    As I mentioned in one of my earlier post, the INPUT selection from GPIO register is don't care if pin is used as EMIF. So that part is redundant.

    Clairification 3:

    Since the number is 60, we should programmed the value 5 or higher value. In this case we have programmed 6 which is ok but  even 5 should work.

    Clairification 4:

    protection registers set?  I assume since the one register looks like a set ONCE feature, the idea here is to lock these settings in the part, likely since once you have SDRAM assigned you won't want to have it accidentally change...  so we don't have to set it, its just optional.

    That is correct. This is optional configuration.

    Clairification 5: I see the WE pulse go low AFTER CAS on a read request... the timing diagram shows it as staying high?  While this doesn't appear to be causing any issue, the question is more why is the part generating a low WE on a read cycle at all?  Could this have something to do with my apparent double width WE pulse on a write cycle? could this be related to the setting of the registers differences that I see (T_RC & T_RFC) such that whatever is causing the double width WE pulse might be why we see the 2nd cycle on the read cycle as well?

    I think this is burst terminate command after READ (same would be applicable for write as well). Please note that for SDRAM the max burst is 1 access (except for 32bit access to 16bit SDRAM device where it'll be 2 ) on this device so after every access there will be burst terminate command.

    Regards,

    Vivek Singh