Hi,
I need to place some data in RAM and then use the watchdog to force a device reset. After the device reset, I will read the same locations in RAM to determine what to do. This has to do with a bootloader project.
However, I am running into a very strange problem that stumps me. I can work around it, but I need to understand what's happening.
I am using a Keil MCB2130 (MCU 2138/01, NXP bootloader v2.12), a Keil ULINK2, and a full licence of uVision3/RealView compiler.
I've modified one of the demo projects to test this. Here's the complete code:
#include <LPC213X.H> int main (void) { unsigned int n, i, j; //IODIR1 = 0x00FF0000; /* P1.16..23 defined as Outputs */ // while (0) { /* Loop forever */ for (n = 0x00010000; n <= 0x00800000; n <<= 1) { /* Blink LED 0, 1, 2, 3, 4, 5, 6, 7 */ IOSET1 = n; /* Turn on LED */ for(i = 0; i < 200000; i++) { if(j > 100) j = 0; j++; } IOCLR1 = 0x00FF0000; /* Turn off LEDs */ } } *((volatile unsigned long *)0x40000000) = 0xABCD1234; *((volatile unsigned long *)0x40000004) = 0x30000; WDTC = 0xFFFF; WDMOD = 0x03; WDFEED = 0xAA; WDFEED = 0x55; while(1); }
The startup code is as default, but I have changed the target options so that IRAM1 starts at 0x40000040 instead of 0x40000000 (which is start of RAM on this device).
Now, if I set a breakpoint before the watchdog is started, I can see that the values 0xABCD1234 and 0x30000 are correctly written to ram at 0x40000000 and 0x40000004. However, when the watchdog has expired and the device has been reset, I can see that only the value in 0x40000000 has survived the reset. The value at 0x40000004 has been corrupted. That is strange, but it becomes even more strange:
If I modify the code like so:
*((volatile unsigned long *)0x40000000) = 0xABCD1234; *((volatile unsigned long *)0x40000004) = 0x30000; *((volatile unsigned long *)0x40000008) = 0x12345678;
then it is the value at 0x40000008 that gets corrupted after watchdog reset.
Why does this happen? The NXP bootloader should not touch this memory area according to their docs.
To make it even stranger, this modification also fixes the issue:
*((volatile unsigned long *)0x40000000) = 0xABCD1234; *((volatile unsigned long *)0x40000004) = 0x30000; *((volatile unsigned long *)0x40000004) = 0x30000;
Writing the same value twice to the same memory location should not make a difference, but it does.
I am hoping I am missing something really obvious here, but I've spent the better part of the evening on this problem now, and I can't figure it out.
Regards -Oyvind