mirror of
https://github.com/BotChain-Robots/firmware.git
synced 2026-07-08 09:37:21 +02:00
Flush the LUT every 30 seconds to prevent broken entires from causing incontrollable robot
This commit is contained in:
@@ -49,6 +49,9 @@ DataLinkManager::DataLinkManager(uint8_t board_id, uint8_t num_channels = MAX_CH
|
|||||||
|
|
||||||
init_rip();
|
init_rip();
|
||||||
init_scheduler();
|
init_scheduler();
|
||||||
|
|
||||||
|
// Start the periodic LUT flush task
|
||||||
|
xTaskCreate(lut_flush_task, "lut_flush", 2048, this, 2, &lut_flush_task_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -134,6 +137,10 @@ DataLinkManager::~DataLinkManager(){
|
|||||||
vTaskDelete(send_ack_task);
|
vTaskDelete(send_ack_task);
|
||||||
send_ack_task = NULL;
|
send_ack_task = NULL;
|
||||||
}
|
}
|
||||||
|
if (lut_flush_task_handle != NULL){
|
||||||
|
vTaskDelete(lut_flush_task_handle);
|
||||||
|
lut_flush_task_handle = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t DataLinkManager::set_board_id(uint8_t board_id){
|
esp_err_t DataLinkManager::set_board_id(uint8_t board_id){
|
||||||
@@ -304,6 +311,49 @@ void DataLinkManager::lut_insert(uint32_t hash, const uint8_t* message, size_t m
|
|||||||
xSemaphoreGive(control_frame_lut_mutex);
|
xSemaphoreGive(control_frame_lut_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flush (invalidate) all entries in the control-frame LFU LUT.
|
||||||
|
*
|
||||||
|
* Acquires the LUT mutex, marks every slot as invalid and resets frequency
|
||||||
|
* counters, then releases the mutex. Safe to call from any context.
|
||||||
|
*/
|
||||||
|
void DataLinkManager::lut_flush(){
|
||||||
|
if (xSemaphoreTake(control_frame_lut_mutex, pdMS_TO_TICKS(SEQUENCE_NUM_MAP_MUTEX_MAX_WAIT_MS)) != pdTRUE){
|
||||||
|
ESP_LOGW(DEBUG_LINK_TAG, "LUT flush: could not acquire mutex, skipping");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < CONTROL_FRAME_LUT_SIZE; i++){
|
||||||
|
control_frame_lut[i].valid = false;
|
||||||
|
control_frame_lut[i].frequency = 0;
|
||||||
|
control_frame_lut[i].message.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
xSemaphoreGive(control_frame_lut_mutex);
|
||||||
|
ESP_LOGI(DEBUG_LINK_TAG, "Control-frame LUT flushed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Periodic FreeRTOS task that flushes the control-frame LUT every
|
||||||
|
* LUT_FLUSH_INTERVAL_MS milliseconds.
|
||||||
|
*
|
||||||
|
* @param args Pointer to the owning DataLinkManager instance.
|
||||||
|
*/
|
||||||
|
[[noreturn]] void DataLinkManager::lut_flush_task(void* args){
|
||||||
|
DataLinkManager* self = static_cast<DataLinkManager*>(args);
|
||||||
|
while (true){
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(LUT_FLUSH_INTERVAL_MS));
|
||||||
|
if (self->stop_tasks){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
self->lut_flush();
|
||||||
|
}
|
||||||
|
// Should never reach here during normal operation; loop exits only when
|
||||||
|
// stop_tasks is set so the destructor can clean up.
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
while(true) { vTaskDelay(portMAX_DELAY); }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Helper function to create a control frame
|
* @brief Helper function to create a control frame
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ static const uint16_t crc16_table[256] = {
|
|||||||
#define SEQUENCE_NUM_MAP_MUTEX_MAX_WAIT_MS 50
|
#define SEQUENCE_NUM_MAP_MUTEX_MAX_WAIT_MS 50
|
||||||
#define MAX_RX_QUEUE_SIZE 100
|
#define MAX_RX_QUEUE_SIZE 100
|
||||||
#define CONTROL_FRAME_LUT_SIZE 15 // Maximum number of control frames cached in the receiver-side LFU LUT
|
#define CONTROL_FRAME_LUT_SIZE 15 // Maximum number of control frames cached in the receiver-side LFU LUT
|
||||||
|
#define LUT_FLUSH_INTERVAL_MS 30000 // Flush (invalidate) the entire control-frame LUT every 30 seconds
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Class to represent the Data Link Layer
|
* @brief Class to represent the Data Link Layer
|
||||||
@@ -223,8 +224,19 @@ class DataLinkManager{
|
|||||||
*/
|
*/
|
||||||
void lut_insert(uint32_t hash, const uint8_t* message, size_t message_len, const FrameHeader& header);
|
void lut_insert(uint32_t hash, const uint8_t* message, size_t message_len, const FrameHeader& header);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Flush (invalidate) all entries in the control-frame LUT.
|
||||||
|
*/
|
||||||
|
void lut_flush();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Periodic task that flushes the control-frame LUT every LUT_FLUSH_INTERVAL_MS milliseconds.
|
||||||
|
*/
|
||||||
|
[[noreturn]] static void lut_flush_task(void* args);
|
||||||
|
|
||||||
ControlFrameLutEntry control_frame_lut[CONTROL_FRAME_LUT_SIZE];
|
ControlFrameLutEntry control_frame_lut[CONTROL_FRAME_LUT_SIZE];
|
||||||
SemaphoreHandle_t control_frame_lut_mutex;
|
SemaphoreHandle_t control_frame_lut_mutex;
|
||||||
|
TaskHandle_t lut_flush_task_handle = NULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct frame_scheduler_args {
|
struct frame_scheduler_args {
|
||||||
|
|||||||
Reference in New Issue
Block a user