Search code examples
c++ctaskfreertos

FreeRTOS Task for UART communication


I'm developing a program, which receives commands via UART. My idea was to create a FreeRTOS Task, which runs during the complete program lifecycle and is responsible only for receiving uart messages, interprets them and sends a command into a queue.

I tested this with the built-in Serial functions, before writing my own UART functions.

    /*========== Static Function Implementations ================================*/
    
    static void uartControllerTaskLoop(void *pvParameters)
    {
    
        Serial.begin(115200);
        Serial.println("Start Task");
    
        for (;;)
        {
            unsigned long currentMillis = millis();
    
            if (currentMillis - previousMillis > interval)
            {
                Serial.println("Start Task loop");
                previousMillis = currentMillis;
            }
        }
    }
    
    /*========== Extern Function Implementations ================================*/
    
    extern void uartControllerCreateTask()
    {
        xTaskCreate(uartControllerTaskLoop, "uartControllerTask", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
    }

When running this code I get the following error:

Guru Meditation Error: Core  1 panic'ed (InstrFetchProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x800d0eee  PS      : 0x00050a33  A0      : 0x800d0eee  A1      : 0x3ffb2780
A2      : 0x3ffb27c0  A3      : 0x3ffb9818  A4      : 0x00000158  A5      : 0x00000000
A6      : 0x3ffb89dc  A7      : 0x400d0ef4  A8      : 0x00000000  A9      : 0x800d1209
A10     : 0x3ffb2800  A11     : 0x00000000  A12     : 0x00000000  A13     : 0x3ffb9818
A14     : 0x00000001  A15     : 0x00000000  SAR     : 0x00000000  EXCCAUSE: 0x00000014
EXCVADDR: 0x800d0eec  LBEG    : 0x3ffb9408  LEND    : 0x00000400  LCOUNT  : 0x3ffc155c

When I start the Serial communication with Serial.begin()from outside the Task the program works fine. For me this is a little bit ugly, because I wanted to have all UART dependend stuff within the Task.

What are here the best practices? Leave the setup of the UART outside the Task or find a way to set up the UART within the task?

Thanks!


Solution

  • I switched from the Arduino framwork to the espidf framework.

    Using then the uart driver from espressif let's me install the uart driver within a task.

        #include "driver/uart.h"
        #include "esp_log.h"
        
        static const char *TAG = "example";
        
        static void uartController(void *pvParameters)
        {
            int64_t previousMillis = 0UL;
            int64_t interval = 1000000UL;
            // configure the UART peripheral
            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,
            };
            uart_param_config(UART_NUM_0, &uart_config);
            uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
            uart_driver_install(UART_NUM_0, 256, 0, 0, NULL, 0);
            for (;;)
            {
                int64_t currentMillis = esp_timer_get_time();
                // print messages to the serial monitor
                if (currentMillis - previousMillis > interval)
                {
                    char my_char_array[20];
                    snprintf(my_char_array, sizeof(my_char_array), "%lld", currentMillis);
                    ESP_LOGI(TAG, "%s", my_char_array);
                    ESP_LOGI(TAG, "This is an informational message.");
                    ESP_LOGW(TAG, "This is a warning message.");
                    ESP_LOGE(TAG, "This is an error message.");
                    previousMillis = currentMillis;
                }
                vTaskDelay(1);
            }
        }
        
        void app_main()
        {
            xTaskCreate(uartController, "uartController", 4096, NULL, 1, NULL);
        }