xQueue ESP32 can't send two command

0

I'm looking for help because I'm stuck on the problem for a long time. I have at home an ESP32 wrover kit that I have connected in uart to a Zigbee gateway module. I would like to send via uart some commands to the module, for that I put the commands in an xQueue and I get in a thread to send to the uart. In another thread I get the answer via the uart. Everything goes well for the first message and then I have a crash when the second message is read. I think it's because my tx_msg doesn't exist in memory anymore but I can't solve the problem. And I think there is also a syncronization problem. I'm inspired by this example but it doesn't work https://www.freertos.org/a00118.html.

Here is my code, if you have an idea of what I have to modify or if you can explain me how to fix it I thank you !

Code edit:

#include <stdio.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/queue.h>
#include <esp_system.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
//#include <driver/gpio.h>
#include <driver/uart.h>
#include <pthread.h>

typedef unsigned char byte;

// Setup UART buffered IO with event queue
const int uart_buffer_size = 1024;
// Queue used to send and receive complete struct message structures. 
QueueHandle_t uart_queue = NULL;
const int uart_num = UART_NUM_2;

struct message{
    char cmd[128];
    int len;
}tx_msg;

pthread_t zigbee_thread_id;
pthread_t zigbee_send_thread_id;
pthread_t zigbee_receive_thread_id;

/**
 * @brief Configuraiton of UART and set pin that uart use.
 * 
 * @return [int] 0 if is successed
 */
int uart_setup()
{
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
    };
    // Configure UART parameters
    ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config));
    ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, 18, 19, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
    // Install UART driver using an event queue here
    ESP_ERROR_CHECK(uart_driver_install(UART_NUM_2, uart_buffer_size, \
                                        uart_buffer_size, 10, &uart_queue, 0));
    return 0;
}

void translate_hexa_to_string(char* data,int len){

    for (int i=0; i<len;i++)
    {
        if (data[i]==2)
            {
                i++;
                data[i]^=0x10;
                printf("%02x ",data[i]);
                    
            }else if (data[i]==3)
            {
                printf("%02x \n",data[i]);
            }else{
                printf("%02x ",data[i]);
            }
            
        }
        printf("\n");
}

/**
 * @brief [Thread]Send commande to Zigbee module by UART
 * 
 */
void * send_cmd(void * arg){
    struct message rx_msg;
    int err;
    while(1){
        if (xQueueReceive(uart_queue, &rx_msg, portMAX_DELAY) == pdPASS){
            printf("len : %d\n",rx_msg.len);
            for(int i=0;i<rx_msg.len;i++){
                printf("%02x \n",rx_msg.cmd[i]);
            }
            printf("\n");
            err = uart_write_bytes(uart_num, (const char *)rx_msg.cmd, rx_msg.len); // Write data to UART.
            if(err != rx_msg.len){
                printf("Err, not all bytes send : %d/%d\n",err,rx_msg.len);
            }
            vTaskDelay(1000 / portTICK_RATE_MS);
        }
    }
    return NULL;
}

/**
 * @brief [Thread]Read response from UART
 * 
 */
void * read_cmd(void * arg){
    char data[512];
    int length = 0;
    while(1){
        if(uxQueueMessagesWaiting(uart_queue) >= 1){
            ESP_ERROR_CHECK(uart_get_buffered_data_len(uart_num, (size_t*)&length));
            length = uart_read_bytes(uart_num, (uint8_t*)data, length, 100);
            if (length > 0){
                printf("[R] len : %d\n",length);
                translate_hexa_to_string(data,length);
                printf("%c",data[6]);
                if(strcmp(data[6],"00")!=0){
                    printf("[R] Command failed\n");
                }
            }
            ESP_ERROR_CHECK(uart_flush(uart_num));
        }
        vTaskDelay(1000 / portTICK_RATE_MS);
    }
    return NULL;
}

/**
 * @brief Configuration of Zigbee module (channel,type) and start network
 * 
 */
void zigbee_config(){
    struct message *ptx_msg;
    //Set Channel
    sprintf(tx_msg.cmd,"%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",0x01, 0x02, 0x10, 0x21, 0x02, 0x10, 0x02, 0x14, 0x2D, 0x02, 0x10, 0x02, 0x10, 0x02, 0x18, 0x02, 0x10, 0x03);
    tx_msg.len =strlen(tx_msg.cmd);
    ptx_msg = &tx_msg;
    xQueueSend(uart_queue, (void*)ptx_msg, portMAX_DELAY);
    printf("[S] Set channel to 11\n");
    vTaskDelay(100 / portTICK_RATE_MS);/*
    //Set Type
    sprintf(tx_msg.cmd,"%c%c%c%c%c%c%c%c%c%c%c%c\n",0x01, 0x02, 0x10, 0x23, 0x02, 0x10, 0x02, 0x11, 0x22, 0x02, 0x10, 0x03);
    tx_msg.len =strlen(tx_msg.cmd);
    xQueueSend(uart_queue, (void*)&tx_msg, portMAX_DELAY);
    printf("[S] Set as Coordinator\n");
    vTaskDelay(100 / portTICK_RATE_MS);
    //Start Network
    sprintf(tx_msg.cmd,"%c%c%c%c%c%c%c%c%c%c\n",0x01, 0x02, 0x10, 0x24, 0x02, 0x10, 0x02, 0x10, 0x24, 0x03);
    tx_msg.len =strlen(tx_msg.cmd);
    xQueueSend(uart_queue, (void*)&tx_msg, portMAX_DELAY);
    printf("[S] Start Network\n");*/
}

void * ZIGBEE_thread(void * arg){

    /* Create the queue used to send complete struct message structures. */
    uart_queue = xQueueCreate(20, sizeof(struct message));
    if (uart_setup() == -1){
        printf("Err during uart setup\n");
    }
    zigbee_config();
    while(1){
        vTaskDelay(100000 / portTICK_RATE_MS);
    }
    return 0;
    
}

int app_main() {
    
    err += pthread_create(&zigbee_thread_id, NULL, &ZIGBEE_thread, NULL);
    err += pthread_create(&zigbee_send_thread_id, NULL, &send_cmd, NULL);
    err += pthread_create(&zigbee_receive_thread_id, NULL, &read_cmd, NULL);
    // Check if thread is created sucessfuly
    if (err > 0)
    {
        printf("Thread creation failed : %s \n",strerror(err));
        return err;
    }
    pthread_join(zigbee_thread_id, NULL);
    pthread_join(zigbee_send_thread_id, NULL);
    pthread_join(zigbee_receive_thread_id, NULL);
    return 0;
    
}




Result : [S] Set channel to 11 h h 01 02 10 21 02 10 02 14 2d 02 10 02 10 02 18 02 10 03 0a [S] Set as Coordinator [S] Start Network h h Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.

Core 0 register dump: PC : 0x400014fd PS : 0x00060130 A0 : 0x800d34d1 A1 : 0x3ffba280
A2 : 0x00000000 A3 : 0xfffffffc A4 : 0x000000ff A5 : 0x0000ff00
A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x00000000 A9 : 0x3ffba230
A10 : 0x0000000a A11 : 0x3ffae920 A12 : 0x00000013 A13 : 0x00000013 A14 : 0x00000000 A15 : 0x00000013 SAR : 0x00000000 EXCCAUSE: 0x0000001c EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff

Backtrace:0x400014fa:0x3ffba280 0x400d34ce:0x3ffba290 0x400d1bad:0x3ffba2c0 0x40085339:0x3ffba2e0 0x400d34ce: send_cmd at C:\Users\tgasser\Documents\ESP32\template-app\fibonacci-app\build/../main/main.c:97

0x400d1bad: pthread_task_func at C:/Users/tgasser/esp/esp-idf/components/pthread/pthread.c:209 (discriminator 15)

0x40085339: vPortTaskWrapper at C:/Users/tgasser/esp/esp-idf/components/freertos/xtensa/port.c:143

queue
pthreads
esp32
freertos
asked on Stack Overflow Mar 25, 2021 by Sixance • edited Mar 26, 2021 by Sixance

1 Answer

2

You've misunderstood the interface to queues. xQueueReceive wants you to provide the actual memory to store its payload. In function send_cmd you pass to xQueueReceive a pointer to another, uninitialized pointer:

    struct message *rx_msg;
...
        if (xQueueReceive( uart_queue, &rx_msg, portMAX_DELAY) == pdPASS && uart_queue != NULL){
...

Instead you need to create a variable of expected type and pass a pointer to that variable.

    struct message rx_msg;
...
        if (xQueueReceive( uart_queue, &rx_msg, portMAX_DELAY) == pdPASS && uart_queue != NULL){
...

Also posting to queue is incorrect. You're giving it a pointer to pointer to tx_msg, but it wants just the pointer to tx_msg.

Wrong:

xQueueSend(uart_queue, (void*)&ptx_msg, portMAX_DELAY);

Right:

xQueueSend(uart_queue, (void*)ptx_msg, portMAX_DELAY);

As an excellent resource on FreeRTOS, I recommend the book/tutorial on their web site: Mastering the FreeRTOS Real Time Kernel - a Hands On Tutorial Guide.

Side note: please post console output as text, not screenshot.

answered on Stack Overflow Mar 25, 2021 by Tarmo • edited Mar 25, 2021 by Tarmo

User contributions licensed under CC BY-SA 3.0