Dear LPC Community,
I use a LPC4357 at 204MHz with an external SDRAM at 102MHz.
The SDRAM is a Micron MT48LC8M32B2 (datasheet link).
I ~thought~ all was working fine (with quite frequent writes and reads of a few hundred to a few kBytes as a shared buffer between the cores - all DMA transfers), but now another function was added which reads larger chunks up 512kB and writes them to an SD card (also using some direct DMA transfer and the SDMMC DMA mode as part of the SDIF driver). The read also 'works' (the 512kB are written correct on the card) but afterwards the data in the SDRAM gets corrupted, at least for a while. I see 'gaps' (blank areas) and repeats of data from earlier in the SDRAM but can't really make out what exactly happens.
Here's my SDRAM initialization code:
#define BUFFER_BASE 0x28000000
#define MS 8350 // for() loop count to delay 1 ms (measured)
void SDRAM_Init (void) {
uint32_t pclk, temp;
uint64_t tmpclk;
uint32_t i = 0;
uint32_t MODE;
uint32_t OFFSET;
Chip_SCU_PinMuxSet( 2 , 9 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //A0
Chip_SCU_PinMuxSet( 2 , 10 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //A1
Chip_SCU_PinMuxSet( 2 , 11 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //A2
Chip_SCU_PinMuxSet( 2 , 12 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //A3
Chip_SCU_PinMuxSet( 2 , 13 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //A4
Chip_SCU_PinMuxSet( 1 , 0 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //A5
Chip_SCU_PinMuxSet( 1 , 1 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //A6
Chip_SCU_PinMuxSet( 1 , 2 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //A7
Chip_SCU_PinMuxSet( 2 , 8 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //A8
Chip_SCU_PinMuxSet( 2 , 7 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //A9
Chip_SCU_PinMuxSet( 2 , 6 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //A10
Chip_SCU_PinMuxSet( 2 , 2 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //A11
Chip_SCU_PinMuxSet( 2 , 1 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //A12
Chip_SCU_PinMuxSet( 2 , 0 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //A13
Chip_SCU_PinMuxSet( 6 , 8 , (SCU_PINIO_FAST | SCU_MODE_FUNC1)); //A14
Chip_SCU_PinMuxSet( 1 , 7 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D0
Chip_SCU_PinMuxSet( 1 , 8 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D1
Chip_SCU_PinMuxSet( 1 , 9 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D2
Chip_SCU_PinMuxSet( 1 , 10 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D3
Chip_SCU_PinMuxSet( 1 , 11 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D4
Chip_SCU_PinMuxSet( 1 , 12 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D5
Chip_SCU_PinMuxSet( 1 , 13 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D6
Chip_SCU_PinMuxSet( 1 , 14 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D7
Chip_SCU_PinMuxSet( 5 , 4 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D8
Chip_SCU_PinMuxSet( 5 , 5 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D9
Chip_SCU_PinMuxSet( 5 , 6 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D10
Chip_SCU_PinMuxSet( 5 , 7 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D11
Chip_SCU_PinMuxSet( 5 , 0 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D12
Chip_SCU_PinMuxSet( 5 , 1 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D13
Chip_SCU_PinMuxSet( 5 , 2 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D14
Chip_SCU_PinMuxSet( 5 , 3 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D15
Chip_SCU_PinMuxSet( 0X0D , 2 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D16
Chip_SCU_PinMuxSet( 0X0D , 3 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D17
Chip_SCU_PinMuxSet( 0X0D , 4 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D18
Chip_SCU_PinMuxSet( 0X0D , 5 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D19
Chip_SCU_PinMuxSet( 0X0D , 6 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D20
Chip_SCU_PinMuxSet( 0X0D , 7 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D21
Chip_SCU_PinMuxSet( 0X0D , 8 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D22
Chip_SCU_PinMuxSet( 0X0D , 9 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //D23
Chip_SCU_PinMuxSet( 0X0E , 5 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D24
Chip_SCU_PinMuxSet( 0X0E , 6 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D25
Chip_SCU_PinMuxSet( 0X0E , 7 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D26
Chip_SCU_PinMuxSet( 0X0E , 8 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D27
Chip_SCU_PinMuxSet( 0X0E , 9 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D28
Chip_SCU_PinMuxSet( 0X0E , 10 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D29
Chip_SCU_PinMuxSet( 0X0E , 11 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D30
Chip_SCU_PinMuxSet( 0X0E , 12 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //D31
Chip_SCU_PinMuxSet( 6 , 11 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); // CKEOUT0
Chip_SCU_ClockPinMuxSet(0, (SCU_PINIO_FAST | SCU_MODE_FUNC0)); // CLK0 connected to EMC_CLK0
Chip_SCU_ClockPinMuxSet(1, (SCU_PINIO_FAST | SCU_MODE_FUNC0)); // CLK1 connected to EMC_CLK1
Chip_SCU_ClockPinMuxSet(2, (SCU_PINIO_FAST | SCU_MODE_FUNC0)); // CLK2 connected to EMC_CLK3
Chip_SCU_ClockPinMuxSet(3, (SCU_PINIO_FAST | SCU_MODE_FUNC0)); // CLK3 connected to EMC_CLK2
Chip_SCU_PinMuxSet( 6 , 12 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //DQMOUT0
Chip_SCU_PinMuxSet( 6 , 10 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //DQMOUT1
Chip_SCU_PinMuxSet( 0X0D, 0 , (SCU_PINIO_FAST | SCU_MODE_FUNC2)); //DQMOUT2
Chip_SCU_PinMuxSet( 0X0E, 13 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //DQMOUT3
Chip_SCU_PinMuxSet( 6 , 4 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //CAS
Chip_SCU_PinMuxSet( 6 , 5 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //RAS
Chip_SCU_PinMuxSet( 1 , 6 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //WE
Chip_SCU_PinMuxSet( 6 , 9 , (SCU_PINIO_FAST | SCU_MODE_FUNC3)); //DYCS0
/* Select EMC clock-out */
LPC_SCU->SFSCLK[0] = SCU_PINIO_FAST;
LPC_SCU->SFSCLK[1] = SCU_PINIO_FAST;
LPC_SCU->SFSCLK[2] = SCU_PINIO_FAST;
LPC_SCU->SFSCLK[3] = SCU_PINIO_FAST;
/* Setup EMC Delays */
LPC_SCU->EMCDELAYCLK = 0x7777; // ~3.5 ns delay
LPC_CCU1->CLKCCU[CLK_MX_EMC_DIV].CFG |= (1 << 5);
LPC_CREG->CREG6 |= (1 << 16);
pclk = Chip_Clock_GetEMCRate();
LPC_EMC->CONTROL = 0x00000001;
LPC_EMC->CONFIG = 0x00000000;
LPC_EMC->DYNAMICCONFIG0 = 1 << 14 | 0 << 12 | 2 << 9 | 1 << 7; /* RBC 256Mb, 8Mx32, 4 banks, row=12, column=9 */
LPC_EMC->DYNAMICRASCAS0 = (3UL); //RAS latency
LPC_EMC->DYNAMICRASCAS0 |= (3UL << 8); //CAS latency
LPC_EMC->DYNAMICREADCONFIG = 0x00000001; /* Command delayed strategy, using EMCCLKDELAY */
LPC_EMC->DYNAMICRP = NS2CLK(pclk, 20);
LPC_EMC->DYNAMICRAS = NS2CLK(pclk, 42);
LPC_EMC->DYNAMICSREX = NS2CLK(pclk, 63);
LPC_EMC->DYNAMICAPR = 0x00000005;
LPC_EMC->DYNAMICDAL = 0x00000005;
LPC_EMC->DYNAMICWR = 2;
LPC_EMC->DYNAMICRC = NS2CLK(pclk, 63);
LPC_EMC->DYNAMICRFC = NS2CLK(pclk, 63);
LPC_EMC->DYNAMICXSR = NS2CLK(pclk, 63);
LPC_EMC->DYNAMICRRD = NS2CLK(pclk, 14);
LPC_EMC->DYNAMICMRD = 0x00000002;
for(i = 0; i < 100*MS; i++); /* wait 100ms */
LPC_EMC->DYNAMICCONTROL = 0x00000183; /* Issue NOP command */
for(i = 0; i < 200*MS; i++); /* wait 200ms */
LPC_EMC->DYNAMICCONTROL = 0x00000103; /* Issue PALL command */
LPC_EMC->DYNAMICREFRESH = EMC_SDRAM_REFRESH(pclk,70); /* ( n * 16 ) -> 32 clock cycles */
for(i = 0; i < 200*MS; i++); /* wait 200ms */ /* wait 128 AHB clock cycles */
tmpclk = (uint64_t)15625*(uint64_t)pclk/1000000000/16;
LPC_EMC->DYNAMICREFRESH = tmpclk; /* ( n * 16 ) -> 736 clock cycles -> 15.330uS at 48MHz <= 15.625uS ( 64ms / 4096 row ) */
LPC_EMC->DYNAMICCONTROL = 0x00000083; /* Issue MODE command */
//Timing for 48/60/72MHZ Bus
MODE = (2 << 0) | (0 << 3) | (3 << 4) | (0 << 9); // burst = 4, seq. mode, latency = 3, write burst = 0
OFFSET = 9 + 2 + 2; // RBC: 9 col + 32 bit (=2) + 2 bank select
temp = *((volatile uint32_t *)(BUFFER_BASE + (MODE << OFFSET)));
temp = temp;
LPC_EMC->DYNAMICCONTROL = 0x00000000; /* Issue NORMAL command */
//[re]enable buffers
LPC_EMC->DYNAMICCONFIG0 |= 1<<19;
}
Please, does anyone see what the issue may be? Or if not this code, what else can cause this problem?
Thank you!
On this board, EMC_CLK0 drives the SDRAM clock pin.
References I found in AN11508:
When x32 data width SDRAM is used, EMC_CLK1 or EMC_CLK3 may be used to drive SDRAM clock while EMC_CLK01 and EMC_CLK23 are used for FBCLK.
The key to running the EMC at full speed is to use EMC_CLK01 (CLK0 pin with SFSCLK0 = function 5) and EMC_CLK23 (CLK2 pin with SFSCLK2 = function 5) for the four byte lane feedback clocks, while using EMC_CLK1 (CLK1 pin) and / or EMC_CLK2 (CLK3 pin) to drive the SDRAM clocks.
I can't change the EMC_CLKx pin to CLK1 or CLK3 to try as this is a BGA256 package, but can using EMC_CLK0 be the reason for the issue described above?