lpcware

LPC1788 SDRAM test failure

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 18, 2016 by lpcware
Content originally posted in LPCWare by jim.shentu on Mon May 02 04:19:05 MST 2016
Hello,

I am developing a device based on the evaluation kit UEZGUI-1788-70WVT with MCU of LPC1788FBD208. Instead of a 32-bit SDRAM used in the evaluation kit, a 16-bit SDRAM of MT48LC4M16A2 is used in my prototype. The software used for the project is based on uEZ_v2.06_SourceForge. The system failed the SDRAM test at the intialisation stage. In the end of the test, the memory from address 0xA0000000 is filled with test data, however, the last four words (16 bit) are identical in every eight words. Could the NXP technical support team help identify the problem? Thanks a lot.

SDRAM-MCU wiring:

SDRAM               MCU
DQ0:DQ15 <--> P3.0:P3.15
A0:A11 <--> P4.0:P4.11
BA0:BA1 <--> P4.12:P4.13
DQM0:DQM1 <--> P2.28:P2.29
WE# <--> P4.25
CAS# <--> P2.16
RAS# <--> P2.17
CS# <--> P2.20
CLK <--> P2.18
CKE <--> P2.24

Configuration:
void LPC17xx_40xx_SDRAM_Init_16BitBus(const T_LPC17xx_40xx_SDRAM_Configuration * aConfig)
{
    TUInt32 dynconfig;
    __IO uint32_t *dc;
    volatile TUInt32 dmy = 0;
    volatile uint32_t ringosccount[2] = { 0, 0 };
    volatile unsigned int i;

    // Do this to get rid of warning in compiler that dmy is set but not used
    VARIABLE_NOT_USED(dmy);

    G_SDRAMSize = aConfig->iSize;
    G_SDRAMAddress = aConfig->iBaseAddress;

    LPC_SC->SCS &= ~(1 << 1); /*EMC reset disable*/

    LPC_SC->PCONP |= (1 << 11); /*bit 11: external memory control bit*/

    // Setup slow/default delays
    LPC_SC->EMCDLYCTL = 0x00001010;

    // Reset the EMC and put configuration
    LPC_EMC->Control = 0x00000001;
    LPC_EMC->Config = 0x00000000;

    // Setup 16-bit data bus
    LPC17xx_40xx_ExternalDataBus_ConfigureIOPins(16);

    // Setup A0 .. A14 for SDRAM
    LPC17xx_40xx_ExternalAddressBus_ConfigureIOPins(14); 


    LPC_IOCON->P4_25 = (LPC_IOCON->P4_25 & ~7) | 1;

    //      LPC_IOCON->P4_26 |= 1; /* BLSN[0] @ P4.26 */
    //      LPC_IOCON->P4_27 |= 1; /* BLSN[1] @ P4.27 */
    //      LPC_IOCON->P4_28 |= 1; /* BLSN[2] @ P4.28 */
    //      LPC_IOCON->P4_29 |= 1; /* BLSN[3] @ P4.29 */
    dynconfig = 0;
    if (aConfig->iSize == (8 * 1024 * 1024)) {
        dynconfig = 0x00001280; //0x00005300;
    } else if (aConfig->iSize == (16 * 1024 * 1024)) {
        dynconfig = 0x00005500;
    } else if (aConfig->iSize == (32 * 1024 * 1024)) {
        dynconfig = 0x00005480;
    } else {
        // "Unsupported UEZBSP_SDRAM_SIZE!"
        UEZFailureMsg("SDRAM Init");
    }

    if (aConfig->iBaseAddress == 0xA0000000) {
        /* WE[0] @ P4.25 */
        LPC_IOCON->P4_25 = (LPC_IOCON->P4_25 & ~7) | 1;

        /* DYCSN[0] @ P2.20 */
        LPC_IOCON->P2_20 = (LPC_IOCON->P2_20 & ~7) | 1;

        /* CKE[0] @ P2.24 */
        LPC_IOCON->P2_24 = (LPC_IOCON->P2_24 & ~7) | 1;

        dc = &LPC_EMC->DynamicConfig0;
        LPC_EMC->DynamicConfig0 = dynconfig;
    } else if (aConfig->iBaseAddress == 0xB0000000) {
        /* CSN[1] @ P4.31 */
        LPC_IOCON->P4_31 = (LPC_IOCON->P4_31 & ~7) | 1;

        /* DYCSN[1] @ P2.21 */
        LPC_IOCON->P2_21 = (LPC_IOCON->P2_21 & ~7) | 1;

        /* CKE[1] @ P2.25 */
        LPC_IOCON->P2_25 = (LPC_IOCON->P2_25 & ~7) | 1;

        dc = &LPC_EMC->DynamicConfig1;
        LPC_EMC->DynamicConfig1 = dynconfig;
    } else if (aConfig->iBaseAddress == 0xC0000000) {
        /* CSN[2] @ P2.14 */
        LPC_IOCON->P2_14 = (LPC_IOCON->P2_14 & ~7) | 1;

        /* DYCSN[2] @ P2.22 */
        LPC_IOCON->P2_22 = (LPC_IOCON->P2_22 & ~7) | 1;

        /* CKE[2] @ P2.26 */
        LPC_IOCON->P2_26 = (LPC_IOCON->P2_26 & ~7) | 1;

        dc = &LPC_EMC->DynamicConfig2;
        LPC_EMC->DynamicConfig2 = dynconfig;
    } else /*if (aConfig->iBaseAddress == 0xD0000000) */ {
        /* CSN[3] @ P2.15 */
        LPC_IOCON->P2_15 = (LPC_IOCON->P2_15 & ~7) | 1;

        /* DYCSN[3] @ P2.23 */
        LPC_IOCON->P2_23 = (LPC_IOCON->P2_23 & ~7) | 1;

        /* CKE[3] @ P2.27 */
        LPC_IOCON->P2_27 = (LPC_IOCON->P2_27 & ~7) | 1;

        dc = &LPC_EMC->DynamicConfig3;
        LPC_EMC->DynamicConfig3 = dynconfig;
    }

    /* CASN @ P2.16, CAS0 */
    LPC_IOCON->P2_16 = (LPC_IOCON->P2_16 & ~7) | 1;

    /* RASN @ P2.17, CAS1 */
    LPC_IOCON->P2_17 = (LPC_IOCON->P2_17 & ~7) | 1;

    if (aConfig->iClockOut == 0) {
        /* CLK[0] @ P2.18 */
        LPC_IOCON->P2_18 = (LPC_IOCON->P2_18 & ~7) | 1;
    } else {
        /* CLK[1] @ P2.19 */
        LPC_IOCON->P2_19 = (LPC_IOCON->P2_19 & ~7) | 1;
    }

    // Setup for 32-bit bus
    /* DQM[0] @ P2.28 */
    LPC_IOCON->P2_28 = (LPC_IOCON->P2_28 & ~7) | 1;
    /* DQM[1] @ P2.29 */
    LPC_IOCON->P2_29 = (LPC_IOCON->P2_29 & ~7) | 1;
    /* DQM[2] @ P2.30 */
    //LPC_IOCON->P2_30 = (LPC_IOCON->P2_30 & ~7) | 1;
    /* DQM[3] @ P2.31 */
    //LPC_IOCON->P2_31 = (LPC_IOCON->P2_31 & ~7) | 1;

    // RAS=2, CAS=2
    LPC_EMC->DynamicRasCas0 = 0x00000202; 
    LPC_EMC->DynamicReadConfig = 0x00000001; /* Command delayed strategy, using EMCCLKDELAY */


    LPC_EMC->DynamicRP = aConfig->iDynamicRP - 1;
    LPC_EMC->DynamicRAS = aConfig->iDynamicRAS - 1;
    LPC_EMC->DynamicSREX = aConfig->iDynamicSREX - 1;
    LPC_EMC->DynamicAPR = aConfig->iDynamicAPR - 1;
    LPC_EMC->DynamicDAL = aConfig->iDynamicDAL;
    LPC_EMC->DynamicWR = aConfig->iDynamicWR - 1;
    LPC_EMC->DynamicRC = aConfig->iDynamicRC - 1;
    LPC_EMC->DynamicRFC = aConfig->iDynamicRFC - 1;
    LPC_EMC->DynamicXSR = aConfig->iDynamicXSR - 1;
    LPC_EMC->DynamicRRD = aConfig->iDynamicRRD - 1;
    LPC_EMC->DynamicMRD = aConfig->iDynamicMRD - 1;

    //Send command: NOP
    LPC_EMC->DynamicControl = 0x00000183;

    //wait 200mS
    UEZBSPDelayMS(200);

    //Send command: PRECHARGE-ALL, shortest possible refresh period
    LPC_EMC->DynamicControl = 0x00000100;
    LPC_EMC->DynamicRefresh = 0x00000001;


    UEZBSPDelayMS(2);

    //Set correct refresh period
    LPC_EMC->DynamicRefresh
            = (unsigned int)((((aConfig->iClockFrequency / 1000)
               * (aConfig->iRefreshPeriod)) / aConfig->iRefreshCycles)
               / 16) + 1;

    //wait at least 128 ABH clock cycles
    for (i = 0; i < 0x40; i++)
        NOP();


    //Send command: MODE
    LPC_EMC->DynamicControl = 0x00000080;

    //Set mode register in SDRAM
      dmy = *((volatile uint32_t *)(aConfig->iBaseAddress | (0x23 << 11)));

    //wait 128 ABH clock cycles
    for (i = 0; i < 0x40; i++)
        NOP();

//UEZBSPDelayMS(2);

    //Send command: NORMAL ?
    LPC_EMC->DynamicControl = 0x00000000;

    //Enable buffer
    *dc |= 0x00080000;

    //initial system delay
    UEZBSPDelayMS(1);

    ringosccount[0] = ILPC17xx_40xx_SDRAM_Calibration();


    if (ILPC17xx_40xx_SDRAM_FindCmdDelay(aConfig->iBaseAddress, aConfig->iSize)
            == 0x0) {
        UEZFailureMsg("SDRAM Init"); /* fatal error */
    }

    if (ILPC17xx_40xx_SDRAM_FindFBClockDelay(aConfig->iBaseAddress, aConfig->iSize)
            == 0x0) {
        UEZFailureMsg("SDRAM Init"); /* fatal error */
    }

    ILPC17xx_40xx_SDRAM_AdjustTiming(ringosccount);

}

//test code
static uint32_t ILPC17xx_40xx_SDRAM_QuickTest(TUInt32 aBaseAddress, TUInt32 aSize)
{
    volatile uint16_t *wr_ptr;
    volatile uint16_t *short_wr_ptr;
    uint32_t data;
    uint32_t i, j;

    wr_ptr = (uint16_t *)aBaseAddress;
    short_wr_ptr = (uint16_t *)wr_ptr;

    /* Clear content before 16 bit access test */
    //  for (i = 0; i < G_SDRAMSize/4; i++)
    //  {
    //  *wr_ptr++ = 0;
    //  }

    /* 16 bit write */
    for (i = 0; i < aSize / 0x40000; i++) {
        for (j = 0; j < 0x100; j++) {
            *short_wr_ptr++ = (i + j);
        }
    }

    /* Verifying */
    wr_ptr = (uint16_t *)aBaseAddress;
    for (i = 0; i < aSize / 0x40000; i++) {
        for (j = 0; j < 0x100; j++) {
            data = *wr_ptr;
            if (data != ((i + j)&0xFFFF)) {
                return 0x0;
            }
            wr_ptr++;
        }
    }
    return 0x1;
}

//Command delay test function
static uint32_t ILPC17xx_40xx_SDRAM_FindCmdDelay(TUInt32 aBaseAddress, TUInt32 aSize)
{
    uint32_t cmddly, cmddlystart, cmddlyend, dwtemp;
    uint32_t ppass = 0x0, pass = 0x0;

    cmddly = 0x0;
    cmddlystart = cmddlyend = 0xFF;

    while (cmddly < 32) {
        dwtemp = LPC_SC->EMCDLYCTL & ~0x1F;
        LPC_SC->EMCDLYCTL = dwtemp | cmddly;

        if (ILPC17xx_40xx_SDRAM_QuickTest(aBaseAddress, aSize) == 0x1) {
            /* Test passed */
            if (cmddlystart == 0xFF) {
                cmddlystart = cmddly;
            }
            ppass = 0x1;
        } else {
            /* Test failed */
            if (ppass == 1) {
                cmddlyend = cmddly;
                pass = 0x1;
                ppass = 0x0;
            }
        }
        /* Try next value */
        cmddly++;
    }

    /* If the test passed, the we can use the average of the min */
    /* and max values to get an optimal DQSIN delay */
    if (pass == 0x1) {
        cmddly = (cmddlystart + cmddlyend) / 2;
    } else if (ppass == 0x1) {
        cmddly = (cmddlystart + 0x1F) / 2;
    } else {
        /* A working value couldn't be found, just pick something */
        /* safe so the system doesn't become unstable */
        cmddly = 0x10;
    }

    dwtemp = LPC_SC->EMCDLYCTL & ~0x1F;
    LPC_SC->EMCDLYCTL = dwtemp | cmddly;

    return (pass | ppass);
}


//FB clock delay function
static uint32_t ILPC17xx_40xx_SDRAM_FindFBClockDelay(
        TUInt32 aBaseAddress,
        TUInt32 aSize)
{
    uint32_t fbclkdly, fbclkdlystart, fbclkdlyend, dwtemp;
    uint32_t ppass = 0x0, pass = 0x0;

    fbclkdly = 0x0;
    fbclkdlystart = fbclkdlyend = 0xFF;

    while (fbclkdly < 32) {
        dwtemp = LPC_SC->EMCDLYCTL & ~0x1F00;
        LPC_SC->EMCDLYCTL = dwtemp | (fbclkdly << 8);

        if (ILPC17xx_40xx_SDRAM_QuickTest(aBaseAddress, aSize) == 0x1) {
            /* Test passed */
            if (fbclkdlystart == 0xFF) {
                fbclkdlystart = fbclkdly;
            }
            ppass = 0x1;
        } else {
            /* Test failed */
            if (ppass == 1) {
                fbclkdlyend = fbclkdly;
                pass = 0x1;
                ppass = 0x0;
            }
        }

        /* Try next value */
        fbclkdly++;
    }

    /* If the test passed, the we can use the average of the min and max values to get an optimal DQSIN delay */
    if (pass == 0x1) {
        fbclkdly = (fbclkdlystart + fbclkdlyend) / 2;
    } else if (ppass == 0x1) {
        fbclkdly = (fbclkdlystart + 0x1F) / 2;
    } else {
        /* A working value couldn't be found, just pick something safe so the system doesn't become unstable */
        fbclkdly = 0x10;
    }

    dwtemp = LPC_SC->EMCDLYCTL & ~0x1F00;
    LPC_SC->EMCDLYCTL = dwtemp | (fbclkdly << 8);

    return (pass | ppass);
}

//calibration
static uint32_t ILPC17xx_40xx_SDRAM_Calibration(void)
{
    uint32_t dwtemp, i;
    uint32_t cnt = 0;

    for (i = 0; i < 10; i++) {
        dwtemp = LPC_SC->EMCCAL & ~0x4000;
        LPC_SC->EMCCAL = dwtemp | 0x4000;

        dwtemp = LPC_SC->EMCCAL;
        while ((dwtemp & 0x8000) == 0x0000) {
            dwtemp = LPC_SC->EMCCAL;
        }
        cnt += (dwtemp & 0xFF);
    }
    return (cnt / 10);
}

//RAM initialisation
void UEZBSP_RAMInit(void)
{

    static const T_LPC17xx_40xx_SDRAM_Configuration sdramConfig_MT48LC4M16A2  = {
            UEZBSP_SDRAM_BASE_ADDR,
            UEZBSP_SDRAM_SIZE,
            SDRAM_CAS_2,   
            SDRAM_RAS_2,   
            LPC17xx_40xx_SDRAM_CLKOUT0,
            SDRAM_CLOCK_FREQUENCY,  //60MHz
            64, // ms
            4096, //8192 cycles

            SDRAM_CYCLES(15),
            SDRAM_CYCLES(37),
            SDRAM_CYCLES(67),
            SDRAM_CYCLES(15),
            SDRAM_CLOCKS(4),
            SDRAM_CYCLES(7),
            SDRAM_CYCLES(60),
            SDRAM_CYCLES(66),
            SDRAM_CYCLES(70),
            SDRAM_CYCLES(14),
            SDRAM_CLOCKS(2)
};

Outcomes