175 lines
4.3 KiB
C
175 lines
4.3 KiB
C
#include "route_msg.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "task.h"
|
|
|
|
typedef struct {
|
|
route_msg_t msg;
|
|
uint8_t data[ROUTE_MSG_MAX_PAYLOAD];
|
|
uint8_t in_use;
|
|
} route_slot_t;
|
|
|
|
static route_slot_t g_route_slots[ROUTE_MSG_POOL_SIZE];
|
|
|
|
void route_msg_init(void)
|
|
{
|
|
memset(g_route_slots, 0, sizeof(g_route_slots));
|
|
}
|
|
|
|
static route_msg_t *route_msg_try_alloc_locked(void)
|
|
{
|
|
uint32_t index;
|
|
|
|
for (index = 0; index < ROUTE_MSG_POOL_SIZE; ++index) {
|
|
if (g_route_slots[index].in_use == 0u) {
|
|
g_route_slots[index].in_use = 1u;
|
|
g_route_slots[index].msg.data = g_route_slots[index].data;
|
|
g_route_slots[index].msg.len = 0u;
|
|
g_route_slots[index].msg.src_id = 0u;
|
|
g_route_slots[index].msg.dst_mask = 0u;
|
|
g_route_slots[index].msg.conn_type = 0u;
|
|
return &g_route_slots[index].msg;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
route_msg_t *route_msg_alloc(TickType_t wait_ticks)
|
|
{
|
|
TickType_t start_tick = xTaskGetTickCount();
|
|
route_msg_t *msg;
|
|
|
|
do {
|
|
taskENTER_CRITICAL();
|
|
msg = route_msg_try_alloc_locked();
|
|
taskEXIT_CRITICAL();
|
|
if (msg != NULL) {
|
|
return msg;
|
|
}
|
|
if (wait_ticks == 0u) {
|
|
break;
|
|
}
|
|
vTaskDelay(pdMS_TO_TICKS(1));
|
|
} while ((xTaskGetTickCount() - start_tick) < wait_ticks);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
route_msg_t *route_msg_alloc_from_isr(BaseType_t *xHigherPriorityTaskWoken)
|
|
{
|
|
route_msg_t *msg;
|
|
UBaseType_t saved_interrupt_status;
|
|
|
|
(void)xHigherPriorityTaskWoken;
|
|
saved_interrupt_status = taskENTER_CRITICAL_FROM_ISR();
|
|
msg = route_msg_try_alloc_locked();
|
|
taskEXIT_CRITICAL_FROM_ISR(saved_interrupt_status);
|
|
return msg;
|
|
}
|
|
|
|
void route_msg_free(route_msg_t *msg)
|
|
{
|
|
uint32_t index;
|
|
|
|
if (msg == NULL) {
|
|
return;
|
|
}
|
|
|
|
taskENTER_CRITICAL();
|
|
for (index = 0; index < ROUTE_MSG_POOL_SIZE; ++index) {
|
|
if (&g_route_slots[index].msg == msg) {
|
|
g_route_slots[index].in_use = 0u;
|
|
g_route_slots[index].msg.len = 0u;
|
|
break;
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL();
|
|
}
|
|
|
|
void route_msg_free_from_isr(route_msg_t *msg)
|
|
{
|
|
uint32_t index;
|
|
UBaseType_t saved_interrupt_status;
|
|
|
|
if (msg == NULL) {
|
|
return;
|
|
}
|
|
|
|
saved_interrupt_status = taskENTER_CRITICAL_FROM_ISR();
|
|
for (index = 0; index < ROUTE_MSG_POOL_SIZE; ++index) {
|
|
if (&g_route_slots[index].msg == msg) {
|
|
g_route_slots[index].in_use = 0u;
|
|
g_route_slots[index].msg.len = 0u;
|
|
break;
|
|
}
|
|
}
|
|
taskEXIT_CRITICAL_FROM_ISR(saved_interrupt_status);
|
|
}
|
|
|
|
static bool route_prepare(route_msg_t *msg,
|
|
uint8_t src_id,
|
|
uint8_t dst_mask,
|
|
uint8_t conn_type,
|
|
const uint8_t *data,
|
|
uint16_t len)
|
|
{
|
|
if (msg == NULL || data == NULL || len == 0u || len > ROUTE_MSG_MAX_PAYLOAD) {
|
|
return false;
|
|
}
|
|
|
|
msg->src_id = src_id;
|
|
msg->dst_mask = dst_mask;
|
|
msg->conn_type = conn_type;
|
|
msg->len = len;
|
|
memcpy(msg->data, data, len);
|
|
return true;
|
|
}
|
|
|
|
bool route_send(QueueHandle_t queue,
|
|
uint8_t src_id,
|
|
uint8_t dst_mask,
|
|
uint8_t conn_type,
|
|
const uint8_t *data,
|
|
uint16_t len,
|
|
TickType_t wait_ticks)
|
|
{
|
|
route_msg_t *msg = route_msg_alloc(wait_ticks);
|
|
|
|
if (!route_prepare(msg, src_id, dst_mask, conn_type, data, len)) {
|
|
route_msg_free(msg);
|
|
return false;
|
|
}
|
|
|
|
if (xQueueSend(queue, &msg, wait_ticks) != pdPASS) {
|
|
route_msg_free(msg);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool route_send_from_isr(QueueHandle_t queue,
|
|
uint8_t src_id,
|
|
uint8_t dst_mask,
|
|
uint8_t conn_type,
|
|
const uint8_t *data,
|
|
uint16_t len,
|
|
BaseType_t *xHigherPriorityTaskWoken)
|
|
{
|
|
route_msg_t *msg = route_msg_alloc_from_isr(xHigherPriorityTaskWoken);
|
|
|
|
if (!route_prepare(msg, src_id, dst_mask, conn_type, data, len)) {
|
|
route_msg_free_from_isr(msg);
|
|
return false;
|
|
}
|
|
|
|
if (xQueueSendFromISR(queue, &msg, xHigherPriorityTaskWoken) != pdPASS) {
|
|
route_msg_free_from_isr(msg);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|