2

I am working on an embedded system (STM32, ARM M33). I am developing both bootloader and application code. The bootloader and application both use the same filesystem code to access external FLASH memory. Since the size of this code is NOT trivial and it won't change (at least not very often), I would like to have only one copy of it located in the MCU to be a "shared library."

I have referenced the following articles looking for a solution:

One option is to hard-code addresses to the functions and force the linker (of the bootloader) to place these functions at those addresses. This is very hard to maintain and prone to all sorts of problems.

Option 2 is not much better. It involves exporting a list of symbols from the bootloader and linking the application against this so that my shared functions are linked directly into the bootloader's address space.

Option 3 is to locate some sort of jump table at a very specific address within the bootloader's address space (similar to an interrupt vector). The application code would then call the filesystem functions indirectly via this vector. I think I know how to accomplish something like this using a linker script and a special section in flash.

Finally, one of the articles mentioned "create a jump table or a C++ object that implements a virtual interface." Since I am using C++ for my application, this seems the most intriguing option to me to use a virtual interface. From my understanding, virtual methods work by two levels of indirection. The object pointer gets you to a vtable, then the vtable gets you to the actual methods. This is very similar to a C-style jump table but with concrete language support.

My question is, how would this be implemented in practice?

At the moment, my bootloader starts executing the application code by calling the Reset ISR from the application's interrupt vector table (the same function the hardware itself would call immediately after reset). In doing this, the bootloader has no way to "pass on" information (i.e., a pointer to a virtual object) to the application.

Patrick Wright
  • 1,401
  • 7
  • 13
  • Tell your bootloader linker to anchor the functions at a specific address. In the application, create a function pointer and load it with the function address in the bootloader. Dereference the function pointer to call the function. – Thomas Matthews Sep 19 '22 at 20:02
  • 1
    In the bootloader, create a table of function pointers (or function addresses). Tell the bootloader linker to place the table at a specific address (anchoring). Create a header file with index values for the functions. Use the index to fetch the function address, then dereference the function address. – Thomas Matthews Sep 19 '22 at 20:05
  • 1
    You could do like MSDOS and create a software interrupt. Set the first register to the table index, then execute the software interrupt. The interrupt receives the index and calls the appropriate entry in the table. This is only worthwhile if the bootloader is handling interrupts. – Thomas Matthews Sep 19 '22 at 20:12
  • 1
    You could just add the table of fs functions onto the end of the bootloader's vector. If you are short of space you could even overwrite entries in it that the bootloader doesn't use. – Tom V Sep 19 '22 at 20:13

2 Answers2

0

Your first link is the right thing to do, except you should scrape the ROM map file to generate your linker/symbol definition file that you link to.

The bigger problem is ensuring the symbols you're linking to aren't referencing other symbols that aren't alive any more like static or global variables.

Russ Schultz
  • 2,545
  • 20
  • 22
0

The first option is also the approach that some semiconductor provide ROM code. Normally, the share software should have stable interface since this will mostly unable to change/update in the future. Therefore, it is not necessary to think about the maintenance of share code in the future.

Other option might fit to some special need. However, they might increase the complexity of your software.

ThongDT
  • 162
  • 7