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.

external ram problem

Other Parts Discussed in Thread: EK-TM4C1294XL

Hello

For my bachelor thesis I am working on a project based on the LaunchPad EK-TM4C1294XL. I connected an external sdram (IS42S16320D-7TL) to the epi of the microcontroller. I am using tivaWare and the epi example with an adjusted pin configuration. The example, which writes and reads the first and the last two elements of the ram works perfectly.

To be shure that all cells of the memory are working, I wrote a little test script, which writes in all cells the same value and reads it back afterwards. If the written and the read value differ, it prints a message on the uart. After the read, the value is incremented, so that every cell is tested with every possible value.

Unfortunately I get very strange results with specific values and I can’t figure out why.

The first error occurs allways at the value 0x8000. The addresses differ, but are always even.

It is the first time I am working with external sdram and I already spend some nights on that problem, but couldn't find a solution for it. That’s why I would like to ask more experienced users for help.

Thank you

Jochen

I append my test code, parts of a uart log file.

4722.putty1.log

#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_uart.h"
#include "inc/hw_epi.h"

#include "driverlib/gpio.h"
#include "driverlib/epi.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/rom_map.h"
#include "driverlib/sysctl.h"

#include "driverlib/uart.h"

#include "utils/uartstdio.h"
#include "utils/ustdlib.h"



//*****************************************************************************
//
// The starting and ending address for the 64MB SDRAM chip (32Meg x 16bits) on
// the SDRAM daughter board.
//
//*****************************************************************************
#define SDRAM_START_ADDRESS 0x00000000
#define SDRAM_END_ADDRESS   0x01FFFFFF		//= dez33554431 = 33554432 Zellen a 16 Bit = 8192 Zeilen * 1024 Spalten * 4 Banks


//*****************************************************************************
//
// The Mapping address space for the EPI SDRAM.
//
//*****************************************************************************
#define SDRAM_MAPPING_ADDRESS 0x60000000


//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>uDMA (udma_demo)</h1>
//!
//!
//! UART0, connected to the ICDI virtual COM port and running at 115,200,
//! 8-N-1, is used to display messages from this application.
//
//*****************************************************************************

//****************************************************************************
//
// System clock rate in Hz.
//
//****************************************************************************
uint32_t g_ui32SysClock;




//*****************************************************************************
//
// pointer to SDRam Beginning
//
//*****************************************************************************
static volatile uint16_t *g_pui16EPISdram;



//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif




void
ConfigureUART(void)
{
    //
    // Enable the GPIO Peripheral used by the UART.
    //
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);

    //
    // Enable UART0
    //
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
    MAP_SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UART0);

    //
    // Configure GPIO Pins for UART mode.
    //
    MAP_GPIOPinConfigure(GPIO_PA0_U0RX);
    MAP_GPIOPinConfigure(GPIO_PA1_U0TX);
    MAP_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);

    //
    // Initialize the UART for console I/O.
    //
    UARTStdioConfig(0, 115200, g_ui32SysClock);
}


//*****************************************************************************
int
main(void)
{


    //
    // Set the clocking to run directly from the crystal at 120MHz.
    //
    g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                             SYSCTL_OSC_MAIN |
                                             SYSCTL_USE_PLL |
                                             SYSCTL_CFG_VCO_480), 120000000);

    ConfigureUART();

    SysCtlDelay(30000000);
    UARTprintf("\033[2J\033[H");	//clear window
	UARTprintf("EPI Demo\n");

	//Enable EPI Module
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_EPI0);

	//Enable GPIO Ports
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOG);
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOK);
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOL);
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOM);
	MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);

	//Enable GPIO special function
	MAP_GPIOPinConfigure(GPIO_PK0_EPI0S0);
	MAP_GPIOPinConfigure(GPIO_PH1_EPI0S1);
	MAP_GPIOPinConfigure(GPIO_PK2_EPI0S2);
	MAP_GPIOPinConfigure(GPIO_PK3_EPI0S3);
	MAP_GPIOPinConfigure(GPIO_PC7_EPI0S4);
	MAP_GPIOPinConfigure(GPIO_PC6_EPI0S5);
	MAP_GPIOPinConfigure(GPIO_PC5_EPI0S6);
	MAP_GPIOPinConfigure(GPIO_PC4_EPI0S7);
	MAP_GPIOPinConfigure(GPIO_PA6_EPI0S8);
	MAP_GPIOPinConfigure(GPIO_PA7_EPI0S9);
	MAP_GPIOPinConfigure(GPIO_PG1_EPI0S10);
	MAP_GPIOPinConfigure(GPIO_PG0_EPI0S11);
	MAP_GPIOPinConfigure(GPIO_PM3_EPI0S12);
	MAP_GPIOPinConfigure(GPIO_PM2_EPI0S13);
	MAP_GPIOPinConfigure(GPIO_PM1_EPI0S14);
	MAP_GPIOPinConfigure(GPIO_PM0_EPI0S15);
	MAP_GPIOPinConfigure(GPIO_PL0_EPI0S16);
	MAP_GPIOPinConfigure(GPIO_PL1_EPI0S17);
	MAP_GPIOPinConfigure(GPIO_PL2_EPI0S18);
	MAP_GPIOPinConfigure(GPIO_PL3_EPI0S19);
	//EPI020 ... EPI027 not used for SDRAM
	MAP_GPIOPinConfigure(GPIO_PB3_EPI0S28);
	MAP_GPIOPinConfigure(GPIO_PN2_EPI0S29);
	MAP_GPIOPinConfigure(GPIO_PN3_EPI0S30);
	MAP_GPIOPinConfigure(GPIO_PK5_EPI0S31);

	GPIOPinTypeEPI(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7);
	GPIOPinTypeEPI(GPIO_PORTB_BASE, GPIO_PIN_3);
	GPIOPinTypeEPI(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
	GPIOPinTypeEPI(GPIO_PORTG_BASE, GPIO_PIN_0 | GPIO_PIN_1);
	GPIOPinTypeEPI(GPIO_PORTH_BASE, GPIO_PIN_1);
	GPIOPinTypeEPI(GPIO_PORTK_BASE, GPIO_PIN_0 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_5);
	GPIOPinTypeEPI(GPIO_PORTL_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
	GPIOPinTypeEPI(GPIO_PORTM_BASE, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3);
	GPIOPinTypeEPI(GPIO_PORTN_BASE, GPIO_PIN_2 | GPIO_PIN_3);

	//
	// Set the EPI divider.
	//
	EPIDividerSet(EPI0_BASE, 1);		//1 ==> 1/2 * sysClock = 60MHz
	//
	// Select SDRAM mode.
	//
	EPIModeSet(EPI0_BASE, EPI_MODE_SDRAM);
	//
	// Configure SDRAM mode.
	//
	EPIConfigSDRAMSet(EPI0_BASE, (EPI_SDRAM_CORE_FREQ_50_100 |
	EPI_SDRAM_FULL_POWER | EPI_SDRAM_SIZE_512MBIT), 400);		
	//
	// Set the address map.
	//
	EPIAddressMapSet(EPI0_BASE, EPI_ADDR_RAM_SIZE_256MB | EPI_ADDR_RAM_BASE_6);		//Although our SDRAM is only 64MB, there is no 64MB aperture option so we pick the next larger size.
	//
	// Wait for the EPI initialization to complete.
	//
	while(HWREG(EPI0_BASE + EPI_O_STAT) & EPI_STAT_INITSEQ)
	{
	//
	// Wait for SDRAM initialization to complete.
	//
	}

	// Set Pointer to beginning of SDRam
	g_pui16EPISdram = (uint16_t *)0x60000000;		//other adresses possible to, see errata sheet

	//
	// At this point, the SDRAM is accessible and available for use.
	//


	  //
	    // Read the initial data in SDRAM, and display it on the console.
	    //
	    UARTprintf("  SDRAM Initial Data:\n");
	    UARTprintf("     Mem[0x6000.0000] = 0x%4x\n",
	               g_pui16EPISdram[SDRAM_START_ADDRESS]);
	    UARTprintf("     Mem[0x6000.0001] = 0x%4x\n",
	               g_pui16EPISdram[SDRAM_START_ADDRESS + 1]);
	    UARTprintf("     Mem[0x603F.FFFE] = 0x%4x\n",
	               g_pui16EPISdram[SDRAM_END_ADDRESS - 1]);
	    UARTprintf("     Mem[0x603F.FFFF] = 0x%4x\n\n",
	               g_pui16EPISdram[SDRAM_END_ADDRESS]);



	    //
	   // Display what writes we are doing on the console.
	   //
	   UARTprintf("  SDRAM Write:\n");
	   UARTprintf("     Mem[0x6000.0000] <- 0xabcd\n");
	   UARTprintf("     Mem[0x6000.0001] <- 0x1234\n");
	   UARTprintf("     Mem[0x603F.FFFE] <- 0xdcba\n");
	   UARTprintf("     Mem[0x603F.FFFF] <- 0x0000\n\n");

	   //
	   // Write to the first 2 and last 2 address of the SDRAM .  Since the
	   // SDRAM card is word addressable, we will write words.
	   //
	   g_pui16EPISdram[SDRAM_START_ADDRESS] = 0xabcd;
	   g_pui16EPISdram[SDRAM_START_ADDRESS + 1] = 0x1234;
	   g_pui16EPISdram[SDRAM_END_ADDRESS - 1] = 0xdcba;
	   g_pui16EPISdram[SDRAM_END_ADDRESS] = 0x0000;

	   //
	   // Read back the data you wrote, and display it on the console.
	   //
	   UARTprintf("  SDRAM Read:\n");
	   UARTprintf("     Mem[0x6000.0000] = 0x%4x\n",
				  g_pui16EPISdram[SDRAM_START_ADDRESS]);
	   UARTprintf("     Mem[0x6000.0001] = 0x%4x\n",
				  g_pui16EPISdram[SDRAM_START_ADDRESS + 1]);
	   UARTprintf("     Mem[0x603F.FFFE] = 0x%4x\n",
				  g_pui16EPISdram[SDRAM_END_ADDRESS - 1]);
	   UARTprintf("     Mem[0x603F.FFFF] = 0x%4x\n\n",
				  g_pui16EPISdram[SDRAM_END_ADDRESS]);
				  
				  
	   UARTprintf("full Test\n\n\n");
	   for(j=0x7fff;j<=0xFFFF;j++)
	   {

		   UARTprintf("\n\nWert 0x%4x\n\n",j);
		   for(i = SDRAM_START_ADDRESS; i<=SDRAM_END_ADDRESS;i++)
		   {
			   g_pui16EPISdram[i] = j;
		   }

 		   for(i = SDRAM_START_ADDRESS; i<=SDRAM_END_ADDRESS;i++)
		   {
			   tmp = g_pui16EPISdram[i];
			   if(tmp != j)
				   UARTprintf("A %10d W:0x%4x\n", i, tmp);	//Adresse Istwert
		   }
	   }		

    while(1)
    {}
}	

  • Hate to see someone's well written post just sit - but confess I haven't time to review your code.

    I'd look carefully at the EPIs handling of the address bit which toggles high to yield 0x8000.  That's the 13th bit (starting from bit 0 as ls bit) is it not?  Does that bit properly toggle high @ 0x8000?  And - does that signal really reach your external sdram?  Further - might that sdram enforce some special (fold-over) or other address scheme - which you may have missed?

    I'm confounded by your writing: " The addresses differ, but are always even."  (this just after your 0x8000 example)  It appears that you're "error-free" thru address 0x7FFF.  Is that correct?  But - the meaning of your other sentence escapes my understanding.

    What happens @ 0x8001, 0x8002, 0x8888?  Does correct data land - and can be recovered - each listed location?

    I'd be very careful not to "repeat" too simple data @ those addresses 0x8000 & beyond.  If that bit @ 0x8000 is missed/lost/rejected - do not you read/write to 0x0000?  Watch for this "masking" of earlier errors - it's not unusual for new users to test improperly - and (enjoy) "false positive" success.

    Suggest that you carefully, methodically test @ other key Address inflections: 0x400, 0x800, 0x1000, 0x2000, 0x4000 and then 0x8000.  Do the lower addresses all (really) work?

    If 0x8000 is as you say - the FIRST sdram location to fault - might the capacity of that sdram have been reached?  If not - I'd bet that your understanding of the sdram's address scheme OR the EPI set-up/config of the MCU is improper. 

    I'd start with unique writes/reads to those listed lower sdram locations (only).  Always use new, distinctive data - you do not want a "false positive" read.  (which may easily result from an accepted write to a lowered order address - differing only by the highest bit currently set.)

  • Hello Jochen,

    Since it is the first time you are using external SDRAM, it would be good as well to look at the schematic for making sure we do not have a wiring issue too.

    cb1's code insight is also valuable...

    Regards

    Amit

  • Thank you for your reply

    I think I found the problem. The connection of the ground pins is to small. Soldering wires on top of the ground connections reduced the problem a lot. I am going to improve my layout and make a new pcb.

    Cadsoft Eagle Files:

    My pcb has male pin headers and is put underneath the launchpad

    The adc's on the board are not used during the ram test.

    1541.sandwich v2.sch

    4314.sandwich v2.brd

  • Jochen Genth said:
    I think I found the problem.

    I do not!  Have never noted a ground connection/routing to plague any singular address - as your initial post reports.  Indeed ground is important - but the "0x8000 unique problem" is extremely hard to tie back to any ground issue.

    You "think" you found the problem - yet you provide no description to justify such thought.  Thus those here are clueless as to what their actions should be - should they experience (likely "when" they experience) a similar issue.  That's not good.

    Indeed an errant connection - imposed upon a critical address bit(s) - will confound reading/writing to that ram location. But that's not what you describe - and ground issues are not famed for causing "address specific" data error/havoc.  Your first and more recent, "report of findings" seem in conflict - and your, "reduced the problem a lot" description is close relative to always precise/illuminating, "Does not work!"  Respinning a pcb - when testing is incomplete & likely less than fully consequential - harks back to past days of, "auto repair" when every part w/in the engine was replaced - and then "magically" the engine ran...  (seems not the best course of action for any "education!")

    A comprehensive MCU-Ram test procedure - not ours (borrowed/stolen from the past) - was provided.  Building a fresh board - w/out harvesting more data - would not be my recommendation! 

  • Jochen Genth said:
    The first error occurs allways at the value 0x8000. The addresses differ, but are always even.

    In the attached program the first value tested is 0x7fff:

    	   UARTprintf("full Test\n\n\n");
    	   for(j=0x7fff;j<=0xFFFF;j++)
    

    If the starting value was 0x0 do the errors occur at any values less than 0x8000?

    Also, if Address Bus Test and Data Bus Tests are performed as per http://www.esacademy.com/en/library/technical-articles-and-documents/miscellaneous/software-based-memory-testing.html what do they show?

  • I second cb1 and Chester.

    Your ground might be a problem (and if it actually fixes or partially fixes I'd check your decoupling and layout).  However I think you do need to run a proper memory test.  Michael Barr's test that Chester pointed to you is a good start.  It will help you more fully characterise the problem.

    The one thing you need to be wary of is making a change and thinking it's fixed your memory without actually fully testing it.

    Robert

  • Robert Adsett said:
    thinking it's fixed your memory without actually fully testing it.

    Properly and fully testing wins my vote...

    I seem alone in rejecting "ground" as a, "prime suspect" in any, "singular address failure."  In years of past proto board (or early/first article boards) test/verify - ground issues caused more generalized faults - I cannot recall any that were so tightly (i.e. confined to a single address - as poster first reported) restricted!

    Would you be so good as to comment in that (ground specific) regard, Robert?

  • Hello

    Thank you for your advice.

    My last post was a bit short.

    First of all there seems to be a misunderstanding about the address and the value. 0x8000 which I mentioned in my fist post is the first value at which an error occured at multiple adresses. There are other values at which errors occurred again on multiple addresses.

    	   for(j=0x8000;j<=0xFFFF;j++)
    	   {
    
    		   UARTprintf("\n\nWert 0x%4x\n\n",j);
    		   for(i = SDRAM_START_ADDRESS; i<=SDRAM_END_ADDRESS;i++)
    		   {
    			   g_pui16EPISdram[i] = j;
    		   }
    
     		   for(i = SDRAM_START_ADDRESS; i<=SDRAM_END_ADDRESS;i++)
    		   {
    			   tmp = g_pui16EPISdram[i];
    			   if(tmp != j)
    				   UARTprintf("A %10d W:0x%4x\n", i, tmp);	//Adresse Istwert
    		   }
    	   }
    

    I found the ground problem by measuring the difference between the ground potential at the ram pins and at the launchpad pins. The difference while running my test program was up to 400 mV.

    I think that the problem was that some pins could not discharge fast enough, because the resistance to ground was to high.  Another sign that leads to my theory is, that the error always occurred at addresses,  where a lot of bits must be pulled low e.g. the change from 0x7fff to 0x8000.

    You are right that I have to run a full test to be sure, that the memory is relay working,.

    Thank you for the link. I will try the proposed test when I have time.

    Thank you for your help!

    Jochen

  • cb1- said:

    Would you be so good as to comment in that (ground specific) regard, Robert?

    Not so much "prime suspect" as "interesting possibility".  There is one thing about that address that makes it intriguing in this regard, when you step to that address from 0x7FFF you flip 16 bits which is a fairly hefty disturbance.

    Also if the pattern bears out I'd suggest investigating the decoupling.  DRAM can have significant current spikes. Changing the grounding leads may be masking an issue with the decoupling (either too small, too few or poor layout).

    The OP has said we have misread the 0x8000 as address when it should be value.  That makes decoupling even more important to look at IMO.

     

    Robert

  • @Robert,

    Thank you - appreciated.  Poster is too vague (and too slow responding) for my taste.

    Yet - I identified (1st answering post) multiple other, "comprehensive bit toggle points" (i.e. 0x4000, 0x2000 etc.) which very likely would serve to cause/create that same current impulse effect.  Poster was silent in his read of or execution of that, "test/verify" suggestion.

    I read his first post as, "All was well until 0x8000" and that strongly indicated that all past, "comprehensive bit toggle points" had passed - performed correctly. 

    Language - care in detail/presentation are important.  Ground issue upon a single address - even a "special" one - remains an unlikely cause of a single, address failure...  (especially so when very similar "special addresses" have escaped data, "hiccup.")

  • Robert Adsett said:
    The OP has said we have misread the 0x8000 as address when it should be value.

    From reading the test code, each test involves writing the same data value to all addresses and then checking that the value is read back from all addresses. That in itself may mask errors with the the addressing not working correctly.

    My understanding is that the failures only occur when data values 0x8000 to 0xffff are written to all addressesi.e. when data bit 15 is set. I don't know if it is a clue but:

    - EPI signals EPI0S0 to EPIS14 are connected to a SDRAM address bits A0-A12,BA0-BA1 and SDRAM data bits 0-14

    - EIP signal EPI0S15 is only connected to a SDRAM data bit 15