Add Product Store Component to enable save/restore for a selection of data products - #196
Add Product Store Component to enable save/restore for a selection of data products#196owhite7128 wants to merge 1 commit into
Conversation
11c1efc to
0f89ae7
Compare
| @@ -0,0 +1,52 @@ | |||
| --- | |||
| description: | | |||
| The product store saves a predefined set of data products from the database to a byte array (memory region) provided at initialization, usually located in nonvolatile storage (i.e. MRAM). The set of data products to save is configured via an autocoded table provided at instantiation, produced from a stored_products.yaml model file. Data products are saved upon receipt of a tick or by command, and can be restored back into the data product database by command or at Set_Up. The store is protected by a CRC which is written on every save and checked prior to every restore, protecting against the restoration of corrupted or never-initialized memory contents. A command is provided to dump the current contents of the store into a packet. The autocoder limits the total size of the store to fit within a single Packet.T. | |||
There was a problem hiding this comment.
Maybe say <assembly_name>.stored_products.yaml to be more clear. I assume .<assembly_name>.stored_products.yaml also works? Please verify, otherwise we will only be able to instantiate this component one time in a given assembly.
| @@ -0,0 +1,52 @@ | |||
| --- | |||
| description: | | |||
| The product store saves a predefined set of data products from the database to a byte array (memory region) provided at initialization, usually located in nonvolatile storage (i.e. MRAM). The set of data products to save is configured via an autocoded table provided at instantiation, produced from a stored_products.yaml model file. Data products are saved upon receipt of a tick or by command, and can be restored back into the data product database by command or at Set_Up. The store is protected by a CRC which is written on every save and checked prior to every restore, protecting against the restoration of corrupted or never-initialized memory contents. A command is provided to dump the current contents of the store into a packet. The autocoder limits the total size of the store to fit within a single Packet.T. | |||
There was a problem hiding this comment.
The idea of not restoring corrupted data makes sense. To be safe, I think we should also require that any data product included in this model is proven to have a type that is ALWAYS_VALID. this will prevent any errant constraint_error from taking down a system.
| - name: Bytes | ||
| type: Basic_Types.Byte_Array_Access | ||
| not_null: true | ||
| description: A pointer to an allocation of bytes to be used for storing the data products. The size of this byte array MUST be at least Store_Description.Store_Size bytes in length. Only the first Store_Description.Store_Size bytes will be used by this component. |
There was a problem hiding this comment.
hopefully that includes the CRC.
| commands: | ||
| - name: Save_Products | ||
| description: Save the configured data products from the database into the store. This performs the same operation as the receipt of a tick. If the store's save time is configured as Tick_Time, the current time is used instead, since no tick is available. | ||
| - name: Restore_Products |
There was a problem hiding this comment.
I am thinking two more commands might be useful
- Enable_Save_On_Tick
- Disable_Save_On_Tick
I feel like these could potentially be mission saving in some sort of crazy scenario where bad data is feeding the store and you need to override and disable the automatic save.
| description: The data products held in the store were restored into the data product database. | ||
| - name: Store_Dumped | ||
| description: Produced a packet with the contents of the store. | ||
| - name: Data_Product_Missing_On_Save |
There was a problem hiding this comment.
This potentially could be spammy. One way we have dealt with this in Adamant is to have a boolean at init for the component that is Issue_Missing_On_Save event, so you could disable this feature when you know you potentially could be running for a long time without DPs in the database.
| param_type: Invalid_Command_Info.T | ||
| - name: Dropped_Command | ||
| description: A command was dropped due to a full queue. | ||
| param_type: Command_Header.T |
There was a problem hiding this comment.
I am thinking that this component could benefit from some simple counter data products:
- U16 roll over save count
- U16 roll over restore count
- U16 roll over CRC mismatch on restore count
| description: A data product stored with its timestamp and restored with that timestamp. | ||
| store_timestamp: True | ||
| restore_time: Use_Stored_Dp_Time | ||
| event_on_missing: True |
There was a problem hiding this comment.
ahh, i like this for event control. ignore my earlier comment in the events.yaml about this
| restore_time: Use_Save_Time | ||
| event_on_missing: False | ||
| - name: Test_Component_1_Instance.Data_Product_C | ||
| description: A data product stored without its timestamp and restored with a timestamp of zero. |
There was a problem hiding this comment.
Looking at this now, I am wondering why we are supporting saving WITHOUT a timestamp at all... will think more on this. I am not sure what the benefit is of this use case except maybe to save space in MRAM/memory dump
There was a problem hiding this comment.
Actually, having second thoughts. Maybe the feature is OK. But my issue with this is that the default behavior here is to restore with a TS of zero, which i think is bad. The default should be Use_Save_Time in this case, since the save time is always available.
| # Current_Time - The current time, fetched from the time connector, is written on each save. | ||
| # Tick_Time - The time found on the incoming Tick.T is written on each save. If a save is | ||
| # commanded, the current time is used instead. | ||
| # No_Time - No save time is written to the store. The store header contains only the CRC. |
There was a problem hiding this comment.
Not sure if we should support No_Time here. A default of always saving either current or tick time seem reasonable, costs basically nothing, and only helps inform a dump.
| Pkt : Packet.T; | ||
| Stat : constant Serialization_Status := Self.Packets.Stored_Products (Self.Sys_Time_T_Get, Self.Bytes.all (Self.Bytes.all'First .. Self.Store_Last), Pkt); | ||
| begin | ||
| -- This should never fail since both the autocoder and an assertion at Init |
There was a problem hiding this comment.
is there such an assertion at Init?
| begin | ||
| -- Handle any commands in the queue. Service up to N commands per tick: | ||
| Messages_Dispatched := Self.Dispatch_N (Self.Commands_Dispatched_Per_Tick); | ||
| pragma Assert (Messages_Dispatched <= Self.Commands_Dispatched_Per_Tick); |
There was a problem hiding this comment.
Hm. I am not sure I like command handling done here. What if the tick rate is really low. Like 1x every 10 minutes. This would mean that we can only execute commands every 10 minutes.
To get around this we may want to set up an initial divider at Init. So we could run this at something reasonable for commands, like 1 Hz, but then slow saving down to 10 minutes using a Ticks_Per_Save parameter (default 1) at 600.
| Messages_Dispatched : Natural; | ||
| begin | ||
| -- Handle any commands in the queue. Service up to N commands per tick: | ||
| Messages_Dispatched := Self.Dispatch_N (Self.Commands_Dispatched_Per_Tick); |
There was a problem hiding this comment.
This dispatch should be done after the business logic.
| -- Save using the current time as the save time. Note that if the store is | ||
| -- configured for Tick_Time, the current time is used for a commanded save, | ||
| -- since no tick is available: | ||
| case Self.Store_Description.Save_Time is |
There was a problem hiding this comment.
code duplication here with the tick. consolidate.
| use Command_Execution_Status; | ||
| Restore_Ok : Boolean; | ||
| begin | ||
| Self.Do_Restore (Restore_Ok); |
There was a problem hiding this comment.
just use function with return boolean instead to clean this up;
This component adds the functionality to save a set of data products to specified memory region. It has the ability to restore data products with different set times depending on the desired behavior.