Content originally posted in LPCWare by bunrockter on Tue Aug 07 00:32:29 MST 2012
I am using the Hitex LPC4350 eval board. I have been able to get it up and running and get my code going. It is now time to hook up an external LCD, but I need to have SDRAM working to have a place to store a frame buffer that is big enough.
First off I am seeing some weird behavior. I am using crossworks, and after initializing the RAM (I hope), when I look at it in the memory viewer the first 32 bit word will change its higher addressed 16 bits between 2 values when I request a memory read. Then eventually all of the memory becomes 0xAAAAAAAA including the registers. The JTAG can't stop the processor, I have to reset the board to get control back.
I have even and a verification error that tells me that the JTAG and what crossworks thought it programmed were not the same. A few times there were all A's and other times there were interleaved block that were invalid.
Now I am at the point, that as soon as I enter the break point on the first line of my code to initialize SDRAM the processor hangs, and I have to reset. If I comment out the call to the method things work just fine, and my other code works great.
Needless to say I am confused, as the first line of code is just a write to a bit int the ECM Control register that should already be set on reset. Is there something else going on? Anyways here is my code
Thanks,
Bun
//EMC Config
LPC_EMC->CONTROL |= (1UL); //Enable EMC
LPC_EMC->CONTROL |= (1UL << 2); //Low Power Clocks
LPC_EMC->CONTROL &= !(1UL << 1); //Enable normal memory map mode
LPC_EMC->CONFIG |= (1UL << 8); //Set clk to half mode
//clock configuration
LPC_CCU1->CLK_M4_EMC_CFG |= (1 << 5); //Set the clock divider into the emc to divide by 2
LPC_CREG->CREG6 |= (1 << 16);
//Configuration common to all dynamic memories
//LPC_EMC->DYNAMICCONTROL |= (1UL); //Set All clocks high
LPC_EMC->DYNAMICREFRESH = N_TO_EMC_CLOCKS(15625UL)>>4; // Multiples of 16 CLK (1=16)
LPC_EMC->DYNAMICREADCONFIG = N_TO_EMC_CLOCKS(1UL); // Do not leave at 0
LPC_EMC->DYNAMICRP = N_TO_EMC_CLOCKS(18UL) - 1; // tRP- (n+1 (my data sheet has tRP but no tPR
LPC_EMC->DYNAMICRAS = N_TO_EMC_CLOCKS(42UL) - 1; // tRAS - (n+1) (Data sheet says 42-1000)
LPC_EMC->DYNAMICSREX = N_TO_EMC_CLOCKS(66UL) - 1; // tSREX,tXSR- (n+1)
LPC_EMC->DYNAMICAPR = 3UL -1; // tAPR - n+1 (Not found in data sheet)
LPC_EMC->DYNAMICDAL = N_TO_EMC_CLOCKS(18UL) +2; // tDAL,tAPW - 2 clk + trp (18ns)
LPC_EMC->DYNAMICWR = 2UL -1; // tWRt,tDPL,tRWL,,tRDL - (n+1)
LPC_EMC->DYNAMICRC = N_TO_EMC_CLOCKS(60UL) - 1; // tRC - (n+1)
LPC_EMC->DYNAMICRFC = N_TO_EMC_CLOCKS(60UL) - 1; // tRFC,tRC - (n+1) TODO: couldn't find value used tRC
LPC_EMC->DYNAMICXSR = N_TO_EMC_CLOCKS(66UL) - 1; // tXSR - (n+1)
LPC_EMC->DYNAMICRRD = N_TO_EMC_CLOCKS(12UL) - 1; // tRRD - (n+1)
LPC_EMC->DYNAMICMRD = 2UL -1; // tMRD,tRSA - (n+1)
//Configuration specific to each memory by chip select (only setting up chip select 0)
//Address mapping for our part (IS42S16400F-6TL)
// 14 12 11:9 8:7
// 0 0 001 01 64 Mb (4Mx16), 4 banks, row length = 12, column length = 8 enhanced
// 0 1 001 01 64 Mb (4Mx16), 4 banks, row length = 12, column length = 8 normal
LPC_EMC->DYNAMICCONFIG0 |= (1UL << 7); //AM0 12:7 Address mapping
LPC_EMC->DYNAMICCONFIG0 |= (1UL << 9);
LPC_EMC->DYNAMICCONFIG0 |= (1UL << 12);
LPC_EMC->DYNAMICRASCAS0 |= (3UL); //RAS latency
LPC_EMC->DYNAMICRASCAS0 |= (3UL << 8); //CAS latency picked from datasheet and drives all other values
//Initialization of the SDRAM
LPC_EMC->DYNAMICCONTROL = (1UL << 0) | (1UL << 1) | (0 << 7); //CS=1 CE=1 OP=Normal Send idle
waitUS(100);
LPC_EMC->DYNAMICCONTROL = (1UL << 0) | (1UL << 1) | (2 << 7); //CS=1 CE=1 OP=Precharge Send precharge
LPC_EMC->DYNAMICREFRESH = 1;
waitUS(100);
LPC_EMC->DYNAMICREFRESH = N_TO_EMC_CLOCKS(15625UL) >>4;
waitUS(100);
LPC_EMC->DYNAMICCONTROL = (1UL << 0) | (1UL << 1) | (1 << 7); //CS=1 CE=1 OP=MODE Send mode
uint32_t modeRegValue = 0;
modeRegValue |= 3UL; //8 burst
modeRegValue |= (0UL << 3); //Sequential
modeRegValue |= (3UL << 4); //CAS of 3
modeRegValue |= (0UL << 7); //standard
modeRegValue |= (0UL << 9); //programed
modeRegValue = SDRAM0_ADDR + (modeRegValue << (8 + 1 + 2));
modeRegValue = *((volatile uint32_t *)modeRegValue); // Set mode register!
waitUS(200);
LPC_EMC->DYNAMICCONTROL = 0;//(0UL << 0) | (0UL << 1) | (0 << 7); //CS=0 CE=0 OP=MODE
LPC_EMC->DYNAMICCONFIG0 = (1UL << 19); //enable buffers
//Mem Test
volatile uint32_t * ramPtr = (volatile uint32_t *)(SDRAM0_ADDR);
uint32_t testVal = 0x102;
while((uint32_t)ramPtr < (SDRAM0_ADDR + 4000000UL))
{
*ramPtr = testVal;
++ramPtr;
testVal += 0x101;
}