Content originally posted in LPCWare by arion2001 on Tue Jan 13 02:44:33 MST 2015
Hi,
I am using LPC1778, 12 MHz. I am trying to initialize my SRAM to work even after following all the procedures mentioned in the LPC1778 manual, but to no avail. The compiler I am using is Crossworks Rowley 2.2.
Attached is the image of how my SRAM is connected. Also showing the screen shot as I stepped through the code and stopped at the test is writting into memory space seems like it is showing FFFFF values in there.
My init code is as follow:
static void pinConfig_SRAM(void) { //Select slew rate and also config for EMC use = 0x201 LPC_IOCON->P3_0 |= 0x201; /* D0 @ P3.0 */ LPC_IOCON->P3_1 |= 0x201; /* D1 @ P3.1 */ LPC_IOCON->P3_2 |= 0x201; /* D2 @ P3.2 */ LPC_IOCON->P3_3 |= 0x201; /* D3 @ P3.3 */ LPC_IOCON->P3_4 |= 0x201; /* D4 @ P3.4 */ LPC_IOCON->P3_5 |= 0x201; /* D5 @ P3.5 */ LPC_IOCON->P3_6 |= 0x201; /* D6 @ P3.6 */ LPC_IOCON->P3_7 |= 0x201; /* D7 @ P3.7 */ LPC_IOCON->P3_8 |= 0x201; /* D8 @ P3.8 */ LPC_IOCON->P3_9 |= 0x201; /* D9 @ P3.9 */ LPC_IOCON->P3_10 |= 0x201; /* D10 @ P3.10 */ LPC_IOCON->P3_11 |= 0x201; /* D11 @ P3.11 */ LPC_IOCON->P3_12 |= 0x201; /* D12 @ P3.12 */ LPC_IOCON->P3_13 |= 0x201; /* D13 @ P3.13 */ LPC_IOCON->P3_14 |= 0x201; /* D14 @ P3.14 */ LPC_IOCON->P3_15 |= 0x201; /* D15 @ P3.15 */ LPC_IOCON->P4_1 |= 0x201; /* A1 @ P4.1 */ LPC_IOCON->P4_2 |= 0x201; /* A2 @ P4.2 */ LPC_IOCON->P4_3 |= 0x201; /* A3 @ P4.3 */ LPC_IOCON->P4_4 |= 0x201; /* A4 @ P4.4 */ LPC_IOCON->P4_5 |= 0x201; /* A5 @ P4.5 */ LPC_IOCON->P4_6 |= 0x201; /* A6 @ P4.6 */ LPC_IOCON->P4_7 |= 0x201; /* A7 @ P4.7 */ LPC_IOCON->P4_8 |= 0x201; /* A8 @ P4.8 */ LPC_IOCON->P4_9 |= 0x201; /* A9 @ P4.9 */ LPC_IOCON->P4_10 |= 0x201; /* A10 @ P4.10 */ LPC_IOCON->P4_11 |= 0x201; /* A11 @ P4.11 */ LPC_IOCON->P4_13 |= 0x201; /* A13 @ P4.13 */ LPC_IOCON->P4_14 |= 0x201; /* A14 @ P4.14 */ LPC_IOCON->P4_15 |= 0x201; /* A15 @ P4.15 */ LPC_IOCON->P4_16 |= 0x201; /* A16 @ P4.16 */ LPC_IOCON->P4_17 |= 0x201; /* A17 @ P4.17 */ LPC_IOCON->P4_18 |= 0x201; /* A18 @ P4.18 */ LPC_IOCON->P4_19 |= 0x201; /* A19 @ P4.19 */ LPC_IOCON->P2_24 |= 0x201; /* /OE @ P2.24 ..EMC_CKE0*/ //******ONE mistake here spotted and corrected by Mike LPC_IOCON->P4_25 |= 0x201; /* /WEN @ P4.25 */ LPC_IOCON->P4_26 |= 0x201; /* /BLS0 @ P4.27 Lower Byte*/ LPC_IOCON->P4_27 |= 0x201; /* /BLS1 @ P4.27 Upper Byte*/ LPC_IOCON->P2_14 |= 0x201; /* /CS2 @ P2.14*/ } void EMCInit (void) { //SRAM_INIT(); pinConfig_SRAM(); LPC_SC->PCONP |= 0x00000800; //LPC_SC->EMCDLYCTL = 0x00001010; //LPC_SC->EMCDLYCTL |= (8<<0); //LPC_SC->EMCDLYCTL |= (8<<8); //LPC_SC->EMCDLYCTL |= (8<<16); LPC_SC->EMCCLKSEL = 0x00000000; //CLCK = EMCCLK LPC_EMC->Config = 0x00000000; LPC_EMC->StaticExtendedWait = 0x00; /* Configure memory layout, but MUST DISABLE BUFFERs during configuration */ /*The buffers can be enabled or disabled for static memory using the EMCStaticConfig Registers.*/ LPC_EMC->StaticConfig2 = 0x00000081; //16bit & active low lower and upper byte select LPC_EMC->StaticWaitWen2 = 0x00000001; //WaitWen0+1 Delay from CHip Select to Write Enable LPC_EMC->StaticWaitWr2 = 0x00000001; // program the delay from the chip select to the write access LPC_EMC->StaticWaitOen2 = 0x00000001; // Chip Select to output enable or address change whichever is later LPC_EMC->StaticWaitRd2 = 0x00000001; //Chip select to read access //LPC_EMC->StaticWaitPage2 = 0x00000000; //Delay for asynchronous page mode sequential accesses for EMC_CS0. //LPC_EMC->StaticWaitTurn2 = 0x00000000; //Number of bus turnaround cycles EMC_CS0. LPC_EMC->Control = 0x00000001; //May not be needed } *************************************************************************************************************************************************************************************** //This portion is to do a test read and write void Memtest(void) { volatile unsigned long *start= (volatile unsigned long *) 0x98000000UL; //volatile unsigned short *start= (volatile unsigned short *) 0x98000000; int value=0; int i; //for(i = 0; i < 1048576; i+= 4) for(i = 0; i < 128; i+= 1) //try just smaller bytes first. { *start = value; start++; value++; } } int main(void) { EMCInit(); while(1) { Memtest(); } } |
ldrbr0, [r2], 1; OE delay strr0, [r3, emcSWaitOen0]; 0..15 |
LPC_EMC->StaticWaitOen0 = (unsigned long) *ramTbl++; |
First some equates. Think #defines Not shown in my snippets, all numbers from user manual emcBase= 0x2009C000; External Memory Controller emcCtrl= 0x000; emcStatus= 0x004; emcConfig= 0x008; emcSExtWait= 0x080; emcSConfig0= 0x200; LPRAM 8000 0000 (512 KByte) emcSWaitWen0= 0x204; emcSWaitOen0= 0x208; emcSWaitRd0= 0x20C; emcSWaitPage0= 0x210; emcSWaitWr0= 0x214; emcSWaitTurn0= 0x218; one important assignment (not shown previously) as if "C" pretend we have long *r3; as a variable. Then r3 = (long *) emcBase; // r3 -> emc register block and as for ... ramTbl:.byte 1-0,5-1,4-1; CS-OE, CS-RD, Page RD .byte 1-1,5-2; CS-WE, CS-WR .byte 1-1,0,0; Bus Turnround, pad[2] equivalent to unsigned char ramTbl[] = {1-0, 5-1, 4-1, 1-1, 5-2, 1-1, 0, 0}; Makes it easier to experiment with timing values rather than hard coding a constant in each of the 6 places. and addr r2, ramTbl is equivalint to variable (i.e.r2 or tblPtr) = &ramTbl[0]; [or simply r2 = ramTbl; in "C" idiom] ldrbr0, [r2], 1; OE delay The "C" would be tmp = *r2++; // where r0 = tmp and r2 is the pointer to ramTbl strr0, [r3, emcSWaitOen0]; 0..15 "C": *(r3+emcSWaitOen0) = tmp; Or from your coding LPC_EMC->StaticWaitOen2 = (long) (*tblPtr++); |
typedef unsigned short datum; /* Set the data bus width to 16 bits. */ datum memTestDataBus(volatile datum * address) { datum pattern; /* * Perform a walking 1's test at the given address. */ for (pattern = 1; pattern != 0; pattern <<= 1) { /* * Write the test pattern. */ *address = pattern; /* * Read it back (immediately is okay for this test). */ if (*address != pattern) { return (pattern); } } return (0); } /* memTestDataBus() */ datum * memTestAddressBus(volatile datum * baseAddress, unsigned long nBytes) { unsigned long addressMask = (nBytes/sizeof(datum) - 1); unsigned long offset; unsigned long testOffset; datum pattern = (datum) 0xAAAAAAAA; datum antipattern = (datum) 0x55555555; /* * Write the default pattern at each of the power-of-two offsets. */ for (offset = 1; (offset & addressMask) != 0; offset <<= 1) { baseAddress[offset] = pattern; } /* * Check for address bits stuck high. */ testOffset = 0; baseAddress[testOffset] = antipattern; for (offset = 1; (offset & addressMask) != 0; offset <<= 1) { if (baseAddress[offset] != pattern) { return ((datum *) &baseAddress[offset]); } } baseAddress[testOffset] = pattern; /* * Check for address bits stuck low or shorted. */ for (testOffset = 1; (testOffset & addressMask) != 0; testOffset <<= 1) { baseAddress[testOffset] = antipattern; if (baseAddress[0] != pattern) { return ((datum *) &baseAddress[testOffset]); } for (offset = 1; (offset & addressMask) != 0; offset <<= 1) { if ((baseAddress[offset] != pattern) && (offset != testOffset)) { return ((datum *) &baseAddress[testOffset]); } } baseAddress[testOffset] = pattern; } return (NULL); } /* memTestAddressBus() */ |
ramTbl:.byte 1-0,5-1,4-1; CS-OE, CS-RD, Page RD .byte 1-1,5-2; CS-WE, CS-WR .byte 1-1,0,0; Bus Turnround, pad[2] |
-----------------------------------------------------------------------! ; Init Low Power RAM! ;-----------------------------------------------------------------------! ramTbl:.byte 1-0,5-1,4-1; CS-OE, CS-RD, Page RD .byte 1-1,5-2; CS-WE, CS-WR .byte 1-1,0,0; Bus Turnround, pad[2] fn InitLPRAM movsr0, (1<<7)+(0<<6)+(0<<3)+(1<<0) ; Byte lanes active (WE) ; CS is active low ; !Page burst ; 16 bit data bus movtr0, (0<<4)+(0<<3)+(0<<0); !WP/!buffer/!ext wait strr0, [r3, emcSConfig0]; set options as above adrr2, ramTbl; memory timing table ldrbr0, [r2], 1; OE delay strr0, [r3, emcSWaitOen0]; 0..15 ldrbr0, [r2], 1; Read delay strr0, [r3, emcSWaitRd0]; 0..31 +1 ldrbr0, [r2], 1; Page mode read delay strr0, [r3, emcSWaitPage0]; 0..31 +1 ldrbr0, [r2], 1; WE delay strr0, [r3, emcSWaitWen0]; 0..15 +1 ldrbr0, [r2], 1; Write delay strr0, [r3, emcSWaitWr0]; 0..31 +2 ldrbr0, [r2] ; bus turn round delay strr0, [r3, emcSWaitTurn0]; 0..15 +1 bxlr; fe InitLPRAM |
;-----------------------------------------------------------------------! ; MemTestData! ;-----------------------------------------------------------------------! fn MemTestData movsr3, 0x80000000; LP RAM movsr2, (1<<15); D15 0:strr2, [r3]; write data bit ldrr1, [r3]; read back subsr0, r1, r2; same? bne9f; OOPS lsrsr2, 1; next data bit bne0b; all done? 9:bxlr; return (0 = ok) fe MemTestData ;-----------------------------------------------------------------------! ; MemTestAddr! ;-----------------------------------------------------------------------! fn MemTestAddr push{r4,r5,r7,lr}; save regs movsr7, 0x80000000; LP RAM movwr5, 0x5555; pattern movwr4, 0xAAAA; inverse ;---------------------------------------; movsr3, (1<<18); A18 0:strhr5, [r7, r3]; populate SRAM with pattern lsrsr3, 1; cmpr3, 1; done (A18..A01)? bhi0b; not yet ;---------------------------------------; movsr3, (1<<18); A18 strhr4, [r7]; check for bits stuck high 0:ldrhr1, [r7, r3]; check address bit subsr0, r1, r5; intact? bne9f; OOPS lsrsr3, 1; cmpr3, 1; done (A18..A01)? bhi0b; not yet strhr5, [r7]; now, set base addr to pattern ;---------------------------------------; movsr3, (1<<18); A18 (test) 0:strhr4, [r7, r3]; set addr bit to inverse ldrhr1, [r7]; stuck low test subsr0, r1, r5; intact? bne9f; OOPS movsr2, (1<<18); A18 (probe) 1:cmpr2, r3; skip if test = probe beq2f; ldrhr1, [r7, r2]; shorted test subsr0, r1, r5; intact? bne9f; OOPS 2:lsrsr2, 1; next probe bit cmpr2, 1; done (A18..A01)? bhi1b; not yet strhr5, [r7, r3]; set addr bit back to pattern lsrsr3, 1; next test bit cmpr3, 1; done (A18..A01)? bhi0b; not yet ;---------------------------------------; 9:pop{r4,r5,r7,pc}; return fe MemTestAddr ;-----------------------------------------------------------------------! ; MemTestDevice! ;-----------------------------------------------------------------------! fn MemTestDev ;---------------------------------------; ; populate ram with deterministic data; movsr3, 0x80000000; LP RAM movsr2, (1<<19); nbr bytes (512 Kb) movsr1, 7; start value 0:strr1, [r3], 4; *p++ = v++ addsr1, 1; subsr2, 4; while (--nWords) bgt0b; ;---------------------------------------; ; validate and invert; movsr3, 0x80000000; LP RAM movsr2, (1<<19); nbr bytes (512 Kb) movsr1, 7; start value 0:ldrr0, [r3]; v = *p subsr0, r0, r1; validate bne9f; OOPS mvnsr0, r1; inverse strr0, [r3], 4; *p++ = ~(v++) addsr1, 1; subsr2, 4; while (--nWords) bgt0b; ;---------------------------------------; ; validate and clear; movsr3, 0x80000000; LP RAM movsr2, (1<<19); nbr bytes (512 Kb) movsr1, 7; start value 0:ldrr0, [r3]; v = ~*p mvnsr0, r0; subsr0, r0, r1; validate bne9f; OOPS movsr0, 0; clear strr0, [r3], 4; *p++ = 0 addsr1, 1; v++ subsr2, 4; while (--nWords) bgt0b; 9:bxlr; return (0 = ok) fe MemTestDev |
void EMCInit (void) { SRAM_INIT(); pinConfig_SRAM(); LPC_SC->PCONP |= 0x00000800; LPC_SC->EMCCLKSEL = 0x00000000; //CLCK = EMCCLK LPC_EMC->Config = 0x00000000; LPC_EMC->StaticExtendedWait = 0x00; LPC_EMC->StaticConfig2 = 0x00080189; //16bits,Asynch PageMode On, CS active low, active low BLs,Extend Wait, Buffer enable LPC_EMC->StaticWaitWen2 = 0x00000000; //WaitWen0+1 Delay from CHip Select to Write Enable LPC_EMC->StaticWaitWr2 = 0x00000003; // program the delay from the chip select to the write access LPC_EMC->StaticWaitOen2 = 0x00000001; // Chip Select to output enable or address change whichever is later LPC_EMC->StaticWaitRd2 = 0x00000003; //Chip select to read access LPC_EMC->StaticWaitPage2 = 0x00000003; //Delay for asynchronous page mode sequential accesses for EMC_CS0. LPC_EMC->StaticWaitTurn2 = 0x00000000; //Number of bus turnaround cycles EMC_CS2. LPC_EMC->Control = 0x00000001; } |
void Memtest(void) { volatile unsigned long *start= (volatile unsigned long *) 0x98000000UL; volatile unsigned long *finish= (volatile unsigned long *) 0x98100000UL; int value=0; int i; int Memory_Size = 1048576; //int Memory_Size = 2048; for(i = 0; i < Memory_Size; i+= 4) //for(i = 0; i < 32; i+= 1) //try just 32 bytes first. { *start = value; start++; value++; } for(i = Memory_Size; i > 0; i-= 4) { *finish = value; finish--; value--; } } |
void EMCInit (void) { SRAM_INIT(); pinConfig_SRAM(); LPC_SC->PCONP |= 0x00000800; LPC_SC->EMCCLKSEL = 0x00000000; //CLCK = EMCCLK LPC_EMC->Config = 0x00000000; LPC_EMC->StaticExtendedWait = 0x00; /* Configure memory layout, but MUST DISABLE BUFFERs during configuration */ /*The buffers can be enabled or disabled for static memory using the EMCStaticConfig Registers.*/ LPC_EMC->StaticConfig2 = 0x00080189; //16bits,Asynch PageMode On, CS active low, active low BLs,Extend Wait, Buffer enable LPC_EMC->StaticWaitWen2 = 0x00000001; //WaitWen0+1 Delay from CHip Select to Write Enable LPC_EMC->StaticWaitWr2 = 0x00000001; // program the delay from the chip select to the write access LPC_EMC->StaticWaitOen2 = 0x00000001; // Chip Select to output enable or address change whichever is later LPC_EMC->StaticWaitRd2 = 0x00000001; //Chip select to read access LPC_EMC->StaticWaitPage2 = 0x00000001; //Delay for asynchronous page mode sequential accesses for EMC_CS0. LPC_EMC->StaticWaitTurn2 = 0x00000001; //Number of bus turnaround cycles EMC_CS2. LPC_EMC->Control = 0x00000001; } |
ramTbl:.byte 1-0,5-1,4-1; CS-OE, CS-RD, Page RD .byte 1-1,5-2; CS-WE, CS-WR .byte 1-1,0,0; Bus Turnround, pad[2] |