Hello,
I'm using the Embedded Artists LPC1788 development kit and I'm trying to get a very simple RTX application running using the external SDRAM.
Here is what I have so far:
1) A simple RTX application that runs (blinks an LED) with no problem when I use the internal RAM. This same application crashes with a bus fault in "os_sys_init" when I us the external SDRAM.
2) I configure and initialize the external SDRAM before the call to __main (this is working as I can run the same blinking LED using the SDRAM with no RTX.
3) Even if I let me STACK and HEAP remain in the internal RAM but have variables etc.. in the SDRAM I get the bus fault.
4) The bus fault is an IMPRECISERR: Imprecise data bus error
The call stack looks like this when the fault occurs:
HardFault_Handler -> rt_put_rdy_first() -> rt_dispatch() -> rt_task_create() -> SVC_Hanlder...
Does anyone have any suggestions? I see no reason why this should cause a fault.
Thanks.
MAC
Oh man, I screwed up! I just noticed I can't seem to divide correctly by shifting (lol)
k = SDRAM_SIZE>>2; // size in bytes divided by 2 (16bit access)
the comments show intent, but the code shows gross error...
when you go back through the code, and change the shift values to the correct ones, the timing output from TeraTerm now looks like this:
Evaluating SDRAM performance: 0 ...clearing SDRAM (8388608 bytes)...............complete! (185 ms.) ...testing SDRAM 16-bit write (4194304 words)...complete! (307 ms.) ...testing SDRAM 16-bit read (4194304 words)....complete! (621 ms.), Errors: 0 ...testing SDRAM 32-bit write (2097152 dwords)..complete! (173 ms.) ...testing SDRAM 32-bit read (2097152 dwords)...complete! (298 ms.), Errors: 0 Comprehensive SDRAM performance: 0 ...clearing SDRAM (8388608 bytes).....................complete! (185 ms.) ...Walking-bit test: SDRAM 16-bit (4194304 words).....complete! (10.468 sec) (Errors: 0) ...Alternate-bit test: SDRAM 16-bit (4194304 words)...complete! (01.390 sec) (Errors: 0) ...Unique value test: SDRAM 16-bit (4194304 words)....complete! (00.900 sec) (Errors: 0) ...Walking-bit test: SDRAM 32-bit (2097152 dwords)....complete! (09.675 sec) (Errors: 0) ...Alternate-bit test: SDRAM 32-bit (2097152 words)...complete! (00.605 sec) (Errors: 0) ...Unique value test: SDRAM 32-bit (2097152 words)....complete! (00.452 sec) (Errors: 0) System ready for USB testing...
I guess the whole point here was to show that the SDRAM worked fine at 120Mhz, not how ignorant I am...
-Dave
So no errors even when the "+ 1" is removed. Hmm, I was about to try adding the "+ 1".
Thanks for all the comments, I think I'll just wait t0 see what NXP responds before spending more time on this item.
Cheers.
M
Well, I got NXP's final answer...
The EMC is rated at 80 MHz. It may work above that, but it is not characterized above 80 MHz. Regards Paul
Go figure...
Hello Folks,
I'm not sure if any of you saw this but I found another bug that would affect this topic.
Dave - Your macro #define tCLK_ns ((double)EMCClock / 1000000000.0 ) may be calculating incorrectly again but only because of an NXP bug.
The EMCClock variable is calculated incorrectly in the "system_LPC177x_8x.c" file.
All of the lines like this (and similar):
EMCClock = (OSC_CLK / ((LPC_SC->EMCCLKSEL & 0x01)+1));
Should be more like this:
EMCClock = (SystemCoreClock / ((LPC_SC->EMCCLKSEL & 0x01)+1));
Anyway, this would skew the macro calculation by a factor of 2.
Here is a better explanation of the issue I found:
www.lpcware.com/.../emc-clock
Hi Marc,
I took a look at the definition for EMCClock, and this is what I found:
uint32_t EMCClock = __EMC_CLK; /*!< EMC Clock Frequency */
tracing the definition for __EMC_CLK further reveals this:
#if ((CCLKSEL_Val & 0x100) == 0) /* cclk = sysclk */ #if ((CLKSRCSEL_Val & 0x01) == 0) /* sysclk = irc_clk */ #define __CORE_CLK (IRC_OSC / __CCLK_DIV) #define __PER_CLK (IRC_OSC/ __PCLK_DIV) #define __EMC_CLK (IRC_OSC/ __ECLK_DIV) #else /* sysclk = osc_clk */ #define __CORE_CLK (OSC_CLK / __CCLK_DIV) #define __PER_CLK (OSC_CLK/ __PCLK_DIV) #define __EMC_CLK (OSC_CLK/ __ECLK_DIV) #endif #else /* cclk = pll_clk */ #if ((CLKSRCSEL_Val & 0x01) == 0) /* sysclk = irc_clk */ #define __CORE_CLK (__PLL0_CLK(IRC_OSC) / __CCLK_DIV) #define __PER_CLK (__PLL0_CLK(IRC_OSC) / __PCLK_DIV) #define __EMC_CLK (__PLL0_CLK(IRC_OSC) / __ECLK_DIV) #else /* sysclk = osc_clk */ #define __CORE_CLK (__PLL0_CLK(OSC_CLK) / __CCLK_DIV) #define __PER_CLK (__PLL0_CLK(OSC_CLK) / __PCLK_DIV) #define __EMC_CLK (__PLL0_CLK(OSC_CLK) / __ECLK_DIV) #endif #endif
When this is evaluated at compile time, since I'm using the PLL0 clock, and my sysclk is the osc_clk, I get simply:
#define __CORE_CLK (__PLL0_CLK(OSC_CLK) / __CCLK_DIV) #define __PER_CLK (__PLL0_CLK(OSC_CLK) / __PCLK_DIV) #define __EMC_CLK (__PLL0_CLK(OSC_CLK) / __ECLK_DIV)
evaluating the macro __PLL0_CLK(), I get:
#define __M ((PLL0CFG_Val & 0x1F) + 1) #define __PLL0_CLK(__F_IN) (__F_IN * __M)
Since OSC_CLK is defined as XTAL, which is 12M, and __PLL0_CLK(12M) = 120M (since __M = 10 for me), the __EMC_CLK value is calculated correctly (I believe).
Can you please explain this better for me?
Hi Dave,
When the CPU clock divider is 1 than this will calculate correctly. The problem is when it isn't.
This is what I believe is required as a change:
#define __CORE_CLK (__PLL0_CLK(OSC_CLK) / __CCLK_DIV) #define __PER_CLK (__PLL0_CLK(OSC_CLK) / __PCLK_DIV) #define __EMC_CLK (__CORE_CLK / __ECLK_DIV)
The reason is that the fig. 7 in the user manual is incorrect. The EMC Clock divider is not feed from the mux (sys_clk or pll0_clk) it is feed from the CPU clock.
So in your setup if you divided the CPU clock to 60MHz (by 2) the EMC Clock would still calculate to 120MHz which is incorrect.
Hope this helps.
Regards,
Marc
Got it! - you are absolutely correct, and I verified it in my test code...
Thanks so much for the input - it makes for building a better mouse trap... ;-)