I am experiencing strange (quite) random issue while writing a bootloader for ARM926ejs.
The bootloader's work is as follow:
- it allows to update the application via a serial port, writing the application code to flash.
(By using checksums, I am sure that data that has been written to flash is correct)
- it loads the application from flash to RAm then starts it by calling the reset handler.
The basic memory map looks like the following in ram (when application has been loaded):
0x80000000 - 0x80040000: bootloader
0x80140000 - 0x80200000: application
The application program's reset handler is located at 0x80141000.
The bootloader's reset handler and application's reset handler perform the same work as follow
(except that adresses are different for MMU table):
1. clean D cache
2. flush D cache
3. flush I cache
4. Disable MMU table
5. Initialize MMU (with the TTB) mainly:
-> Code section to Read-Only / Write Through (RO+WT)
-> Stacks/Heaps Read-Write / Write Back (RW+WB)
-> Hardware registers to Read-Write / NonCache-NonBuffered (RW+NCNB)
-> Free memory space to Read-Write / Write Back (RW+WB)
MMU Translation Table located at 0x80800000 in both cases
6. Enable MMU
7. Set CPU to Supervisor Mode
8. Initialize stack pointer for each CPU mode (Supervisor, Abort, Undefined, Fast Interrupt etc...)
9. Go to system mode
10. Do some lowlevel initialization, then start C main function
11. Then run the program (initialize peripherals etc...)
Steps 1-10 are performed in assembly.
In order to start from the RESET handler, I declare a function pointer as follow:
typedef void (*RESET_HANDLER)();
RESET_HANDLER reset = 0x800141000; <- knowing that my reset handler's first instruction is here.
The interest in doing this way is that the application program should be completely independant
from the boot program. It completely reinitializes the board, stacks etc... for its purpose.
The merit is that if some low-level implementation is to be optimized later, we can update the
application easily via the bootloader, and the appli will benefit from lowlevel ameliorations
in the drivers etc.
The bootloader is just a little program that allows to update the application program.
Also, I can compile and run the application or the bootloader just fine in a debugger with
exactly the same memory mapping as they have after loading from flash.
The application program's update via the bootloader is doing fine.
Now, the problem is that when writing the application to flash, the application aborts when it
has been loaded to RAM then started by the bootloader.
The application is loaded into RAM, I can confirm it with the debugger and the checksums.
When I got the abort exception I took a pick at the R14 register, and it was pointing to the
first instruction that initializes an hardware peripheral register. I dont really know if it
is relevant, or even a true information, since the board since to be in a quite unstable state
when in the abort mode (though the abort handler is just an infinite loop).
Also, I touched the initialization assembly in order to find a solution, and actually at first
I was not performing the following steps:
1. clean D cache
2. flush D cache
3. flush I cache
Then by adding that, AND by changing the code's section attributes in the MMU table:
-> Code section to Read-Write / Write Through (RW+WT)
in both the bootloader program and the application, I was able to start the application from the
I am not sure that adding cache cleaning/flushing and changing code section parameter really had
such a decisive impact (Id like to verify it, but i couldnt check before posting).
Actually at first I added some flushing/cleaning in the reset handler.
Then it seemed to work, and I was able to start application from flash.
THen I recompiled everything to be sure, and I got the same problem occuring again.
Then I modified the flush/clean code, because I discovered that the code was already there, so I
took my own flushing/cleaning away, and used the one I had been provided with.
When I used this new flush/clean code, I was not able to overwrite the application program
with the debugger in the same debug session ("error: Could not write at address 0x80147A94" or so...).
If I closed the debug program and restarted it, I could overwrite the program without problem.
Then I thought without believing it: "maybe this is because the code section is read-only?"
So I changed the code read only to read-write, and everything is working fine now.
I really don't understand, does someone have any idea of what is going on here?
I was also wondering if this could have something to do with an alignment problem?
All my stacks and sections are 8bytes aligned, since it seemed the easiest to handle with
ARM926, and the whole code is at the same memory location when executing from flash or with the
debugger. But maybe there is something else I should care about?
Any idea? Did I miss something?
(I tried to sumup the problem as much as I could so I didn't give much details.
Ill post some source tomorrow if someone wants to take a look)
This post has been edited by FGirault: 25 June 2011 - 03:05 PM