|
28 | 28 |
|
29 | 29 | #include <stdio.h>
|
30 | 30 |
|
| 31 | +#include "uart.h" |
31 | 32 | #include "driver/uart.h"
|
32 | 33 | #include "soc/uart_periph.h"
|
33 | 34 |
|
34 | 35 | #include "py/runtime.h"
|
35 | 36 | #include "py/mphal.h"
|
36 | 37 |
|
37 |
| -STATIC void uart_irq_handler(void *arg); |
| 38 | +static QueueHandle_t uart0_queue; |
| 39 | + |
| 40 | +static void uart_event_task(void *pvParameters); |
| 41 | + |
38 | 42 |
|
39 | 43 | void uart_init(void) {
|
40 |
| - uart_isr_handle_t handle; |
41 |
| - uart_isr_register(UART_NUM_0, uart_irq_handler, NULL, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, &handle); |
42 |
| - uart_enable_rx_intr(UART_NUM_0); |
| 44 | + uart_config_t uartcfg = { |
| 45 | + .baud_rate = 115200, |
| 46 | + .data_bits = UART_DATA_8_BITS, |
| 47 | + .parity = UART_PARITY_DISABLE, |
| 48 | + .stop_bits = UART_STOP_BITS_1, |
| 49 | + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, |
| 50 | + .rx_flow_ctrl_thresh = 0 |
| 51 | + }; |
| 52 | + uart_param_config(UART_NUM_0, &uartcfg); |
| 53 | + |
| 54 | + const uint32_t rxbuf = 260; |
| 55 | + const uint32_t txbuf = 260; |
| 56 | + |
| 57 | + uart_driver_install(UART_NUM_0, rxbuf, txbuf, 20, &uart0_queue, 0); |
| 58 | + |
| 59 | + uart_repl_set_pattern_detect(mp_interrupt_char); |
| 60 | + |
| 61 | + //Create a task to handler UART event from ISR |
| 62 | + xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, 12, NULL); |
| 63 | + |
| 64 | +} |
| 65 | + |
| 66 | +void uart_repl_set_pattern_detect(const char pattern) { |
| 67 | + //Set uart pattern detect function. |
| 68 | + uart_enable_pattern_det_baud_intr(UART_NUM_0, pattern, 1, 9, 0, 0); |
| 69 | + //Reset the pattern queue length to record at most 20 pattern positions. |
| 70 | + uart_pattern_queue_reset(UART_NUM_0, 20); |
43 | 71 | }
|
44 | 72 |
|
45 |
| -// all code executed in ISR must be in IRAM, and any const data must be in DRAM |
46 |
| -STATIC void IRAM_ATTR uart_irq_handler(void *arg) { |
47 |
| - volatile uart_dev_t *uart = &UART0; |
48 |
| - #if CONFIG_IDF_TARGET_ESP32S3 |
49 |
| - uart->int_clr.rxfifo_full_int_clr = 1; |
50 |
| - uart->int_clr.rxfifo_tout_int_clr = 1; |
51 |
| - #else |
52 |
| - uart->int_clr.rxfifo_full = 1; |
53 |
| - uart->int_clr.rxfifo_tout = 1; |
54 |
| - uart->int_clr.frm_err = 1; |
55 |
| - #endif |
56 |
| - while (uart->status.rxfifo_cnt) { |
57 |
| - #if CONFIG_IDF_TARGET_ESP32 |
58 |
| - uint8_t c = uart->fifo.rw_byte; |
59 |
| - #elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 |
60 |
| - uint8_t c = READ_PERI_REG(UART_FIFO_AHB_REG(0)); // UART0 |
61 |
| - #endif |
62 |
| - if (c == mp_interrupt_char) { |
63 |
| - mp_sched_keyboard_interrupt(); |
64 |
| - } else { |
65 |
| - // this is an inline function so will be in IRAM |
66 |
| - ringbuf_put(&stdin_ringbuf, c); |
| 73 | +void uart_event_task(void *pvParameters) |
| 74 | +{ |
| 75 | + uart_event_t event; |
| 76 | + size_t buffered_size; |
| 77 | + // uint8_t* dtmp = (uint8_t*) malloc(RD_BUF_SIZE); |
| 78 | + for(;;) { |
| 79 | + //Waiting for UART event. |
| 80 | + if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) { |
| 81 | + // bzero(dtmp, RD_BUF_SIZE); |
| 82 | + // ESP_LOGI(TAG, "uart[%d] event:", UART_NUM_0); |
| 83 | + switch(event.type) { |
| 84 | + //Event of UART receving data |
| 85 | + /*We'd better handler data event fast, there would be much more data events than |
| 86 | + other types of events. If we take too much time on data event, the queue might |
| 87 | + be full.*/ |
| 88 | + // case UART_DATA: |
| 89 | + // ESP_LOGI(TAG, "[UART DATA]: %d", event.size); |
| 90 | + // uart_read_bytes(UART_NUM_0, dtmp, event.size, portMAX_DELAY); |
| 91 | + // ESP_LOGI(TAG, "[DATA EVT]:"); |
| 92 | + // uart_write_bytes(UART_NUM_0, (const char*) dtmp, event.size); |
| 93 | + // break; |
| 94 | + //Event of HW FIFO overflow detected |
| 95 | + // case UART_FIFO_OVF: |
| 96 | + // ESP_LOGI(TAG, "hw fifo overflow"); |
| 97 | + // // If fifo overflow happened, you should consider adding flow control for your application. |
| 98 | + // // The ISR has already reset the rx FIFO, |
| 99 | + // // As an example, we directly flush the rx buffer here in order to read more data. |
| 100 | + // uart_flush_input(UART_NUM_0); |
| 101 | + // xQueueReset(uart0_queue); |
| 102 | + // break; |
| 103 | + //Event of UART ring buffer full |
| 104 | + // case UART_BUFFER_FULL: |
| 105 | + // ESP_LOGI(TAG, "ring buffer full"); |
| 106 | + // // If buffer full happened, you should consider encreasing your buffer size |
| 107 | + // // As an example, we directly flush the rx buffer here in order to read more data. |
| 108 | + // uart_flush_input(UART_NUM_0); |
| 109 | + // xQueueReset(uart0_queue); |
| 110 | + // break; |
| 111 | + //Event of UART RX break detected |
| 112 | + // case UART_BREAK: |
| 113 | + // ESP_LOGI(TAG, "uart rx break"); |
| 114 | + // break; |
| 115 | + //Event of UART parity check error |
| 116 | + // case UART_PARITY_ERR: |
| 117 | + // ESP_LOGI(TAG, "uart parity error"); |
| 118 | + // break; |
| 119 | + //Event of UART frame error |
| 120 | + // case UART_FRAME_ERR: |
| 121 | + // ESP_LOGI(TAG, "uart frame error"); |
| 122 | + // break; |
| 123 | + //UART_PATTERN_DET |
| 124 | + case UART_PATTERN_DET: |
| 125 | + uart_get_buffered_data_len(UART_NUM_0, &buffered_size); |
| 126 | + int pos = uart_pattern_pop_pos(UART_NUM_0); |
| 127 | + // ESP_LOGI(TAG, "[UART PATTERN DETECTED] pos: %d, buffered size: %d", pos, buffered_size); |
| 128 | + if (pos == -1) { |
| 129 | + // There used to be a UART_PATTERN_DET event, but the pattern position queue is full so that it can not |
| 130 | + // record the position. We should set a larger queue size. |
| 131 | + // As an example, we directly flush the rx buffer here. |
| 132 | + // uart_flush_input(UART_NUM_0); |
| 133 | + } else { |
| 134 | + uint8_t c = 0; |
| 135 | + for (int i = 0; i < pos; i++) { |
| 136 | + uart_read_bytes(UART_NUM_0, &c, 1, 100 / portTICK_PERIOD_MS); |
| 137 | + ringbuf_put(&stdin_ringbuf, c); |
| 138 | + } |
| 139 | + // uint8_t pat[PATTERN_CHR_NUM + 1]; |
| 140 | + // memset(pat, 0, sizeof(pat)); |
| 141 | + uart_read_bytes(UART_NUM_0, &c, 1, 100 / portTICK_PERIOD_MS); |
| 142 | + // ESP_LOGI(TAG, "read data: %s", dtmp); |
| 143 | + // ESP_LOGI(TAG, "read pat : %s", pat); |
| 144 | + } |
| 145 | + mp_sched_keyboard_interrupt(); |
| 146 | + break; |
| 147 | + //Others |
| 148 | + default: |
| 149 | + // ESP_LOGI(TAG, "uart event type: %d", event.type); |
| 150 | + break; |
| 151 | + } |
67 | 152 | }
|
68 | 153 | }
|
| 154 | + // free(dtmp); |
| 155 | + // dtmp = NULL; |
| 156 | + vTaskDelete(NULL); |
69 | 157 | }
|
0 commit comments