Force the linker to put the same code in 2 sections
Asked Answered
O

2

6

I am trying to force the linker (ld from XC32) to place the same executable code in two different sections of flash.

The application is so that the code can be run as a standalone application, and also so that the reset vector can be overridden by a bootloader which can then branch to a pseudo reset vector.

The relevant sections of my linker script are

MEMORY
{
  kseg1_boot_mem     : ORIGIN = 0xBFC00000, LENGTH = 0x480
  bootload_boot_mem  : ORIGIN = 0x9D1F0000, LENGTH = 0x480
}

SECTIONS
{
  .reset 0xBFC00000 :
  {
    KEEP(*(.reset))
  } > kseg1_boot_mem

  .bootloadreset 0x9D1F0000 :
  {
    KEEP(*(.reset))
  } > bootload_boot_mem
}

Using this the area at 0xBFC00000 is populated as expected, but nothing gets placed at 0x9D1F0000. I have tried passing the option --no-gc-sections to the linker but it doesn't seem to make any difference.

My question is: Is it possible to force the linker to put the same code into 2 different sections, and how to do so?

Or answered 26/11, 2015 at 11:46 Comment(1)
I'd solve this problem in the build system, by compiling the same code twice with appropriate variations. It's slightly inefficient, but it relies only upon well-understood behavior in the linker.Plumb
O
1

Whether or not it was the right way to solve this problem, the solution I came up with was:

Move the start up code to the area at 0x9D1F0000, by removing the KEEP(*(.reset)) block from the .reset section. Place an asm function at the reset address which jumps to the relocated start up code. Allow the bootloader to overwrite the asm function as it will then branch to the start up code when it's finished its work.

Or answered 15/12, 2015 at 12:20 Comment(0)
B
1

I solved it by adding new memory region

MEMORY
{
  virtual_boot               : ORIGIN = 0xBFC00000, LENGTH = 0x200
  .
  .
  .
} 

then in section I added

SECTIONS
{
  .virtualboot :
  {
    /*KEEP(*(.virtualboot))*/
    LONG(0x08000000 | ((_RESET_ADDR & 0x1FFFFFFF) >> 2));
    LONG(0x00);
  } > virtual_boot
  .
  .
  .
}

_RESET_ADDR should be defined earlier, in my code it was

_RESET_ADDR = (0x9D006000 + 0x1000);

by this my code become able to run on the MCU with/without bootloader

Braasch answered 16/8, 2017 at 15:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.