#include "route_msg.h" #include #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; }