I am working on a project which involves receiving TWAI
messages which are updated every 1ms and send them through UART
.
As I do not have access to TWAI
Transmitter at the moment, I am simulating incoming messages with a GPTimer
running at 1ms and updating a global shared twai_message_t
object.
Somehow, it is working, but I am not getting my data in the correct order, and maybe even missing some data. I wanted some help in understanding what is going on with my RTOS
Tasks.
#include <stdio.h>
#include <stdlib.h>
#include "string.h"
#include <inttypes.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
#include <freertos/queue.h>
#include "freertos/event_groups.h"
#include <driver/uart.h>
#include "driver/gptimer.h"
#include "driver/twai.h"
#include "esp_log.h"
/*Configuration Settings*/
enum { BUF_LEN = 20 };
/*Pins*/
// #define TXD_PIN (GPIO_NUM_17)
// #define RXD_PIN (GPIO_NUM_16)
#define TXD_PIN (GPIO_NUM_1)
#define RXD_PIN (GPIO_NUM_3)
/*Globals*/
#define UART_NUM UART_NUM_1
#define BUF_SIZE (1024)
#define TWAI_RX_TASK_PRIORITY (configMAX_PRIORITIES - 1)
#define UART_TX_TASK_PRIORITY (configMAX_PRIORITIES - 2)
static const char *Timer_TAG = "Timer";
static const char *TX_TASK_TAG = "TX_TASK";
static TaskHandle_t processing_task = NULL;
static SemaphoreHandle_t sem_done_reading = NULL;
static portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
static portMUX_TYPE uartlock = portMUX_INITIALIZER_UNLOCKED;
gptimer_handle_t gptimer = NULL;
QueueHandle_t uart_tx_queue[2]; // Two buffers for UART transmit
volatile int active_buffer = 0;
static volatile uint8_t buf_overrun = 0; // Double buffer overrun flag
TaskHandle_t uart_tx_task_handle;
twai_message_t rx_message = { .identifier = 1,
.data_length_code = 3,
.data = {0, 0, 0, 0, 0, 0, 0, 0}
};
// Message struct to wrap strings for queue
typedef struct CAN_Serial_Frame {
uint8_t sof;
uint32_t timestamp;
uint8_t dlc;
uint32_t msg_id;
uint8_t payload[8];
uint8_t eof;
}CAN_Serial_Frame;
CAN_Serial_Frame CSF = {0xAA,100,8,1,{0, 0, 0, 0, 0, 0, 0, 0},0xBB};
/*Timer ISR*/
uint8_t update_flag = 1;
void IRAM_ATTR onTimer() {
xQueueSend(uart_tx_queue[active_buffer], &rx_message, 0.001/portTICK_PERIOD_MS);
static uint16_t idx = 0;
BaseType_t task_woken = pdFALSE;
portENTER_CRITICAL(&spinlock);
if(update_flag){
rx_message.data[0]++;
}
if(rx_message.data[0]>84){
rx_message.data[0] = 0;
// update_flag = 0;
}
active_buffer = 1 - active_buffer;
portEXIT_CRITICAL(&spinlock);
xTaskNotifyFromISR(uart_tx_task_handle,0,eNoAction,&task_woken);
xTaskNotifyFromISR(processing_task,0,eNoAction,&task_woken);
if (task_woken == pdTRUE) {
portYIELD_FROM_ISR(task_woken);
}
}
void Data_Update_Task(void *parameters){
// Start a timer to run ISR every 1 ms
// %%% We move this here so it runs in core 0
ESP_LOGI(Timer_TAG, "Create timer handle");
gptimer_config_t timer_config = {
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = 1000000, // 1MHz, 1 tick=1us
};
ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
gptimer_event_callbacks_t cbs = {
.on_alarm = onTimer,
};
ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, NULL));
ESP_LOGI(Timer_TAG, "Enable timer");
ESP_ERROR_CHECK(gptimer_enable(gptimer));
ESP_LOGI(Timer_TAG, "Start timer, auto-reload at alarm event");
gptimer_alarm_config_t alarm_config = {
.reload_count = 0,
.alarm_count = 1000, // period = 1ms
.flags.auto_reload_on_alarm = true,
};
ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config));
ESP_ERROR_CHECK(gptimer_start(gptimer));
while(1){
}
}
/*UART*/
void uart_init() {
uart_config_t uart_config = {
.baud_rate = 921600,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(UART_NUM, &uart_config);
ESP_ERROR_CHECK( uart_set_pin(UART_NUM, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE) );
// Install the UART driver with a buffer size of 1024 bytes
ESP_ERROR_CHECK( uart_driver_install(UART_NUM, 1024, 1024*4, 0, NULL, 0) );
ESP_LOGI(TX_TASK_TAG, "UART Driver Installed");
}
void uart_tx_task(void *parameters){
uart_init();
twai_message_t tx_message;
while (1) {
// Process all available TWAI messages in the active buffer
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
xQueueReceive(uart_tx_queue[active_buffer], &tx_message, portMAX_DELAY) ;
// Process the TWAI message and send it over UART
CSF.dlc = tx_message.data_length_code;
CSF.msg_id = tx_message.identifier;
for (int i = 0; i < tx_message.data_length_code && i < sizeof(CSF.payload); i++) {
CSF.payload[i] = tx_message.data[i];
}
const int txBytes = uart_write_bytes(UART_NUM,(const char *)&CSF, sizeof(CSF));
// ESP_LOGI(TX_TASK_TAG, "Wrote %d bytes", txBytes);
ESP_LOGI(TX_TASK_TAG, "Data Sent: %d",CSF.payload[0]);
}
}
void app_main(void){
/*Create two queues for double buffering of UART transmit*/
uart_tx_queue[0] = xQueueCreate(100, sizeof(twai_message_t));
uart_tx_queue[1] = xQueueCreate(100, sizeof(twai_message_t));
/*Initialize TWAI*/
// twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(TWAI_RX_PIN_CONFIG);
// twai_init(&g_config);
/*Create UART Transmit Task*/
xTaskCreate(uart_tx_task, "uart_tx_task", 1024*5, NULL, UART_TX_TASK_PRIORITY, &uart_tx_task_handle);
/*Create TWAI Receive Task*/
xTaskCreate(Data_Update_Task, "twai_receive_task", 1024*5, NULL, TWAI_RX_TASK_PRIORITY, &processing_task);
}
I (4854) TX_TASK: Data Sent: 74
I (4864) TX_TASK: Data Sent: 78
I (4864) TX_TASK: Data Sent: 82
I (4864) TX_TASK: Data Sent: 8
I (4874) TX_TASK: Data Sent: 12
I (4874) TX_TASK: Data Sent: 16
I (4874) TX_TASK: Data Sent: 20
I (4884) TX_TASK: Data Sent: 24
I (4884) TX_TASK: Data Sent: 1
I (4894) TX_TASK: Data Sent: 27
I (4894) TX_TASK: Data Sent: 31
I (4894) TX_TASK: Data Sent: 35
I (4904) TX_TASK: Data Sent: 39
I (4904) TX_TASK: Data Sent: 46
I (4904) TX_TASK: Data Sent: 50
I (4914) TX_TASK: Data Sent: 54
I (4914) TX_TASK: Data Sent: 58
I (4924) TX_TASK: Data Sent: 62
I (4924) TX_TASK: Data Sent: 43
I (4924) TX_TASK: Data Sent: 65
I (4934) TX_TASK: Data Sent: 69
I (4934) TX_TASK: Data Sent: 73
I (4944) TX_TASK: Data Sent: 77
I (4944) TX_TASK: Data Sent: 81
I (4944) TX_TASK: Data Sent: 3
I (4954) TX_TASK: Data Sent: 7
I (4954) TX_TASK: Data Sent: 11
I (4954) TX_TASK: Data Sent: 15
I (4964) TX_TASK: Data Sent: 0
I (4964) TX_TASK: Data Sent: 22
I (4974) TX_TASK: Data Sent: 26
I (4974) TX_TASK: Data Sent: 30
I (4974) TX_TASK: Data Sent: 34
I (4984) TX_TASK: Data Sent: 19
I (4984) TX_TASK: Data Sent: 41
I (4984) TX_TASK: Data Sent: 45
I (4994) TX_TASK: Data Sent: 49
I (4994) TX_TASK: Data Sent: 53
I (5004) TX_TASK: Data Sent: 57
I (5004) TX_TASK: Data Sent: 38
I (5004) TX_TASK: Data Sent: 64
I (5014) TX_TASK: Data Sent: 68
I (5014) TX_TASK: Data Sent: 72
I (5024) TX_TASK: Data Sent: 76
I (5024) TX_TASK: Data Sent: 80
I (5024) TX_TASK: Data Sent: 61
I (5034) TX_TASK: Data Sent: 83
I (5034) TX_TASK: Data Sent: 2
I (5034) TX_TASK: Data Sent: 6
I (5044) TX_TASK: Data Sent: 17
I (5044) TX_TASK: Data Sent: 21
I (5054) TX_TASK: Data Sent: 25
I (5054) TX_TASK: Data Sent: 29
I (5054) TX_TASK: Data Sent: 33
I (5064) TX_TASK: Data Sent: 55
I (5064) TX_TASK: Data Sent: 10
I (5064) TX_TASK: Data Sent: 14
I (5074) TX_TASK: Data Sent: 36
I (5074) TX_TASK: Data Sent: 40
I (5084) TX_TASK: Data Sent: 44
I (5084) TX_TASK: Data Sent: 59
I (5084) TX_TASK: Data Sent: 63
I (5094) TX_TASK: Data Sent: 67
I (5094) TX_TASK: Data Sent: 71
I (5104) TX_TASK: Data Sent: 8
I (5104) TX_TASK: Data Sent: 48
I (5104) TX_TASK: Data Sent: 52
I (5114) TX_TASK: Data Sent: 74
I (5114) TX_TASK: Data Sent: 78
I (5114) TX_TASK: Data Sent: 82
I (5124) TX_TASK: Data Sent: 1
I (5124) TX_TASK: Data Sent: 12
I (5134) TX_TASK: Data Sent: 16
I (5134) TX_TASK: Data Sent: 20
I (5134) TX_TASK: Data Sent: 24
I (5144) TX_TASK: Data Sent: 50
I (5144) TX_TASK: Data Sent: 5
I (5144) TX_TASK: Data Sent: 27
I (5154) TX_TASK: Data Sent: 31
I (5154) TX_TASK: Data Sent: 35
I (5164) TX_TASK: Data Sent: 39
I (5164) TX_TASK: Data Sent: 54
I (5164) TX_TASK: Data Sent: 58
I (5174) TX_TASK: Data Sent: 62
I (5174) TX_TASK: Data Sent: 66
I (5184) TX_TASK: Data Sent: 3
I (5184) TX_TASK: Data Sent: 43
I (5184) TX_TASK: Data Sent: 47
I (5194) TX_TASK: Data Sent: 69
I (5194) TX_TASK: Data Sent: 73
I (5194) TX_TASK: Data Sent: 77
I (5204) TX_TASK: Data Sent: 7
I (5204) TX_TASK: Data Sent: 11
I (5214) TX_TASK: Data Sent: 15
I (5214) TX_TASK: Data Sent: 19
I (5214) TX_TASK: Data Sent: 23
I (5224) TX_TASK: Data Sent: 45
I (5224) TX_TASK: Data Sent: 81
I (5224) TX_TASK: Data Sent: 0
I (5234) TX_TASK: Data Sent: 26
I (5234) TX_TASK: Data Sent: 30
I (5244) TX_TASK: Data Sent: 34
I (5244) TX_TASK: Data Sent: 49
I (5244) TX_TASK: Data Sent: 53
I (5254) TX_TASK: Data Sent: 57
I (5254) TX_TASK: Data Sent: 61
I (5264) TX_TASK: Data Sent: 65
I (5264) TX_TASK: Data Sent: 38
I (5264) TX_TASK: Data Sent: 42
I (5274) TX_TASK: Data Sent: 68
I (5274) TX_TASK: Data Sent: 72
I (5274) TX_TASK: Data Sent: 76
I (5284) TX_TASK: Data Sent: 80
I (5284) TX_TASK: Data Sent: 83
I (5294) TX_TASK: Data Sent: 2
I (5294) TX_TASK: Data Sent: 6
I (5294) TX_TASK: Data Sent: 10
I (5304) TX_TASK: Data Sent: 17
I (5304) TX_TASK: Data Sent: 21
I (5304) TX_TASK: Data Sent: 25
I (5314) TX_TASK: Data Sent: 29
I (5314) TX_TASK: Data Sent: 33
I (5324) TX_TASK: Data Sent: 37
I (5324) TX_TASK: Data Sent: 14
I (5324) TX_TASK: Data Sent: 40
I (5334) TX_TASK: Data Sent: 44
I (5334) TX_TASK: Data Sent: 48
I (5344) TX_TASK: Data Sent: 52
I (5344) TX_TASK:E (5344) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
E (5344) task_wdt: - IDLE (CPU 0)
E (5344) task_wdt: Tasks currently running:
E (5344) task_wdt: CPU 0: twai_receive_ta
E (5344) task_wdt: CPU 1: uart_tx_task
E (5344) task_wdt: Print CPU 0 (current core) backtrace
Backtrace: 0x400D976B:0x3FFB0D50 0x400D98F2:0x3FFB0D70 0x40082AA9:0x3FFB0D90 0x400D5A51:0x3FFBAB70 0x40088F29:0x3FFBABC0
0x400d976b: task_wdt_timeout_handling at C:/Users/shauryachandra/esp/esp-idf/components/esp_system/task_wdt/task_wdt.c:461 (discriminator 3)
0x400d98f2: task_wdt_isr at C:/Users/shauryachandra/esp/esp-idf/components/esp_system/task_wdt/task_wdt.c:585
0x40082aa9: _xt_lowint1 at C:/Users/shauryachandra/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/xtensa_vectors.S:1240
0x400d5a51: Data_Update_Task at C:/Users/shauryachandra/Timer_UART_MultiCore/main/main.c:144 (discriminator 1)
0x40088f29: vPortTaskWrapper at C:/Users/shauryachandra/esp/esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:162
Data Sent: 59
I (5394) TX_TASK: Data Sent: 63
I (5394) TX_TASK: Data Sent: 67
I (5404) TX_TASK: Data Sent: 71
I (5404) TX_TASK: Data Sent: 75
I (5404) TX_TASK: Data Sent: 79
I (5414) TX_TASK: Data Sent: 56
I (5414) TX_TASK: Data Sent: 82
I (5424) TX_TASK: Data Sent: 1
I (5424) TX_TASK: Data Sent: 5
I (5424) TX_TASK: Data Sent: 9
I (5434) TX_TASK: Data Sent: 16
I (5434) TX_TASK: Data Sent: 20
I (5434) TX_TASK: Data Sent: 24
I (5444) TX_TASK: Data Sent: 28
I (5444) TX_TASK: Data Sent: 32
I (5454) TX_TASK: Data Sent: 13
I (5454) TX_TASK: Data Sent: 35
I (5454) TX_TASK: Data Sent: 39
I (5464) TX_TASK: Data Sent: 43
I (5464) TX_TASK: Data Sent: 47
I (5464) TX_TASK: Data Sent: 54
I (5474) TX_TASK: Data Sent: 58
I (5474) TX_TASK: Data Sent: 62
I (5484) TX_TASK: Data Sent: 66
I (5484) TX_TASK: Data Sent: 70
I (5484) TX_TASK: Data Sent: 74
I (5494) TX_TASK: Data Sent: 51
I (5494) TX_TASK: Data Sent: 77
I (5504) TX_TASK: Data Sent: 81
I (5504) TX_TASK: Data Sent: 0
I (5504) TX_TASK: Data Sent: 4
I (5514) TX_TASK: Data Sent: 11
After around every 5 seconds, the watchdog timer is also triggered as seen in the output log.
If someone can please explain what is happening, it will be really helpful.
Thank you!
I am expecting a sequential output of the messages from the queue and if not sequential then at least all data should be captured and sent through UART.
As HS2 and sawdust were pointing out Data_Update_Task()
is probably causing the crashes.
I (5344) TX_TASK:E (5344) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:
E (5344) task_wdt: - IDLE (CPU 0)
Your log clearly indicates that the Task Watch dog
was triggered.
This is by default set to 5s in your SDKconfig. You find this parameter under Component Configs
->ESP System Settings
->Task Watchdog timeoput period
:
Here is how you should implement a task in FreeRTOS according to from the official FreeRTOS documentation)
void vATaskFunction( void *pvParameters )
{
for( ;; )
{
/* Psudeo code showing a task waiting for an event
with a block time. If the event occurs, process it.
If the timeout expires before the event occurs, then
the system may be in an error state, so handle the
error. Here the pseudo code "WaitForEvent()" could
replaced with xQueueReceive(), ulTaskNotifyTake(),
xEventGroupWaitBits(), or any of the other FreeRTOS
communication and synchronisation primitives. */
if( WaitForEvent( EventObject, TimeOut ) == pdPASS )
{
-- Handle event here. --
}
else
{
-- Clear errors, or take actions here. --
}
}
/* As per the first code listing above. */
vTaskDelete( NULL );
}
As HS2 suggested a reasonibly defined vTaskDelay()
is a good start to solve your problem, allowing the Idle-Task to run, so that that the Task Watch Dog is not triggered.