3

I'm currently writing a custom Ethernet bootloader for a STM32F103C8T6 with a WizNet W5500 Ethernet controller. I want to keep the bootloader code as separate as possible from user code.

The problem is that the WizNet library occupies about 25% of all available ROM (only 64k), so I don't want to include the library both in the bootloader and in the user code but instead include it in the bootloader only and access the library from user code.


My current idea for an approach would be:

In the bootloader:

  • Include the necessary WizNet .h files (and do Ethernet init and bootloader foo)
  • Use a struct/array to store all already used libarary functions as pointers at a predefined location in RAM

In the user code:

  • Still include the WizNet .h files, but use the stored function pointers to "overwrite" the default library function calls, or tell the linker it doesn't have to link them in to save ROM space. (That's the thing I don't know how to do exactly)


But there are some open requirements I don't know how to solve:

  1. Not all functions of the library are called in the bootloader, so they won't get linked in.
    So in the user code only the already existing functions should be called via the function pointers.
    If a library function is called in user corde that was not needed in the bootloader, the compiler/linker has to put that function into the user code.
  2. When the library gets compiled inside the user code, it should internally also use the function pointers where possible.
  3. Ideally the names of the functions should stay the same, so the user code stays compatible regardless of using the existing functions via function pointer, or using the library stand-alone.

I don't understand C linking enough to make that work. Maybe my approach is plain wrong and there is a better way, or maybe it's not possible at all. I hope someone is able to help me here and that I could describe my issue clearly enough.

Some additional constraints / information:

  • The user code should always be able to find the function pointers, even if the bootloader version changes (it gets recompiled and the library function addresses change)
  • I don't want to simply include all the library functions, because that would waste ROM aswell.
  • Both bootloader and user code should reside in the ROM (e.g. for fallback to bootloader, if a fault occurs in user code)
  • The bootloader can update the user code, but leave itself untouched.
  • (Optional) I'd like to not modify the original WizNet library too much.
LeoDJ
  • 31
  • 4
  • Does the bootloader need to stay in the memory after the control is passed to "user" app? – Eugene Sh. Feb 12 '20 at 15:00
  • I updated the additional information, the bootloader should be located in ROM at all times to provide safety in case of an error. But no variables or other RAM content (except the function pointer struct) of the bootloader needs to remain when switching to the "user" app, if that's what you mean. – LeoDJ Feb 12 '20 at 15:12
  • 1
    It is definitively possible, but my time is currently too limited to write down a working solution. The rough idea is like this: Look up `__attribute__((...))` in GCC's documentation. Use this attribute in the bootloader for placing a jump table to all library functions used by the bootloader at a fixed location. Fix this location through the linker script of the bootloader. For user mode programs, provide a linker script that defines the function entries as the addresses in the jump table. Since the library will just add modules for yet unresolved references, it should work out fine. – the busybee Feb 12 '20 at 15:29
  • If you want to share the library code between bootloader and user code, you need to be aware that you can no longer update the library code with your bootloader. If the library code needs an update, you need to revert to the hard-coded bootloader (SWD debug port or UART with BOOT0 pulled high). – Codo Feb 13 '20 at 10:14
  • 3
    The effort for the implementation is probably quite high. It will only pay off if you build a large quantity of your product so that the 30 cents or so you save on each piece (64K instead of 128K version) add up and exceed the additional engineering cost. – Codo Feb 13 '20 at 10:22

0 Answers0