The code to initialize vector table is placed in startup code of STM32cubeIDE:
.global g_pfnVectors
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.
.
.
.word DMA1_Stream0_IRQHandler /* DMA1 Stream 0 */
.
.
.
I want to understand it, Then I have some questsion if anyone could help:
g_pfnVectors have declared two time one with .global other with .word. It first declared as global then declared it's size in hardware?
line 2,3,4 have all something comma separated, what are they?
Is there any reference to understand them?
Note: I know line 6 is array defenition of g_pfnVectord.
It seem the startup have to holds the IRQhandlers function pointer, since we have defined them on *_it.c ,these will link to them, am I right?
In arm interupt vector relocation usage and description they've reassigne SysTick_Handler after table reallocation. If we use linker to move this function to RAM then we don't need this re allocate this function, am I right? (Since this function executes every 1mS by default on cubeIDE apps and have be fast)
Can't exactly cover the assembly syntax well, but I think some explanation of vector table and interrupt entry would be helpful. In fact, it's very easy to have zero assembly code in startup, you can totally make a vector table in C as an array that you place in its own section. Also, I'm not super verse in assembly myself. Anyway, regarding the vector table, what it is, how it works and what you can do with it.
In the beginning of Flash, before any executable code, you have a vector table. It's just a list of pointers to void (void) functions. (The first word of the vector table is loaded into main stack pointer on power on, the others are pointers). Since Flash is not intended to be dynamically changed at runtime, we can safely assume that in practice those pointers are fixed.
When interrupt occurs, the CPU reads the corresponding interrupt handler address from the vector table and then jumps to whatever address it read. Thus, if you move vector table, you also need to make sure that all interrupts have handler addresses in the correct places in new vector table. Basically, you want to copy the old vector table into the new place.
Small addition: in Cortex M, vector table entries' least significant bit is always set to 1 (like all function pointers). Architecture requirement (indicates Thumb instruction set and not 32-bit ARM instruction set). Otherwise usage fault exception. (so for interrupt handler at 0x20040000, the vector table entry is 0x20040001).
Let's consider a basic example.
Your vector table is in Flash and it's fixed (unchangeable). Imagine you have interrupt number 20. Imagine you have void IRQ20_Handler (void) handler for that interrupt, located also in Flash, where your executable code typically resides. Let's imagine the address of the handler is 0x08004000 (any address in Flash that's not overlapping with vector table, just an example).
In your Flash, 32-bit word number 36 of the memory is going to contain 0x08004001. 36 because MSP+Exceptions (hardfault, memmanage fault, busfault, systick, etc) take the first 16 words, and IRQs start only after that. Vector table is in the STM MCU's reference manual.
So right now, your vector table is at location 0x08000000 (beginning of Flash), and word 36 of it has a pointer to IRQ20_Handler, which is also somewhere in Flash. So if IRQ20 interrupt happens, your MCU reads word number 36 from Flash - 0x08004001 - and jumps to 0x08004000 to the handler.
Imagine you want to have a function in SRAM as an interrupt handler located at 0x20040000. You will have to overwrite Flash so that vector table word number 36 has new handler's address - it's not recommended to rewrite flash just for 1 thing - so instead you move vector table to RAM, and then you can dynamically change vectors as much as you want at runtime.
Thus, you first move IRQ handler to RAM (say, 0x20040000), then you move vector table to RAM and make sure that all handler addresses are copied over to there so that all interrupts work just like before, then in the new vector table you overwrite the IRQ20_Handler (word 36 of vector table) with the address of the SRAM function (+1). In this case, with 0x20040001.
Unfortunately, can't provide more details about assembly, since I use it only a bit and mainly as inline assembly blocks for context switching or special instructions not natively supported through C. It looks like it declares a section (and makes it globally visible) and gives it a pair of attributes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With