Fix watchdog on rmt task

This commit is contained in:
2026-03-04 04:26:06 -05:00
parent 5f02634794
commit 9cd7cbac3b
5 changed files with 72 additions and 58 deletions

View File

@@ -514,12 +514,21 @@ esp_err_t DataLinkManager::receive_rmt(uint8_t channel){
res = link_layer_obj->start_receive_frames_rmt(i);
}
while(!link_layer_obj->stop_tasks){
bool any_received = false;
for (uint8_t i = 0; i < link_layer_obj->num_channels; i++){
res = link_layer_obj->receive_rmt(i);
res = link_layer_obj->start_receive_frames_rmt(i);
esp_err_t r = link_layer_obj->receive_rmt(i);
if (r == ESP_OK){
any_received = true;
}
link_layer_obj->start_receive_frames_rmt(i);
taskYIELD(); // feed the watchdog and yield to other tasks between channel polls
}
vTaskDelay(pdMS_TO_TICKS(RECEIVE_TASK_PERIOD_MS));
if (!any_received){
// Nothing received on any channel — sleep briefly to avoid busy-spinning
// and give the watchdog / idle task guaranteed CPU time.
vTaskDelay(pdMS_TO_TICKS(RECEIVE_TASK_PERIOD_MS));
}
}
vTaskDelete(nullptr);

View File

@@ -5,7 +5,7 @@
#define SCHEDULER_MUTEX_WAIT 10 //max time duration to wait
#define SCHEDULER_PERIOD_MS 10
#define RECEIVE_TASK_PERIOD_MS 2
#define RECEIVE_TASK_PERIOD_MS 5
#define GENERIC_FRAME_SLIDING_WINDOW_SIZE 5 //defines the maximum size of the sliding window before resending previously un-ack'd fragments
#define SLIDING_WINDOW_MUTEX_TIMEOUT_MS 5

View File

@@ -8,7 +8,7 @@
/**
* @brief Construct a new RMTManager::RMTManager object
*
*
* @param num_channels Number of channels to init (1-4) inclusive
*/
RMTManager::RMTManager(uint8_t num_channels = MAX_CHANNELS){
@@ -39,17 +39,17 @@ esp_err_t RMTManager::init_tx_channel(){
.callback = encoder_callback,
.arg = &channels[i].encoder_context
};
//create encoder
res_tx = rmt_new_simple_encoder(&encoder_config, &channels[i].encoder);
if (res_tx != ESP_OK){
// printf("Failed to create encoder\n");
ESP_LOGE(DEBUG_TAG, "Failed to create encoder");
channels[i].encoder = NULL;
return ESP_FAIL;
}
//enable the callback
rmt_tx_event_callbacks_t tx_cbs = {
.on_trans_done = RMTManager::rmt_tx_done_callback
@@ -65,8 +65,8 @@ esp_err_t RMTManager::init_tx_channel(){
.invert_out = 0,
.with_dma = 0,
}
};
};
channels[i].tx_gpio = tx_gpio[i];
channels[i].status = CHANNEL_NOT_READY_STATUS;
@@ -83,23 +83,23 @@ esp_err_t RMTManager::init_tx_channel(){
channels[i].tx_queue = xQueueCreate(QUEUE_SIZE, sizeof(TxBuffer)); //can store up to 10 queued transmissions (each transmission size being 192B; based ont he RMT_SYMBOL_BLOCK_SIZE)
res_tx = rmt_new_tx_channel(&tx_channel_config_template, &channels[i].tx_rmt_handle);
//init tx channel
if (res_tx != ESP_OK) {
// printf("Failed to init TX channel\n");
ESP_LOGE(DEBUG_TAG, "Failed to init TX channel %d", i);
continue;
}
if (channels[i].tx_rmt_handle == NULL) {
// printf("TX channel handle is NULL\n");
ESP_LOGE(DEBUG_TAG, "TX channel handle is NULL on channel %d", i);
continue;
}
channels[i].tx_done_semaphore = xSemaphoreCreateBinary(); //create a binary sem
channels[i].tx_context = {
.tx_done_sem = channels[i].tx_done_semaphore,
.transmit_queue = channels[i].tx_queue,
@@ -146,11 +146,11 @@ bool RMTManager::rmt_tx_done_callback(rmt_channel_handle_t channel, const rmt_tx
SemaphoreHandle_t sem = args->tx_done_sem;
QueueHandle_t queue = args->transmit_queue;
rmt_encoder_context_t* encoder_context = args->tx_context;
QueueHandle_t free_queue = args->free_mem_queue;
TxBuffer buf = {};
BaseType_t xTaskWokenByReceive = pdFALSE;
// xSemaphoreTakeFromISR(mutex, &xTaskWokenByReceive);
xQueueReceiveFromISR(queue, static_cast<TxBuffer*>(&buf), &xTaskWokenByReceive); //remove from the queue
@@ -165,7 +165,7 @@ bool RMTManager::rmt_tx_done_callback(rmt_channel_handle_t channel, const rmt_tx
encoder_context->byte_index = 0;
encoder_context->num_symbols = 0;
}
xSemaphoreGiveFromISR(sem, &high_task_wakeup);
return high_task_wakeup == pdTRUE;
}
@@ -213,33 +213,33 @@ esp_err_t RMTManager::init_rx_channel(){
.with_dma = 0
}
}; //temp for one rx channel
//temp
channels[i].rx_gpio = rx_gpio[i];
esp_err_t res_rx = rmt_new_rx_channel(&rx_channel_config, &channels[i].rx_rmt_handle);
if (res_rx != ESP_OK) {
// printf("Failed to init RX channel - reason %s\n", esp_err_to_name(res_rx));
ESP_LOGE(DEBUG_TAG, "Failed to init RX channel - reason %s", esp_err_to_name(res_rx));
return ESP_FAIL;
}
if (channels[i].rx_rmt_handle == NULL) {
// printf("RX channel handle is NULL\n");
ESP_LOGE(DEBUG_TAG, "RX channel handle is NULL");
return ESP_FAIL;
}
channels[i].rx_queue = xQueueCreate(QUEUE_SIZE, sizeof(rmt_rx_done_event_data_t)); //creating queue with some random size
rmt_rx_event_callbacks_t cbs = {
.on_recv_done = RMTManager::rmt_rx_done_callback
};
rmt_rx_register_event_callbacks(channels[i].rx_rmt_handle, &cbs, channels[i].rx_queue);
res_rx = rmt_enable(channels[i].rx_rmt_handle);
if (res_rx != ESP_OK) {
// printf("Failed to enable RX channel\n");
ESP_LOGE(DEBUG_TAG, "Failed to enable RX channel");
@@ -259,7 +259,7 @@ esp_err_t RMTManager::init(){
ESP_LOGE(DEBUG_TAG, "Failed to init TX channel");
return ESP_FAIL;
}
res = this->init_rx_channel();
if (res != ESP_OK) {
// printf("Failed to init RX channel\n");
@@ -273,7 +273,7 @@ esp_err_t RMTManager::init(){
channels[i].status = CHANNEL_READY_STATUS;
}
}
// printf("Free heap before encoder creation: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_DEFAULT));
// heap_caps_print_heap_info(MALLOC_CAP_DEFAULT);
// printf("Free DMA-capable heap before encoder creation: %d bytes\n", heap_caps_get_free_size(MALLOC_CAP_DMA));
@@ -299,7 +299,7 @@ esp_err_t RMTManager::init(){
/**
* @brief This is a callback function called by RMT when transmitting. This function will encode the user data `data` with rising and falling edges based on the bit.a64l
* The symbols are defined in `RMTManager.h`, where a bit 1 is transmitted as a `RMT_SYMBOL_ONE` and a bit 0 is transmitted as a `RMT_SYMBOL_ZERO`
*
*
* @param data
* @param data_size
* @param symbols_written
@@ -308,8 +308,8 @@ esp_err_t RMTManager::init(){
* @param done
* @param arg
*/
size_t RMTManager::encoder_callback(const void* data, size_t data_size, size_t symbols_written,
size_t symbols_free, rmt_symbol_word_t* symbols, bool* done, void* arg){
size_t RMTManager::encoder_callback(const void* data, size_t data_size, size_t symbols_written,
size_t symbols_free, rmt_symbol_word_t* symbols, bool* done, void* arg){
rmt_encoder_context_t* ctx = (rmt_encoder_context_t*) arg; //get the current context
if (symbols_free == 0){ //no space in the tx buffer; don't encode any more bytes until there is space left
@@ -321,13 +321,13 @@ size_t RMTManager::encoder_callback(const void* data, size_t data_size, size_t s
while (ctx->byte_index < data_size && symbols_used < symbols_free){ //loop until we have reached the end of the data or filled the RMT symbol buffer (`symbols_free`)
uint8_t byte = bytes[ctx->byte_index]; //get the byte from the data
uint8_t bit = (byte >> (7 - ctx->bit_index)) & 0x01; //get the current bit, as determined from the bit index (MSB first)
//Manchester (Ethernet Standard) Encoding
//Manchester (Ethernet Standard) Encoding
symbols[symbols_used++] = bit ? RMT_SYMBOL_ONE : RMT_SYMBOL_ZERO; //if the bit is a 1, transmit a 1 symbol; otherwise, transmit 0 symbol
ctx->num_symbols++;
ctx->bit_index++;
if (ctx->bit_index >= 8) {
if (ctx->bit_index >= 8) {
//reached the end of the byte; go to the next byte
ctx->bit_index = 0;
ctx->byte_index++;
@@ -347,11 +347,11 @@ void RMTManager::reset_encoder_context(rmt_encoder_context_t* ctx){
/**
* @brief Sends the string `data` of size `size`, with config `config`
*
* @param data
* @param size
* @param config
* @return int
*
* @param data
* @param size
* @param config
* @return int
*/
esp_err_t RMTManager::send(uint8_t* data, size_t size, rmt_transmit_config_t* config, uint8_t channel_num){
if (channel_num >= num_channels){
@@ -406,7 +406,7 @@ esp_err_t RMTManager::send(uint8_t* data, size_t size, rmt_transmit_config_t* co
vPortFree(new_data_to_send_buf.data);
ESP_LOGE(DEBUG_TAG, "Failed to queue data");
return ESP_FAIL;
}
}
esp_err_t res = rmt_transmit(this->channels[channel_num].tx_rmt_handle, this->channels[channel_num].encoder, new_data_to_send_buf.data, new_data_to_send_buf.length, config);
@@ -426,7 +426,7 @@ esp_err_t RMTManager::send(uint8_t* data, size_t size, rmt_transmit_config_t* co
/**
* @brief This function, given the `symbols` and the length `num`, will convert the received symbols into the symbols defined in `RMTSymbols.h`
* this somehow works first try????? (tested with 't', 'O', and 'THIS IS A SAMPLE TEXT MESSAGE')
* @param symbols received symbols
* @param symbols received symbols
* @param num number of received symbols
* @param decoded decoded symbol string
* @param output_num size of `decoded`
@@ -445,7 +445,7 @@ int RMTManager::decode_symbols(rmt_symbol_word_t* symbols, size_t num, rmt_symbo
// printf("duration0 %d level0 %d duration1 %d level1 %d\n", symbols[i].duration0, symbols[i].level0, symbols[i].duration1, symbols[i].level1); //dummy print receive
//manchester encoding
/*there are two cases in the beginning:
1. if duration0 = 20, then we are in between two symbols (low to high and high to low).
1. if duration0 = 20, then we are in between two symbols (low to high and high to low).
in this case, we need to insert a low in the beginning and "split" the current symbol into 2
2. if duration0 = 10, then the first symbol should be high to low
*/
@@ -461,21 +461,21 @@ int RMTManager::decode_symbols(rmt_symbol_word_t* symbols, size_t num, rmt_symbo
//need to insert a 0 before received symbols
decoded[output_index++] = RMT_SYMBOL_ZERO;
}
}
if (curr_high_low){
decoded[output_index++] = RMT_SYMBOL_ONE;
} else {
decoded[output_index++] = RMT_SYMBOL_ZERO;
}
//if duration1 = 20, then we are starting low
if (symbols[i].duration1 != RMT_DURATION_SYMBOL){
curr_high_low = !curr_high_low;
}
i++;
}
return (int)output_index;
@@ -483,7 +483,7 @@ int RMTManager::decode_symbols(rmt_symbol_word_t* symbols, size_t num, rmt_symbo
/**
* @brief This converts the parsed symbols into a string of size `output_index`
*
*
* @param symbols Parsed received symbols (see `RMTSymbols.h` for the definitions of the symbols)
* @param num Length of `symbols`
* @param string Output string encoded by the symbols
@@ -498,7 +498,7 @@ int RMTManager::convert_symbols_to_char(rmt_symbol_word_t* symbols, size_t num,
char byte = 0;
size_t output_index = 0;
int i = 0;
while (i < num && output_index < output_num){
if (symbols[i].level0 == 0 && symbols[i].level1 == 1){
//zero
@@ -525,8 +525,8 @@ int RMTManager::convert_symbols_to_char(rmt_symbol_word_t* symbols, size_t num,
/**
* @brief Start async RX job
*
* @return esp_err_t
*
* @return esp_err_t
*/
esp_err_t RMTManager::start_receiving(uint8_t channel_num){
if (channel_num >= num_channels){
@@ -560,13 +560,13 @@ esp_err_t RMTManager::start_receiving(uint8_t channel_num){
/**
* @brief Function to get the received messages
*
*
* @param recv_buf Byte array of the received bytes
* @param size Size of the byte array
* @param output_size Pointer containing the received bytes (will be written)
* @param channel_num Physical channel pair to receive from
*
* @return esp_err_t
*
* @return esp_err_t
*/
esp_err_t RMTManager::receive(uint8_t* recv_buf, size_t size, size_t* output_size, uint8_t channel_num){
if (channel_num >= num_channels){
@@ -579,9 +579,7 @@ esp_err_t RMTManager::receive(uint8_t* recv_buf, size_t size, size_t* output_siz
}
rmt_rx_done_event_data_t rx_data;
if (xQueueReceive(channels[channel_num].rx_queue, &rx_data, pdMS_TO_TICKS(5)) != pdTRUE){ //this will wait until a message has arrived or not
// printf("Timeout occurred while waiting for RX event\n");
// ESP_LOGE(DEBUG_TAG, "Timeout occurred while waiting for RX event - didn't receive a message in time");
if (xQueueReceive(channels[channel_num].rx_queue, &rx_data, 0) != pdTRUE){ // non-blocking poll
return ESP_FAIL;
}
@@ -597,12 +595,12 @@ esp_err_t RMTManager::receive(uint8_t* recv_buf, size_t size, size_t* output_siz
if (num < 0){
return ESP_FAIL;
}
*output_size = this->convert_symbols_to_char(channels[channel_num].decoded_recv_symbols, num, recv_buf, size);
if (*output_size < 0){
return ESP_FAIL;
}
//UNCOMMENT HERE TO GET RAW BITS TO USE IN `components/dataLink/test_scripts/parse_bit_frame.py`
// printf("\n\nparsed characters:\n");
// for (int i = 0; i < *output_size; i++) {
@@ -630,4 +628,4 @@ RMTManager::~RMTManager(){
vQueueDelete(channels[i].rx_queue);
}
}
}
}