Hello
We used Nuvoton Nu-Tiny Evaluation Board M051 V 2.0 (having on-board Nuvoton M0516LBN controller 'Cortex-M0' with 12 MHz external crystal) in our 8052-based project hardware. We interfaced 32K Battery-backed parallel SRAM (Cypress Make CY62256HLL-70PXC).
For accessing this parallel SRAM, we used the ARM EBI interface (8-bit) and matched the data lines, address lines, RD/, WR/, CS/, ALE as per the EBI requirements for Cortex-M0 Core.
For multiplexed address and data bus, we interfaced the latching device 74HC373 and connected ALE to its OE.
LEDs are used in the project, which are used as status indicators. They are directly interfaced to GPIOs.
Keil Project Settings:
Selected Nuvoton M0516LBN Controller; Set off-chip SRAM (IRAM1) at address 0x60000000; Used Scatter Loading in Keil Linker options; Checked 'Use Memory Layout from Target Dialog' in Linker options; As per the 'startup_M051Series.s' file, control jumps into SystemInit() before main() at startup.
The initialization routines are in this SystemInit() function routine.
Project code flow:
--> Unlock Protected Registers;
--> Enable External 12 MHz crystal and wait for clock stable;
--> GPIO Initializations: Port 0 as Quasi-Bidirectional (AD0 ~ AD7); Port 2 as Quasi-Bidirectional (A8 ~ A15); Remaining used port pins as per I/O requirement;
--> EBI Initializations:
#define M32(adr) (*((volatile unsigned long *) (adr))) #define EBI_MCLKDIV_4 0x2UL /* EBI output clock(MCLK) is HCLK/4 */ #define VAL 3 void DrvEBI_SetBusTiming(void) { EBI->EBICON.ExttALE = VAL; EBI->EBICON.MCLKDIV = EBI_MCLKDIV_4; EBI->EXTIME.ExttACC = VAL; EBI->EXTIME.ExttAHD = VAL; EBI->EXTIME.ExtIW2X = VAL; EBI->EXTIME.ExtIR2R = VAL; } void ebi_init(void) { /* Multiple Function Port 0 Control Register */ M32(&SYS->P0_MFP) |= 0x000000FF; M32(&SYS->P0_MFP) &= 0xFF0000FF; /* Multiple Function Port 1 Control Register */ M32(&SYS->P1_MFP) &= 0xFF000000; /* Multiple Function Port 2 Control Register */ M32(&SYS->P2_MFP) |= 0x000000FF; M32(&SYS->P2_MFP) &= 0xFF0000FF; /* Multiple Function Port 3 Control Register */ M32(&SYS->P3_MFP) &= 0xFF000000; M32(&SYS->P3_MFP) |= 0x000038C3;/* Enable nRD/nWR for EBI, MCLK for EBI */ //Multiple Function Port 4 Control Register M32(&SYS->P4_MFP) &= 0xFF000000; M32(&SYS->P4_MFP) |= 0x00000030; /* Enable ALE/nCS for EBI */ DrvEBI_SetBusTiming(); /* EBI function enable */ EBI->EBICON.ExtBW16 = 0; /* EBI data width is 8-bit */ /*EBI Controller Clock Enable Control */ SYSCLK->AHBCLK.EBI_EN = 1; /* Enable the EBI engine clock */ /* This bit is the functional enable bit for EBI */ EBI->EBICON.ExtEN = 1; /* EBI function is enabled */ }
--> Lock Protected Registers;
--> CY62256 SRAM Testing Routine (EBI_SRAM BSP code) Path: "C:\Nuvoton\BSP Library\M051_Series_BSP_CMSIS_Rev3.00.002\ SampleCode\RegBased\EBI_SRAM\KEIL\EBI_SRAM.uvproj"
RAM Test:
const uint32_t g_au32DataArrary[4] = {0x36363636, 0xFFFFFFFF, 0x5A5A5A5A, 0x70707070};/* RAM check pass for these values */ The SRAM testing code is modified as per 8-bit EBI; The 32-bit values in g_au32DataArrary[] are checked; LEDs are used to indicate the RAM test status; RAM test is OK with the array values provided in the BSP code; The SRAM test fails for some specific 32-bit values in combination with 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x08, 0x09; So, patterns like 0x01010101, 0x50505050, 0x08080808, 0x00000000, etc fails.
--> main() starts after successful RAM Test. All headers are included in file containing main().
RAM test is just a basic RAM cross-checking operation. After the system comes into running mode with timely interrupts and other hardware-driven operations, some variables or flags stored in the external RAM fail in conditional checkings, as explained below:
unsigned char hook_state;/* = 0 at startup */ if(hook_state == 1)/* Inside the main() while{} superloop */ { hook_state = 0; //remaining code. } hook_state = 1; /* Inside the Timer ISR or any other function */
Eventhough the flag is set, the condition fails. So, non-logical changes made to the above code...
unsigned char hook_state;/* = 0x55 at startup */ if(hook_state == 0xAA)/* Inside the main() while{} superloop */ { hook_state = 0x55; //remaining code. } hook_state = 0xAA; /* Inside the Timer ISR or any other function */
Now, the condition is TRUE.
Any specific reason for above conditional failures?
Any suggestions for proper access to the external RAM when using Cortex Core.
It actually has nothing specifically to do with the Cortex core - it is all down to the particular vendor's EBI implementation.
So you need to carefully study the Manufacturer's documentation for the proper use of the specific EBI implementation in this particular Chip:
" href= "http://www.nuvoton.com/hq/products/microcontrollers/arm-cortex-m0-mcus/m051-base-series/?__locale=en"> www.nuvoton.com/.../
I believe some people think about "core" as similar to Intel's "Core", "CoreDuo", Core2Duo", ... and misses that companies buys parts of a processor and then glues on additional intellectual properties also bought from ARM or inhouse-developed or bought from other companies when they want to release Cortex-based chips.
Yes, a lot of people fail to understand ARM's business model and what, exactly, it is that they do & do not provide.
Witness frequent references to "ARM microcontroller" and "I want to learn ARM", etc...
Diagram (and text) here show what constitutes the Cortex-M0 Core:
www.arm.com/.../cortex-m0.php
No matter Whether it is ARM Core or 8052.
The main problem is: Some variables or flags stored in the external RAM fail in conditional checkings (or) their values are read as different from what exactly they should be
Example:
Eventhough the flag is set, the condition is FALSE. So, non-logical changes made to the above code...
Same is the case if we tried to test the External RAM in a loop, as shown below:
#define EBI_BASE_ADDR 0x60000000UL #define EBI_Write_Data8(u16Addr, u8Data) (*((volatile unsigned char *)( (EBI_BASE_ADDR) + u16Addr)) = u8Data) #define EBI_Read_Data8(u16Addr)(*((volatile unsigned char *)( (EBI_BASE_ADDR) + u16Addr))) void RAM_Test(void) { unsigned short no; unsigned char error; error = 0; for(no=0 ;no < 0x8000; no++) { EBI_Write_Data8(no,0x55); if(EBI_Read_Data8(no)!=0x55) error = 1; EBI_Write_Data8(no,0xAA); if(EBI_Read_Data8(no)!=0xAA) error = 1; } }
error = 0 after the above loop execution.
Now, if we tried to change the values, the test fails:
void RAM_Test(void) { unsigned short no; unsigned char error; error = 0; for(no=0 ;no < 0x8000; no++) { EBI_Write_Data8(no,0x01); if(EBI_Read_Data8(no)!=0x01) error = 1; EBI_Write_Data8(no,0x09); if(EBI_Read_Data8(no)!=0x09) error = 1; } }
RAM test failed for values 0x00,0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 0x09
Any specific reason for failure with these values?
You need to declare hook_state as volatile.
I declared hook_state as volatile and the result is same
I can't see that you have specified how you have specifically verified every signal line between processor and memory, and verified that each signal can be set high or low without affecting any other signal.
And I can't see that you have made any notes that the high and low voltages - and rise/fall times - have been checked for each signal line to verify that you don't have any accidental resistors or capacitors creating load, or for some reason gets two outputs to try to drive the same signal lines.
Yes, it is quite possible for a naive RAM test to "pass" when the hardware is actually faulty - been there, done that.
Clearly, if your RAM (and/or its interface) is faulty, you are going to get trouble with anything that uses it!
See this article for a detailed discussion of the types of faults that can occur in RAM systems, and code to detect them:
www.esacademy.com/.../software-based-memory-testing.html