Compiling for a different OS than what is on the device

What actually happens when a firmware is compiled for OS1.5.2 but downloaded to a device with OS2.0.1?

Specifically, I have bug on a B523 based device, using PublishQueueAsyncRK with MB85RC256V-FRAM-RK. When queueing a message for upload the device resets depending on OS version.

The same happens on the B SOM evaluation board, and also with Argon on a breadboard.

If I build for OS2.0.1 (Web-IDE), devices with 2.0.1 have the resets. If I build for OS1.5.2 there is no problem on devices with OS1.5.2 or OS2.0.1. The devices are still marked as running the respective OS’es in the console.

So, I am wondering, what is the difference between running a build for 1.5.2 and a build for 2.0.1, when it is uploaded to a device with OS2.0.1?

Nothing special. Any application that is targeted at a device OS equal or less than what is installed on your device will run without any further action.

If your application targets a higher version the bootloader/device OS will recognize the mismatch and attempt a roll-forward the device OS to match the minimum target requirement of the application. But for that your device needs to be able to connect to the cloud in order to download the required binaries.

To answer that we’d need to know more about what your firmware is doing :wink:

Thanks. Well, as it is the same firmware being build for either OS, it is doing the same :slightly_smiling_face:

This is the mechanism I do not understand. I have not been able to find documentation on limitations etc. Do you know of any docs on this?

Not sure what kind of documentation you’d expect to see. There isn’t anymore to say than what I already said :confused:
What limitations would you expect?

A new OS can introduce breaking changes. Either directly like removing a parameter in a function call, or indirectly like you can no longer call one function before having called another. Maybe a newer compiler is required, or the bootloader works differently.

When Firmware built for an older OS can run on newer OS’s, it implies A: there are never breaking changes or B: There is some kind of handling when e.g. a deprecated API is called by a firmware built for an earlier OS, or C: it is an unwarranted claim, and you may be lucky to not trigger breaking changes.

From what you are telling me, it confirms option C.

1 Like

This is how I understand it:
Since your application is typically not directly calling into the device OS but rather goes via a “slim interface” of soft linked APIs selecting the correct target should suffice.
However whenever undocumented features are employed or direct calls (only possible when building locally) you may run into issues.
Also when your code relied on some “buggy” behaviour which was then ironed out the application may break too.

However, there might well be changes I missed any memos about :flushed:
So maybe @rickkas7 can clarify this a bit better.

1 Like

The intention is that you should be able to run a binary targeting 1.5.2 on 2.0.0 without recompilation. For example, when you particle flash tinker from the Particle CLI on the Photon/P1, it targets Device OS 0.4.5 (really).

When user firmware calls into Device OS, it’s through an immutable API. Whenever a function signature changes, a completely different exported API function is created to maintain compatibility with older firmware binaries.

Now, in practice, code could depend on behaviors that do not affect the function signature. For example, whether a function in Device OS is interrupt safe or not, whether it can be called from a global object constructor or not, etc…

Also there is a possibility that an accidental impermissible change was made to an API introducing an accidental breaking of the ABI contract. These are usually fixed in subsequent versions when they occur.

For 2.0.0, the most common problem is related to calling functions from STARTUP or global object constructors. Prior Device OS versions were lenient on this, however the code would also randomly fail. In 2.0, these dangerous calls now reliably fail, instead of randomly fail.

2 Likes

I see. Thank you both. That is what I was wondering about.

Unfortunately STARTUP or global constructors does not appear to be the issue in this case.

The only additional libraries I use are MB85RC256V-FRAM-RK.h and PublishQueueAsyncRK, and as far as I can see they behave correctly with fram.begin(); and publishQueue.setup(); in setup().