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
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.
User contributions licensed under CC BY-SA 3.0