Skip to main content
warning

🚧 This document is still being actively worked on and is subject to change. 🚧

Responsible
  • Aaron Bojarski
Last Updated10/12/2025, 12:48:54 PM
Last AuthorKai Berszin

Inter Task Communication

SBUS (Software Bus)​

The SBUS is a software bus that allows for inter task communication using publish/subscribe messaging. It is built on top of FreeRTOS queues and provides a standardized way to send messages between tasks. It uses fixed size packets of 64 bytes. The SBUS consists of a read only data structre that contains all topics and their subscribers. It further provides functions to send and receive messages from the bus. The SBUS does not have its own "broker" task. It is fully implemented as library functions and is thread safe. The following figure shows this design.

Task 1
...
Task n
Forwarding Logic

Each tasks that receives messages from the SBUS has a dedicated FreeRTOS queue. The SBUS library functions handle the sending and receiving of messages to and from these queues. Furthermore, the task must have a second (short) queue for receiving responses to service requests. For more on service requests see the next section.

Services​

Tasks can provide "services" to other tasks. A service is a functionality that can be requested by other tasks. The service provider task subscribes to a specific topic on the SBUS and waits for incoming requests. The service request is sent as a message on the SBUS to the service provider task. The service provider task processes the request and sends a response back to the requesting task. The requesting task waits for the response on its dedicated response queue. The following figure shows the sequence of operations for a service request.

Service Request OperationService Request OperationClientService ProviderClientClientService ProviderService ProviderServiceRequest = (ServiceTopic, TaskID, Seq, Data...)alt[successful case (ResponseTopic = ServiceTopic, Seq' = Seq, ResponseCode = Success)]Response = (ResponseTopic, Seq', ResponseCode, Data...)Process returned data and continue with operations.[reported failiure case (ResponseTopic = ServiceTopic, Seq' = Seq, ResponseCode = Failiure)]Response = (ResponseTopic, Seq', ResponseCode, Data...)Handle the failiure if possible or notify FDIR task. Proceed with operations if possible.[response does not match request ((ResponseTopic != ServiceTopic) or (Seq' != Seq))]Response = (ResponseTopic, Seq', ResponseCode, Data...)Discard the message and wait for actual response.[timeout (no response received in time)]Notify FDIR task. Proceed with operations if possible.Seq = Seq + 1

Sequence numbers are used to match requests and responses. This is necessary because timouts can occur and therefore multiple requests of the same task can be "in flight" at the same time.

Idea for Services with Large Data Transfers​

The idea is to use FreeRTOS MessageBuffers for larger data transfers. MessageBuffers are meant to be used with one producer and one consumer only. However, if we can strictly serialize the sending of data (producer side) we should be able to use this with multiple senders. I therefore propose the following sequence of operations for transfers that do not fit into a single SBUS packet. The MessageBuffer is owned by the service provider and it decides who is currently allowed to send (some amount of bytes) by accepting requests sent over the SBUS.

Service Request Large Data TransferService Request Large Data TransferClientService ProviderClientClientService ProviderService ProviderAquire service mutexServiceRequest = (ServiceTopic, TaskID, Seq, B, Data...)Response = (ResponseTopic, Seq', ResponseCode, B)alt[successful case (ResponseTopic = ServiceTopic, Seq' = Seq, ResponseCode = Success)]Client has permission to use the MessageBuffer for exactly B bytes.DataDataDataConfirmation Message = (ResponseTopic, Seq', ResponseCode, Data...)[failiure case]Handle the failiure if possible or notify FDIR task.Release service mutexSeq = Seq + 1