DelfiSpace / DelfiPQcore

0 stars 1 forks source link

FRAM Variables #44

Closed CasperBroekhuizen closed 4 years ago

CasperBroekhuizen commented 4 years ago

A lot of methods already implement variables from FRAM, however, these variables are not always automatically updated in FRAM and accessing/updating these variables is quite tedious as it requires multiple instructions

It would be nice to create a variable that is automatically updated in FRAM on change, and loaded from FRAM during initialization. Assigning a new value to this variable will automatically update the FRAM copy (e.g. simple as uptime = uptime + 1)

I created a simple implementation for this in: https://github.com/DelfiSpace/DelfiPQcore/blob/FRAMBackedVariables/FRAMBackedVar.h which is the object that automatically tracks a copy of the variable in RAM and FRAM.

I tested this object with the uptime, changing the declaration of unsigned int uptime into FRAMBackedVar<unsigned int> uptime(fram, FRAM_UPTIME_ADDRESS); and initializing it, will make the uptime non-volatile. allowing variables to be FRAM backed with minimal changes.

Automatically having a duplicate in RAM also opens the opportunity to create failure tolerance in a central location, by simply only tracking the RAM copy, and to stop updating the FRAM copy.

small extra effort has been made to also support arrays (which can be used for example in the reprogramming service), which can be found here https://github.com/DelfiSpace/DelfiPQcore/blob/FRAMBackedVariables/FRAMBackedArray.h, setting the variable has to be done with the write method, however getting a variable entry can be simply done with the overload of the [] operator. Note that the user has to supply a pointer to the RAM copy buffer themselves, as the size of the array is not known and dynamic allocation during runtime should be avoided.

Second thoughts on this might be to make the RAMcopy optional, in case very big variables in FRAM, a copy in RAM can be neglected to save space.

what are your thoughts on this @StefanoSperetta ?

StefanoSperetta commented 4 years ago

Do we really need the array at this stage? I think we could survive without it for the moment and live with the current solution.

There is maybe a little twist I am thinking about: with variable in FRAM, we make the change always permanent. One interesting feature that could be needed is a variable that we could choose to backup to FRAM or not. Imagine like a parameter we want to try and, if it works, we backup to FRAM. This prevents the risk of saving a potentially problematic value in FRAM.

For the FRAMcopy, do we have an immediate need? Being maybe over-conservative, but I also do not want to work indefinitely to the OS part of the satellite and not finish the basic functionality.

CasperBroekhuizen commented 4 years ago

I would appreciate the Array functionality for the OTA reprogramming, as it is an easy way to track the CRCs and CRC checklist in both FRAM and RAM, meaning that you could still reprogram the FLASH blocks using RAM, even if the FRAM fails, without the need to implement callbacks directly in the OTA itself. as it is an inherent property of the FRAMBackedArray.

I agree that setting a temporary variable might be a neat addition! and also an addition that is easy to implement, however, what would the default behavior be if I type var = 5 ? to just update the ramcopy? and make 'permanent' using var.save() or something?

I agree that having a RAMcopy for every value we have might be wasteful. For example, things like 'total bootcounter' only have to exist in fram, and creating a ram copy serves no purpose. I played around with ideas, and maybe it makes sense to have both a FRAMBackedVar and a FRAMVar, where the second variant does not have a copy in RAM?

I agree that we should finish the last stuff on the OS and freeze it.

StefanoSperetta commented 4 years ago

If possible, I would have the default behaviour of a variable (only RAM, only FRAM or RAM+FRAM) be selected in the constructor. Not that I need always all 3 cases to be implemented or that maybe there are other relevant cases.

What would be handy would be to choose: if the persistent boot counter needs to be persistent, we do not need to call .save() everytime but could simply increment it. Some other edge cases might benefit from an explicit .save() to make the variable persistent. That might be the case for the OTA, btw...

CasperBroekhuizen commented 4 years ago

If we would make the decision to keep a RAMCopy or not in the constructor, I think it will require us to do memory allocation during runtime.

I think two separate objects, for example, FRAMBackedVar and a FRAMVar, will force the user to make the decision about RAMcopies before building.

So an object will either be FRAM or FRAM+RAM and in the constructor you can select whether to initialize using the FRAM copy and whether to automatically commit changes to FRAM.

CasperBroekhuizen commented 4 years ago

comitted in https://github.com/DelfiSpace/DelfiPQcore/commit/b44aaa15ff4ceaacf3d15b00a5351e7e663f38d8

Four new objects, FRAMVar, FRAMBackedVar, FRAMArray and FRAMBackedArray. meant to be use as easy access handles for FRAM variables. during initialization the 'Backed' variants can be set initialize from FRAM and to auto-update the FRAM copy. if not auto-updating, the FRAM copy is updated with the .save method.