/* * File : uart.c * Copyright (C) 2013 - 2016, Espressif Systems * * This program is free software: you can redistribute it and/or modify * it under the terms of version 3 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "ets_sys.h" #include "osapi.h" #include "driver/uart.h" #include "osapi.h" #include "driver/uart_register.h" #include "mem.h" #include "os_type.h" #ifdef _ENABLE_RING_BUFFER static ringbuf_t rxBuff; static ringbuf_t txBuff; #endif #ifdef _ENABLE_CONSOLE_INTEGRATION uint8_t linked_to_console = 0; uint8_t echo_on = 1; #endif extern UartDevice UartDev; /* Local variables */ static uint8 uart_recvTaskPrio = 0; /* Internal Functions */ static void ICACHE_FLASH_ATTR uart_config(uint8 uart_no); static void uart0_rx_intr_handler(void *para); /* Public APIs */ void ICACHE_FLASH_ATTR UART_init(UartBautRate uart0_br, UartBautRate uart1_br, uint8 recv_task_priority); #define ENABLE_DEBUG #ifdef ENABLE_DEBUG #define DBG #define DBG1 os_printf #define DBG2 os_printf #else #define DBG #define DBG1 #define DBG2 #endif #if _ENABLE_CONSOLE_INTEGRATION == 1 void ICACHE_FLASH_ATTR UART_init_console(UartBautRate uart0_br, uint8 recv_task_priority, ringbuf_t rxbuffer, ringbuf_t txBuffer) { /* Set the task which should receive the signals once the data is received */ uart_recvTaskPrio = recv_task_priority; UartDev.baut_rate = uart0_br; rxBuff = rxbuffer; txBuff = txBuffer; linked_to_console = 1; echo_on = 1; uart_config(UART0); UART_SetPrintPort(UART0); UartDev.baut_rate = uart0_br; uart_config(UART1); ETS_UART_INTR_ENABLE(); } #endif void ICACHE_FLASH_ATTR UART_init(UartBautRate uart0_br, UartBautRate uart1_br, uint8 recv_task_priority) { /* Set the task which should receive the signals once the data is received */ uart_recvTaskPrio = recv_task_priority; UartDev.baut_rate = uart0_br; uart_config(UART0); UART_SetPrintPort(UART0); UartDev.baut_rate = uart1_br; uart_config(UART1); ETS_UART_INTR_ENABLE(); #if _ENABLE_CONSOLE_INTEGRATION == 0 #if _ENABLE_RING_BUFFER == 1 rxBuff = ringbuf_new(RX_RING_BUFFER_SIZE); #endif #endif } /****************************************************************************** * FunctionName : uart_config * Description : Internal used function * UART0 used for data TX/RX, RX buffer size is 0x100, interrupt enabled * UART1 just used for debug output * Parameters : uart_no, use UART0 or UART1 defined ahead * Returns : NONE *******************************************************************************/ LOCAL void ICACHE_FLASH_ATTR uart_config(uint8 uart_no) { if (uart_no == UART1) { PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); } else { /* rcv_buff size if 0x100 */ ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff)); PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); #if UART_HW_RTS PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); //HW FLOW CONTROL RTS PIN #endif #if UART_HW_CTS PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_U0CTS); //HW FLOW CONTROL CTS PIN #endif } uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate));//SET BAUDRATE WRITE_PERI_REG(UART_CONF0(uart_no), ((UartDev.exist_parity & UART_PARITY_EN_M) << UART_PARITY_EN_S) //SET BIT AND PARITY MODE | ((UartDev.parity & UART_PARITY_M) <>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT; if (fifo_len) { max_unload = (fifo_len>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT; //DBG1("RX FIFO FULL [%d]\r\n", fifo_len ); if (fifo_len) { //DBG1("Rx Fifo contains %d characters have to unload\r\n", fifo_len); for (index=0;index>UART_RXFIFO_CNT_S)& UART_RXFIFO_CNT); uart_rx_intr_disable(UART0); WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR); system_os_post(uart_recvTaskPrio, SIG_UART0, 0); #endif goto end_int_handler; } if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)) { /* The Time out threshold for Rx/Tx is being execeeded */ DBG1("Rx Timeout Threshold not being met \r\n"); uart_rx_intr_disable(UART0); WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR); system_os_post(uart_recvTaskPrio, SIG_UART0, 0); goto end_int_handler; } if(UART_TXFIFO_EMPTY_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_TXFIFO_EMPTY_INT_ST)) { /* The Tx FIFO is empty, the FIFO needs to be fed with new data */ DBG1("Tx FIFO is empty\r\n"); CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA); #if UART_BUFF_EN tx_start_uart_buffer(UART0); #endif //system_os_post(uart_recvTaskPrio, 1, 0); WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_TXFIFO_EMPTY_INT_CLR); } end_int_handler: return; } /****************************************************************************** * FunctionName : uart_tx_one_char_no_wait * Description : uart tx a single char without waiting for fifo * Parameters : uint8 uart - uart port * uint8 TxChar - char to tx * Returns : STATUS *******************************************************************************/ STATUS uart_tx_one_char(uint8 uart, uint8 TxChar) { while (true) { uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT<> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) { break; } } WRITE_PERI_REG(UART_FIFO(uart) , TxChar); return OK; } /****************************************************************************** * FunctionName : uart_tx_one_char_no_wait * Description : uart tx a single char without waiting for fifo * Parameters : uint8 uart - uart port * uint8 TxChar - char to tx * Returns : STATUS *******************************************************************************/ STATUS uart_tx_one_char_no_wait(uint8 uart, uint8 TxChar) { uint8 fifo_cnt = (( READ_PERI_REG(UART_STATUS(uart))>>UART_TXFIFO_CNT_S)& UART_TXFIFO_CNT); if (fifo_cnt < 126) { WRITE_PERI_REG(UART_FIFO(uart) , TxChar); } return OK; } /****************************************************************************** * FunctionName : uart0_write_char_no_wait * Description : tx a single char without waiting for uart 0. helper function for os_printf output to fifo or tx buffer * Parameters : uint8 uart - uart port * uint8 TxChar - char to tx * Returns : STATUS *******************************************************************************/ LOCAL void ICACHE_FLASH_ATTR uart0_write_char_no_wait(char c) { #if UART_BUFF_EN //send to uart0 fifo but do not wait uint8 chr; if (c == '\n'){ chr = '\r'; tx_buff_enq(&chr, 1); chr = '\n'; tx_buff_enq(&chr, 1); }else if (c == '\r'){ }else{ tx_buff_enq(&c,1); } #else //send to uart tx buffer if (c == '\n') { uart_tx_one_char(UART0, '\r'); uart_tx_one_char(UART0, '\n'); //uart_tx_one_char_no_wait(UART0, '\r'); //uart_tx_one_char_no_wait(UART0, '\n'); } else if (c == '\r') { uart_tx_one_char(UART0, c); } else { uart_tx_one_char(UART0, c); //uart_tx_one_char_no_wait(UART0, c); } #endif } /****************************************************************************** * FunctionName : UART_SetPrintPort * Description : * * Parameters : * Returns : NONE *******************************************************************************/ void ICACHE_FLASH_ATTR UART_SetPrintPort(uint8 uart_no) { if(uart_no==1) { //os_install_putc1(uart1_write_char); } else { /*option 1: do not wait if uart fifo is full,drop current character*/ //os_install_putc1(uart0_write_char_no_wait); /*option 2: wait for a while if uart fifo is full*/ //os_install_putc1(uart0_write_char); } }