ESP32 FreeRTOS avoiding deadlock, etc.
Posted: Thu Mar 21, 2024 9:40 pm
Hi,
First time using a RTOS and I was wondering what your suggestion on what synchronization techniques you would use in my situation.
My application is based on the RA6E2 - bt_spp_initiator example. A device is connected to the ESP32 through serial and the ESP connects to a printer over BT classic. There is a task that handles UART RXs and when a specific header byte is sent to the ESP, all device messages need to be transmitted to the printer over bluetooth. This requires repeated calls to esp_spp_write but that would need the parameter 'cong' to equal false for the callback event ESP_SPP_WRITE_EVT. If the parameter isn't false, I would need to wait for the callback event ESP_SPP_CONG_EVT and for its parameter 'cong' to equal false.
I was planning to implement a task just for bluetooth TXs, a mutex that modifies a flag whenever the header byte is received and after it transmit the message to the printer, and group events to signal to the BT TX task when the 'cong' parameter of the callback are false.
Is this approach okay or is there a better method?
code snippet:
First time using a RTOS and I was wondering what your suggestion on what synchronization techniques you would use in my situation.
My application is based on the RA6E2 - bt_spp_initiator example. A device is connected to the ESP32 through serial and the ESP connects to a printer over BT classic. There is a task that handles UART RXs and when a specific header byte is sent to the ESP, all device messages need to be transmitted to the printer over bluetooth. This requires repeated calls to esp_spp_write but that would need the parameter 'cong' to equal false for the callback event ESP_SPP_WRITE_EVT. If the parameter isn't false, I would need to wait for the callback event ESP_SPP_CONG_EVT and for its parameter 'cong' to equal false.
I was planning to implement a task just for bluetooth TXs, a mutex that modifies a flag whenever the header byte is received and after it transmit the message to the printer, and group events to signal to the BT TX task when the 'cong' parameter of the callback are false.
Is this approach okay or is there a better method?
code snippet:
Code: Select all
#define BLUETOOTH_READY_BIT (1 << 0)
SemaphoreHandle_t dataMutex;
static EventGroupHandle_t bluetoothEventGroup;
//uart rx task
static void console_uart_task(void *pvParameters)
{
uart_event_t event;
spp_msg_prs_cb_t *parser = &spp_msg_parser;
spp_msg_parser_reset_state(parser);
spp_msg_parser_register_callback(parser, spp_msg_handler);
for (;;) {
//Waiting for UART event.
if (xQueueReceive(uart_queue, (void * )&event, (TickType_t)portMAX_DELAY)) {
switch (event.type) {
//Event of UART receving data
case UART_DATA:
{
memset(tmp, 0, TMP_BUF_LEN);
memset(tmp_buf, 0, TMP_BUF_LEN);
len = uart_read_bytes(CONSOLE_UART_NUM, tmp_buf, TMP_BUF_LEN, 0);
// printf("len: [%d]\r\n", len);
// if data mode, send all msgs to bt device
if (tmp_buf[len - 3] == 0x00 && tmp_buf[len - 2] == 0x1b && tmp_buf[len - 1] == 0x79)
{
//set flag/semaphore TODO: ---------------------------------------
xSemaphoreTake(dataMutex, portMAX_DELAY);
if (num_connected_dev && num_connected_dev <= MAX_CONNECT_DEV)
{
esp_spp_write(connect_id[num_connected_dev - 1], len, &tmp_buf);
bt_tx_flag = 1;
// printf("%c%c%c", special_msg2[0], special_msg2[1], special_msg2[2]);
}
xSemaphoreGive(dataMutex);
//----------------------------------------------------------------
//RELEVANT EVENTS FROM BT CALLBACK
case ESP_SPP_WRITE_EVT:
if (param->write.cong)
{
//wait for cong event
} else if (bt_tx_flag && !param->write.cong)
{
xEventGroupSetBitsFromISR(bluetoothEventGroup, BLUETOOTH_READY_BIT, &xHigherPriorityTaskWoken);
}
break;
case ESP_SPP_CONG_EVT:
if (param->cong.cong)
{
//wait for .cong = false
} else if (bt_tx_flag && !param->cong.cong)
{
xEventGroupSetBitsFromISR(bluetoothEventGroup, BLUETOOTH_READY_BIT, &xHigherPriorityTaskWoken);
}
break;
//BT task
void bluetooth_tx(void *pvParameters)
{
while (1)
{
EventBits_t bits = xEventGroupWaitBits(bluetoothEventGroup, BLUETOOTH_READY_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
if (bits && BLUETOOTH_READY_BIT)
{
//send over bt to printer
esp_spp_write(connect_id[num_connected_dev - 1], len, &tmp_buf);
xEventGroupClearBits(bluetoothEventGroup, BLUETOOTH_READY_BIT);
xSemaphoreTake(dataMutex, portMAX_DELAY);
bt_tx_flag = 0;
xSemaphoreGive();
}
}
}
Initialization
bluetoothEventGroup = xEventGroupCreate();
dataMutex = xSemaphoreCreateMutex();
xTaskCreate(bluetooth_tx, "bt_tx", 4096, NULL, 8, NULL);