ESP32 uart event example not able to compile as CPP

paddynoob
Posts: 9
Joined: Tue Sep 24, 2019 10:08 am

ESP32 uart event example not able to compile as CPP

Postby paddynoob » Wed Feb 24, 2021 2:24 pm

Hello,

I use uart events in one of my projects and was able to build it using c, but it fails when using cpp. I tried the same with the official example found here
https://github.com/espressif/esp-idf/tr ... art_events

It compiles well if using it as is. But as soon as I change file extension to cpp, build fails with these errors:

Code: Select all

_main.dir/uart_events_example_main.cpp.obj -c ../main/uart_events_example_main.cpp
../main/uart_events_example_main.cpp: In function 'void uart_event_task(void*)':
../main/uart_events_example_main.cpp:109:17: error: jump to case label [-fpermissive]
                 default:
                 ^~~~~~~
../main/uart_events_example_main.cpp:92:25: note:   crosses initialization of 'int pos'
                     int pos = uart_pattern_pop_pos(EX_UART_NUM);
                         ^~~
../main/uart_events_example_main.cpp:49:19: error: enumeration value 'UART_DATA_BREAK' not handled in switch [-Werror=switch]
             switch(event.type) {
                   ^
../main/uart_events_example_main.cpp:49:19: error: enumeration value 'UART_EVENT_MAX' not handled in switch [-Werror=switch]
../main/uart_events_example_main.cpp: In function 'void app_main()':
../main/uart_events_example_main.cpp:133:5: warning: missing initializer for member 'uart_config_t::rx_flow_ctrl_thresh' [-Wmissing-field-initializers]
     };
     ^
cc1plus: some warnings being treated as errors
ninja: build stopped: subcommand failed.
ninja failed with exit code 1

Even if I add the failing cases, it still fails with the same error. Please note also, a default case is also there. I tried the official example which looks like this:

Code: Select all

/* UART Events Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/uart.h"
#include "esp_log.h"

static const char *TAG = "uart_events";

/**
 * This example shows how to use the UART driver to handle special UART events.
 *
 * It also reads data from UART0 directly, and echoes it to console.
 *
 * - Port: UART0
 * - Receive (Rx) buffer: on
 * - Transmit (Tx) buffer: off
 * - Flow control: off
 * - Event queue: on
 * - Pin assignment: TxD (default), RxD (default)
 */

#define EX_UART_NUM UART_NUM_0
#define PATTERN_CHR_NUM    (3)         /*!< Set the number of consecutive and identical characters received by receiver which defines a UART pattern*/

#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)
static QueueHandle_t uart0_queue;

static void uart_event_task(void *pvParameters)
{
    uart_event_t event;
    size_t buffered_size;
    uint8_t* dtmp = (uint8_t*) malloc(RD_BUF_SIZE);
    for(;;) {
        //Waiting for UART event.
        if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
            bzero(dtmp, RD_BUF_SIZE);
            ESP_LOGI(TAG, "uart[%d] event:", EX_UART_NUM);
            switch(event.type) {
                //Event of UART receving data
                /*We'd better handler data event fast, there would be much more data events than
                other types of events. If we take too much time on data event, the queue might
                be full.*/
                case UART_DATA:
                    ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
                    uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY);
                    ESP_LOGI(TAG, "[DATA EVT]:");
                    uart_write_bytes(EX_UART_NUM, (const char*) dtmp, event.size);
                    break;
                //Event of HW FIFO overflow detected
                case UART_FIFO_OVF:
                    ESP_LOGI(TAG, "hw fifo overflow");
                    // If fifo overflow happened, you should consider adding flow control for your application.
                    // The ISR has already reset the rx FIFO,
                    // As an example, we directly flush the rx buffer here in order to read more data.
                    uart_flush_input(EX_UART_NUM);
                    xQueueReset(uart0_queue);
                    break;
                //Event of UART ring buffer full
                case UART_BUFFER_FULL:
                    ESP_LOGI(TAG, "ring buffer full");
                    // If buffer full happened, you should consider encreasing your buffer size
                    // As an example, we directly flush the rx buffer here in order to read more data.
                    uart_flush_input(EX_UART_NUM);
                    xQueueReset(uart0_queue);
                    break;
                //Event of UART RX break detected
                case UART_BREAK:
                    ESP_LOGI(TAG, "uart rx break");
                    break;
                //Event of UART parity check error
                case UART_PARITY_ERR:
                    ESP_LOGI(TAG, "uart parity error");
                    break;
                //Event of UART frame error
                case UART_FRAME_ERR:
                    ESP_LOGI(TAG, "uart frame error");
                    break;
                //UART_PATTERN_DET
                case UART_PATTERN_DET:
                    uart_get_buffered_data_len(EX_UART_NUM, &buffered_size);
                    int pos = uart_pattern_pop_pos(EX_UART_NUM);
                    ESP_LOGI(TAG, "[UART PATTERN DETECTED] pos: %d, buffered size: %d", pos, buffered_size);
                    if (pos == -1) {
                        // There used to be a UART_PATTERN_DET event, but the pattern position queue is full so that it can not
                        // record the position. We should set a larger queue size.
                        // As an example, we directly flush the rx buffer here.
                        uart_flush_input(EX_UART_NUM);
                    } else {
                        uart_read_bytes(EX_UART_NUM, dtmp, pos, 100 / portTICK_PERIOD_MS);
                        uint8_t pat[PATTERN_CHR_NUM + 1];
                        memset(pat, 0, sizeof(pat));
                        uart_read_bytes(EX_UART_NUM, pat, PATTERN_CHR_NUM, 100 / portTICK_PERIOD_MS);
                        ESP_LOGI(TAG, "read data: %s", dtmp);
                        ESP_LOGI(TAG, "read pat : %s", pat);
                    }
                    break;
                //Others
                default:
                    ESP_LOGI(TAG, "uart event type: %d", event.type);
                    break;
            }
        }
    }
    free(dtmp);
    dtmp = NULL;
    vTaskDelete(NULL);
}

void app_main(void)
{
    esp_log_level_set(TAG, ESP_LOG_INFO);

    /* Configure parameters of an UART driver,
     * communication pins and install the driver */
    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,
        .source_clk = UART_SCLK_APB,
    };
    //Install UART driver, and get the queue.
    uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0);
    uart_param_config(EX_UART_NUM, &uart_config);

    //Set UART log level
    esp_log_level_set(TAG, ESP_LOG_INFO);
    //Set UART pins (using UART0 default pins ie no changes.)
    uart_set_pin(EX_UART_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    //Set uart pattern detect function.
    uart_enable_pattern_det_baud_intr(EX_UART_NUM, '+', PATTERN_CHR_NUM, 9, 0, 0);
    //Reset the pattern queue length to record at most 20 pattern positions.
    uart_pattern_queue_reset(EX_UART_NUM, 20);

    //Create a task to handler UART event from ISR
    xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, 12, NULL);
}

and I build it simply with

Code: Select all

idf.py build
This version I'm using

ESP-IDF v4.3-dev-2586-g526f68239

PeterR
Posts: 621
Joined: Mon Jun 04, 2018 2:47 pm

Re: ESP32 uart event example not able to compile as CPP

Postby PeterR » Wed Feb 24, 2021 5:40 pm

C++ is not C! C++17 even removes trigraths although I think ESP toolchain is C++11/14 ATM. Won't be long though.
Also you might have different compiler flags in your make file from C to CPP. I often do.

I would say that C++ warnings and errors are there for a reason. Code developed in C might miss the warnings/errors now caught by C++. The C compiler is just not thinking the modern way.
You have some choices; (1) Disable the permissive warning (-fpermissive) and other warning to error flags, (2) Fix the warnings.
I would suggest (2) and as you make the changes consider why the change is an improvement.
Learn a lot that way.
PS I -Wall and fix all. ESP seem (rightly) going the same way. A warning is telling you about an error you have not found/added yet. Review and argue for acceptance takes longer than fixing and still risks error.
& I also believe that IDF CAN should be fixed.

paddynoob
Posts: 9
Joined: Tue Sep 24, 2019 10:08 am

Re: ESP32 uart event example not able to compile as CPP

Postby paddynoob » Wed Feb 24, 2021 5:57 pm

Hello

thank you for your answer. I know c++ in not C and there are reasons I want to use c++ instead.
But I don't understand why there are warnings related to
enumeratuon value not handled

They occur even if I add them and even if there is a default case. From my knowledge this should work.

PeterR
Posts: 621
Joined: Mon Jun 04, 2018 2:47 pm

Re: ESP32 uart event example not able to compile as CPP

Postby PeterR » Thu Feb 25, 2021 8:15 pm

Cool,
I did not see 'UART_EVENT_MAX' in your code but then 'default' should cover it.
Sometimes the build system breaks.
Delete '/build' and rebuild all again. An idf config update should also force a rebuild all.
If not cut and paste the switch code and post a MVE.

PS
Go C++. It makes sense. That said all my low level drivers are C, portability & force of habit I guess. Application is C++ all day long.
& I also believe that IDF CAN should be fixed.

Who is online

Users browsing this forum: Google [Bot] and 97 guests