LPC1788 SDRAM test failure

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

LPC1788 SDRAM test failure

2,420 Views
lpcware
NXP Employee
NXP Employee
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)
};
Labels (1)
5 Replies

2,152 Views
lpcware
NXP Employee
NXP Employee
bump
0 Kudos
Reply

2,152 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jim.shentu on Thu May 12 03:34:54 MST 2016

Thanks DF9DQ.

The SDRAM test is passed. As you pointed out, I could only access two banks. I'll have to modify the wiring for SDRAM to use A13/A14 instead of A12/A13 for bank selection.
0 Kudos
Reply

2,152 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by DF9DQ on Wed May 11 09:11:55 MST 2016
You set the DYNAMICCONFIG0 register to 0x1280, which selects Bank/Row/Column mode. In this mode you don't want to add the number of bank lines to the shift offset. The correct address for mode register becomes 0xA0000000 + (0x23 + (8 + 1)).

Is it true that you have connected A12/A13 to the SDRAM's bank select lines? If that is the case you will only be able to access two of the four banks.
You must always use A13/A14 for bank select, independent of SDRAM size.
0 Kudos
Reply

2,152 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by jim.shentu on Wed May 11 04:07:44 MST 2016

Thanks Bavarian. 

I have run the test using your magic number 0x23<<(2+10+1), unfortunately, the test is failed again.

I have double checked the datasheet of MT48LC4M16A2, mode register parameters are as below:
bank bit = 2 (for 4 banks)
column bits = 8 (for the MT48LC4M16A2)
bus width/16 = 1 (16-bit data bus)
0x23 is in principle correct for this 16-bit SDRAM

0xA000 0000 + (0x23 << (2 + 8 + 1))

-------------------------------------------------------------------
datasheet information
-------------------------------------------------------------------
Part Numbers               Architecture        Package
MT48LC4M16A2P       4 Meg x 16          54-pin TSOP II

------------------------------------------------------------------
Parameter                  4 Meg x 16
------------------------------------------------------------------
Configuration             1 Meg x 16 x 4 banks
Refresh count            4K
Row addressing         4K A[11:0]
Bank addressing        4 BA[1:0]
Column addressing    256 A[7:0]

Could you please check the attached datasheet and confirm if the magic number for the mode register is
0x23<<11


0 Kudos
Reply

2,152 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by bavarian on Mon May 02 08:29:26 MST 2016
Check the settings for the mode register:

Base address + (mode register value << (bank bits + column bits + bus width/16)

bank bit = 2  (for 4 banks)
column bits = 10 (for the MT48LC4M16A2)
bus width/16 = 1 (16-bit data bus)
0x23 is in principle correct for this 16-bit SDRAM

0xA000 0000 + (0x23 << (2 + 10 + 1))

Regards,
NXP Support Team
0 Kudos
Reply