While trying to get the SDK's bootloader working with gcc, I have to replace some ARMCC-speific code found in bootloader_util_arm.c:
__asm void StartApplication(uint32_t start_addr)
{
; Get App MSP.
LDR R2, [R0]
; Set the main stack pointer to the applications MSP.
MSR MSP, R2
; Get application reset vector address.
LDR R3, [R0, #0x00000004]
; No return - stack code is now activated only
; through SVC and plain interrupts.
BX R3
ALIGN
}
void bootloader_util_app_start(uint32_t start_addr)
{
StartApplication(start_addr);
}
After trying some approaches I found 2 apparently working solutions to substitute that for gcc. The 1st one is based on some code I found in Ole Mortens early bootloader implementation:
typedef void (*main_t)();
void bootloader_util_app_start(uint32_t start_addr)
{
main_t app_main =*(main_t*)(start_addr+4);
app_main();
}
The 2nd solution uses inline assembler:
void bootloader_util_app_start(uint32_t start_addr)
{
// Assign app code address
asm volatile(" LDR R0, =0x14000 \n\t"
// Get App MSP
" LDR R2, [R0] \n\t"
// Set the main stack pointer to the applications MSP
" MSR MSP, R2 \n\t"
// Get application reset vector address
" LDR R3, [R0, #0x00000004] \n\t"
// No return - stack code is now activated only
// through SVC and plain interrupts
" BX R3 \n\t"
" .ALIGN ");
}
Both solutions are working (on my desktop) but are they safe? Don't know if MSP is set right in the 1st approach.
All tested with gcc-arm-none-eabi-4_7-2013q3 and gcc-arm-none-eabi-4_8-2013q4 compiled on a linux host (kubuntu 12.04 with backports) using both Ole Mortons pure-gcc and also the original sdk gcc setup (makefiles, linkerscripts and startup code).