Hello,
I'm working with the AT91SAM9361 controller. Moreover I installed a nor flash (where the real program is stored) and a small data flash (where a small bootloader is stored. Among other things, the bootloader should check if the arm vectors (at the beginning of each code) are valid). If this code is valid the program stored in the nor flash should be executed.
I want to use two seperate memories, so that everyone is able to load a new update of the real program via the bootloader in the dataflash in the nor flash.
How is it possible to start the application from the bootloader in the nor flash? Do I have to set the PC to the beginning of the nor flash? Which are the steps to execute this programm?
I'm not working with an operating system.
best regards Hans
I'm not using ARM but C166 but since it's Keil I expect things to be quite similar.
I like the idea of having a stable bootloader stored in flash. We should have done it that way in a previous project I did...
What we are using now, during development, is the bootstrap loader functionality of the C166 to download new software and store it in flash. Does the ARM have something similar? We set the MCU to bootstrap download, it starts listening on its UART and we can download a small app to RAM that continues listening for more data to be stored in flash. That way you don't need anything stored in flash, but you do however need to switch a jumper to set the MCU to bootstrap mode; opening a device like that might not be an option.
To do flash updates from within our application, we have in fact 2 standalone apps (not an optimal solution at this moment, but hey, legacy...): the flash application (ie. "bootloader") and the main application.
If you look at the startup.asm file, in our case, what it does at the end is:
JMP FAR main ; Jump to C program
Before that, we check if it should switch to the flash application by doing a call:
EXTERN MAINAPP_test_for_update : FAR CALL MAINAPP_test_for_update
Depending on the result, it simply jumps to a hardcoded memory location (like you mentioned already) where the flash application is stored:
JMPS 01H, 00000H ; location of FLASHAPP
At that address, the entire flash application is stored, starting again with a startup.asm file.
In your casem, you could switch things around, by starting the device to the bootloader, testing if it should do anything (timeout on serial input or something; if update -> read data and update main application flash) and if no update is requested, jump to the fixed memory location of your main application.
Good luck, Joost
AT91SAM9361 doesn't exist. You probably mean AT91SAM9261 or AT91SAM9263.
ARM is quite different from C166 so I wouldn't take it for a reference. Also you need to take into the account the SAM9 specifics.
You should check the SAM9 user manuals for details.
Basically SAM9 can directly boot from NOR Flash when BMS = 0 (latched at reset). The flash is mapped at address 0 and starts automatically. Alternative is to boot from internal ROM (BMS = 1 at Reset) and this is what you need looking at your requirements.
Booting from internal ROM starts Atmel's bootloader which will try to load user's program (second level bootloader) to internal SRAM from SD Card, NAND Flash, SPI Data Flash, USB (in that order). In your case you need a valid bootloader in SPI Data Flash (first 8 vectors including size) which will be downloaded into internal SRAM, remapped to address 0 and started from that address.
Your bootloader then needs to validate if NOR Flash contains a valid program and then copy the complete vector table (first 64 bytes) from NOR Flash to SRAM at address 0 and the jump to NOR Flash to it's start address (address 0x10000000 when Chip select 0 is used). Your application for NOR flash needs to include the standard Atmel startup file and needs to be compiled for the NOR flash address. This is pretty much all you need to do.
thanks for your help.
copy the complete vector table (first 64 bytes) from NOR Flash to SRAM the only thing I don't understand is how could I copy the first 64Byte from the nor flash to the internal sram, if the bootloader from the data flash is already at 0x00?
//copy from 0x10000000 to 0x00000000 (range 0x20) //jump to 0x10000000 or 0x10000020?
And what about the first 64 Bytes? I thought I've only to copy the first 32Byte (arm vectors) to the internal RAM?
ok the bootloader in the data flash works.
But could you tell me the way I have to write the jump instruction?
I copy the first 32Bytes (arm vectors) to 0x00000000 with memcpy()
int main(void) { void (*functionptr)( void ) = 0x0; //... //copy the arm vectors memcpy((char *)0x00000000, (char *)(0x10000000), 32); //generate jump instruction to 0x10000000???? //jump to 0x00000000 functionptr(); return 0; }
The problem is that I have to place the jump instruction behind the last arm vector and I don't know how to do that...
__asm { //JMP 0x10000000 }
how could I copy the first 64Byte from the nor flash to the internal sram, if the bootloader from the data flash is already at 0x00?
Bootloader already executed remap and now SRAM is at address 0. So copying should be performed like:
//copy from 0x10000000 to 0x00000000 (range 0x40)
And then the user code can be executed:
//jump to 0x10000000 or 0
8 vectors (32 bytes) are actually LDR instructions which use addresses located after the vectors (another 32 bytes). Therefore you need to copy the first 64 bytes.
thank you for your explanations. At the moment the programm code in the nor flash won't work.
That's my programm which runs in the internal RAM (executed from the data-flash)and should start the nor-flash application. Could you see some errors?
int main(void) { void (*functionptr)( void ) = (void (*)(void))0x10000000; //led led(); //copy first 64Bytes to 0x0 (START_ADDR) memcpy((char *)START_ADDR, (char *)(AT91_NORFLASH_BASE), 64); //Norflash-Base: 0x10000000 functionptr(); return 0; }
I made a test and it seems that it should work. I load a small programm in the internal RAM so that I could see what the processor is doing.
The internal RAM is at 0x00200000
1. copy the 64Bytes at the beginning of the internal RAM
memcpy((char *)0x00200000, (char *)(0x10000000), 64);
2. functionsptr() //to 0x10000000
The PC jump to 0x10000000 and then to 0x10000058 (after the last vectors EAFFFFFE B...)
When I run the programm I get a lof of "JTAG Communication Failure" error messages.
Hi,
now I'm able to run the programm! The error was within the startup script. You have to disable the pll, because if the pll is already started, plls will be turned off!
I find this message in the atmel startup file. Maybe it would be a great thing if Keil could add some comments to their files, too!