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] |