From 288f4f63f0a108003e29c3a041b86de3bb64976a Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Mon, 24 Oct 2016 09:17:10 +0800 Subject: [PATCH 01/12] Add UART driver 1. add uart.h and uart.c 2. add ESP_ERR_TIMEOUT in esp_err.h 3. add UART AHB FIFO address in uart_reg.h 4. modify xRingbufferSendFromISR return value in ringbuffer.c 5. add #include "soc/gpio_sig_map.h" in gpio.h --- components/driver/include/driver/gpio.h | 1 + components/driver/include/driver/uart.h | 688 +++++++++++++++++ components/driver/uart.c | 938 ++++++++++++++++++++++++ components/esp32/include/esp_err.h | 1 + components/esp32/include/soc/uart_reg.h | 4 +- components/freertos/ringbuf.c | 3 +- 6 files changed, 1632 insertions(+), 3 deletions(-) create mode 100644 components/driver/include/driver/uart.h create mode 100644 components/driver/uart.c diff --git a/components/driver/include/driver/gpio.h b/components/driver/include/driver/gpio.h index 9b47c88e6..c821b640e 100644 --- a/components/driver/include/driver/gpio.h +++ b/components/driver/include/driver/gpio.h @@ -20,6 +20,7 @@ #include "soc/gpio_struct.h" #include "soc/rtc_io_reg.h" #include "soc/io_mux_reg.h" +#include "soc/gpio_sig_map.h" #include "rom/gpio.h" #include "esp_attr.h" diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h new file mode 100644 index 000000000..cd0725d2c --- /dev/null +++ b/components/driver/include/driver/uart.h @@ -0,0 +1,688 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _DRIVER_UART_H_ +#define _DRIVER_UART_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include "soc/uart_reg.h" +#include "soc/uart_struct.h" +#include "esp_err.h" +#include "driver/periph_ctrl.h" +#include + +extern const char* UART_TAG; +#define UART_FIFO_LEN (128) //Do Not Change it +#define UART_INTR_MASK 0x1ff +#define UART_LINE_INV_MASK (0x3f << 19) + +typedef enum { + UART_DATA_5_BITS = 0x0, //word length: 5bits + UART_DATA_6_BITS = 0x1, //word length: 6bits + UART_DATA_7_BITS = 0x2, //word length: 7bits + UART_DATA_8_BITS = 0x3, //word length: 8bits + UART_DATA_MAX_BITS = 0X4, +} uart_word_length_t; + +typedef enum { + UART_STOP_BITS_1 = 0x1, //stop bit: 1bit + UART_STOP_BITS_1_5 = 0x2, //stop bit: 1.5bits + UART_STOP_BITS_2 = 0x3, //stop bit: 2bits + UART_STOP_BITS_MAX = 0x4, +} uart_stop_bits_t; + +typedef enum { + UART_NUM_0 = 0x0, //base address 0x3ff40000 + UART_NUM_1 = 0x1, //base address 0x3ff50000 + UART_NUM_2 = 0x2, //base address 0x3ff6E000 + UART_NUM_MAX, +} uart_port_t; + +typedef enum { + UART_PARITY_DISABLE = 0x0, //Disable UART parity + UART_PARITY_EVEN = 0x10, //Enable UART even parity + UART_PARITY_ODD = 0x11 //Enable UART odd parity +} uart_parity_t; + +typedef enum { + UART_BITRATE_300 = 300, + UART_BITRATE_600 = 600, + UART_BITRATE_1200 = 1200, + UART_BITRATE_2400 = 2400, + UART_BITRATE_4800 = 4800, + UART_BITRATE_9600 = 9600, + UART_BITRATE_19200 = 19200, + UART_BITRATE_38400 = 38400, + UART_BITRATE_57600 = 57600, + UART_BITRATE_74880 = 74880, + UART_BITRATE_115200 = 115200, + UART_BITRATE_230400 = 230400, + UART_BITRATE_460800 = 460800, + UART_BITRATE_921600 = 921600, + UART_BITRATE_1843200 = 1843200, + UART_BITRATE_3686400 = 3686400, + UART_BITRATE_MAX = 5000000, +} uart_baudrate_t; //you can set any rate you need in this range + +typedef enum { + UART_HW_FLOWCTRL_DISABLE = 0x0, //disable hardware flow control + UART_HW_FLOWCTRL_RTS = 0x1, //enable RX hardware flow control (rts) + UART_HW_FLOWCTRL_CTS = 0x2, //enable TX hardware flow control (cts) + UART_HW_FLOWCTRL_CTS_RTS = 0x3, //enable hardware flow control + UART_HW_FLOWCTRL_MAX = 0x4, +} uart_hw_flowcontrol_t; + +typedef enum { + UART_INVERSE_DISABLE = 0x0, //Disable UART wire output inverse + UART_INVERSE_RXD = (uint32_t)UART_RXD_INV_M, //UART RXD input inverse + UART_INVERSE_CTS = (uint32_t)UART_CTS_INV_M, //UART CTS input inverse + UART_INVERSE_TXD = (uint32_t)UART_TXD_INV_M, //UART TXD output inverse + UART_INVERSE_RTS = (uint32_t)UART_RTS_INV_M, //UART RTS output inverse +} uart_inverse_t; + +typedef struct { + uart_baudrate_t baud_rate; //UART baudrate + uart_word_length_t data_bits; //UART byte size + uart_parity_t parity; //UART parity mode + uart_stop_bits_t stop_bits; //UART stop bits + uart_hw_flowcontrol_t flow_ctrl; //UART hw flow control mode(cts/rts) + uint8_t rx_flow_ctrl_thresh ; //UART hw RTS threshold +} uart_config_t; + +typedef struct { + uint32_t intr_enable_mask; //UART interrupt enable mask, choose from UART_XXXX_INT_ENA_M under UART_INT_ENA_REG(i), connect with bit-or operator + uint8_t rx_timeout_thresh; //UART timeout interrupt threshold(unit: time of sending one byte) + uint8_t txfifo_empty_intr_thresh; //UART TX empty interrupt threshold. + uint8_t rxfifo_full_thresh; //UART RX full interrupt threshold. +} uart_intr_config_t; + + +typedef enum { + UART_DATA, + UART_BREAK, + UART_BUFFER_FULL, + UART_FIFO_OVF, + UART_FRAME_ERR, + UART_PARITY_ERR, + UART_EVENT_MAX, +} uart_event_type_t; + +typedef struct { + uart_event_type_t type; + union { + struct { + size_t size; + } data; + + }; +} uart_event_t; + + + +/** + * @brief Set UART data bits. + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_word_length_t data_bit : UART data bits + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit); + +/** + * @brief Get UART data bits. + * + * @param uart_port_t uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @return ESP_FAIL (-1) : Parameter error + * UART_DATA_5_BITS (0): UART word length: 5 bits. + * UART_DATA_6_BITS (1): UART word length: 6 bits. + * UART_DATA_7_BITS (2): UART word length: 7 bits. + * UART_DATA_8_BITS (3): UART word length: 8 bits. + */ +int uart_get_word_length(uart_port_t uart_num); + +/** + * @brief Set UART stop bits. + * + * @param uart_port_t uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_stop_bits_t bit_num : UART stop bits + * + * @return ESP_OK : Success + * ESP_FAIL: Fail + */ +esp_err_t uart_set_stop_bits(uart_port_t uart_no, uart_stop_bits_t bit_num); + +/** + * @brief Set UART stop bits. + * + * @param uart_port_t uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @return ESP_FAIL (-1): Parameter error + * UART_STOP_BITS_1 (1): 1 stop bit + * UART_STOP_BITS_1_5 (2): 1.5 stop bits + * UART_STOP_BITS_1 (3): 2 stop bits + */ +int uart_get_stop_bits(uart_port_t uart_num); + +/** + * @brief Set UART parity. + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_parity_t parity_mode : the enum of uart parity configuration + * + * @return null + */ +esp_err_t uart_set_parity(uart_port_t uart_no, uart_parity_t parity_mode); + +/** + * @brief Get UART parity mode. + * + * @param uart_port_t uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @return ESP_FAIL (-1): Parameter error + * UART_PARITY_ODD (0x11): Odd parity check mode + * UART_PARITY_EVEN (0x10): Even parity check mode + * UART_PARITY_DISABLE(0x0) : parity check disabled + * + */ +int uart_get_parity(uart_port_t uart_num); + +/** + * @brief Set UART baud rate. + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uint32_t baud_rate : UART baud-rate, we can choose one from uart_baudrate_t, or set a value. + * + * @return null + */ +esp_err_t uart_set_baudrate(uart_port_t uart_no, uint32_t baud_rate); + +/** + * @brief Get UART bit-rate. + * + * @param uart_port_t uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @return ESP_FAIL(-1): Parameter error + * Others (>0): UART baud-rate + * + */ +int uart_get_baudrate(uart_port_t uart_num); + +/** + * @brief Set UART line inverse mode + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uint32_t inverse_mask : Choose the wires that need to be inversed + * (Should be chosen from uart_inverse_t, combine with OR-OPERATION) + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_set_line_inverse(uart_port_t uart_no, uint32_t inverse_mask) ; + + +/** + * @brief Set hardware flow control. + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_hw_flowcontrol_t flow_ctrl : Hardware flow control mode + * @param uint8_t rx_thresh : Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN) + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_no, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh); + +/** + * @brief Get hardware flow control mode + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @return ESP_FAIL (-1): Parameter error + * UART_HW_FLOWCTRL_DISABLE (0): UART hw flow control disabled + * UART_HW_FLOWCTRL_RTS (1): UART RX flow control enabled + * UART_HW_FLOWCTRL_CTS (2): UART TX flow control enabled + * UART_HW_FLOWCTRL_CTS_RTS (3): UART TX/RX flow control enabled + */ +int uart_get_hw_flow_ctrl(uart_port_t uart_num); + +/** + * @brief Clear UART interrupt status + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uint32_t clr_mask : Bit mask of the status that to be cleared. + * enable_mask should be chosen from the fields of register UART_INT_CLR_REG + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask); + +/** + * @brief Set UART interrupt enable + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uint32_t enable_mask : Bit mask of the enable bits. + * enable_mask should be chosen from the fields of register UART_INT_ENA_REG + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask); + +/** + * @brief Clear UART interrupt enable bits + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uint32_t disable_mask : Bit mask of the disable bits. + * Disable_mask should be chosen from the fields of register UART_INT_ENA_REG + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask); + + +/** + * @brief Enable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_enable_rx_intr(uart_port_t uart_num); + +/** + * @brief Disable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_disable_rx_intr(uart_port_t uart_num); + +/** + * @brief Disable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_disable_tx_intr(uart_port_t uart_num); + +/** + * @brief Enable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param int enable : 1: enable; 0: disable + * @param int thresh : Threshold of TX interrupt, 0 ~ UART_FIFO_LEN + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh); + +/** +* @brief register UART interrupt handler(ISR). + * UART ISR handler will be attached to the same CPU core that this function is running on. + * Users should know that which CPU is running and then pick a INUM that is not used by system. + * We can find the information of INUM and interrupt level in soc.h. + * + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uint8_t uart_intr_num : UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details + * @param void (* fn)(void* ) : Interrupt handler function. + * Note that the handler function MUST be defined with attribution of "IRAM_ATTR" for now. + * @param void * arg : parameter for handler function + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (*fn)(void*), void * arg); + +/** + * @brief Set UART pin number + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param tx_io_num : UART TX pin GPIO number + * @param rx_io_num : UART RX pin GPIO number + * @param rts_io_num : UART RTS pin GPIO number + * @param cts_io_num : UART CTS pin GPIO number + * + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num); + +/** + * @brief UART set RTS level (before inverse) + * UART rx hardware flow control should not be set. + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param int level : 1: RTS output low(active) + * 0: RTS output high(block) + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_set_rts(uart_port_t uart_num, int level); + +/** + * @brief UART set DTR level (before inverse) + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param int level : 1: DTR output low + * 0: DTR output high + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_set_dtr(uart_port_t uart_num, int level); + +/** +* @brief UART parameter configure + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_config_t *uart_config: UART parameter settings + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_param_config(uart_port_t uart_num, uart_config_t *uart_config); + +/** +* @brief UART interrupt configure + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_intr_config_t *p_intr_conf: UART interrupt settings + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_intr_config(uart_port_t uart_num, uart_intr_config_t *p_intr_conf); + +/** + * @brief Install UART driver. + * UART ISR handler will be attached to the same CPU core that this function is running on. + * Users should know that which CPU is running and then pick a INUM that is not used by system. + * We can find the information of INUM and interrupt level in soc.h. + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param int buffer_size : UART ring buffer size + * @param int queue_size : UART event queue size/depth. + * @param int uart_intr_num : UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_driver_install(uart_port_t uart_num, int buffer_size, int queue_size, int uart_intr_num, void* uart_queue); + +/** + * @brief Uninstall UART driver. + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_driver_delete(uart_port_t uart_num); + +/** + * @brief Wait UART TX FIFO empty + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param TickType_t ticks_to_wait: Timeout, count in RTOS ticks + * + * @return ESP_OK : Success + * ESP_ERR_TIMEOUT: Timeout + */ +esp_err_t uart_wait_tx_fifo_empty(uart_port_t uart_num, TickType_t ticks_to_wait); + +/** + * @brief Send data to the UART port from a given buffer and length, + * This function will not wait for the space in TX FIFO, just fill the TX FIFO and return when the FIFO is full. + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param char* buffer : data buffer address + * @param uint32_t len : data length to send + * + * @return The number of data that pushed to the TX FIFO + */ +int uart_tx_chars(uart_port_t uart_no, char* buffer, uint32_t len); + +/** + * @brief Send data to the UART port from a given buffer and length, + * This function will not return until all the data have been sent out, or at least pushed into TX FIFO. + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param char* src : data buffer address + * @param size_t size : data length to send + * + * @return The number of data that sent out. + */ +int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size); + +/** + * @brief Send data to the UART port from a given buffer and length, + * This function will not return until all the data and the break signal have been sent out. + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param char* src : data buffer address + * @param size_t size : data length to send + * @param int brk_len : break signal length (unit: one bit's time@current_baudrate) + * + * @return The number of data that sent out. + */ +int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len); + +/** +* @brief UART read one char + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param TickType_t ticks_to_wait : ticks to wait. + * + * @return -1 : Error + * Others : return a char data from uart fifo. + */ +int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait); + +/** +* @brief UART read bytes from UART buffer + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uint8_t* buf : pointer to the buffer. + * @param uint32_t length : data length + * @param TickType_t ticks_to_wait: timeout time( FreeRTOS ti c + * + * @return -1 : Error + * Others : return a char data from uart fifo. + */ +int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait); + +/** + * @brief UART ring buffer flush + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error + */ +esp_err_t uart_flush(uart_port_t uart_num); + +/** + * @brief Set the serial output port for ets_printf function, not effective for ESP_LOGX macro. + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @return ESP_OK : Success + * ESP_FAIL: Parameter error, or UART driver not installed. + */ +esp_err_t uart_set_print_port(uart_port_t uart_no); + +/** + * @brief Get the current serial port for ets_printf function + * + * + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @return null + */ +int uart_get_print_port(); + +/***************************EXAMPLE********************************** + * + * + * ----------------EXAMPLE OF UART SETTING --------------------- + * //1. Setup UART + * #include "freertos/queue.h" + * #define UART_INTR_NUM 17 //choose one interrupt number from soc.h + * //a. Set UART parameter + * int uart_num = 0; //uart port number + * uart_config_t uart_config = { + * .baud_rate = UART_BITRATE_115200, //baudrate + * .data_bits = UART_DATA_8_BITS, //data bit mode + * .parity = UART_PARITY_DISABLE, //parity mode + * .stop_bits = UART_STOP_BITS_1, //stop bit mode + * .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, //hardware flow control(cts/rts) + * .rx_flow_ctrl_thresh = 120, //flow control threshold + * }; + * uart_param_config(uart_num, &uart_config); + * //b1. Setup UART driver(with UART queue) + * QueueHandle_t uart_queue; + * uart_driver_install(uart_num, 1024 * 2, 10, UART_INTR_NUM, &uart_queue);//parameters here are just an example + * //b2. Setup UART driver(without UART queue) + * uart_driver_install(uart_num, 1024 * 2, 10, UART_INTR_NUM, NULL); //parameters here are just an example + * + *-----------------------------------------------------------------------------* + * //2. Set UART pin + * uart_set_pin(uart_num, -1, -1, 15, 13); //set UART pin, not needed if use default pins. + * + *-----------------------------------------------------------------------------* + * //3. Read data from UART. + * uint8_t data[128]; + * int length = 0; + * length = uart_read_bytes(uart_num, data, sizeof(data), 100); + * + *-----------------------------------------------------------------------------* + * //4. Write data to UART. + * char* test_str = "This is a test string.\n" + * uart_tx_all_chars(uart_num, (const char*)test_str, strlen(test_str)); + * + *-----------------------------------------------------------------------------* + * //5. Write data to UART, end with a break signal. + * uart_tx_all_chars_with_break(0, "test break\n",strlen("test break\n"), 100); + * + *-----------------------------------------------------------------------------* + * + * //6. an example of echo test with hardware flow control on UART1 + * void uart_loop_back_test() + * { + * int uart_num = 1; + * 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_CTS_RTS, + * .rx_flow_ctrl_thresh = 122, + * }; + * uart_param_config(uart_num, &uart_config); //Config UART1 parameters + * uart_set_pin(uart_num, 16, 17, 18, 19); //Set UART1 pins(TX: IO16, RX: IO17, RTS: IO18, CTS: IO19) + * esp_log_level_set(UART_TAG, ESP_LOG_ERROR); //Set UART log level + * uart_driver_install(uart_num, 1024 * 2, 10, 17, NULL); //Install UART driver( We don't need an event queue here) + * uint8_t data[1000]; + * while(1) { + * int len = uart_read_bytes(uart_num, data, sizeof(data), 10); //Read data from UART + * uart_tx_all_chars(uart_num, (const char*)data, len); //Write data back to UART + * } + * } + * + *-----------------------------------------------------------------------------* + * //7. An example of using UART event queue on UART0. + * + * #include "freertos/queue.h" + * QueueHandle_t uart0_queue; //A queue to handle UART event. + * void uart_task(void *pvParameters) + * { + * int uart_num = (int)pvParameters; + * uart_event_t event; + * uint8_t dtmp[1000]; + * for(;;) { + * if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) { //Waiting for UART event. + * ESP_LOGI(UART_TAG, "uart[%d] event:", uart_num); + * switch(event.type) { + * case UART_DATA: //Event of UART receving data + * ESP_LOGI(UART_TAG,"data, len: %d\n", event.data.size); + * int len = uart_read_bytes(uart_num, dtmp, event.data.size, 10); + * ESP_LOGI(UART_TAG, "uart read: %d\n", len); + * break; + * case UART_FIFO_OVF: //Event of HW FIFO overflow detected + * ESP_LOGI(UART_TAG, "hw fifo overflow\n"); + * while(1); + * break; + * case UART_BUFFER_FULL: //Event of UART ring buffer full + * ESP_LOGI(UART_TAG, "ring buffer full\n"); + * break; + * case UART_BREAK: + * ESP_LOGI(UART_TAG, "uart rx break\n"); //Event of UART RX break detected + * break; + * case UART_PARITY_ERR: //Event of UART parity check error + * ESP_LOGI(UART_TAG, "uart parity error\n"); + * break; + * case UART_FRAME_ERR: //Event of UART frame error + * ESP_LOGI(UART_TAG, "uart frame error\n"); + * break; + * default: //Others + * ESP_LOGI(UART_TAG, "uart event type: %d\n", event.type); + * break; + * } + * } + * } + * vTaskDelete(NULL); + * } + * + * void uart_queue_test() + * { + * int uart_num = 0; + * 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, + * .rx_flow_ctrl_thresh = 122, + * }; + * uart_param_config(uart_num, &uart_config); //Set UART parameters + * uart_set_pin(uart_num, -1, -1, 15, 13); //Set UART pins,(-1: default pin, no change.) + * esp_log_level_set(UART_TAG, ESP_LOG_INFO); //Set UART log level + * uart_driver_install(uart_num, 1024 * 2, 10, 17, &uart0_queue); //Install UART driver, and get the queue. + * xTaskCreate(uart_task, "uTask", 2048*8, (void*)uart_num, 10, NULL); //Create a task to handler UART event from ISR + * } + * + * + ***************************END OF EXAMPLE**********************************/ + +#ifdef __cplusplus +} +#endif + +#endif /*_DRIVER_UART_H_*/ diff --git a/components/driver/uart.c b/components/driver/uart.c new file mode 100644 index 000000000..157e0c49c --- /dev/null +++ b/components/driver/uart.c @@ -0,0 +1,938 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include "esp_types.h" +#include "esp_attr.h" +#include "esp_intr.h" +#include "esp_log.h" +#include "malloc.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/xtensa_api.h" +#include "freertos/task.h" +#include "freertos/ringbuf.h" +#include "soc/dport_reg.h" +#include "rom/ets_sys.h" +#include "soc/uart_struct.h" +#include "driver/uart.h" +#include "driver/gpio.h" +#include "soc/uart_struct.h" + +const char* UART_TAG = "UART"; +#define UART_CHECK(a, str) if (!(a)) { \ + ESP_LOGE(UART_TAG,"%s:%d (%s):%s\n", __FILE__, __LINE__, __FUNCTION__, str); \ + return ESP_FAIL; \ + } +#define DEFAULT_EMPTY_THRESH 10 +#define DEFAULT_FULL_THRESH 120 +#define DEFAULT_TOUT_THRESH 10 +#define UART_ENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux) +#define UART_EXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux) +#define UART_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux) +#define UART_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) + +typedef struct { + uart_port_t uart_num; + SemaphoreHandle_t tx_fifo_sem; + SemaphoreHandle_t tx_mutex; + SemaphoreHandle_t tx_done_sem; + SemaphoreHandle_t tx_brk_sem; + SemaphoreHandle_t rx_sem; + QueueHandle_t xQueueUart; + int queue_size; + int intr_num; + RingbufHandle_t ring_buffer; + bool buffer_full_flg; + bool tx_waiting; + int cur_remain; + uint8_t* rd_ptr; + uint8_t* head_ptr; + uint8_t data_buf[UART_FIFO_LEN]; + uint8_t data_len; +} uart_obj_t; + +static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0}; +static uart_dev_t* UART[UART_NUM_MAX] = {&UART0, &UART1, &UART2}; +static portMUX_TYPE uart_spinlock[UART_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED}; + +//Fill UART tx_fifo and return a number, +//This function by itself is not thread-safe, always call from within a muxed section. +static int uart_fill_fifo(uart_port_t uart_num, char* buffer, uint32_t len) +{ + uint8_t i = 0; + uint8_t tx_fifo_cnt = UART[uart_num]->status.txfifo_cnt; + uint8_t tx_remain_fifo_cnt = (UART_FIFO_LEN - tx_fifo_cnt); + uint8_t copy_cnt = (len >= tx_remain_fifo_cnt ? tx_remain_fifo_cnt : len); + for(i = 0; i < copy_cnt; i++) { + WRITE_PERI_REG(UART_FIFO_AHB_REG(uart_num), buffer[i]); + } + return copy_cnt; +} + +esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((data_bit < UART_DATA_MAX_BITS), "data bit error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + UART[uart_num]->conf0.bit_num = data_bit; + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +int uart_get_word_length(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + return UART[uart_num]->conf0.bit_num; +} + +esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bit) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((stop_bit < UART_STOP_BITS_MAX), "stop bit error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + UART[uart_num]->conf0.stop_bit_num = stop_bit; + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +int uart_get_stop_bits(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + return UART[uart_num]->conf0.stop_bit_num; +} + +esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + UART[uart_num]->conf0.parity = parity_mode & 0x1; + UART[uart_num]->conf0.parity_en = (parity_mode >> 1) & 0x1; + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +int uart_get_parity(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + int val = UART[uart_num]->conf0.val; + if(val & UART_PARITY_EN_M) { + if(val & UART_PARITY_M) { + return UART_PARITY_ODD; + } else { + return UART_PARITY_EVEN; + } + } else { + return UART_PARITY_DISABLE; + } +} + +esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((baud_rate < UART_BITRATE_MAX), "baud_rate error"); + uint32_t clk_div = (((UART_CLK_FREQ) << 4) / baud_rate); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + UART[uart_num]->clk_div.div_int = clk_div >> 4; + UART[uart_num]->clk_div.div_frag = clk_div & 0xf; + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +int uart_get_baudrate(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + uint32_t clk_div = (UART[uart_num]->clk_div.div_int << 4) | UART[uart_num]->clk_div.div_frag; + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + uint32_t baudrate = ((UART_CLK_FREQ) << 4) / clk_div; + return baudrate; +} + +esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((((inverse_mask & UART_LINE_INV_MASK) == 0) && (inverse_mask != 0)), "inverse_mask error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + CLEAR_PERI_REG_MASK(UART_CONF0_REG(uart_num), UART_LINE_INV_MASK); + SET_PERI_REG_MASK(UART_CONF0_REG(uart_num), inverse_mask); + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +//only when UART_HW_FLOWCTRL_RTS is set , will the rx_thresh value be set. +esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((rx_thresh < UART_FIFO_LEN), "rx flow thresh error"); + UART_CHECK((flow_ctrl < UART_HW_FLOWCTRL_MAX), "hw_flowctrl mode error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + if(flow_ctrl & UART_HW_FLOWCTRL_RTS) { + UART[uart_num]->conf1.rx_flow_thrhd = rx_thresh; + UART[uart_num]->conf1.rx_flow_en = 1; + } else { + UART[uart_num]->conf1.rx_flow_en = 0; + } + if(flow_ctrl & UART_HW_FLOWCTRL_CTS) { + UART[uart_num]->conf0.tx_flow_en = 1; + } else { + UART[uart_num]->conf0.tx_flow_en = 0; + } + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +int uart_get_hw_flow_ctrl(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + uart_hw_flowcontrol_t val = UART_HW_FLOWCTRL_DISABLE; + if(UART[uart_num]->conf1.rx_flow_en) { + val |= UART_HW_FLOWCTRL_RTS; + } + if(UART[uart_num]->conf0.tx_flow_en) { + val |= UART_HW_FLOWCTRL_CTS; + } + return val; +} + +static esp_err_t uart_reset_fifo(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + UART[uart_num]->conf0.rxfifo_rst = 1; + UART[uart_num]->conf0.rxfifo_rst = 0; + UART[uart_num]->conf0.txfifo_rst = 1; + UART[uart_num]->conf0.txfifo_rst = 0; + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + //intr_clr register is write-only + UART[uart_num]->int_clr.val = clr_mask; + return ESP_OK; +} + +esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + SET_PERI_REG_MASK(UART_INT_CLR_REG(uart_num), enable_mask); + SET_PERI_REG_MASK(UART_INT_ENA_REG(uart_num), enable_mask); + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(uart_num), disable_mask); + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +esp_err_t uart_enable_rx_intr(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + SET_PERI_REG_MASK(UART_INT_ENA_REG(uart_num), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA); + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +esp_err_t uart_disable_rx_intr(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(uart_num), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA); + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +esp_err_t uart_disable_tx_intr(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + UART[uart_num]->int_ena.txfifo_empty = 0; + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((thresh < UART_FIFO_LEN), "empty intr threshold error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + UART[uart_num]->int_clr.txfifo_empty = 1; + UART[uart_num]->conf1.txfifo_empty_thrhd = thresh & UART_TXFIFO_EMPTY_THRHD_V; + UART[uart_num]->int_ena.txfifo_empty = enable & 0x1; + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + ESP_INTR_ENABLE(p_uart_obj[uart_num]->intr_num); + return ESP_OK; +} + +esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (*fn)(void*), void * arg) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + ESP_INTR_DISABLE(uart_intr_num); + switch(uart_num) { + case UART_NUM_1: + intr_matrix_set(xPortGetCoreID(), ETS_UART1_INTR_SOURCE, uart_intr_num); + break; + case UART_NUM_2: + intr_matrix_set(xPortGetCoreID(), ETS_UART2_INTR_SOURCE, uart_intr_num); + break; + case UART_NUM_0: + default: + intr_matrix_set(xPortGetCoreID(), ETS_UART0_INTR_SOURCE, uart_intr_num); + break; + } + xt_set_interrupt_handler(uart_intr_num, fn, arg); + ESP_INTR_ENABLE(uart_intr_num); + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +//internal signal can be output to multiple GPIO pads +//only one GPIO pad can connect with input signal +esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((tx_io_num < 0 || tx_io_num < GPIO_PIN_COUNT || GPIO_PIN_MUX_REG[tx_io_num] != 0), "tx_io_num error"); + UART_CHECK((rx_io_num < 0 || rx_io_num < GPIO_PIN_COUNT || GPIO_PIN_MUX_REG[rx_io_num] != 0), "rx_io_num error"); + UART_CHECK((rts_io_num < 0 || rts_io_num < GPIO_PIN_COUNT || GPIO_PIN_MUX_REG[rts_io_num] != 0), "rts_io_num error"); + UART_CHECK((cts_io_num < 0 || cts_io_num < GPIO_PIN_COUNT || GPIO_PIN_MUX_REG[cts_io_num] != 0), "cts_io_num error"); + + int tx_sig, rx_sig, rts_sig, cts_sig; + switch(uart_num) { + case UART_NUM_0: + tx_sig = U0TXD_OUT_IDX; + rx_sig = U0RXD_IN_IDX; + rts_sig = U0RTS_OUT_IDX; + cts_sig = U0CTS_IN_IDX; + break; + case UART_NUM_1: + tx_sig = U1TXD_OUT_IDX; + rx_sig = U1RXD_IN_IDX; + rts_sig = U1RTS_OUT_IDX; + cts_sig = U1CTS_IN_IDX; + break; + case UART_NUM_2: + tx_sig = U2TXD_OUT_IDX; + rx_sig = U2RXD_IN_IDX; + rts_sig = U2RTS_OUT_IDX; + cts_sig = U2CTS_IN_IDX; + break; + case UART_NUM_MAX: + default: + tx_sig = U0TXD_OUT_IDX; + rx_sig = U0RXD_IN_IDX; + rts_sig = U0RTS_OUT_IDX; + cts_sig = U0CTS_IN_IDX; + break; + } + if(tx_io_num >= 0) { + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[tx_io_num], PIN_FUNC_GPIO); + gpio_set_direction(tx_io_num, GPIO_MODE_OUTPUT); + gpio_matrix_out(tx_io_num, tx_sig, 0, 0); + } + + if(rx_io_num >= 0) { + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[rx_io_num], PIN_FUNC_GPIO); + gpio_set_direction(rx_io_num, GPIO_MODE_INPUT); + gpio_matrix_in(rx_io_num, rx_sig, 0); + } + if(rts_io_num >= 0) { + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[rts_io_num], PIN_FUNC_GPIO); + gpio_set_direction(rts_io_num, GPIO_MODE_OUTPUT); + gpio_matrix_out(rts_io_num, rts_sig, 0, 0); + } + if(cts_io_num >= 0) { + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cts_io_num], PIN_FUNC_GPIO); + gpio_set_direction(cts_io_num, GPIO_MODE_INPUT); + gpio_matrix_in(cts_io_num, cts_sig, 0); + } + return ESP_OK; +} + +esp_err_t uart_set_rts(uart_port_t uart_num, int level) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((UART[uart_num]->conf1.rx_flow_en != 1), "disable hw flowctrl before using sw control\n"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + UART[uart_num]->conf0.sw_rts = level & 0x1; + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +esp_err_t uart_set_dtr(uart_port_t uart_num, int level) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + UART[uart_num]->conf0.sw_dtr = level & 0x1; + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +esp_err_t uart_param_config(uart_port_t uart_num, uart_config_t *uart_config) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_config), "param null\n"); + if(uart_num == UART_NUM_0) { + periph_module_enable(PERIPH_UART0_MODULE); + } else if(uart_num == UART_NUM_1) { + periph_module_enable(PERIPH_UART1_MODULE); + } else if(uart_num == UART_NUM_2) { + periph_module_enable(PERIPH_UART2_MODULE); + } + uart_set_hw_flow_ctrl(uart_num, uart_config->flow_ctrl, uart_config->rx_flow_ctrl_thresh); + uart_set_baudrate(uart_num, uart_config->baud_rate); + UART[uart_num]->conf0.val = ( + (uart_config->parity << UART_PARITY_S) + | (uart_config->stop_bits << UART_STOP_BIT_NUM_S) + | (uart_config->data_bits << UART_BIT_NUM_S) + | ((uart_config->flow_ctrl & UART_HW_FLOWCTRL_CTS) ? UART_TX_FLOW_EN : 0x0) + | UART_TICK_REF_ALWAYS_ON_M); + return ESP_OK; +} + +esp_err_t uart_intr_config(uart_port_t uart_num, uart_intr_config_t *p_intr_conf) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((p_intr_conf), "param null\n"); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + UART[uart_num]->int_clr.val = UART_INTR_MASK; + if(p_intr_conf->intr_enable_mask & UART_RXFIFO_TOUT_INT_ENA_M) { + UART[uart_num]->conf1.rx_tout_thrhd = ((p_intr_conf->rx_timeout_thresh) & UART_RX_TOUT_THRHD_V); + UART[uart_num]->conf1.rx_tout_en = 1; + } else { + UART[uart_num]->conf1.rx_tout_en = 0; + } + if(p_intr_conf->intr_enable_mask & UART_RXFIFO_FULL_INT_ENA_M) { + UART[uart_num]->conf1.rxfifo_full_thrhd = p_intr_conf->rxfifo_full_thresh; + } + if(p_intr_conf->intr_enable_mask & UART_TXFIFO_EMPTY_INT_ENA_M) { + UART[uart_num]->conf1.txfifo_empty_thrhd = p_intr_conf->txfifo_empty_intr_thresh; + } + UART[uart_num]->int_ena.val = p_intr_conf->intr_enable_mask; + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_FAIL; +} + +//internal isr handler for default driver code. +static void IRAM_ATTR uart_rx_intr_handler_default(void *param) +{ + uart_obj_t *p_uart = (uart_obj_t*) param; + uint8_t uart_num = p_uart->uart_num; + uart_dev_t* uart_reg = UART[uart_num]; + + uint8_t buf_idx = 0; + uint32_t uart_intr_status = UART[uart_num]->int_st.val; + static int rx_fifo_len = 0; + uart_event_t uart_event; + portBASE_TYPE HPTaskAwoken = 0; + while(uart_intr_status != 0x0) { + buf_idx = 0; + uart_event.type = UART_EVENT_MAX; + if(uart_intr_status & UART_TXFIFO_EMPTY_INT_ST_M) { + UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_reg->int_ena.txfifo_empty = 0; + uart_reg->int_clr.txfifo_empty = 1; + UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); + if(p_uart->tx_waiting == true) { + p_uart->tx_waiting = false; + xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, NULL); + } + } + else if((uart_intr_status & UART_RXFIFO_TOUT_INT_ST_M) || (uart_intr_status & UART_RXFIFO_FULL_INT_ST_M)) { + if(p_uart->buffer_full_flg == false) { + //Get the buffer from the FIFO + rx_fifo_len = uart_reg->status.rxfifo_cnt; + p_uart->data_len = rx_fifo_len; + memset(p_uart->data_buf, 0, sizeof(p_uart->data_buf)); + while(buf_idx < rx_fifo_len) { + p_uart->data_buf[buf_idx++] = uart_reg->fifo.rw_byte; + } + //After Copying the Data From FIFO ,Clear intr_status + UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_reg->int_clr.rxfifo_tout = 1; + uart_reg->int_clr.rxfifo_full = 1; + UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_event.type = UART_DATA; + uart_event.data.size = rx_fifo_len; + if(pdFALSE == xRingbufferSendFromISR(p_uart->ring_buffer, p_uart->data_buf, p_uart->data_len, &HPTaskAwoken)) { + UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_reg->int_ena.rxfifo_full = 0; + uart_reg->int_ena.rxfifo_tout = 0; + UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); + p_uart->buffer_full_flg = true; + uart_event.type = UART_BUFFER_FULL; + } else { + uart_event.type = UART_DATA; + } + } else { + UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_reg->int_ena.rxfifo_full = 0; + uart_reg->int_ena.rxfifo_tout = 0; + uart_reg->int_clr.val = UART_RXFIFO_FULL_INT_CLR_M | UART_RXFIFO_TOUT_INT_CLR_M; + UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_event.type = UART_BUFFER_FULL; + } + } else if(uart_intr_status & UART_RXFIFO_OVF_INT_ST_M) { + UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_reg->conf0.rxfifo_rst = 1; + uart_reg->conf0.rxfifo_rst = 0; + uart_reg->int_clr.rxfifo_ovf = 1; + UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_event.type = UART_FIFO_OVF; + } else if(uart_intr_status & UART_BRK_DET_INT_ST_M) { + uart_reg->int_clr.brk_det = 1; + uart_event.type = UART_BREAK; + } else if(uart_intr_status & UART_FRM_ERR_INT_ST_M) { + uart_reg->int_clr.parity_err = 1; + uart_event.type = UART_FRAME_ERR; + } else if(uart_intr_status & UART_PARITY_ERR_INT_ST_M) { + uart_reg->int_clr.frm_err = 1; + uart_event.type = UART_PARITY_ERR; + } else if(uart_intr_status & UART_TX_BRK_DONE_INT_ST_M) { + UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_reg->conf0.txd_brk = 0; + uart_reg->int_ena.tx_brk_done = 0; + uart_reg->int_clr.tx_brk_done = 1; + UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); + xSemaphoreGiveFromISR(p_uart->tx_brk_sem, &HPTaskAwoken); + } else if(uart_intr_status & UART_TX_BRK_IDLE_DONE_INT_ST_M) { + UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_reg->int_ena.tx_brk_idle_done = 0; + uart_reg->int_clr.tx_brk_idle_done = 1; + UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); + } else if(uart_intr_status & UART_TX_DONE_INT_ST_M) { + UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_reg->int_ena.tx_done = 0; + uart_reg->int_clr.tx_done = 1; + UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); + xSemaphoreGiveFromISR(p_uart_obj[uart_num]->tx_done_sem, &HPTaskAwoken); + } + else { + uart_reg->int_clr.val = uart_intr_status; /*simply clear all other intr status*/ + uart_event.type = UART_EVENT_MAX; + } + + if(uart_event.type != UART_EVENT_MAX && p_uart->xQueueUart) { + xQueueSendFromISR(p_uart->xQueueUart, (void * )&uart_event, &HPTaskAwoken); + } + uart_intr_status = uart_reg->int_st.val; + } +} + +/**************************************************************/ +esp_err_t uart_driver_install(uart_port_t uart_num, int buffer_size, int queue_size, int uart_intr_num, void* uart_queue) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + if(p_uart_obj[uart_num] == NULL) { + ESP_INTR_DISABLE(uart_intr_num); + p_uart_obj[uart_num] = (uart_obj_t*) malloc(sizeof(uart_obj_t)); + if(p_uart_obj[uart_num] == NULL) { + ESP_LOGE(UART_TAG, "UART driver malloc error\n"); + return ESP_FAIL; + } + p_uart_obj[uart_num]->uart_num = uart_num; + p_uart_obj[uart_num]->tx_fifo_sem = xSemaphoreCreateBinary(); + xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); + p_uart_obj[uart_num]->tx_done_sem = xSemaphoreCreateBinary(); + xSemaphoreGive(p_uart_obj[uart_num]->tx_done_sem); + p_uart_obj[uart_num]->tx_brk_sem = xSemaphoreCreateBinary(); + + p_uart_obj[uart_num]->tx_mutex = xSemaphoreCreateMutex(); + p_uart_obj[uart_num]->rx_sem = xSemaphoreCreateMutex(); + p_uart_obj[uart_num]->intr_num = uart_intr_num; + p_uart_obj[uart_num]->queue_size = queue_size; + + if(uart_queue) { + p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t)); + *((QueueHandle_t*) uart_queue) = p_uart_obj[uart_num]->xQueueUart; + ESP_LOGI(UART_TAG, "queue free spaces: %d\n", uxQueueSpacesAvailable(p_uart_obj[uart_num]->xQueueUart)); + } else { + p_uart_obj[uart_num]->xQueueUart = NULL; + } + p_uart_obj[uart_num]->buffer_full_flg = false; + p_uart_obj[uart_num]->tx_waiting = false; + p_uart_obj[uart_num]->rd_ptr = NULL; + p_uart_obj[uart_num]->cur_remain = 0; + p_uart_obj[uart_num]->head_ptr = NULL; + p_uart_obj[uart_num]->ring_buffer = xRingbufferCreate(buffer_size, 0); + } else { + ESP_LOGE(UART_TAG, "UART driver already installed\n"); + return ESP_FAIL; + } + uart_isr_register(uart_num, uart_intr_num, uart_rx_intr_handler_default, p_uart_obj[uart_num]); + uart_intr_config_t uart_intr = { + .intr_enable_mask = UART_RXFIFO_FULL_INT_ENA_M + | UART_RXFIFO_TOUT_INT_ENA_M + | UART_FRM_ERR_INT_ENA_M + | UART_RXFIFO_OVF_INT_ENA_M + | UART_BRK_DET_INT_ENA_M, + .rxfifo_full_thresh = DEFAULT_FULL_THRESH, + .rx_timeout_thresh = DEFAULT_TOUT_THRESH, + .txfifo_empty_intr_thresh = DEFAULT_EMPTY_THRESH + }; + uart_intr_config(uart_num, &uart_intr); + ESP_INTR_ENABLE(uart_intr_num); + return ESP_OK; +} + +//Make sure no other tasks are still using UART before you call this function +esp_err_t uart_driver_delete(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + if(p_uart_obj[uart_num] == NULL) { + ESP_LOGI(UART_TAG, "ALREADY NULL\n"); + return ESP_OK; + } + ESP_INTR_DISABLE(p_uart_obj[uart_num]->intr_num); + uart_disable_rx_intr(uart_num); + uart_disable_tx_intr(uart_num); + uart_isr_register(uart_num, p_uart_obj[uart_num]->intr_num, NULL, NULL); + + if(p_uart_obj[uart_num]->tx_fifo_sem) { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_fifo_sem); + p_uart_obj[uart_num]->tx_fifo_sem = NULL; + } + if(p_uart_obj[uart_num]->tx_done_sem) { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_done_sem); + p_uart_obj[uart_num]->tx_done_sem = NULL; + } + if(p_uart_obj[uart_num]->tx_brk_sem) { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_brk_sem); + p_uart_obj[uart_num]->tx_brk_sem = NULL; + } + if(p_uart_obj[uart_num]->tx_mutex) { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_mutex); + p_uart_obj[uart_num]->tx_mutex = NULL; + } + if(p_uart_obj[uart_num]->rx_sem) { + vSemaphoreDelete(p_uart_obj[uart_num]->rx_sem); + p_uart_obj[uart_num]->rx_sem = NULL; + } + if(p_uart_obj[uart_num]->xQueueUart) { + vQueueDelete(p_uart_obj[uart_num]->xQueueUart); + p_uart_obj[uart_num]->xQueueUart = NULL; + } + if(p_uart_obj[uart_num]->ring_buffer) { + vRingbufferDelete(p_uart_obj[uart_num]->ring_buffer); + p_uart_obj[uart_num]->ring_buffer = NULL; + } + free(p_uart_obj[uart_num]); + p_uart_obj[uart_num] = NULL; + return ESP_OK; +} + +esp_err_t uart_wait_tx_fifo_empty(uart_port_t uart_num, TickType_t ticks_to_wait) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); + BaseType_t res; + portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait; + //Take tx_mutex + res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mutex, (portTickType)ticks_to_wait); + if(res == pdFALSE) { + return ESP_ERR_TIMEOUT; + } + ticks_to_wait = ticks_end - xTaskGetTickCount(); + //take 1st tx_done_sem + res = xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, (portTickType)ticks_to_wait); + if(res == pdFALSE) { + ESP_LOGE(UART_TAG, "take uart done sem error, should not get here.\n"); + xSemaphoreGive(p_uart_obj[uart_num]->tx_done_sem); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + return ESP_ERR_TIMEOUT; + } + ticks_to_wait = ticks_end - xTaskGetTickCount(); + if(UART[uart_num]->status.txfifo_cnt == 0) { + xSemaphoreGive(p_uart_obj[uart_num]->tx_done_sem); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + return ESP_OK; + } + uart_enable_intr_mask(uart_num, UART_TX_DONE_INT_ENA_M); + //take 2nd tx_done_sem, wait given from ISR + res = xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, (portTickType)ticks_to_wait); + if(res == pdFALSE) { + uart_disable_intr_mask(uart_num, UART_TX_DONE_INT_ENA_M); + xSemaphoreGive(p_uart_obj[uart_num]->tx_done_sem); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + return ESP_ERR_TIMEOUT; + } + xSemaphoreGive(p_uart_obj[uart_num]->tx_done_sem); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + return ESP_OK; +} + +static esp_err_t uart_set_break(uart_port_t uart_num, int break_num) +{ + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + UART[uart_num]->idle_conf.tx_brk_num = break_num; + UART[uart_num]->conf0.txd_brk = 1; + UART[uart_num]->int_clr.tx_brk_done = 1; + UART[uart_num]->int_ena.tx_brk_done = 1; + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + return ESP_OK; +} + +int uart_tx_chars(uart_port_t uart_num, char* buffer, uint32_t len) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); + UART_CHECK(buffer, "buffer null"); + if(len == 0) { + return 0; + } + xSemaphoreTake(p_uart_obj[uart_num]->tx_mutex, (portTickType)portMAX_DELAY); + int tx_len = uart_fill_fifo(uart_num, buffer, len); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + return tx_len; +} + +static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool brk_en, int brk_len) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); + UART_CHECK(src, "buffer null"); + if(size == 0) { + return 0; + } + //lock for uart_tx + xSemaphoreTake(p_uart_obj[uart_num]->tx_mutex, (portTickType)portMAX_DELAY); + size_t original_size = size; + while(size) { + //semaphore for tx_fifo available + if(pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) { + size_t sent = uart_fill_fifo(uart_num, (char*) src, size); + if(sent < size) { + p_uart_obj[uart_num]->tx_waiting = true; + uart_enable_tx_intr(uart_num, 1, DEFAULT_EMPTY_THRESH); + } + size -= sent; + src += sent; + } + } + if(brk_en) { + uart_set_break(uart_num, brk_len); + xSemaphoreTake(p_uart_obj[uart_num]->tx_brk_sem, (portTickType)portMAX_DELAY); + } + xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + return original_size; +} + +int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); + UART_CHECK(src, "buffer null"); + return uart_tx_all(uart_num, src, size, 0, 0); +} + +int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); + UART_CHECK((size > 0), "uart size error"); + UART_CHECK((src), "uart data null"); + UART_CHECK((brk_len > 0 && brk_len < 256), "break_num error"); + return uart_tx_all(uart_num, src, size, 1, brk_len); +} + +int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); + uint8_t* data; + size_t size; + int val; + portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait; + if(xSemaphoreTake(p_uart_obj[uart_num]->rx_sem,(portTickType)ticks_to_wait) != pdTRUE) { + return -1; + } + if(p_uart_obj[uart_num]->cur_remain == 0) { + ticks_to_wait = ticks_end - xTaskGetTickCount(); + data = (uint8_t*) xRingbufferReceive(p_uart_obj[uart_num]->ring_buffer, &size, (portTickType) ticks_to_wait); + if(data) { + p_uart_obj[uart_num]->head_ptr = data; + p_uart_obj[uart_num]->rd_ptr = data; + p_uart_obj[uart_num]->cur_remain = size; + } else { + xSemaphoreGive(p_uart_obj[uart_num]->rx_sem); + return -1; + } + } + val = *(p_uart_obj[uart_num]->rd_ptr); + p_uart_obj[uart_num]->rd_ptr++; + p_uart_obj[uart_num]->cur_remain--; + if(p_uart_obj[uart_num]->cur_remain == 0) { + vRingbufferReturnItem(p_uart_obj[uart_num]->ring_buffer, p_uart_obj[uart_num]->head_ptr); + p_uart_obj[uart_num]->head_ptr = NULL; + p_uart_obj[uart_num]->rd_ptr = NULL; + if(p_uart_obj[uart_num]->buffer_full_flg) { + BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->ring_buffer, p_uart_obj[uart_num]->data_buf, p_uart_obj[uart_num]->data_len, 1); + if(res == pdTRUE) { + p_uart_obj[uart_num]->buffer_full_flg = false; + uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); + } + } + } + xSemaphoreGive(p_uart_obj[uart_num]->rx_sem); + return val; +} + +int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((buf), "uart_num error"); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); + + uint8_t* data = NULL; + size_t size; + size_t copy_len = 0; + int len_tmp; + if(xSemaphoreTake(p_uart_obj[uart_num]->rx_sem,(portTickType)ticks_to_wait) != pdTRUE) { + return -1; + } + while(length) { + if(p_uart_obj[uart_num]->cur_remain == 0) { + data = (uint8_t*) xRingbufferReceive(p_uart_obj[uart_num]->ring_buffer, &size, (portTickType) ticks_to_wait); + if(data) { + p_uart_obj[uart_num]->head_ptr = data; + p_uart_obj[uart_num]->rd_ptr = data; + p_uart_obj[uart_num]->cur_remain = size; + } else { + xSemaphoreGive(p_uart_obj[uart_num]->rx_sem); + return copy_len; + } + } + if(p_uart_obj[uart_num]->cur_remain > length) { + len_tmp = length; + } else { + len_tmp = p_uart_obj[uart_num]->cur_remain; + } + memcpy(buf + copy_len, p_uart_obj[uart_num]->rd_ptr, len_tmp); + p_uart_obj[uart_num]->rd_ptr += len_tmp; + p_uart_obj[uart_num]->cur_remain -= len_tmp; + copy_len += len_tmp; + length -= len_tmp; + if(p_uart_obj[uart_num]->cur_remain == 0) { + vRingbufferReturnItem(p_uart_obj[uart_num]->ring_buffer, p_uart_obj[uart_num]->head_ptr); + p_uart_obj[uart_num]->head_ptr = NULL; + p_uart_obj[uart_num]->rd_ptr = NULL; + if(p_uart_obj[uart_num]->buffer_full_flg) { + BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->ring_buffer, p_uart_obj[uart_num]->data_buf, p_uart_obj[uart_num]->data_len, 1); + if(res == pdTRUE) { + p_uart_obj[uart_num]->buffer_full_flg = false; + uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); + } + } + } + } + xSemaphoreGive(p_uart_obj[uart_num]->rx_sem); + return copy_len; +} + +esp_err_t uart_flush(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); + + uart_obj_t* p_uart = p_uart_obj[uart_num]; + uint8_t* data; + size_t size; + //rx sem protect the ring buffer read related functions + xSemaphoreTake(p_uart->rx_sem, (portTickType)portMAX_DELAY); + while(true) { + if(p_uart->head_ptr) { + vRingbufferReturnItem(p_uart->ring_buffer, p_uart->head_ptr); + p_uart->rd_ptr = NULL; + p_uart->cur_remain = 0; + p_uart->head_ptr = NULL; + } + data = (uint8_t*) xRingbufferReceive(p_uart->ring_buffer, &size, (portTickType) 0); + if(data == NULL) { + break; + } + vRingbufferReturnItem(p_uart->ring_buffer, data); + } + p_uart->rd_ptr = NULL; + p_uart->cur_remain = 0; + p_uart->head_ptr = NULL; + xSemaphoreGive(p_uart->rx_sem); + uart_wait_tx_fifo_empty(uart_num, portMAX_DELAY); + uart_reset_fifo(uart_num); + return ESP_OK; +} + +//----------------------------------- +//Should not enable hw flow control the debug print port. +//Use uart_tx_all_chars() as a thread-safe function to send data. +static int s_uart_print_nport = UART_NUM_0; +static void uart2_write_char(char chr) +{ + uart_tx_all_chars(UART_NUM_2, (const char*)&chr, 1); +} + +static void uart1_write_char(char chr) +{ + uart_tx_all_chars(UART_NUM_1, (const char*)&chr, 1); +} + +static void uart0_write_char(char chr) +{ + uart_tx_all_chars(UART_NUM_0, (const char*)&chr, 1); +} + +static void uart_ignore_char(char chr) +{ + +} + +//Only effective to ets_printf function, not ESP_LOGX macro. +esp_err_t uart_set_print_port(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((p_uart_obj[uart_num]), "UART driver error"); + + s_uart_print_nport = uart_num; + switch(s_uart_print_nport) { + case UART_NUM_0: + ets_install_putc1(uart0_write_char); + break; + case UART_NUM_1: + ets_install_putc1(uart1_write_char); + break; + case UART_NUM_2: + ets_install_putc1(uart2_write_char); + break; + case UART_NUM_MAX: + default: + ets_install_putc1(uart_ignore_char); + break; + } + return ESP_OK; +} + +int uart_get_print_port() +{ + return s_uart_print_nport; +} + diff --git a/components/esp32/include/esp_err.h b/components/esp32/include/esp_err.h index 4f013f91a..5504c3d68 100644 --- a/components/esp32/include/esp_err.h +++ b/components/esp32/include/esp_err.h @@ -31,6 +31,7 @@ typedef int32_t esp_err_t; #define ESP_ERR_NO_MEM 0x101 #define ESP_ERR_INVALID_ARG 0x102 #define ESP_ERR_INVALID_STATE 0x103 +#define ESP_ERR_TIMEOUT 0x104 /** * Macro which can be used to check the error code, diff --git a/components/esp32/include/soc/uart_reg.h b/components/esp32/include/soc/uart_reg.h index 155700b29..8cac4bb83 100644 --- a/components/esp32/include/soc/uart_reg.h +++ b/components/esp32/include/soc/uart_reg.h @@ -18,8 +18,10 @@ #include "soc.h" #define REG_UART_BASE( i ) (DR_REG_UART_BASE + (i) * 0x10000 + ( i > 1 ? 0xe000 : 0 ) ) - +#define REG_UART_AHB_BASE(i) (0x60000000 + (i) * 0x10000 + ( i > 1 ? 0xe000 : 0 ) ) +#define UART_FIFO_AHB_REG(i) (REG_UART_AHB_BASE(i) + 0x0) #define UART_FIFO_REG(i) (REG_UART_BASE(i) + 0x0) + /* UART_RXFIFO_RD_BYTE : RO ;bitpos:[7:0] ;default: 8'b0 ; */ /*description: This register stores one byte data read by rx fifo.*/ #define UART_RXFIFO_RD_BYTE 0x000000FF diff --git a/components/freertos/ringbuf.c b/components/freertos/ringbuf.c index 6045c5a69..365175314 100644 --- a/components/freertos/ringbuf.c +++ b/components/freertos/ringbuf.c @@ -371,8 +371,7 @@ BaseType_t xRingbufferSendFromISR(RingbufHandle_t ringbuf, void *data, size_t da //Does not fit in the remaining space in the ringbuffer. write_succeeded=pdFALSE; } else { - copyItemToRingbuf(rb, data, dataSize); - write_succeeded=pdTRUE; + write_succeeded = copyItemToRingbuf(rb, data, dataSize); } portEXIT_CRITICAL_ISR(&rb->mux); if (write_succeeded) { From 9098e64398e1af7418e7c27c6bba23f80b55810f Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Mon, 24 Oct 2016 09:38:34 +0800 Subject: [PATCH 02/12] modify GPIO number check --- components/driver/uart.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/driver/uart.c b/components/driver/uart.c index 157e0c49c..f585c0965 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -312,10 +312,10 @@ esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (* esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((tx_io_num < 0 || tx_io_num < GPIO_PIN_COUNT || GPIO_PIN_MUX_REG[tx_io_num] != 0), "tx_io_num error"); - UART_CHECK((rx_io_num < 0 || rx_io_num < GPIO_PIN_COUNT || GPIO_PIN_MUX_REG[rx_io_num] != 0), "rx_io_num error"); - UART_CHECK((rts_io_num < 0 || rts_io_num < GPIO_PIN_COUNT || GPIO_PIN_MUX_REG[rts_io_num] != 0), "rts_io_num error"); - UART_CHECK((cts_io_num < 0 || cts_io_num < GPIO_PIN_COUNT || GPIO_PIN_MUX_REG[cts_io_num] != 0), "cts_io_num error"); + UART_CHECK((tx_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(tx_io_num))), "tx_io_num error"); + UART_CHECK((rx_io_num < 0 || (GPIO_IS_VALID_GPIO(rx_io_num))), "rx_io_num error"); + UART_CHECK((rts_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(rts_io_num))), "rts_io_num error"); + UART_CHECK((cts_io_num < 0 || (GPIO_IS_VALID_GPIO(cts_io_num))), "cts_io_num error"); int tx_sig, rx_sig, rts_sig, cts_sig; switch(uart_num) { From 74aff2b9d2762578f1da7ff736e402c909755620 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Mon, 24 Oct 2016 15:57:23 +0800 Subject: [PATCH 03/12] Update UART driver 1. Use esp_log API for LEDC and GPIO code. 2. Modify some API return value. 3. Add ledc_set_pin() for LEDC 4. Modify typo in uart.h Questions: In uart driver ISR handler, I used xxxFromISR , like xSemaphoreGiveFromISR, do those FromISR functions need to be put in IRAM? --- components/driver/gpio.c | 123 ++++--------- components/driver/include/driver/gpio.h | 2 + components/driver/include/driver/ledc.h | 33 +++- components/driver/include/driver/uart.h | 71 ++++---- components/driver/ledc.c | 223 ++++++------------------ components/driver/uart.c | 40 +++-- 6 files changed, 169 insertions(+), 323 deletions(-) diff --git a/components/driver/gpio.c b/components/driver/gpio.c index 14dfc00b4..da0fedb89 100644 --- a/components/driver/gpio.c +++ b/components/driver/gpio.c @@ -18,34 +18,13 @@ #include "freertos/xtensa_api.h" #include "driver/gpio.h" #include "soc/soc.h" +#include "esp_log.h" -//TODO: move debug options to menuconfig -#define GPIO_DBG_ENABLE (0) -#define GPIO_WARNING_ENABLE (0) -#define GPIO_ERROR_ENABLE (0) -#define GPIO_INFO_ENABLE (0) -//DBG INFOR -#if GPIO_INFO_ENABLE -#define GPIO_INFO ets_printf -#else -#define GPIO_INFO(...) -#endif -#if GPIO_WARNING_ENABLE -#define GPIO_WARNING(format,...) do{\ - ets_printf("[waring][%s#%u]",__FUNCTION__,__LINE__);\ - ets_printf(format,##__VA_ARGS__);\ -}while(0) -#else -#define GPIO_WARNING(...) -#endif -#if GPIO_ERROR_ENABLE -#define GPIO_ERROR(format,...) do{\ - ets_printf("[error][%s#%u]",__FUNCTION__,__LINE__);\ - ets_printf(format,##__VA_ARGS__);\ -}while(0) -#else -#define GPIO_ERROR(...) -#endif +const char* GPIO_TAG = "GPIO"; +#define GPIO_CHECK(a, str, ret_val) if (!(a)) { \ + ESP_LOGE(GPIO_TAG,"%s:%d (%s):%s\n", __FILE__, __LINE__, __FUNCTION__, str); \ + return (ret_val); \ + } const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT] = { GPIO_PIN_REG_0, @@ -90,33 +69,17 @@ const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT] = { GPIO_PIN_REG_39 }; -static int is_valid_gpio(int gpio_num) -{ - if(gpio_num >= GPIO_PIN_COUNT || GPIO_PIN_MUX_REG[gpio_num] == 0) { - GPIO_ERROR("GPIO io_num=%d does not exist\n",gpio_num); - return 0; - } - return 1; -} - esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type) { - if(!is_valid_gpio(gpio_num)) { - return ESP_ERR_INVALID_ARG; - } - if(intr_type >= GPIO_INTR_MAX) { - GPIO_ERROR("Unknown GPIO intr:%u\n",intr_type); - return ESP_ERR_INVALID_ARG; - } + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); + GPIO_CHECK(intr_type < GPIO_INTR_MAX, "GPIO interrupt type error\n", ESP_ERR_INVALID_ARG); GPIO.pin[gpio_num].int_type = intr_type; return ESP_OK; } esp_err_t gpio_intr_enable(gpio_num_t gpio_num) { - if(!is_valid_gpio(gpio_num)) { - return ESP_ERR_INVALID_ARG; - } + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); if(xPortGetCoreID() == 0) { GPIO.pin[gpio_num].int_ena = GPIO_PRO_CPU_INTR_ENA; //enable pro cpu intr } else { @@ -127,18 +90,14 @@ esp_err_t gpio_intr_enable(gpio_num_t gpio_num) esp_err_t gpio_intr_disable(gpio_num_t gpio_num) { - if(!is_valid_gpio(gpio_num)) { - return ESP_ERR_INVALID_ARG; - } + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); GPIO.pin[gpio_num].int_ena = 0; //disable GPIO intr return ESP_OK; } static esp_err_t gpio_output_disable(gpio_num_t gpio_num) { - if(!is_valid_gpio(gpio_num)) { - return ESP_ERR_INVALID_ARG; - } + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); if(gpio_num < 32) { GPIO.enable_w1tc = (0x1 << gpio_num); } else { @@ -149,13 +108,7 @@ static esp_err_t gpio_output_disable(gpio_num_t gpio_num) static esp_err_t gpio_output_enable(gpio_num_t gpio_num) { - if(gpio_num >= 34) { - GPIO_ERROR("io_num=%d can only be input\n",gpio_num); - return ESP_ERR_INVALID_ARG; - } - if(!is_valid_gpio(gpio_num)) { - return ESP_ERR_INVALID_ARG; - } + GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO output gpio_num error\n", ESP_ERR_INVALID_ARG); if(gpio_num < 32) { GPIO.enable_w1ts = (0x1 << gpio_num); } else { @@ -166,9 +119,7 @@ static esp_err_t gpio_output_enable(gpio_num_t gpio_num) esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level) { - if(!GPIO_IS_VALID_GPIO(gpio_num)) { - return ESP_ERR_INVALID_ARG; - } + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); if(level) { if(gpio_num < 32) { GPIO.out_w1ts = (1 << gpio_num); @@ -196,9 +147,8 @@ int gpio_get_level(gpio_num_t gpio_num) esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull) { - if(!is_valid_gpio(gpio_num)) { - return ESP_ERR_INVALID_ARG; - } + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); + GPIO_CHECK(pull <= GPIO_FLOATING, "GPIO pull mode error\n", ESP_ERR_INVALID_ARG); esp_err_t ret = ESP_OK; switch(pull) { case GPIO_PULLUP_ONLY: @@ -218,7 +168,7 @@ esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull) PIN_PULLDWN_DIS(GPIO_PIN_MUX_REG[gpio_num]); break; default: - GPIO_ERROR("Unknown pull up/down mode,gpio_num=%u,pull=%u\n",gpio_num,pull); + ESP_LOGE(GPIO_TAG, "Unknown pull up/down mode,gpio_num=%u,pull=%u\n",gpio_num,pull); ret = ESP_ERR_INVALID_ARG; break; } @@ -227,11 +177,9 @@ esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull) esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode) { - if(!is_valid_gpio(gpio_num)) { - return ESP_ERR_INVALID_ARG; - } + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); if(gpio_num >= 34 && (mode & (GPIO_MODE_DEF_OUTPUT))) { - GPIO_ERROR("io_num=%d can only be input\n",gpio_num); + ESP_LOGE(GPIO_TAG, "io_num=%d can only be input\n",gpio_num); return ESP_ERR_INVALID_ARG; } esp_err_t ret = ESP_OK; @@ -268,52 +216,51 @@ esp_err_t gpio_config(gpio_config_t *pGPIOConfig) uint32_t io_num = 0; uint64_t bit_valid = 0; if(pGPIOConfig->pin_bit_mask == 0 || pGPIOConfig->pin_bit_mask >= (((uint64_t) 1) << GPIO_PIN_COUNT)) { - GPIO_ERROR("GPIO_PIN mask error \n"); + ESP_LOGE(GPIO_TAG, "GPIO_PIN mask error \n"); return ESP_ERR_INVALID_ARG; } if((pGPIOConfig->mode) & (GPIO_MODE_DEF_OUTPUT)) { //GPIO 34/35/36/37/38/39 can only be used as input mode; if((gpio_pin_mask & ( GPIO_SEL_34 | GPIO_SEL_35 | GPIO_SEL_36 | GPIO_SEL_37 | GPIO_SEL_38 | GPIO_SEL_39))) { - GPIO_ERROR("GPIO34-39 can only be used as input mode\n"); + ESP_LOGE(GPIO_TAG, "GPIO34-39 can only be used as input mode\n"); return ESP_ERR_INVALID_ARG; } } do { io_reg = GPIO_PIN_MUX_REG[io_num]; if(((gpio_pin_mask >> io_num) & BIT(0)) && io_reg) { - GPIO_INFO("Gpio%02d |Mode:",io_num); + ESP_LOGI(GPIO_TAG, "Gpio%02d |Mode:",io_num); if((pGPIOConfig->mode) & GPIO_MODE_DEF_INPUT) { - GPIO_INFO("INPUT "); + ESP_LOGI(GPIO_TAG, "INPUT "); PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[io_num]); } else { PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[io_num]); } if((pGPIOConfig->mode) & GPIO_MODE_DEF_OD) { - GPIO_INFO("OD "); + ESP_LOGI(GPIO_TAG, "OD "); GPIO.pin[io_num].pad_driver = 1; /*0x01 Open-drain */ } else { GPIO.pin[io_num].pad_driver = 0; /*0x00 Normal gpio output */ } if((pGPIOConfig->mode) & GPIO_MODE_DEF_OUTPUT) { - GPIO_INFO("OUTPUT "); + ESP_LOGI(GPIO_TAG, "OUTPUT "); gpio_output_enable(io_num); } else { gpio_output_disable(io_num); } - GPIO_INFO("|"); if(pGPIOConfig->pull_up_en) { - GPIO_INFO("PU "); + ESP_LOGI(GPIO_TAG, "PU "); PIN_PULLUP_EN(io_reg); } else { PIN_PULLUP_DIS(io_reg); } if(pGPIOConfig->pull_down_en) { - GPIO_INFO("PD "); + ESP_LOGI(GPIO_TAG, "PD "); PIN_PULLDWN_EN(io_reg); } else { PIN_PULLDWN_DIS(io_reg); } - GPIO_INFO("Intr:%d |\n",pGPIOConfig->intr_type); + ESP_LOGI(GPIO_TAG, "Intr:%d |\n",pGPIOConfig->intr_type); gpio_set_intr_type(io_num, pGPIOConfig->intr_type); if(pGPIOConfig->intr_type) { gpio_intr_enable(io_num); @@ -322,7 +269,7 @@ esp_err_t gpio_config(gpio_config_t *pGPIOConfig) } PIN_FUNC_SELECT(io_reg, PIN_FUNC_GPIO); /*function number 2 is GPIO_FUNC for each pin */ } else if(bit_valid && (io_reg == 0)) { - GPIO_WARNING("io_num=%d does not exist\n",io_num); + ESP_LOGW(GPIO_TAG, "io_num=%d does not exist\n",io_num); } io_num++; } while(io_num < GPIO_PIN_COUNT); @@ -331,9 +278,7 @@ esp_err_t gpio_config(gpio_config_t *pGPIOConfig) esp_err_t gpio_isr_register(uint32_t gpio_intr_num, void (*fn)(void*), void * arg) { - if(fn == NULL) { - return ESP_ERR_INVALID_ARG; - } + GPIO_CHECK(fn, "GPIO ISR null\n", ESP_ERR_INVALID_ARG); ESP_INTR_DISABLE(gpio_intr_num); intr_matrix_set(xPortGetCoreID(), ETS_GPIO_INTR_SOURCE, gpio_intr_num); xt_set_interrupt_handler(gpio_intr_num, fn, arg); @@ -344,15 +289,13 @@ esp_err_t gpio_isr_register(uint32_t gpio_intr_num, void (*fn)(void*), void * ar /*only level interrupt can be used for wake-up function*/ esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type) { - if(!is_valid_gpio(gpio_num)) { - return ESP_ERR_INVALID_ARG; - } + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); esp_err_t ret = ESP_OK; if((intr_type == GPIO_INTR_LOW_LEVEL) || (intr_type == GPIO_INTR_HIGH_LEVEL)) { GPIO.pin[gpio_num].int_type = intr_type; GPIO.pin[gpio_num].wakeup_enable = 0x1; } else { - GPIO_ERROR("GPIO wakeup only support Level mode,but edge mode set. gpio_num:%u\n",gpio_num); + ESP_LOGE(GPIO_TAG, "GPIO wakeup only support Level mode,but edge mode set. gpio_num:%u\n",gpio_num); ret = ESP_ERR_INVALID_ARG; } return ret; @@ -360,9 +303,7 @@ esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type) esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num) { - if(!is_valid_gpio(gpio_num)) { - return ESP_ERR_INVALID_ARG; - } + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); GPIO.pin[gpio_num].wakeup_enable = 0; return ESP_OK; } diff --git a/components/driver/include/driver/gpio.h b/components/driver/include/driver/gpio.h index c821b640e..5ed99e597 100644 --- a/components/driver/include/driver/gpio.h +++ b/components/driver/include/driver/gpio.h @@ -28,6 +28,8 @@ extern "C" { #endif +extern const char* GPIO_TAG; + #define GPIO_SEL_0 (BIT(0)) /* Pin 0 selected */ #define GPIO_SEL_1 (BIT(1)) /* Pin 1 selected */ #define GPIO_SEL_2 (BIT(2)) /* Pin 2 selected */ diff --git a/components/driver/include/driver/ledc.h b/components/driver/include/driver/ledc.h index 79a6c7f9f..d6ce9b86c 100644 --- a/components/driver/include/driver/ledc.h +++ b/components/driver/include/driver/ledc.h @@ -26,6 +26,7 @@ extern "C" { #endif +extern const char* LEDC_TAG; #define LEDC_APB_CLK_HZ (APB_CLK_FREQ) #define LEDC_REF_CLK_HZ (1*1000000) @@ -338,6 +339,22 @@ esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel); */ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint32_t timer_idx); +/** + * @brief Set LEDC output signal to GPIO + * + * @param[in] gpio_num : GPIO number for LEDC signal output + * + * @param[in] speed_mode : select the LEDC speed_mode, high-speed mode and low-speed mode, now we only support high-speed mode. We will access low-speed mode in next version + * + * @param[in] channel : LEDC channel index(0-7), select from ledc_channel_t + * + * + * @return ESP_ERR_INVALID_ARG: parameter error + * ESP_OK: success + * + */ +esp_err_t ledc_set_pin(int gpio_num,ledc_mode_t speed_mode, ledc_channel_t ledc_channel); + /***************************EXAMPLE********************************** * * @@ -349,21 +366,21 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint * ledc_timer_config_t timer_conf = { * .bit_num = LEDC_TIMER_12_BIT, //set timer counter bit number * .freq_hz = 1000, //set frequency of pwm, here, 1000Hz - * .speed_mode = LEDC_HIGH_SPEED_MODE //timer mode, + * .speed_mode = LEDC_HIGH_SPEED_MODE, //timer mode, * .timer_num = LEDC_TIMER_0, //timer number * }; * ledc_timer_config(&timer_conf); //setup timer. * * //3. set LEDC channel * ledc_channel_config_t ledc_conf = { - * .channel = LEDC_CHANNEL_0; //set LEDC channel 0 - * .duty = 1000; //set the duty for initialization.(duty range is 0 ~ ((2**bit_num)-1) - * .gpio_num = 16; //GPIO number - * .intr_type = LEDC_INTR_FADE_END; //GPIO INTR TYPE, as an example, we enable fade_end interrupt here. - * .speed_mode = LEDC_HIGH_SPEED_MODE; //set LEDC mode, from ledc_mode_t - * .timer_sel = LEDC_TIMER_0; //set LEDC timer source, if different channel use one timer, the frequency and bit_num of these channels should be the same + * .channel = LEDC_CHANNEL_0, //set LEDC channel 0 + * .duty = 1000, //set the duty for initialization.(duty range is 0 ~ ((2**bit_num)-1) + * .gpio_num = 16, //GPIO number + * .intr_type = LEDC_INTR_FADE_END, //GPIO INTR TYPE, as an example, we enable fade_end interrupt here. + * .speed_mode = LEDC_HIGH_SPEED_MODE, //set LEDC mode, from ledc_mode_t + * .timer_sel = LEDC_TIMER_0, //set LEDC timer source, if different channel use one timer, the frequency and bit_num of these channels should be the same * } - * ledc_channel_config(&ledc_conf); //setup the configuration + * ledc_channel_config(&ledc_conf); //setup the configuration * * ----------------EXAMPLE OF SETTING DUTY --- ----------------- * uint32_t ledc_channel = LEDC_CHANNEL_0; //LEDC channel(0-73) diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index cd0725d2c..dafdf54a8 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -27,7 +27,7 @@ extern "C" { #include extern const char* UART_TAG; -#define UART_FIFO_LEN (128) //Do Not Change it +#define UART_FIFO_LEN (128) //Do not change this, this value describes the length of the gardware FIFO in the ESP32 #define UART_INTR_MASK 0x1ff #define UART_LINE_INV_MASK (0x3f << 19) @@ -150,13 +150,10 @@ esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit * * @param uart_port_t uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_FAIL (-1) : Parameter error - * UART_DATA_5_BITS (0): UART word length: 5 bits. - * UART_DATA_6_BITS (1): UART word length: 6 bits. - * UART_DATA_7_BITS (2): UART word length: 7 bits. - * UART_DATA_8_BITS (3): UART word length: 8 bits. + * @return ESP_FAIL : Parameter error + * ESP_OK : Success, result will be put in (*data_bit) */ -int uart_get_word_length(uart_port_t uart_num); +esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bit); /** * @brief Set UART stop bits. @@ -174,12 +171,10 @@ esp_err_t uart_set_stop_bits(uart_port_t uart_no, uart_stop_bits_t bit_num); * * @param uart_port_t uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_FAIL (-1): Parameter error - * UART_STOP_BITS_1 (1): 1 stop bit - * UART_STOP_BITS_1_5 (2): 1.5 stop bits - * UART_STOP_BITS_1 (3): 2 stop bits + * @return ESP_FAIL : Parameter error + * ESP_OK : Success, result will be put in (*stop_bit) */ -int uart_get_stop_bits(uart_port_t uart_num); +esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit); /** * @brief Set UART parity. @@ -196,13 +191,11 @@ esp_err_t uart_set_parity(uart_port_t uart_no, uart_parity_t parity_mode); * * @param uart_port_t uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_FAIL (-1): Parameter error - * UART_PARITY_ODD (0x11): Odd parity check mode - * UART_PARITY_EVEN (0x10): Even parity check mode - * UART_PARITY_DISABLE(0x0) : parity check disabled + * @return ESP_FAIL : Parameter error + * ESP_OK : Success, result will be put in (*parity_mode) * */ -int uart_get_parity(uart_port_t uart_num); +esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode); /** * @brief Set UART baud rate. @@ -219,11 +212,11 @@ esp_err_t uart_set_baudrate(uart_port_t uart_no, uint32_t baud_rate); * * @param uart_port_t uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_FAIL(-1): Parameter error - * Others (>0): UART baud-rate + * @return ESP_FAIL : Parameter error + * ESP_OK : Success, result will be put in (*baudrate) * */ -int uart_get_baudrate(uart_port_t uart_num); +esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate); /** * @brief Set UART line inverse mode @@ -253,13 +246,10 @@ esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_no, uart_hw_flowcontrol_t flow_ * @brief Get hardware flow control mode * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_FAIL (-1): Parameter error - * UART_HW_FLOWCTRL_DISABLE (0): UART hw flow control disabled - * UART_HW_FLOWCTRL_RTS (1): UART RX flow control enabled - * UART_HW_FLOWCTRL_CTS (2): UART TX flow control enabled - * UART_HW_FLOWCTRL_CTS_RTS (3): UART TX/RX flow control enabled + * @return ESP_FAIL : Parameter error + * ESP_OK : Success, result will be put in (*flow_ctrl) */ -int uart_get_hw_flow_ctrl(uart_port_t uart_num); +esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flow_ctrl); /** * @brief Clear UART interrupt status @@ -453,6 +443,7 @@ esp_err_t uart_driver_delete(uart_port_t uart_num); * @param TickType_t ticks_to_wait: Timeout, count in RTOS ticks * * @return ESP_OK : Success + * ESP_FAIL : Parameter error * ESP_ERR_TIMEOUT: Timeout */ esp_err_t uart_wait_tx_fifo_empty(uart_port_t uart_num, TickType_t ticks_to_wait); @@ -465,7 +456,8 @@ esp_err_t uart_wait_tx_fifo_empty(uart_port_t uart_num, TickType_t ticks_to_wait * @param char* buffer : data buffer address * @param uint32_t len : data length to send * - * @return The number of data that pushed to the TX FIFO + * @return -1 : Parameter error + * OTHERS(>=0): The number of data that pushed to the TX FIFO */ int uart_tx_chars(uart_port_t uart_no, char* buffer, uint32_t len); @@ -477,7 +469,8 @@ int uart_tx_chars(uart_port_t uart_no, char* buffer, uint32_t len); * @param char* src : data buffer address * @param size_t size : data length to send * - * @return The number of data that sent out. + * @return -1 : Parameter error + * OTHERS(>=0): The number of data that pushed to the TX FIFO */ int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size); @@ -490,7 +483,8 @@ int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size); * @param size_t size : data length to send * @param int brk_len : break signal length (unit: one bit's time@current_baudrate) * - * @return The number of data that sent out. + * @return -1 : Parameter error + * OTHERS(>=0): The number of data that pushed to the TX FIFO */ int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len); @@ -498,20 +492,20 @@ int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t s * @brief UART read one char * * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param TickType_t ticks_to_wait : ticks to wait. + * @param TickType_t ticks_to_wait : Timeout, count in RTOS ticks * * @return -1 : Error - * Others : return a char data from uart fifo. + * Others : return a char data from UART. */ int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait); /** * @brief UART read bytes from UART buffer * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param uint8_t* buf : pointer to the buffer. - * @param uint32_t length : data length - * @param TickType_t ticks_to_wait: timeout time( FreeRTOS ti c + * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uint8_t* buf : pointer to the buffer. + * @param uint32_t length : data length + * @param TickType_t ticks_to_wait: Timeout, count in RTOS ticks * * @return -1 : Error * Others : return a char data from uart fifo. @@ -542,9 +536,9 @@ esp_err_t uart_set_print_port(uart_port_t uart_no); * @brief Get the current serial port for ets_printf function * * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * - * @return null + * @return current print port: 0: UART0; + * 1: UART1; + * 2: UART2; */ int uart_get_print_port(); @@ -637,7 +631,6 @@ int uart_get_print_port(); * break; * case UART_FIFO_OVF: //Event of HW FIFO overflow detected * ESP_LOGI(UART_TAG, "hw fifo overflow\n"); - * while(1); * break; * case UART_BUFFER_FULL: //Event of UART ring buffer full * ESP_LOGI(UART_TAG, "ring buffer full\n"); diff --git a/components/driver/ledc.c b/components/driver/ledc.c index 386c93dfa..771c4a17d 100644 --- a/components/driver/ledc.c +++ b/components/driver/ledc.c @@ -18,86 +18,19 @@ #include "freertos/xtensa_api.h" #include "soc/gpio_sig_map.h" #include "driver/ledc.h" +#include "esp_log.h" -//TODO: to use APIs in esp_log.h. -#define LEDC_DBG_WARING_ENABLE (0) -#define LEDC_DBG_ERROR_ENABLE (0) -#define LEDC_INFO_ENABLE (0) -#define LEDC_DBG_ENABLE (0) - -//DBG INFOR -#if LEDC_DBG_ENABLE -#define LEDC_DBG(format,...) do{\ - ets_printf("[dbg][%s#%u]",__FUNCTION__,__LINE__);\ - ets_printf(format,##__VA_ARGS__);\ -}while(0) -#else -#define LEDC_DBG(...) -#endif - -#if LEDC_INFO_ENABLE -#define LEDC_INFO(format,...) do{\ - ets_printf("[info][%s#%u]",__FUNCTION__,__LINE__);\ - ets_printf(format,##__VA_ARGS__);\ -}while(0) -#else -#define LEDC_INFO(...) -#endif - -#if LEDC_DBG_WARING_ENABLE -#define LEDC_WARING(format,...) do{\ - ets_printf("[waring][%s#%u]",__FUNCTION__,__LINE__);\ - ets_printf(format,##__VA_ARGS__);\ -}while(0) -#else -#define LEDC_WARING(...) -#endif -#if LEDC_DBG_ERROR_ENABLE -#define LEDC_ERROR(format,...) do{\ - ets_printf("[error][%s#%u]",__FUNCTION__,__LINE__);\ - ets_printf(format,##__VA_ARGS__);\ -}while(0) -#else -#define LEDC_ERROR(...) -#endif - +const char* LEDC_TAG = "LEDC"; static portMUX_TYPE ledc_spinlock = portMUX_INITIALIZER_UNLOCKED; - -static bool ledc_is_valid_channel(uint32_t channel) -{ - if(channel > LEDC_CHANNEL_7) { - LEDC_ERROR("LEDC CHANNEL ERR: %d\n",channel); - return false; - } - return true; -} - -static bool ledc_is_valid_mode(uint32_t mode) -{ - if(mode >= LEDC_SPEED_MODE_MAX) { - LEDC_ERROR("LEDC MODE ERR: %d\n",mode); - return false; - } - return true; -} - -static bool ledc_is_valid_timer(int timer) -{ - if(timer > LEDC_TIMER_3) { - LEDC_ERROR("LEDC TIMER ERR: %d\n", timer); - return false; - } - return true; -} +#define LEDC_CHECK(a, str, ret_val) if (!(a)) { \ + ESP_LOGE(LEDC_TAG,"%s:%d (%s):%s\n", __FILE__, __LINE__, __FUNCTION__, str); \ + return (ret_val); \ + } esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t div_num, uint32_t bit_num, ledc_clk_src_t clk_src) { - if(!ledc_is_valid_mode(speed_mode)) { - return ESP_ERR_INVALID_ARG; - } - if(!ledc_is_valid_timer(timer_sel)) { - return ESP_ERR_INVALID_ARG; - } + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error\n", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.div_num = div_num; LEDC.timer_group[speed_mode].timer[timer_sel].conf.tick_sel = clk_src; @@ -125,12 +58,8 @@ static esp_err_t ledc_duty_config(ledc_mode_t speed_mode, uint32_t channel_num, esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint32_t timer_idx) { - if(!ledc_is_valid_mode(speed_mode)) { - return ESP_ERR_INVALID_ARG; - } - if(!ledc_is_valid_timer(timer_idx)) { - return ESP_ERR_INVALID_ARG; - } + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(timer_idx <= LEDC_TIMER_3, "ledc timer error\n", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel = timer_idx; portEXIT_CRITICAL(&ledc_spinlock); @@ -139,12 +68,8 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel) { - if(!ledc_is_valid_mode(speed_mode)) { - return ESP_ERR_INVALID_ARG; - } - if(!ledc_is_valid_timer(timer_sel)) { - return ESP_ERR_INVALID_ARG; - } + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error\n", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.rst = 1; LEDC.timer_group[speed_mode].timer[timer_sel].conf.rst = 0; @@ -154,12 +79,8 @@ esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel) esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel) { - if(!ledc_is_valid_mode(speed_mode)) { - return ESP_ERR_INVALID_ARG; - } - if(!ledc_is_valid_timer(timer_sel)) { - return ESP_ERR_INVALID_ARG; - } + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error\n", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.pause = 1; portEXIT_CRITICAL(&ledc_spinlock); @@ -168,12 +89,8 @@ esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel) esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel) { - if(!ledc_is_valid_mode(speed_mode)) { - return ESP_ERR_INVALID_ARG; - } - if(!ledc_is_valid_timer(timer_sel)) { - return ESP_ERR_INVALID_ARG; - } + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error\n", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.pause = 0; portEXIT_CRITICAL(&ledc_spinlock); @@ -182,9 +99,7 @@ esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel) static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, uint32_t channel, ledc_intr_type_t type) { - if(!ledc_is_valid_mode(speed_mode)) { - return ESP_ERR_INVALID_ARG; - } + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); uint32_t value; uint32_t intr_type = type; portENTER_CRITICAL(&ledc_spinlock); @@ -200,9 +115,7 @@ static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, uint32_t channel, esp_err_t ledc_isr_register(uint32_t ledc_intr_num, void (*fn)(void*), void * arg) { - if(fn == NULL) { - return ESP_ERR_INVALID_ARG; - } + LEDC_CHECK(fn, "ledc isr null\n", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); ESP_INTR_DISABLE(ledc_intr_num); intr_matrix_set(xPortGetCoreID(), ETS_LEDC_INTR_SOURCE, ledc_intr_num); @@ -218,16 +131,13 @@ esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf) int bit_num = timer_conf->bit_num; int timer_num = timer_conf->timer_num; int speed_mode = timer_conf->speed_mode; - - if(!ledc_is_valid_mode(speed_mode)) { - return ESP_ERR_INVALID_ARG; - } + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); if(freq_hz == 0 || bit_num == 0 || bit_num > LEDC_TIMER_15_BIT) { - LEDC_ERROR("freq_hz=%u bit_num=%u\n", freq_hz, bit_num); + ESP_LOGE(LEDC_TAG, "freq_hz=%u bit_num=%u\n", freq_hz, bit_num); return ESP_ERR_INVALID_ARG; } if(timer_num > LEDC_TIMER_3) { - LEDC_ERROR("Time Select %u\n", timer_num); + ESP_LOGE(LEDC_TAG, "Time Select %u\n", timer_num); return ESP_ERR_INVALID_ARG; } esp_err_t ret = ESP_OK; @@ -239,7 +149,7 @@ esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf) /*Selet the reference tick*/ div_param = ((uint64_t) LEDC_REF_CLK_HZ << 8) / freq_hz / precision; if(div_param <= 256 || div_param > LEDC_DIV_NUM_HSTIMER0_V) { - LEDC_ERROR("div param err,div_param=%u\n", div_param); + ESP_LOGE(LEDC_TAG, "div param err,div_param=%u\n", (uint32_t)div_param); ret = ESP_FAIL; } timer_clk_src = LEDC_REF_TICK; @@ -254,6 +164,21 @@ esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf) return ret; } +esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc_channel) +{ + LEDC_CHECK(ledc_channel <= LEDC_CHANNEL_7, "ledc channel error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "ledc GPIO output number error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO); + gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT); + if(speed_mode == LEDC_HIGH_SPEED_MODE) { + gpio_matrix_out(gpio_num, LEDC_HS_SIG_OUT0_IDX + ledc_channel, 0, 0); + } else { + + } + return ESP_OK; +} + esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf) { uint32_t speed_mode = ledc_conf->speed_mode; @@ -262,21 +187,10 @@ esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf) uint32_t timer_select = ledc_conf->timer_sel; uint32_t intr_type = ledc_conf->intr_type; uint32_t duty = ledc_conf->duty; - - if(!ledc_is_valid_channel(ledc_channel)) { - return ESP_ERR_INVALID_ARG; - } - if(!ledc_is_valid_mode(speed_mode)) { - return ESP_ERR_INVALID_ARG; - } - if(!GPIO_IS_VALID_OUTPUT_GPIO(gpio_num)) { - LEDC_ERROR("GPIO number error: IO%d\n ", gpio_num); - return ESP_ERR_INVALID_ARG; - } - if(timer_select > LEDC_TIMER_3) { - LEDC_ERROR("Time Select %u\n", timer_select); - return ESP_ERR_INVALID_ARG; - } + LEDC_CHECK(ledc_channel <= LEDC_CHANNEL_7, "ledc channel error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "ledc GPIO output number error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(timer_select <= LEDC_TIMER_3, "ledc timer error\n", ESP_ERR_INVALID_ARG); esp_err_t ret = ESP_OK; /*set channel parameters*/ /* channel parameters decide how the waveform looks like in one period*/ @@ -288,7 +202,7 @@ esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf) ledc_bind_channel_timer(speed_mode, ledc_channel, timer_select); /*set interrupt type*/ ledc_enable_intr_type(speed_mode, ledc_channel, intr_type); - LEDC_INFO("LEDC_PWM CHANNEL %1u|GPIO %02u|Duty %04u|Time %01u\n", + ESP_LOGI(LEDC_TAG, "LEDC_PWM CHANNEL %1u|GPIO %02u|Duty %04u|Time %01u\n", ledc_channel, gpio_num, duty, timer_select ); /*set LEDC signal in gpio matrix*/ @@ -300,12 +214,8 @@ esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf) esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel) { - if(!ledc_is_valid_mode(speed_mode)) { - return ESP_ERR_INVALID_ARG; - } - if(!ledc_is_valid_channel(channel)) { - return ESP_ERR_INVALID_ARG; - } + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error\n", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 1; LEDC.channel_group[speed_mode].channel[channel].conf1.duty_start = 1; @@ -315,12 +225,8 @@ esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel) esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_level) { - if(!ledc_is_valid_mode(speed_mode)) { - return ESP_ERR_INVALID_ARG; - } - if(!ledc_is_valid_channel(channel)) { - return ESP_ERR_INVALID_ARG; - } + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error\n", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.channel_group[speed_mode].channel[channel].conf0.idle_lv = idle_level & 0x1; LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 0; @@ -331,18 +237,11 @@ esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idl esp_err_t ledc_set_fade(ledc_mode_t speed_mode, uint32_t channel, uint32_t duty, ledc_duty_direction_t fade_direction, uint32_t step_num, uint32_t duty_cyle_num, uint32_t duty_scale) { - if(!ledc_is_valid_mode(speed_mode)) { - return ESP_ERR_INVALID_ARG; - } - if(!ledc_is_valid_channel(channel)) { - return ESP_ERR_INVALID_ARG; - } - if(fade_direction > LEDC_DUTY_DIR_INCREASE) { - LEDC_ERROR("Duty direction err\n"); - return ESP_ERR_INVALID_ARG; - } + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(fade_direction <= LEDC_DUTY_DIR_INCREASE, "ledc fade direction error\n", ESP_ERR_INVALID_ARG); if(step_num > LEDC_DUTY_NUM_HSCH0_V || duty_cyle_num > LEDC_DUTY_CYCLE_HSCH0_V || duty_scale > LEDC_DUTY_SCALE_HSCH0_V) { - LEDC_ERROR("step_num=%u duty_cyle_num=%u duty_scale=%u\n", step_num, duty_cyle_num, duty_scale); + ESP_LOGE(LEDC_TAG, "step_num=%u duty_cyle_num=%u duty_scale=%u\n", step_num, duty_cyle_num, duty_scale); return ESP_ERR_INVALID_ARG; } ledc_duty_config(speed_mode, @@ -359,12 +258,8 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, uint32_t channel, uint32_t duty, esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty) { - if(!ledc_is_valid_mode(speed_mode)) { - return ESP_ERR_INVALID_ARG; - } - if(!ledc_is_valid_channel(channel)) { - return ESP_ERR_INVALID_ARG; - } + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error\n", ESP_ERR_INVALID_ARG); ledc_duty_config(speed_mode, channel, //uint32_t chan_num, 0, //uint32_t hpoint_val, @@ -379,18 +274,14 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t int ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel) { - if(!ledc_is_valid_mode(speed_mode)) { - return -1; - } + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", (-1)); uint32_t duty = (LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> 4); return duty; } esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t freq_hz) { - if(!ledc_is_valid_mode(speed_mode)) { - return ESP_ERR_INVALID_ARG; - } + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); esp_err_t ret = ESP_OK; uint32_t div_num = 0; @@ -403,7 +294,7 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t div_num = ((uint64_t) LEDC_REF_CLK_HZ << 8) / freq_hz / precision; } if(div_num <= 256 || div_num > LEDC_DIV_NUM_HSTIMER0) { - LEDC_ERROR("div param err,div_param=%u\n", div_num); + ESP_LOGE(LEDC_TAG, "div param err,div_param=%u\n", div_num); ret = ESP_FAIL; } LEDC.timer_group[speed_mode].timer[timer_num].conf.div_num = div_num; @@ -413,9 +304,7 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num) { - if(!ledc_is_valid_mode(speed_mode)) { - return 0; - } + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", (0)); portENTER_CRITICAL(&ledc_spinlock); uint32_t freq = 0; uint32_t timer_source_clk = LEDC.timer_group[speed_mode].timer[timer_num].conf.tick_sel; diff --git a/components/driver/uart.c b/components/driver/uart.c index f585c0965..29e4522d6 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -90,10 +90,11 @@ esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit return ESP_OK; } -int uart_get_word_length(uart_port_t uart_num) +esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bit) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - return UART[uart_num]->conf0.bit_num; + *(data_bit) = UART[uart_num]->conf0.bit_num; + return ESP_OK; } esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bit) @@ -106,10 +107,11 @@ esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bit) return ESP_OK; } -int uart_get_stop_bits(uart_port_t uart_num) +esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - return UART[uart_num]->conf0.stop_bit_num; + (*stop_bit) = UART[uart_num]->conf0.stop_bit_num; + return ESP_OK; } esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode) @@ -122,19 +124,20 @@ esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode) return ESP_OK; } -int uart_get_parity(uart_port_t uart_num) +esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); int val = UART[uart_num]->conf0.val; if(val & UART_PARITY_EN_M) { if(val & UART_PARITY_M) { - return UART_PARITY_ODD; + (*parity_mode) = UART_PARITY_ODD; } else { - return UART_PARITY_EVEN; + (*parity_mode) = UART_PARITY_EVEN; } } else { - return UART_PARITY_DISABLE; + (*parity_mode) = UART_PARITY_DISABLE; } + return ESP_OK; } esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate) @@ -149,14 +152,14 @@ esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate) return ESP_OK; } -int uart_get_baudrate(uart_port_t uart_num) +esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); uint32_t clk_div = (UART[uart_num]->clk_div.div_int << 4) | UART[uart_num]->clk_div.div_frag; UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); - uint32_t baudrate = ((UART_CLK_FREQ) << 4) / clk_div; - return baudrate; + (*baudrate) = ((UART_CLK_FREQ) << 4) / clk_div; + return ESP_OK; } esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask) @@ -192,7 +195,7 @@ esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow return ESP_OK; } -int uart_get_hw_flow_ctrl(uart_port_t uart_num) +esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flow_ctrl) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); uart_hw_flowcontrol_t val = UART_HW_FLOWCTRL_DISABLE; @@ -202,7 +205,8 @@ int uart_get_hw_flow_ctrl(uart_port_t uart_num) if(UART[uart_num]->conf0.tx_flow_en) { val |= UART_HW_FLOWCTRL_CTS; } - return val; + (*flow_ctrl) = val; + return ESP_OK; } static esp_err_t uart_reset_fifo(uart_port_t uart_num) @@ -311,11 +315,11 @@ esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (* //only one GPIO pad can connect with input signal esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((tx_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(tx_io_num))), "tx_io_num error"); - UART_CHECK((rx_io_num < 0 || (GPIO_IS_VALID_GPIO(rx_io_num))), "rx_io_num error"); - UART_CHECK((rts_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(rts_io_num))), "rts_io_num error"); - UART_CHECK((cts_io_num < 0 || (GPIO_IS_VALID_GPIO(cts_io_num))), "cts_io_num error"); +// UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); +// UART_CHECK((tx_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(tx_io_num))), "tx_io_num error"); +// UART_CHECK((rx_io_num < 0 || (GPIO_IS_VALID_GPIO(rx_io_num))), "rx_io_num error"); +// UART_CHECK((rts_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(rts_io_num))), "rts_io_num error"); +// UART_CHECK((cts_io_num < 0 || (GPIO_IS_VALID_GPIO(cts_io_num))), "cts_io_num error"); int tx_sig, rx_sig, rts_sig, cts_sig; switch(uart_num) { From d9005e739dbf1e32aab0b2cbce01eae100d43ef6 Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Mon, 24 Oct 2016 21:18:02 +0800 Subject: [PATCH 04/12] Add bytebuffer support to ringbuf.c --- .../freertos/include/freertos/ringbuf.h | 50 ++- components/freertos/ringbuf.c | 344 +++++++++++++----- 2 files changed, 303 insertions(+), 91 deletions(-) diff --git a/components/freertos/include/freertos/ringbuf.h b/components/freertos/include/freertos/ringbuf.h index 7884e9856..93ba30758 100644 --- a/components/freertos/include/freertos/ringbuf.h +++ b/components/freertos/include/freertos/ringbuf.h @@ -18,22 +18,34 @@ to this bit of memory will block. The requirement for items to be contiguous is slightly problematic when the only way to place the next item would involve a wraparound from the end to the beginning of the ringbuffer. This can -be solved in two ways: -- allow_split_items = pdTRUE: The insertion code will split the item in two items; one which fits +be solved (or not) in a few ways: +- type = RINGBUF_TYPE_ALLOWSPLIT: The insertion code will split the item in two items; one which fits in the space left at the end of the ringbuffer, one that contains the remaining data which is placed in the beginning. Two xRingbufferReceive calls will be needed to retrieve the data. -- allow_split_items = pdFALSE: The insertion code will leave the room at the end of the ringbuffer +- type = RINGBUF_TYPE_NOSPLIT: The insertion code will leave the room at the end of the ringbuffer unused and instead will put the entire item at the start of the ringbuffer, as soon as there is enough free space. +- type = RINGBUF_TYPE_BYTEBUF: This is your conventional byte-based ringbuffer. It does have no +overhead, but it has no item contiguousness either: a read will just give you the entire written +buffer space, or the space up to the end of the buffer, and writes can be broken up in any way +possible. Note that this type cannot do a 2nd read before returning the memory of the 1st. The maximum size of an item will be affected by this decision. When split items are allowed, it's acceptable to push items of (buffer_size)-16 bytes into the buffer. When it's not allowed, the -maximum size is (buffer_size/2)-8 bytes. +maximum size is (buffer_size/2)-8 bytes. The bytebuf can fill the entire buffer with data, it has +no overhead. */ //An opaque handle for a ringbuff object. typedef void * RingbufHandle_t; +//The various types of buffer +typedef enum { + RINGBUF_TYPE_NOSPLIT = 0, + RINGBUF_TYPE_ALLOWSPLIT, + RINGBUF_TYPE_BYTEBUF +} ringbuf_type_t; + /** * @brief Create a ring buffer @@ -45,7 +57,7 @@ typedef void * RingbufHandle_t; * * @return A RingbufHandle_t handle to the created ringbuffer, or NULL in case of error. */ -RingbufHandle_t xRingbufferCreate(size_t buf_length, BaseType_t allow_split_items); +RingbufHandle_t xRingbufferCreate(size_t buf_length, ringbuf_type_t type); /** @@ -120,6 +132,34 @@ void *xRingbufferReceive(RingbufHandle_t ringbuf, size_t *item_size, TickType_t void *xRingbufferReceiveFromISR(RingbufHandle_t ringbuf, size_t *item_size); +/** + * @brief Retrieve bytes from a ByteBuf type of ring buffer, specifying the maximum amount of bytes + * to return + * + * @param ringbuf - Ring buffer to retrieve the item from + * @param item_size - Pointer to a variable to which the size of the retrieved item will be written. + * @param xTicksToWait - Ticks to wait for items in the ringbuffer. + * + * @return Pointer to the retrieved item on success; *item_size filled with the length of the + * item. NULL on timeout, *item_size is untouched in that case. + */ +void *xRingbufferReceiveUpTo(RingbufHandle_t ringbuf, size_t *item_size, TickType_t ticks_to_wait, size_t wanted_size); + + +/** + * @brief Retrieve bytes from a ByteBuf type of ring buffer, specifying the maximum amount of bytes + * to return. Call this from an ISR. + * + * @param ringbuf - Ring buffer to retrieve the item from + * @param item_size - Pointer to a variable to which the size of the retrieved item will be written. + * + * @return Pointer to the retrieved item on success; *item_size filled with the length of the + * item. NULL when the ringbuffer is empty, *item_size is untouched in that case. + */ +void *xRingbufferReceiveUpToFromISR(RingbufHandle_t ringbuf, size_t *item_size, size_t wanted_size); + + + /** * @brief Return a previously-retrieved item to the ringbuffer * diff --git a/components/freertos/ringbuf.c b/components/freertos/ringbuf.c index 365175314..77eb36284 100644 --- a/components/freertos/ringbuf.c +++ b/components/freertos/ringbuf.c @@ -18,6 +18,7 @@ #include "freertos/queue.h" #include "freertos/xtensa_api.h" #include "freertos/ringbuf.h" +#include "esp_attr.h" #include #include #include @@ -25,6 +26,7 @@ typedef enum { flag_allowsplit = 1, + flag_bytebuf = 2, } rbflag_t; typedef enum { @@ -33,8 +35,10 @@ typedef enum { } itemflag_t; +typedef struct ringbuf_t ringbuf_t; + //The ringbuffer structure -typedef struct { +struct ringbuf_t { SemaphoreHandle_t free_space_sem; //Binary semaphore, wakes up writing threads when there's more free space SemaphoreHandle_t items_buffered_sem; //Binary semaphore, indicates there are new packets in the circular buffer. See remark. size_t size; //Size of the data storage @@ -44,7 +48,12 @@ typedef struct { uint8_t *data; //Data storage portMUX_TYPE mux; //Spinlock for actual data/ptr/struct modification rbflag_t flags; -} ringbuf_t; + size_t maxItemSize; + //The following keep function pointers to hold different implementations for ringbuffer management. + BaseType_t (*copyItemToRingbufImpl)(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size); + uint8_t *(*getItemFromRingbufImpl)(ringbuf_t *rb, size_t *length, int wanted_length); + void (*returnItemToRingbufImpl)(ringbuf_t *rb, void *item); +}; @@ -73,14 +82,16 @@ static int ringbufferFreeMem(ringbuf_t *rb) return free_size-1; } -//Copies a single item to the ring buffer. Assumes there is space in the ringbuffer and + +//Copies a single item to the ring buffer; refuses to split items. Assumes there is space in the ringbuffer and //the ringbuffer is locked. Increases write_ptr to the next item. Returns pdTRUE on //success, pdFALSE if it can't make the item fit and the calling routine needs to retry //later or fail. //This function by itself is not threadsafe, always call from within a muxed section. -static BaseType_t copyItemToRingbuf(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size) +static BaseType_t copyItemToRingbufNoSplit(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size) { - size_t rbuffer_size=(buffer_size+3)&~3; //Payload length, rounded to next 32-bit value + size_t rbuffer_size; + rbuffer_size=(buffer_size+3)&~3; //Payload length, rounded to next 32-bit value configASSERT(((int)rb->write_ptr&3)==0); //write_ptr needs to be 32-bit aligned configASSERT(rb->write_ptr-(rb->data+rb->size) >= sizeof(buf_entry_hdr_t)); //need to have at least the size //of a header to the end of the ringbuff @@ -88,65 +99,28 @@ static BaseType_t copyItemToRingbuf(ringbuf_t *rb, uint8_t *buffer, size_t buffe //See if we have enough contiguous space to write the buffer. if (rem_len < rbuffer_size + sizeof(buf_entry_hdr_t)) { - //The buffer can't be contiguously written to the ringbuffer, but needs special handling. Do - //that depending on how the ringbuffer is configured. - //The code here is also expected to check if the buffer, mangled in whatever way is implemented, - //will still fit, and return pdFALSE if that is not the case. - if (rb->flags & flag_allowsplit) { - //Buffer plus header is not going to fit in the room from wr_pos to the end of the - //ringbuffer... we need to split the write in two. - //First, see if this will fit at all. - if (ringbufferFreeMem(rb) < (sizeof(buf_entry_hdr_t)*2)+rbuffer_size) { - //Will not fit. - return pdFALSE; - } - //Because the code at the end of the function makes sure we always have - //room for a header, this should never assert. - configASSERT(rem_len>=sizeof(buf_entry_hdr_t)); - //Okay, it should fit. Write everything. - //First, place bit of buffer that does fit. Write header first... - buf_entry_hdr_t *hdr=(buf_entry_hdr_t *)rb->write_ptr; - hdr->flags=0; - hdr->len=rem_len-sizeof(buf_entry_hdr_t); - rb->write_ptr+=sizeof(buf_entry_hdr_t); - rem_len-=sizeof(buf_entry_hdr_t); - if (rem_len!=0) { - //..then write the data bit that fits. - memcpy(rb->write_ptr, buffer, rem_len); - //Update vars so the code later on will write the rest of the data. - buffer+=rem_len; - rbuffer_size-=rem_len; - buffer_size-=rem_len; - } else { - //Huh, only the header fit. Mark as dummy so the receive function doesn't receive - //an useless zero-byte packet. - hdr->flags|=iflag_dummydata; - } - rb->write_ptr=rb->data; - } else { - //Buffer plus header is not going to fit in the room from wr_pos to the end of the - //ringbuffer... but we're not allowed to split the buffer. We need to fill the - //rest of the ringbuffer with a dummy item so we can place the data at the _start_ of - //the ringbuffer.. - //First, find out if we actually have enough space at the start of the ringbuffer to - //make this work (Again, we need 4 bytes extra because otherwise read_ptr==free_ptr) - if (rb->free_ptr-rb->data < rbuffer_size+sizeof(buf_entry_hdr_t)+4) { - //Will not fit. - return pdFALSE; - } - //If the read buffer hasn't wrapped around yet, there's no way this will work either. - if (rb->free_ptr > rb->write_ptr) { - //No luck. - return pdFALSE; - } - - //Okay, it will fit. Mark the rest of the ringbuffer space with a dummy packet. - buf_entry_hdr_t *hdr=(buf_entry_hdr_t *)rb->write_ptr; - hdr->flags=iflag_dummydata; - //Reset the write pointer to the start of the ringbuffer so the code later on can - //happily write the data. - rb->write_ptr=rb->data; + //Buffer plus header is not going to fit in the room from wr_pos to the end of the + //ringbuffer... but we're not allowed to split the buffer. We need to fill the + //rest of the ringbuffer with a dummy item so we can place the data at the _start_ of + //the ringbuffer.. + //First, find out if we actually have enough space at the start of the ringbuffer to + //make this work (Again, we need 4 bytes extra because otherwise read_ptr==free_ptr) + if (rb->free_ptr-rb->data < rbuffer_size+sizeof(buf_entry_hdr_t)+4) { + //Will not fit. + return pdFALSE; } + //If the read buffer hasn't wrapped around yet, there's no way this will work either. + if (rb->free_ptr > rb->write_ptr) { + //No luck. + return pdFALSE; + } + + //Okay, it will fit. Mark the rest of the ringbuffer space with a dummy packet. + buf_entry_hdr_t *hdr=(buf_entry_hdr_t *)rb->write_ptr; + hdr->flags=iflag_dummydata; + //Reset the write pointer to the start of the ringbuffer so the code later on can + //happily write the data. + rb->write_ptr=rb->data; } else { //No special handling needed. Checking if it's gonna fit probably still is a good idea. if (ringbufferFreeMem(rb) < sizeof(buf_entry_hdr_t)+rbuffer_size) { @@ -174,9 +148,117 @@ static BaseType_t copyItemToRingbuf(ringbuf_t *rb, uint8_t *buffer, size_t buffe return pdTRUE; } +//Copies a single item to the ring buffer; allows split items. Assumes there is space in the ringbuffer and +//the ringbuffer is locked. Increases write_ptr to the next item. Returns pdTRUE on +//success, pdFALSE if it can't make the item fit and the calling routine needs to retry +//later or fail. +//This function by itself is not threadsafe, always call from within a muxed section. +static BaseType_t copyItemToRingbufAllowSplit(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size) +{ + size_t rbuffer_size; + rbuffer_size=(buffer_size+3)&~3; //Payload length, rounded to next 32-bit value + configASSERT(((int)rb->write_ptr&3)==0); //write_ptr needs to be 32-bit aligned + configASSERT(rb->write_ptr-(rb->data+rb->size) >= sizeof(buf_entry_hdr_t)); //need to have at least the size + //of a header to the end of the ringbuff + size_t rem_len=(rb->data + rb->size) - rb->write_ptr; //length remaining until end of ringbuffer + + //See if we have enough contiguous space to write the buffer. + if (rem_len < rbuffer_size + sizeof(buf_entry_hdr_t)) { + //The buffer can't be contiguously written to the ringbuffer, but needs special handling. Do + //that depending on how the ringbuffer is configured. + //The code here is also expected to check if the buffer, mangled in whatever way is implemented, + //will still fit, and return pdFALSE if that is not the case. + //Buffer plus header is not going to fit in the room from wr_pos to the end of the + //ringbuffer... we need to split the write in two. + //First, see if this will fit at all. + if (ringbufferFreeMem(rb) < (sizeof(buf_entry_hdr_t)*2)+rbuffer_size) { + //Will not fit. + return pdFALSE; + } + //Because the code at the end of the function makes sure we always have + //room for a header, this should never assert. + configASSERT(rem_len>=sizeof(buf_entry_hdr_t)); + //Okay, it should fit. Write everything. + //First, place bit of buffer that does fit. Write header first... + buf_entry_hdr_t *hdr=(buf_entry_hdr_t *)rb->write_ptr; + hdr->flags=0; + hdr->len=rem_len-sizeof(buf_entry_hdr_t); + rb->write_ptr+=sizeof(buf_entry_hdr_t); + rem_len-=sizeof(buf_entry_hdr_t); + if (rem_len!=0) { + //..then write the data bit that fits. + memcpy(rb->write_ptr, buffer, rem_len); + //Update vars so the code later on will write the rest of the data. + buffer+=rem_len; + rbuffer_size-=rem_len; + buffer_size-=rem_len; + } else { + //Huh, only the header fit. Mark as dummy so the receive function doesn't receive + //an useless zero-byte packet. + hdr->flags|=iflag_dummydata; + } + rb->write_ptr=rb->data; + } else { + //No special handling needed. Checking if it's gonna fit probably still is a good idea. + if (ringbufferFreeMem(rb) < sizeof(buf_entry_hdr_t)+rbuffer_size) { + //Buffer is not going to fit, period. + return pdFALSE; + } + } + + //If we are here, the buffer is guaranteed to fit in the space starting at the write pointer. + buf_entry_hdr_t *hdr=(buf_entry_hdr_t *)rb->write_ptr; + hdr->len=buffer_size; + hdr->flags=0; + rb->write_ptr+=sizeof(buf_entry_hdr_t); + memcpy(rb->write_ptr, buffer, buffer_size); + rb->write_ptr+=rbuffer_size; + + //The buffer will wrap around if we don't have room for a header anymore. + if ((rb->data+rb->size)-rb->write_ptr < sizeof(buf_entry_hdr_t)) { + //'Forward' the write buffer until we are at the start of the ringbuffer. + //The read pointer will always be at the start of a full header, which cannot + //exist at the point of the current write pointer, so there's no chance of overtaking + //that. + rb->write_ptr=rb->data; + } + return pdTRUE; +} + + +//Copies a bunch of daya to the ring bytebuffer. Assumes there is space in the ringbuffer and +//the ringbuffer is locked. Increases write_ptr to the next item. Returns pdTRUE on +//success, pdFALSE if it can't make the item fit and the calling routine needs to retry +//later or fail. +//This function by itself is not threadsafe, always call from within a muxed section. +static BaseType_t copyItemToRingbufByteBuf(ringbuf_t *rb, uint8_t *buffer, size_t buffer_size) +{ + size_t rem_len=(rb->data + rb->size) - rb->write_ptr; //length remaining until end of ringbuffer + + //See if we have enough contiguous space to write the buffer. + if (rem_len < buffer_size) { + //...Nope. Write the data bit that fits. + memcpy(rb->write_ptr, buffer, rem_len); + //Update vars so the code later on will write the rest of the data. + buffer+=rem_len; + buffer_size-=rem_len; + rb->write_ptr=rb->data; + } + + //If we are here, the buffer is guaranteed to fit in the space starting at the write pointer. + memcpy(rb->write_ptr, buffer, buffer_size); + rb->write_ptr+=buffer_size; + //The buffer will wrap around if we're at the end. + if ((rb->data+rb->size)==rb->write_ptr) { + rb->write_ptr=rb->data; + } + return pdTRUE; +} + //Retrieves a pointer to the data of the next item, or NULL if this is not possible. //This function by itself is not threadsafe, always call from within a muxed section. -static uint8_t *getItemFromRingbuf(ringbuf_t *rb, size_t *length) +//Because we always return one item, this function ignores the wanted_length variable. +static uint8_t *getItemFromRingbufDefault(ringbuf_t *rb, size_t *length, int wanted_length) { uint8_t *ret; configASSERT(((int)rb->read_ptr&3)==0); @@ -210,10 +292,48 @@ static uint8_t *getItemFromRingbuf(ringbuf_t *rb, size_t *length) return ret; } +//Retrieves a pointer to the data in the buffer, or NULL if this is not possible. +//This function by itself is not threadsafe, always call from within a muxed section. +//This function honours the wanted_length and will never return more data than this. +static uint8_t *getItemFromRingbufByteBuf(ringbuf_t *rb, size_t *length, int wanted_length) +{ + uint8_t *ret; + if (rb->read_ptr != rb->free_ptr) { + //This type of ringbuff does not support multiple outstanding buffers. + return NULL; + } + if (rb->read_ptr == rb->write_ptr) { + //No data available. + return NULL; + } + ret=rb->read_ptr; + if (rb->read_ptr > rb->write_ptr) { + //Available data wraps around. Give data until the end of the buffer. + *length=rb->size-(rb->read_ptr - rb->data); + if (wanted_length != 0 && *length > wanted_length) { + *length=wanted_length; + rb->read_ptr+=wanted_length; + } else { + rb->read_ptr=rb->data; + } + } else { + //Return data up to write pointer. + *length=rb->write_ptr -rb->read_ptr; + if (wanted_length != 0 && *length > wanted_length) { + *length=wanted_length; + rb->read_ptr+=wanted_length; + } else { + rb->read_ptr=rb->write_ptr; + } + } + return ret; +} + + //Returns an item to the ringbuffer. Will mark the item as free, and will see if the free pointer //can be increase. //This function by itself is not threadsafe, always call from within a muxed section. -static void returnItemToRingbuf(ringbuf_t *rb, void *item) { +static void returnItemToRingbufDefault(ringbuf_t *rb, void *item) { uint8_t *data=(uint8_t*)item; configASSERT(((int)rb->free_ptr&3)==0); configASSERT(data >= rb->data); @@ -249,6 +369,17 @@ static void returnItemToRingbuf(ringbuf_t *rb, void *item) { } +//Returns an item to the ringbuffer. Will mark the item as free, and will see if the free pointer +//can be increase. +//This function by itself is not threadsafe, always call from within a muxed section. +static void returnItemToRingbufBytebuf(ringbuf_t *rb, void *item) { + uint8_t *data=(uint8_t*)item; + configASSERT(data >= rb->data); + configASSERT(data < rb->data+rb->size); + //Free the read memory. + rb->free_ptr=rb->read_ptr; +} + void xRingbufferPrintInfo(RingbufHandle_t ringbuf) { ringbuf_t *rb=(ringbuf_t *)ringbuf; @@ -259,7 +390,7 @@ void xRingbufferPrintInfo(RingbufHandle_t ringbuf) -RingbufHandle_t xRingbufferCreate(size_t buf_length, BaseType_t allow_split_items) +RingbufHandle_t xRingbufferCreate(size_t buf_length, ringbuf_type_t type) { ringbuf_t *rb = malloc(sizeof(ringbuf_t)); if (rb==NULL) goto err; @@ -273,9 +404,35 @@ RingbufHandle_t xRingbufferCreate(size_t buf_length, BaseType_t allow_split_item rb->free_space_sem = xSemaphoreCreateBinary(); rb->items_buffered_sem = xSemaphoreCreateBinary(); rb->flags=0; - if (allow_split_items) rb->flags|=flag_allowsplit; + if (type==RINGBUF_TYPE_ALLOWSPLIT) { + rb->flags|=flag_allowsplit; + rb->copyItemToRingbufImpl=copyItemToRingbufAllowSplit; + rb->getItemFromRingbufImpl=getItemFromRingbufDefault; + rb->returnItemToRingbufImpl=returnItemToRingbufDefault; + //Calculate max item size. Worst case, we need to split an item into two, which means two headers of overhead. + rb->maxItemSize=rb->size-(sizeof(buf_entry_hdr_t)*2)-4; + } else if (type==RINGBUF_TYPE_BYTEBUF) { + rb->flags|=flag_bytebuf; + rb->copyItemToRingbufImpl=copyItemToRingbufByteBuf; + rb->getItemFromRingbufImpl=getItemFromRingbufByteBuf; + rb->returnItemToRingbufImpl=returnItemToRingbufBytebuf; + //Calculate max item size. We have no headers and can split anywhere -> size is total size minus one. + rb->maxItemSize=rb->size-1; + } else if (type==RINGBUF_TYPE_NOSPLIT) { + rb->copyItemToRingbufImpl=copyItemToRingbufNoSplit; + rb->getItemFromRingbufImpl=getItemFromRingbufDefault; + rb->returnItemToRingbufImpl=returnItemToRingbufDefault; + //Calculate max item size. Worst case, we have the write ptr in such a position that we are lacking four bytes of free + //memory to put an item into the rest of the memory. If this happens, we have to dummy-fill + //(item_data-4) bytes of buffer, then we only have (size-(item_data-4) bytes left to fill + //with the real item. (item size being header+data) + rb->maxItemSize=(rb->size/2)-sizeof(buf_entry_hdr_t)-4; + } else { + configASSERT(0); + } if (rb->free_space_sem == NULL || rb->items_buffered_sem == NULL) goto err; vPortCPUInitializeMutex(&rb->mux); + return (RingbufHandle_t)rb; err: @@ -303,18 +460,7 @@ size_t xRingbufferGetMaxItemSize(RingbufHandle_t ringbuf) { ringbuf_t *rb=(ringbuf_t *)ringbuf; configASSERT(rb); - //In both cases, we return 4 bytes less than what we actually can have. If the ringbuffer is - //indeed entirely filled, read_ptr==free_ptr, which throws off the free space calculation. - if (rb->flags & flag_allowsplit) { - //Worst case, we need to split an item into two, which means two headers of overhead. - return rb->size-(sizeof(buf_entry_hdr_t)*2)-4; - } else { - //Worst case, we have the write ptr in such a position that we are lacking four bytes of free - //memory to put an item into the rest of the memory. If this happens, we have to dummy-fill - //(item_data-4) bytes of buffer, then we only have (size-(item_data-4) bytes left to fill - //with the real item. (item size being header+data) - return (rb->size/2)-sizeof(buf_entry_hdr_t)-4; - } + return rb->maxItemSize; } BaseType_t xRingbufferSend(RingbufHandle_t ringbuf, void *data, size_t dataSize, TickType_t ticks_to_wait) @@ -352,7 +498,7 @@ BaseType_t xRingbufferSend(RingbufHandle_t ringbuf, void *data, size_t dataSize, portENTER_CRITICAL(&rb->mux); //Another thread may have been able to sneak its write first. Check again now we locked the ringbuff, and retry //everything if this is the case. Otherwise, we can write and are done. - done=copyItemToRingbuf(rb, data, dataSize); + done=rb->copyItemToRingbufImpl(rb, data, dataSize); portEXIT_CRITICAL(&rb->mux); } xSemaphoreGive(rb->items_buffered_sem); @@ -371,7 +517,7 @@ BaseType_t xRingbufferSendFromISR(RingbufHandle_t ringbuf, void *data, size_t da //Does not fit in the remaining space in the ringbuffer. write_succeeded=pdFALSE; } else { - write_succeeded = copyItemToRingbuf(rb, data, dataSize); + write_succeeded = rb->copyItemToRingbufImpl(rb, data, dataSize); } portEXIT_CRITICAL_ISR(&rb->mux); if (write_succeeded) { @@ -381,7 +527,7 @@ BaseType_t xRingbufferSendFromISR(RingbufHandle_t ringbuf, void *data, size_t da } -void *xRingbufferReceive(RingbufHandle_t ringbuf, size_t *item_size, TickType_t ticks_to_wait) +static void *xRingbufferReceiveGeneric(RingbufHandle_t ringbuf, size_t *item_size, TickType_t ticks_to_wait, size_t wanted_size) { ringbuf_t *rb=(ringbuf_t *)ringbuf; uint8_t *itemData; @@ -398,7 +544,7 @@ void *xRingbufferReceive(RingbufHandle_t ringbuf, size_t *item_size, TickType_t } //Okay, we seem to have data in the buffer. Grab the mux and copy it out if it's still there. portENTER_CRITICAL(&rb->mux); - itemData=getItemFromRingbuf(rb, item_size); + itemData=rb->getItemFromRingbufImpl(rb, item_size, wanted_size); portEXIT_CRITICAL(&rb->mux); if (itemData) { //We managed to get an item. @@ -408,6 +554,11 @@ void *xRingbufferReceive(RingbufHandle_t ringbuf, size_t *item_size, TickType_t return (void*)itemData; } +void *xRingbufferReceive(RingbufHandle_t ringbuf, size_t *item_size, TickType_t ticks_to_wait) +{ + return xRingbufferReceiveGeneric(ringbuf, item_size, ticks_to_wait, 0); +} + void *xRingbufferReceiveFromISR(RingbufHandle_t ringbuf, size_t *item_size) { @@ -415,7 +566,28 @@ void *xRingbufferReceiveFromISR(RingbufHandle_t ringbuf, size_t *item_size) uint8_t *itemData; configASSERT(rb); portENTER_CRITICAL_ISR(&rb->mux); - itemData=getItemFromRingbuf(rb, item_size); + itemData=rb->getItemFromRingbufImpl(rb, item_size, 0); + portEXIT_CRITICAL_ISR(&rb->mux); + return (void*)itemData; +} + +void *xRingbufferReceiveUpTo(RingbufHandle_t ringbuf, size_t *item_size, TickType_t ticks_to_wait, size_t wanted_size) { + ringbuf_t *rb=(ringbuf_t *)ringbuf; + if (wanted_size == 0) return NULL; + configASSERT(rb); + configASSERT(rb->flags & flag_bytebuf); + return xRingbufferReceiveGeneric(ringbuf, item_size, ticks_to_wait, wanted_size); +} + +void *xRingbufferReceiveUpToFromISR(RingbufHandle_t ringbuf, size_t *item_size, size_t wanted_size) +{ + ringbuf_t *rb=(ringbuf_t *)ringbuf; + uint8_t *itemData; + if (wanted_size == 0) return NULL; + configASSERT(rb); + configASSERT(rb->flags & flag_bytebuf); + portENTER_CRITICAL_ISR(&rb->mux); + itemData=rb->getItemFromRingbufImpl(rb, item_size, 0); portEXIT_CRITICAL_ISR(&rb->mux); return (void*)itemData; } @@ -425,7 +597,7 @@ void vRingbufferReturnItem(RingbufHandle_t ringbuf, void *item) { ringbuf_t *rb=(ringbuf_t *)ringbuf; portENTER_CRITICAL_ISR(&rb->mux); - returnItemToRingbuf(rb, item); + rb->returnItemToRingbufImpl(rb, item); portEXIT_CRITICAL_ISR(&rb->mux); xSemaphoreGive(rb->free_space_sem); } @@ -435,7 +607,7 @@ void vRingbufferReturnItemFromISR(RingbufHandle_t ringbuf, void *item, BaseType_ { ringbuf_t *rb=(ringbuf_t *)ringbuf; portENTER_CRITICAL_ISR(&rb->mux); - returnItemToRingbuf(rb, item); + rb->returnItemToRingbufImpl(rb, item); portEXIT_CRITICAL_ISR(&rb->mux); xSemaphoreGiveFromISR(rb->free_space_sem, higher_prio_task_awoken); } From d7ea61734b2474460fde113833a382a81ba88fb6 Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Mon, 24 Oct 2016 21:25:48 +0800 Subject: [PATCH 05/12] Tabs -> spaces --- components/freertos/ringbuf.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/components/freertos/ringbuf.c b/components/freertos/ringbuf.c index 77eb36284..ce5504596 100644 --- a/components/freertos/ringbuf.c +++ b/components/freertos/ringbuf.c @@ -556,7 +556,7 @@ static void *xRingbufferReceiveGeneric(RingbufHandle_t ringbuf, size_t *item_siz void *xRingbufferReceive(RingbufHandle_t ringbuf, size_t *item_size, TickType_t ticks_to_wait) { - return xRingbufferReceiveGeneric(ringbuf, item_size, ticks_to_wait, 0); + return xRingbufferReceiveGeneric(ringbuf, item_size, ticks_to_wait, 0); } @@ -573,17 +573,17 @@ void *xRingbufferReceiveFromISR(RingbufHandle_t ringbuf, size_t *item_size) void *xRingbufferReceiveUpTo(RingbufHandle_t ringbuf, size_t *item_size, TickType_t ticks_to_wait, size_t wanted_size) { ringbuf_t *rb=(ringbuf_t *)ringbuf; - if (wanted_size == 0) return NULL; + if (wanted_size == 0) return NULL; configASSERT(rb); configASSERT(rb->flags & flag_bytebuf); - return xRingbufferReceiveGeneric(ringbuf, item_size, ticks_to_wait, wanted_size); + return xRingbufferReceiveGeneric(ringbuf, item_size, ticks_to_wait, wanted_size); } void *xRingbufferReceiveUpToFromISR(RingbufHandle_t ringbuf, size_t *item_size, size_t wanted_size) { ringbuf_t *rb=(ringbuf_t *)ringbuf; uint8_t *itemData; - if (wanted_size == 0) return NULL; + if (wanted_size == 0) return NULL; configASSERT(rb); configASSERT(rb->flags & flag_bytebuf); portENTER_CRITICAL_ISR(&rb->mux); From 8d6b78232728d7a987a2cae690fdd820cf8cf36a Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Tue, 1 Nov 2016 09:22:09 +0800 Subject: [PATCH 06/12] Modify UART driver: 1. Add a ring buffer for UART TX. If the buffer size is set to zero, driver will not use a buffer. But we need a task to send data from buffer to fifo. I tried directly copy data in ISR, but the code looked too long for ISR. 2. Modify the format in uart.h --- components/driver/include/driver/uart.h | 712 +++++++++++++----------- components/driver/uart.c | 421 ++++++++------ 2 files changed, 633 insertions(+), 500 deletions(-) diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index dafdf54a8..3ea77b2d0 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -24,175 +24,168 @@ extern "C" { #include "soc/uart_struct.h" #include "esp_err.h" #include "driver/periph_ctrl.h" +#include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" +#include "freertos/xtensa_api.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/ringbuf.h" #include extern const char* UART_TAG; #define UART_FIFO_LEN (128) //Do not change this, this value describes the length of the gardware FIFO in the ESP32 #define UART_INTR_MASK 0x1ff #define UART_LINE_INV_MASK (0x3f << 19) +#define UART_BITRATE_MAX 5000000 typedef enum { - UART_DATA_5_BITS = 0x0, //word length: 5bits - UART_DATA_6_BITS = 0x1, //word length: 6bits - UART_DATA_7_BITS = 0x2, //word length: 7bits - UART_DATA_8_BITS = 0x3, //word length: 8bits + UART_DATA_5_BITS = 0x0, /*!< word length: 5bits*/ + UART_DATA_6_BITS = 0x1, /*!< word length: 6bits*/ + UART_DATA_7_BITS = 0x2, /*!< word length: 7bits*/ + UART_DATA_8_BITS = 0x3, /*!< word length: 8bits*/ UART_DATA_MAX_BITS = 0X4, } uart_word_length_t; typedef enum { - UART_STOP_BITS_1 = 0x1, //stop bit: 1bit - UART_STOP_BITS_1_5 = 0x2, //stop bit: 1.5bits - UART_STOP_BITS_2 = 0x3, //stop bit: 2bits + UART_STOP_BITS_1 = 0x1, /*!< stop bit: 1bit*/ + UART_STOP_BITS_1_5 = 0x2, /*!< stop bit: 1.5bits*/ + UART_STOP_BITS_2 = 0x3, /*!< stop bit: 2bits*/ UART_STOP_BITS_MAX = 0x4, } uart_stop_bits_t; typedef enum { - UART_NUM_0 = 0x0, //base address 0x3ff40000 - UART_NUM_1 = 0x1, //base address 0x3ff50000 - UART_NUM_2 = 0x2, //base address 0x3ff6E000 + UART_NUM_0 = 0x0, /*!< UART base address 0x3ff40000*/ + UART_NUM_1 = 0x1, /*!< UART base address 0x3ff50000*/ + UART_NUM_2 = 0x2, /*!< UART base address 0x3ff6E000*/ UART_NUM_MAX, } uart_port_t; typedef enum { - UART_PARITY_DISABLE = 0x0, //Disable UART parity - UART_PARITY_EVEN = 0x10, //Enable UART even parity - UART_PARITY_ODD = 0x11 //Enable UART odd parity + UART_PARITY_DISABLE = 0x0, /*!< Disable UART parity*/ + UART_PARITY_EVEN = 0x10, /*!< Enable UART even parity*/ + UART_PARITY_ODD = 0x11 /*!< Enable UART odd parity*/ } uart_parity_t; typedef enum { - UART_BITRATE_300 = 300, - UART_BITRATE_600 = 600, - UART_BITRATE_1200 = 1200, - UART_BITRATE_2400 = 2400, - UART_BITRATE_4800 = 4800, - UART_BITRATE_9600 = 9600, - UART_BITRATE_19200 = 19200, - UART_BITRATE_38400 = 38400, - UART_BITRATE_57600 = 57600, - UART_BITRATE_74880 = 74880, - UART_BITRATE_115200 = 115200, - UART_BITRATE_230400 = 230400, - UART_BITRATE_460800 = 460800, - UART_BITRATE_921600 = 921600, - UART_BITRATE_1843200 = 1843200, - UART_BITRATE_3686400 = 3686400, - UART_BITRATE_MAX = 5000000, -} uart_baudrate_t; //you can set any rate you need in this range - -typedef enum { - UART_HW_FLOWCTRL_DISABLE = 0x0, //disable hardware flow control - UART_HW_FLOWCTRL_RTS = 0x1, //enable RX hardware flow control (rts) - UART_HW_FLOWCTRL_CTS = 0x2, //enable TX hardware flow control (cts) - UART_HW_FLOWCTRL_CTS_RTS = 0x3, //enable hardware flow control + UART_HW_FLOWCTRL_DISABLE = 0x0, /*!< disable hardware flow control*/ + UART_HW_FLOWCTRL_RTS = 0x1, /*!< enable RX hardware flow control (rts)*/ + UART_HW_FLOWCTRL_CTS = 0x2, /*!< enable TX hardware flow control (cts)*/ + UART_HW_FLOWCTRL_CTS_RTS = 0x3, /*!< enable hardware flow control*/ UART_HW_FLOWCTRL_MAX = 0x4, } uart_hw_flowcontrol_t; typedef enum { - UART_INVERSE_DISABLE = 0x0, //Disable UART wire output inverse - UART_INVERSE_RXD = (uint32_t)UART_RXD_INV_M, //UART RXD input inverse - UART_INVERSE_CTS = (uint32_t)UART_CTS_INV_M, //UART CTS input inverse - UART_INVERSE_TXD = (uint32_t)UART_TXD_INV_M, //UART TXD output inverse - UART_INVERSE_RTS = (uint32_t)UART_RTS_INV_M, //UART RTS output inverse + UART_INVERSE_DISABLE = 0x0, /*!< Disable UART wire output inverse*/ + UART_INVERSE_RXD = (uint32_t)UART_RXD_INV_M, /*!< UART RXD input inverse*/ + UART_INVERSE_CTS = (uint32_t)UART_CTS_INV_M, /*!< UART CTS input inverse*/ + UART_INVERSE_TXD = (uint32_t)UART_TXD_INV_M, /*!< UART TXD output inverse*/ + UART_INVERSE_RTS = (uint32_t)UART_RTS_INV_M, /*!< UART RTS output inverse*/ } uart_inverse_t; typedef struct { - uart_baudrate_t baud_rate; //UART baudrate - uart_word_length_t data_bits; //UART byte size - uart_parity_t parity; //UART parity mode - uart_stop_bits_t stop_bits; //UART stop bits - uart_hw_flowcontrol_t flow_ctrl; //UART hw flow control mode(cts/rts) - uint8_t rx_flow_ctrl_thresh ; //UART hw RTS threshold + int baud_rate; /*!< UART baudrate*/ + uart_word_length_t data_bits; /*!< UART byte size*/ + uart_parity_t parity; /*!< UART parity mode*/ + uart_stop_bits_t stop_bits; /*!< UART stop bits*/ + uart_hw_flowcontrol_t flow_ctrl; /*!< UART hw flow control mode(cts/rts)*/ + uint8_t rx_flow_ctrl_thresh ; /*!< UART hw RTS threshold*/ } uart_config_t; typedef struct { - uint32_t intr_enable_mask; //UART interrupt enable mask, choose from UART_XXXX_INT_ENA_M under UART_INT_ENA_REG(i), connect with bit-or operator - uint8_t rx_timeout_thresh; //UART timeout interrupt threshold(unit: time of sending one byte) - uint8_t txfifo_empty_intr_thresh; //UART TX empty interrupt threshold. - uint8_t rxfifo_full_thresh; //UART RX full interrupt threshold. + uint32_t intr_enable_mask; /*!< UART interrupt enable mask, choose from UART_XXXX_INT_ENA_M under UART_INT_ENA_REG(i), connect with bit-or operator*/ + uint8_t rx_timeout_thresh; /*!< UART timeout interrupt threshold(unit: time of sending one byte)*/ + uint8_t txfifo_empty_intr_thresh; /*!< UART TX empty interrupt threshold.*/ + uint8_t rxfifo_full_thresh; /*!< UART RX full interrupt threshold.*/ } uart_intr_config_t; - typedef enum { - UART_DATA, - UART_BREAK, - UART_BUFFER_FULL, - UART_FIFO_OVF, - UART_FRAME_ERR, - UART_PARITY_ERR, - UART_EVENT_MAX, + UART_DATA, /*!< UART data event*/ + UART_BREAK, /*!< UART break event*/ + UART_BUFFER_FULL, /*!< UART RX buffer full event*/ + UART_FIFO_OVF, /*!< UART FIFO overflow event*/ + UART_FRAME_ERR, /*!< UART RX frame error event*/ + UART_PARITY_ERR, /*!< UART RX parity event*/ + UART_DATA_BREAK, /*!< UART TX data and break event*/ + UART_EVENT_MAX, /*!< UART event max index*/ } uart_event_type_t; typedef struct { uart_event_type_t type; union { struct { + int brk_len; size_t size; + uint8_t data[]; } data; - }; } uart_event_t; - - /** * @brief Set UART data bits. * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param uart_word_length_t data_bit : UART data bits + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param data_bit UART data bits * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit); /** * @brief Get UART data bits. * - * @param uart_port_t uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_FAIL : Parameter error - * ESP_OK : Success, result will be put in (*data_bit) + * @return + * - ESP_FAIL Parameter error + * - ESP_OK Success, result will be put in (*data_bit) */ esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bit); /** * @brief Set UART stop bits. * - * @param uart_port_t uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param uart_stop_bits_t bit_num : UART stop bits + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param bit_num UART stop bits * - * @return ESP_OK : Success - * ESP_FAIL: Fail + * @return + * - ESP_OK Success + * - ESP_FAIL Fail */ esp_err_t uart_set_stop_bits(uart_port_t uart_no, uart_stop_bits_t bit_num); /** * @brief Set UART stop bits. * - * @param uart_port_t uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_FAIL : Parameter error - * ESP_OK : Success, result will be put in (*stop_bit) + * @return + * - ESP_FAIL Parameter error + * - ESP_OK Success, result will be put in (*stop_bit) */ esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit); /** * @brief Set UART parity. * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param uart_parity_t parity_mode : the enum of uart parity configuration + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param parity_mode the enum of uart parity configuration * - * @return null + * @return + * - ESP_FAIL Parameter error + * - ESP_OK Success */ esp_err_t uart_set_parity(uart_port_t uart_no, uart_parity_t parity_mode); /** * @brief Get UART parity mode. * - * @param uart_port_t uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_FAIL : Parameter error - * ESP_OK : Success, result will be put in (*parity_mode) + * @return + * - ESP_FAIL Parameter error + * - ESP_OK Success, result will be put in (*parity_mode) * */ esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode); @@ -200,32 +193,37 @@ esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode); /** * @brief Set UART baud rate. * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param uint32_t baud_rate : UART baud-rate, we can choose one from uart_baudrate_t, or set a value. + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param baud_rate UART baud-rate. * - * @return null + * @return + * - ESP_FAIL Parameter error + * - ESP_OK Success */ esp_err_t uart_set_baudrate(uart_port_t uart_no, uint32_t baud_rate); /** * @brief Get UART bit-rate. * - * @param uart_port_t uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_no: UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_FAIL : Parameter error - * ESP_OK : Success, result will be put in (*baudrate) + * @return + * - ESP_FAIL Parameter error + * - ESP_OK Success, result will be put in (*baudrate) * */ esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate); /** * @brief Set UART line inverse mode - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param uint32_t inverse_mask : Choose the wires that need to be inversed - * (Should be chosen from uart_inverse_t, combine with OR-OPERATION) + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param inverse_mask Choose the wires that need to be inversed. * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * (inverse_mask should be chosen from uart_inverse_t, combine with OR-OPERATION) + * + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_set_line_inverse(uart_port_t uart_no, uint32_t inverse_mask) ; @@ -233,57 +231,65 @@ esp_err_t uart_set_line_inverse(uart_port_t uart_no, uint32_t inverse_mask) ; /** * @brief Set hardware flow control. * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param uart_hw_flowcontrol_t flow_ctrl : Hardware flow control mode - * @param uint8_t rx_thresh : Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN) + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param flow_ctrl Hardware flow control mode + * @param rx_thresh Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN) * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_no, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh); /** * @brief Get hardware flow control mode - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_FAIL : Parameter error - * ESP_OK : Success, result will be put in (*flow_ctrl) + * @return + * - ESP_FAIL Parameter error + * - ESP_OK Success, result will be put in (*flow_ctrl) */ esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flow_ctrl); /** * @brief Clear UART interrupt status * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param uint32_t clr_mask : Bit mask of the status that to be cleared. - * enable_mask should be chosen from the fields of register UART_INT_CLR_REG + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param clr_mask Bit mask of the status that to be cleared. * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * (enable_mask should be chosen from the fields of register UART_INT_CLR_REG) + * + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask); /** * @brief Set UART interrupt enable * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param uint32_t enable_mask : Bit mask of the enable bits. - * enable_mask should be chosen from the fields of register UART_INT_ENA_REG + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param enable_mask Bit mask of the enable bits. * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * (enable_mask should be chosen from the fields of register UART_INT_ENA_REG) + * + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask); /** * @brief Clear UART interrupt enable bits * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param uint32_t disable_mask : Bit mask of the disable bits. - * Disable_mask should be chosen from the fields of register UART_INT_ENA_REG + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param disable_mask Bit mask of the disable bits. * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * (disable_mask should be chosen from the fields of register UART_INT_ENA_REG) + * + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask); @@ -291,42 +297,46 @@ esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask); /** * @brief Enable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_enable_rx_intr(uart_port_t uart_num); /** * @brief Disable UART RX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_disable_rx_intr(uart_port_t uart_num); /** * @brief Disable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_disable_tx_intr(uart_port_t uart_num); /** * @brief Enable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param int enable : 1: enable; 0: disable - * @param int thresh : Threshold of TX interrupt, 0 ~ UART_FIFO_LEN + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param enable 1: enable; 0: disable + * @param thresh Threshold of TX interrupt, 0 ~ UART_FIFO_LEN * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh); @@ -337,29 +347,31 @@ esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh); * We can find the information of INUM and interrupt level in soc.h. * * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param uint8_t uart_intr_num : UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details - * @param void (* fn)(void* ) : Interrupt handler function. - * Note that the handler function MUST be defined with attribution of "IRAM_ATTR" for now. - * @param void * arg : parameter for handler function + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details + * @param fn Interrupt handler function. + * @attention + * The ISR handler function MUST be defined with attribution of "IRAM_ATTR" for now. + * @param arg parameter for handler function * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (*fn)(void*), void * arg); /** * @brief Set UART pin number * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param tx_io_num : UART TX pin GPIO number - * @param rx_io_num : UART RX pin GPIO number - * @param rts_io_num : UART RTS pin GPIO number - * @param cts_io_num : UART CTS pin GPIO number + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param tx_io_num UART TX pin GPIO number + * @param rx_io_num UART RX pin GPIO number + * @param rts_io_num UART RTS pin GPIO number + * @param cts_io_num UART CTS pin GPIO number * - * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num); @@ -367,97 +379,107 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r * @brief UART set RTS level (before inverse) * UART rx hardware flow control should not be set. * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param int level : 1: RTS output low(active) - * 0: RTS output high(block) + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param level 1: RTS output low(active); 0: RTS output high(block) * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_set_rts(uart_port_t uart_num, int level); /** * @brief UART set DTR level (before inverse) * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param int level : 1: DTR output low - * 0: DTR output high + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param level 1: DTR output low; 0: DTR output high * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_set_dtr(uart_port_t uart_num, int level); /** * @brief UART parameter configure * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param uart_config_t *uart_config: UART parameter settings + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_config UART parameter settings * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_param_config(uart_port_t uart_num, uart_config_t *uart_config); /** * @brief UART interrupt configure * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param uart_intr_config_t *p_intr_conf: UART interrupt settings + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param p_intr_conf UART interrupt settings * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_intr_config(uart_port_t uart_num, uart_intr_config_t *p_intr_conf); /** * @brief Install UART driver. + * * UART ISR handler will be attached to the same CPU core that this function is running on. * Users should know that which CPU is running and then pick a INUM that is not used by system. * We can find the information of INUM and interrupt level in soc.h. * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param int buffer_size : UART ring buffer size - * @param int queue_size : UART event queue size/depth. - * @param int uart_intr_num : UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param rx_buffer_size UART RX ring buffer size + * @param tx_buffer_size UART TX ring buffer size, if set to zero, driver will not use TX buffer and TX task. + * @param queue_size UART event queue size/depth. + * @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details + * @param uart_queue UART event queue handle, if set NULL, driver will not use an event queue. + * @param buf_type UART RX ring_buffer type * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ -esp_err_t uart_driver_install(uart_port_t uart_num, int buffer_size, int queue_size, int uart_intr_num, void* uart_queue); +esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue, ringbuf_type_t rx_buf_type); /** * @brief Uninstall UART driver. * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_driver_delete(uart_port_t uart_num); /** * @brief Wait UART TX FIFO empty * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param TickType_t ticks_to_wait: Timeout, count in RTOS ticks + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param ticks_to_wait Timeout, count in RTOS ticks * - * @return ESP_OK : Success - * ESP_FAIL : Parameter error - * ESP_ERR_TIMEOUT: Timeout + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error + * - ESP_ERR_TIMEOUT Timeout */ -esp_err_t uart_wait_tx_fifo_empty(uart_port_t uart_num, TickType_t ticks_to_wait); +esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait); /** * @brief Send data to the UART port from a given buffer and length, * This function will not wait for the space in TX FIFO, just fill the TX FIFO and return when the FIFO is full. * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param char* buffer : data buffer address - * @param uint32_t len : data length to send + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param buffer data buffer address + * @param len data length to send * - * @return -1 : Parameter error - * OTHERS(>=0): The number of data that pushed to the TX FIFO + * @return + * - (-1) Parameter error + * - OTHERS(>=0) The number of data that pushed to the TX FIFO */ int uart_tx_chars(uart_port_t uart_no, char* buffer, uint32_t len); @@ -465,12 +487,13 @@ int uart_tx_chars(uart_port_t uart_no, char* buffer, uint32_t len); * @brief Send data to the UART port from a given buffer and length, * This function will not return until all the data have been sent out, or at least pushed into TX FIFO. * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param char* src : data buffer address - * @param size_t size : data length to send + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param src data buffer address + * @param size data length to send * - * @return -1 : Parameter error - * OTHERS(>=0): The number of data that pushed to the TX FIFO + * @return + * - (-1) Parameter error + * - OTHERS(>=0) The number of data that pushed to the TX FIFO */ int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size); @@ -478,57 +501,62 @@ int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size); * @brief Send data to the UART port from a given buffer and length, * This function will not return until all the data and the break signal have been sent out. * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param char* src : data buffer address - * @param size_t size : data length to send - * @param int brk_len : break signal length (unit: one bit's time@current_baudrate) + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param src data buffer address + * @param size data length to send + * @param brk_len break signal length (unit: one bit's time@current_baudrate) * - * @return -1 : Parameter error - * OTHERS(>=0): The number of data that pushed to the TX FIFO + * @return + * - (-1) Parameter error + * - OTHERS(>=0) The number of data that pushed to the TX FIFO */ int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len); /** * @brief UART read one char * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param TickType_t ticks_to_wait : Timeout, count in RTOS ticks + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param ticks_to_wait Timeout, count in RTOS ticks * - * @return -1 : Error - * Others : return a char data from UART. + * @return + * - (-1) Error + * - Others return a char data from UART. */ int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait); /** * @brief UART read bytes from UART buffer * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param uint8_t* buf : pointer to the buffer. - * @param uint32_t length : data length - * @param TickType_t ticks_to_wait: Timeout, count in RTOS ticks + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param buf pointer to the buffer. + * @param length data length + * @param ticks_to_wait: Timeout, count in RTOS ticks * - * @return -1 : Error - * Others : return a char data from uart fifo. + * @return + * - (-1) Error + * - Others return a char data from uart fifo. */ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait); /** * @brief UART ring buffer flush * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error */ esp_err_t uart_flush(uart_port_t uart_num); /** * @brief Set the serial output port for ets_printf function, not effective for ESP_LOGX macro. * - * @param uart_port_t uart_no : UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @return ESP_OK : Success - * ESP_FAIL: Parameter error, or UART driver not installed. + * @return + * - ESP_OK Success + * - ESP_FAIL Parameter error, or UART driver not installed. */ esp_err_t uart_set_print_port(uart_port_t uart_no); @@ -536,141 +564,155 @@ esp_err_t uart_set_print_port(uart_port_t uart_no); * @brief Get the current serial port for ets_printf function * * - * @return current print port: 0: UART0; - * 1: UART1; - * 2: UART2; + * @return current print port(0: UART0; 1: UART1; 2: UART2) */ -int uart_get_print_port(); +int uart_get_print_port(void); /***************************EXAMPLE********************************** * * * ----------------EXAMPLE OF UART SETTING --------------------- - * //1. Setup UART - * #include "freertos/queue.h" - * #define UART_INTR_NUM 17 //choose one interrupt number from soc.h - * //a. Set UART parameter - * int uart_num = 0; //uart port number + * @code{c} + * //1. Setup UART + * #include "freertos/queue.h" + * #define UART_INTR_NUM 17 //choose one interrupt number from soc.h + * //a. Set UART parameter + * int uart_num = 0; //uart port number + * uart_config_t uart_config = { + * .baud_rate = UART_BITRATE_115200, //baudrate + * .data_bits = UART_DATA_8_BITS, //data bit mode + * .parity = UART_PARITY_DISABLE, //parity mode + * .stop_bits = UART_STOP_BITS_1, //stop bit mode + * .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, //hardware flow control(cts/rts) + * .rx_flow_ctrl_thresh = 120, //flow control threshold + * }; + * uart_param_config(uart_num, &uart_config); + * //b1. Setup UART driver(with UART queue) + * QueueHandle_t uart_queue; + * uart_driver_install(uart_num, 1024 * 2, 10, UART_INTR_NUM, &uart_queue);//parameters here are just an example + * //b2. Setup UART driver(without UART queue) + * uart_driver_install(uart_num, 1024 * 2, 10, UART_INTR_NUM, NULL); //parameters here are just an example + *@endcode + *-----------------------------------------------------------------------------* + * @code{c} + * //2. Set UART pin + * uart_set_pin(uart_num, -1, -1, 15, 13); //set UART pin, not needed if use default pins. + * @endcode + *-----------------------------------------------------------------------------* + * @code{c} + * //3. Read data from UART. + * uint8_t data[128]; + * int length = 0; + * length = uart_read_bytes(uart_num, data, sizeof(data), 100); + * @endcode + *-----------------------------------------------------------------------------* + * @code{c} + * //4. Write data to UART. + * char* test_str = "This is a test string.\n" + * uart_tx_all_chars(uart_num, (const char*)test_str, strlen(test_str)); + * @endcode + *-----------------------------------------------------------------------------* + * @code{c} + * //5. Write data to UART, end with a break signal. + * uart_tx_all_chars_with_break(0, "test break\n",strlen("test break\n"), 100); + * @endcode + *-----------------------------------------------------------------------------* + * @code{c} + * //6. an example of echo test with hardware flow control on UART1 + * void uart_loop_back_test() + * { + * int uart_num = 1; * uart_config_t uart_config = { - * .baud_rate = UART_BITRATE_115200, //baudrate - * .data_bits = UART_DATA_8_BITS, //data bit mode - * .parity = UART_PARITY_DISABLE, //parity mode - * .stop_bits = UART_STOP_BITS_1, //stop bit mode - * .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, //hardware flow control(cts/rts) - * .rx_flow_ctrl_thresh = 120, //flow control threshold + * .baud_rate = 115200, + * .data_bits = UART_DATA_8_BITS, + * .parity = UART_PARITY_DISABLE, + * .stop_bits = UART_STOP_BITS_1, + * .flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS, + * .rx_flow_ctrl_thresh = 122, * }; - * uart_param_config(uart_num, &uart_config); - * //b1. Setup UART driver(with UART queue) - * QueueHandle_t uart_queue; - * uart_driver_install(uart_num, 1024 * 2, 10, UART_INTR_NUM, &uart_queue);//parameters here are just an example - * //b2. Setup UART driver(without UART queue) - * uart_driver_install(uart_num, 1024 * 2, 10, UART_INTR_NUM, NULL); //parameters here are just an example - * - *-----------------------------------------------------------------------------* - * //2. Set UART pin - * uart_set_pin(uart_num, -1, -1, 15, 13); //set UART pin, not needed if use default pins. - * - *-----------------------------------------------------------------------------* - * //3. Read data from UART. - * uint8_t data[128]; - * int length = 0; - * length = uart_read_bytes(uart_num, data, sizeof(data), 100); - * - *-----------------------------------------------------------------------------* - * //4. Write data to UART. - * char* test_str = "This is a test string.\n" - * uart_tx_all_chars(uart_num, (const char*)test_str, strlen(test_str)); - * - *-----------------------------------------------------------------------------* - * //5. Write data to UART, end with a break signal. - * uart_tx_all_chars_with_break(0, "test break\n",strlen("test break\n"), 100); - * - *-----------------------------------------------------------------------------* - * - * //6. an example of echo test with hardware flow control on UART1 - * void uart_loop_back_test() - * { - * int uart_num = 1; - * 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_CTS_RTS, - * .rx_flow_ctrl_thresh = 122, - * }; - * uart_param_config(uart_num, &uart_config); //Config UART1 parameters - * uart_set_pin(uart_num, 16, 17, 18, 19); //Set UART1 pins(TX: IO16, RX: IO17, RTS: IO18, CTS: IO19) - * esp_log_level_set(UART_TAG, ESP_LOG_ERROR); //Set UART log level - * uart_driver_install(uart_num, 1024 * 2, 10, 17, NULL); //Install UART driver( We don't need an event queue here) - * uint8_t data[1000]; - * while(1) { - * int len = uart_read_bytes(uart_num, data, sizeof(data), 10); //Read data from UART - * uart_tx_all_chars(uart_num, (const char*)data, len); //Write data back to UART - * } + * uart_param_config(uart_num, &uart_config); //Config UART1 parameters + * uart_set_pin(uart_num, 16, 17, 18, 19); //Set UART1 pins(TX: IO16, RX: IO17, RTS: IO18, CTS: IO19) + * esp_log_level_set(UART_TAG, ESP_LOG_ERROR); //Set UART log level + * //Install UART driver( We don't need an event queue here) + * uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, 17, NULL, RINGBUF_TYPE_BYTEBUF); + * uint8_t data[1000]; + * while(1) { + * int len = uart_read_bytes(uart_num, data, sizeof(data), 10); //Read data from UART + * uart_tx_all_chars(uart_num, (const char*)data, len); //Write data back to UART * } - * + * } + * @endcode *-----------------------------------------------------------------------------* - * //7. An example of using UART event queue on UART0. - * - * #include "freertos/queue.h" - * QueueHandle_t uart0_queue; //A queue to handle UART event. - * void uart_task(void *pvParameters) - * { - * int uart_num = (int)pvParameters; - * uart_event_t event; - * uint8_t dtmp[1000]; - * for(;;) { - * if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) { //Waiting for UART event. - * ESP_LOGI(UART_TAG, "uart[%d] event:", uart_num); - * switch(event.type) { - * case UART_DATA: //Event of UART receving data - * ESP_LOGI(UART_TAG,"data, len: %d\n", event.data.size); - * int len = uart_read_bytes(uart_num, dtmp, event.data.size, 10); - * ESP_LOGI(UART_TAG, "uart read: %d\n", len); - * break; - * case UART_FIFO_OVF: //Event of HW FIFO overflow detected - * ESP_LOGI(UART_TAG, "hw fifo overflow\n"); - * break; - * case UART_BUFFER_FULL: //Event of UART ring buffer full - * ESP_LOGI(UART_TAG, "ring buffer full\n"); - * break; - * case UART_BREAK: - * ESP_LOGI(UART_TAG, "uart rx break\n"); //Event of UART RX break detected - * break; - * case UART_PARITY_ERR: //Event of UART parity check error - * ESP_LOGI(UART_TAG, "uart parity error\n"); - * break; - * case UART_FRAME_ERR: //Event of UART frame error - * ESP_LOGI(UART_TAG, "uart frame error\n"); - * break; - * default: //Others - * ESP_LOGI(UART_TAG, "uart event type: %d\n", event.type); - * break; - * } - * } - * } - * vTaskDelete(NULL); - * } - * - * void uart_queue_test() - * { - * int uart_num = 0; - * 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, - * .rx_flow_ctrl_thresh = 122, - * }; - * uart_param_config(uart_num, &uart_config); //Set UART parameters - * uart_set_pin(uart_num, -1, -1, 15, 13); //Set UART pins,(-1: default pin, no change.) - * esp_log_level_set(UART_TAG, ESP_LOG_INFO); //Set UART log level - * uart_driver_install(uart_num, 1024 * 2, 10, 17, &uart0_queue); //Install UART driver, and get the queue. - * xTaskCreate(uart_task, "uTask", 2048*8, (void*)uart_num, 10, NULL); //Create a task to handler UART event from ISR + * @code{c} + * //7. An example of using UART event queue on UART0. + * #include "freertos/queue.h" + * //A queue to handle UART event. + * QueueHandle_t uart0_queue; + * void uart_task(void *pvParameters) + * { + * int uart_num = (int)pvParameters; + * uart_event_t event; + * uint8_t dtmp[1000]; + * for(;;) { + * //Waiting for UART event. + * if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) { + * ESP_LOGI(UART_TAG, "uart[%d] event:", uart_num); + * switch(event.type) { + * //Event of UART receving data + * case UART_DATA: + * ESP_LOGI(UART_TAG,"data, len: %d\n", event.data.size); + * int len = uart_read_bytes(uart_num, dtmp, event.data.size, 10); + * ESP_LOGI(UART_TAG, "uart read: %d\n", len); + * break; + * //Event of HW FIFO overflow detected + * case UART_FIFO_OVF: + * ESP_LOGI(UART_TAG, "hw fifo overflow\n"); + * break; + * //Event of UART ring buffer full + * case UART_BUFFER_FULL: + * ESP_LOGI(UART_TAG, "ring buffer full\n"); + * break; + * //Event of UART RX break detected + * case UART_BREAK: + * ESP_LOGI(UART_TAG, "uart rx break\n"); + * break; + * //Event of UART parity check error + * case UART_PARITY_ERR: + * ESP_LOGI(UART_TAG, "uart parity error\n"); + * break; + * //Event of UART frame error + * case UART_FRAME_ERR: + * ESP_LOGI(UART_TAG, "uart frame error\n"); + * break; + * //Others + * default: + * ESP_LOGI(UART_TAG, "uart event type: %d\n", event.type); + * break; + * } * } + * } + * vTaskDelete(NULL); + * } * + * void uart_queue_test() + * { + * int uart_num = 0; + * 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, + * .rx_flow_ctrl_thresh = 122, + * }; + * uart_param_config(uart_num, &uart_config); //Set UART parameters + * uart_set_pin(uart_num, -1, -1, 15, 13); //Set UART pins,(-1: default pin, no change.) + * esp_log_level_set(UART_TAG, ESP_LOG_INFO); //Set UART log level + * //Install UART driver, and get the queue. + * uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, 17, &uart0_queue, RINGBUF_TYPE_BYTEBUF); + * xTaskCreate(uart_task, "uTask", 2048*8, (void*)uart_num, 10, NULL); //Create a task to handler UART event from ISR + * } + * @endcode * ***************************END OF EXAMPLE**********************************/ diff --git a/components/driver/uart.c b/components/driver/uart.c index 29e4522d6..eeb2c6420 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -30,13 +30,15 @@ #include "soc/uart_struct.h" const char* UART_TAG = "UART"; -#define UART_CHECK(a, str) if (!(a)) { \ +#define UART_CHECK(a, str) if (!(a)) { \ ESP_LOGE(UART_TAG,"%s:%d (%s):%s\n", __FILE__, __LINE__, __FUNCTION__, str); \ return ESP_FAIL; \ } -#define DEFAULT_EMPTY_THRESH 10 -#define DEFAULT_FULL_THRESH 120 -#define DEFAULT_TOUT_THRESH 10 +#define UART_EMPTY_THRESH_DEFAULT (10) +#define UART_FULL_THRESH_DEFAULT (120) +#define UART_TOUT_THRESH_DEFAULT (10) +#define UART_TX_TASK_DEPTH_DEFAULT (256*2+64) +#define UART_TX_TASK_PRIO_DEFAULT (10) #define UART_ENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux) #define UART_EXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux) #define UART_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux) @@ -46,13 +48,19 @@ typedef struct { uart_port_t uart_num; SemaphoreHandle_t tx_fifo_sem; SemaphoreHandle_t tx_mutex; + SemaphoreHandle_t tx_buffer_mutex; SemaphoreHandle_t tx_done_sem; SemaphoreHandle_t tx_brk_sem; - SemaphoreHandle_t rx_sem; + SemaphoreHandle_t rx_mux; QueueHandle_t xQueueUart; int queue_size; int intr_num; - RingbufHandle_t ring_buffer; + int rx_buf_size; + ringbuf_type_t rx_buf_type; + RingbufHandle_t rx_ring_buf; + int tx_buf_size; + RingbufHandle_t tx_ring_buf; + TaskHandle_t tx_task_handle; bool buffer_full_flg; bool tx_waiting; int cur_remain; @@ -66,20 +74,6 @@ static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0}; static uart_dev_t* UART[UART_NUM_MAX] = {&UART0, &UART1, &UART2}; static portMUX_TYPE uart_spinlock[UART_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED}; -//Fill UART tx_fifo and return a number, -//This function by itself is not thread-safe, always call from within a muxed section. -static int uart_fill_fifo(uart_port_t uart_num, char* buffer, uint32_t len) -{ - uint8_t i = 0; - uint8_t tx_fifo_cnt = UART[uart_num]->status.txfifo_cnt; - uint8_t tx_remain_fifo_cnt = (UART_FIFO_LEN - tx_fifo_cnt); - uint8_t copy_cnt = (len >= tx_remain_fifo_cnt ? tx_remain_fifo_cnt : len); - for(i = 0; i < copy_cnt; i++) { - WRITE_PERI_REG(UART_FIFO_AHB_REG(uart_num), buffer[i]); - } - return copy_cnt; -} - esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); @@ -315,11 +309,11 @@ esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (* //only one GPIO pad can connect with input signal esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num) { -// UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); -// UART_CHECK((tx_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(tx_io_num))), "tx_io_num error"); -// UART_CHECK((rx_io_num < 0 || (GPIO_IS_VALID_GPIO(rx_io_num))), "rx_io_num error"); -// UART_CHECK((rts_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(rts_io_num))), "rts_io_num error"); -// UART_CHECK((cts_io_num < 0 || (GPIO_IS_VALID_GPIO(cts_io_num))), "cts_io_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((tx_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(tx_io_num))), "tx_io_num error"); + UART_CHECK((rx_io_num < 0 || (GPIO_IS_VALID_GPIO(rx_io_num))), "rx_io_num error"); + UART_CHECK((rts_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(rts_io_num))), "rts_io_num error"); + UART_CHECK((cts_io_num < 0 || (GPIO_IS_VALID_GPIO(cts_io_num))), "cts_io_num error"); int tx_sig, rx_sig, rts_sig, cts_sig; switch(uart_num) { @@ -443,7 +437,6 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) uart_obj_t *p_uart = (uart_obj_t*) param; uint8_t uart_num = p_uart->uart_num; uart_dev_t* uart_reg = UART[uart_num]; - uint8_t buf_idx = 0; uint32_t uart_intr_status = UART[uart_num]->int_st.val; static int rx_fifo_len = 0; @@ -478,7 +471,7 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_event.type = UART_DATA; uart_event.data.size = rx_fifo_len; - if(pdFALSE == xRingbufferSendFromISR(p_uart->ring_buffer, p_uart->data_buf, p_uart->data_len, &HPTaskAwoken)) { + if(pdFALSE == xRingbufferSendFromISR(p_uart->rx_ring_buf, p_uart->data_buf, p_uart->data_len, &HPTaskAwoken)) { UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_reg->int_ena.rxfifo_full = 0; uart_reg->int_ena.rxfifo_tout = 0; @@ -544,108 +537,7 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) } /**************************************************************/ -esp_err_t uart_driver_install(uart_port_t uart_num, int buffer_size, int queue_size, int uart_intr_num, void* uart_queue) -{ - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - if(p_uart_obj[uart_num] == NULL) { - ESP_INTR_DISABLE(uart_intr_num); - p_uart_obj[uart_num] = (uart_obj_t*) malloc(sizeof(uart_obj_t)); - if(p_uart_obj[uart_num] == NULL) { - ESP_LOGE(UART_TAG, "UART driver malloc error\n"); - return ESP_FAIL; - } - p_uart_obj[uart_num]->uart_num = uart_num; - p_uart_obj[uart_num]->tx_fifo_sem = xSemaphoreCreateBinary(); - xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); - p_uart_obj[uart_num]->tx_done_sem = xSemaphoreCreateBinary(); - xSemaphoreGive(p_uart_obj[uart_num]->tx_done_sem); - p_uart_obj[uart_num]->tx_brk_sem = xSemaphoreCreateBinary(); - - p_uart_obj[uart_num]->tx_mutex = xSemaphoreCreateMutex(); - p_uart_obj[uart_num]->rx_sem = xSemaphoreCreateMutex(); - p_uart_obj[uart_num]->intr_num = uart_intr_num; - p_uart_obj[uart_num]->queue_size = queue_size; - - if(uart_queue) { - p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t)); - *((QueueHandle_t*) uart_queue) = p_uart_obj[uart_num]->xQueueUart; - ESP_LOGI(UART_TAG, "queue free spaces: %d\n", uxQueueSpacesAvailable(p_uart_obj[uart_num]->xQueueUart)); - } else { - p_uart_obj[uart_num]->xQueueUart = NULL; - } - p_uart_obj[uart_num]->buffer_full_flg = false; - p_uart_obj[uart_num]->tx_waiting = false; - p_uart_obj[uart_num]->rd_ptr = NULL; - p_uart_obj[uart_num]->cur_remain = 0; - p_uart_obj[uart_num]->head_ptr = NULL; - p_uart_obj[uart_num]->ring_buffer = xRingbufferCreate(buffer_size, 0); - } else { - ESP_LOGE(UART_TAG, "UART driver already installed\n"); - return ESP_FAIL; - } - uart_isr_register(uart_num, uart_intr_num, uart_rx_intr_handler_default, p_uart_obj[uart_num]); - uart_intr_config_t uart_intr = { - .intr_enable_mask = UART_RXFIFO_FULL_INT_ENA_M - | UART_RXFIFO_TOUT_INT_ENA_M - | UART_FRM_ERR_INT_ENA_M - | UART_RXFIFO_OVF_INT_ENA_M - | UART_BRK_DET_INT_ENA_M, - .rxfifo_full_thresh = DEFAULT_FULL_THRESH, - .rx_timeout_thresh = DEFAULT_TOUT_THRESH, - .txfifo_empty_intr_thresh = DEFAULT_EMPTY_THRESH - }; - uart_intr_config(uart_num, &uart_intr); - ESP_INTR_ENABLE(uart_intr_num); - return ESP_OK; -} - -//Make sure no other tasks are still using UART before you call this function -esp_err_t uart_driver_delete(uart_port_t uart_num) -{ - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - if(p_uart_obj[uart_num] == NULL) { - ESP_LOGI(UART_TAG, "ALREADY NULL\n"); - return ESP_OK; - } - ESP_INTR_DISABLE(p_uart_obj[uart_num]->intr_num); - uart_disable_rx_intr(uart_num); - uart_disable_tx_intr(uart_num); - uart_isr_register(uart_num, p_uart_obj[uart_num]->intr_num, NULL, NULL); - - if(p_uart_obj[uart_num]->tx_fifo_sem) { - vSemaphoreDelete(p_uart_obj[uart_num]->tx_fifo_sem); - p_uart_obj[uart_num]->tx_fifo_sem = NULL; - } - if(p_uart_obj[uart_num]->tx_done_sem) { - vSemaphoreDelete(p_uart_obj[uart_num]->tx_done_sem); - p_uart_obj[uart_num]->tx_done_sem = NULL; - } - if(p_uart_obj[uart_num]->tx_brk_sem) { - vSemaphoreDelete(p_uart_obj[uart_num]->tx_brk_sem); - p_uart_obj[uart_num]->tx_brk_sem = NULL; - } - if(p_uart_obj[uart_num]->tx_mutex) { - vSemaphoreDelete(p_uart_obj[uart_num]->tx_mutex); - p_uart_obj[uart_num]->tx_mutex = NULL; - } - if(p_uart_obj[uart_num]->rx_sem) { - vSemaphoreDelete(p_uart_obj[uart_num]->rx_sem); - p_uart_obj[uart_num]->rx_sem = NULL; - } - if(p_uart_obj[uart_num]->xQueueUart) { - vQueueDelete(p_uart_obj[uart_num]->xQueueUart); - p_uart_obj[uart_num]->xQueueUart = NULL; - } - if(p_uart_obj[uart_num]->ring_buffer) { - vRingbufferDelete(p_uart_obj[uart_num]->ring_buffer); - p_uart_obj[uart_num]->ring_buffer = NULL; - } - free(p_uart_obj[uart_num]); - p_uart_obj[uart_num] = NULL; - return ESP_OK; -} - -esp_err_t uart_wait_tx_fifo_empty(uart_port_t uart_num, TickType_t ticks_to_wait) +esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); @@ -657,17 +549,9 @@ esp_err_t uart_wait_tx_fifo_empty(uart_port_t uart_num, TickType_t ticks_to_wait return ESP_ERR_TIMEOUT; } ticks_to_wait = ticks_end - xTaskGetTickCount(); - //take 1st tx_done_sem - res = xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, (portTickType)ticks_to_wait); - if(res == pdFALSE) { - ESP_LOGE(UART_TAG, "take uart done sem error, should not get here.\n"); - xSemaphoreGive(p_uart_obj[uart_num]->tx_done_sem); - xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); - return ESP_ERR_TIMEOUT; - } + xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, 0); ticks_to_wait = ticks_end - xTaskGetTickCount(); if(UART[uart_num]->status.txfifo_cnt == 0) { - xSemaphoreGive(p_uart_obj[uart_num]->tx_done_sem); xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); return ESP_OK; } @@ -676,11 +560,9 @@ esp_err_t uart_wait_tx_fifo_empty(uart_port_t uart_num, TickType_t ticks_to_wait res = xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, (portTickType)ticks_to_wait); if(res == pdFALSE) { uart_disable_intr_mask(uart_num, UART_TX_DONE_INT_ENA_M); - xSemaphoreGive(p_uart_obj[uart_num]->tx_done_sem); xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); return ESP_ERR_TIMEOUT; } - xSemaphoreGive(p_uart_obj[uart_num]->tx_done_sem); xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); return ESP_OK; } @@ -696,6 +578,20 @@ static esp_err_t uart_set_break(uart_port_t uart_num, int break_num) return ESP_OK; } +//Fill UART tx_fifo and return a number, +//This function by itself is not thread-safe, always call from within a muxed section. +static int uart_fill_fifo(uart_port_t uart_num, char* buffer, uint32_t len) +{ + uint8_t i = 0; + uint8_t tx_fifo_cnt = UART[uart_num]->status.txfifo_cnt; + uint8_t tx_remain_fifo_cnt = (UART_FIFO_LEN - tx_fifo_cnt); + uint8_t copy_cnt = (len >= tx_remain_fifo_cnt ? tx_remain_fifo_cnt : len); + for(i = 0; i < copy_cnt; i++) { + WRITE_PERI_REG(UART_FIFO_AHB_REG(uart_num), buffer[i]); + } + return copy_cnt; +} + int uart_tx_chars(uart_port_t uart_num, char* buffer, uint32_t len) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); @@ -727,7 +623,7 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool size_t sent = uart_fill_fifo(uart_num, (char*) src, size); if(sent < size) { p_uart_obj[uart_num]->tx_waiting = true; - uart_enable_tx_intr(uart_num, 1, DEFAULT_EMPTY_THRESH); + uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); } size -= sent; src += sent; @@ -742,12 +638,55 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool return original_size; } +static void uart_tx_task(void* arg) +{ + uart_obj_t* p_uart = (uart_obj_t*) arg; + size_t size; + uart_event_t evt; + for(;;) { + char* data = (char*) xRingbufferReceive(p_uart->tx_ring_buf, &size, portMAX_DELAY); + if(data == NULL) { + continue; + } + memcpy(&evt, data, sizeof(evt)); + if(evt.type == UART_DATA) { + uart_tx_all(p_uart->uart_num, (const char*) data + sizeof(uart_event_t), evt.data.size, 0, 0); + } else if(evt.type == UART_DATA_BREAK) { + uart_tx_all(p_uart->uart_num, (const char*) data + sizeof(uart_event_t), evt.data.size, 1, evt.data.brk_len); + } + vRingbufferReturnItem(p_uart->tx_ring_buf, data); + } + vTaskDelete(NULL); +} + int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); + UART_CHECK((p_uart_obj[uart_num] != NULL), "uart driver error"); UART_CHECK(src, "buffer null"); - return uart_tx_all(uart_num, src, size, 0, 0); + if(p_uart_obj[uart_num]->tx_buf_size > 0) { + if(xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf) > (size + sizeof(uart_event_t))) { + uart_event_t *evt = (uart_event_t*) malloc(sizeof(uart_event_t) + size); + if(evt == NULL) { + ESP_LOGE(UART_TAG, "UART EVT MALLOC ERROR\n"); + return -1; + } + xSemaphoreTake(p_uart_obj[uart_num]->tx_buffer_mutex, (portTickType)portMAX_DELAY); + evt->type = UART_DATA; + evt->data.size = size; + memcpy(evt->data.data, src, size); + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) evt, sizeof(uart_event_t) + size, portMAX_DELAY); + free(evt); + evt = NULL; + xSemaphoreGive(p_uart_obj[uart_num]->tx_buffer_mutex); + return size; + } else { + ESP_LOGW(UART_TAG, "UART TX BUFFER TOO SMALL[0], SEND DIRECTLY\n"); + return uart_tx_all(uart_num, src, size, 0, 0); + } + } else { + return uart_tx_all(uart_num, src, size, 0, 0); + } } int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len) @@ -757,7 +696,29 @@ int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t s UART_CHECK((size > 0), "uart size error"); UART_CHECK((src), "uart data null"); UART_CHECK((brk_len > 0 && brk_len < 256), "break_num error"); - return uart_tx_all(uart_num, src, size, 1, brk_len); + if(p_uart_obj[uart_num]->tx_buf_size > 0) { + if(xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf) > (size)) { + uart_event_t *evt = (uart_event_t*) malloc(sizeof(uart_event_t) + size); + if(evt == NULL) { + return -1; + } + xSemaphoreTake(p_uart_obj[uart_num]->tx_buffer_mutex, (portTickType)portMAX_DELAY); + evt->type = UART_DATA_BREAK; + evt->data.size = size; + evt->data.brk_len = brk_len; + memcpy(evt->data.data, src, size); + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) evt, sizeof(uart_event_t) + size, portMAX_DELAY); + free(evt); + evt = NULL; + xSemaphoreGive(p_uart_obj[uart_num]->tx_buffer_mutex); + return size; + } else { + ESP_LOGW(UART_TAG, "UART TX BUFFER TOO SMALL[1], SEND DIRECTLY\n"); + return uart_tx_all(uart_num, src, size, 1, brk_len); + } + } else { + return uart_tx_all(uart_num, src, size, 1, brk_len); + } } int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait) @@ -768,18 +729,18 @@ int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait) size_t size; int val; portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait; - if(xSemaphoreTake(p_uart_obj[uart_num]->rx_sem,(portTickType)ticks_to_wait) != pdTRUE) { + if(xSemaphoreTake(p_uart_obj[uart_num]->rx_mux,(portTickType)ticks_to_wait) != pdTRUE) { return -1; } if(p_uart_obj[uart_num]->cur_remain == 0) { ticks_to_wait = ticks_end - xTaskGetTickCount(); - data = (uint8_t*) xRingbufferReceive(p_uart_obj[uart_num]->ring_buffer, &size, (portTickType) ticks_to_wait); + data = (uint8_t*) xRingbufferReceive(p_uart_obj[uart_num]->rx_ring_buf, &size, (portTickType) ticks_to_wait); if(data) { p_uart_obj[uart_num]->head_ptr = data; p_uart_obj[uart_num]->rd_ptr = data; p_uart_obj[uart_num]->cur_remain = size; } else { - xSemaphoreGive(p_uart_obj[uart_num]->rx_sem); + xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); return -1; } } @@ -787,18 +748,18 @@ int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait) p_uart_obj[uart_num]->rd_ptr++; p_uart_obj[uart_num]->cur_remain--; if(p_uart_obj[uart_num]->cur_remain == 0) { - vRingbufferReturnItem(p_uart_obj[uart_num]->ring_buffer, p_uart_obj[uart_num]->head_ptr); + vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->head_ptr); p_uart_obj[uart_num]->head_ptr = NULL; p_uart_obj[uart_num]->rd_ptr = NULL; if(p_uart_obj[uart_num]->buffer_full_flg) { - BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->ring_buffer, p_uart_obj[uart_num]->data_buf, p_uart_obj[uart_num]->data_len, 1); + BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->data_buf, p_uart_obj[uart_num]->data_len, 1); if(res == pdTRUE) { p_uart_obj[uart_num]->buffer_full_flg = false; uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); } } } - xSemaphoreGive(p_uart_obj[uart_num]->rx_sem); + xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); return val; } @@ -807,23 +768,22 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); UART_CHECK((buf), "uart_num error"); UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); - uint8_t* data = NULL; size_t size; size_t copy_len = 0; int len_tmp; - if(xSemaphoreTake(p_uart_obj[uart_num]->rx_sem,(portTickType)ticks_to_wait) != pdTRUE) { + if(xSemaphoreTake(p_uart_obj[uart_num]->rx_mux,(portTickType)ticks_to_wait) != pdTRUE) { return -1; } while(length) { if(p_uart_obj[uart_num]->cur_remain == 0) { - data = (uint8_t*) xRingbufferReceive(p_uart_obj[uart_num]->ring_buffer, &size, (portTickType) ticks_to_wait); + data = (uint8_t*) xRingbufferReceive(p_uart_obj[uart_num]->rx_ring_buf, &size, (portTickType) ticks_to_wait); if(data) { p_uart_obj[uart_num]->head_ptr = data; p_uart_obj[uart_num]->rd_ptr = data; p_uart_obj[uart_num]->cur_remain = size; } else { - xSemaphoreGive(p_uart_obj[uart_num]->rx_sem); + xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); return copy_len; } } @@ -838,11 +798,11 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp copy_len += len_tmp; length -= len_tmp; if(p_uart_obj[uart_num]->cur_remain == 0) { - vRingbufferReturnItem(p_uart_obj[uart_num]->ring_buffer, p_uart_obj[uart_num]->head_ptr); + vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->head_ptr); p_uart_obj[uart_num]->head_ptr = NULL; p_uart_obj[uart_num]->rd_ptr = NULL; if(p_uart_obj[uart_num]->buffer_full_flg) { - BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->ring_buffer, p_uart_obj[uart_num]->data_buf, p_uart_obj[uart_num]->data_len, 1); + BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->data_buf, p_uart_obj[uart_num]->data_len, 1); if(res == pdTRUE) { p_uart_obj[uart_num]->buffer_full_flg = false; uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); @@ -850,7 +810,7 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp } } } - xSemaphoreGive(p_uart_obj[uart_num]->rx_sem); + xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); return copy_len; } @@ -858,30 +818,38 @@ esp_err_t uart_flush(uart_port_t uart_num) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); - uart_obj_t* p_uart = p_uart_obj[uart_num]; uint8_t* data; size_t size; //rx sem protect the ring buffer read related functions - xSemaphoreTake(p_uart->rx_sem, (portTickType)portMAX_DELAY); + xSemaphoreTake(p_uart->rx_mux, (portTickType)portMAX_DELAY); while(true) { if(p_uart->head_ptr) { - vRingbufferReturnItem(p_uart->ring_buffer, p_uart->head_ptr); + vRingbufferReturnItem(p_uart->rx_ring_buf, p_uart->head_ptr); p_uart->rd_ptr = NULL; p_uart->cur_remain = 0; p_uart->head_ptr = NULL; } - data = (uint8_t*) xRingbufferReceive(p_uart->ring_buffer, &size, (portTickType) 0); + data = (uint8_t*) xRingbufferReceive(p_uart->rx_ring_buf, &size, (portTickType) 0); if(data == NULL) { break; } - vRingbufferReturnItem(p_uart->ring_buffer, data); + vRingbufferReturnItem(p_uart->rx_ring_buf, data); } p_uart->rd_ptr = NULL; p_uart->cur_remain = 0; p_uart->head_ptr = NULL; - xSemaphoreGive(p_uart->rx_sem); - uart_wait_tx_fifo_empty(uart_num, portMAX_DELAY); + xSemaphoreGive(p_uart->rx_mux); + xSemaphoreTake(p_uart->tx_mutex, (portTickType)portMAX_DELAY); + do { + data = (uint8_t*) xRingbufferReceive(p_uart->tx_ring_buf, &size, (portTickType) 0); + if(data == NULL) { + break; + } + vRingbufferReturnItem(p_uart->rx_ring_buf, data); + } while(1); + xSemaphoreGive(p_uart->tx_mutex); + uart_wait_tx_done(uart_num, portMAX_DELAY); uart_reset_fifo(uart_num); return ESP_OK; } @@ -915,7 +883,6 @@ esp_err_t uart_set_print_port(uart_port_t uart_num) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); UART_CHECK((p_uart_obj[uart_num]), "UART driver error"); - s_uart_print_nport = uart_num; switch(s_uart_print_nport) { case UART_NUM_0: @@ -940,3 +907,127 @@ int uart_get_print_port() return s_uart_print_nport; } +esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue, ringbuf_type_t rx_buf_type) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((rx_buffer_size > 0), "uart rx buffer length error\n"); + if(p_uart_obj[uart_num] == NULL) { + ESP_INTR_DISABLE(uart_intr_num); + p_uart_obj[uart_num] = (uart_obj_t*) malloc(sizeof(uart_obj_t)); + if(p_uart_obj[uart_num] == NULL) { + ESP_LOGE(UART_TAG, "UART driver malloc error\n"); + return ESP_FAIL; + } + p_uart_obj[uart_num]->uart_num = uart_num; + p_uart_obj[uart_num]->tx_fifo_sem = xSemaphoreCreateBinary(); + xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); + p_uart_obj[uart_num]->tx_done_sem = xSemaphoreCreateBinary(); + p_uart_obj[uart_num]->tx_brk_sem = xSemaphoreCreateBinary(); + p_uart_obj[uart_num]->tx_mutex = xSemaphoreCreateMutex(); + p_uart_obj[uart_num]->tx_buffer_mutex = xSemaphoreCreateMutex(); + p_uart_obj[uart_num]->rx_mux = xSemaphoreCreateMutex(); + p_uart_obj[uart_num]->intr_num = uart_intr_num; + p_uart_obj[uart_num]->queue_size = queue_size; + + if(uart_queue) { + p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t)); + *((QueueHandle_t*) uart_queue) = p_uart_obj[uart_num]->xQueueUart; + ESP_LOGI(UART_TAG, "queue free spaces: %d\n", uxQueueSpacesAvailable(p_uart_obj[uart_num]->xQueueUart)); + } else { + p_uart_obj[uart_num]->xQueueUart = NULL; + } + p_uart_obj[uart_num]->buffer_full_flg = false; + p_uart_obj[uart_num]->tx_waiting = false; + p_uart_obj[uart_num]->rd_ptr = NULL; + p_uart_obj[uart_num]->cur_remain = 0; + p_uart_obj[uart_num]->head_ptr = NULL; + p_uart_obj[uart_num]->rx_buf_type = rx_buf_type; + p_uart_obj[uart_num]->rx_ring_buf = xRingbufferCreate(rx_buffer_size, rx_buf_type); + if(tx_buffer_size > 0) { + p_uart_obj[uart_num]->tx_ring_buf = xRingbufferCreate(tx_buffer_size, RINGBUF_TYPE_NOSPLIT); + p_uart_obj[uart_num]->tx_buf_size = tx_buffer_size; + xTaskCreate(uart_tx_task, "uart_tx_task", UART_TX_TASK_DEPTH_DEFAULT, (void*)p_uart_obj[uart_num], UART_TX_TASK_PRIO_DEFAULT, &p_uart_obj[uart_num]->tx_task_handle); + + } else { + p_uart_obj[uart_num]->tx_ring_buf = NULL; + p_uart_obj[uart_num]->tx_buf_size = 0; + p_uart_obj[uart_num]->tx_task_handle = NULL; + } + } else { + ESP_LOGE(UART_TAG, "UART driver already installed\n"); + return ESP_FAIL; + } + uart_isr_register(uart_num, uart_intr_num, uart_rx_intr_handler_default, p_uart_obj[uart_num]); + uart_intr_config_t uart_intr = { + .intr_enable_mask = UART_RXFIFO_FULL_INT_ENA_M + | UART_RXFIFO_TOUT_INT_ENA_M + | UART_FRM_ERR_INT_ENA_M + | UART_RXFIFO_OVF_INT_ENA_M + | UART_BRK_DET_INT_ENA_M, + .rxfifo_full_thresh = UART_FULL_THRESH_DEFAULT, + .rx_timeout_thresh = UART_TOUT_THRESH_DEFAULT, + .txfifo_empty_intr_thresh = UART_EMPTY_THRESH_DEFAULT + }; + uart_intr_config(uart_num, &uart_intr); + ESP_INTR_ENABLE(uart_intr_num); + return ESP_OK; +} + +//Make sure no other tasks are still using UART before you call this function +esp_err_t uart_driver_delete(uart_port_t uart_num) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + if(p_uart_obj[uart_num] == NULL) { + ESP_LOGI(UART_TAG, "ALREADY NULL\n"); + return ESP_OK; + } + ESP_INTR_DISABLE(p_uart_obj[uart_num]->intr_num); + uart_disable_rx_intr(uart_num); + uart_disable_tx_intr(uart_num); + uart_isr_register(uart_num, p_uart_obj[uart_num]->intr_num, NULL, NULL); + + if(p_uart_obj[uart_num]->tx_task_handle) { + vTaskDelete(p_uart_obj[uart_num]->tx_task_handle); + p_uart_obj[uart_num]->tx_task_handle = NULL; + } + if(p_uart_obj[uart_num]->tx_fifo_sem) { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_fifo_sem); + p_uart_obj[uart_num]->tx_fifo_sem = NULL; + } + if(p_uart_obj[uart_num]->tx_done_sem) { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_done_sem); + p_uart_obj[uart_num]->tx_done_sem = NULL; + } + if(p_uart_obj[uart_num]->tx_brk_sem) { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_brk_sem); + p_uart_obj[uart_num]->tx_brk_sem = NULL; + } + if(p_uart_obj[uart_num]->tx_mutex) { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_mutex); + p_uart_obj[uart_num]->tx_mutex = NULL; + } + if(p_uart_obj[uart_num]->tx_buffer_mutex) { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_buffer_mutex); + p_uart_obj[uart_num]->tx_buffer_mutex = NULL; + } + if(p_uart_obj[uart_num]->rx_mux) { + vSemaphoreDelete(p_uart_obj[uart_num]->rx_mux); + p_uart_obj[uart_num]->rx_mux = NULL; + } + if(p_uart_obj[uart_num]->xQueueUart) { + vQueueDelete(p_uart_obj[uart_num]->xQueueUart); + p_uart_obj[uart_num]->xQueueUart = NULL; + } + if(p_uart_obj[uart_num]->rx_ring_buf) { + vRingbufferDelete(p_uart_obj[uart_num]->rx_ring_buf); + p_uart_obj[uart_num]->rx_ring_buf = NULL; + } + if(p_uart_obj[uart_num]->tx_ring_buf) { + vRingbufferDelete(p_uart_obj[uart_num]->tx_ring_buf); + p_uart_obj[uart_num]->tx_ring_buf = NULL; + } + + free(p_uart_obj[uart_num]); + p_uart_obj[uart_num] = NULL; + return ESP_OK; +} From 8282c73ac25a3b6e8895719eadab0eec92f1e1b3 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Thu, 3 Nov 2016 18:28:36 +0800 Subject: [PATCH 07/12] debug ring buffer error. --- components/driver/include/driver/uart.h | 2 +- components/driver/uart.c | 205 +++++++++++++++++------- components/freertos/ringbuf.c | 29 +++- 3 files changed, 177 insertions(+), 59 deletions(-) diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index 3ea77b2d0..445d71b68 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -530,7 +530,7 @@ int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait); * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * @param buf pointer to the buffer. * @param length data length - * @param ticks_to_wait: Timeout, count in RTOS ticks + * @param ticks_to_wait sTimeout, count in RTOS ticks * * @return * - (-1) Error diff --git a/components/driver/uart.c b/components/driver/uart.c index eeb2c6420..d6585405f 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -37,8 +37,6 @@ const char* UART_TAG = "UART"; #define UART_EMPTY_THRESH_DEFAULT (10) #define UART_FULL_THRESH_DEFAULT (120) #define UART_TOUT_THRESH_DEFAULT (10) -#define UART_TX_TASK_DEPTH_DEFAULT (256*2+64) -#define UART_TX_TASK_PRIO_DEFAULT (10) #define UART_ENTER_CRITICAL_ISR(mux) portENTER_CRITICAL_ISR(mux) #define UART_EXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL_ISR(mux) #define UART_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux) @@ -60,7 +58,6 @@ typedef struct { RingbufHandle_t rx_ring_buf; int tx_buf_size; RingbufHandle_t tx_ring_buf; - TaskHandle_t tx_task_handle; bool buffer_full_flg; bool tx_waiting; int cur_remain; @@ -439,8 +436,17 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) uart_dev_t* uart_reg = UART[uart_num]; uint8_t buf_idx = 0; uint32_t uart_intr_status = UART[uart_num]->int_st.val; - static int rx_fifo_len = 0; + int rx_fifo_len = 0; uart_event_t uart_event; + + static uint8_t * tx_ptr; + static uart_event_t* tx_head; + static int tx_len_tot = 0; + static int brk_flg = 0; + static int tx_brk_len = 0; + static int wait_brk = 0; + + portBASE_TYPE HPTaskAwoken = 0; while(uart_intr_status != 0x0) { buf_idx = 0; @@ -450,14 +456,99 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) uart_reg->int_ena.txfifo_empty = 0; uart_reg->int_clr.txfifo_empty = 1; UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); + if(wait_brk) { + return; + } if(p_uart->tx_waiting == true) { p_uart->tx_waiting = false; xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, NULL); } + else { + int tx_fifo_rem = UART_FIFO_LEN - UART[uart_num]->status.txfifo_cnt; + bool en_tx_flg = false; + if(tx_len_tot == 0) { + size_t size; +// ets_printf("dbg1,tot=0,get 1st head\n"); +// xRingbufferPrintInfo(p_uart->tx_ring_buf); + tx_head = (uart_event_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); +// xRingbufferPrintInfo(p_uart->tx_ring_buf); + if(tx_head) { //enable empty intr +// tx_ptr = (uint8_t*)tx_head + sizeof(uart_event_t); + tx_ptr = NULL; +// en_tx_flg = true; + tx_len_tot = tx_head->data.size; + if(tx_head->type == UART_DATA_BREAK) { + tx_len_tot = tx_head->data.size; + brk_flg = 1; + tx_brk_len = tx_head->data.brk_len; + } +// ets_printf("ret1,tot: %d\n", tx_len_tot); + vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, tx_head, &HPTaskAwoken); +// xRingbufferPrintInfo(p_uart->tx_ring_buf); +// xRingbufferPrintInfo(p_uart->tx_ring_buf); + } + else { + return; + } + } + if(tx_ptr == NULL) { + size_t size; +// ets_printf("dbg2, tx ptr null, get 2nd tx ptr\n"); +// xRingbufferPrintInfo(p_uart->tx_ring_buf); + tx_ptr = (uint8_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); + +// xRingbufferPrintInfo(p_uart->tx_ring_buf); + if(tx_ptr) { + tx_head = (void*) tx_ptr; +// ets_printf("get size: %d ; h size: %d\n", size, tx_len_tot); + en_tx_flg = true; + } else { + return; + } + } +// else + if(tx_len_tot > 0 && tx_ptr) { //tx + int send_len = tx_len_tot > tx_fifo_rem ? tx_fifo_rem : tx_len_tot; + for(buf_idx = 0; buf_idx < send_len; buf_idx++) { + WRITE_PERI_REG(UART_FIFO_AHB_REG(uart_num), *(tx_ptr++) & 0xff); + } + tx_len_tot -= send_len; +// ets_printf("tot: %d\n", tx_len_tot); + if(tx_len_tot == 0) { + if(brk_flg == 1) { + UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_reg->int_ena.tx_brk_done = 0; + uart_reg->idle_conf.tx_brk_num = tx_brk_len; + uart_reg->conf0.txd_brk = 1; + uart_reg->int_clr.tx_brk_done = 1; + uart_reg->int_ena.tx_brk_done = 1; + UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); + wait_brk = 1; + } else { + en_tx_flg = true; + } +// ets_printf("ret2\n"); + vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, tx_head, &HPTaskAwoken); +// xRingbufferPrintInfo(p_uart->tx_ring_buf); +// xRingbufferPrintInfo(p_uart->tx_ring_buf); + tx_head = NULL; + tx_ptr = NULL; + } else { + en_tx_flg = true; + } + } + if(en_tx_flg) { + UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_reg->int_clr.txfifo_empty = 1; + uart_reg->int_ena.txfifo_empty = 1; + UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); + } + } } else if((uart_intr_status & UART_RXFIFO_TOUT_INT_ST_M) || (uart_intr_status & UART_RXFIFO_FULL_INT_ST_M)) { if(p_uart->buffer_full_flg == false) { //Get the buffer from the FIFO +// ESP_LOGE(UART_TAG, "FULL\n"); rx_fifo_len = uart_reg->status.rxfifo_cnt; p_uart->data_len = rx_fifo_len; memset(p_uart->data_buf, 0, sizeof(p_uart->data_buf)); @@ -506,12 +597,22 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) uart_reg->int_clr.frm_err = 1; uart_event.type = UART_PARITY_ERR; } else if(uart_intr_status & UART_TX_BRK_DONE_INT_ST_M) { +// ESP_LOGE(UART_TAG, "UART TX BRK DONE\n"); + ets_printf("tx brk done\n"); UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_reg->conf0.txd_brk = 0; uart_reg->int_ena.tx_brk_done = 0; uart_reg->int_clr.tx_brk_done = 1; + if(brk_flg == 1) { + uart_reg->int_ena.txfifo_empty = 1; + } UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); - xSemaphoreGiveFromISR(p_uart->tx_brk_sem, &HPTaskAwoken); + if(brk_flg == 1) { + brk_flg = 0; + wait_brk = 0; + } else { + xSemaphoreGiveFromISR(p_uart->tx_brk_sem, &HPTaskAwoken); + } } else if(uart_intr_status & UART_TX_BRK_IDLE_DONE_INT_ST_M) { UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_reg->int_ena.tx_brk_idle_done = 0; @@ -638,26 +739,26 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool return original_size; } -static void uart_tx_task(void* arg) -{ - uart_obj_t* p_uart = (uart_obj_t*) arg; - size_t size; - uart_event_t evt; - for(;;) { - char* data = (char*) xRingbufferReceive(p_uart->tx_ring_buf, &size, portMAX_DELAY); - if(data == NULL) { - continue; - } - memcpy(&evt, data, sizeof(evt)); - if(evt.type == UART_DATA) { - uart_tx_all(p_uart->uart_num, (const char*) data + sizeof(uart_event_t), evt.data.size, 0, 0); - } else if(evt.type == UART_DATA_BREAK) { - uart_tx_all(p_uart->uart_num, (const char*) data + sizeof(uart_event_t), evt.data.size, 1, evt.data.brk_len); - } - vRingbufferReturnItem(p_uart->tx_ring_buf, data); - } - vTaskDelete(NULL); -} +//static void uart_tx_task(void* arg) +//{ +// uart_obj_t* p_uart = (uart_obj_t*) arg; +// size_t size; +// uart_event_t evt; +// for(;;) { +// char* data = (char*) xRingbufferReceive(p_uart->tx_ring_buf, &size, portMAX_DELAY); +// if(data == NULL) { +// continue; +// } +// memcpy(&evt, data, sizeof(evt)); +// if(evt.type == UART_DATA) { +// uart_tx_all(p_uart->uart_num, (const char*) data + sizeof(uart_event_t), evt.data.size, 0, 0); +// } else if(evt.type == UART_DATA_BREAK) { +// uart_tx_all(p_uart->uart_num, (const char*) data + sizeof(uart_event_t), evt.data.size, 1, evt.data.brk_len); +// } +// vRingbufferReturnItem(p_uart->tx_ring_buf, data); +// } +// vTaskDelete(NULL); +//} int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size) { @@ -666,19 +767,18 @@ int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size) UART_CHECK(src, "buffer null"); if(p_uart_obj[uart_num]->tx_buf_size > 0) { if(xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf) > (size + sizeof(uart_event_t))) { - uart_event_t *evt = (uart_event_t*) malloc(sizeof(uart_event_t) + size); - if(evt == NULL) { - ESP_LOGE(UART_TAG, "UART EVT MALLOC ERROR\n"); - return -1; - } + uart_event_t evt; xSemaphoreTake(p_uart_obj[uart_num]->tx_buffer_mutex, (portTickType)portMAX_DELAY); - evt->type = UART_DATA; - evt->data.size = size; - memcpy(evt->data.data, src, size); - xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) evt, sizeof(uart_event_t) + size, portMAX_DELAY); - free(evt); - evt = NULL; + evt.type = UART_DATA; + evt.data.size = size; + ets_printf("-----1st send-----\n"); + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_event_t), portMAX_DELAY); + xRingbufferPrintInfo(p_uart_obj[uart_num]->tx_ring_buf); + ets_printf("====2nd send====\n"); + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) src, size, portMAX_DELAY); + xRingbufferPrintInfo(p_uart_obj[uart_num]->tx_ring_buf); xSemaphoreGive(p_uart_obj[uart_num]->tx_buffer_mutex); + uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); return size; } else { ESP_LOGW(UART_TAG, "UART TX BUFFER TOO SMALL[0], SEND DIRECTLY\n"); @@ -698,19 +798,15 @@ int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t s UART_CHECK((brk_len > 0 && brk_len < 256), "break_num error"); if(p_uart_obj[uart_num]->tx_buf_size > 0) { if(xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf) > (size)) { - uart_event_t *evt = (uart_event_t*) malloc(sizeof(uart_event_t) + size); - if(evt == NULL) { - return -1; - } + uart_event_t evt; xSemaphoreTake(p_uart_obj[uart_num]->tx_buffer_mutex, (portTickType)portMAX_DELAY); - evt->type = UART_DATA_BREAK; - evt->data.size = size; - evt->data.brk_len = brk_len; - memcpy(evt->data.data, src, size); - xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) evt, sizeof(uart_event_t) + size, portMAX_DELAY); - free(evt); - evt = NULL; + evt.type = UART_DATA_BREAK; + evt.data.size = size; + evt.data.brk_len = brk_len; + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_event_t), portMAX_DELAY); + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) src, size, portMAX_DELAY); xSemaphoreGive(p_uart_obj[uart_num]->tx_buffer_mutex); + uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); return size; } else { ESP_LOGW(UART_TAG, "UART TX BUFFER TOO SMALL[1], SEND DIRECTLY\n"); @@ -782,8 +878,10 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp p_uart_obj[uart_num]->head_ptr = data; p_uart_obj[uart_num]->rd_ptr = data; p_uart_obj[uart_num]->cur_remain = size; +// ets_printf("dbg0\n"); } else { xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); +// ets_printf("dbg1\n"); return copy_len; } } @@ -792,17 +890,20 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp } else { len_tmp = p_uart_obj[uart_num]->cur_remain; } +// ets_printf("dbga\n"); memcpy(buf + copy_len, p_uart_obj[uart_num]->rd_ptr, len_tmp); p_uart_obj[uart_num]->rd_ptr += len_tmp; p_uart_obj[uart_num]->cur_remain -= len_tmp; copy_len += len_tmp; length -= len_tmp; +// ets_printf("dbgb\n"); if(p_uart_obj[uart_num]->cur_remain == 0) { vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->head_ptr); p_uart_obj[uart_num]->head_ptr = NULL; p_uart_obj[uart_num]->rd_ptr = NULL; if(p_uart_obj[uart_num]->buffer_full_flg) { BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->data_buf, p_uart_obj[uart_num]->data_len, 1); +// ets_printf("dbg2\n"); if(res == pdTRUE) { p_uart_obj[uart_num]->buffer_full_flg = false; uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); @@ -810,6 +911,7 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp } } } +// ets_printf("dbg3\n"); xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); return copy_len; } @@ -944,14 +1046,11 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b p_uart_obj[uart_num]->rx_buf_type = rx_buf_type; p_uart_obj[uart_num]->rx_ring_buf = xRingbufferCreate(rx_buffer_size, rx_buf_type); if(tx_buffer_size > 0) { - p_uart_obj[uart_num]->tx_ring_buf = xRingbufferCreate(tx_buffer_size, RINGBUF_TYPE_NOSPLIT); + p_uart_obj[uart_num]->tx_ring_buf = xRingbufferCreate(tx_buffer_size, RINGBUF_TYPE_NOSPLIT);//RINGBUF_TYPE_BYTEBUF);//RINGBUF_TYPE_NOSPLIT); p_uart_obj[uart_num]->tx_buf_size = tx_buffer_size; - xTaskCreate(uart_tx_task, "uart_tx_task", UART_TX_TASK_DEPTH_DEFAULT, (void*)p_uart_obj[uart_num], UART_TX_TASK_PRIO_DEFAULT, &p_uart_obj[uart_num]->tx_task_handle); - } else { p_uart_obj[uart_num]->tx_ring_buf = NULL; p_uart_obj[uart_num]->tx_buf_size = 0; - p_uart_obj[uart_num]->tx_task_handle = NULL; } } else { ESP_LOGE(UART_TAG, "UART driver already installed\n"); @@ -986,10 +1085,6 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) uart_disable_tx_intr(uart_num); uart_isr_register(uart_num, p_uart_obj[uart_num]->intr_num, NULL, NULL); - if(p_uart_obj[uart_num]->tx_task_handle) { - vTaskDelete(p_uart_obj[uart_num]->tx_task_handle); - p_uart_obj[uart_num]->tx_task_handle = NULL; - } if(p_uart_obj[uart_num]->tx_fifo_sem) { vSemaphoreDelete(p_uart_obj[uart_num]->tx_fifo_sem); p_uart_obj[uart_num]->tx_fifo_sem = NULL; diff --git a/components/freertos/ringbuf.c b/components/freertos/ringbuf.c index ce5504596..560eb5fdd 100644 --- a/components/freertos/ringbuf.c +++ b/components/freertos/ringbuf.c @@ -77,9 +77,13 @@ static int ringbufferFreeMem(ringbuf_t *rb) { int free_size = rb->free_ptr-rb->write_ptr; if (free_size <= 0) free_size += rb->size; + //If we free the last dummy item in the buffer, free_ptr will point to rb->data + //In this case, after we write the last some bytes, the buffer might wrap around if we don't have room for a header anymore. +// if (free_size == 0 && rb->read_ptr == rb->write_ptr) free_size += rb->size; //Reserve one byte. If we do not do this and the entire buffer is filled, we get a situation - //where read_ptr == free_ptr, messing up the next calculation. - return free_size-1; + //where write_ptr == free_ptr, messing up the next calculation. +// return free_size == 0 ? 0 : free_size - 1; + return free_size - 1; } @@ -334,6 +338,10 @@ static uint8_t *getItemFromRingbufByteBuf(ringbuf_t *rb, size_t *length, int wan //can be increase. //This function by itself is not threadsafe, always call from within a muxed section. static void returnItemToRingbufDefault(ringbuf_t *rb, void *item) { + ets_printf("in returnItemToRingbufDefault\n"); + xRingbufferPrintInfo(rb); + + uint8_t *data=(uint8_t*)item; configASSERT(((int)rb->free_ptr&3)==0); configASSERT(data >= rb->data); @@ -350,9 +358,16 @@ static void returnItemToRingbufDefault(ringbuf_t *rb, void *item) { hdr=(buf_entry_hdr_t *)rb->free_ptr; //basically forward free_ptr until we run into either a block that is still in use or the write pointer. while (((hdr->flags & iflag_free) || (hdr->flags & iflag_dummydata)) && rb->free_ptr != rb->write_ptr) { + if (hdr->flags & iflag_dummydata) { + ets_printf("hrd len: %d; flg: 0x%02x\n",hdr->len,hdr->flags); //Rest is dummy data. Reset to start of ringbuffer. rb->free_ptr=rb->data; + //If the read_ptr is pointing to this dummy item, + //we should also move the read pointer to data, in case we overwrite the read hdr. +// if(rb->read_ptr == (uint8_t*)hdr) { +// rb->read_ptr = rb->data; +// } } else { //Skip past item size_t len=(hdr->len+3)&~3; @@ -363,8 +378,10 @@ static void returnItemToRingbufDefault(ringbuf_t *rb, void *item) { if ((rb->data+rb->size)-rb->free_ptr < sizeof(buf_entry_hdr_t)) { rb->free_ptr=rb->data; } + if(rb->free_ptr == rb->read_ptr) break; //Next header hdr=(buf_entry_hdr_t *)rb->free_ptr; + } } @@ -386,6 +403,12 @@ void xRingbufferPrintInfo(RingbufHandle_t ringbuf) configASSERT(rb); ets_printf("Rb size %d free %d rptr %d freeptr %d wptr %d\n", rb->size, ringbufferFreeMem(rb), rb->read_ptr-rb->data, rb->free_ptr-rb->data, rb->write_ptr-rb->data); + buf_entry_hdr_t *hdr=(buf_entry_hdr_t *)rb->read_ptr; + if(rb->write_ptr == rb->read_ptr) { + ets_printf("write que read\n"); + } else { + ets_printf("hdr len: %d; flg: 0x%08x\n", hdr->len, hdr->flags); + } } @@ -493,7 +516,7 @@ BaseType_t xRingbufferSend(RingbufHandle_t ringbuf, void *data, size_t dataSize, ticks_to_wait = ticks_end - xTaskGetTickCount(); } } while (ringbufferFreeMem(rb) < needed_size && ticks_to_wait>=0); - + //Lock the mux in order to make sure no one else is messing with the ringbuffer and do the copy. portENTER_CRITICAL(&rb->mux); //Another thread may have been able to sneak its write first. Check again now we locked the ringbuff, and retry From 9ed7c4f8bc7f0c8d1f26bf68877b95099b6703ef Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Thu, 3 Nov 2016 23:30:54 +0800 Subject: [PATCH 08/12] fix ringbuffer bug. --- components/driver/include/driver/uart.h | 3 +- components/driver/uart.c | 427 ++++++++++++------------ components/freertos/ringbuf.c | 30 +- 3 files changed, 214 insertions(+), 246 deletions(-) diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index 445d71b68..0d9ab3c56 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -437,13 +437,12 @@ esp_err_t uart_intr_config(uart_port_t uart_num, uart_intr_config_t *p_intr_conf * @param queue_size UART event queue size/depth. * @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details * @param uart_queue UART event queue handle, if set NULL, driver will not use an event queue. - * @param buf_type UART RX ring_buffer type * * @return * - ESP_OK Success * - ESP_FAIL Parameter error */ -esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue, ringbuf_type_t rx_buf_type); +esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue); /** * @brief Uninstall UART driver. diff --git a/components/driver/uart.c b/components/driver/uart.c index d6585405f..9eaf78343 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -43,28 +43,35 @@ const char* UART_TAG = "UART"; #define UART_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) typedef struct { - uart_port_t uart_num; - SemaphoreHandle_t tx_fifo_sem; - SemaphoreHandle_t tx_mutex; - SemaphoreHandle_t tx_buffer_mutex; - SemaphoreHandle_t tx_done_sem; - SemaphoreHandle_t tx_brk_sem; - SemaphoreHandle_t rx_mux; - QueueHandle_t xQueueUart; - int queue_size; - int intr_num; - int rx_buf_size; - ringbuf_type_t rx_buf_type; - RingbufHandle_t rx_ring_buf; - int tx_buf_size; - RingbufHandle_t tx_ring_buf; - bool buffer_full_flg; - bool tx_waiting; - int cur_remain; - uint8_t* rd_ptr; - uint8_t* head_ptr; - uint8_t data_buf[UART_FIFO_LEN]; - uint8_t data_len; + uart_port_t uart_num; /*!< UART port number*/ + int queue_size; /*!< UART event queue size*/ + QueueHandle_t xQueueUart; /*!< UART queue handler*/ + int intr_num; /*!< UART interrupt number*/ + //rx parameters + SemaphoreHandle_t rx_mux; /*!< UART RX data mutex*/ + int rx_buf_size; /*!< RX ring buffer size */ + RingbufHandle_t rx_ring_buf; /*!< RX ring buffer handler*/ + bool rx_buffer_full_flg; /*!< RX ring buffer full flag. */ + int rx_cur_remain; /*!< Data number that waiting to be read out in ring buffer item*/ + uint8_t* rx_ptr; /*!< pointer to the current data in ring buffer*/ + uint8_t* rx_head_ptr; /*!< pointer to the head of RX item*/ + uint8_t rx_data_buf[UART_FIFO_LEN]; /*!< Data buffer to stash FIFO data*/ + uint8_t rx_stash_len; /*!< stashed data length.(When using flow control, after reading out FIFO data, if we fail to push to buffer, we can just stash them.) */ + //tx parameters + SemaphoreHandle_t tx_fifo_sem; /*!< UART TX FIFO semaphore*/ + SemaphoreHandle_t tx_mux; /*!< UART TX mutex*/ + SemaphoreHandle_t tx_buffer_mux; /*!< UART TX buffer semaphore*/ + SemaphoreHandle_t tx_done_sem; /*!< UART TX done semaphore*/ + SemaphoreHandle_t tx_brk_sem; /*!< UART TX send break done semaphore*/ + int tx_buf_size; /*!< TX ring buffer size */ + RingbufHandle_t tx_ring_buf; /*!< TX ring buffer handler*/ + bool tx_waiting_fifo; /*!< this flag indicates that some task is waiting for FIFO empty interrupt, used to send all data without any data buffer*/ + uint8_t* tx_ptr; /*!< TX data pointer to push to FIFO in TX buffer mode*/ + uart_event_t* tx_head; /*!< TX data pointer to head of the current buffer in TX ring buffer*/ + uint32_t tx_len_tot; /*!< Total length of current item in ring buffer*/ + uint8_t tx_brk_flg; /*!< Flag to indicate to send a break signal in the end of the item sending procedure */ + uint8_t tx_brk_len; /*!< TX break signal cycle length/number */ + uint8_t tx_waiting_brk; /*!< Flag to indicate that TX FIFO is ready to send break signal after FIFO is empty, do not push data into TX FIFO right now.*/ } uart_obj_t; static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0}; @@ -438,16 +445,8 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) uint32_t uart_intr_status = UART[uart_num]->int_st.val; int rx_fifo_len = 0; uart_event_t uart_event; - - static uint8_t * tx_ptr; - static uart_event_t* tx_head; - static int tx_len_tot = 0; - static int brk_flg = 0; - static int tx_brk_len = 0; - static int wait_brk = 0; - - portBASE_TYPE HPTaskAwoken = 0; + while(uart_intr_status != 0x0) { buf_idx = 0; uart_event.type = UART_EVENT_MAX; @@ -456,85 +455,92 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) uart_reg->int_ena.txfifo_empty = 0; uart_reg->int_clr.txfifo_empty = 1; UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); - if(wait_brk) { + if(p_uart->tx_waiting_brk) { return; } - if(p_uart->tx_waiting == true) { - p_uart->tx_waiting = false; + if(p_uart->tx_waiting_fifo == true) { + p_uart->tx_waiting_fifo = false; xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, NULL); } else { + //We don't use TX ring buffer, because the size if zero. + if(p_uart->tx_buf_size == 0) { + return; + } int tx_fifo_rem = UART_FIFO_LEN - UART[uart_num]->status.txfifo_cnt; bool en_tx_flg = false; - if(tx_len_tot == 0) { - size_t size; -// ets_printf("dbg1,tot=0,get 1st head\n"); -// xRingbufferPrintInfo(p_uart->tx_ring_buf); - tx_head = (uart_event_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); -// xRingbufferPrintInfo(p_uart->tx_ring_buf); - if(tx_head) { //enable empty intr -// tx_ptr = (uint8_t*)tx_head + sizeof(uart_event_t); - tx_ptr = NULL; -// en_tx_flg = true; - tx_len_tot = tx_head->data.size; - if(tx_head->type == UART_DATA_BREAK) { - tx_len_tot = tx_head->data.size; - brk_flg = 1; - tx_brk_len = tx_head->data.brk_len; + //We need to put a loop here, in case all the buffer items are very short. + //That would cause a watch_dog reset because empty interrupt happens so often. + //Although this is a loop in ISR, this loop will execute at most 128 turns. + while(tx_fifo_rem) { + if(p_uart->tx_len_tot == 0) { + size_t size; + //The first item is the data description + //Get the first item to get the data information + p_uart->tx_head = (uart_event_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); + if(p_uart->tx_head) { + p_uart->tx_ptr = NULL; + p_uart->tx_len_tot = p_uart->tx_head->data.size; + if(p_uart->tx_head->type == UART_DATA_BREAK) { + p_uart->tx_len_tot = p_uart->tx_head->data.size; + p_uart->tx_brk_flg = 1; + p_uart->tx_brk_len = p_uart->tx_head->data.brk_len; + } + //We have saved the data description from the 1st item, return buffer. + vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken); + } + else { + //Can not get data from ring buffer, return; + return; } -// ets_printf("ret1,tot: %d\n", tx_len_tot); - vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, tx_head, &HPTaskAwoken); -// xRingbufferPrintInfo(p_uart->tx_ring_buf); -// xRingbufferPrintInfo(p_uart->tx_ring_buf); } - else { - return; - } - } - if(tx_ptr == NULL) { - size_t size; -// ets_printf("dbg2, tx ptr null, get 2nd tx ptr\n"); -// xRingbufferPrintInfo(p_uart->tx_ring_buf); - tx_ptr = (uint8_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); - -// xRingbufferPrintInfo(p_uart->tx_ring_buf); - if(tx_ptr) { - tx_head = (void*) tx_ptr; -// ets_printf("get size: %d ; h size: %d\n", size, tx_len_tot); - en_tx_flg = true; - } else { - return; - } - } -// else - if(tx_len_tot > 0 && tx_ptr) { //tx - int send_len = tx_len_tot > tx_fifo_rem ? tx_fifo_rem : tx_len_tot; - for(buf_idx = 0; buf_idx < send_len; buf_idx++) { - WRITE_PERI_REG(UART_FIFO_AHB_REG(uart_num), *(tx_ptr++) & 0xff); - } - tx_len_tot -= send_len; -// ets_printf("tot: %d\n", tx_len_tot); - if(tx_len_tot == 0) { - if(brk_flg == 1) { - UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); - uart_reg->int_ena.tx_brk_done = 0; - uart_reg->idle_conf.tx_brk_num = tx_brk_len; - uart_reg->conf0.txd_brk = 1; - uart_reg->int_clr.tx_brk_done = 1; - uart_reg->int_ena.tx_brk_done = 1; - UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); - wait_brk = 1; + if(p_uart->tx_ptr == NULL) { + size_t size; + //2nd item is the data we need to send through UART + //Get 2nd item from ring buffer + p_uart->tx_ptr = (uint8_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); + if(p_uart->tx_ptr) { + //Update the TX item head, we will need this to return item to buffer. + p_uart->tx_head = (void*) p_uart->tx_ptr; + en_tx_flg = true; } else { + //Can not get data from ring buffer, return; + return; + } + } + if(p_uart->tx_len_tot > 0 && p_uart->tx_ptr) { + //To fill the TX FIFO. + int send_len = p_uart->tx_len_tot > tx_fifo_rem ? tx_fifo_rem : p_uart->tx_len_tot; + for(buf_idx = 0; buf_idx < send_len; buf_idx++) { + WRITE_PERI_REG(UART_FIFO_AHB_REG(uart_num), *(p_uart->tx_ptr++) & 0xff); + } + p_uart->tx_len_tot -= send_len; + tx_fifo_rem -= send_len; + if(p_uart->tx_len_tot == 0) { + //Sending item done, now we need to send break if there is a record. + //Return item to ring buffer. + vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken); + p_uart->tx_head = NULL; + p_uart->tx_ptr = NULL; + //Set TX break signal after FIFO is empty + if(p_uart->tx_brk_flg == 1) { + UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); + uart_reg->int_ena.tx_brk_done = 0; + uart_reg->idle_conf.tx_brk_num = p_uart->tx_brk_len; + uart_reg->conf0.txd_brk = 1; + uart_reg->int_clr.tx_brk_done = 1; + uart_reg->int_ena.tx_brk_done = 1; + UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); + p_uart->tx_waiting_brk = 1; + return; + } else { + //enable TX empty interrupt + en_tx_flg = true; + } + } else { + //enable TX empty interrupt en_tx_flg = true; } -// ets_printf("ret2\n"); - vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, tx_head, &HPTaskAwoken); -// xRingbufferPrintInfo(p_uart->tx_ring_buf); -// xRingbufferPrintInfo(p_uart->tx_ring_buf); - tx_head = NULL; - tx_ptr = NULL; - } else { - en_tx_flg = true; } } if(en_tx_flg) { @@ -546,14 +552,13 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) } } else if((uart_intr_status & UART_RXFIFO_TOUT_INT_ST_M) || (uart_intr_status & UART_RXFIFO_FULL_INT_ST_M)) { - if(p_uart->buffer_full_flg == false) { + if(p_uart->rx_buffer_full_flg == false) { //Get the buffer from the FIFO -// ESP_LOGE(UART_TAG, "FULL\n"); rx_fifo_len = uart_reg->status.rxfifo_cnt; - p_uart->data_len = rx_fifo_len; - memset(p_uart->data_buf, 0, sizeof(p_uart->data_buf)); + p_uart->rx_stash_len = rx_fifo_len; + //We have to read out all data in RX FIFO to clear the interrupt signal while(buf_idx < rx_fifo_len) { - p_uart->data_buf[buf_idx++] = uart_reg->fifo.rw_byte; + p_uart->rx_data_buf[buf_idx++] = uart_reg->fifo.rw_byte; } //After Copying the Data From FIFO ,Clear intr_status UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); @@ -562,12 +567,14 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_event.type = UART_DATA; uart_event.data.size = rx_fifo_len; - if(pdFALSE == xRingbufferSendFromISR(p_uart->rx_ring_buf, p_uart->data_buf, p_uart->data_len, &HPTaskAwoken)) { + //If we fail to push data to ring buffer, we will have to stash the data, and send next time. + //Mainly for applications that uses flow control or small ring buffer. + if(pdFALSE == xRingbufferSendFromISR(p_uart->rx_ring_buf, p_uart->rx_data_buf, p_uart->rx_stash_len, &HPTaskAwoken)) { UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_reg->int_ena.rxfifo_full = 0; uart_reg->int_ena.rxfifo_tout = 0; UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); - p_uart->buffer_full_flg = true; + p_uart->rx_buffer_full_flg = true; uart_event.type = UART_BUFFER_FULL; } else { uart_event.type = UART_DATA; @@ -597,19 +604,17 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) uart_reg->int_clr.frm_err = 1; uart_event.type = UART_PARITY_ERR; } else if(uart_intr_status & UART_TX_BRK_DONE_INT_ST_M) { -// ESP_LOGE(UART_TAG, "UART TX BRK DONE\n"); - ets_printf("tx brk done\n"); UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_reg->conf0.txd_brk = 0; uart_reg->int_ena.tx_brk_done = 0; uart_reg->int_clr.tx_brk_done = 1; - if(brk_flg == 1) { + if(p_uart->tx_brk_flg == 1) { uart_reg->int_ena.txfifo_empty = 1; } UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); - if(brk_flg == 1) { - brk_flg = 0; - wait_brk = 0; + if(p_uart->tx_brk_flg == 1) { + p_uart->tx_brk_flg = 0; + p_uart->tx_waiting_brk = 0; } else { xSemaphoreGiveFromISR(p_uart->tx_brk_sem, &HPTaskAwoken); } @@ -644,8 +649,8 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); BaseType_t res; portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait; - //Take tx_mutex - res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mutex, (portTickType)ticks_to_wait); + //Take tx_mux + res = xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)ticks_to_wait); if(res == pdFALSE) { return ESP_ERR_TIMEOUT; } @@ -653,7 +658,7 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, 0); ticks_to_wait = ticks_end - xTaskGetTickCount(); if(UART[uart_num]->status.txfifo_cnt == 0) { - xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return ESP_OK; } uart_enable_intr_mask(uart_num, UART_TX_DONE_INT_ENA_M); @@ -661,10 +666,10 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) res = xSemaphoreTake(p_uart_obj[uart_num]->tx_done_sem, (portTickType)ticks_to_wait); if(res == pdFALSE) { uart_disable_intr_mask(uart_num, UART_TX_DONE_INT_ENA_M); - xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return ESP_ERR_TIMEOUT; } - xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return ESP_OK; } @@ -701,9 +706,9 @@ int uart_tx_chars(uart_port_t uart_num, char* buffer, uint32_t len) if(len == 0) { return 0; } - xSemaphoreTake(p_uart_obj[uart_num]->tx_mutex, (portTickType)portMAX_DELAY); + xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); int tx_len = uart_fill_fifo(uart_num, buffer, len); - xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return tx_len; } @@ -716,14 +721,14 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool return 0; } //lock for uart_tx - xSemaphoreTake(p_uart_obj[uart_num]->tx_mutex, (portTickType)portMAX_DELAY); + xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); size_t original_size = size; while(size) { //semaphore for tx_fifo available if(pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) { size_t sent = uart_fill_fifo(uart_num, (char*) src, size); if(sent < size) { - p_uart_obj[uart_num]->tx_waiting = true; + p_uart_obj[uart_num]->tx_waiting_fifo = true; uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); } size -= sent; @@ -735,49 +740,25 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool xSemaphoreTake(p_uart_obj[uart_num]->tx_brk_sem, (portTickType)portMAX_DELAY); } xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); - xSemaphoreGive(p_uart_obj[uart_num]->tx_mutex); + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return original_size; } -//static void uart_tx_task(void* arg) -//{ -// uart_obj_t* p_uart = (uart_obj_t*) arg; -// size_t size; -// uart_event_t evt; -// for(;;) { -// char* data = (char*) xRingbufferReceive(p_uart->tx_ring_buf, &size, portMAX_DELAY); -// if(data == NULL) { -// continue; -// } -// memcpy(&evt, data, sizeof(evt)); -// if(evt.type == UART_DATA) { -// uart_tx_all(p_uart->uart_num, (const char*) data + sizeof(uart_event_t), evt.data.size, 0, 0); -// } else if(evt.type == UART_DATA_BREAK) { -// uart_tx_all(p_uart->uart_num, (const char*) data + sizeof(uart_event_t), evt.data.size, 1, evt.data.brk_len); -// } -// vRingbufferReturnItem(p_uart->tx_ring_buf, data); -// } -// vTaskDelete(NULL); -//} - int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); UART_CHECK((p_uart_obj[uart_num] != NULL), "uart driver error"); UART_CHECK(src, "buffer null"); + //Push data to TX ring buffer and return, ISR will send the data. if(p_uart_obj[uart_num]->tx_buf_size > 0) { if(xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf) > (size + sizeof(uart_event_t))) { uart_event_t evt; - xSemaphoreTake(p_uart_obj[uart_num]->tx_buffer_mutex, (portTickType)portMAX_DELAY); + xSemaphoreTake(p_uart_obj[uart_num]->tx_buffer_mux, (portTickType)portMAX_DELAY); evt.type = UART_DATA; evt.data.size = size; - ets_printf("-----1st send-----\n"); xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_event_t), portMAX_DELAY); - xRingbufferPrintInfo(p_uart_obj[uart_num]->tx_ring_buf); - ets_printf("====2nd send====\n"); xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) src, size, portMAX_DELAY); - xRingbufferPrintInfo(p_uart_obj[uart_num]->tx_ring_buf); - xSemaphoreGive(p_uart_obj[uart_num]->tx_buffer_mutex); + xSemaphoreGive(p_uart_obj[uart_num]->tx_buffer_mux); uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); return size; } else { @@ -785,6 +766,7 @@ int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size) return uart_tx_all(uart_num, src, size, 0, 0); } } else { + //Send data without TX ring buffer, the task will block until all data have been sent out return uart_tx_all(uart_num, src, size, 0, 0); } } @@ -796,16 +778,17 @@ int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t s UART_CHECK((size > 0), "uart size error"); UART_CHECK((src), "uart data null"); UART_CHECK((brk_len > 0 && brk_len < 256), "break_num error"); + //Push data to TX ring buffer and return, ISR will send the data. if(p_uart_obj[uart_num]->tx_buf_size > 0) { if(xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf) > (size)) { uart_event_t evt; - xSemaphoreTake(p_uart_obj[uart_num]->tx_buffer_mutex, (portTickType)portMAX_DELAY); + xSemaphoreTake(p_uart_obj[uart_num]->tx_buffer_mux, (portTickType)portMAX_DELAY); evt.type = UART_DATA_BREAK; evt.data.size = size; evt.data.brk_len = brk_len; xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_event_t), portMAX_DELAY); xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) src, size, portMAX_DELAY); - xSemaphoreGive(p_uart_obj[uart_num]->tx_buffer_mutex); + xSemaphoreGive(p_uart_obj[uart_num]->tx_buffer_mux); uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); return size; } else { @@ -813,6 +796,7 @@ int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t s return uart_tx_all(uart_num, src, size, 1, brk_len); } } else { + //Send data without TX ring buffer, the task will block until all data have been sent out return uart_tx_all(uart_num, src, size, 1, brk_len); } } @@ -828,29 +812,29 @@ int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait) if(xSemaphoreTake(p_uart_obj[uart_num]->rx_mux,(portTickType)ticks_to_wait) != pdTRUE) { return -1; } - if(p_uart_obj[uart_num]->cur_remain == 0) { + if(p_uart_obj[uart_num]->rx_cur_remain == 0) { ticks_to_wait = ticks_end - xTaskGetTickCount(); data = (uint8_t*) xRingbufferReceive(p_uart_obj[uart_num]->rx_ring_buf, &size, (portTickType) ticks_to_wait); if(data) { - p_uart_obj[uart_num]->head_ptr = data; - p_uart_obj[uart_num]->rd_ptr = data; - p_uart_obj[uart_num]->cur_remain = size; + p_uart_obj[uart_num]->rx_head_ptr = data; + p_uart_obj[uart_num]->rx_ptr = data; + p_uart_obj[uart_num]->rx_cur_remain = size; } else { xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); return -1; } } - val = *(p_uart_obj[uart_num]->rd_ptr); - p_uart_obj[uart_num]->rd_ptr++; - p_uart_obj[uart_num]->cur_remain--; - if(p_uart_obj[uart_num]->cur_remain == 0) { - vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->head_ptr); - p_uart_obj[uart_num]->head_ptr = NULL; - p_uart_obj[uart_num]->rd_ptr = NULL; - if(p_uart_obj[uart_num]->buffer_full_flg) { - BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->data_buf, p_uart_obj[uart_num]->data_len, 1); + val = *(p_uart_obj[uart_num]->rx_ptr); + p_uart_obj[uart_num]->rx_ptr++; + p_uart_obj[uart_num]->rx_cur_remain--; + if(p_uart_obj[uart_num]->rx_cur_remain == 0) { + vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_head_ptr); + p_uart_obj[uart_num]->rx_head_ptr = NULL; + p_uart_obj[uart_num]->rx_ptr = NULL; + if(p_uart_obj[uart_num]->rx_buffer_full_flg) { + BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1); if(res == pdTRUE) { - p_uart_obj[uart_num]->buffer_full_flg = false; + p_uart_obj[uart_num]->rx_buffer_full_flg = false; uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); } } @@ -872,46 +856,40 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp return -1; } while(length) { - if(p_uart_obj[uart_num]->cur_remain == 0) { + if(p_uart_obj[uart_num]->rx_cur_remain == 0) { data = (uint8_t*) xRingbufferReceive(p_uart_obj[uart_num]->rx_ring_buf, &size, (portTickType) ticks_to_wait); if(data) { - p_uart_obj[uart_num]->head_ptr = data; - p_uart_obj[uart_num]->rd_ptr = data; - p_uart_obj[uart_num]->cur_remain = size; -// ets_printf("dbg0\n"); + p_uart_obj[uart_num]->rx_head_ptr = data; + p_uart_obj[uart_num]->rx_ptr = data; + p_uart_obj[uart_num]->rx_cur_remain = size; } else { xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); -// ets_printf("dbg1\n"); return copy_len; } } - if(p_uart_obj[uart_num]->cur_remain > length) { + if(p_uart_obj[uart_num]->rx_cur_remain > length) { len_tmp = length; } else { - len_tmp = p_uart_obj[uart_num]->cur_remain; + len_tmp = p_uart_obj[uart_num]->rx_cur_remain; } -// ets_printf("dbga\n"); - memcpy(buf + copy_len, p_uart_obj[uart_num]->rd_ptr, len_tmp); - p_uart_obj[uart_num]->rd_ptr += len_tmp; - p_uart_obj[uart_num]->cur_remain -= len_tmp; + memcpy(buf + copy_len, p_uart_obj[uart_num]->rx_ptr, len_tmp); + p_uart_obj[uart_num]->rx_ptr += len_tmp; + p_uart_obj[uart_num]->rx_cur_remain -= len_tmp; copy_len += len_tmp; length -= len_tmp; -// ets_printf("dbgb\n"); - if(p_uart_obj[uart_num]->cur_remain == 0) { - vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->head_ptr); - p_uart_obj[uart_num]->head_ptr = NULL; - p_uart_obj[uart_num]->rd_ptr = NULL; - if(p_uart_obj[uart_num]->buffer_full_flg) { - BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->data_buf, p_uart_obj[uart_num]->data_len, 1); -// ets_printf("dbg2\n"); + if(p_uart_obj[uart_num]->rx_cur_remain == 0) { + vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_head_ptr); + p_uart_obj[uart_num]->rx_head_ptr = NULL; + p_uart_obj[uart_num]->rx_ptr = NULL; + if(p_uart_obj[uart_num]->rx_buffer_full_flg) { + BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1); if(res == pdTRUE) { - p_uart_obj[uart_num]->buffer_full_flg = false; + p_uart_obj[uart_num]->rx_buffer_full_flg = false; uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); } } } } -// ets_printf("dbg3\n"); xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); return copy_len; } @@ -926,11 +904,11 @@ esp_err_t uart_flush(uart_port_t uart_num) //rx sem protect the ring buffer read related functions xSemaphoreTake(p_uart->rx_mux, (portTickType)portMAX_DELAY); while(true) { - if(p_uart->head_ptr) { - vRingbufferReturnItem(p_uart->rx_ring_buf, p_uart->head_ptr); - p_uart->rd_ptr = NULL; - p_uart->cur_remain = 0; - p_uart->head_ptr = NULL; + if(p_uart->rx_head_ptr) { + vRingbufferReturnItem(p_uart->rx_ring_buf, p_uart->rx_head_ptr); + p_uart->rx_ptr = NULL; + p_uart->rx_cur_remain = 0; + p_uart->rx_head_ptr = NULL; } data = (uint8_t*) xRingbufferReceive(p_uart->rx_ring_buf, &size, (portTickType) 0); if(data == NULL) { @@ -938,19 +916,24 @@ esp_err_t uart_flush(uart_port_t uart_num) } vRingbufferReturnItem(p_uart->rx_ring_buf, data); } - p_uart->rd_ptr = NULL; - p_uart->cur_remain = 0; - p_uart->head_ptr = NULL; + p_uart->rx_ptr = NULL; + p_uart->rx_cur_remain = 0; + p_uart->rx_head_ptr = NULL; xSemaphoreGive(p_uart->rx_mux); - xSemaphoreTake(p_uart->tx_mutex, (portTickType)portMAX_DELAY); - do { - data = (uint8_t*) xRingbufferReceive(p_uart->tx_ring_buf, &size, (portTickType) 0); - if(data == NULL) { - break; - } - vRingbufferReturnItem(p_uart->rx_ring_buf, data); - } while(1); - xSemaphoreGive(p_uart->tx_mutex); + + xSemaphoreTake(p_uart->tx_mux, (portTickType)portMAX_DELAY); + if(p_uart->tx_buf_size > 0) { + xSemaphoreTake(p_uart->tx_buffer_mux, (portTickType)portMAX_DELAY); + do { + data = (uint8_t*) xRingbufferReceive(p_uart->tx_ring_buf, &size, (portTickType) 0); + if(data == NULL) { + break; + } + vRingbufferReturnItem(p_uart->rx_ring_buf, data); + } while(1); + xSemaphoreGive(p_uart->tx_buffer_mux); + } + xSemaphoreGive(p_uart->tx_mux); uart_wait_tx_done(uart_num, portMAX_DELAY); uart_reset_fifo(uart_num); return ESP_OK; @@ -1009,7 +992,7 @@ int uart_get_print_port() return s_uart_print_nport; } -esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue, ringbuf_type_t rx_buf_type) +esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); UART_CHECK((rx_buffer_size > 0), "uart rx buffer length error\n"); @@ -1025,11 +1008,16 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); p_uart_obj[uart_num]->tx_done_sem = xSemaphoreCreateBinary(); p_uart_obj[uart_num]->tx_brk_sem = xSemaphoreCreateBinary(); - p_uart_obj[uart_num]->tx_mutex = xSemaphoreCreateMutex(); - p_uart_obj[uart_num]->tx_buffer_mutex = xSemaphoreCreateMutex(); + p_uart_obj[uart_num]->tx_mux = xSemaphoreCreateMutex(); p_uart_obj[uart_num]->rx_mux = xSemaphoreCreateMutex(); p_uart_obj[uart_num]->intr_num = uart_intr_num; p_uart_obj[uart_num]->queue_size = queue_size; + p_uart_obj[uart_num]->tx_ptr = NULL; + p_uart_obj[uart_num]->tx_head = NULL; + p_uart_obj[uart_num]->tx_len_tot = 0; + p_uart_obj[uart_num]->tx_brk_flg = 0; + p_uart_obj[uart_num]->tx_brk_len = 0; + p_uart_obj[uart_num]->tx_waiting_brk = 0; if(uart_queue) { p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t)); @@ -1038,19 +1026,20 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b } else { p_uart_obj[uart_num]->xQueueUart = NULL; } - p_uart_obj[uart_num]->buffer_full_flg = false; - p_uart_obj[uart_num]->tx_waiting = false; - p_uart_obj[uart_num]->rd_ptr = NULL; - p_uart_obj[uart_num]->cur_remain = 0; - p_uart_obj[uart_num]->head_ptr = NULL; - p_uart_obj[uart_num]->rx_buf_type = rx_buf_type; - p_uart_obj[uart_num]->rx_ring_buf = xRingbufferCreate(rx_buffer_size, rx_buf_type); + p_uart_obj[uart_num]->rx_buffer_full_flg = false; + p_uart_obj[uart_num]->tx_waiting_fifo = false; + p_uart_obj[uart_num]->rx_ptr = NULL; + p_uart_obj[uart_num]->rx_cur_remain = 0; + p_uart_obj[uart_num]->rx_head_ptr = NULL; + p_uart_obj[uart_num]->rx_ring_buf = xRingbufferCreate(rx_buffer_size, RINGBUF_TYPE_BYTEBUF); if(tx_buffer_size > 0) { p_uart_obj[uart_num]->tx_ring_buf = xRingbufferCreate(tx_buffer_size, RINGBUF_TYPE_NOSPLIT);//RINGBUF_TYPE_BYTEBUF);//RINGBUF_TYPE_NOSPLIT); p_uart_obj[uart_num]->tx_buf_size = tx_buffer_size; + p_uart_obj[uart_num]->tx_buffer_mux = xSemaphoreCreateMutex(); } else { p_uart_obj[uart_num]->tx_ring_buf = NULL; p_uart_obj[uart_num]->tx_buf_size = 0; + p_uart_obj[uart_num]->tx_buffer_mux = NULL; } } else { ESP_LOGE(UART_TAG, "UART driver already installed\n"); @@ -1097,13 +1086,13 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) vSemaphoreDelete(p_uart_obj[uart_num]->tx_brk_sem); p_uart_obj[uart_num]->tx_brk_sem = NULL; } - if(p_uart_obj[uart_num]->tx_mutex) { - vSemaphoreDelete(p_uart_obj[uart_num]->tx_mutex); - p_uart_obj[uart_num]->tx_mutex = NULL; + if(p_uart_obj[uart_num]->tx_mux) { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_mux); + p_uart_obj[uart_num]->tx_mux = NULL; } - if(p_uart_obj[uart_num]->tx_buffer_mutex) { - vSemaphoreDelete(p_uart_obj[uart_num]->tx_buffer_mutex); - p_uart_obj[uart_num]->tx_buffer_mutex = NULL; + if(p_uart_obj[uart_num]->tx_buffer_mux) { + vSemaphoreDelete(p_uart_obj[uart_num]->tx_buffer_mux); + p_uart_obj[uart_num]->tx_buffer_mux = NULL; } if(p_uart_obj[uart_num]->rx_mux) { vSemaphoreDelete(p_uart_obj[uart_num]->rx_mux); diff --git a/components/freertos/ringbuf.c b/components/freertos/ringbuf.c index 560eb5fdd..a4205d88d 100644 --- a/components/freertos/ringbuf.c +++ b/components/freertos/ringbuf.c @@ -77,13 +77,9 @@ static int ringbufferFreeMem(ringbuf_t *rb) { int free_size = rb->free_ptr-rb->write_ptr; if (free_size <= 0) free_size += rb->size; - //If we free the last dummy item in the buffer, free_ptr will point to rb->data - //In this case, after we write the last some bytes, the buffer might wrap around if we don't have room for a header anymore. -// if (free_size == 0 && rb->read_ptr == rb->write_ptr) free_size += rb->size; //Reserve one byte. If we do not do this and the entire buffer is filled, we get a situation - //where write_ptr == free_ptr, messing up the next calculation. -// return free_size == 0 ? 0 : free_size - 1; - return free_size - 1; + //where read_ptr == free_ptr, messing up the next calculation. + return free_size-1; } @@ -338,10 +334,6 @@ static uint8_t *getItemFromRingbufByteBuf(ringbuf_t *rb, size_t *length, int wan //can be increase. //This function by itself is not threadsafe, always call from within a muxed section. static void returnItemToRingbufDefault(ringbuf_t *rb, void *item) { - ets_printf("in returnItemToRingbufDefault\n"); - xRingbufferPrintInfo(rb); - - uint8_t *data=(uint8_t*)item; configASSERT(((int)rb->free_ptr&3)==0); configASSERT(data >= rb->data); @@ -358,16 +350,9 @@ static void returnItemToRingbufDefault(ringbuf_t *rb, void *item) { hdr=(buf_entry_hdr_t *)rb->free_ptr; //basically forward free_ptr until we run into either a block that is still in use or the write pointer. while (((hdr->flags & iflag_free) || (hdr->flags & iflag_dummydata)) && rb->free_ptr != rb->write_ptr) { - if (hdr->flags & iflag_dummydata) { - ets_printf("hrd len: %d; flg: 0x%02x\n",hdr->len,hdr->flags); //Rest is dummy data. Reset to start of ringbuffer. rb->free_ptr=rb->data; - //If the read_ptr is pointing to this dummy item, - //we should also move the read pointer to data, in case we overwrite the read hdr. -// if(rb->read_ptr == (uint8_t*)hdr) { -// rb->read_ptr = rb->data; -// } } else { //Skip past item size_t len=(hdr->len+3)&~3; @@ -378,10 +363,11 @@ static void returnItemToRingbufDefault(ringbuf_t *rb, void *item) { if ((rb->data+rb->size)-rb->free_ptr < sizeof(buf_entry_hdr_t)) { rb->free_ptr=rb->data; } + //The free_ptr can not exceed read_ptr, otherwise write_ptr might overwrite read_ptr. + //Read_ptr can not set to rb->data with free_ptr, otherwise write_ptr might wrap around to rb->data. if(rb->free_ptr == rb->read_ptr) break; //Next header hdr=(buf_entry_hdr_t *)rb->free_ptr; - } } @@ -403,12 +389,6 @@ void xRingbufferPrintInfo(RingbufHandle_t ringbuf) configASSERT(rb); ets_printf("Rb size %d free %d rptr %d freeptr %d wptr %d\n", rb->size, ringbufferFreeMem(rb), rb->read_ptr-rb->data, rb->free_ptr-rb->data, rb->write_ptr-rb->data); - buf_entry_hdr_t *hdr=(buf_entry_hdr_t *)rb->read_ptr; - if(rb->write_ptr == rb->read_ptr) { - ets_printf("write que read\n"); - } else { - ets_printf("hdr len: %d; flg: 0x%08x\n", hdr->len, hdr->flags); - } } @@ -516,7 +496,7 @@ BaseType_t xRingbufferSend(RingbufHandle_t ringbuf, void *data, size_t dataSize, ticks_to_wait = ticks_end - xTaskGetTickCount(); } } while (ringbufferFreeMem(rb) < needed_size && ticks_to_wait>=0); - + //Lock the mux in order to make sure no one else is messing with the ringbuffer and do the copy. portENTER_CRITICAL(&rb->mux); //Another thread may have been able to sneak its write first. Check again now we locked the ringbuff, and retry From a6b3be6734b8f8acd13a8f401d046f3531b7a893 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Fri, 4 Nov 2016 02:48:25 +0800 Subject: [PATCH 09/12] Update UART driver 1. fix bug in ringbuffer.c: When return an dummy item, free_ptr might exceed rd_ptr, so the write_ptr would overwrite rd_ptr in this case. 2. Delete UART tx task in buffer mode. UART ISR will copy the data from tx buffer to fifo. --- components/driver/include/driver/uart.h | 110 +++++++-- components/driver/uart.c | 285 ++++++++++++------------ 2 files changed, 237 insertions(+), 158 deletions(-) diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index 0d9ab3c56..200d1148c 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -87,8 +87,8 @@ typedef struct { uart_word_length_t data_bits; /*!< UART byte size*/ uart_parity_t parity; /*!< UART parity mode*/ uart_stop_bits_t stop_bits; /*!< UART stop bits*/ - uart_hw_flowcontrol_t flow_ctrl; /*!< UART hw flow control mode(cts/rts)*/ - uint8_t rx_flow_ctrl_thresh ; /*!< UART hw RTS threshold*/ + uart_hw_flowcontrol_t flow_ctrl; /*!< UART HW flow control mode(cts/rts)*/ + uint8_t rx_flow_ctrl_thresh ; /*!< UART HW RTS threshold*/ } uart_config_t; typedef struct { @@ -124,6 +124,7 @@ typedef struct { * @brief Set UART data bits. * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param data_bit UART data bits * * @return @@ -147,6 +148,7 @@ esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bi * @brief Set UART stop bits. * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param bit_num UART stop bits * * @return @@ -170,6 +172,7 @@ esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit); * @brief Set UART parity. * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param parity_mode the enum of uart parity configuration * * @return @@ -194,6 +197,7 @@ esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode); * @brief Set UART baud rate. * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param baud_rate UART baud-rate. * * @return @@ -216,7 +220,9 @@ esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate); /** * @brief Set UART line inverse mode + * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param inverse_mask Choose the wires that need to be inversed. * * (inverse_mask should be chosen from uart_inverse_t, combine with OR-OPERATION) @@ -232,7 +238,9 @@ esp_err_t uart_set_line_inverse(uart_port_t uart_no, uint32_t inverse_mask) ; * @brief Set hardware flow control. * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param flow_ctrl Hardware flow control mode + * * @param rx_thresh Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN) * * @return @@ -243,6 +251,7 @@ esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_no, uart_hw_flowcontrol_t flow_ /** * @brief Get hardware flow control mode + * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * * @return @@ -255,6 +264,7 @@ esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flo * @brief Clear UART interrupt status * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param clr_mask Bit mask of the status that to be cleared. * * (enable_mask should be chosen from the fields of register UART_INT_CLR_REG) @@ -269,6 +279,7 @@ esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask); * @brief Set UART interrupt enable * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param enable_mask Bit mask of the enable bits. * * (enable_mask should be chosen from the fields of register UART_INT_ENA_REG) @@ -283,6 +294,7 @@ esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask); * @brief Clear UART interrupt enable bits * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param disable_mask Bit mask of the disable bits. * * (disable_mask should be chosen from the fields of register UART_INT_ENA_REG) @@ -331,7 +343,9 @@ esp_err_t uart_disable_tx_intr(uart_port_t uart_num); * @brief Enable UART TX interrupt(RX_FULL & RX_TIMEOUT INTERRUPT) * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param enable 1: enable; 0: disable + * * @param thresh Threshold of TX interrupt, 0 ~ UART_FIFO_LEN * * @return @@ -342,13 +356,16 @@ esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh); /** * @brief register UART interrupt handler(ISR). +* @note * UART ISR handler will be attached to the same CPU core that this function is running on. * Users should know that which CPU is running and then pick a INUM that is not used by system. * We can find the information of INUM and interrupt level in soc.h. * * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details + * * @param fn Interrupt handler function. * @attention * The ISR handler function MUST be defined with attribution of "IRAM_ATTR" for now. @@ -364,9 +381,13 @@ esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (* * @brief Set UART pin number * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param tx_io_num UART TX pin GPIO number + * * @param rx_io_num UART RX pin GPIO number + * * @param rts_io_num UART RTS pin GPIO number + * * @param cts_io_num UART CTS pin GPIO number * * @return @@ -380,6 +401,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r * UART rx hardware flow control should not be set. * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param level 1: RTS output low(active); 0: RTS output high(block) * * @return @@ -392,6 +414,7 @@ esp_err_t uart_set_rts(uart_port_t uart_num, int level); * @brief UART set DTR level (before inverse) * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param level 1: DTR output low; 0: DTR output high * * @return @@ -404,6 +427,7 @@ esp_err_t uart_set_dtr(uart_port_t uart_num, int level); * @brief UART parameter configure * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param uart_config UART parameter settings * * @return @@ -416,6 +440,7 @@ esp_err_t uart_param_config(uart_port_t uart_num, uart_config_t *uart_config); * @brief UART interrupt configure * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param p_intr_conf UART interrupt settings * * @return @@ -431,12 +456,19 @@ esp_err_t uart_intr_config(uart_port_t uart_num, uart_intr_config_t *p_intr_conf * Users should know that which CPU is running and then pick a INUM that is not used by system. * We can find the information of INUM and interrupt level in soc.h. * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * @param rx_buffer_size UART RX ring buffer size - * @param tx_buffer_size UART TX ring buffer size, if set to zero, driver will not use TX buffer and TX task. - * @param queue_size UART event queue size/depth. + * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * + * @param rx_buffer_size UART RX ring buffer size + * + * @param tx_buffer_size UART TX ring buffer size. + * + * If set to zero, driver will not use TX buffer, TX function will block task until all data have been sent out.. + * + * @param queue_size UART event queue size/depth. + * * @param uart_intr_num UART interrupt number,check the info in soc.h, and please refer to core-isa.h for more details - * @param uart_queue UART event queue handle, if set NULL, driver will not use an event queue. + * + * @param uart_queue UART event queue handle, if set NULL, driver will not use an event queue. * * @return * - ESP_OK Success @@ -459,6 +491,7 @@ esp_err_t uart_driver_delete(uart_port_t uart_num); * @brief Wait UART TX FIFO empty * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param ticks_to_wait Timeout, count in RTOS ticks * * @return @@ -473,7 +506,9 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait); * This function will not wait for the space in TX FIFO, just fill the TX FIFO and return when the FIFO is full. * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param buffer data buffer address + * * @param len data length to send * * @return @@ -484,10 +519,17 @@ int uart_tx_chars(uart_port_t uart_no, char* buffer, uint32_t len); /** * @brief Send data to the UART port from a given buffer and length, + * + * If parameter tx_buffer_size is set to zero: * This function will not return until all the data have been sent out, or at least pushed into TX FIFO. * + * Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer, + * then, UART ISR will move data from ring buffer to TX FIFO gradually. + * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param src data buffer address + * * @param size data length to send * * @return @@ -498,23 +540,37 @@ int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size); /** * @brief Send data to the UART port from a given buffer and length, + * + * If parameter tx_buffer_size is set to zero: * This function will not return until all the data and the break signal have been sent out. + * After all data send out, send a break signal. + * + * Otherwise, if tx_buffer_size > 0, this function will return after copying all the data to tx ringbuffer, + * then, UART ISR will move data from ring buffer to TX FIFO gradually. + * After all data send out, send a break signal. + * + * * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param src data buffer address + * * @param size data length to send + * * @param brk_len break signal length (unit: one bit's time@current_baudrate) * * @return * - (-1) Parameter error * - OTHERS(>=0) The number of data that pushed to the TX FIFO */ + int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len); /** * @brief UART read one char * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param ticks_to_wait Timeout, count in RTOS ticks * * @return @@ -527,10 +583,14 @@ int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait); * @brief UART read bytes from UART buffer * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 + * * @param buf pointer to the buffer. + * * @param length data length + * * @param ticks_to_wait sTimeout, count in RTOS ticks * + * * @return * - (-1) Error * - Others return a char data from uart fifo. @@ -588,14 +648,17 @@ int uart_get_print_port(void); * uart_param_config(uart_num, &uart_config); * //b1. Setup UART driver(with UART queue) * QueueHandle_t uart_queue; - * uart_driver_install(uart_num, 1024 * 2, 10, UART_INTR_NUM, &uart_queue);//parameters here are just an example + * //parameters here are just an example, tx buffer size is 2048 + * uart_driver_install(uart_num, 1024 * 2, 1024 * 2, 10, UART_INTR_NUM, &uart_queue); * //b2. Setup UART driver(without UART queue) - * uart_driver_install(uart_num, 1024 * 2, 10, UART_INTR_NUM, NULL); //parameters here are just an example + * //parameters here are just an example, tx buffer size is 0 + * uart_driver_install(uart_num, 1024 * 2, 0, 10, UART_INTR_NUM, NULL); *@endcode *-----------------------------------------------------------------------------* * @code{c} * //2. Set UART pin - * uart_set_pin(uart_num, -1, -1, 15, 13); //set UART pin, not needed if use default pins. + * //set UART pin, not needed if use default pins. + * uart_set_pin(uart_num, -1, -1, 15, 13); * @endcode *-----------------------------------------------------------------------------* * @code{c} @@ -629,15 +692,20 @@ int uart_get_print_port(void); * .flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS, * .rx_flow_ctrl_thresh = 122, * }; - * uart_param_config(uart_num, &uart_config); //Config UART1 parameters - * uart_set_pin(uart_num, 16, 17, 18, 19); //Set UART1 pins(TX: IO16, RX: IO17, RTS: IO18, CTS: IO19) - * esp_log_level_set(UART_TAG, ESP_LOG_ERROR); //Set UART log level + * //Configure UART1 parameters + * uart_param_config(uart_num, &uart_config); + * //Set UART1 pins(TX: IO16, RX: IO17, RTS: IO18, CTS: IO19) + * uart_set_pin(uart_num, 16, 17, 18, 19); + * //Set UART log level + * esp_log_level_set(UART_TAG, ESP_LOG_ERROR); * //Install UART driver( We don't need an event queue here) * uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, 17, NULL, RINGBUF_TYPE_BYTEBUF); * uint8_t data[1000]; * while(1) { - * int len = uart_read_bytes(uart_num, data, sizeof(data), 10); //Read data from UART - * uart_tx_all_chars(uart_num, (const char*)data, len); //Write data back to UART + * //Read data from UART + * int len = uart_read_bytes(uart_num, data, sizeof(data), 10); + * //Write data back to UART + * uart_tx_all_chars(uart_num, (const char*)data, len); * } * } * @endcode @@ -704,12 +772,16 @@ int uart_get_print_port(void); * .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, * .rx_flow_ctrl_thresh = 122, * }; - * uart_param_config(uart_num, &uart_config); //Set UART parameters - * uart_set_pin(uart_num, -1, -1, 15, 13); //Set UART pins,(-1: default pin, no change.) - * esp_log_level_set(UART_TAG, ESP_LOG_INFO); //Set UART log level + * //Set UART parameters + * uart_param_config(uart_num, &uart_config); + * //Set UART pins,(-1: default pin, no change.) + * uart_set_pin(uart_num, -1, -1, 15, 13); + * //Set UART log level + * esp_log_level_set(UART_TAG, ESP_LOG_INFO); * //Install UART driver, and get the queue. * uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, 17, &uart0_queue, RINGBUF_TYPE_BYTEBUF); - * xTaskCreate(uart_task, "uTask", 2048*8, (void*)uart_num, 10, NULL); //Create a task to handler UART event from ISR + * //Create a task to handler UART event from ISR + * xTaskCreate(uart_task, "uTask", 2048*8, (void*)uart_num, 10, NULL); * } * @endcode * diff --git a/components/driver/uart.c b/components/driver/uart.c index 9eaf78343..cab05dd0b 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -30,9 +30,9 @@ #include "soc/uart_struct.h" const char* UART_TAG = "UART"; -#define UART_CHECK(a, str) if (!(a)) { \ +#define UART_CHECK(a, str, ret) if (!(a)) { \ ESP_LOGE(UART_TAG,"%s:%d (%s):%s\n", __FILE__, __LINE__, __FUNCTION__, str); \ - return ESP_FAIL; \ + return (ret); \ } #define UART_EMPTY_THRESH_DEFAULT (10) #define UART_FULL_THRESH_DEFAULT (120) @@ -42,6 +42,7 @@ const char* UART_TAG = "UART"; #define UART_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux) #define UART_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) + typedef struct { uart_port_t uart_num; /*!< UART port number*/ int queue_size; /*!< UART event queue size*/ @@ -60,7 +61,6 @@ typedef struct { //tx parameters SemaphoreHandle_t tx_fifo_sem; /*!< UART TX FIFO semaphore*/ SemaphoreHandle_t tx_mux; /*!< UART TX mutex*/ - SemaphoreHandle_t tx_buffer_mux; /*!< UART TX buffer semaphore*/ SemaphoreHandle_t tx_done_sem; /*!< UART TX done semaphore*/ SemaphoreHandle_t tx_brk_sem; /*!< UART TX send break done semaphore*/ int tx_buf_size; /*!< TX ring buffer size */ @@ -69,6 +69,7 @@ typedef struct { uint8_t* tx_ptr; /*!< TX data pointer to push to FIFO in TX buffer mode*/ uart_event_t* tx_head; /*!< TX data pointer to head of the current buffer in TX ring buffer*/ uint32_t tx_len_tot; /*!< Total length of current item in ring buffer*/ + uint32_t tx_len_cur; uint8_t tx_brk_flg; /*!< Flag to indicate to send a break signal in the end of the item sending procedure */ uint8_t tx_brk_len; /*!< TX break signal cycle length/number */ uint8_t tx_waiting_brk; /*!< Flag to indicate that TX FIFO is ready to send break signal after FIFO is empty, do not push data into TX FIFO right now.*/ @@ -80,8 +81,8 @@ static portMUX_TYPE uart_spinlock[UART_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((data_bit < UART_DATA_MAX_BITS), "data bit error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); + UART_CHECK((data_bit < UART_DATA_MAX_BITS), "data bit error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); UART[uart_num]->conf0.bit_num = data_bit; UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); @@ -90,15 +91,15 @@ esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit esp_err_t uart_get_word_length(uart_port_t uart_num, uart_word_length_t* data_bit) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); *(data_bit) = UART[uart_num]->conf0.bit_num; return ESP_OK; } esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bit) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((stop_bit < UART_STOP_BITS_MAX), "stop bit error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); + UART_CHECK((stop_bit < UART_STOP_BITS_MAX), "stop bit error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); UART[uart_num]->conf0.stop_bit_num = stop_bit; UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); @@ -107,14 +108,14 @@ esp_err_t uart_set_stop_bits(uart_port_t uart_num, uart_stop_bits_t stop_bit) esp_err_t uart_get_stop_bits(uart_port_t uart_num, uart_stop_bits_t* stop_bit) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); (*stop_bit) = UART[uart_num]->conf0.stop_bit_num; return ESP_OK; } esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); UART[uart_num]->conf0.parity = parity_mode & 0x1; UART[uart_num]->conf0.parity_en = (parity_mode >> 1) & 0x1; @@ -124,7 +125,7 @@ esp_err_t uart_set_parity(uart_port_t uart_num, uart_parity_t parity_mode) esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); int val = UART[uart_num]->conf0.val; if(val & UART_PARITY_EN_M) { if(val & UART_PARITY_M) { @@ -140,8 +141,8 @@ esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode) esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((baud_rate < UART_BITRATE_MAX), "baud_rate error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); + UART_CHECK((baud_rate < UART_BITRATE_MAX), "baud_rate error", ESP_FAIL); uint32_t clk_div = (((UART_CLK_FREQ) << 4) / baud_rate); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); UART[uart_num]->clk_div.div_int = clk_div >> 4; @@ -152,7 +153,7 @@ esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate) esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); uint32_t clk_div = (UART[uart_num]->clk_div.div_int << 4) | UART[uart_num]->clk_div.div_frag; UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); @@ -162,8 +163,8 @@ esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate) esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((((inverse_mask & UART_LINE_INV_MASK) == 0) && (inverse_mask != 0)), "inverse_mask error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); + UART_CHECK((((inverse_mask & UART_LINE_INV_MASK) == 0) && (inverse_mask != 0)), "inverse_mask error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); CLEAR_PERI_REG_MASK(UART_CONF0_REG(uart_num), UART_LINE_INV_MASK); SET_PERI_REG_MASK(UART_CONF0_REG(uart_num), inverse_mask); @@ -174,9 +175,9 @@ esp_err_t uart_set_line_inverse(uart_port_t uart_num, uint32_t inverse_mask) //only when UART_HW_FLOWCTRL_RTS is set , will the rx_thresh value be set. esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow_ctrl, uint8_t rx_thresh) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((rx_thresh < UART_FIFO_LEN), "rx flow thresh error"); - UART_CHECK((flow_ctrl < UART_HW_FLOWCTRL_MAX), "hw_flowctrl mode error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); + UART_CHECK((rx_thresh < UART_FIFO_LEN), "rx flow thresh error", ESP_FAIL); + UART_CHECK((flow_ctrl < UART_HW_FLOWCTRL_MAX), "hw_flowctrl mode error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); if(flow_ctrl & UART_HW_FLOWCTRL_RTS) { UART[uart_num]->conf1.rx_flow_thrhd = rx_thresh; @@ -195,7 +196,7 @@ esp_err_t uart_set_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t flow esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flow_ctrl) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); uart_hw_flowcontrol_t val = UART_HW_FLOWCTRL_DISABLE; if(UART[uart_num]->conf1.rx_flow_en) { val |= UART_HW_FLOWCTRL_RTS; @@ -209,7 +210,7 @@ esp_err_t uart_get_hw_flow_ctrl(uart_port_t uart_num, uart_hw_flowcontrol_t* flo static esp_err_t uart_reset_fifo(uart_port_t uart_num) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); UART[uart_num]->conf0.rxfifo_rst = 1; UART[uart_num]->conf0.rxfifo_rst = 0; @@ -221,7 +222,7 @@ static esp_err_t uart_reset_fifo(uart_port_t uart_num) esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); //intr_clr register is write-only UART[uart_num]->int_clr.val = clr_mask; return ESP_OK; @@ -229,7 +230,7 @@ esp_err_t uart_clear_intr_status(uart_port_t uart_num, uint32_t clr_mask) esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); SET_PERI_REG_MASK(UART_INT_CLR_REG(uart_num), enable_mask); SET_PERI_REG_MASK(UART_INT_ENA_REG(uart_num), enable_mask); @@ -239,7 +240,7 @@ esp_err_t uart_enable_intr_mask(uart_port_t uart_num, uint32_t enable_mask) esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(uart_num), disable_mask); UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); @@ -248,7 +249,7 @@ esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask) esp_err_t uart_enable_rx_intr(uart_port_t uart_num) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); SET_PERI_REG_MASK(UART_INT_ENA_REG(uart_num), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA); UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); @@ -257,7 +258,7 @@ esp_err_t uart_enable_rx_intr(uart_port_t uart_num) esp_err_t uart_disable_rx_intr(uart_port_t uart_num) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(uart_num), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA); UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); @@ -266,7 +267,7 @@ esp_err_t uart_disable_rx_intr(uart_port_t uart_num) esp_err_t uart_disable_tx_intr(uart_port_t uart_num) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); UART[uart_num]->int_ena.txfifo_empty = 0; UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); @@ -275,8 +276,8 @@ esp_err_t uart_disable_tx_intr(uart_port_t uart_num) esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((thresh < UART_FIFO_LEN), "empty intr threshold error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); + UART_CHECK((thresh < UART_FIFO_LEN), "empty intr threshold error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); UART[uart_num]->int_clr.txfifo_empty = 1; UART[uart_num]->conf1.txfifo_empty_thrhd = thresh & UART_TXFIFO_EMPTY_THRHD_V; @@ -288,7 +289,7 @@ esp_err_t uart_enable_tx_intr(uart_port_t uart_num, int enable, int thresh) esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (*fn)(void*), void * arg) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); ESP_INTR_DISABLE(uart_intr_num); switch(uart_num) { @@ -313,11 +314,11 @@ esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (* //only one GPIO pad can connect with input signal esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((tx_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(tx_io_num))), "tx_io_num error"); - UART_CHECK((rx_io_num < 0 || (GPIO_IS_VALID_GPIO(rx_io_num))), "rx_io_num error"); - UART_CHECK((rts_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(rts_io_num))), "rts_io_num error"); - UART_CHECK((cts_io_num < 0 || (GPIO_IS_VALID_GPIO(cts_io_num))), "cts_io_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); + UART_CHECK((tx_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(tx_io_num))), "tx_io_num error", ESP_FAIL); + UART_CHECK((rx_io_num < 0 || (GPIO_IS_VALID_GPIO(rx_io_num))), "rx_io_num error", ESP_FAIL); + UART_CHECK((rts_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(rts_io_num))), "rts_io_num error", ESP_FAIL); + UART_CHECK((cts_io_num < 0 || (GPIO_IS_VALID_GPIO(cts_io_num))), "cts_io_num error", ESP_FAIL); int tx_sig, rx_sig, rts_sig, cts_sig; switch(uart_num) { @@ -373,8 +374,8 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r esp_err_t uart_set_rts(uart_port_t uart_num, int level) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((UART[uart_num]->conf1.rx_flow_en != 1), "disable hw flowctrl before using sw control\n"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); + UART_CHECK((UART[uart_num]->conf1.rx_flow_en != 1), "disable hw flowctrl before using sw control\n", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); UART[uart_num]->conf0.sw_rts = level & 0x1; UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); @@ -383,7 +384,7 @@ esp_err_t uart_set_rts(uart_port_t uart_num, int level) esp_err_t uart_set_dtr(uart_port_t uart_num, int level) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); UART[uart_num]->conf0.sw_dtr = level & 0x1; UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); @@ -392,8 +393,8 @@ esp_err_t uart_set_dtr(uart_port_t uart_num, int level) esp_err_t uart_param_config(uart_port_t uart_num, uart_config_t *uart_config) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((uart_config), "param null\n"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); + UART_CHECK((uart_config), "param null\n", ESP_FAIL); if(uart_num == UART_NUM_0) { periph_module_enable(PERIPH_UART0_MODULE); } else if(uart_num == UART_NUM_1) { @@ -414,8 +415,8 @@ esp_err_t uart_param_config(uart_port_t uart_num, uart_config_t *uart_config) esp_err_t uart_intr_config(uart_port_t uart_num, uart_intr_config_t *p_intr_conf) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((p_intr_conf), "param null\n"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); + UART_CHECK((p_intr_conf), "param null\n", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); UART[uart_num]->int_clr.val = UART_INTR_MASK; if(p_intr_conf->intr_enable_mask & UART_RXFIFO_TOUT_INT_ENA_M) { @@ -458,7 +459,8 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) if(p_uart->tx_waiting_brk) { return; } - if(p_uart->tx_waiting_fifo == true) { + //TX semaphore used in none tx ringbuffer mode. + if(p_uart->tx_waiting_fifo == true && p_uart->tx_buf_size > 0) { p_uart->tx_waiting_fifo = false; xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, NULL); } @@ -473,57 +475,51 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) //That would cause a watch_dog reset because empty interrupt happens so often. //Although this is a loop in ISR, this loop will execute at most 128 turns. while(tx_fifo_rem) { - if(p_uart->tx_len_tot == 0) { + if(p_uart->tx_len_tot == 0 || p_uart->tx_ptr == NULL || p_uart->tx_len_cur == 0) { size_t size; - //The first item is the data description - //Get the first item to get the data information p_uart->tx_head = (uart_event_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); if(p_uart->tx_head) { - p_uart->tx_ptr = NULL; - p_uart->tx_len_tot = p_uart->tx_head->data.size; - if(p_uart->tx_head->type == UART_DATA_BREAK) { + //The first item is the data description + //Get the first item to get the data information + if(p_uart->tx_len_tot == 0) { + p_uart->tx_ptr = NULL; p_uart->tx_len_tot = p_uart->tx_head->data.size; - p_uart->tx_brk_flg = 1; - p_uart->tx_brk_len = p_uart->tx_head->data.brk_len; + if(p_uart->tx_head->type == UART_DATA_BREAK) { + p_uart->tx_len_tot = p_uart->tx_head->data.size; + p_uart->tx_brk_flg = 1; + p_uart->tx_brk_len = p_uart->tx_head->data.brk_len; + } + //We have saved the data description from the 1st item, return buffer. + vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken); + }else if(p_uart->tx_ptr == NULL) { + //Update the TX item pointer, we will need this to return item to buffer. + p_uart->tx_ptr = (uint8_t*) p_uart->tx_head; + en_tx_flg = true; + p_uart->tx_len_cur = size; } - //We have saved the data description from the 1st item, return buffer. - vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken); } else { //Can not get data from ring buffer, return; return; } } - if(p_uart->tx_ptr == NULL) { - size_t size; - //2nd item is the data we need to send through UART - //Get 2nd item from ring buffer - p_uart->tx_ptr = (uint8_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); - if(p_uart->tx_ptr) { - //Update the TX item head, we will need this to return item to buffer. - p_uart->tx_head = (void*) p_uart->tx_ptr; - en_tx_flg = true; - } else { - //Can not get data from ring buffer, return; - return; - } - } - if(p_uart->tx_len_tot > 0 && p_uart->tx_ptr) { + if(p_uart->tx_len_tot > 0 && p_uart->tx_ptr && p_uart->tx_len_cur > 0) { //To fill the TX FIFO. - int send_len = p_uart->tx_len_tot > tx_fifo_rem ? tx_fifo_rem : p_uart->tx_len_tot; + int send_len = p_uart->tx_len_cur > tx_fifo_rem ? tx_fifo_rem : p_uart->tx_len_cur; for(buf_idx = 0; buf_idx < send_len; buf_idx++) { WRITE_PERI_REG(UART_FIFO_AHB_REG(uart_num), *(p_uart->tx_ptr++) & 0xff); } p_uart->tx_len_tot -= send_len; + p_uart->tx_len_cur -= send_len; tx_fifo_rem -= send_len; - if(p_uart->tx_len_tot == 0) { - //Sending item done, now we need to send break if there is a record. + if(p_uart->tx_len_cur == 0) { //Return item to ring buffer. vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken); p_uart->tx_head = NULL; p_uart->tx_ptr = NULL; + //Sending item done, now we need to send break if there is a record. //Set TX break signal after FIFO is empty - if(p_uart->tx_brk_flg == 1) { + if(p_uart->tx_brk_flg == 1 && p_uart->tx_len_tot == 0) { UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_reg->int_ena.tx_brk_done = 0; uart_reg->idle_conf.tx_brk_num = p_uart->tx_brk_len; @@ -645,8 +641,8 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) /**************************************************************/ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL); BaseType_t res; portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait; //Take tx_mux @@ -700,9 +696,9 @@ static int uart_fill_fifo(uart_port_t uart_num, char* buffer, uint32_t len) int uart_tx_chars(uart_port_t uart_num, char* buffer, uint32_t len) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); - UART_CHECK(buffer, "buffer null"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1)); + UART_CHECK(buffer, "buffer null", (-1)); if(len == 0) { return 0; } @@ -714,9 +710,6 @@ int uart_tx_chars(uart_port_t uart_num, char* buffer, uint32_t len) static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool brk_en, int brk_len) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); - UART_CHECK(src, "buffer null"); if(size == 0) { return 0; } @@ -746,25 +739,28 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((p_uart_obj[uart_num] != NULL), "uart driver error"); - UART_CHECK(src, "buffer null"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); + UART_CHECK((p_uart_obj[uart_num] != NULL), "uart driver error", (-1)); + UART_CHECK(src, "buffer null", (-1)); //Push data to TX ring buffer and return, ISR will send the data. if(p_uart_obj[uart_num]->tx_buf_size > 0) { - if(xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf) > (size + sizeof(uart_event_t))) { - uart_event_t evt; - xSemaphoreTake(p_uart_obj[uart_num]->tx_buffer_mux, (portTickType)portMAX_DELAY); - evt.type = UART_DATA; - evt.data.size = size; - xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_event_t), portMAX_DELAY); - xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) src, size, portMAX_DELAY); - xSemaphoreGive(p_uart_obj[uart_num]->tx_buffer_mux); - uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); - return size; - } else { - ESP_LOGW(UART_TAG, "UART TX BUFFER TOO SMALL[0], SEND DIRECTLY\n"); - return uart_tx_all(uart_num, src, size, 0, 0); + xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); + int max_size = xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf); + int ori_size = size; + int offset = 0; + uart_event_t evt; + evt.type = UART_DATA; + evt.data.size = size; + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_event_t), portMAX_DELAY); + while(size > 0) { + int send_size = size > max_size / 2 ? max_size / 2 : size; + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) (src + offset), send_size, portMAX_DELAY); + size -= send_size; + offset += send_size; } + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); + return ori_size; } else { //Send data without TX ring buffer, the task will block until all data have been sent out return uart_tx_all(uart_num, src, size, 0, 0); @@ -773,28 +769,31 @@ int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size) int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); - UART_CHECK((size > 0), "uart size error"); - UART_CHECK((src), "uart data null"); - UART_CHECK((brk_len > 0 && brk_len < 256), "break_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1)); + UART_CHECK((size > 0), "uart size error", (-1)); + UART_CHECK((src), "uart data null", (-1)); + UART_CHECK((brk_len > 0 && brk_len < 256), "break_num error", (-1)); //Push data to TX ring buffer and return, ISR will send the data. if(p_uart_obj[uart_num]->tx_buf_size > 0) { - if(xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf) > (size)) { - uart_event_t evt; - xSemaphoreTake(p_uart_obj[uart_num]->tx_buffer_mux, (portTickType)portMAX_DELAY); - evt.type = UART_DATA_BREAK; - evt.data.size = size; - evt.data.brk_len = brk_len; - xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_event_t), portMAX_DELAY); - xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) src, size, portMAX_DELAY); - xSemaphoreGive(p_uart_obj[uart_num]->tx_buffer_mux); - uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); - return size; - } else { - ESP_LOGW(UART_TAG, "UART TX BUFFER TOO SMALL[1], SEND DIRECTLY\n"); - return uart_tx_all(uart_num, src, size, 1, brk_len); + xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); + int max_size = xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf); + int ori_size = size; + int offset = 0; + uart_event_t evt; + evt.type = UART_DATA_BREAK; + evt.data.size = size; + evt.data.brk_len = brk_len; + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_event_t), portMAX_DELAY); + while(size > 0) { + int send_size = size > max_size / 2 ? max_size / 2 : size; + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) (src + offset), send_size, portMAX_DELAY); + size -= send_size; + offset += send_size; } + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); + return ori_size; } else { //Send data without TX ring buffer, the task will block until all data have been sent out return uart_tx_all(uart_num, src, size, 1, brk_len); @@ -803,8 +802,8 @@ int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t s int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1)); uint8_t* data; size_t size; int val; @@ -845,9 +844,9 @@ int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait) int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((buf), "uart_num error"); - UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); + UART_CHECK((buf), "uart_num error", (-1)); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1)); uint8_t* data = NULL; size_t size; size_t copy_len = 0; @@ -896,13 +895,15 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp esp_err_t uart_flush(uart_port_t uart_num) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((p_uart_obj[uart_num]), "uart driver error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); + UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_FAIL); uart_obj_t* p_uart = p_uart_obj[uart_num]; uint8_t* data; size_t size; + //rx sem protect the ring buffer read related functions xSemaphoreTake(p_uart->rx_mux, (portTickType)portMAX_DELAY); + ESP_INTR_DISABLE(p_uart->intr_num); while(true) { if(p_uart->rx_head_ptr) { vRingbufferReturnItem(p_uart->rx_ring_buf, p_uart->rx_head_ptr); @@ -919,11 +920,16 @@ esp_err_t uart_flush(uart_port_t uart_num) p_uart->rx_ptr = NULL; p_uart->rx_cur_remain = 0; p_uart->rx_head_ptr = NULL; + ESP_INTR_ENABLE(p_uart->intr_num); xSemaphoreGive(p_uart->rx_mux); - xSemaphoreTake(p_uart->tx_mux, (portTickType)portMAX_DELAY); if(p_uart->tx_buf_size > 0) { - xSemaphoreTake(p_uart->tx_buffer_mux, (portTickType)portMAX_DELAY); + xSemaphoreTake(p_uart->tx_mux, (portTickType)portMAX_DELAY); + ESP_INTR_DISABLE(p_uart->intr_num); + UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); + UART[uart_num]->int_ena.txfifo_empty = 0; + UART[uart_num]->int_clr.txfifo_empty = 1; + UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); do { data = (uint8_t*) xRingbufferReceive(p_uart->tx_ring_buf, &size, (portTickType) 0); if(data == NULL) { @@ -931,10 +937,17 @@ esp_err_t uart_flush(uart_port_t uart_num) } vRingbufferReturnItem(p_uart->rx_ring_buf, data); } while(1); - xSemaphoreGive(p_uart->tx_buffer_mux); + p_uart->tx_brk_flg = 0; + p_uart->tx_brk_len = 0; + p_uart->tx_head = NULL; + p_uart->tx_len_cur = 0; + p_uart->tx_len_tot = 0; + p_uart->tx_ptr = NULL; + p_uart->tx_waiting_brk = 0; + p_uart->tx_waiting_fifo = false; + ESP_INTR_ENABLE(p_uart->intr_num); + xSemaphoreGive(p_uart->tx_mux); } - xSemaphoreGive(p_uart->tx_mux); - uart_wait_tx_done(uart_num, portMAX_DELAY); uart_reset_fifo(uart_num); return ESP_OK; } @@ -966,8 +979,8 @@ static void uart_ignore_char(char chr) //Only effective to ets_printf function, not ESP_LOGX macro. esp_err_t uart_set_print_port(uart_port_t uart_num) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((p_uart_obj[uart_num]), "UART driver error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); + UART_CHECK((p_uart_obj[uart_num]), "UART driver error", ESP_FAIL); s_uart_print_nport = uart_num; switch(s_uart_print_nport) { case UART_NUM_0: @@ -994,8 +1007,8 @@ int uart_get_print_port() esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); - UART_CHECK((rx_buffer_size > 0), "uart rx buffer length error\n"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); + UART_CHECK((rx_buffer_size > 0), "uart rx buffer length error\n", ESP_FAIL); if(p_uart_obj[uart_num] == NULL) { ESP_INTR_DISABLE(uart_intr_num); p_uart_obj[uart_num] = (uart_obj_t*) malloc(sizeof(uart_obj_t)); @@ -1033,13 +1046,11 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b p_uart_obj[uart_num]->rx_head_ptr = NULL; p_uart_obj[uart_num]->rx_ring_buf = xRingbufferCreate(rx_buffer_size, RINGBUF_TYPE_BYTEBUF); if(tx_buffer_size > 0) { - p_uart_obj[uart_num]->tx_ring_buf = xRingbufferCreate(tx_buffer_size, RINGBUF_TYPE_NOSPLIT);//RINGBUF_TYPE_BYTEBUF);//RINGBUF_TYPE_NOSPLIT); + p_uart_obj[uart_num]->tx_ring_buf = xRingbufferCreate(tx_buffer_size, RINGBUF_TYPE_NOSPLIT); p_uart_obj[uart_num]->tx_buf_size = tx_buffer_size; - p_uart_obj[uart_num]->tx_buffer_mux = xSemaphoreCreateMutex(); } else { p_uart_obj[uart_num]->tx_ring_buf = NULL; p_uart_obj[uart_num]->tx_buf_size = 0; - p_uart_obj[uart_num]->tx_buffer_mux = NULL; } } else { ESP_LOGE(UART_TAG, "UART driver already installed\n"); @@ -1064,7 +1075,7 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b //Make sure no other tasks are still using UART before you call this function esp_err_t uart_driver_delete(uart_port_t uart_num) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error"); + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); if(p_uart_obj[uart_num] == NULL) { ESP_LOGI(UART_TAG, "ALREADY NULL\n"); return ESP_OK; @@ -1090,10 +1101,6 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) vSemaphoreDelete(p_uart_obj[uart_num]->tx_mux); p_uart_obj[uart_num]->tx_mux = NULL; } - if(p_uart_obj[uart_num]->tx_buffer_mux) { - vSemaphoreDelete(p_uart_obj[uart_num]->tx_buffer_mux); - p_uart_obj[uart_num]->tx_buffer_mux = NULL; - } if(p_uart_obj[uart_num]->rx_mux) { vSemaphoreDelete(p_uart_obj[uart_num]->rx_mux); p_uart_obj[uart_num]->rx_mux = NULL; From 3ec23f1b837959548da8e7ddec4dfd7db7929a6c Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Fri, 4 Nov 2016 12:52:34 +0800 Subject: [PATCH 10/12] Modify as Angus's suggestion: 1. Set XXX_TAG static, remove extern XXX_TAG in uart.h/ledc.h/gpio.h 2. I removed uart_set/get_print_port() functions, these functions are not well tested, I removed them for now. 3. Modify some function names for uart_read/write_bytes 4. Modify uart_write_bytes and uart_write_bytes_with_break. --- components/driver/gpio.c | 2 +- components/driver/include/driver/gpio.h | 2 +- components/driver/include/driver/ledc.h | 1 - components/driver/include/driver/uart.h | 98 ++++------ components/driver/ledc.c | 2 +- components/driver/uart.c | 238 ++++++------------------ 6 files changed, 96 insertions(+), 247 deletions(-) diff --git a/components/driver/gpio.c b/components/driver/gpio.c index da0fedb89..62a0e7faa 100644 --- a/components/driver/gpio.c +++ b/components/driver/gpio.c @@ -20,7 +20,7 @@ #include "soc/soc.h" #include "esp_log.h" -const char* GPIO_TAG = "GPIO"; +static const char* GPIO_TAG = "GPIO"; #define GPIO_CHECK(a, str, ret_val) if (!(a)) { \ ESP_LOGE(GPIO_TAG,"%s:%d (%s):%s\n", __FILE__, __LINE__, __FUNCTION__, str); \ return (ret_val); \ diff --git a/components/driver/include/driver/gpio.h b/components/driver/include/driver/gpio.h index a31c2f64b..903621f61 100644 --- a/components/driver/include/driver/gpio.h +++ b/components/driver/include/driver/gpio.h @@ -27,7 +27,7 @@ #ifdef __cplusplus extern "C" { #endif -extern const char* GPIO_TAG; + #define GPIO_SEL_0 (BIT(0)) /*!< Pin 0 selected */ #define GPIO_SEL_1 (BIT(1)) /*!< Pin 1 selected */ #define GPIO_SEL_2 (BIT(2)) /*!< Pin 2 selected */ diff --git a/components/driver/include/driver/ledc.h b/components/driver/include/driver/ledc.h index ac29eaf56..3ab0ebff1 100644 --- a/components/driver/include/driver/ledc.h +++ b/components/driver/include/driver/ledc.h @@ -26,7 +26,6 @@ extern "C" { #endif -extern const char* LEDC_TAG; #define LEDC_APB_CLK_HZ (APB_CLK_FREQ) #define LEDC_REF_CLK_HZ (1*1000000) diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index 200d1148c..ba487d57d 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -32,11 +32,11 @@ extern "C" { #include "freertos/ringbuf.h" #include -extern const char* UART_TAG; -#define UART_FIFO_LEN (128) //Do not change this, this value describes the length of the gardware FIFO in the ESP32 +#define UART_FIFO_LEN (128) /*< Length of the hardware FIFO buffers */ #define UART_INTR_MASK 0x1ff #define UART_LINE_INV_MASK (0x3f << 19) #define UART_BITRATE_MAX 5000000 +#define UART_PIN_NO_CHANGE (-1) typedef enum { UART_DATA_5_BITS = 0x0, /*!< word length: 5bits*/ @@ -243,6 +243,8 @@ esp_err_t uart_set_line_inverse(uart_port_t uart_no, uint32_t inverse_mask) ; * * @param rx_thresh Threshold of Hardware RX flow control(0 ~ UART_FIFO_LEN) * + * Only when UART_HW_FLOWCTRL_RTS is set , will the rx_thresh value be set. + * * @return * - ESP_OK Success * - ESP_FAIL Parameter error @@ -380,15 +382,19 @@ esp_err_t uart_isr_register(uart_port_t uart_num, uint8_t uart_intr_num, void (* /** * @brief Set UART pin number * + * @note + * Internal signal can be output to multiple GPIO pads + * Only one GPIO pad can connect with input signal + * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param tx_io_num UART TX pin GPIO number + * @param tx_io_num UART TX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. * - * @param rx_io_num UART RX pin GPIO number + * @param rx_io_num UART RX pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. * - * @param rts_io_num UART RTS pin GPIO number + * @param rts_io_num UART RTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. * - * @param cts_io_num UART CTS pin GPIO number + * @param cts_io_num UART CTS pin GPIO number, if set to UART_PIN_NO_CHANGE, use the current pin. * * @return * - ESP_OK Success @@ -434,20 +440,20 @@ esp_err_t uart_set_dtr(uart_port_t uart_num, int level); * - ESP_OK Success * - ESP_FAIL Parameter error */ -esp_err_t uart_param_config(uart_port_t uart_num, uart_config_t *uart_config); +esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config); /** * @brief UART interrupt configure * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * - * @param p_intr_conf UART interrupt settings + * @param intr_conf UART interrupt settings * * @return * - ESP_OK Success * - ESP_FAIL Parameter error */ -esp_err_t uart_intr_config(uart_port_t uart_num, uart_intr_config_t *p_intr_conf); +esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_conf); /** * @brief Install UART driver. @@ -504,6 +510,9 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait); /** * @brief Send data to the UART port from a given buffer and length, * This function will not wait for the space in TX FIFO, just fill the TX FIFO and return when the FIFO is full. + * @note + * This function should only be used when UART TX buffer is not enabled. + * * * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 * @@ -515,7 +524,7 @@ esp_err_t uart_wait_tx_done(uart_port_t uart_num, TickType_t ticks_to_wait); * - (-1) Parameter error * - OTHERS(>=0) The number of data that pushed to the TX FIFO */ -int uart_tx_chars(uart_port_t uart_no, char* buffer, uint32_t len); +int uart_tx_chars(uart_port_t uart_no, const char* buffer, uint32_t len); /** * @brief Send data to the UART port from a given buffer and length, @@ -536,7 +545,7 @@ int uart_tx_chars(uart_port_t uart_no, char* buffer, uint32_t len); * - (-1) Parameter error * - OTHERS(>=0) The number of data that pushed to the TX FIFO */ -int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size); +int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size); /** * @brief Send data to the UART port from a given buffer and length, @@ -564,20 +573,7 @@ int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size); * - OTHERS(>=0) The number of data that pushed to the TX FIFO */ -int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len); - -/** -* @brief UART read one char - * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * - * @param ticks_to_wait Timeout, count in RTOS ticks - * - * @return - * - (-1) Error - * - Others return a char data from UART. - */ -int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait); +int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len); /** * @brief UART read bytes from UART buffer @@ -608,25 +604,6 @@ int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickTyp */ esp_err_t uart_flush(uart_port_t uart_num); -/** - * @brief Set the serial output port for ets_printf function, not effective for ESP_LOGX macro. - * - * @param uart_no UART_NUM_0, UART_NUM_1 or UART_NUM_2 - * - * @return - * - ESP_OK Success - * - ESP_FAIL Parameter error, or UART driver not installed. - */ -esp_err_t uart_set_print_port(uart_port_t uart_no); - -/** - * @brief Get the current serial port for ets_printf function - * - * - * @return current print port(0: UART0; 1: UART1; 2: UART2) - */ -int uart_get_print_port(void); - /***************************EXAMPLE********************************** * * @@ -658,7 +635,7 @@ int uart_get_print_port(void); * @code{c} * //2. Set UART pin * //set UART pin, not needed if use default pins. - * uart_set_pin(uart_num, -1, -1, 15, 13); + * uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, 15, 13); * @endcode *-----------------------------------------------------------------------------* * @code{c} @@ -671,12 +648,12 @@ int uart_get_print_port(void); * @code{c} * //4. Write data to UART. * char* test_str = "This is a test string.\n" - * uart_tx_all_chars(uart_num, (const char*)test_str, strlen(test_str)); + * uart_write_bytes(uart_num, (const char*)test_str, strlen(test_str)); * @endcode *-----------------------------------------------------------------------------* * @code{c} * //5. Write data to UART, end with a break signal. - * uart_tx_all_chars_with_break(0, "test break\n",strlen("test break\n"), 100); + * uart_write_bytes_with_break(0, "test break\n",strlen("test break\n"), 100); * @endcode *-----------------------------------------------------------------------------* * @code{c} @@ -696,8 +673,6 @@ int uart_get_print_port(void); * uart_param_config(uart_num, &uart_config); * //Set UART1 pins(TX: IO16, RX: IO17, RTS: IO18, CTS: IO19) * uart_set_pin(uart_num, 16, 17, 18, 19); - * //Set UART log level - * esp_log_level_set(UART_TAG, ESP_LOG_ERROR); * //Install UART driver( We don't need an event queue here) * uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, 17, NULL, RINGBUF_TYPE_BYTEBUF); * uint8_t data[1000]; @@ -705,7 +680,7 @@ int uart_get_print_port(void); * //Read data from UART * int len = uart_read_bytes(uart_num, data, sizeof(data), 10); * //Write data back to UART - * uart_tx_all_chars(uart_num, (const char*)data, len); + * uart_write_bytes(uart_num, (const char*)data, len); * } * } * @endcode @@ -715,6 +690,7 @@ int uart_get_print_port(void); * #include "freertos/queue.h" * //A queue to handle UART event. * QueueHandle_t uart0_queue; + * static const char *TAG = "uart_example"; * void uart_task(void *pvParameters) * { * int uart_num = (int)pvParameters; @@ -723,37 +699,37 @@ int uart_get_print_port(void); * for(;;) { * //Waiting for UART event. * if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) { - * ESP_LOGI(UART_TAG, "uart[%d] event:", uart_num); + * ESP_LOGI(TAG, "uart[%d] event:", uart_num); * switch(event.type) { * //Event of UART receving data * case UART_DATA: - * ESP_LOGI(UART_TAG,"data, len: %d\n", event.data.size); + * ESP_LOGI(TAG,"data, len: %d\n", event.data.size); * int len = uart_read_bytes(uart_num, dtmp, event.data.size, 10); - * ESP_LOGI(UART_TAG, "uart read: %d\n", len); + * ESP_LOGI(TAG, "uart read: %d\n", len); * break; * //Event of HW FIFO overflow detected * case UART_FIFO_OVF: - * ESP_LOGI(UART_TAG, "hw fifo overflow\n"); + * ESP_LOGI(TAG, "hw fifo overflow\n"); * break; * //Event of UART ring buffer full * case UART_BUFFER_FULL: - * ESP_LOGI(UART_TAG, "ring buffer full\n"); + * ESP_LOGI(TAG, "ring buffer full\n"); * break; * //Event of UART RX break detected * case UART_BREAK: - * ESP_LOGI(UART_TAG, "uart rx break\n"); + * ESP_LOGI(TAG, "uart rx break\n"); * break; * //Event of UART parity check error * case UART_PARITY_ERR: - * ESP_LOGI(UART_TAG, "uart parity error\n"); + * ESP_LOGI(TAG, "uart parity error\n"); * break; * //Event of UART frame error * case UART_FRAME_ERR: - * ESP_LOGI(UART_TAG, "uart frame error\n"); + * ESP_LOGI(TAG, "uart frame error\n"); * break; * //Others * default: - * ESP_LOGI(UART_TAG, "uart event type: %d\n", event.type); + * ESP_LOGI(TAG, "uart event type: %d\n", event.type); * break; * } * } @@ -775,9 +751,9 @@ int uart_get_print_port(void); * //Set UART parameters * uart_param_config(uart_num, &uart_config); * //Set UART pins,(-1: default pin, no change.) - * uart_set_pin(uart_num, -1, -1, 15, 13); + * uart_set_pin(uart_num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, 15, 13); * //Set UART log level - * esp_log_level_set(UART_TAG, ESP_LOG_INFO); + * esp_log_level_set(TAG, ESP_LOG_INFO); * //Install UART driver, and get the queue. * uart_driver_install(uart_num, 1024 * 2, 1024*4, 10, 17, &uart0_queue, RINGBUF_TYPE_BYTEBUF); * //Create a task to handler UART event from ISR diff --git a/components/driver/ledc.c b/components/driver/ledc.c index 771c4a17d..b9039cf62 100644 --- a/components/driver/ledc.c +++ b/components/driver/ledc.c @@ -20,7 +20,7 @@ #include "driver/ledc.h" #include "esp_log.h" -const char* LEDC_TAG = "LEDC"; +static const char* LEDC_TAG = "LEDC"; static portMUX_TYPE ledc_spinlock = portMUX_INITIALIZER_UNLOCKED; #define LEDC_CHECK(a, str, ret_val) if (!(a)) { \ ESP_LOGE(LEDC_TAG,"%s:%d (%s):%s\n", __FILE__, __LINE__, __FUNCTION__, str); \ diff --git a/components/driver/uart.c b/components/driver/uart.c index cab05dd0b..a3e0b92b2 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -29,7 +29,7 @@ #include "driver/gpio.h" #include "soc/uart_struct.h" -const char* UART_TAG = "UART"; +static const char* UART_TAG = "UART"; #define UART_CHECK(a, str, ret) if (!(a)) { \ ESP_LOGE(UART_TAG,"%s:%d (%s):%s\n", __FILE__, __LINE__, __FUNCTION__, str); \ return (ret); \ @@ -249,28 +249,19 @@ esp_err_t uart_disable_intr_mask(uart_port_t uart_num, uint32_t disable_mask) esp_err_t uart_enable_rx_intr(uart_port_t uart_num) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); - UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); - SET_PERI_REG_MASK(UART_INT_ENA_REG(uart_num), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA); - UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + uart_enable_intr_mask(uart_num, UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA); return ESP_OK; } esp_err_t uart_disable_rx_intr(uart_port_t uart_num) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); - UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); - CLEAR_PERI_REG_MASK(UART_INT_ENA_REG(uart_num), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA); - UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + uart_disable_intr_mask(uart_num, UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA); return ESP_OK; } esp_err_t uart_disable_tx_intr(uart_port_t uart_num) { - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); - UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); - UART[uart_num]->int_ena.txfifo_empty = 0; - UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); + uart_disable_intr_mask(uart_num, UART_TXFIFO_EMPTY_INT_ENA); return ESP_OK; } @@ -391,7 +382,7 @@ esp_err_t uart_set_dtr(uart_port_t uart_num, int level) return ESP_OK; } -esp_err_t uart_param_config(uart_port_t uart_num, uart_config_t *uart_config) +esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); UART_CHECK((uart_config), "param null\n", ESP_FAIL); @@ -413,25 +404,25 @@ esp_err_t uart_param_config(uart_port_t uart_num, uart_config_t *uart_config) return ESP_OK; } -esp_err_t uart_intr_config(uart_port_t uart_num, uart_intr_config_t *p_intr_conf) +esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_conf) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); - UART_CHECK((p_intr_conf), "param null\n", ESP_FAIL); + UART_CHECK((intr_conf), "param null\n", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); UART[uart_num]->int_clr.val = UART_INTR_MASK; - if(p_intr_conf->intr_enable_mask & UART_RXFIFO_TOUT_INT_ENA_M) { - UART[uart_num]->conf1.rx_tout_thrhd = ((p_intr_conf->rx_timeout_thresh) & UART_RX_TOUT_THRHD_V); + if(intr_conf->intr_enable_mask & UART_RXFIFO_TOUT_INT_ENA_M) { + UART[uart_num]->conf1.rx_tout_thrhd = ((intr_conf->rx_timeout_thresh) & UART_RX_TOUT_THRHD_V); UART[uart_num]->conf1.rx_tout_en = 1; } else { UART[uart_num]->conf1.rx_tout_en = 0; } - if(p_intr_conf->intr_enable_mask & UART_RXFIFO_FULL_INT_ENA_M) { - UART[uart_num]->conf1.rxfifo_full_thrhd = p_intr_conf->rxfifo_full_thresh; + if(intr_conf->intr_enable_mask & UART_RXFIFO_FULL_INT_ENA_M) { + UART[uart_num]->conf1.rxfifo_full_thrhd = intr_conf->rxfifo_full_thresh; } - if(p_intr_conf->intr_enable_mask & UART_TXFIFO_EMPTY_INT_ENA_M) { - UART[uart_num]->conf1.txfifo_empty_thrhd = p_intr_conf->txfifo_empty_intr_thresh; + if(intr_conf->intr_enable_mask & UART_TXFIFO_EMPTY_INT_ENA_M) { + UART[uart_num]->conf1.txfifo_empty_thrhd = intr_conf->txfifo_empty_intr_thresh; } - UART[uart_num]->int_ena.val = p_intr_conf->intr_enable_mask; + UART[uart_num]->int_ena.val = intr_conf->intr_enable_mask; UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); return ESP_FAIL; } @@ -459,8 +450,8 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) if(p_uart->tx_waiting_brk) { return; } - //TX semaphore used in none tx ringbuffer mode. - if(p_uart->tx_waiting_fifo == true && p_uart->tx_buf_size > 0) { + //TX semaphore will only be used when tx_buf_size is zero. + if(p_uart->tx_waiting_fifo == true && p_uart->tx_buf_size == 0) { p_uart->tx_waiting_fifo = false; xSemaphoreGiveFromISR(p_uart->tx_fifo_sem, NULL); } @@ -682,7 +673,7 @@ static esp_err_t uart_set_break(uart_port_t uart_num, int break_num) //Fill UART tx_fifo and return a number, //This function by itself is not thread-safe, always call from within a muxed section. -static int uart_fill_fifo(uart_port_t uart_num, char* buffer, uint32_t len) +static int uart_fill_fifo(uart_port_t uart_num, const char* buffer, uint32_t len) { uint8_t i = 0; uint8_t tx_fifo_cnt = UART[uart_num]->status.txfifo_cnt; @@ -694,7 +685,7 @@ static int uart_fill_fifo(uart_port_t uart_num, char* buffer, uint32_t len) return copy_cnt; } -int uart_tx_chars(uart_port_t uart_num, char* buffer, uint32_t len) +int uart_tx_chars(uart_port_t uart_num, const char* buffer, uint32_t len) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1)); @@ -703,7 +694,7 @@ int uart_tx_chars(uart_port_t uart_num, char* buffer, uint32_t len) return 0; } xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); - int tx_len = uart_fill_fifo(uart_num, buffer, len); + int tx_len = uart_fill_fifo(uart_num, (const char*) buffer, len); xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); return tx_len; } @@ -713,44 +704,21 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool if(size == 0) { return 0; } + size_t original_size = size; + //lock for uart_tx xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); - size_t original_size = size; - while(size) { - //semaphore for tx_fifo available - if(pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) { - size_t sent = uart_fill_fifo(uart_num, (char*) src, size); - if(sent < size) { - p_uart_obj[uart_num]->tx_waiting_fifo = true; - uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); - } - size -= sent; - src += sent; - } - } - if(brk_en) { - uart_set_break(uart_num, brk_len); - xSemaphoreTake(p_uart_obj[uart_num]->tx_brk_sem, (portTickType)portMAX_DELAY); - } - xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); - xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); - return original_size; -} - -int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size) -{ - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); - UART_CHECK((p_uart_obj[uart_num] != NULL), "uart driver error", (-1)); - UART_CHECK(src, "buffer null", (-1)); - //Push data to TX ring buffer and return, ISR will send the data. if(p_uart_obj[uart_num]->tx_buf_size > 0) { - xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); int max_size = xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf); - int ori_size = size; int offset = 0; uart_event_t evt; - evt.type = UART_DATA; evt.data.size = size; + evt.data.brk_len = brk_len; + if(brk_en) { + evt.type = UART_DATA_BREAK; + } else { + evt.type = UART_DATA; + } xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_event_t), portMAX_DELAY); while(size > 0) { int send_size = size > max_size / 2 ? max_size / 2 : size; @@ -760,86 +728,45 @@ int uart_tx_all_chars(uart_port_t uart_num, const char* src, size_t size) } xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); - return ori_size; } else { - //Send data without TX ring buffer, the task will block until all data have been sent out - return uart_tx_all(uart_num, src, size, 0, 0); + while(size) { + //semaphore for tx_fifo available + if(pdTRUE == xSemaphoreTake(p_uart_obj[uart_num]->tx_fifo_sem, (portTickType)portMAX_DELAY)) { + size_t sent = uart_fill_fifo(uart_num, (char*) src, size); + if(sent < size) { + p_uart_obj[uart_num]->tx_waiting_fifo = true; + uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); + } + size -= sent; + src += sent; + } + } + if(brk_en) { + uart_set_break(uart_num, brk_len); + xSemaphoreTake(p_uart_obj[uart_num]->tx_brk_sem, (portTickType)portMAX_DELAY); + } + xSemaphoreGive(p_uart_obj[uart_num]->tx_fifo_sem); } + xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); + return original_size; } -int uart_tx_all_chars_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len) +int uart_write_bytes(uart_port_t uart_num, const char* src, size_t size) +{ + UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); + UART_CHECK((p_uart_obj[uart_num] != NULL), "uart driver error", (-1)); + UART_CHECK(src, "buffer null", (-1)); + return uart_tx_all(uart_num, src, size, 0, 0); +} + +int uart_write_bytes_with_break(uart_port_t uart_num, const char* src, size_t size, int brk_len) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1)); UART_CHECK((size > 0), "uart size error", (-1)); UART_CHECK((src), "uart data null", (-1)); UART_CHECK((brk_len > 0 && brk_len < 256), "break_num error", (-1)); - //Push data to TX ring buffer and return, ISR will send the data. - if(p_uart_obj[uart_num]->tx_buf_size > 0) { - xSemaphoreTake(p_uart_obj[uart_num]->tx_mux, (portTickType)portMAX_DELAY); - int max_size = xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf); - int ori_size = size; - int offset = 0; - uart_event_t evt; - evt.type = UART_DATA_BREAK; - evt.data.size = size; - evt.data.brk_len = brk_len; - xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_event_t), portMAX_DELAY); - while(size > 0) { - int send_size = size > max_size / 2 ? max_size / 2 : size; - xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) (src + offset), send_size, portMAX_DELAY); - size -= send_size; - offset += send_size; - } - xSemaphoreGive(p_uart_obj[uart_num]->tx_mux); - uart_enable_tx_intr(uart_num, 1, UART_EMPTY_THRESH_DEFAULT); - return ori_size; - } else { - //Send data without TX ring buffer, the task will block until all data have been sent out - return uart_tx_all(uart_num, src, size, 1, brk_len); - } -} - -int uart_read_char(uart_port_t uart_num, TickType_t ticks_to_wait) -{ - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", (-1)); - UART_CHECK((p_uart_obj[uart_num]), "uart driver error", (-1)); - uint8_t* data; - size_t size; - int val; - portTickType ticks_end = xTaskGetTickCount() + ticks_to_wait; - if(xSemaphoreTake(p_uart_obj[uart_num]->rx_mux,(portTickType)ticks_to_wait) != pdTRUE) { - return -1; - } - if(p_uart_obj[uart_num]->rx_cur_remain == 0) { - ticks_to_wait = ticks_end - xTaskGetTickCount(); - data = (uint8_t*) xRingbufferReceive(p_uart_obj[uart_num]->rx_ring_buf, &size, (portTickType) ticks_to_wait); - if(data) { - p_uart_obj[uart_num]->rx_head_ptr = data; - p_uart_obj[uart_num]->rx_ptr = data; - p_uart_obj[uart_num]->rx_cur_remain = size; - } else { - xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); - return -1; - } - } - val = *(p_uart_obj[uart_num]->rx_ptr); - p_uart_obj[uart_num]->rx_ptr++; - p_uart_obj[uart_num]->rx_cur_remain--; - if(p_uart_obj[uart_num]->rx_cur_remain == 0) { - vRingbufferReturnItem(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_head_ptr); - p_uart_obj[uart_num]->rx_head_ptr = NULL; - p_uart_obj[uart_num]->rx_ptr = NULL; - if(p_uart_obj[uart_num]->rx_buffer_full_flg) { - BaseType_t res = xRingbufferSend(p_uart_obj[uart_num]->rx_ring_buf, p_uart_obj[uart_num]->rx_data_buf, p_uart_obj[uart_num]->rx_stash_len, 1); - if(res == pdTRUE) { - p_uart_obj[uart_num]->rx_buffer_full_flg = false; - uart_enable_rx_intr(p_uart_obj[uart_num]->uart_num); - } - } - } - xSemaphoreGive(p_uart_obj[uart_num]->rx_mux); - return val; + return uart_tx_all(uart_num, src, size, 1, brk_len); } int uart_read_bytes(uart_port_t uart_num, uint8_t* buf, uint32_t length, TickType_t ticks_to_wait) @@ -952,59 +879,6 @@ esp_err_t uart_flush(uart_port_t uart_num) return ESP_OK; } -//----------------------------------- -//Should not enable hw flow control the debug print port. -//Use uart_tx_all_chars() as a thread-safe function to send data. -static int s_uart_print_nport = UART_NUM_0; -static void uart2_write_char(char chr) -{ - uart_tx_all_chars(UART_NUM_2, (const char*)&chr, 1); -} - -static void uart1_write_char(char chr) -{ - uart_tx_all_chars(UART_NUM_1, (const char*)&chr, 1); -} - -static void uart0_write_char(char chr) -{ - uart_tx_all_chars(UART_NUM_0, (const char*)&chr, 1); -} - -static void uart_ignore_char(char chr) -{ - -} - -//Only effective to ets_printf function, not ESP_LOGX macro. -esp_err_t uart_set_print_port(uart_port_t uart_num) -{ - UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); - UART_CHECK((p_uart_obj[uart_num]), "UART driver error", ESP_FAIL); - s_uart_print_nport = uart_num; - switch(s_uart_print_nport) { - case UART_NUM_0: - ets_install_putc1(uart0_write_char); - break; - case UART_NUM_1: - ets_install_putc1(uart1_write_char); - break; - case UART_NUM_2: - ets_install_putc1(uart2_write_char); - break; - case UART_NUM_MAX: - default: - ets_install_putc1(uart_ignore_char); - break; - } - return ESP_OK; -} - -int uart_get_print_port() -{ - return s_uart_print_nport; -} - esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); From e452278194ff16696519444fb9132b3ffa143dc0 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Mon, 7 Nov 2016 14:16:52 +0800 Subject: [PATCH 11/12] Minor changes for driver 1. remove "\n" when calling ESP_LOGX APIs. 2. modify uart_event_t for uart rx data. 3. use MICRO for uart inverse value 4. add uart_tx_data_t for internal tx function. --- components/driver/gpio.c | 59 ++++++++++--------- components/driver/include/driver/uart.h | 39 +++++-------- components/driver/ledc.c | 78 ++++++++++++------------- components/driver/uart.c | 48 +++++++++------ 4 files changed, 114 insertions(+), 110 deletions(-) diff --git a/components/driver/gpio.c b/components/driver/gpio.c index 62a0e7faa..b445d3df0 100644 --- a/components/driver/gpio.c +++ b/components/driver/gpio.c @@ -22,7 +22,7 @@ static const char* GPIO_TAG = "GPIO"; #define GPIO_CHECK(a, str, ret_val) if (!(a)) { \ - ESP_LOGE(GPIO_TAG,"%s:%d (%s):%s\n", __FILE__, __LINE__, __FUNCTION__, str); \ + ESP_LOGE(GPIO_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \ return (ret_val); \ } @@ -71,15 +71,15 @@ const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT] = { esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type) { - GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); - GPIO_CHECK(intr_type < GPIO_INTR_MAX, "GPIO interrupt type error\n", ESP_ERR_INVALID_ARG); + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); + GPIO_CHECK(intr_type < GPIO_INTR_MAX, "GPIO interrupt type error", ESP_ERR_INVALID_ARG); GPIO.pin[gpio_num].int_type = intr_type; return ESP_OK; } esp_err_t gpio_intr_enable(gpio_num_t gpio_num) { - GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); if(xPortGetCoreID() == 0) { GPIO.pin[gpio_num].int_ena = GPIO_PRO_CPU_INTR_ENA; //enable pro cpu intr } else { @@ -90,14 +90,14 @@ esp_err_t gpio_intr_enable(gpio_num_t gpio_num) esp_err_t gpio_intr_disable(gpio_num_t gpio_num) { - GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); GPIO.pin[gpio_num].int_ena = 0; //disable GPIO intr return ESP_OK; } static esp_err_t gpio_output_disable(gpio_num_t gpio_num) { - GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); if(gpio_num < 32) { GPIO.enable_w1tc = (0x1 << gpio_num); } else { @@ -108,7 +108,7 @@ static esp_err_t gpio_output_disable(gpio_num_t gpio_num) static esp_err_t gpio_output_enable(gpio_num_t gpio_num) { - GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO output gpio_num error\n", ESP_ERR_INVALID_ARG); + GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO output gpio_num error", ESP_ERR_INVALID_ARG); if(gpio_num < 32) { GPIO.enable_w1ts = (0x1 << gpio_num); } else { @@ -119,7 +119,7 @@ static esp_err_t gpio_output_enable(gpio_num_t gpio_num) esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level) { - GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); if(level) { if(gpio_num < 32) { GPIO.out_w1ts = (1 << gpio_num); @@ -147,8 +147,8 @@ int gpio_get_level(gpio_num_t gpio_num) esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull) { - GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); - GPIO_CHECK(pull <= GPIO_FLOATING, "GPIO pull mode error\n", ESP_ERR_INVALID_ARG); + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); + GPIO_CHECK(pull <= GPIO_FLOATING, "GPIO pull mode error", ESP_ERR_INVALID_ARG); esp_err_t ret = ESP_OK; switch(pull) { case GPIO_PULLUP_ONLY: @@ -168,7 +168,7 @@ esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull) PIN_PULLDWN_DIS(GPIO_PIN_MUX_REG[gpio_num]); break; default: - ESP_LOGE(GPIO_TAG, "Unknown pull up/down mode,gpio_num=%u,pull=%u\n",gpio_num,pull); + ESP_LOGE(GPIO_TAG, "Unknown pull up/down mode,gpio_num=%u,pull=%u",gpio_num,pull); ret = ESP_ERR_INVALID_ARG; break; } @@ -177,9 +177,9 @@ esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull) esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode) { - GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); if(gpio_num >= 34 && (mode & (GPIO_MODE_DEF_OUTPUT))) { - ESP_LOGE(GPIO_TAG, "io_num=%d can only be input\n",gpio_num); + ESP_LOGE(GPIO_TAG, "io_num=%d can only be input",gpio_num); return ESP_ERR_INVALID_ARG; } esp_err_t ret = ESP_OK; @@ -214,53 +214,56 @@ esp_err_t gpio_config(gpio_config_t *pGPIOConfig) uint64_t gpio_pin_mask = (pGPIOConfig->pin_bit_mask); uint32_t io_reg = 0; uint32_t io_num = 0; - uint64_t bit_valid = 0; + uint8_t input_en = 0; + uint8_t output_en = 0; + uint8_t od_en = 0; + uint8_t pu_en = 0; + uint8_t pd_en = 0; if(pGPIOConfig->pin_bit_mask == 0 || pGPIOConfig->pin_bit_mask >= (((uint64_t) 1) << GPIO_PIN_COUNT)) { - ESP_LOGE(GPIO_TAG, "GPIO_PIN mask error \n"); + ESP_LOGE(GPIO_TAG, "GPIO_PIN mask error "); return ESP_ERR_INVALID_ARG; } if((pGPIOConfig->mode) & (GPIO_MODE_DEF_OUTPUT)) { //GPIO 34/35/36/37/38/39 can only be used as input mode; if((gpio_pin_mask & ( GPIO_SEL_34 | GPIO_SEL_35 | GPIO_SEL_36 | GPIO_SEL_37 | GPIO_SEL_38 | GPIO_SEL_39))) { - ESP_LOGE(GPIO_TAG, "GPIO34-39 can only be used as input mode\n"); + ESP_LOGE(GPIO_TAG, "GPIO34-39 can only be used as input mode"); return ESP_ERR_INVALID_ARG; } } do { io_reg = GPIO_PIN_MUX_REG[io_num]; if(((gpio_pin_mask >> io_num) & BIT(0)) && io_reg) { - ESP_LOGI(GPIO_TAG, "Gpio%02d |Mode:",io_num); if((pGPIOConfig->mode) & GPIO_MODE_DEF_INPUT) { - ESP_LOGI(GPIO_TAG, "INPUT "); + input_en = 1; PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[io_num]); } else { PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[io_num]); } if((pGPIOConfig->mode) & GPIO_MODE_DEF_OD) { - ESP_LOGI(GPIO_TAG, "OD "); + od_en = 1; GPIO.pin[io_num].pad_driver = 1; /*0x01 Open-drain */ } else { GPIO.pin[io_num].pad_driver = 0; /*0x00 Normal gpio output */ } if((pGPIOConfig->mode) & GPIO_MODE_DEF_OUTPUT) { - ESP_LOGI(GPIO_TAG, "OUTPUT "); + output_en = 1; gpio_output_enable(io_num); } else { gpio_output_disable(io_num); } if(pGPIOConfig->pull_up_en) { - ESP_LOGI(GPIO_TAG, "PU "); + pu_en = 1; PIN_PULLUP_EN(io_reg); } else { PIN_PULLUP_DIS(io_reg); } if(pGPIOConfig->pull_down_en) { - ESP_LOGI(GPIO_TAG, "PD "); + pd_en = 1; PIN_PULLDWN_EN(io_reg); } else { PIN_PULLDWN_DIS(io_reg); } - ESP_LOGI(GPIO_TAG, "Intr:%d |\n",pGPIOConfig->intr_type); + ESP_LOGI(GPIO_TAG, "GPIO[%d]| InputEn: %d| OutputEn: %d| OpenDrain: %d| Pullup: %d| Pulldown: %d| Intr:%d ", io_num, input_en, output_en, od_en, pu_en, pd_en, pGPIOConfig->intr_type); gpio_set_intr_type(io_num, pGPIOConfig->intr_type); if(pGPIOConfig->intr_type) { gpio_intr_enable(io_num); @@ -268,8 +271,6 @@ esp_err_t gpio_config(gpio_config_t *pGPIOConfig) gpio_intr_disable(io_num); } PIN_FUNC_SELECT(io_reg, PIN_FUNC_GPIO); /*function number 2 is GPIO_FUNC for each pin */ - } else if(bit_valid && (io_reg == 0)) { - ESP_LOGW(GPIO_TAG, "io_num=%d does not exist\n",io_num); } io_num++; } while(io_num < GPIO_PIN_COUNT); @@ -278,7 +279,7 @@ esp_err_t gpio_config(gpio_config_t *pGPIOConfig) esp_err_t gpio_isr_register(uint32_t gpio_intr_num, void (*fn)(void*), void * arg) { - GPIO_CHECK(fn, "GPIO ISR null\n", ESP_ERR_INVALID_ARG); + GPIO_CHECK(fn, "GPIO ISR null", ESP_ERR_INVALID_ARG); ESP_INTR_DISABLE(gpio_intr_num); intr_matrix_set(xPortGetCoreID(), ETS_GPIO_INTR_SOURCE, gpio_intr_num); xt_set_interrupt_handler(gpio_intr_num, fn, arg); @@ -289,13 +290,13 @@ esp_err_t gpio_isr_register(uint32_t gpio_intr_num, void (*fn)(void*), void * ar /*only level interrupt can be used for wake-up function*/ esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type) { - GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); esp_err_t ret = ESP_OK; if((intr_type == GPIO_INTR_LOW_LEVEL) || (intr_type == GPIO_INTR_HIGH_LEVEL)) { GPIO.pin[gpio_num].int_type = intr_type; GPIO.pin[gpio_num].wakeup_enable = 0x1; } else { - ESP_LOGE(GPIO_TAG, "GPIO wakeup only support Level mode,but edge mode set. gpio_num:%u\n",gpio_num); + ESP_LOGE(GPIO_TAG, "GPIO wakeup only support Level mode,but edge mode set. gpio_num:%u",gpio_num); ret = ESP_ERR_INVALID_ARG; } return ret; @@ -303,7 +304,7 @@ esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type) esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num) { - GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error\n", ESP_ERR_INVALID_ARG); + GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG); GPIO.pin[gpio_num].wakeup_enable = 0; return ESP_OK; } diff --git a/components/driver/include/driver/uart.h b/components/driver/include/driver/uart.h index ba487d57d..7dccf1666 100644 --- a/components/driver/include/driver/uart.h +++ b/components/driver/include/driver/uart.h @@ -38,12 +38,18 @@ extern "C" { #define UART_BITRATE_MAX 5000000 #define UART_PIN_NO_CHANGE (-1) +#define UART_INVERSE_DISABLE (0x0) /*!< Disable UART signal inverse*/ +#define UART_INVERSE_RXD (UART_RXD_INV_M) /*!< UART RXD input inverse*/ +#define UART_INVERSE_CTS (UART_CTS_INV_M) /*!< UART CTS input inverse*/ +#define UART_INVERSE_TXD (UART_TXD_INV_M) /*!< UART TXD output inverse*/ +#define UART_INVERSE_RTS (UART_RTS_INV_M) /*!< UART RTS output inverse*/ + typedef enum { UART_DATA_5_BITS = 0x0, /*!< word length: 5bits*/ UART_DATA_6_BITS = 0x1, /*!< word length: 6bits*/ UART_DATA_7_BITS = 0x2, /*!< word length: 7bits*/ UART_DATA_8_BITS = 0x3, /*!< word length: 8bits*/ - UART_DATA_MAX_BITS = 0X4, + UART_DATA_BITS_MAX = 0X4, } uart_word_length_t; typedef enum { @@ -74,14 +80,6 @@ typedef enum { UART_HW_FLOWCTRL_MAX = 0x4, } uart_hw_flowcontrol_t; -typedef enum { - UART_INVERSE_DISABLE = 0x0, /*!< Disable UART wire output inverse*/ - UART_INVERSE_RXD = (uint32_t)UART_RXD_INV_M, /*!< UART RXD input inverse*/ - UART_INVERSE_CTS = (uint32_t)UART_CTS_INV_M, /*!< UART CTS input inverse*/ - UART_INVERSE_TXD = (uint32_t)UART_TXD_INV_M, /*!< UART TXD output inverse*/ - UART_INVERSE_RTS = (uint32_t)UART_RTS_INV_M, /*!< UART RTS output inverse*/ -} uart_inverse_t; - typedef struct { int baud_rate; /*!< UART baudrate*/ uart_word_length_t data_bits; /*!< UART byte size*/ @@ -110,14 +108,8 @@ typedef enum { } uart_event_type_t; typedef struct { - uart_event_type_t type; - union { - struct { - int brk_len; - size_t size; - uint8_t data[]; - } data; - }; + uart_event_type_t type; /*!< UART event type */ + size_t size; /*!< UART data size for UART_DATA event*/ } uart_event_t; /** @@ -225,14 +217,13 @@ esp_err_t uart_get_baudrate(uart_port_t uart_num, uint32_t* baudrate); * * @param inverse_mask Choose the wires that need to be inversed. * - * (inverse_mask should be chosen from uart_inverse_t, combine with OR-OPERATION) + * (inverse_mask should be chosen from UART_INVERSE_RXD/UART_INVERSE_TXD/UART_INVERSE_RTS/UART_INVERSE_CTS, combine with OR-OPERATION) * * @return * - ESP_OK Success * - ESP_FAIL Parameter error */ -esp_err_t uart_set_line_inverse(uart_port_t uart_no, uint32_t inverse_mask) ; - +esp_err_t uart_set_line_inverse(uart_port_t uart_no, uint32_t inverse_mask); /** * @brief Set hardware flow control. @@ -701,11 +692,13 @@ esp_err_t uart_flush(uart_port_t uart_num); * if(xQueueReceive(uart0_queue, (void * )&event, (portTickType)portMAX_DELAY)) { * ESP_LOGI(TAG, "uart[%d] event:", uart_num); * switch(event.type) { + * memset(dtmp, 0, sizeof(dtmp)); * //Event of UART receving data * case UART_DATA: - * ESP_LOGI(TAG,"data, len: %d\n", event.data.size); - * int len = uart_read_bytes(uart_num, dtmp, event.data.size, 10); - * ESP_LOGI(TAG, "uart read: %d\n", len); + * ESP_LOGI(TAG,"data, len: %d", event.size); + * int len = uart_read_bytes(uart_num, dtmp, event.size, 10); + * ESP_LOGI(TAG, "uart read: %d", len); + uart_write_bytes(uart_num, (const char*)dtmp, len); * break; * //Event of HW FIFO overflow detected * case UART_FIFO_OVF: diff --git a/components/driver/ledc.c b/components/driver/ledc.c index b9039cf62..41eb82cbd 100644 --- a/components/driver/ledc.c +++ b/components/driver/ledc.c @@ -23,14 +23,14 @@ static const char* LEDC_TAG = "LEDC"; static portMUX_TYPE ledc_spinlock = portMUX_INITIALIZER_UNLOCKED; #define LEDC_CHECK(a, str, ret_val) if (!(a)) { \ - ESP_LOGE(LEDC_TAG,"%s:%d (%s):%s\n", __FILE__, __LINE__, __FUNCTION__, str); \ + ESP_LOGE(LEDC_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \ return (ret_val); \ } esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t div_num, uint32_t bit_num, ledc_clk_src_t clk_src) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.div_num = div_num; LEDC.timer_group[speed_mode].timer[timer_sel].conf.tick_sel = clk_src; @@ -58,8 +58,8 @@ static esp_err_t ledc_duty_config(ledc_mode_t speed_mode, uint32_t channel_num, esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint32_t timer_idx) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(timer_idx <= LEDC_TIMER_3, "ledc timer error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(timer_idx <= LEDC_TIMER_3, "ledc timer error", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.channel_group[speed_mode].channel[channel].conf0.timer_sel = timer_idx; portEXIT_CRITICAL(&ledc_spinlock); @@ -68,8 +68,8 @@ esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, uint32_t channel, uint esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.rst = 1; LEDC.timer_group[speed_mode].timer[timer_sel].conf.rst = 0; @@ -79,8 +79,8 @@ esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, uint32_t timer_sel) esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.pause = 1; portEXIT_CRITICAL(&ledc_spinlock); @@ -89,8 +89,8 @@ esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, uint32_t timer_sel) esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(timer_sel <= LEDC_TIMER_3, "ledc timer error", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.timer_group[speed_mode].timer[timer_sel].conf.pause = 0; portEXIT_CRITICAL(&ledc_spinlock); @@ -99,7 +99,7 @@ esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, uint32_t timer_sel) static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, uint32_t channel, ledc_intr_type_t type) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); uint32_t value; uint32_t intr_type = type; portENTER_CRITICAL(&ledc_spinlock); @@ -115,7 +115,7 @@ static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, uint32_t channel, esp_err_t ledc_isr_register(uint32_t ledc_intr_num, void (*fn)(void*), void * arg) { - LEDC_CHECK(fn, "ledc isr null\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(fn, "ledc isr null", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); ESP_INTR_DISABLE(ledc_intr_num); intr_matrix_set(xPortGetCoreID(), ETS_LEDC_INTR_SOURCE, ledc_intr_num); @@ -131,13 +131,13 @@ esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf) int bit_num = timer_conf->bit_num; int timer_num = timer_conf->timer_num; int speed_mode = timer_conf->speed_mode; - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); if(freq_hz == 0 || bit_num == 0 || bit_num > LEDC_TIMER_15_BIT) { - ESP_LOGE(LEDC_TAG, "freq_hz=%u bit_num=%u\n", freq_hz, bit_num); + ESP_LOGE(LEDC_TAG, "freq_hz=%u bit_num=%u", freq_hz, bit_num); return ESP_ERR_INVALID_ARG; } if(timer_num > LEDC_TIMER_3) { - ESP_LOGE(LEDC_TAG, "Time Select %u\n", timer_num); + ESP_LOGE(LEDC_TAG, "Time Select %u", timer_num); return ESP_ERR_INVALID_ARG; } esp_err_t ret = ESP_OK; @@ -149,7 +149,7 @@ esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf) /*Selet the reference tick*/ div_param = ((uint64_t) LEDC_REF_CLK_HZ << 8) / freq_hz / precision; if(div_param <= 256 || div_param > LEDC_DIV_NUM_HSTIMER0_V) { - ESP_LOGE(LEDC_TAG, "div param err,div_param=%u\n", (uint32_t)div_param); + ESP_LOGE(LEDC_TAG, "div param err,div_param=%u", (uint32_t)div_param); ret = ESP_FAIL; } timer_clk_src = LEDC_REF_TICK; @@ -166,9 +166,9 @@ esp_err_t ledc_timer_config(ledc_timer_config_t* timer_conf) esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc_channel) { - LEDC_CHECK(ledc_channel <= LEDC_CHANNEL_7, "ledc channel error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "ledc GPIO output number error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(ledc_channel <= LEDC_CHANNEL_7, "ledc channel error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "ledc GPIO output number error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO); gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT); if(speed_mode == LEDC_HIGH_SPEED_MODE) { @@ -187,10 +187,10 @@ esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf) uint32_t timer_select = ledc_conf->timer_sel; uint32_t intr_type = ledc_conf->intr_type; uint32_t duty = ledc_conf->duty; - LEDC_CHECK(ledc_channel <= LEDC_CHANNEL_7, "ledc channel error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "ledc GPIO output number error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(timer_select <= LEDC_TIMER_3, "ledc timer error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(ledc_channel <= LEDC_CHANNEL_7, "ledc channel error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "ledc GPIO output number error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(timer_select <= LEDC_TIMER_3, "ledc timer error", ESP_ERR_INVALID_ARG); esp_err_t ret = ESP_OK; /*set channel parameters*/ /* channel parameters decide how the waveform looks like in one period*/ @@ -202,7 +202,7 @@ esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf) ledc_bind_channel_timer(speed_mode, ledc_channel, timer_select); /*set interrupt type*/ ledc_enable_intr_type(speed_mode, ledc_channel, intr_type); - ESP_LOGI(LEDC_TAG, "LEDC_PWM CHANNEL %1u|GPIO %02u|Duty %04u|Time %01u\n", + ESP_LOGI(LEDC_TAG, "LEDC_PWM CHANNEL %1u|GPIO %02u|Duty %04u|Time %01u", ledc_channel, gpio_num, duty, timer_select ); /*set LEDC signal in gpio matrix*/ @@ -214,8 +214,8 @@ esp_err_t ledc_channel_config(ledc_channel_config_t* ledc_conf) esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 1; LEDC.channel_group[speed_mode].channel[channel].conf1.duty_start = 1; @@ -225,8 +225,8 @@ esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel) esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_level) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); LEDC.channel_group[speed_mode].channel[channel].conf0.idle_lv = idle_level & 0x1; LEDC.channel_group[speed_mode].channel[channel].conf0.sig_out_en = 0; @@ -237,11 +237,11 @@ esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idl esp_err_t ledc_set_fade(ledc_mode_t speed_mode, uint32_t channel, uint32_t duty, ledc_duty_direction_t fade_direction, uint32_t step_num, uint32_t duty_cyle_num, uint32_t duty_scale) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(fade_direction <= LEDC_DUTY_DIR_INCREASE, "ledc fade direction error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(fade_direction <= LEDC_DUTY_DIR_INCREASE, "ledc fade direction error", ESP_ERR_INVALID_ARG); if(step_num > LEDC_DUTY_NUM_HSCH0_V || duty_cyle_num > LEDC_DUTY_CYCLE_HSCH0_V || duty_scale > LEDC_DUTY_SCALE_HSCH0_V) { - ESP_LOGE(LEDC_TAG, "step_num=%u duty_cyle_num=%u duty_scale=%u\n", step_num, duty_cyle_num, duty_scale); + ESP_LOGE(LEDC_TAG, "step_num=%u duty_cyle_num=%u duty_scale=%u", step_num, duty_cyle_num, duty_scale); return ESP_ERR_INVALID_ARG; } ledc_duty_config(speed_mode, @@ -258,8 +258,8 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, uint32_t channel, uint32_t duty, esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); - LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); + LEDC_CHECK(channel <= LEDC_CHANNEL_7, "ledc channel error", ESP_ERR_INVALID_ARG); ledc_duty_config(speed_mode, channel, //uint32_t chan_num, 0, //uint32_t hpoint_val, @@ -274,14 +274,14 @@ esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t int ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", (-1)); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", (-1)); uint32_t duty = (LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> 4); return duty; } esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t freq_hz) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", ESP_ERR_INVALID_ARG); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", ESP_ERR_INVALID_ARG); portENTER_CRITICAL(&ledc_spinlock); esp_err_t ret = ESP_OK; uint32_t div_num = 0; @@ -294,7 +294,7 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t div_num = ((uint64_t) LEDC_REF_CLK_HZ << 8) / freq_hz / precision; } if(div_num <= 256 || div_num > LEDC_DIV_NUM_HSTIMER0) { - ESP_LOGE(LEDC_TAG, "div param err,div_param=%u\n", div_num); + ESP_LOGE(LEDC_TAG, "div param err,div_param=%u", div_num); ret = ESP_FAIL; } LEDC.timer_group[speed_mode].timer[timer_num].conf.div_num = div_num; @@ -304,7 +304,7 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num) { - LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error\n", (0)); + LEDC_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "ledc mode error", (0)); portENTER_CRITICAL(&ledc_spinlock); uint32_t freq = 0; uint32_t timer_source_clk = LEDC.timer_group[speed_mode].timer[timer_num].conf.tick_sel; diff --git a/components/driver/uart.c b/components/driver/uart.c index a3e0b92b2..b961fbed7 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -31,7 +31,7 @@ static const char* UART_TAG = "UART"; #define UART_CHECK(a, str, ret) if (!(a)) { \ - ESP_LOGE(UART_TAG,"%s:%d (%s):%s\n", __FILE__, __LINE__, __FUNCTION__, str); \ + ESP_LOGE(UART_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \ return (ret); \ } #define UART_EMPTY_THRESH_DEFAULT (10) @@ -42,6 +42,14 @@ static const char* UART_TAG = "UART"; #define UART_ENTER_CRITICAL(mux) portENTER_CRITICAL(mux) #define UART_EXIT_CRITICAL(mux) portEXIT_CRITICAL(mux) +typedef struct { + uart_event_type_t type; /*!< UART TX data type */ + struct { + int brk_len; + size_t size; + uint8_t data[0]; + } tx_data; +} uart_tx_data_t; typedef struct { uart_port_t uart_num; /*!< UART port number*/ @@ -67,7 +75,7 @@ typedef struct { RingbufHandle_t tx_ring_buf; /*!< TX ring buffer handler*/ bool tx_waiting_fifo; /*!< this flag indicates that some task is waiting for FIFO empty interrupt, used to send all data without any data buffer*/ uint8_t* tx_ptr; /*!< TX data pointer to push to FIFO in TX buffer mode*/ - uart_event_t* tx_head; /*!< TX data pointer to head of the current buffer in TX ring buffer*/ + uart_tx_data_t* tx_head; /*!< TX data pointer to head of the current buffer in TX ring buffer*/ uint32_t tx_len_tot; /*!< Total length of current item in ring buffer*/ uint32_t tx_len_cur; uint8_t tx_brk_flg; /*!< Flag to indicate to send a break signal in the end of the item sending procedure */ @@ -75,6 +83,8 @@ typedef struct { uint8_t tx_waiting_brk; /*!< Flag to indicate that TX FIFO is ready to send break signal after FIFO is empty, do not push data into TX FIFO right now.*/ } uart_obj_t; + + static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0}; static uart_dev_t* UART[UART_NUM_MAX] = {&UART0, &UART1, &UART2}; static portMUX_TYPE uart_spinlock[UART_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED, portMUX_INITIALIZER_UNLOCKED}; @@ -82,7 +92,7 @@ static portMUX_TYPE uart_spinlock[UART_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED, esp_err_t uart_set_word_length(uart_port_t uart_num, uart_word_length_t data_bit) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); - UART_CHECK((data_bit < UART_DATA_MAX_BITS), "data bit error", ESP_FAIL); + UART_CHECK((data_bit < UART_DATA_BITS_MAX), "data bit error", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); UART[uart_num]->conf0.bit_num = data_bit; UART_EXIT_CRITICAL(&uart_spinlock[uart_num]); @@ -366,7 +376,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r esp_err_t uart_set_rts(uart_port_t uart_num, int level) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); - UART_CHECK((UART[uart_num]->conf1.rx_flow_en != 1), "disable hw flowctrl before using sw control\n", ESP_FAIL); + UART_CHECK((UART[uart_num]->conf1.rx_flow_en != 1), "disable hw flowctrl before using sw control", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); UART[uart_num]->conf0.sw_rts = level & 0x1; UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); @@ -385,7 +395,7 @@ esp_err_t uart_set_dtr(uart_port_t uart_num, int level) esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_config) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); - UART_CHECK((uart_config), "param null\n", ESP_FAIL); + UART_CHECK((uart_config), "param null", ESP_FAIL); if(uart_num == UART_NUM_0) { periph_module_enable(PERIPH_UART0_MODULE); } else if(uart_num == UART_NUM_1) { @@ -407,7 +417,7 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf esp_err_t uart_intr_config(uart_port_t uart_num, const uart_intr_config_t *intr_conf) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); - UART_CHECK((intr_conf), "param null\n", ESP_FAIL); + UART_CHECK((intr_conf), "param null", ESP_FAIL); UART_ENTER_CRITICAL(&uart_spinlock[uart_num]); UART[uart_num]->int_clr.val = UART_INTR_MASK; if(intr_conf->intr_enable_mask & UART_RXFIFO_TOUT_INT_ENA_M) { @@ -468,17 +478,17 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) while(tx_fifo_rem) { if(p_uart->tx_len_tot == 0 || p_uart->tx_ptr == NULL || p_uart->tx_len_cur == 0) { size_t size; - p_uart->tx_head = (uart_event_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); + p_uart->tx_head = (uart_tx_data_t*) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size); if(p_uart->tx_head) { //The first item is the data description //Get the first item to get the data information if(p_uart->tx_len_tot == 0) { p_uart->tx_ptr = NULL; - p_uart->tx_len_tot = p_uart->tx_head->data.size; + p_uart->tx_len_tot = p_uart->tx_head->tx_data.size; if(p_uart->tx_head->type == UART_DATA_BREAK) { - p_uart->tx_len_tot = p_uart->tx_head->data.size; + p_uart->tx_len_tot = p_uart->tx_head->tx_data.size; p_uart->tx_brk_flg = 1; - p_uart->tx_brk_len = p_uart->tx_head->data.brk_len; + p_uart->tx_brk_len = p_uart->tx_head->tx_data.brk_len; } //We have saved the data description from the 1st item, return buffer. vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken); @@ -553,7 +563,7 @@ static void IRAM_ATTR uart_rx_intr_handler_default(void *param) uart_reg->int_clr.rxfifo_full = 1; UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]); uart_event.type = UART_DATA; - uart_event.data.size = rx_fifo_len; + uart_event.size = rx_fifo_len; //If we fail to push data to ring buffer, we will have to stash the data, and send next time. //Mainly for applications that uses flow control or small ring buffer. if(pdFALSE == xRingbufferSendFromISR(p_uart->rx_ring_buf, p_uart->rx_data_buf, p_uart->rx_stash_len, &HPTaskAwoken)) { @@ -711,9 +721,9 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool if(p_uart_obj[uart_num]->tx_buf_size > 0) { int max_size = xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf); int offset = 0; - uart_event_t evt; - evt.data.size = size; - evt.data.brk_len = brk_len; + uart_tx_data_t evt; + evt.tx_data.size = size; + evt.tx_data.brk_len = brk_len; if(brk_en) { evt.type = UART_DATA_BREAK; } else { @@ -882,12 +892,12 @@ esp_err_t uart_flush(uart_port_t uart_num) esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, int uart_intr_num, void* uart_queue) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); - UART_CHECK((rx_buffer_size > 0), "uart rx buffer length error\n", ESP_FAIL); + UART_CHECK((rx_buffer_size > 0), "uart rx buffer length error", ESP_FAIL); if(p_uart_obj[uart_num] == NULL) { ESP_INTR_DISABLE(uart_intr_num); p_uart_obj[uart_num] = (uart_obj_t*) malloc(sizeof(uart_obj_t)); if(p_uart_obj[uart_num] == NULL) { - ESP_LOGE(UART_TAG, "UART driver malloc error\n"); + ESP_LOGE(UART_TAG, "UART driver malloc error"); return ESP_FAIL; } p_uart_obj[uart_num]->uart_num = uart_num; @@ -909,7 +919,7 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b if(uart_queue) { p_uart_obj[uart_num]->xQueueUart = xQueueCreate(queue_size, sizeof(uart_event_t)); *((QueueHandle_t*) uart_queue) = p_uart_obj[uart_num]->xQueueUart; - ESP_LOGI(UART_TAG, "queue free spaces: %d\n", uxQueueSpacesAvailable(p_uart_obj[uart_num]->xQueueUart)); + ESP_LOGI(UART_TAG, "queue free spaces: %d", uxQueueSpacesAvailable(p_uart_obj[uart_num]->xQueueUart)); } else { p_uart_obj[uart_num]->xQueueUart = NULL; } @@ -927,7 +937,7 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b p_uart_obj[uart_num]->tx_buf_size = 0; } } else { - ESP_LOGE(UART_TAG, "UART driver already installed\n"); + ESP_LOGE(UART_TAG, "UART driver already installed"); return ESP_FAIL; } uart_isr_register(uart_num, uart_intr_num, uart_rx_intr_handler_default, p_uart_obj[uart_num]); @@ -951,7 +961,7 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); if(p_uart_obj[uart_num] == NULL) { - ESP_LOGI(UART_TAG, "ALREADY NULL\n"); + ESP_LOGI(UART_TAG, "ALREADY NULL"); return ESP_OK; } ESP_INTR_DISABLE(p_uart_obj[uart_num]->intr_num); From 4f4c9030fd284e79eed46aa403fb9ec5efba84a8 Mon Sep 17 00:00:00 2001 From: Wangjialin Date: Thu, 10 Nov 2016 17:01:39 +0800 Subject: [PATCH 12/12] Fix uart tx bug, data pass(with flow control) through test ok. --- components/driver/uart.c | 2 +- components/esp32/include/esp_err.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/components/driver/uart.c b/components/driver/uart.c index b961fbed7..d9e3fd64c 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -729,7 +729,7 @@ static int uart_tx_all(uart_port_t uart_num, const char* src, size_t size, bool } else { evt.type = UART_DATA; } - xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_event_t), portMAX_DELAY); + xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) &evt, sizeof(uart_tx_data_t), portMAX_DELAY); while(size > 0) { int send_size = size > max_size / 2 ? max_size / 2 : size; xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void*) (src + offset), send_size, portMAX_DELAY); diff --git a/components/esp32/include/esp_err.h b/components/esp32/include/esp_err.h index f8271ba25..a1f4b8f35 100644 --- a/components/esp32/include/esp_err.h +++ b/components/esp32/include/esp_err.h @@ -34,6 +34,8 @@ typedef int32_t esp_err_t; #define ESP_ERR_INVALID_SIZE 0x104 #define ESP_ERR_NOT_FOUND 0x105 #define ESP_ERR_NOT_SUPPORTED 0x106 +#define ESP_ERR_TIMEOUT 0x107 + #define ESP_ERR_WIFI_BASE 0x3000 /*!< Starting number of WiFi error codes */