Page 1 of 1

UART pattern detect interrupt

Posted: Mon Jul 24, 2017 3:40 pm
by tristanb293
I have a stream of ASCII based NMEA sentences (each ending in 'LF') feeding into one UART and I would like to split them up and print them out to another UART. I am using the uart_enable_pattern_det() function to try and achieve this.

My program is detecting all the 'LF' characters but upon detection the interrupt isn't being called in the way I'd like and the buffer continues to fill. This means I read in more characters after the pattern has been detected. Any ideas where I'm going wrong? Do I need to call either of uart_enable_intterupt_mask() or uart_intr_config() separately?

Code: Select all

#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";

#define BUF_SIZE (200)
uint8_t* RXdata[BUF_SIZE];
int len;
int RX = 0;
QueueHandle_t uart0_queue;
QueueHandle_t EventToRXTX;

void RxToTx(void *pvParameters){
uint8_t* data = (uint8_t*) malloc(BUF_SIZE); // malloc() = memory allocation
uint32_t NewData;
	while(1){
				if(xQueueReceive(EventToRXTX,&NewData,60000/portTICK_RATE_MS)!=pdTRUE){
					printf("\t\tfail to receive queued value");
				}
				else{  // max wait 60s
				ESP_LOGI(TAG, "About To Read")
				int len = uart_read_bytes(UART_NUM_0, data, BUF_SIZE, 100 / portTICK_RATE_MS);
				ESP_LOGI(TAG, "Read Length 2 = %d", len);
				ESP_LOGI(TAG, "Bytes Read")
				uart_write_bytes(UART_NUM_1, (const char*)data, len);
				ESP_LOGI(TAG, "Bytes Written")
				//uart_write_bytes(UART_NUM_1, "Data Received\n", 15);
				}
			}
	RX = 0;
	}

void patternDetect(void *pvParameters)
{
    int uart_num = (int) pvParameters;
    uint32_t TaskTrigger = 1;
    uart_event_t event;
    size_t buffered_size;

    //uint8_t* data = (uint8_t*) malloc(BUF_SIZE); // malloc() = memory allocation

    for(;;) {
        //Waiting for UART event.
        if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) {
            switch(event.type) {
            //UART_PATTERN_DET
				case UART_PATTERN_DET:
					ESP_LOGI(TAG, "Pattern Detected\n");
					xQueueSendToBack(EventToRXTX,&TaskTrigger,1000/portTICK_RATE_MS);
					break;
                default:
                    //ESP_LOGI(TAG, "uart event type: %d\n", event.type);
                    break;
            }
        }
    }
    vTaskDelete(NULL);
}

void app_main()
{
		int uart_num = UART_NUM_0;
	    int uart_num1 = UART_NUM_1;
	    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,
	    };

	    // UART configuration
	    uart_param_config(uart_num, &uart_config);
	    uart_param_config(uart_num1, &uart_config);
	    esp_log_level_set(TAG, ESP_LOG_INFO);
	    uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 10, &uart0_queue, 0);
	    uart_driver_install(uart_num1, BUF_SIZE * 2, BUF_SIZE * 2, 10, NULL, 0);
	    uart_set_pin(uart_num1, 4, 5, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
	    uart_enable_pattern_det_intr(uart_num, 10, 1, 10000, 10, 10);

	    EventToRXTX = xQueueCreate(10, sizeof(uint32_t));

	    // Start Pattern Detect Trigger Task
	    xTaskCreate(patternDetect, "patternDetect", 6000, (void*)uart_num, 12, NULL);

	    // Start Pattern Detect Trigger Task
	    xTaskCreate(RxToTx, "RxToTx", 6000, NULL, 13, NULL);
}

Re: UART pattern detect interrupt

Posted: Tue Jul 25, 2017 9:13 pm
by samsam
You are not going wrong, thats how currently esp-idf UART works. I proposed already some solution for the same problem, I'm not sure when and if will be implemented.
Meanwhile my temp fix is: one extra buffer where you append all the bytes received from the UART. On UART_PATTERN_DET received, scan this buffer for the terminator pattern ('LF' in your case) then process the symbols before the terminator and after delete them and the terminator from the buffer, shifting rest of the bytes waiting in the buffer. There is also a ring buffer available in esp-idf, but is not documented. I gave it a try, but after decide to use simpler solution ...

Re: UART pattern detect interrupt

Posted: Wed Jul 26, 2017 12:36 pm
by tristanb293
Hi samsam, have you got any code I could look at for this implementation you've used?