Content originally posted in LPCWare by Marc Crandall on Mon Dec 19 14:54:16 MST 2011
I configure a NOR and an SDRAM device. (SST38VF640 and MT48LC16M16)
This is my working INI:
<code>
DEFINE INT SDRAM_BASE_ADDR;
DEFINE INT EMC_BASE; // EMC Base Address
DEFINE INT EMC_CTRL_REG;
DEFINE INT EMC_STAT_REG;
DEFINE INT EMC_CONFIG_REG;
DEFINE INT EMC_DYN_CTRL_REG;
DEFINE INT EMC_DYN_RFSH_REG;
DEFINE INT EMC_DYN_RD_CFG_REG;
DEFINE INT EMC_DYN_RP_REG;
DEFINE INT EMC_DYN_RAS_REG;
DEFINE INT EMC_DYN_SREX_REG;
DEFINE INT EMC_DYN_APR_REG;
DEFINE INT EMC_DYN_DAL_REG;
DEFINE INT EMC_DYN_WR_REG;
DEFINE INT EMC_DYN_RC_REG;
DEFINE INT EMC_DYN_RFC_REG;
DEFINE INT EMC_DYN_XSR_REG;
DEFINE INT EMC_DYN_RRD_REG;
DEFINE INT EMC_DYN_MRD_REG;
DEFINE INT EMC_DYN_CFG0_REG;
DEFINE INT EMC_DYN_RASCAS0_REG;
//note: missing the other dyn mem register offsets.
DEFINE INT EMC_STA_CFG0_REG;
DEFINE INT EMC_STA_WWEN0_REG;
DEFINE INT EMC_STA_WOEN0_REG;
DEFINE INT EMC_STA_WRD0_REG;
DEFINE INT EMC_STA_WPAGE0_REG;
DEFINE INT EMC_STA_WWR0_REG;
DEFINE INT EMC_STA_WTURN0_REG;
//note: missing the other static mem register offsets.
DEFINE INT EMC_STA_EXT_W_REG;
DEFINE INT PCONP_REG;
DEFINE INT EMCDLYCTL_REG;
DEFINE INT EMCCAL_REG;
DEFINE INT EMCClock_m
DEFINE INT SCS_REG;
SDRAM_BASE_ADDR = 0xA0000000;
EMC_BASE = 0x2009C000; // EMC Base Address
EMC_CTRL_REG = EMC_BASE + 0x000;
EMC_STAT_REG = EMC_BASE + 0x004;
EMC_CONFIG_REG = EMC_BASE + 0x008;
EMC_DYN_CTRL_REG = EMC_BASE + 0x020;
EMC_DYN_RFSH_REG = EMC_BASE + 0x024;
EMC_DYN_RD_CFG_REG = EMC_BASE + 0x028;
EMC_DYN_RP_REG = EMC_BASE + 0x030;
EMC_DYN_RAS_REG = EMC_BASE + 0x034;
EMC_DYN_SREX_REG = EMC_BASE + 0x038;
EMC_DYN_APR_REG = EMC_BASE + 0x03C;
EMC_DYN_DAL_REG = EMC_BASE + 0x040;
EMC_DYN_WR_REG = EMC_BASE + 0x044;
EMC_DYN_RC_REG = EMC_BASE + 0x048;
EMC_DYN_RFC_REG = EMC_BASE + 0x04C;
EMC_DYN_XSR_REG = EMC_BASE + 0x050;
EMC_DYN_RRD_REG = EMC_BASE + 0x054;
EMC_DYN_MRD_REG = EMC_BASE + 0x058;
EMC_DYN_CFG0_REG = EMC_BASE + 0x100;
EMC_DYN_RASCAS0_REG = EMC_BASE + 0x104;
EMC_STA_CFG0_REG = EMC_BASE + 0x200;
EMC_STA_WWEN0_REG = EMC_BASE + 0x204;
EMC_STA_WOEN0_REG = EMC_BASE + 0x208;
EMC_STA_WRD0_REG = EMC_BASE + 0x20C;
EMC_STA_WPAGE0_REG = EMC_BASE + 0x210;
EMC_STA_WWR0_REG = EMC_BASE + 0x214;
EMC_STA_WTURN0_REG = EMC_BASE + 0x218;
EMC_STA_EXT_W_REG = EMC_BASE + 0x080;
PCONP_REG = 0x400FC0C4;
EMCDLYCTL_REG = 0x400FC1DC;
EMCCAL_REG = 0x400FC1E0;
EMCClock_m = 78000000;
SCS_REG = 0x400FC1A0;
FUNC int NS_2_CLKS(int ns)
{
double tCLK_ns;
tCLK_ns = ((double)EMCClock_m / 1000000000.0 ); // CCLK period in ns
return (int)((double)(ns) * tCLK_ns ); // convert ns to CCLKs
}
FUNC void Setup (void)
{
printf("START - Setup() \r\n");
SP = _RDWORD(0x00040000); // Setup Stack Pointer
PC = _RDWORD(0x00040004); // Setup Program Counter
_WDWORD(0xE000ED08, 0x00040000); // Setup Vector Table Offset Register
//SP = _RDWORD(0x00000000); // Setup Stack Pointer
//PC = _RDWORD(0x00000004); // Setup Program Counter
//_WDWORD(0xE000ED08, 0x00000000); // Setup Vector Table Offset Register
printf("END - Setup() \r\n");
}
FUNC void init_emc(void)
{
//*********************************************
// PIN CONFIGURATION
//*********************************************
_WDWORD(0x4002C140, _RDWORD(0x4002C140) | 0x1); //LPC_IOCON->P2_16 |= 1; // CASN @ P2.16 (SDRAM Column Address Strobe)
_WDWORD(0x4002C144, _RDWORD(0x4002C144) | 0x1); //LPC_IOCON->P2_17 |= 1; // RASN @ P2.17 (SDRAM Row Address Strobe)
_WDWORD(0x4002C148, _RDWORD(0x4002C148) | 0x1); //LPC_IOCON->P2_18 |= 1; // CLK[0] @ P2.18 (SDRAM System Clock)
_WDWORD(0x4002C150, _RDWORD(0x4002C150) | 0x1); //LPC_IOCON->P2_20 |= 1; // DYCSN[0] @ P2.20 (SDRAM Chip Select)
_WDWORD(0x4002C160, _RDWORD(0x4002C160) | 0x1); //LPC_IOCON->P2_24 |= 1; // CKE[0] @ P2.24 (SDRAM Clock Enable)
_WDWORD(0x4002C170, _RDWORD(0x4002C170) | 0x1); //LPC_IOCON->P2_28 |= 1; // DQM[0] @ P2.28 (SDRAM Data Input/Output Mask)
_WDWORD(0x4002C174, _RDWORD(0x4002C174) | 0x1); //LPC_IOCON->P2_29 |= 1; // DQM[1] @ P2.29 (SDRAM Data Input/Output Mask)
_WDWORD(0x4002C180, _RDWORD(0x4002C180) | 0x1); // LPC_IOCON->P3_0 |= 1; /* D0 @ P3.0 */
_WDWORD(0x4002C184, _RDWORD(0x4002C184) | 0x1); // LPC_IOCON->P3_1 |= 1; /* D1 @ P3.1 */
_WDWORD(0x4002C188, _RDWORD(0x4002C188) | 0x1); // LPC_IOCON->P3_2 |= 1; /* D2 @ P3.2 */
_WDWORD(0x4002C18C, _RDWORD(0x4002C18C) | 0x1); // LPC_IOCON->P3_3 |= 1; /* D3 @ P3.3 */
_WDWORD(0x4002C190, _RDWORD(0x4002C190) | 0x1); // LPC_IOCON->P3_4 |= 1; /* D4 @ P3.4 */
_WDWORD(0x4002C194, _RDWORD(0x4002C194) | 0x1); // LPC_IOCON->P3_5 |= 1; /* D5 @ P3.5 */
_WDWORD(0x4002C198, _RDWORD(0x4002C198) | 0x1); // LPC_IOCON->P3_6 |= 1; /* D6 @ P3.6 */
_WDWORD(0x4002C19C, _RDWORD(0x4002C19C) | 0x1); // LPC_IOCON->P3_7 |= 1; /* D7 @ P3.7 */
_WDWORD(0x4002C1A0, _RDWORD(0x4002C1A0) | 0x1); // LPC_IOCON->P3_8 |= 1; /* D8 @ P3.8 */
_WDWORD(0x4002C1A4, _RDWORD(0x4002C1A4) | 0x1); // LPC_IOCON->P3_9 |= 1; /* D9 @ P3.9 */
_WDWORD(0x4002C1A8, _RDWORD(0x4002C1A8) | 0x1); // LPC_IOCON->P3_10 |= 1; /* D10 @ P3.10 */
_WDWORD(0x4002C1AC, _RDWORD(0x4002C1AC) | 0x1); // LPC_IOCON->P3_11 |= 1; /* D11 @ P3.11 */
_WDWORD(0x4002C1B0, _RDWORD(0x4002C1B0) | 0x1); // LPC_IOCON->P3_12 |= 1; /* D12 @ P3.12 */
_WDWORD(0x4002C1B4, _RDWORD(0x4002C1B4) | 0x1); // LPC_IOCON->P3_13 |= 1; /* D13 @ P3.13 */
_WDWORD(0x4002C1B8, _RDWORD(0x4002C1B8) | 0x1); // LPC_IOCON->P3_14 |= 1; /* D14 @ P3.14 */
_WDWORD(0x4002C1BC, _RDWORD(0x4002C1BC) | 0x1); // LPC_IOCON->P3_15 |= 1; /* D15 @ P3.15 */
_WDWORD(0x4002C1C0, _RDWORD(0x4002C1C0) | 0x1); // LPC_IOCON->P3_16 |= 1; /* D16 @ P3.16 */
_WDWORD(0x4002C1C4, _RDWORD(0x4002C1C4) | 0x1); // LPC_IOCON->P3_17 |= 1; /* D17 @ P3.17 */
_WDWORD(0x4002C1C8, _RDWORD(0x4002C1C8) | 0x1); // LPC_IOCON->P3_18 |= 1; /* D18 @ P3.18 */
_WDWORD(0x4002C1CC, _RDWORD(0x4002C1CC) | 0x1); // LPC_IOCON->P3_19 |= 1; /* D19 @ P3.19 */
_WDWORD(0x4002C1D0, _RDWORD(0x4002C1D0) | 0x1); // LPC_IOCON->P3_20 |= 1; /* D20 @ P3.20 */
_WDWORD(0x4002C1D4, _RDWORD(0x4002C1D4) | 0x1); // LPC_IOCON->P3_21 |= 1; /* D21 @ P3.21 */
_WDWORD(0x4002C1D8, _RDWORD(0x4002C1D8) | 0x1); // LPC_IOCON->P3_22 |= 1; /* D22 @ P3.22 */
_WDWORD(0x4002C1DC, _RDWORD(0x4002C1DC) | 0x1); // LPC_IOCON->P3_23 |= 1; /* D23 @ P3.23 */
_WDWORD(0x4002C1E0, _RDWORD(0x4002C1E0) | 0x1); // LPC_IOCON->P3_24 |= 1; /* D24 @ P3.24 */
_WDWORD(0x4002C1E4, _RDWORD(0x4002C1E4) | 0x1); // LPC_IOCON->P3_25 |= 1; /* D25 @ P3.25 */
_WDWORD(0x4002C1E8, _RDWORD(0x4002C1E8) | 0x1); // LPC_IOCON->P3_26 |= 1; /* D26 @ P3.26 */
_WDWORD(0x4002C1EC, _RDWORD(0x4002C1EC) | 0x1); // LPC_IOCON->P3_27 |= 1; /* D27 @ P3.27 */
_WDWORD(0x4002C1F0, _RDWORD(0x4002C1F0) | 0x1); // LPC_IOCON->P3_28 |= 1; /* D28 @ P3.28 */
_WDWORD(0x4002C1F4, _RDWORD(0x4002C1F4) | 0x1); // LPC_IOCON->P3_29 |= 1; /* D29 @ P3.29 */
_WDWORD(0x4002C1F8, _RDWORD(0x4002C1F8) | 0x1); // LPC_IOCON->P3_30 |= 1; /* D30 @ P3.30 */
_WDWORD(0x4002C1FC, _RDWORD(0x4002C1FC) | 0x1); // LPC_IOCON->P3_31 |= 1; /* D31 @ P3.31 */
_WDWORD(0x4002C200, _RDWORD(0x4002C200) | 0x1); // LPC_IOCON->P4_0 |= 1; /* A0 @ P4.0 */
_WDWORD(0x4002C204, _RDWORD(0x4002C204) | 0x1); // LPC_IOCON->P4_1 |= 1; /* A1 @ P4.1 */
_WDWORD(0x4002C208, _RDWORD(0x4002C208) | 0x1); // LPC_IOCON->P4_2 |= 1; /* A2 @ P4.2 */
_WDWORD(0x4002C20C, _RDWORD(0x4002C20C) | 0x1); // LPC_IOCON->P4_3 |= 1; /* A3 @ P4.3 */
_WDWORD(0x4002C210, _RDWORD(0x4002C210) | 0x1); // LPC_IOCON->P4_4 |= 1; /* A4 @ P4.4 */
_WDWORD(0x4002C214, _RDWORD(0x4002C214) | 0x1); // LPC_IOCON->P4_5 |= 1; /* A5 @ P4.5 */
_WDWORD(0x4002C218, _RDWORD(0x4002C218) | 0x1); // LPC_IOCON->P4_6 |= 1; /* A6 @ P4.6 */
_WDWORD(0x4002C21C, _RDWORD(0x4002C21C) | 0x1); // LPC_IOCON->P4_7 |= 1; /* A7 @ P4.7 */
_WDWORD(0x4002C220, _RDWORD(0x4002C220) | 0x1); // LPC_IOCON->P4_8 |= 1; /* A8 @ P4.8 */
_WDWORD(0x4002C224, _RDWORD(0x4002C224) | 0x1); // LPC_IOCON->P4_9 |= 1; /* A9 @ P4.9 */
_WDWORD(0x4002C228, _RDWORD(0x4002C228) | 0x1); // LPC_IOCON->P4_10 |= 1; /* A10 @ P4.10 */
_WDWORD(0x4002C22C, _RDWORD(0x4002C22C) | 0x1); // LPC_IOCON->P4_11 |= 1; /* A11 @ P4.11 */
_WDWORD(0x4002C230, _RDWORD(0x4002C230) | 0x1); // LPC_IOCON->P4_12 |= 1; /* A12 @ P4.12 */
_WDWORD(0x4002C234, _RDWORD(0x4002C234) | 0x1); // LPC_IOCON->P4_13 |= 1; /* A13 @ P4.13 */
_WDWORD(0x4002C238, _RDWORD(0x4002C238) | 0x1); // LPC_IOCON->P4_14 |= 1; /* A14 @ P4.14 */
_WDWORD(0x4002C23C, _RDWORD(0x4002C23C) | 0x1); // LPC_IOCON->P4_15 |= 1; /* A15 @ P4.15 */
_WDWORD(0x4002C240, _RDWORD(0x4002C240) | 0x1); // LPC_IOCON->P4_16 |= 1; /* A16 @ P4.16 */
_WDWORD(0x4002C244, _RDWORD(0x4002C244) | 0x1); // LPC_IOCON->P4_17 |= 1; /* A17 @ P4.17 */
_WDWORD(0x4002C248, _RDWORD(0x4002C248) | 0x1); // LPC_IOCON->P4_18 |= 1; /* A18 @ P4.18 */
_WDWORD(0x4002C24C, _RDWORD(0x4002C24C) | 0x1); // LPC_IOCON->P4_19 |= 1; /* A19 @ P4.19 */
_WDWORD(0x4002C250, _RDWORD(0x4002C250) | 0x1); // LPC_IOCON->P4_20 |= 1; /* A20 @ P4.20 */
_WDWORD(0x4002C254, _RDWORD(0x4002C254) | 0x1); // LPC_IOCON->P4_21 |= 1; /* A21 @ P4.21 */
_WDWORD(0x4002C258, _RDWORD(0x4002C258) | 0x1); // LPC_IOCON->P4_22 |= 1; /* A22 @ P4.22 */
_WDWORD(0x4002C25C, _RDWORD(0x4002C25C) | 0x1); // LPC_IOCON->P4_23 |= 1; /* A23 @ P4.23 */
_WDWORD(0x4002C260, _RDWORD(0x4002C260) | 0x1); // LPC_IOCON->P4_24 |= 1; /* OEN @ P4.24 */
_WDWORD(0x4002C264, _RDWORD(0x4002C264) | 0x1); // LPC_IOCON->P4_25 |= 1; /* WEN @ P4.25 */
_WDWORD(0x4002C268, _RDWORD(0x4002C268) | 0x1); // LPC_IOCON->P4_26 |= 1; /* BLSN[0] @ P4.26 */
_WDWORD(0x4002C26C, _RDWORD(0x4002C26C) | 0x1); // LPC_IOCON->P4_27 |= 1; /* BLSN[1] @ P4.27 */
_WDWORD(0x4002C270, _RDWORD(0x4002C270) | 0x1); // LPC_IOCON->P4_28 |= 1; /* BLSN[2] @ P4.28 */
_WDWORD(0x4002C274, _RDWORD(0x4002C274) | 0x1); // LPC_IOCON->P4_29 |= 1; /* BLSN[3] @ P4.29 */
_WDWORD(0x4002C278, _RDWORD(0x4002C278) | 0x1); // LPC_IOCON->P4_30 |= 1; /* CSN[0] @ P4.30 */
_WDWORD(0x4002C27C, _RDWORD(0x4002C27C) | 0x1); // LPC_IOCON->P4_31 |= 1; /* CSN[1] @ P4.31 */
_WDWORD(0x4002C138, _RDWORD(0x4002C138) | 0x1); // LPC_IOCON->P2_14 |= 1; /* CSN[2] @ P2.14 */
_WDWORD(0x4002C13C, _RDWORD(0x4002C13C) | 0x1); // LPC_IOCON->P2_15 |= 1; /* CSN[3] @ P2.15 */
_WDWORD(PCONP_REG, _RDWORD(PCONP_REG) | 0x00000800); // LPC_SC->PCONP |= 0x00000800;
//*********************************************
// DYNAMIC MEMORY CONFIGURATION
//*********************************************
_WDWORD(EMCDLYCTL_REG, 0x00000A05); //LPC_SC->EMCDLYCTL = 0x00000A05;
_WDWORD(EMC_CTRL_REG, 0x1); // LPC_EMC->Control = 0x00000001;
_WDWORD(EMC_CONFIG_REG, 0x0); // LPC_EMC->Config = 0x00000000;
_WDWORD(SCS_REG, _RDWORD(SCS_REG) | (1<<1)); //LPC_SC->SCS |= (1<<1);
_WDWORD(SCS_REG, _RDWORD(SCS_REG) & ~(0x00000001)); //LPC_SC->SCS &= ~(0x00000001);
_WDWORD(EMC_DYN_CFG0_REG, 0x00001680); //LPC_EMC->DynamicConfig0 = 0x00001680;
_WDWORD(EMCDLYCTL_REG, 0x00000A05);
_WDWORD(EMC_DYN_RASCAS0_REG, 2 + (2<<8)); //LPC_EMC->DynamicRasCas0 = RAS_Latency + (CAS_Latency<<8);
_WDWORD(EMC_DYN_RD_CFG_REG, 0x00000001); //LPC_EMC->DynamicReadConfig = 0x00000001;
_WDWORD(EMC_DYN_RP_REG, NS_2_CLKS(18)); //LPC_EMC->DynamicRP = NS_2_CLKS(18);
_WDWORD(EMC_DYN_RAS_REG, NS_2_CLKS(42)); //LPC_EMC->DynamicRAS = NS_2_CLKS(42);
_WDWORD(EMC_DYN_SREX_REG, NS_2_CLKS(70)); //LPC_EMC->DynamicSREX = NS_2_CLKS(70);
_WDWORD(EMC_DYN_APR_REG, NS_2_CLKS(18)); //LPC_EMC->DynamicAPR = NS_2_CLKS(18);
_WDWORD(EMC_DYN_DAL_REG, 4); //LPC_EMC->DynamicDAL = CAS_Latency+2;
_WDWORD(EMC_DYN_WR_REG, (NS_2_CLKS(6)+1)); //LPC_EMC->DynamicWR = (NS_2_CLKS(6)+1);
_WDWORD(EMC_DYN_RC_REG, NS_2_CLKS(60)); //LPC_EMC->DynamicRC = NS_2_CLKS(60);
_WDWORD(EMC_DYN_RFC_REG, NS_2_CLKS(60)); //LPC_EMC->DynamicRFC = NS_2_CLKS(60);
_WDWORD(EMC_DYN_XSR_REG, NS_2_CLKS(70)); //LPC_EMC->DynamicXSR = NS_2_CLKS(70);
_WDWORD(EMC_DYN_RRD_REG, NS_2_CLKS(12)); //LPC_EMC->DynamicRRD = NS_2_CLKS(12);
_WDWORD(EMC_DYN_MRD_REG, 2); //LPC_EMC->DynamicMRD = 2;
_WDWORD(EMC_DYN_CTRL_REG, 0x00000183); //LPC_EMC->DynamicControl = 0x00000183;
_sleep_(2);
_WDWORD(EMC_DYN_CTRL_REG, 0x00000183); //LPC_EMC->DynamicControl = 0x00000183;
_sleep_(2);
_WDWORD(EMC_DYN_CTRL_REG, 0x00000103); //LPC_EMC->DynamicControl = 0x00000103;
_WDWORD(EMC_DYN_RFSH_REG, 0x00000001); //LPC_EMC->DynamicRefresh = 0x00000001; // 1 x 16 = 16 CCLKs between SDRAM refresh cycles
_sleep_(2);
_WDWORD(EMC_DYN_CTRL_REG, 0x00000103); //LPC_EMC->DynamicControl = 0x00000103;
_WDWORD(EMC_DYN_RFSH_REG, 0x00000001); //LPC_EMC->DynamicRefresh = 0x00000001; // 1 x 16 = 16 CCLKs between SDRAM refresh cycles
_sleep_(2);
_WDWORD(EMC_DYN_RFSH_REG, NS_2_CLKS(7813 + 1)>>4); //LPC_EMC->DynamicRefresh = NS_2_CLKS(7813 + 1)>>4; // Refresh units are x16 (8192 rows...)
_sleep_(1);
_WDWORD(EMC_DYN_CTRL_REG, 0x00000083); //LPC_EMC->DynamicControl = 0x00000083; /* Issue MODE command */
_RDWORD(SDRAM_BASE_ADDR|((0x03+(2<<4))<<10)); //Temp = *((volatile uint32_t *)(SDRAM_BASE_ADDR|((0x03+(CAS_Latency<<4))<<10)));
_sleep_(1);
_WDWORD(EMC_DYN_CTRL_REG, 0x00000000); //LPC_EMC->DynamicControl = 0x00000000;
_WDWORD(EMC_DYN_CFG0_REG, _RDWORD(EMC_DYN_CFG0_REG) | 0x00080000); //LPC_EMC->DynamicConfig0 |= 0x00080000;
//*********************************************
// STATIC MEMORY CONFIGURATION
//*********************************************
_WDWORD(EMC_STA_CFG0_REG, 0x00000081); // LPC_EMC->StaticConfig0 = 0x00000081;
_WDWORD(EMC_STA_WWEN0_REG, 0x00000003); // LPC_EMC->StaticWaitWen0 = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
_WDWORD(EMC_STA_WOEN0_REG, 0x00000003); // LPC_EMC->StaticWaitOen0 = 0x00000003; /* ( n ) -> 0 clock cycles */
_WDWORD(EMC_STA_WRD0_REG, 0x00000006); // LPC_EMC->StaticWaitRd0 = 0x00000006; /* ( n + 1 ) -> 7 clock cycles */
_WDWORD(EMC_STA_WPAGE0_REG, 0x00000003); // LPC_EMC->StaticWaitPage0 = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
_WDWORD(EMC_STA_WWR0_REG, 0x00000005); // LPC_EMC->StaticWaitWr0 = 0x00000005; /* ( n + 2 ) -> 7 clock cycles */
_WDWORD(EMC_STA_WTURN0_REG, 0x00000003); // LPC_EMC->StaticWaitTurn0 = 0x00000003; /* ( n + 1 ) -> 4 clock cycles */
_sleep_(100);
}
define button "init_emc()", "init_emc()";
Setup();
init_emc();
//G,SystemInit;
//init_emc();
G;
</code>