\uD83D\uDCD8 Background
For MSXIV, we use a Super Loop architecture for driving all data transitions through each project.
Ex: Pedal Poard
It begins with the initialization of all storages and modules. Next, the super loop, does 2 things, event_process
, to grab the first event and then pass that event to can_process_event
event_process
essentially loops through 5 fifos
and returns the first highest priority event. The current CAN implementation is joined within this, meaning CAN messages are raise as events to process.
CAN Receiving:
In libraries/ms-common/src/can.c
all incoming CAN messages trigger an interrupt and the messages is added to the can_storage->rx_info
and an event_raise
raises a CAN event, which needs to be propagated back up to the global event fifos
and then processed through can_process_event
. So the cycle is this
Incoming CAN msg
→ CAN Receive ISR
→ raise CAN event
→ parse through event_process super loop
→ can_process_event
→ look in CAN storage for msg
→ call specific can_rx_handler
And most often what happens is that the can_rx_handler
will raise another event going through the entire cycle again to tell other processes what to do.
CAN Transmit:
Transmitting CAN message is done much through the same way. A can_transmit
is called which raises an event on the global event_queue
. The can_process_event
process the transmit event and can_fsm
transitions to TX_STATE
and calls can_hw_transmit
which transmits the message
\uD83C\uDF08 Options considered
Proposal: Redesign CAN architecture to be main clock of system, since its the main mode of communication between different boards of the car.
Using the current system, we receive CAN messages using interrupts and just push onto the event queue as normal priority. This means that even critical messages are are some what delayed as they go through the event_processing.
There’s also no semaphores/guards for the global event queue. Would be fine single threaded but not if we move to SafeRTOS.
What would this look like?: Still can use interrupts to catch CAN messages, but separate CAN events from the main event queues. Instead, every incoming message will be logged on separate queue, then main program will only read off the queue every 10Hz or something. Same with transmitting. Transmit will just log on the tx queue, and only transmit at a fixed interval.
What this does?: It creates a synchronized system within the main program, only doing tasks at specific intervals of time. Other tasks can based themselves off the CAN tasks to only poll at certain and lifts CPU power off constant polling and other tasks.