2023-02-23 03:40 PM
I am using the STM32F746VET6 which was setup with STM32CubeMX project. In the code it creates I see there's a STM32F746VETX_RAM.ld linker file and a #define VECT_TAB_SRAM to locate the IVT in RAM, but I don't see in MX where I specify that I want the autogenerated code to behave that way. Am I just missing something?
The reason I want the IVT in RAM is that I want to reconfigure which ISR is used for a timer depending upon a setting set through the SPI port. Doing this by overwriting an IVT in Flash would be a problem for my bootloader which has a CRC over the entire Flash range.
2023-02-23 05:46 PM
AFAIK CubeMX does not have option to place the vectors in RAM. Add the code (and link script stuff) for this manually.
2023-02-24 04:50 AM
Thanks for this. I guess I'll stop looking and hopefully my changes don't get overwritten if I ever generate code from the MX project again.
2023-02-24 06:58 AM
Expect that you need some unused space in RAM, with suitable alignment, and then memcpy() the table into that RAM and change SCB->VTOR to point at it.
SystemInit() might be the place to do it, but it doesn't have to be.
You can dispense with the ST #define methodology too.
2023-02-24 07:30 AM
Thanks. I added the memcpy but my code still doesn't run. I'll dispense with the ST #define methodology and handle that part manually too.
2023-02-24 09:10 AM
What doesn't run? Your interrupts? All the interrupts?
The table will need to be on a 512-byte boundary, perhaps use 0x20000000, and then move up and shrink the space defined for that RAM in the Linker Script.
RAM based vector tables definitely work, but don't expect the data to magically appear there at startup. You should keep the regular table, copy it to the new location, and then you can modify the function pointers within the array.
Instrument your Hard Fault Handler so you can identify if anything goes sideways..
2023-02-24 10:28 AM
Well, at the moment the code builds but when I try to debug I get the message "(Read)Failed determine breakpoint type" and "Break at address "0x137cf8de" with no debug information available, or outside of program code."
I did reserve "IVT_RAM (xrw) : ORIGIN = 0x20000200, LENGTH = 512" in the linker file and the map file shows the correct location. The first thing I do in main() is this:
extern const unsigned char ivt_text_start;
extern const unsigned char ivt_text_end;
extern const unsigned char ivt_data;
memcpy((void *)&ivt_text_start, (const void *)&ivt_data, (int) (&ivt_text_end - &ivt_text_start));
I'm obviously still doing something wrong, but I am still relying on the autogenerated startup_stm32f746vetx.s and system_stm32f7xx.c with USER_VECT_TAB_ADDRESS and VECT_TAB_SRAM defined and VECT_TAB_OFFSET defined as 0x00000200U.
2023-02-24 10:49 AM
It shouldn't be this hard..
Build as you would for a normal FLASH firmware
in main()
extern uint32_t *g_pfnVectors; // Original FLASH/ROM table
memcpy(0x20040000, (void *)&g_pfnVectors, 0x200); // Some arbitrary slack space for experiment
SCB->VTOR = 0x20040000;
2023-02-24 11:23 AM
That does allow me to run (after reverting system_stm32f7xx.c so that USER_VECT_TAB_ADDRESS and VECT_TAB_SRAM are not defined), but using the original FLASH linker file what's telling the linker not to place other variables at addresses 0x20040000 - 0x20040200?
2023-02-24 11:26 AM
What a bad looking code, shame on you! ;)
How about this:
// STM32F0 bootloader fragments
struct vectable_ {
uint32_t Init_SP;
void (*Reset_Handler)(void);
void (*CoreExcHandler[14])(void);
void (*IRQHandler[32])(void);
};
// these defs could be replaced by declarations with section attributes
#define RAM_VTBASE 0x20004000
#define ram_vectable (*(struct vectable_ *)RAM_VTBASE)
#define ROM_VTBASE 0x08004000
#define rom_vectable (*(struct vectable_ *)ROM_VTBASE)
int main(void)
{
...
ram_vectable = rom_vectable;
SCB->VTOR = (uint32_t)&ram_vectable;
__set_MSP(ram_vectable.Init_SP);
ram_vectable.Reset_Handler();
}