We have been building a general purpose infrastructure for CubeSat flight control software that we call CubedOS. Applications using CubedOS are organized as a collection of interacting "modules" with at least one thread of control, or task, per module. The CubedOS infrastructure provides an asynchronous messaging service as well as libraries of other useful space-mission oriented tools. Task management is handled by the underlying Ada runtime system under the restrictions imposed by the Ravenscar profile. It is our intention to eventually verify freedom from runtime errors using the SPARK tools although we don't yet have access to SPARK 2014 tools that can process Ada tasking constructs.
In part to demonstrate the usability of CubedOS, as well as to create a valuable software component in its own right, we are currently working on an implementation of the CCSDS File Delivery Protocol (CFDP) as a CubedOS module. This is a work in progress but so far it illustrates both what is good and bad about the CubedOS architecture.
CFDP requires that multiple, simultaneous file transfers be supported. Furthermore, a CFDP "entity" (the software implementing the protocol), must be able to simultaneously receive requests from a CFDP "user" (the software using the protocol) as well as protocol data units (PDUs) from a peer CFDP entity. These requirements are relatively straightforward to implement using CubedOS's message passing architecture.
Each CFDP entity executes a loop that first receives a message from its mailbox and then processes it. Roughly this loop looks like:
loop Message_Manager.Mailboxes(MyID).Receive(Incoming_Message); -- Decode and process Incoming_Message end loop;
Messages coming from the CFDP user to initiate new file transfers and messages coming from the underlying communication module containing PDUs for active transfers can be mixed freely with no special handling. Provided the messages contain enough information to distinguish one transaction from another, it is also easy to see how to manage multiple transactions at once. The CFDP module maintains state information about all active transactions and uses information in the message to update the state of the appropriate transaction. Of course, processing an incoming message may require a reply message to be sent to either the CFDP user or to the underlying communication module. Again this presents no special problems and is quite straightforward to program.
The concurrency inherent in CubedOS allows CFDP protocol processing, communications, and high level application logic, to all execute simultaneously. Receiving a PDU in the communications module and processing some previously received PDU can be overlapped.
However, although the architecture of CubedOS is clearly well suited to this example there are problems with it as well:
- Messages can potentially pile up in a module's mailbox causing large and difficult to predict latencies in message handling. Even determining how large a mailbox is necessary can be problematic.
- There is runtime overhead associated with encoding and decoding CubedOS messages. We have yet to fully analyze the amount of overhead involved and its possible impact on performance.
- There is a loss of static type safety since invalid messages are detected and handled at runtime. Compare this to the static checking of procedure parameter types in normal Ada. This is a worrisome issue in light of our desire to ensure high levels of reliability in our software.
- The analyzability of CubedOS with SPARK remains to be seen. We await access to SPARK tools that can handle Ada's tasking constructs.
Yet despite the possible difficulties, we are encouraged so far by our experience with the CFDP implementation. The architecture of CubedOS is not without problems, but it clearly offers some nice advantages as well.