I am having an immense amount of trouble getting the SDRAM chip initialized on the rt1060-evk.
I went through the memory performance example found in an12437sw, however the exact values used to populate the SEMC registers are heavily obfuscated and finding those values is unclear/error prone. With the code I have below, I always have an IPCMDERR interrupt and I do not know why. I am running the SEMC at 132MHz and the processor core at 600MHz.
What am I missing?
The code I have for initializing the SDRAM is:
void SDRAM_Init(void) //Base regions start 8000_0000
{
CCM->CBCDR &= ~(CCM_CBCDR_SEMC_ALT_CLK_SEL_MASK | CCM_CBCDR_SEMC_CLK_SEL_MASK); //Primary clock comes from PLL2 - PFD2
CCM->CBCDR |= (CCM_CBCDR_SEMC_ALT_CLK_SEL(0) | CCM_CBCDR_SEMC_CLK_SEL(1)); //Primary clock comes from CBCDR(SEMC_ALT_SEL)
//clock is PFD2/3 = 396/3 = 132MHz
CCM->CCGR3 |= CCM_CCGR3_CG2(3); //Enables the clock gate and is on in all cpu modes except for stop
CCM->CCGR1 |= CCM_CCGR1_CG9(3);
SEMC->MCR = SEMC_MCR_SWRST_MASK;//reset the peripheral
while (SEMC->MCR & SEMC_MCR_SWRST_MASK);
SEMC->MCR |= SEMC_MCR_MDIS_MASK | SEMC_MCR_BTO(0x1F) | SEMC_MCR_CTO(0) | SEMC_MCR_DQSMD(1);
SEMC->IOCR |= (SEMC_IOCR_MUX_CLKX0(1) | SEMC_IOCR_MUX_CLKX1(1) |
SEMC_IOCR_MUX_RDY(1) | SEMC_IOCR_MUX_CSX0(0) | SEMC_IOCR_MUX_A8(0));
SEMC->BMCR0 = SEMC_BMCR0_WAGE(8) | SEMC_BMCR0_WQOS(5) | SEMC_BMCR0_WSH(0x40) | SEMC_BMCR0_WRWS(0x10); //Needs more research - Default Operation
SEMC->BMCR1 = SEMC_BMCR1_WAGE(8) | SEMC_BMCR1_WQOS(5) | SEMC_BMCR1_WPH(0x60) | SEMC_BMCR1_WBR(0x40) | SEMC_BMCR1_WRWS(0x24); //Needs more research - Default Operation
SEMC->MCR &= ~SEMC_MCR_MDIS_MASK;
SEMC->BR[0]= SEMC_BR_BA(0x90000) |SEMC_BR_MS(0xD) | SEMC_BR_VLD_MASK; // SDRAM_CS0 - Address of 9000_F000
SEMC->BR[1] = 0;
SEMC->BR[2] = 0;
SEMC->BR[3] = 0;
SEMC->INTEN = 0x0C; //bits 0-7 all AXI/IP error interrupts enabled, 8-9 Nand related
SEMC->INTR = 0x1F; //Interrupt status register
//SDRAM Configuration Registers in SEMC values calculated go ("(DataSheet_NS * 1000) / (SEMC Clock Rate / 1000000) = (Value)" )
SEMC->SDRAMCR0 = SEMC_SDRAMCR0_BANK2(0) | SEMC_SDRAMCR0_CL(3) | SEMC_SDRAMCR0_COL(3) | SEMC_SDRAMCR0_COL8(0) | SEMC_SDRAMCR0_BL(3) | SEMC_SDRAMCR0_PS(1); //needs more research
SEMC->SDRAMCR1 = SEMC_SDRAMCR1_PRE2ACT(1) | SEMC_SDRAMCR1_ACT2RW(1) | SEMC_SDRAMCR1_RFRC(7) | SEMC_SDRAMCR1_WRC(0) | SEMC_SDRAMCR1_CKEOFF(4) | SEMC_SDRAMCR1_ACT2PRE(4);
SEMC->SDRAMCR2 = SEMC_SDRAMCR2_ACT2ACT(7) | SEMC_SDRAMCR2_REF2REF(7) | SEMC_SDRAMCR2_SRRC(7) | SEMC_SDRAMCR2_ITO(0);
SEMC->SDRAMCR3 = SEMC_SDRAMCR3_UT(6)| SEMC_SDRAMCR3_RT(6) | SEMC_SDRAMCR3_PRESCALE(0) | SEMC_SDRAMCR3_REBL(0);
//SDRAM Chip Init -------
//wait atleast 100us, we'll do 1ms
SysTick_Init(SYSTICK_SLOW); //Systick is running at 100KHz
SysTick_Start(1000);
while(SysTick_GetState() != STSTATE_STOP);
//PreCharge
SEMC->IPCR0 = 0x90000;
SEMC->IPCR1 = 0x2;
SEMC->IPCR2 = 0x0;
SEMC->IPTXDAT = 0;
SEMC->IPCMD = 0xA55A000F; //SEMC_IPCMD_KEY(0xA55A) | SEMC_IPCMD_CMD(0xF); //pre-charge all
while((SEMC->INTR & SEMC_INTR_IPCMDDONE_MASK) == 0);
SEMC->INTR = SEMC_INTR_IPCMDDONE_MASK;
/*
SEMC->INTR = SEMC_INTR_IPCMDDONE_MASK | SEMC_INTR_IPCMDERR_MASK;
SEMC->IPCMD = SEMC_IPCMD_KEY(0xA55A) | SEMC_IPCMD_CMD(0xC); //auto-refresh
while((SEMC->INTR & SEMC_INTR_IPCMDDONE_MASK) == 0);
SEMC->INTR = SEMC_INTR_IPCMDDONE_MASK | SEMC_INTR_IPCMDERR_MASK;
SEMC->IPCMD = SEMC_IPCMD_KEY(0xA55A) | SEMC_IPCMD_CMD(0xC); //auto-refresh
while((SEMC->INTR & SEMC_INTR_IPCMDDONE_MASK) == 0);
//Configure the RAM Chip though the IP Bus, AXI bus reads are done simply via accessing.
//IP CMD Command Key ((0xA55A) << 16) | 0xA ( Mode Set for SDRAM ),
SEMC->INTR = SEMC_INTR_IPCMDDONE_MASK | SEMC_INTR_IPCMDERR_MASK;
SEMC->IPTXDAT = 0x033U;
SEMC->IPCMD = SEMC_IPCMD_KEY(0xA55A) | SEMC_IPCMD_CMD(0xA); //mode set
while((SEMC->INTR & SEMC_INTR_IPCMDDONE_MASK) == 0);
SEMC->INTR = SEMC_INTR_IPCMDDONE_MASK;
//Enable SEMC Clock
SEMC->SDRAMCR3 |= SEMC_SDRAMCR3_REN_MASK;
*/
}
Hi Richard Tilson,
Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
To provide the fastest possible support, I'd highly recommend you to refer to the SEMC demo in the SDK library, the demo shows how to use SEMC controller driver to initialize the external SDRAM chip.
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
I did eventually go through the memory performance example and found that the real difference between what I had and what the example had was setting the SEMC_DQS signal to 0x10
IOMUXC->SW_MUX_CTL_PAD[39] = 0x10U; Bit 4 - Software Input On Field = True, MUX_Mode = SEMC_DQS
This signal on the EVK is left floating. What is this signal doing internally? There is no explanation in the Reference Manual (at least what I could find..I could have missed it) on how the SEMC is using this signal.
Thanks, I did miss the IOMUXC settings for these pins but even after setting up the MUX_Mode for the pins. I had to dig into the memory performance to see what I missed.
Hi Richard Tilson,
Thanks for your reply.
According to design experience, the SEMC_DQS is recommended to be floating to achieve max speed.
Have a great day,
TIC
-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!
- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------
Hi Richard
Have you configured the GPIOs needed to their SEMC functions with appropriate attributes?
Generally the SEMC for SDRAM use tends to be configured by the DCD table - have you tried this?
Regards
Mark
[uTasker project developer for Kinetis and i.MX RT]