I use GCC 4.9 (arm-none-eabi) with STM32 and want to place an interrupt table into an array in order to change interrup handler adresses when it's needed in my code.
I read existing manuals and articles and did the following:
I have to align the array, so I changed the linker script to add custom section in RAM and place it to 0x20001000 in order to automatically align it
.vectorsSection 0x20001000 :
{
KEEP(*(.vectorsSection))
} >RAM
Declare array to place IVT into, I declared it as extern in the header, and in .cc:
volatile word __attribute__((section (".vectorsSection"))) _vectors_[64] = {0};
Check that array is at the correct address:
arm-none-eabi-nm program.elf | grep _vectors_
20001000 d _ZL9_vectors_
Now it comes to reallocate the table to RAM. I wrote this function
void (*new_code_entry)(void);
.......
static void remap_vector_table (void)
{
//VTOR is 0 on startup, so we change VTOR only once
if(SCB->VTOR)
return;
new_code_entry = (void (*)(void))((word)&_vectors_ + sizeof(word) + 1);//Skip SP and jump to Reset
memcpy((void*)_vectors_, (void*)SCB->VTOR, sizeof _vectors_);
SCB->VTOR = 0x1FFFFF80ul & (word)(&_vectors_); //Set VTOR offset
__DSB(); //Complete all memory requests
new_code_entry(); //Jump to new code
}
I created enum from startup code in order to easy access the array.
After the final jump the code start from beginning and VTOR is 4096.
Array contain correct addresses in the same order as in the startup code.
But when it comes to
__enable_irq();
__ISB();
It hangs on the first exception, to be more specific this is the callstack
5 <symbol is not available> 0x697b617a
4 <signal handler called>() 0xfffffff9
3 <symbol is not available> 0x200011f8
2 remap_vector_table() main.cc:31 0x08000cd4
1 main() main.cc:46 0x08000d32
200011f4: tickcounter+0 movs r0, r0
200011f6: tickcounter+2 movs r0, r0
200011f8: ; <UNDEFINED> instruction: 0xf0d3e321
tickcounter is from SysTick_Handler that is surelly was called first. May be I should do something with stack pointer? I have no clue what is wrong here.
The root cause is quite simple:
According to manual bit 29 is shows the base offset: RAM or FLASH.
SCB->VTOR |= 1 << SCB_VTOR_TBLBASE_Pos;
This fixed the issue