I have been trying to jump from my bootloader to an application for a while now but I can not figure out what is going wrong. I am hoping someone here might be able to help me.
I am using Texas Instrument's CC2652 and Texas Instrument's Code Composer Studio to develop and flash the bootloader. The code below is the code I use to jump to the application.
void startApp(uint32_t prgEntry) {
static uint32_t temp;
temp = prgEntry;
// Reset the stack pointer,
temp +=4;
asm(" LDR SP, [R0, #0x0] ");
((void (*)(void))(*((uint32_t*)temp)))();
}
When I run this code I will end up in the FaultISR. Here I can use the debugger to look at the registers. In the CFSR (Configurable Fault Status Register) I can see that the STKERR and the IBUSERR bits are set.
prgEntry Is 0x2E000 in this case. I defined this address as the start of the application in the linker command files of both the bootloader and the application as well. I copied the command files further below.
The application I am trying to jump to is first uploaded to the device in intel hex format and looks like this https://pastebin.com/DAerFkXr. Texas Instruments has a Flash Programmer application for Windows with which I can read a range of addresses from the internal flash of the device. I went through the intel hex file by hand and compared it to what I saw in the Flash Programmer application and I believe everything is put in the correct location. I posted a screenshot of the output of the Flash Programmer below the command files.
When I flash the application to the device using Code Composer Studio without my bootloader I can see that the application runs normally so I know it is not a problem with the application.
Application command file:
--stack_size=1024 /* C stack is also used for ISR stack */
--heap_size=256
/* Retain interrupt vector table variable */
--retain=g_pfnVectors
/* Override default entry point. */
--entry_point resetISR
/* Allow main() to take args */
--args 0x8
/* Suppress warnings and errors: */
/* - 10063: Warning about entry point not being _c_int00 */
/* - 16011, 16012: 8-byte alignment errors. Observed when linking in object */
/* files compiled using Keil (ARM compiler) */
--diag_suppress=10063,16011,16012
#define BOOT_BASE 0x0
#define BOOT_SIZE 0x8000
#define FLASH_BASE 0x2E000
#define FLASH_SIZE 0x2A000
#define RAM_BASE 0x20000000
#define RAM_SIZE 0x14000
#define GPRAM_BASE 0x11000000
#define GPRAM_SIZE 0x2000
/* System memory map */
MEMORY
{
/* Application stored in and executes from internal flash */
FLASH (RX) : origin = FLASH_BASE, length = FLASH_SIZE
/* Application uses internal RAM for data */
SRAM (RWX) : origin = RAM_BASE, length = RAM_SIZE
/* Application can use GPRAM region as RAM if cache is disabled in the CCFG
(DEFAULT_CCFG_SIZE_AND_DIS_FLAGS.SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM = 0) */
GPRAM (RWX): origin = GPRAM_BASE, length = GPRAM_SIZE
}
/* Section allocation in memory */
SECTIONS
{
.intvecs : > FLASH_BASE
.text : > FLASH
.TI.ramfunc : {} load=FLASH, run=SRAM, table(BINIT)
.const : > FLASH
.constdata : > FLASH
.rodata : > FLASH
.binit : > FLASH
.cinit : > FLASH
.pinit : > FLASH
.init_array : > FLASH
.emb_text : > FLASH
.ccfg : > FLASH (HIGH)
.vtable : > SRAM
.vtable_ram : > SRAM
vtable_ram : > SRAM
.data : > SRAM
.bss : > SRAM
.sysmem : > SRAM
.stack : > SRAM (HIGH)
.nonretenvar : > SRAM
.gpram : > GPRAM
}
Bootloader command file:
--stack_size=1024 /* C stack is also used for ISR stack */
--heap_size=256
/* Retain interrupt vector table variable */
--retain=g_pfnVectors
/* Override default entry point. */
--entry_point resetISR
/* Allow main() to take args */
--args 0x8
/* Suppress warnings and errors: */
/* - 10063: Warning about entry point not being _c_int00 */
/* - 16011, 16012: 8-byte alignment errors. Observed when linking in object */
/* files compiled using Keil (ARM compiler) */
--diag_suppress=10063,16011,16012
#define BOOT_BASE 0x0
#define BOOT_SIZE 0x8000
#define FLASH_BASE 0x2E000
#define FLASH_SIZE 0x2A000
#define RAM_BASE 0x20000000
#define RAM_SIZE 0x14000
#define GPRAM_BASE 0x11000000
#define GPRAM_SIZE 0x2000
/* System memory map */
MEMORY
{
/* The bootloader will be stored and executed from this location in internal flash */
BOOT (RX) : origin = BOOT_BASE, length = BOOT_SIZE
/* Application stored in and executes from internal flash */
FLASH (RX) : origin = FLASH_BASE, length = FLASH_SIZE
/* Application uses internal RAM for data */
SRAM (RWX) : origin = RAM_BASE, length = RAM_SIZE
/* Application can use GPRAM region as RAM if cache is disabled in the CCFG
(DEFAULT_CCFG_SIZE_AND_DIS_FLAGS.SET_CCFG_SIZE_AND_DIS_FLAGS_DIS_GPRAM = 0) */
GPRAM (RWX): origin = GPRAM_BASE, length = GPRAM_SIZE
}
/* Section allocation in memory */
SECTIONS
{
.intvecs : > BOOT_BASE
.text : > BOOT
.TI.ramfunc : {} load=BOOT, run=SRAM, table(BINIT)
.const : > BOOT
.constdata : > BOOT
.rodata : > BOOT
.binit : > BOOT
.cinit : > BOOT
.pinit : > BOOT
.init_array : > BOOT
.emb_text : > BOOT
.ccfg : > BOOT (HIGH)
.vtable : > SRAM
.vtable_ram : > SRAM
vtable_ram : > SRAM
.data : > SRAM
.bss : > SRAM
.sysmem : > SRAM
.stack : > SRAM (HIGH)
.nonretenvar : > SRAM
.gpram : > GPRAM
}
Screenshot from Flash Programmer:
Description of STKERR: Stacking from exception has caused one or more bus faults. The SP is still adjusted and the values in the context area on the stack might be incorrect. BFAR is not written.
Description of IBUSERR: Instruction bus error flag. This flag is set by a prefetch error. The fault stops on the instruction, so if the error occurs under a branch shadow, no fault occurs. BFAR is not written.
Edit:
This is the disassembly of the startApp function:
void startApp(uint32_t prgEntry) {
startApp():
push {r3, r14}
str r0, [r13]
temp = prgEntry;
ldr r1, [pc, #0x18]
ldr r0, [r13]
str r0, [r1]
temp +=4;
ldr r1, [pc, #0x14]
ldr r0, [r1]
adds r0, r0, #4
str r0, [r1]
asm(" LDR SP, [R0, #0x0] ");
ldr.w r13, [r0]
((void (*)(void))(*((uint32_t*)temp)))();
ldr r0, [pc, #8]
ldr r0, [r0]
ldr r0, [r0]
blx r0
}
startApp
and see what's going on, then see if the generated machine code matches the calling convention of your particular compiler. Generally, C code doesn't exist in a predictable state until the SP is initialized, nor does it like the co-exist in the same function with code manually setting the SP. \$\endgroup\$