High Level Overview
This Page:Page
1) Purpose
The packet dispatcher is used to decode protobuf frames.
Application code usually wants:
- strongly typed decoded payloads
- one handler per packet type
- decoupling between input reception and packet processing
This module solves that by:
- receiving a raw protobuf
receive_frame - decoding it into
PBEnvelope - determining
which_payload - finding the corresponding handler
- copying the decoded payload into that handler’s (freeRTOS) queue
- letting a dedicated task call callback for this handler
In short, each packet type gets its own handler callback, queue and task. That makes the system modular and easy to extend, at least conceptually. So the module acts as a bridge between transport-level bytes and application-level packet handler.
In practical terms, it is a decode-and-dispatch layer between an input source that receives raw bytes and a set of application handlers that want already-decoded payloads
The implementation has some assumptions and hazards that absolutely need to be understood before you start messing with its internal structure.
2) High-level design
The design has three major parts:
- Global handler registry
One queue & task per packet typeShared decode step
a. Global handler registry
The global handler registry contains an array of packet handler tasks (type:see packet_handler_config_t )packet_handler_config_t . ThisA packet handler task configures (amongst other things) the callback function for a certain type of packet.
The array of configs is given by the caller at initialization time. One packet handler task contains information on the handler for a specific type of packet, see packet_handler_config_t.time. This array is stored globally and used by dispatch logic for packet type lookup.
What we call a packet is a raw protobuf.
What we call a handler is a (configuration of a) callback function for a specific protobuf/packet.
b.
- One queue & task per packet type
The
Eachdispatcher takes each handler configuration and creates 1 FreeRTOS queue and 1 FreeRTOS
The task takes the correspoding payload out of the queue and calls the specified handler/callback function. By corresponding we mean that each type of packet has their own queue.
TaskNOTE lifecycleon handler task lifecycles
Each handler task is intended to live forever.
ItsA lifecycletask is:
- responsible for passing a specific packet type from the corresponding queue to the correct callback. As stated above, a handler task gets created by the dispatcher according to the configuration (see packet_handler_config_t ) done by the caller when initializing the dispatcher.
Lifecycle
- Created by
PacketHandlerStart()(
As part ofthe initialization process (seePacketDispatcherInit()). validateValidateconfigconfiguration
Task_name, handler and queue need to be present for it to work. These params are set in packet_handler_config_t. If you use the macros, this should be fine.allocateAllocate local packet bufferblockBlock forever on queue receive
So, when we receive a packet in the corresponding queue, we wait for it to be handled.processProcess packets as they arrive
The processing is done by the callback specified in the handler.
It terminatesTerminates only
if:if...- config is invalid
- queue is null
- heap allocation fails for packet buffer
fails
In those cases it deletes itself.
At the moment, there is no restart or supervision mechanism in this
module.c. Shared decode stepIncoming frames are decoded into a global staticPBEnvelopeobject:static PBEnvelope DecodingEnvelopeCurrent;The dispatcher then copiesDecodingEnvelopeCurrent.payloadinto a handler queue.This detail matters a lot for concurrency and payload sizing.module!
3)External dependenciesThis is not a standalone module. It sits in the middle of RTOS tasking, protobuf decoding, and transport reception.
This module depends on:
specifically used pieces
FreeRTOS
xQueueCreateStaticxQueueReceivexQueueSendxTaskCreatevTaskDelete
nanopb / protobuf decoding
pb_istream_from_bufferpb_decode
PBEnvelopegenerated protobuf definitionsPBEnvelope_fieldsPBEnvelope_size
stm/ethernet_udp.hreceive_frame
- Created by