1

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

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

8 Comments

Thank you for your answer! I will read the document! However if I put struct message rx_msg instead of ``struct message *rx_msg``` I get back what I suppose is the address and not the value: with pointer : [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 without pointer : [S] Set channel to 11 h h 18 26 fb 3f [S] Set as Coordinator [S] Start Network h h 18 26 fb 3f h h 18 26 fb 3f
Right, that's because posting to queue with xQueueSend is also incorrect. I updated my answer to fix that as well.
Oh thanks but I receive nothing now T-T len : 19 01 02 10 21 02 10 02 14 2d 02 10 02 10 02 18 02 10 03 0a [S] Set channel to 11 len : 0
Please update your post with the code you have now.
I just edited it! Thanks in advance for your help!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.