Vector table relocation works only in debug mode
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-02-18 10:23 AM
Hi,
I'm facing a problem with relocation of the vector table to the internal SRAM. I work with the STM32F030CCT6 (using the Ac6 System Workbench and CubeMX, with the HAL libraries 1.9.0) and I want to design a simple bootloader.
This is a part of my linker script:
/* Specify the memory areas */
MEMORY{RAM (xrw) : ORIGIN = 0x200000C0, LENGTH = 32K-0xC0VTRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 0xC0FLASH (rx) : ORIGIN = 0x08000800, LENGTH = 256K-0x800}....RAMVectorTable(NOLOAD): {*(.RAMVectorTable)} >VTRAMThis is a vector table relocation in the main() of the bootloader:
__IO uint32_t VectorTable[48] __attribute__((section('.RAMVectorTable')));
/* USER CODE END 0 *//** * @brief The application entry point. * * @retval None */int main(void){ /* USER CODE BEGIN 1 */ uint32_t i = 0; for(i = 0; i < 48; i++) VectorTable[i] = *(__IO uint32_t*)((uint32_t)0x08000800 + (i<<2)); /* Enable the SYSCFG peripheral clock*/ __HAL_RCC_SYSCFG_CLK_ENABLE(); /* Remap SRAM at 0x00000000 */ __HAL_SYSCFG_REMAPMEMORY_SRAM();...Later on I send some test messages over the UART interface. I do not know why, but the above code works perfectly in the debug mode - I just need to run 'debug' and then 'resume' the program execution (with or without breakpoints later, does not matter).
Nevertheless, if I program the target (right click on the project -> 'Target' -> 'Program chip...', or just power-reset what I uploaded during the debug session), there is no response from the board. I am pretty sure that finally there is the same program on flash since I use the same .elf file both for the debugging session and regular programming... However, I've checked that if I do not relocate the vector table and I program the flash from the beginning (flash starts at 0x08000000), everything works just fine.
Just to clarify - I want to program the bootloader with some offset (0x0800) in memory because I need some space for the bootloader sensitive data (bootheader).
BR,
Marek
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-02-18 3:55 PM
Well absent a debug connection you're probably going to want to push telemetry out a serial port.
Things would want to dump out would be the FLASH based vector table, the one in SRAM, the address of the table as linked, and the SYSCFG registers, etc.
I might order things like this to avoid any potential clock enable hazards.
/* USER CODE BEGIN 1 */
/* Enable the SYSCFG peripheral clock*/ __HAL_RCC_SYSCFG_CLK_ENABLE(); uint32_t i = 0; for(i = 0; i < 48; i++) VectorTable[i] = *(__IO uint32_t*)((uint32_t)0x08000800 + (i<<2)); /* Remap SRAM at 0x00000000 */ __HAL_SYSCFG_REMAPMEMORY_SRAM();Also make sure BOOT0 is pulled low externally.
Don't transfer control from an IRQ Handler
Watch for name mangling issue with C++ syntax
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-02-19 1:31 PM
Hi, thank you for your attention! Unfortunately, none of this has helped: what I did:
- I checked whether the vector table is correctly copied to SRAM; furthermore, I disassembled the .elf and I checked that the vector table content from SRAM (after copying) contains proper addresses of the IRQ handlers,
- I checked the content of all flash regions,
- I checked the content of the SYSCFG register,
- BOOT0 pin is externally pulled low (through and without pull-down resistor, checked both options),
- In the debug mode I put a breakpoint in the very first instruction (assembler code, loading the end of stack address to the r0 register (ldr r0, _estack); this is the very first instruction below the Reset_Handler label marked in the linker script as the ENTRY point), then I just run the program without any more breakpoints in the debug mode and it worked like a charm...
- Moreover, I do not transfer control from an IRQ Handler; I tried to disable interrupts at all but it does not help neither
Any suggestions would be appreciated
BR,
Marek
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-02-19 2:27 PM
Disabling interrupt can be problematic if you never re-enable them again.
And the code runs without the debugger? ie if you set up a GPIO in the loader, and first code in application main() can toggle.
Without some output to look at and review it is probably not something I can debug through a keyhole.
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-02-20 12:15 AM
I think you got me wrong: all what I described here concerns only the bootloader. At this point I even do not think about passing the control to a main (loaded) application after the loader stage (in fact it does not exist at the moment ). The problems listed above are ALL in the loader. I need to do all of this remapping stuff etc. in the bootloader as well since I must store some sensitive data at the first flash page; the bootloader will be stored in the second page.
To sum up: we might think about this software as a regular firmware, which has just to be stored in a different flash area (i.e. not in the beginning).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-02-20 4:47 AM
The processor isn't going to magically start from an image based at 0x08000800
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-02-20 12:08 PM
Turvey.Clive.002
thank you for you tips and suggestions. I do not know why I hardcoded in my mind that setting the ENTRY point in the linker script is equivalent to saying to the uC (in this particular case): Hey, start from that point! In this case I will have to move the bootheader to another flash page and locate the bootloader at the address 0x0800 0000.Nevertheless, I'm still curious how it was possible to execute that code in the debug mode?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2018-02-20 12:19 PM
The debugger starts and breakpoints/halts the processor, it then applies the address you want execution to occur. The entry point visible in the .ELF is likely Reset_Handler, so it uses that and off you go.
The processor on the other hand when reset pulls the SP/PC pair from address zero (with FLASH, ROM, RAM mapped there depending on BOOTx pin settings). In the normative case BOOT0=Low, FLASH from 0x08000000 shadows at 0x00000000, and then it vectors off to the FLASH in it's usual address.
Up vote any posts that you find helpful, it shows what's working..
