Michał Michał - 3 years ago 156
C Question

Using pointer functions - 2 seperate applications on 1 device

I asked some time ago this question How can I use one function from main application and bootloader? (embedded) and started to implement proposed solution but ran into a few problems.

On my cortex M4 I, have 2 seperate applications - bootloader and user application. Now I had some (many) functions which were the same for both apps. So I compiled them only for bootloader, then created an array of function pointers at specified address, which is known for user application. So in application, I didn't compile the files with those functions again, but I use those pointers whenever needed.

This is example of code I tried to make common for both applications:

static uint8_t m_var_1;

// Sends events to the application.
static void send_event(fs_op_t const * const p_op, fs_ret_t result)
{
uint8_t var_2;
[...]
}


My application ends in Hardfault, which happens e.g. when dividing by zero or using pointer to function with NULL value. I am not sure why yet, but I started wondering what happens with those variables.
var_2
will most surely be located on stack so this is no problem. But what about
m_var_1
? In the map file, it has a specified place in RAM. But I don't have seperate RAM sections for app and bootloader. I am not sure, but I have a feeling that this variable may use the same RAM location as when created for bootloader. Is this possible? Maybe some other issues?

Answer Source

Yes you are right, the code will attempt to access the global variable at the same location as it is linked for loader. This is because linking involves replacing all occurrences of identifiers (including function names and variable names) by the addresses determined after compiling.

In your application, the variable, even if it does exist there too, is likely to be at a different address. The calling of the functions happens to work, because they are located in ROM and cannot be different for application and loader. Calling them via const pointers, which are also stored in ROM, bypasses the problem.

The solution is using a file system simulator, if you can find one for your hardware.

Otherwise you will hate having to do the following.

Part 1, setup:

  • introduce a special linker section with all the variables accessed by both system paprts (application and loader)
  • let one linker fill it
  • set it up for the other linker as don't-tocuh
  • be careful with the initialisation
    • preferrably do not assume any intialisation value
    • if you need initialisation, e.g. "bss" (init to 0) or "data" (init to specified value),
      do so explicitly at the start of the system part which is not associated to the linker you let setup the variables
    • for safety, it is recommended to do the init the same way in both system parts
    • "data" init uses a special non-volatile linker section with a copy of the to-be-initialised variables, accessing that is possible

Part 2, access:

  • option 1)
    store const pointers to those variables, like you did for the functions
  • option 2)
    get the second linker (the other one, which did not do the actual setup of the common variable section) to create an identically structured and identically located section as the one from first linker; more studying of your linker needed here

Part 3, resuing values stored by other system part
(e.g. you want to leave some kind of message from loader, to be read my application)

  • design which system part initisalises which variable, the other one only reads them
  • separate the common variables in four sections,
    • written and read by both system parts, initialised by both
    • written and read by x, only read by y, initialised by x
    • written and read by y, only read by x, initialised by y
    • written by both system parts, not initialised, uses checksums and plausibility cehcks,
      if a variable has not been initialised, init to default
  • init each section only in the corresponding writer system part
  • setup as "no init" in the other linker
  • setup as "no init" in both linkers for the fourth case
  • use getters and setters with checksum update and plausibility for the fourth case

To do all that, intense study of your linker features and syntax is needed.
So I recommend not to try, if you can get around it. Consider using an existing file system simulator; because that is basically what above means.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download