/****************************************************************************** * 2016 ideasX (Tyler Berezowsky) * * FileName: uart.c * * Description: Two UART mode configration and interrupt handler. * Check your hardware connection while use this mode. * Future Work: Modify ISR to handle UART timeout and Errors * * Modification history: * 2014/3/12, v1.0 create this file. *******************************************************************************/ #include "driver/uart.h" // UartDev is defined and initialized in rom code. extern UartDevice UartDev; static void uart0_rx_intr_handler(void *para); /****************************************************************************** * 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 *******************************************************************************/ static void ICACHE_FLASH_ATTR uart_config(uint8 uart_no) { if (uart_no == UART1) { PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); // setup gpio2 for UART1 } else { ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff)); // attach uart0_rx_intr_handler ISR PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); // disable pullup on TX pin PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); // setup gpio TX pin /* setup hardware flow control */ #if UART_HW_RTS PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); //SETUP HW FLOW CONTROL RTS PIN #endif #if UART_HW_CTS PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_U0CTS); //SETUP HW FLOW CONTROL CTS PIN #endif } uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate)); // setup baudrate WRITE_PERI_REG(UART_CONF0(uart_no), ((UartDev.exist_parity & UART_PARITY_EN_M) << UART_PARITY_EN_S) // setup parity | ((UartDev.parity & UART_PARITY_M) <> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) { break; } } WRITE_PERI_REG(UART_FIFO(UART1) , TxChar); // add character to FIFO return OK; } /****************************************************************************** * FunctionName : uart1_write_char * Description : Internal used function * Do some special deal while tx char is '\r' or '\n' * Parameters : char c - character to tx * Returns : NONE *******************************************************************************/ static void ICACHE_FLASH_ATTR uart1_write_char(char c) { if (c == '\n') { uart1_tx_one_char('\r'); uart1_tx_one_char('\n'); } else if (c == '\r') { } else { uart1_tx_one_char(c); } } /****************************************************************************** * FunctionName : uart0_rx_intr_handler * Description : Internal used function * UART0 interrupt handler, add self handle code inside * Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg * Returns : NONE *******************************************************************************/ extern void process_command(char* str); static void uart0_rx_intr_handler(void *para) { /* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents * uart1 and uart0 respectively */ RcvMsgBuff *pRxBuff = (RcvMsgBuff *)para; uint8 RcvChar; // if uart0 fifo isn't full return if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_RXFIFO_FULL_INT_ST)){ WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR); // clear full FIFO flag while (READ_PERI_REG(UART_STATUS(UART0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) { RcvChar = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF; /* you can add your handle code below.*/ uart_tx_one_char(RcvChar); // echo recieved character // NOTE: Lets modify the \r\n sequence to something more american. // NOTE: Add hook for backspace character...I need to learn the ASCII code // NOTE: Backspace character should also remove the last two stored characters // in the buffer. This might be possible by moving the pWritePos back 2 characters? // if "\r\n" recieved dump UART buffer into str if (RcvChar == '\r') continue; if (RcvChar == '\n') { int len; char *str; len = pRxBuff->pWritePos - pRxBuff->pReadPos; if (len == 0) continue; if (len < 0) len += RX_BUFF_SIZE; str = (char*)os_zalloc(len+1); if (str) { uint8 loop; for (loop = 0; loop < len; loop++) str[loop] = uart0_rx_one_char(); str[len] = '\0'; process_command(str); os_free(str); } } // otherwise add character to buffer else { *(pRxBuff->pWritePos) = RcvChar; pRxBuff->pWritePos++; } // if we hit the end of the buffer, loop back to the beginning if (pRxBuff->pWritePos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE)) { // overflow ...we may need more error handle here. pRxBuff->pWritePos = pRxBuff->pRcvMsgBuff ; } } } } ICACHE_FLASH_ATTR int uart0_rx_one_char() { if(UartDev.rcv_buff.pReadPos == UartDev.rcv_buff.pWritePos) return -1; int ret = *UartDev.rcv_buff.pReadPos; UartDev.rcv_buff.pReadPos++; if(UartDev.rcv_buff.pReadPos == (UartDev.rcv_buff.pRcvMsgBuff + RX_BUFF_SIZE)) { UartDev.rcv_buff.pReadPos = UartDev.rcv_buff.pRcvMsgBuff; } return ret; } /****************************************************************************** * FunctionName : uart0_tx_buffer * Description : use uart0 to transfer buffer * Parameters : uint8 *buf - point to send buffer * uint16 len - buffer len * Returns : *******************************************************************************/ // void ICACHE_FLASH_ATTR uart0_tx_buffer(uint8 *buf, uint16 len) // { // uint16 i; // // for (i = 0; i < len; i++) { // uart_tx_one_char(buf[i]); // } // } void ICACHE_FLASH_ATTR uart0_send(const char *str) { uint8 i = 0; while (str[i]) { uart_tx_one_char(str[i]); i++; } } /****************************************************************************** * FunctionName : uart_init * Description : user interface for init uart * Parameters : UartBautRate uart0_br - uart0 bautrate * UartBautRate uart1_br - uart1 bautrate * Returns : NONE *******************************************************************************/ void ICACHE_FLASH_ATTR uart_init(UartBautRate uart0_br, UartBautRate uart1_br, bool enable_uart1) { // rom use 74880 baut_rate, here reinitialize UartDev.baut_rate = uart0_br; uart_config(UART0); if (enable_uart1) { UartDev.baut_rate = uart1_br; uart_config(UART1); } ETS_UART_INTR_ENABLE(); }