LPC1785 EMC with SDRAM freezes

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC1785 EMC with SDRAM freezes

Jump to solution
1,091 Views
lltsu
Contributor II

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);

Tags (3)
0 Kudos
1 Solution
664 Views
lltsu
Contributor II

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.

View solution in original post

0 Kudos
2 Replies
665 Views
lltsu
Contributor II

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.

0 Kudos
664 Views
Hui_Ma
NXP TechSupport
NXP TechSupport

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!
-----------------------------------------------------------------------------------------------------------------------