Trying to create two sections (linker) which can be read from the application/bootloader

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello everyone,

 

I am trying to create two sections in the flash of my AT90CAN128, which can be read from the application as well as from the bootloader. The idea behind it is, that if the bootloader detects an application in the flash, the version number etc. can be send to the CAN master. And in case there is an older application in the flash you can update the application.

 

The issue is that if I debug I can not see any data in the two sections. When I added the variables to the watch list the pointer points to the RAM and not to the flash. However, when I check the .map file the two sections seems to be created.

 

The application and bootloader are two complete independet projects, they only share the same CAN lib.

#pragma GCC push_options

#pragma GCC optimize ("O0")

#if (ACTIVE_BUILD==BUILD_BOOTLOADER) && defined(main_C)
  FIRMWARE_INFO_t __attribute__((section(".infobtl"))) InfoBootloader =
  {
    ...
      FINF_SW_VERSION_BTL, // this is a define
    ...
  };
#else
  extern FIRMWARE_INFO_t __attribute__((section(".infobtl"))) InfoBootloader;
#endif


#if (ACTIVE_BUILD==BUILD_ENCODER_BOARD) &&  defined(main_C)
  FIRMWARE_INFO_t __attribute__((section(".infoapp"))) InfoApplication =
  {
    ...
      FINF_SW_VERSION_APP, // this is a define
    ..
  };
#else
  extern FIRMWARE_INFO_t __attribute__((section(".infoapp"))) InfoApplication;
#endif

#pragma GCC pop_options

To achieve the two seperated sections, I created my own linker scripts (one for the application and one for the bootloader). These are inlcuded via AtmelStudio7->Project Properties->AVR/GNU linker->Miscellaneous->Other Linker Flags: with -T ..linker_script.x .

 

Application linker script:

MEMORY
{
  text   (rx)   : ORIGIN = 0, LENGTH = 0x1DDF8
  app    (rx)	: ORIGIN = 0x1DDF8, LENGTH = 0x200
  btl	 (rx)	: ORIGIN = 0x1FE00, LENGTH = 0x200
  data   (rw!x) : ORIGIN = 0x800100, LENGTH = __DATA_REGION_LENGTH__
  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = __EEPROM_REGION_LENGTH__
  fuse      (rw!x) : ORIGIN = 0x820000, LENGTH = __FUSE_REGION_LENGTH__
  lock      (rw!x) : ORIGIN = 0x830000, LENGTH = __LOCK_REGION_LENGTH__
  signature (rw!x) : ORIGIN = 0x840000, LENGTH = __SIGNATURE_REGION_LENGTH__
  user_signatures (rw!x) : ORIGIN = 0x850000, LENGTH = __USER_SIGNATURE_REGION_LENGTH__
}
SECTIONS
{
 ...
 
  .infoapp :
  {
      *(.infoapp*);
  } > app

  .infobtl (NOLOAD) :
  {
      *(.infobtl*);
  } > btl
  
  ...
}

Bootloader linker script:

MEMORY
{
  text   (rx)   : ORIGIN = 0x1E000, LENGTH = 0x1E00
  app (rx)	: ORIGIN = 0x1DDF8, LENGTH = 0x200
  btl	 (rx)	: ORIGIN = 0x1FE00, LENGTH = 0x200
  ... same as above
}
SECTIONS
{
  ...
  
  .infobtl :
  {
      *(.infobtl*);
  } > btl

  .infoapp (NOLOAD) :
  {
      *(.infoapp*);
  } > app
  
  ...
}

 

Piece of the .map file


.infoapp        0x0001ddf8       0x12
 *(.infoapp)
 .infoapp       0x0001ddf8       0x12 src/main.o
                0x0001ddf8                InfoApplication

.infobtl        0x0001fe00       0x12
 *(.infobtl)
 .infobtl       0x0001fe00       0x12 src/main.o
                0x0001fe00                InfoBootloader

 

Does anyone have some tipps, what I could try to get this running?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You appear to be over-complicating things. The only thing the two programs actually need to "share" is one 16 bit pointer. This can be the base address of an array of maybe a struct{} that then contains all the addresses of all the other things to be shared. While you can use registers to pass this (presumably from boot to app?) it's probably easiest to just pick a 16 bit register that's unused at that moment (like TCNT1 or similar) and put the pointer in that, then have the "other half" pick it up when it starts.

 

Actually if you want to hard code the address of the array/struct at some point near the end of the bootloader then you don't even have to pass the address - just have the receiver know the hard coded base address (and the data layout). I suppose that is when you would use a named section and a -section-start.

 

Obviously an app can use facilities shared out of a bootloader but a bootloader can not rely on anything in the app (which might be erased after a failed update) so usually this thing is a one way street.