cancel
Showing results for 
Search instead for 
Did you mean: 

Vector table relocation works only in debug mode

Marek Frydrysiak_2
Associate II
Posted on February 18, 2018 at 19:23

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-0xC0

VTRAM (xrw)    : ORIGIN = 0x20000000, LENGTH = 0xC0

FLASH (rx)     : ORIGIN = 0x08000800, LENGTH = 256K-0x800

}

....RAMVectorTable(NOLOAD): {*(.RAMVectorTable)} >VTRAM

This 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

7 REPLIES 7
Posted on February 19, 2018 at 00:55

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

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on February 19, 2018 at 21:31

Hi, thank you for your attention! Unfortunately, none of this has helped: what I did:

  1. 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,
  2. I checked the content of all flash regions,
  3. I checked the content of the SYSCFG register,
  4. BOOT0 pin is externally pulled low (through and without pull-down resistor, checked both options),
  5. 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...
  6. 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

Posted on February 19, 2018 at 22:27

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.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on February 20, 2018 at 08:15

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).

Posted on February 20, 2018 at 12:47

The processor isn't going to magically start from an image based at 0x08000800

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on February 20, 2018 at 20:08

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?

Posted on February 20, 2018 at 20:19

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.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..