Hi,
Sorry if this isn't the proper forum section to ask for advice...
I'm working on a small learning project but reached a point where I'd like to be able to trace what exception/interrupts are triggered. I obviously can't simply overwrite entries in the _VectorsRam array as library code may overwrite to it at anytime.
My idea was then to switch to another vector table, and make all the entries point to a function that reads the current interrupt number (from ICSR's VECTACTIVE field), writes somewhere that an exception occured, and called the correct entry from the _VectorsRam array.
_VectorsRam is stored in SRAM at address 0x20004c00, 1024-bytes aligned while my secondary table (I called it VRAMHooks) is at 0x20003400, also 1024-bytes aligned.
However when I write VRAMHooks address into SCB_VTOR, the teensy hangs and doesn't respond over serial to programming commands.
VRAMHooks is filled with pointers to this function.
Anyway I couldn't figure out what was causing the crash, and even memcpy'ing _VectorsRam into VRAMHooks still caused the teensy to hang. I then took the ResetHandler function, and copy pasted it into my program, set the original ResetHandler to a weak symbol to override it, and the teensy still booted correctly.
I then modified that ResetHandler to fill VRAMHooks and set it to SCB_VTOR, instead of _VectorsRam and that's when things got weird.
Basically, I don't understand how to initialize th VRAMHooks array:
I left SCB_VTOR initialized to _VectorsRam, meaning that from this point on, I'm only writing into VRAMHooks.
I can't add a line in this loop that initializes _VectorsRam, or else the teensy doesn't hang, but the led starts blinking, which I guess is from the hardfault handler. My guess is that this optimize("no-tree-loop-distribute-patterns") attribute is related to this?
However, if I move the initialization to a separate loop right after:
This doesn't hardfault. Except if I'm assigning debug_exception. unused_interrupt_vector works.
Why? How?
Anyway, since it stopped crashing to the hardfault handler, I tried writing VRAMHooks to SCB_VTOR but obviously no luck, and reverted back to _VectorsRam, since the rest of the initialization requires systick to be properly working, which it can't if I can't initialize VRAMHooks with pointers to debug_exception (and assuming it does what I think it does).
I did a bit of further investigating, and it does this even if I move that loop right before the call to main, but it works from main. So I deduced that the issue is because ResetHandler is in the .startup section and main is in .text.itcm, but this raises more questions than it answers:
- _VectorsRam and VRAMHooks are in the same memory region, why can't ResetHandler write arbitrary values to VRAMHooks if it's only being written to, never read, while code after main can? debug_exception and unused_interrupt_vector are in the same memory region, what makes them different? I even copy pasted unused_interrupt_vector's code and attributes into debug_exception, but it didn't do anything.
- What makes code executing in flash different from code in ITCM?
Thanks, please don't hesitate to point out any error I made.
Sorry if this isn't the proper forum section to ask for advice...
I'm working on a small learning project but reached a point where I'd like to be able to trace what exception/interrupts are triggered. I obviously can't simply overwrite entries in the _VectorsRam array as library code may overwrite to it at anytime.
My idea was then to switch to another vector table, and make all the entries point to a function that reads the current interrupt number (from ICSR's VECTACTIVE field), writes somewhere that an exception occured, and called the correct entry from the _VectorsRam array.
_VectorsRam is stored in SRAM at address 0x20004c00, 1024-bytes aligned while my secondary table (I called it VRAMHooks) is at 0x20003400, also 1024-bytes aligned.
However when I write VRAMHooks address into SCB_VTOR, the teensy hangs and doesn't respond over serial to programming commands.
Code:
void debug_exception(void) {
int excn = int_csr->vectactive;
Serial.printf("exc: %d\n", excn);
activated[excn] = 1;
_VectorsRam[excn]();
}
VRAMHooks is filled with pointers to this function.
Anyway I couldn't figure out what was causing the crash, and even memcpy'ing _VectorsRam into VRAMHooks still caused the teensy to hang. I then took the ResetHandler function, and copy pasted it into my program, set the original ResetHandler to a weak symbol to override it, and the teensy still booted correctly.
I then modified that ResetHandler to fill VRAMHooks and set it to SCB_VTOR, instead of _VectorsRam and that's when things got weird.
Basically, I don't understand how to initialize th VRAMHooks array:
Code:
for (i=0; i < NVIC_NUM_INTERRUPTS + 16; i++) {
_VectorsRam[i] = &unused_interrupt_vector;
// VRAMHooks[i] = [anything, function pointer or constant value];
}
I left SCB_VTOR initialized to _VectorsRam, meaning that from this point on, I'm only writing into VRAMHooks.
I can't add a line in this loop that initializes _VectorsRam, or else the teensy doesn't hang, but the led starts blinking, which I guess is from the hardfault handler. My guess is that this optimize("no-tree-loop-distribute-patterns") attribute is related to this?
However, if I move the initialization to a separate loop right after:
Code:
for (i=0; i < NVIC_NUM_INTERRUPTS + 16; i++) {
_VectorsRam[i] = &unused_interrupt_vector;
}
for (i=0; i < NVIC_NUM_INTERRUPTS + 16; i++) {
VRAMHooks[i] = [anything except a pointer to debug_exception];
}
This doesn't hardfault. Except if I'm assigning debug_exception. unused_interrupt_vector works.
Why? How?
Anyway, since it stopped crashing to the hardfault handler, I tried writing VRAMHooks to SCB_VTOR but obviously no luck, and reverted back to _VectorsRam, since the rest of the initialization requires systick to be properly working, which it can't if I can't initialize VRAMHooks with pointers to debug_exception (and assuming it does what I think it does).
I did a bit of further investigating, and it does this even if I move that loop right before the call to main, but it works from main. So I deduced that the issue is because ResetHandler is in the .startup section and main is in .text.itcm, but this raises more questions than it answers:
- _VectorsRam and VRAMHooks are in the same memory region, why can't ResetHandler write arbitrary values to VRAMHooks if it's only being written to, never read, while code after main can? debug_exception and unused_interrupt_vector are in the same memory region, what makes them different? I even copy pasted unused_interrupt_vector's code and attributes into debug_exception, but it didn't do anything.
- What makes code executing in flash different from code in ITCM?
Thanks, please don't hesitate to point out any error I made.