Hello,
I'm trying to use LPC1785 with AS4C4M16SA SDRAM. The controller is running at 120 MHz and the EMC controller at 60 MHz.
It looks like that the first 8 bytes of the memory (from 0xA0000000 to 0xA0000007) work the way they should, but reading from any other location freezes the controller. I can write to any location I want to, but it looks like that writing to a memory location bigger than 0xA0000080 corrupts the first 8 bytes of data.
What could be the problem?
The SDRAM and LPC1785 are connected like this:
DQ0-DQ15 - EMC_D0-EMC_D15
A0-A11 - EMC_A0-EMC_A11
BA0 - EMC_A13
BA1 - EMC_A14
LDQM - EMC_DQM0
UDQM - EMC_DQM1
WE - EMC_WE
CAS - EMC_CAS
RAS - EMC_RAS
CS - EMC_DYCS0
CLK - EMC_CLK0
CKE - EMC_CKE0
Code to initialize the SDRAM:
// clock divide
LPC_SC->EMCCLKSEL = 1;
// ensure that the power to the EMC module is on
LPC_SC->PCONP |= (1 << 11);
// reset EMC on any controller reset
// enable burst control
LPC_SC->SCS &= ~(0b111);
// enable EMC in normal power mode and set normal memory map
LPC_EMC->Control = 0b001;
// little endian mode
LPC_EMC->Config = 0;
// enable dynamic memory, CLKOUT runs continously
LPC_EMC->DynamicControl = 0b00000110;
// disable buffer for initialization and write configuration values
LPC_EMC->DynamicConfig0 = (0b000101 << 7);
// set RAS and CAS
LPC_EMC->DynamicRasCas0 = 3 + (3 << 8);
// set the SDRAM refresh rate to small value for PALL command
LPC_EMC->DynamicRefresh = 2;
// issue PALL command
LPC_EMC->DynamicControl = 0x103;
volatile int i;
for (i = 0; i < 128 * 2; i++) {
__NOP();
}
// set the SDRAM refresh rate
LPC_EMC->DynamicRefresh = 54;
// issue MODE command to the SDRAM
LPC_EMC->DynamicControl = 0x83;
// configure SDRAM
volatile unsigned int temp = *((volatile unsigned int *) (0xA0000000 + (0x33 << (2 + 8 + 1))));
// issue normal command
LPC_EMC->DynamicControl &= ~(0b11 << 7);
// enable buffer
LPC_EMC->DynamicConfig0 |= (1 << 19);
Solved! Go to Solution.
Looks like I got it working by copying the initialization code shown on this thread:
https://community.nxp.com/message/754829#comment-754829
I only modified the burst length, timing etc settings to fit my SDRAM. I have no idea why my own code didn't work. I found the LPC1785 manual little bit ambiguous regarding the EMC registers.
Looks like I got it working by copying the initialization code shown on this thread:
https://community.nxp.com/message/754829#comment-754829
I only modified the burst length, timing etc settings to fit my SDRAM. I have no idea why my own code didn't work. I found the LPC1785 manual little bit ambiguous regarding the EMC registers.
Hi
There is a SDRAM initialization example code of LPC1788 evaluation board (with SDRAM IS42S32800D) for customer reference.
Below is abstracted LPC1788 EMC module init configuration part:
in <board_sysinit.c> file:
/* Keil SDRAM timing and chip Config */
STATIC const IP_EMC_DYN_CONFIG_T IS42S32800D_config = {
EMC_NANOSECOND(64000000 / 4096),
0x01, /* Command Delayed */
3, /* tRP */
7, /* tRAS */
EMC_NANOSECOND(70), /* tSREX */
EMC_CLOCK(0x01), /* tAPR */
EMC_CLOCK(0x05), /* tDAL */
EMC_NANOSECOND(12), /* tWR */
EMC_NANOSECOND(60), /* tRC */
EMC_NANOSECOND(60), /* tRFC */
EMC_NANOSECOND(70), /* tXSR */
EMC_NANOSECOND(12), /* tRRD */
EMC_CLOCK(0x02), /* tMRD */
{
{
EMC_ADDRESS_DYCS0, /* EA Board uses DYCS0 for SDRAM */
2, /* RAS */
EMC_DYN_MODE_WBMODE_PROGRAMMED |
EMC_DYN_MODE_OPMODE_STANDARD |
EMC_DYN_MODE_CAS_2 |
EMC_DYN_MODE_BURST_TYPE_SEQUENTIAL |
EMC_DYN_MODE_BURST_LEN_4,
EMC_DYN_CONFIG_DATA_BUS_32 |
EMC_DYN_CONFIG_LPSDRAM |
EMC_DYN_CONFIG_8Mx16_4BANKS_12ROWS_9COLS |
EMC_DYN_CONFIG_MD_SDRAM
},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
}
};
/* Init EMC Dynamic Controller */
Chip_EMC_Dynamic_Init((IP_EMC_DYN_CONFIG_T *) &IS42S32800D_config);
In <emc_17xx_40xx.c> file:
/* Dyanmic memory setup */
void Chip_EMC_Dynamic_Init(IP_EMC_DYN_CONFIG_T *Dynamic_Config)
{
uint32_t ClkFreq;
/* Note clocks must be enabled prior to this call */
ClkFreq = Chip_Clock_GetEMCClockRate();
initDynMem(LPC_EMC, Dynamic_Config, ClkFreq);
}
/* Initializes the Dynamic Controller according to the specified parameters
in the IP_EMC_DYN_CONFIG_T */
void initDynMem(LPC_EMC_T *pEMC, IP_EMC_DYN_CONFIG_T *Dynamic_Config, uint32_t EMC_Clock)
{
uint32_t ChipSelect, tmpclk;
int i;
for (ChipSelect = 0; ChipSelect < 4; ChipSelect++) {
LPC_EMC_T *EMC_Reg_add = (LPC_EMC_T *) ((uint32_t) pEMC + (ChipSelect << 5));
EMC_Reg_add->DYNAMICRASCAS0 = Dynamic_Config->DevConfig[ChipSelect].RAS |
((Dynamic_Config->DevConfig[ChipSelect].ModeRegister <<
(8 - EMC_DYN_MODE_CAS_BIT)) & 0xF00);
EMC_Reg_add->DYNAMICCONFIG0 = Dynamic_Config->DevConfig[ChipSelect].DynConfig;
}
pEMC->DYNAMICREADCONFIG = Dynamic_Config->ReadConfig; /* Read strategy */
pEMC->DYNAMICRP = convertTimmingParam(EMC_Clock, Dynamic_Config->tRP, 1);
pEMC->DYNAMICRAS = convertTimmingParam(EMC_Clock, Dynamic_Config->tRAS, 1);
pEMC->DYNAMICSREX = convertTimmingParam(EMC_Clock, Dynamic_Config->tSREX, 1);
pEMC->DYNAMICAPR = convertTimmingParam(EMC_Clock, Dynamic_Config->tAPR, 1);
pEMC->DYNAMICDAL = convertTimmingParam(EMC_Clock, Dynamic_Config->tDAL, 0);
pEMC->DYNAMICWR = convertTimmingParam(EMC_Clock, Dynamic_Config->tWR, 1);
pEMC->DYNAMICRC = convertTimmingParam(EMC_Clock, Dynamic_Config->tRC, 1);
pEMC->DYNAMICRFC = convertTimmingParam(EMC_Clock, Dynamic_Config->tRFC, 1);
pEMC->DYNAMICXSR = convertTimmingParam(EMC_Clock, Dynamic_Config->tXSR, 1);
pEMC->DYNAMICRRD = convertTimmingParam(EMC_Clock, Dynamic_Config->tRRD, 1);
pEMC->DYNAMICMRD = convertTimmingParam(EMC_Clock, Dynamic_Config->tMRD, 1);
/* TIM_Waitus(100); */
/*FIXME: if Timer driver is ready, it should replace below "for" delay technic */
for (i = 0; i < 1000; i++) { /* wait 100us */
}
pEMC->DYNAMICCONTROL = 0x00000183; /* Issue NOP command */
/* TIM_Waitus(200); */ /* wait 200us */
/*FIXME: if Timer driver is ready, it should replace below "for" delay technic */
for (i = 0; i < 1000; i++) {}
pEMC->DYNAMICCONTROL = 0x00000103; /* Issue PALL command */
pEMC->DYNAMICREFRESH = 2; /* ( 2 * 16 ) -> 32 clock cycles */
/* FIXME: TIM_Waitus(200); */ /* wait 200us */
for (i = 0; i < 80; i++) {}
tmpclk = EMC_DIV_ROUND_UP(convertTimmingParam(EMC_Clock, Dynamic_Config->RefreshPeriod, 0), 16);
pEMC->DYNAMICREFRESH = tmpclk;
pEMC->DYNAMICCONTROL = 0x00000083; /* Issue MODE command */
for (ChipSelect = 0; ChipSelect < 4; ChipSelect++) {
/*uint32_t burst_length;*/
uint32_t DynAddr;
uint8_t Col_len;
Col_len = getColsLen(Dynamic_Config->DevConfig[ChipSelect].DynConfig);
/* get bus wide: if 32bit, len is 4 else if 16bit len is 2 */
/* burst_length = 1 << ((((Dynamic_Config->DynConfig[ChipSelect] >> 14) & 1)^1) +1); */
if (Dynamic_Config->DevConfig[ChipSelect].DynConfig & (1 << EMC_DYN_CONFIG_DATA_BUS_WIDTH_BIT)) {
/*32bit bus */
/*burst_length = 2;*/
Col_len += 2;
}
else {
/*burst_length = 4;*/
Col_len += 1;
}
DynAddr = Dynamic_Config->DevConfig[ChipSelect].BaseAddr;
if (DynAddr != 0) {
uint32_t temp;
uint32_t ModeRegister;
ModeRegister = Dynamic_Config->DevConfig[ChipSelect].ModeRegister;
temp = *((volatile uint32_t *) (DynAddr | (ModeRegister << Col_len)));
temp = temp;
}
}
pEMC->DYNAMICCONTROL = 0x00000000; /* Issue NORMAL command */
/* enable buffers */
pEMC->DYNAMICCONFIG0 |= 1 << 19;
pEMC->DYNAMICCONFIG1 |= 1 << 19;
pEMC->DYNAMICCONFIG2 |= 1 << 19;
pEMC->DYNAMICCONFIG3 |= 1 << 19;
}
Customer could download the whole LPCOpen software package for EA LPC1788 board project from here.
Wish it helps.
Have a great day,
Ma Hui
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------