To begin with, I should tell you that my code is linked to be run from the embedded SRAM in the STM32. This is because I think it is prettier to not have to erase and reprogram the flash all the time. On the other hand, the Cortex-M3 always has it's exception vectors placed at 0x0 out of reset, and that is within the flash area. That means that following a reset, the CPU will always start executing from the reset vector at 0x4. It is possible to relocate the exception vectors to 0x20000000 (SRAM) by modifying the vector table offset register once you're running and thereby pointing out your own vectors placed in SRAM.
To be able to practically run my code from SRAM I implemented a minimal bootstrap routine that I put into the flash area:
static void reset();
unsigned int *vectors[2] __attribute__ ((section(".vectors"))) = {
(unsigned int *) 0, /* No stack used. */
(unsigned int *) reset
};
__attribute__ ((naked)) static void reset()
{
/* We enter here, running as privileged in thread mode. TRM 2.2.
We use SP_main. TRM 2.2.1 and 5.4.
NVIC interrupts disabled. NMI and Hard Fault disabled. TRM 5.9. */
/* Remap vectors to 0x20000000.
Read stack top and entry point from
user's RAM-based vectors. Jump to
entry point. */
asm("mov r0, #0x20000000\n\t"
"ldr r1, =0xE000ED08\n\t"
"str r0, [r1]\n\t"
"ldr sp, [r0]\n\t"
"ldr pc, [r0, #4]");
}
TRM refers to the Cortex-M3 Technical Reference Manual. The reset routine reads the initial stack pointer and SRAM-based boot routine address from the user's exception vector at 0x20000000. It set the vector table offset register and jumps to the user's reset routine. This way, it appears like the board boots from SRAM.So first, load your code including your exception vectors to SRAM, then issue a system reset to the board.
The problem I ran into yesterday was when performing an svc (system call). The CPU properly jumped to my exception handler:
.global CM3_handler_svc
.extern portable_syscall
CM3_handler_svc:
bl portable_syscall
bx lr
Problem was that when executing the first instruction (the bl), an exception occured. I noticed that the T-bit in the xPSR register was cleared when taking the svc exception. Executing instructions in the Cortex-M3 with the T-bit (thumb mode) cleared is not allowed. The fix was to add the pseudo-op .thumb_func before the exception handler code. That way, the exception table entry corresponding to svc sets the LSB of the jump address and the T-bit gets set when running the svc handler. Haven't tested this yet, but it should work.
No comments:
Post a Comment