STM32G4 Position Independent Code with custom startup file - fail to start first task

I’m trying to achieve a dual-boot system where the two position-independent STM Applications are compiled with the following flags:

*-fPIC   -mpic-register=r9   -msingle-pic-base   -mno-pic-data-is-text-relative*

In the app linker file, the memory is organized as follow:

/* Entry Point *
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */

_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Memories definition */
MEMORY
{
  RAM        (xrw)    : ORIGIN = 0x20000000,    LENGTH = 128K
  FLASH       (rx)    : ORIGIN = 0x08000000,    LENGTH = 512K
}

while the .isr_vector and .got sections are declared as:

  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  }>RAM AT> FLASH

.got :
  {
    . = ALIGN(4);
    *(.got)
    *(.got.plt)
    . = ALIGN(4);
  } >RAM AT> FLASH

After the jump to the app, the customized startup file allows the correct execution of main.c file until the start of the first task. My program gets stacked at vPortSVCHandler in the path GCC/ARM_CM4F/port.c [FreeRTOS Kernel V10.3.1, using heap_4].
I tried the solution provided in the topic

[Imx rt1024 position independent code - fail to start first task]#

to keep invariate the R9 register, but it didn’t work.
EDIT for specification: the above solution works when running the application alone from the beginning of flash, but fails when it is integrated with bootloader code.

I wonder if you need to set SCB->VTOR. Can you try setting it manually at the beginning of main()?

SCB->VTOR is correctly set. I repeat the assignment both in system_stm32g4xx.c file and main.c, without difference in behavior.

How are you routing control to your interrupt handlers? Does VTOR point to the bootloader’s vectors? Or does VTOR point to a RAM table? Or something else perhaps?

SCB->VTOR points to the RAM VECTOR TABLE at 0x20000000, where is located the isr_vector section of application

Do you intend your RAM vectors to point directly to handlers in the application image, regardless of where you load that image into flash? If so, can you post the code that populates the RAM vector table?

How do the contents of the RAM vector table compare in these two scenarios?

If so, can you post the code that populates the RAM vector table?

Yes, the startup code is taken from a public study:

I’m trying to overcome the limitations of recent disclaimer, to be good for FreeRTOS.

How do the contents of the RAM vector table compare in these two scenarios?

Unfortunately, STM provides debugging feature only with hardcoded offset, so I’m able to use debbuger only in 1st scenario and in a slightly different version of 2nd scenario:

EX: APP OFFSET = 0x44000
/* Memories definition */
MEMORY
{
  RAM        (xrw)    : ORIGIN = 0x20000000,    LENGTH = 128K
  FLASH       (rx)    : ORIGIN = 0x080**44000**,    LENGTH = 220K
} 
//THEN I REMOVE (as follow) the reference OFFSET everywhere 
//TO APPLY again the OFFSET via the start-up code (as in the above study)
.isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  }>RAM AT> FLASH
  __flash_vector_table_begin = (LOADADDR(.isr_vector)-0x00044000) ;
  __flash_vector_table_end = __flash_vector_table_begin + SIZEOF(.isr_vector) ;
  __ram_vector_table_begin = ADDR(.isr_vector) ;
  __ram_vector_table_end = __ram_vector_table_begin + SIZEOF(.isr_vector) ;

.got :
  {
    . = ALIGN(4);
    *(.got)
    *(.got.plt)
    . = ALIGN(4);
  } >RAM AT> FLASH
  __flash_global_offset_table_begin = (LOADADDR(.got)-0x00044000) ;
  __flash_global_offset_table_end = __flash_global_offset_table_begin + SIZEOF(.got) ;
  __ram_global_offset_table_begin = ADDR(.got) ;
  __ram_global_offset_table_end = __ram_global_offset_table_begin + SIZEOF(.got) ;

SUMMARY:
APP alone starting from 0x08000000: works and can be debugged
BTL+APP with this slightly difference and hardcoded offset in linker script, starting from 0x08044000: works and can be debugged
BTL+APP without hardcoded offset and put at 0x08044000: works in main.c, but fails at first task of Freertos and can’t be debugged (I used leds to look at variables’ and registers’ contents, but I couldn’t find the difference with previous scenario).

I’m sure I’m missing something about -fPIC and Freertos, which is a relatively new field for me

One essential fact that the article you linked to ignores is that the rest of interrupt vector is going to be processed by the hardware. Thus, code using that technique just can’t use interrupts at all.

Since FreeRTOS DOES use interrupt, that technique just becomes a non-starter,

In your case, you want the RAM vectors to point at functions in the application image regardless of any offset used when loading the application image into flash. I would suggest you create a small blinky application that uses interrupts but doesn’t use FreeRTOS. Once you get that working with a load offset, then come back and try to add FreeRTOS. I suspect your issue is the content of your RAM vector table.

I don’t think this is really a FreeRTOS issue.

I’m going to reach out to my teammate @aggarg and see if he has any experience with this. He has much more experience porting FreeRTOS than I do. I’ll try to get you a response tomorrow.

In the meantime I think @jefftenney has provided solid advice and would be a great launch point.

I think @jefftenney’s suggestion is correct. @MarkIO10, can you check if you are able to run a bare metal application?

After an other week, I finally make it work! The issues stand in the .data section and static library patch of startup file, where there are some pointers (I think related to FreeRTOS) which point towards memory slot (that is equivalent to not-offseted binary image of application). So I adjust these values as with .got and .isr_vector section. Thanks to everyone for the suggestions @jefftenney @kstribrn @richard-damon @aggarg. I hope to not need further help to integrate the left (and more complex) part of my FW

Thank you for reporting back!