Page 1 of 1

UART interrupt to trigger buffer read on character pattern detection

Posted: Wed Jul 19, 2017 9:43 am
by tristanb293
Hello!

I have adapted the uart example code found here - https://github.com/espressif/esp-idf/bl ... art_test.c in the form shown below.

I am looking to read the UART buffer in ONLY upon the recognition of the 'LF' (line feed) closing character than comes with every NMEA0183 sentence (boat data format). I want to split these up as I want to eventually have them separately packaged for TCP/UDP packaging.

I am wondering how to alter the interfacing between the uart_enable_pattern_det_intr() and the uart_read_bytes() functions. Do I need to configure the way the interrupt works in some way? At the moment the read function is running whenever there is nothing more being added to the buffer (the frequency of the read depending on the baud rate). Just struggling to get a handle on what the ISR is actually doing at the moment and what purpose it it serving in the code.

Any help would be much appreciated!

Thanks Guys :D

Code: Select all

/* Uart 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 <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "driver/uart.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "soc/uart_struct.h"
static const char *TAG = "uart_example";

/**
 * Test code brief
 * This example shows how to configure uart settings and install uart driver.
 *
 * uart_evt_test() is an example that read and write data on UART0, and handler some of the special events.
 * - port: UART0
 * - rx buffer: on
 * - tx buffer: on
 * - flow control: off
 * - event queue: on
 * - pin assignment: txd(default), rxd(default)
*/

#define BUF_SIZE (1024)


QueueHandle_t uart0_queue;
void uart_task(void *pvParameters)
{
    int uart_num = (int) pvParameters;
    uart_event_t event;
    size_t buffered_size;
    uint8_t* dtmp = (uint8_t*) malloc(BUF_SIZE);
    for(;;) {
        //Waiting for UART event.
        if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
            ESP_LOGI(TAG, "uart[%d] event:", 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.
                in this example, we don't process data in event, but read data outside.*/
                case UART_DATA:
                    uart_get_buffered_data_len(uart_num, &buffered_size);
                    ESP_LOGI(TAG, "data, len: %d; buffered len: %d", event.size, buffered_size);
                    break;
                //Event of HW FIFO overflow detected
                case UART_FIFO_OVF:
                    ESP_LOGI(TAG, "hw fifo overflow\n");
                    //If fifo overflow happened, you should consider adding flow control for your application.
                    //We can read data out out the buffer, or directly flush the rx buffer.
                    uart_flush(uart_num);
                    break;
                //Event of UART ring buffer full
                case UART_BUFFER_FULL:
                    ESP_LOGI(TAG, "ring buffer full\n");
                    //If buffer full happened, you should consider encreasing your buffer size
                    //We can read data out out the buffer, or directly flush the rx buffer.
                    uart_flush(uart_num);
                    break;
                //Event of UART RX break detected
                case UART_BREAK:
                    ESP_LOGI(TAG, "uart rx break\n");
                    break;
                //Event of UART parity check error
                case UART_PARITY_ERR:
                    ESP_LOGI(TAG, "uart parity error\n");
                    break;
                //Event of UART frame error
                case UART_FRAME_ERR:
                    ESP_LOGI(TAG, "uart frame error\n");
                    break;
                //UART_PATTERN_DET
                case UART_PATTERN_DET:
                    ESP_LOGI(TAG, "uart pattern detected\n");
                    break;
                //Others
                default:
                    ESP_LOGI(TAG, "uart event type: %d\n", event.type);
                    break;
            }
        }
    }
    free(dtmp);
    dtmp = NULL;
    vTaskDelete(NULL);
}

void uart_evt_test()
{
    int uart_num = UART_NUM_0;
    uart_config_t uart_config = {
       .baud_rate = 4800,
       .data_bits = UART_DATA_8_BITS,
       .parity = UART_PARITY_DISABLE,
       .stop_bits = UART_STOP_BITS_1,
       .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
       .rx_flow_ctrl_thresh = 122,
    };
    //Set UART parameters
    //uart_num = UART_NUM_0 (as defined above)
    //uart_config = array 'uart_config' defined above
    uart_param_config(uart_num, &uart_config);

    //Set UART log level - how much information is recorded - might want to record more data for troubleshooting purposes - stick to the default one here
    //TAG = char('uart_example') as defined at the top
    //ESP_LOG_INFO - a specified log level - 'information messages that describe normal flow of events'
    esp_log_level_set(TAG, ESP_LOG_INFO);

    //Install UART driver, and get the queue.
    uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 10, &uart0_queue, 0);
    //Set UART pins,(-1: default pin, no change.)
    //For UART0, we can just use the default pins.
    //uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    //Set uart pattern detect function - using this for the CRLF detection

        // uart_num: UART port number.
        // pattern_chr: character of the pattern
        // chr_num: number of the character, 8bit value.
        // chr_tout: timeout of the interval between each pattern characters, 24bit value, unit is APB(80Mhz) clock cycle.
        // post_idle: idle time after the last pattern character, 24bit value, unit is APB(80Mhz) clock cycle.
        // pre_idle: idle time before the first pattern character, 24bit value, unit is APB(80Mhz) clock cycle.


    uart_enable_pattern_det_intr(uart_num, 'LF', 1, 10000, 10, 10);

    //Create a task to handler UART event from ISR (interrupt service routine) - this is the first function described
    xTaskCreate(uart_task, "uart_task", 2048, (void*)uart_num, 12, NULL);

    //Process data
    uint8_t* data = (uint8_t*) malloc(BUF_SIZE); // malloc() = memory allocation
    do {
      // BUF_SIZE defined at the top as 1024
        int len = uart_read_bytes(uart_num, data, BUF_SIZE, 100 / portTICK_RATE_MS);
        if(len > 0) {
            ESP_LOGI(TAG, "uart read : %d", len);
            uart_write_bytes(uart_num, (const char*)data, len);
        }
    } while(1);
}

void app_main()
{
    //A uart example with event queue.
    uart_evt_test();
}

Re: UART interrupt to trigger buffer read on character pattern detection

Posted: Tue Jul 25, 2017 6:16 pm
by shamsul
I do have similar issue. Have you figured it out yet?

Re: UART interrupt to trigger buffer read on character pattern detection

Posted: Wed Jul 26, 2017 12:35 pm
by tristanb293
See reply on my most recent query - viewtopic.php?f=2&t=2534 I don't think it's actually implementable live time at the moment, you have to incorporate another buffer