Skip to main content

Recommended Usage Pattern

More information on the mentioned steps can be found in Functions of the Packet Dispatcher



Typical Usage Model

Intended setup

  1. Define one handler function per packet type
  2. define one packet_handler_config_t entry per packet type (using the macros)
  3. provide queue storage buffers
    (When using the macros, you do not need to do this manually)
  4. call PacketDispatcherInit(...)
  5. whenever a frame arrives, call DispatchPacket()

Flow after setup

  1. Ethernet/UDP receives raw frame
  2. networking code builds receive_frame
  3. DispatchPacket() decodes it
  4. payload type is matched
  5. decoded payload is copied into target queue
  6. matching handler task wakes
  7. the callback processes typed payload


Examples

1) Using macros

//Imports
#include "packet_dispatcher.h"
#include "packet_dispatcher_macros.h"

/*Define handler callbacks*/
static result_t handle_drive_msg(void* buffer) {
    PBDriveMsg* msg = (PBDriveMsg*)buffer;
    return process_drive_msg(msg);
}

static result_t handle_sensor_diag(void* buffer) {
    PBSensorDiag* msg = (PBSensorDiag*)buffer;
    return process_sensor_diag(msg);
}

PACKET_HANDLER_CONFIG_STATIC(drive_handler_cfg,
                             PBEnvelope_drive_msg_tag,
                             drive_msg,
                             handle_drive_msg);

PACKET_HANDLER_CONFIG_STATIC_QUEUE(sensor_diag_handler_cfg,
                                   PBEnvelope_sensor_diag_tag,
                                   sensor_diag,
                                   handle_sensor_diag,
                                   10U);

static packet_handler_config_t* handlers[] = {
    drive_handler_cfg,
    sensor_diag_handler_cfg,
};


2) Manual configuration

//Imports
#include "packet_dispatcher.h"

static result_t handle_drive_cmd(void* buffer) {
    PBDriveCommand* msg = (PBDriveCommand*)buffer;
    return drive_process(msg);
}

static result_t handle_arm_cmd(void* buffer) {
    PBArmCommand* msg = (PBArmCommand*)buffer;
    return arm_process(msg);
}

static uint8_t drive_queue_storage[8 * sizeof(PBDriveCommand)];
static uint8_t arm_queue_storage[4 * sizeof(PBArmCommand)];

static packet_handler_config_t handlers[] = {
    {
        .handler = handle_drive_cmd,
        .task_name = "drive_pkt",
        .packet_type = PBEnvelope_drive_cmd_tag,
        .task_priority = 3,
        .task_stack_depth = 512,
        .item_size = sizeof(PBDriveCommand),
        .queue_length = 8,
        .queue_buffer = drive_queue_storage,
    },
    {
        .handler = handle_arm_cmd,
        .task_name = "arm_pkt",
        .packet_type = PBEnvelope_arm_cmd_tag,
        .task_priority = 3,
        .task_stack_depth = 512,
        .item_size = sizeof(PBArmCommand),
        .queue_length = 4,
        .queue_buffer = arm_queue_storage,
    },
};

Then during startup:

result_t res = PacketDispatcherInit(handlers, ARRAY_LEN(handlers));

And during frame reception:

DispatchPacket(&rx_frame);


Important note about array type

The current PacketDispatcherInit() API expects:

packet_handler_config_t* handlers

meaning a contiguous array of structs, not an array of pointers.

So with the current implementation, the final array should actually be:

static packet_handler_config_t handlers[] = {
    drive_handler_cfg,
    sensor_diag_handler_cfg,
};

not an array of pointers.

That distinction matters. The macros define actual config objects, not pointers.