Two firmware slots application, FreeRTOS jumps to the first slot while executing first task

vipperdev wrote on Monday, May 28, 2018:

Hey guys
I’ve created an application with two firmware slots. Bootloader works fine, it properly starts firmware from particular slot based on sequencer number saved on FLASH.
By default, firmware is compiled for the first slot, which starts from address 0x08008000 in memory. Second slot is mapped to address 0x08104000.
When my device starts firmware from the second slot, FreeRTOS in booting time starts its first task from address located in the first slot and then entire application jumps to the first slot. I thought addresses in binaries after compilation are relative, but in that case it’s somehow hardcoded with an absolute value.
Running firmware from the first slot has nothing problems.

What should I change? Some FreeRTOS params in config? I don’t think so…

hs2sf wrote on Monday, May 28, 2018:

Assuming you’re using e.g. ARM-CM3 you maybe missed to adjust SCB->VTOR (vector table start address) accordingly i.e. pointing to the exception table linked into the actual app binary.
Starting the app binary from bootloader needs to be done right and is not related to FreeRTOS.
In short I’m using this sequence in my bootloader:

  • disable all IRQs
  • get app(1 or 2) image vector table pVec starting at app image base address
  • set main stack pointer and activate (privileged) thread mode using main stack
    __set_MSP( (uint32_t)pVec->pvStack );
    __set_CONTROL( 0 );
  • invoke pVec->pfnReset_Handler function of the app image to start the app
  • in (app image) Reset_Handler() after optional relocation of init data and clearing BSS adjust VTOR with the (new) app image exception table
    SCB->VTOR = (uint32_t)&exception_table;
    • branch to app main() after CRT init __libc_init_array();

Good luck, HS2

vipperdev wrote on Wednesday, May 30, 2018:

Hey, thanks for your reply. In this project ARM-CM4 is used.

So my flow during switching from bootloader to main application is as follows:

  1. Check which firmware slot should be used.
  2. Disable IRQs.
  3. Copy vector table to RAM. That part of RAM is the same for both slots. During copying process I’m changing offset for each address, so they will be compatible with particular firmware slot. By default addresses don’t have offset, it’s removed in post-compiling stage.
  4. Set stack pointer, according to the first word in vector table in RAM. That addresses is not changed while copying vector table to RAM.
  5. Set SCB->VTOR.
  6. Execute Data Sync Barrier DSB().
  7. Jump to the Reset Handler from vector table copied to RAM.

Vector table is copied with correct offset for each firmware slot.
When RTOS starts its first task in prvPortStartFirstTask, and then jumps to vPortSVCHandler it switches to the task in the first slot. It fail while returning from vPortSVCHandler called by that first dummy task.

hs2sf wrote on Wednesday, May 30, 2018:

I’m a bit confused why you leave the main stack address untouched but need to patch the handlers.
Following the rather simple ‘.relocate’ segment mechanism provided by (I think) Atmel Studio or maybe ARM example code you could avoid fixing up the exception table yourself and let the linker and the app startup routine do its work. However, if you’re sure linking and loading the app correctly (incl. relocating parts of it to RAM properly), I afraid the debugger will be your friend…

vipperdev wrote on Thursday, May 31, 2018:

  1. What do you mean by leaving MSP untouched?
  2. I’ll check /relocate segment, I think it’s provided by Atmel.

hs2sf wrote on Thursday, May 31, 2018:

Regarding MSP maybe I got you wrong if you store the corresponding entry of the new app exception_table into it. Sorry !

vipperdev wrote on Friday, June 01, 2018:

When I compile application with changed FLASH memory address range to the secondary slot, it works properly. Is it possible compile code such that application will be PC independent, at least it will work in that case?

I think my problem is similar to that one:

richard_damon wrote on Friday, June 01, 2018:

Fundammentally, programs generally need to run from the address they were compiled to run at, as there are some absolute address values in the code. One solution is to design the code to always copy itself into ram (at a fixed address) and run there, then just the ‘bootloader’ that does the copy needs to understand the changing address.
On some processors, with some compilers, there is a flag to compile the code a ‘Position Independent’, and when this is done right, the program can be stored at any address and it will run there, GCC for ARM has a pic (Position Independant Code) option that I beleive can do this, but that question does bring up one of the issues that it sounds like you only want to relocate the ‘flash’ memory but keep ram references absolute.

vipperdev wrote on Friday, June 01, 2018:

Richard, you’re right! It’s a MCU project so there is no enoughr RAM to copy entire code there. I’m trying to use -fPIC flag, so far without successful result but still working on it.
You’re also right about RAM address is absolute, only FLASH memory range changes here.

richard_damon wrote on Friday, June 01, 2018:

I beleive the topic you reference dealt with one issue with PIC, that by default is also relocates the ram references (It was originally developed to allow the code of a shared library be loaded at any address, and in this case you wanted to move the data section too. I haven’t studied the issue enough to know if that was solved or not. (I suppose if you can make you program have NO global variables that get relocated in that manner you could make it work).

This really isn’t a FreeRTOS issue, as non of this deals with FreeRTOS itself, but is a tools issue of geting GCC to generate the right sort of code.

hs2sf wrote on Saturday, June 02, 2018:

As Richard mentioned PIC is for shared libs and requires dynamic linking, I think. I wouldn’t go this way. It’s way more complicated than it seems at the first place.
If I got you right you want to implement a safe update of the application binary by keeping the previous image in place and and activate the new image once successfully installed.
Since you can’t run the complete app from RAM (after relocation) you’ve to run (parts) of the code from flash. This code can’t be relocated anyway.
So I’d prepare an update package containing 2 app binaries properly linked to their (flash) slots and deal with updating the ‘next free’ slot by the update protocol. The currently running app knows it’s slot and also the bootloader. So regardless which program actually does the update both are able to select the ‘next free’ slot and tell it to the update tool, which in turn sends the selected app binary 1 or 2 to the device.
I’m just guessing that you want to update a device via an external interface using an update tool.