From acd8801d3367b4bb88a4382e01e9fa01bf21b22e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Thu, 24 Aug 2017 00:47:14 +0200 Subject: [PATCH] W.I.P. new async Rx Tx buffer, probably not working --- CMakeLists.txt | 20 +- user/uart_asyncdrv.c- | 830 ++++++++++++++++++++++++++++++++++++++++++ user/uart_asyncdrv.h- | 178 +++++++++ user/uart_buffer.c | 251 +++++++++++++ user/uart_buffer.h | 24 ++ user/uart_handler.c | 43 ++- user/uart_handler.h | 7 +- 7 files changed, 1337 insertions(+), 16 deletions(-) create mode 100644 user/uart_asyncdrv.c- create mode 100644 user/uart_asyncdrv.h- create mode 100644 user/uart_buffer.c create mode 100644 user/uart_buffer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index de126e6..c991ee4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -110,6 +110,8 @@ set(SOURCE_FILES user/serial.h user/routes.c user/routes.h + user/uart_asyncdrv.c- + user/uart_asyncdrv.h- user/cgi_main.c user/cgi_main.h user/cgi_sockets.c @@ -123,7 +125,23 @@ set(SOURCE_FILES user/persist.h include/helpers.h user/syscfg.c - user/syscfg.h user/ascii.h user/sgr.h user/apars_utf8.c user/apars_utf8.h user/apars_logging.h user/version.h user/apars_csi.c user/apars_csi.h user/apars_short.c user/apars_short.h user/apars_string.c user/apars_string.h user/apars_osc.c user/apars_osc.h user/apars_dcs.c user/apars_dcs.h) + user/syscfg.h + user/ascii.h + user/sgr.h + user/apars_utf8.c + user/apars_utf8.h + user/apars_logging.h + user/version.h + user/apars_csi.c + user/apars_csi.h + user/apars_short.c + user/apars_short.h + user/apars_string.c + user/apars_string.h + user/apars_osc.c + user/apars_osc.h + user/apars_dcs.c + user/apars_dcs.h user/uart_buffer.c user/uart_buffer.h) include_directories(include) include_directories(user) diff --git a/user/uart_asyncdrv.c- b/user/uart_asyncdrv.c- new file mode 100644 index 0000000..c257b67 --- /dev/null +++ b/user/uart_asyncdrv.c- @@ -0,0 +1,830 @@ +/* + * 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 +#include +#include "uart_asyncdrv.h-" + +// UartDev is defined and initialized in rom code. +extern UartDevice UartDev; + +struct UartBuffer { + uint32 UartBuffSize; + uint8 *pUartBuff; + uint8 *pInPos; + uint8 *pOutPos; + STATUS BuffState; + uint16 Space; //remanent space of the buffer + uint8 TcpControl; + struct UartBuffer *nextBuff; +}; + +struct UartRxBuff { + uint32 UartRxBuffSize; + uint8 *pUartRxBuff; + uint8 *pWritePos; + uint8 *pReadPos; + STATUS RxBuffState; + uint32 Space; //remanent space of the buffer +}; + +LOCAL struct UartBuffer* pTxBuffer = NULL; +LOCAL struct UartBuffer* pRxBuffer = NULL; + +// Forward declare +#if UART_BUFF_EN +LOCAL void Uart_Buf_Cpy(struct UartBuffer* pCur, char* pdata , uint16 data_len); +void uart_buf_free(struct UartBuffer* pBuff); +void tx_buff_enq(char* pdata, uint16 data_len ); +LOCAL void tx_fifo_insert(struct UartBuffer* pTxBuff, uint8 data_len, uint8 uart_no); +void tx_start_uart_buffer(uint8 uart_no); +uint16 rx_buff_deq(char* pdata, uint16 data_len ); +void Uart_rx_buff_enq(); +#endif + +//void ICACHE_FLASH_ATTR uart_test_rx(); +STATUS uart_tx_one_char(uint8 uart, uint8 TxChar); +STATUS uart_tx_one_char_no_wait(uint8 uart, uint8 TxChar); +void uart1_sendStr_no_wait(const char *str); +struct UartBuffer* UART_AsyncBufferInit(u32 size); + +void uart_rx_intr_enable(uint8 uart_no); +void uart_rx_intr_disable(uint8 uart_no); +void uart0_tx_buffer(uint8 *buf, uint16 len); + +void uart0_sendStr(const char *str); + + +/*uart demo with a system task, to output what uart receives*/ +/*this is a example to process uart data from task,please change the priority to fit your application task if exists*/ +/*it might conflict with your task, if so,please arrange the priority of different task, or combine it to a different event in the same task. */ +#define uart_recvTaskPrio 0 +#define uart_recvTaskQueueLen 10 +os_event_t uart_recvTaskQueue[uart_recvTaskQueueLen]; + +#define DBG +#define DBG1 uart1_sendStr_no_wait +#define DBG2 os_printf + + +LOCAL 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 +*******************************************************************************/ +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_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) { + break; + } + } + WRITE_PERI_REG(UART_FIFO(uart) , TxChar); + 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 +*******************************************************************************/ +LOCAL void ICACHE_FLASH_ATTR +uart1_write_char(char c) +{ + if (c == '\n'){ + uart_tx_one_char(UART1, '\r'); + uart_tx_one_char(UART1, '\n'); + }else if (c == '\r'){ + + }else{ + uart_tx_one_char(UART1, c); + } +} + +//os_printf output to fifo or to the tx buffer +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_no_wait(UART0, '\r'); + uart_tx_one_char_no_wait(UART0, '\n'); + }else if (c == '\r'){ + + } + else{ + uart_tx_one_char_no_wait(UART0, c); + } +#endif +} + +/****************************************************************************** + * 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(UART0, buf[i]); + } +} + +/****************************************************************************** + * FunctionName : uart0_sendStr + * Description : use uart0 to transfer buffer + * Parameters : uint8 *buf - point to send buffer + * uint16 len - buffer len + * Returns : +*******************************************************************************/ +void ICACHE_FLASH_ATTR +uart0_sendStr(const char *str) +{ + while(*str){ + uart_tx_one_char(UART0, *str++); + } +} +void at_port_print(const char *str) __attribute__((alias("uart0_sendStr"))); +/****************************************************************************** + * 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 +*******************************************************************************/ +LOCAL 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 + */ + uint8 RcvChar; + uint8 uart_no = UART0;//UartDev.buff_uart_no; + uint8 fifo_len = 0; + uint8 buf_idx = 0; + uint8 temp,cnt; + //RcvMsgBuff *pRxBuff = (RcvMsgBuff *)para; + + /*ATTENTION:*/ + /*IN NON-OS VERSION SDK, DO NOT USE "ICACHE_FLASH_ATTR" FUNCTIONS IN THE WHOLE HANDLER PROCESS*/ + /*ALL THE FUNCTIONS CALLED IN INTERRUPT HANDLER MUST BE DECLARED IN RAM */ + /*IF NOT , POST AN EVENT AND PROCESS IN SYSTEM TASK */ + if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST)){ + DBG1("FRM_ERR\r\n"); + WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR); + }else if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)){ + // Full interrupt - FIFO threshold reached + DBG("f"); + uart_rx_intr_disable(UART0); + WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR); + system_os_post(uart_recvTaskPrio, 0, 0); // tell the handler + }else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)){ + // Timeout interrupt - Line idle for a while + DBG("t"); + uart_rx_intr_disable(UART0); + WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR); + system_os_post(uart_recvTaskPrio, 0, 0); // tell the handler + }else if(UART_TXFIFO_EMPTY_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_TXFIFO_EMPTY_INT_ST)){ + DBG("e"); + // TX fifo is empty, can send more. + + /* to output uart data from uart buffer directly in empty interrupt handler*/ + /*instead of processing in system event, in order not to wait for current task/function to quit */ + /*ATTENTION:*/ + /*IN NON-OS VERSION SDK, DO NOT USE "ICACHE_FLASH_ATTR" FUNCTIONS IN THE WHOLE HANDLER PROCESS*/ + /*ALL THE FUNCTIONS CALLED IN INTERRUPT HANDLER MUST BE DECLARED IN RAM */ + 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); + + }else if(UART_RXFIFO_OVF_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_OVF_INT_ST)){ + WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_OVF_INT_CLR); + DBG1("RX OVF!!\r\n"); + } + +} + +/****************************************************************************** + * FunctionName : uart_init + * Description : user interface for init uart + * Parameters : UartBautRate uart0_br - uart0 bautrate + * UartBautRate uart1_br - uart1 bautrate + * Returns : NONE +*******************************************************************************/ +#if UART_SELFTEST&UART_BUFF_EN +os_timer_t buff_timer_t; +void ICACHE_FLASH_ATTR +uart_test_rx() +{ + uint8 uart_buf[128]={0}; + uint16 len = 0; + len = rx_buff_deq(uart_buf, 128 ); + tx_buff_enq(uart_buf,len); +} +#endif + +LOCAL void ICACHE_FLASH_ATTR /////// +uart_recvTask(os_event_t *events) +{ + if(events->sig == 0){ + #if UART_BUFF_EN + Uart_rx_buff_enq(); + #else + uint8 fifo_len = (READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT; + uint8 d_tmp = 0; + uint8 idx=0; + for(idx=0;idxsig == 1){ + #if UART_BUFF_EN + //already move uart buffer output to uart empty interrupt + //tx_start_uart_buffer(UART0); + #else + + #endif + } +} + +void ICACHE_FLASH_ATTR +uart_init(UartBautRate uart0_br, UartBautRate uart1_br) +{ + /*this is a example to process uart data from task,please change the priority to fit your application task if exists*/ + system_os_task(uart_recvTask, uart_recvTaskPrio, uart_recvTaskQueue, uart_recvTaskQueueLen); //demo with a task to process the uart data + + UartDev.baut_rate = uart0_br; + uart_config(UART0); + UartDev.baut_rate = uart1_br; + uart_config(UART1); + ETS_UART_INTR_ENABLE(); + + #if UART_BUFF_EN + pTxBuffer = UART_AsyncBufferInit(UART_TX_BUFFER_SIZE); + pRxBuffer = UART_AsyncBufferInit(UART_RX_BUFFER_SIZE); + #endif + + + /*option 1: use default print, output from uart0 , will wait some time if fifo is full */ + //do nothing... + + /*option 2: output from uart1,uart1 output will not wait , just for output debug info */ + /*os_printf output uart data via uart1(GPIO2)*/ + os_install_putc1((void *)uart1_write_char); //use this one to output debug information via uart1 // + + /*option 3: output from uart0 will skip current byte if fifo is full now... */ + /*see uart0_write_char_no_wait:you can output via a buffer or output directly */ + /*os_printf output uart data via uart0 or uart buffer*/ + //os_install_putc1((void *)uart0_write_char_no_wait); //use this to print via uart0 + + #if UART_SELFTEST&UART_BUFF_EN + os_timer_disarm(&buff_timer_t); + os_timer_setfn(&buff_timer_t, uart_test_rx , NULL); //a demo to process the data in uart rx buffer + os_timer_arm(&buff_timer_t,10,1); + #endif +} + +//void ICACHE_FLASH_ATTR +//uart_reattach() +//{ +// uart_init(BIT_RATE_115200, BIT_RATE_115200); +//} + +/****************************************************************************** + * 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; +} + +//STATUS uart0_tx_one_char_no_wait(uint8 TxChar) +//{ +// uint8 fifo_cnt = (( READ_PERI_REG(UART_STATUS(UART0))>>UART_TXFIFO_CNT_S)& UART_TXFIFO_CNT); +// if (fifo_cnt < 126) { +// WRITE_PERI_REG(UART_FIFO(UART0) , TxChar); +// } +// return OK; +//} + + +/****************************************************************************** + * FunctionName : uart1_sendStr_no_wait + * Description : uart tx a string without waiting for every char, used for print debug info which can be lost + * Parameters : const char *str - string to be sent + * Returns : NONE +*******************************************************************************/ +void uart1_sendStr_no_wait(const char *str) +{ + while(*str){ + uart_tx_one_char_no_wait(UART1, *str++); + } +} + + +#if UART_BUFF_EN +/****************************************************************************** + * FunctionName : Uart_Buf_Init + * Description : tx buffer enqueue: fill a first linked buffer + * Parameters : char *pdata - data point to be enqueue + * Returns : NONE +*******************************************************************************/ +struct UartBuffer* ICACHE_FLASH_ATTR +UART_AsyncBufferInit(uint32 buf_size) +{ + uint32 heap_size = system_get_free_heap_size(); + if(heap_size <=buf_size){ + DBG1("no buf for uart\n\r"); + return NULL; + }else{ + DBG("test heap size: %d\n\r",heap_size); + struct UartBuffer* pBuff = (struct UartBuffer* )os_malloc(sizeof(struct UartBuffer)); + pBuff->UartBuffSize = buf_size; + pBuff->pUartBuff = (uint8*)os_malloc(pBuff->UartBuffSize); + pBuff->pInPos = pBuff->pUartBuff; + pBuff->pOutPos = pBuff->pUartBuff; + pBuff->Space = (uint16) pBuff->UartBuffSize; + pBuff->BuffState = OK; + pBuff->nextBuff = NULL; + pBuff->TcpControl = RUN; + return pBuff; + } +} + + +//copy uart buffer +LOCAL void Uart_Buf_Cpy(struct UartBuffer* pCur, char* pdata , uint16 data_len) +{ + if(data_len == 0) return; + + uint16 tail_len = (uint16) (pCur->pUartBuff + pCur->UartBuffSize - pCur->pInPos); + if(tail_len >= data_len){ //do not need to loop back the queue + os_memcpy(pCur->pInPos , pdata , data_len ); + pCur->pInPos += ( data_len ); + pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize ); + pCur->Space -=data_len; + }else{ + os_memcpy(pCur->pInPos, pdata, tail_len); + pCur->pInPos += ( tail_len ); + pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize ); + pCur->Space -=tail_len; + os_memcpy(pCur->pInPos, pdata+tail_len , data_len-tail_len); + pCur->pInPos += ( data_len-tail_len ); + pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize ); + pCur->Space -=( data_len-tail_len); + } + +} + +/****************************************************************************** + * FunctionName : uart_buf_free + * Description : deinit of the tx buffer + * Parameters : struct UartBuffer* pTxBuff - tx buffer struct pointer + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR +uart_buf_free(struct UartBuffer* pBuff) +{ + os_free(pBuff->pUartBuff); + os_free(pBuff); +} + + +//rx buffer dequeue +uint16 ICACHE_FLASH_ATTR +rx_buff_deq(char* pdata, uint16 data_len) +{ + uint16 buf_len = (pRxBuffer->UartBuffSize- pRxBuffer->Space); + uint16 tail_len = pRxBuffer->pUartBuff + pRxBuffer->UartBuffSize - pRxBuffer->pOutPos ; + uint16 len_tmp = 0; + len_tmp = ((data_len > buf_len)?buf_len:data_len); + if(pRxBuffer->pOutPos <= pRxBuffer->pInPos){ + os_memcpy(pdata, pRxBuffer->pOutPos,len_tmp); + pRxBuffer->pOutPos+= len_tmp; + pRxBuffer->Space += len_tmp; + }else{ + if(len_tmp>tail_len){ + os_memcpy(pdata, pRxBuffer->pOutPos, tail_len); + pRxBuffer->pOutPos += tail_len; + pRxBuffer->pOutPos = (pRxBuffer->pUartBuff + (pRxBuffer->pOutPos- pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize ); + pRxBuffer->Space += tail_len; + + os_memcpy(pdata+tail_len , pRxBuffer->pOutPos, len_tmp-tail_len); + pRxBuffer->pOutPos+= ( len_tmp-tail_len ); + pRxBuffer->pOutPos= (pRxBuffer->pUartBuff + (pRxBuffer->pOutPos- pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize ); + pRxBuffer->Space +=( len_tmp-tail_len); + }else{ + //os_printf("case 3 in rx deq\n\r"); + os_memcpy(pdata, pRxBuffer->pOutPos, len_tmp); + pRxBuffer->pOutPos += len_tmp; + pRxBuffer->pOutPos = (pRxBuffer->pUartBuff + (pRxBuffer->pOutPos- pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize ); + pRxBuffer->Space += len_tmp; + } + } + if(pRxBuffer->Space >= UART_FIFO_LEN){ + uart_rx_intr_enable(UART0); + } + return len_tmp; +} + + +//move data from uart fifo to rx buffer +void Uart_rx_buff_enq() +{ + uint8 fifo_len,buf_idx; + uint8 fifo_data; + #if 1 + fifo_len = (READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT; + if(fifo_len >= pRxBuffer->Space){ + os_printf("buf full!!!\n\r"); + }else{ + buf_idx=0; + while(buf_idx < fifo_len){ + buf_idx++; + fifo_data = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF; + *(pRxBuffer->pInPos++) = fifo_data; + if(pRxBuffer->pInPos == (pRxBuffer->pUartBuff + pRxBuffer->UartBuffSize)){ + pRxBuffer->pInPos = pRxBuffer->pUartBuff; + } + } + pRxBuffer->Space -= fifo_len ; + if(pRxBuffer->Space >= UART_FIFO_LEN){ + //os_printf("after rx enq buf enough\n\r"); + uart_rx_intr_enable(UART0); + } + } + #endif +} + + +//fill the uart tx buffer +void ICACHE_FLASH_ATTR +tx_buff_enq(char* pdata, uint16 data_len ) +{ + if(pTxBuffer == NULL){ + DBG1("\n\rnull, create buffer struct\n\r"); + pTxBuffer = UART_AsyncBufferInit(UART_TX_BUFFER_SIZE); + if(pTxBuffer!= NULL){ + Uart_Buf_Cpy(pTxBuffer , pdata, data_len ); + }else{ + DBG1("uart tx MALLOC no buf \n\r"); + } + }else{ + if(data_len <= pTxBuffer->Space){ + Uart_Buf_Cpy(pTxBuffer , pdata, data_len); + }else{ + DBG1("UART TX BUF FULL!!!!\n\r"); + } + } + #if 0 + if(pTxBuffer->Space <= URAT_TX_LOWER_SIZE){ + set_tcp_block(); + } + #endif + SET_PERI_REG_MASK(UART_CONF1(UART0), (UART_TX_EMPTY_THRESH_VAL & UART_TXFIFO_EMPTY_THRHD)<pOutPos++)); + if(pTxBuff->pOutPos == (pTxBuff->pUartBuff + pTxBuff->UartBuffSize)){ + pTxBuff->pOutPos = pTxBuff->pUartBuff; + } + } + pTxBuff->pOutPos = (pTxBuff->pUartBuff + (pTxBuff->pOutPos - pTxBuff->pUartBuff) % pTxBuff->UartBuffSize ); + pTxBuff->Space += data_len; +} + + +/****************************************************************************** + * FunctionName : tx_start_uart_buffer + * Description : get data from the tx buffer and fill the uart tx fifo, co-work with the uart fifo empty interrupt + * Parameters : uint8 uart_no - uart port num + * Returns : NONE +*******************************************************************************/ +void tx_start_uart_buffer(uint8 uart_no) +{ + uint8 tx_fifo_len = (READ_PERI_REG(UART_STATUS(uart_no))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT; + uint8 fifo_remain = UART_FIFO_LEN - tx_fifo_len ; + uint8 len_tmp; + uint16 tail_ptx_len,head_ptx_len,data_len; + //struct UartBuffer* pTxBuff = *get_buff_prt(); + + if(pTxBuffer){ + data_len = (pTxBuffer->UartBuffSize - pTxBuffer->Space); + if(data_len > fifo_remain){ + len_tmp = fifo_remain; + tx_fifo_enq(pTxBuffer, len_tmp, uart_no); + SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA); + }else{ + len_tmp = data_len; + tx_fifo_enq(pTxBuffer, len_tmp, uart_no); + } + }else{ + DBG1("pTxBuff null \n\r"); + } +} + +#endif + + +void uart_rx_intr_disable(uint8 uart_no) +{ +#if 1 + CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA); +#else + ETS_UART_INTR_DISABLE(); +#endif +} + +void uart_rx_intr_enable(uint8 uart_no) +{ +#if 1 + SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA); +#else + ETS_UART_INTR_ENABLE(); +#endif +} + + +//======================================================== +LOCAL void +uart0_write_char(char c) +{ + if (c == '\n') { + uart_tx_one_char(UART0, '\r'); + uart_tx_one_char(UART0, '\n'); + } else if (c == '\r') { + } else { + uart_tx_one_char(UART0, c); + } +} + +void ICACHE_FLASH_ATTR +UART_SetWordLength(uint8 uart_no, UartBitsNum4Char len) +{ + SET_PERI_REG_BITS(UART_CONF0(uart_no),UART_BIT_NUM,len,UART_BIT_NUM_S); +} + +void ICACHE_FLASH_ATTR +UART_SetStopBits(uint8 uart_no, UartStopBitsNum bit_num) +{ + SET_PERI_REG_BITS(UART_CONF0(uart_no),UART_STOP_BIT_NUM,bit_num,UART_STOP_BIT_NUM_S); +} + +void ICACHE_FLASH_ATTR +UART_SetLineInverse(uint8 uart_no, UART_LineLevelInverse inverse_mask) +{ + CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_LINE_INV_MASK); + SET_PERI_REG_MASK(UART_CONF0(uart_no), inverse_mask); +} + +void ICACHE_FLASH_ATTR +UART_SetParity(uint8 uart_no, UartParityMode Parity_mode) +{ + CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_PARITY |UART_PARITY_EN); + if(Parity_mode==NONE_BITS){ + }else{ + SET_PERI_REG_MASK(UART_CONF0(uart_no), Parity_mode|UART_PARITY_EN); + } +} + +void ICACHE_FLASH_ATTR +UART_SetBaudrate(uint8 uart_no,uint32 baud_rate) +{ + uart_div_modify(uart_no, UART_CLK_FREQ /baud_rate); +} + +void ICACHE_FLASH_ATTR +UART_SetFlowCtrl(uint8 uart_no,UART_HwFlowCtrl flow_ctrl,uint8 rx_thresh) +{ + if(flow_ctrl&USART_HardwareFlowControl_RTS){ + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); + SET_PERI_REG_BITS(UART_CONF1(uart_no),UART_RX_FLOW_THRHD,rx_thresh,UART_RX_FLOW_THRHD_S); + SET_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN); + }else{ + CLEAR_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN); + } + if(flow_ctrl&USART_HardwareFlowControl_CTS){ + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS); + SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN); + }else{ + CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN); + } +} + +void ICACHE_FLASH_ATTR +UART_WaitTxFifoEmpty(uint8 uart_no , uint32 time_out_us) //do not use if tx flow control enabled +{ + uint32 t_s = system_get_time(); + while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S)){ + + if(( system_get_time() - t_s )> time_out_us){ + break; + } + WRITE_PERI_REG(0X60000914, 0X73);//WTD + + } +} + + +bool ICACHE_FLASH_ATTR +UART_CheckOutputFinished(uint8 uart_no, uint32 time_out_us) +{ + uint32 t_start = system_get_time(); + uint8 tx_fifo_len; + uint32 tx_buff_len; + while(1){ + tx_fifo_len =( (READ_PERI_REG(UART_STATUS(uart_no))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT); + if(pTxBuffer){ + tx_buff_len = ((pTxBuffer->UartBuffSize)-(pTxBuffer->Space)); + }else{ + tx_buff_len = 0; + } + + if( tx_fifo_len==0 && tx_buff_len==0){ + return TRUE; + } + if( system_get_time() - t_start > time_out_us){ + return FALSE; + } + WRITE_PERI_REG(0X60000914, 0X73);//WTD + } +} + + +void ICACHE_FLASH_ATTR +UART_ResetFifo(uint8 uart_no) +{ + SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); + CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); +} + +void ICACHE_FLASH_ATTR +UART_ClearIntrStatus(uint8 uart_no,uint32 clr_mask) +{ + WRITE_PERI_REG(UART_INT_CLR(uart_no), clr_mask); +} + +void ICACHE_FLASH_ATTR +UART_SetIntrEna(uint8 uart_no,uint32 ena_mask) +{ + SET_PERI_REG_MASK(UART_INT_ENA(uart_no), ena_mask); +} + + +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); + } +} + + +//======================================================== + +// +///*test code*/ +//void ICACHE_FLASH_ATTR +//uart_init_2(UartBautRate uart0_br, UartBautRate uart1_br) +//{ +// // rom use 74880 baut_rate, here reinitialize +// UartDev.baut_rate = uart0_br; +// UartDev.exist_parity = STICK_PARITY_EN; +// UartDev.parity = EVEN_BITS; +// UartDev.stop_bits = ONE_STOP_BIT; +// UartDev.data_bits = EIGHT_BITS; +// +// uart_config(UART0); +// UartDev.baut_rate = uart1_br; +// uart_config(UART1); +// ETS_UART_INTR_ENABLE(); +// +// // install uart1 putc callback +// os_install_putc1((void *)uart1_write_char);//print output at UART1 +//} +// +// diff --git a/user/uart_asyncdrv.h- b/user/uart_asyncdrv.h- new file mode 100644 index 0000000..5730e00 --- /dev/null +++ b/user/uart_asyncdrv.h- @@ -0,0 +1,178 @@ +/* + * File : uart.h + * 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 . + */ +#ifndef UART_APP_H +#define UART_APP_H + +#include + +#define UART_TX_BUFFER_SIZE 512 //Ring buffer length of tx buffer +#define UART_RX_BUFFER_SIZE 512 //Ring buffer length of rx buffer + +#define UART_BUFF_EN 1 //use uart buffer , FOR UART0 +#define UART_SELFTEST 0 //set 1:enable the loop test demo for uart buffer, FOR UART0 + +#define UART_HW_RTS 0 //set 1: enable uart hw flow control RTS, PIN MTDO, FOR UART0 +#define UART_HW_CTS 0 //set1: enable uart hw flow contrl CTS , PIN MTCK, FOR UART0 + +#define UART0 0 +#define UART1 1 + +typedef enum { + FIVE_BITS = 0x0, + SIX_BITS = 0x1, + SEVEN_BITS = 0x2, + EIGHT_BITS = 0x3 +} UartBitsNum4Char; + +typedef enum { + ONE_STOP_BIT = 0x1, + ONE_HALF_STOP_BIT = 0x2, + TWO_STOP_BIT = 0x3 +} UartStopBitsNum; + +typedef enum { + NONE_BITS = 0x2, + ODD_BITS = 1, + EVEN_BITS = 0 +} UartParityMode; + +typedef enum { + STICK_PARITY_DIS = 0, + STICK_PARITY_EN = 1 +} UartExistParity; + +typedef enum { + UART_None_Inverse = 0x0, + UART_Rxd_Inverse = UART_RXD_INV, + UART_CTS_Inverse = UART_CTS_INV, + UART_Txd_Inverse = UART_TXD_INV, + UART_RTS_Inverse = UART_RTS_INV, +} UART_LineLevelInverse; + + +typedef enum { + BIT_RATE_300 = 300, + BIT_RATE_600 = 600, + BIT_RATE_1200 = 1200, + BIT_RATE_2400 = 2400, + BIT_RATE_4800 = 4800, + BIT_RATE_9600 = 9600, + BIT_RATE_19200 = 19200, + BIT_RATE_38400 = 38400, + BIT_RATE_57600 = 57600, + BIT_RATE_74880 = 74880, + BIT_RATE_115200 = 115200, + BIT_RATE_230400 = 230400, + BIT_RATE_460800 = 460800, + BIT_RATE_921600 = 921600, + BIT_RATE_1843200 = 1843200, + BIT_RATE_3686400 = 3686400, +} UartBautRate; + +typedef enum { + NONE_CTRL, + HARDWARE_CTRL, + XON_XOFF_CTRL +} UartFlowCtrl; + +typedef enum { + USART_HardwareFlowControl_None = 0x0, + USART_HardwareFlowControl_RTS = 0x1, + USART_HardwareFlowControl_CTS = 0x2, + USART_HardwareFlowControl_CTS_RTS = 0x3 +} UART_HwFlowCtrl; + +typedef enum { + EMPTY, + UNDER_WRITE, + WRITE_OVER +} RcvMsgBuffState; + +typedef struct { + uint32 RcvBuffSize; + uint8 *pRcvMsgBuff; + uint8 *pWritePos; + uint8 *pReadPos; + uint8 TrigLvl; //JLU: may need to pad + RcvMsgBuffState BuffState; +} RcvMsgBuff; + +typedef struct { + uint32 TrxBuffSize; + uint8 *pTrxBuff; +} TrxMsgBuff; + +typedef enum { + BAUD_RATE_DET, + WAIT_SYNC_FRM, + SRCH_MSG_HEAD, + RCV_MSG_BODY, + RCV_ESC_CHAR, +} RcvMsgState; + +typedef struct { + UartBautRate baut_rate; + UartBitsNum4Char data_bits; + UartExistParity exist_parity; + UartParityMode parity; + UartStopBitsNum stop_bits; + UartFlowCtrl flow_ctrl; + RcvMsgBuff rcv_buff; + TrxMsgBuff trx_buff; + RcvMsgState rcv_state; + int received; + int buff_uart_no; //indicate which uart use tx/rx buffer +} UartDevice; + +void uart_init(UartBautRate uart0_br, UartBautRate uart1_br); + +/////////////////////////////////////// +#define UART_FIFO_LEN 128 //define the tx fifo length +#define UART_TX_EMPTY_THRESH_VAL 0x10 + + +typedef enum { + RUN = 0, + BLOCK = 1, +} TCPState; + + +//============================================== +#define FUNC_UART0_CTS 4 +#define FUNC_U0CTS 4 +#define FUNC_U1TXD_BK 2 +#define UART_LINE_INV_MASK (0x3f<<19) +void UART_SetWordLength(uint8 uart_no, UartBitsNum4Char len); +void UART_SetStopBits(uint8 uart_no, UartStopBitsNum bit_num); +void UART_SetLineInverse(uint8 uart_no, UART_LineLevelInverse inverse_mask); +void UART_SetParity(uint8 uart_no, UartParityMode Parity_mode); +void UART_SetBaudrate(uint8 uart_no, uint32 baud_rate); +void UART_SetFlowCtrl(uint8 uart_no, UART_HwFlowCtrl flow_ctrl, uint8 rx_thresh); +void UART_WaitTxFifoEmpty(uint8 uart_no, uint32 time_out_us); //do not use if tx flow control enabled +void UART_ResetFifo(uint8 uart_no); +void UART_ClearIntrStatus(uint8 uart_no, uint32 clr_mask); +void UART_SetIntrEna(uint8 uart_no, uint32 ena_mask); +void UART_SetPrintPort(uint8 uart_no); +bool UART_CheckOutputFinished(uint8 uart_no, uint32 time_out_us); +//============================================== + +// Buffer functions +uint16 rx_buff_deq(char* pdata, uint16 data_len); +void tx_buff_enq(char* pdata, uint16 data_len); + +#endif + diff --git a/user/uart_buffer.c b/user/uart_buffer.c new file mode 100644 index 0000000..70965bc --- /dev/null +++ b/user/uart_buffer.c @@ -0,0 +1,251 @@ +// +// Created by MightyPork on 2017/08/24. +// + +#include "uart_buffer.h" +#include "uart_driver.h" +#include "uart_handler.h" +#include +#include + +#define UART_TX_BUFFER_SIZE 512 //Ring buffer length of tx buffer +#define UART_RX_BUFFER_SIZE 512 //Ring buffer length of rx buffer + +struct UartBuffer { + uint32 UartBuffSize; + uint8 *pUartBuff; + uint8 *pInPos; + uint8 *pOutPos; + uint16 Space; +}; + +static struct UartBuffer *pTxBuffer = NULL; +static struct UartBuffer *pRxBuffer = NULL; + +static struct UartBuffer *UART_AsyncBufferInit(uint32 buf_size); + +void ICACHE_FLASH_ATTR UART_AllocBuffers(void) +{ + pTxBuffer = UART_AsyncBufferInit(UART_TX_BUFFER_SIZE); + pRxBuffer = UART_AsyncBufferInit(UART_RX_BUFFER_SIZE); +} + +/****************************************************************************** + * FunctionName : Uart_Buf_Init + * Description : tx buffer enqueue: fill a first linked buffer + * Parameters : char *pdata - data point to be enqueue + * Returns : NONE +*******************************************************************************/ +static struct UartBuffer *ICACHE_FLASH_ATTR +UART_AsyncBufferInit(uint32 buf_size) +{ + uint32 heap_size = system_get_free_heap_size(); + if (heap_size <= buf_size) { + error("uart buf malloc fail, out of memory"); + return NULL; + } + else { + struct UartBuffer *pBuff = (struct UartBuffer *) os_malloc(sizeof(struct UartBuffer)); + pBuff->UartBuffSize = buf_size; + pBuff->pUartBuff = (uint8 *) os_malloc(pBuff->UartBuffSize); + pBuff->pInPos = pBuff->pUartBuff; + pBuff->pOutPos = pBuff->pUartBuff; + pBuff->Space = (uint16) pBuff->UartBuffSize; + return pBuff; + } +} + + +/** + * Copy data onto Buffer + * @param pCur - buffer + * @param pdata - data src + * @param data_len - data len + */ +static void UART_WriteToAsyncBuffer(struct UartBuffer *pCur, const char *pdata, uint16 data_len) +{ + if (data_len == 0) return; + + uint16 tail_len = (uint16) (pCur->pUartBuff + pCur->UartBuffSize - pCur->pInPos); + if (tail_len >= data_len) { //do not need to loop back the queue + os_memcpy(pCur->pInPos, pdata, data_len); + pCur->pInPos += (data_len); + pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize); + pCur->Space -= data_len; + } + else { + os_memcpy(pCur->pInPos, pdata, tail_len); + pCur->pInPos += (tail_len); + pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize); + pCur->Space -= tail_len; + os_memcpy(pCur->pInPos, pdata + tail_len, data_len - tail_len); + pCur->pInPos += (data_len - tail_len); + pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize); + pCur->Space -= (data_len - tail_len); + } + +} + +/****************************************************************************** + * FunctionName : uart_buf_free + * Description : deinit of the tx buffer + * Parameters : struct UartBuffer* pTxBuff - tx buffer struct pointer + * Returns : NONE +*******************************************************************************/ +void ICACHE_FLASH_ATTR UART_FreeAsyncBuffer(struct UartBuffer *pBuff) +{ + os_free(pBuff->pUartBuff); + os_free(pBuff); +} + +/** + * Retrieve some data from the RX buffer + * @param pdata - target + * @param data_len - max data to retrieve + * @return real nr of bytes retrieved + */ +uint16 ICACHE_FLASH_ATTR +UART_ReadAsync(char *pdata, uint16 data_len) +{ + uint16 buf_len = (uint16) (pRxBuffer->UartBuffSize - pRxBuffer->Space); + uint16 tail_len = (uint16) (pRxBuffer->pUartBuff + pRxBuffer->UartBuffSize - pRxBuffer->pOutPos); + uint16 len_tmp = 0; + len_tmp = ((data_len > buf_len) ? buf_len : data_len); + if (pRxBuffer->pOutPos <= pRxBuffer->pInPos) { + os_memcpy(pdata, pRxBuffer->pOutPos, len_tmp); + pRxBuffer->pOutPos += len_tmp; + pRxBuffer->Space += len_tmp; + } + else { + if (len_tmp > tail_len) { + os_memcpy(pdata, pRxBuffer->pOutPos, tail_len); + pRxBuffer->pOutPos += tail_len; + pRxBuffer->pOutPos = (pRxBuffer->pUartBuff + + (pRxBuffer->pOutPos - pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize); + pRxBuffer->Space += tail_len; + + os_memcpy(pdata + tail_len, pRxBuffer->pOutPos, len_tmp - tail_len); + pRxBuffer->pOutPos += (len_tmp - tail_len); + pRxBuffer->pOutPos = (pRxBuffer->pUartBuff + + (pRxBuffer->pOutPos - pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize); + pRxBuffer->Space += (len_tmp - tail_len); + } + else { + //os_printf("case 3 in rx deq\n\r"); + os_memcpy(pdata, pRxBuffer->pOutPos, len_tmp); + pRxBuffer->pOutPos += len_tmp; + pRxBuffer->pOutPos = (pRxBuffer->pUartBuff + + (pRxBuffer->pOutPos - pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize); + pRxBuffer->Space += len_tmp; + } + } + if (pRxBuffer->Space >= UART_FIFO_LEN) { + uart_rx_intr_enable(UART0); + } + return len_tmp; +} + +//move data from uart fifo to rx buffer +void UART_RxFifoDeq(void) +{ + uint8 fifo_len, buf_idx; + uint8 fifo_data; + fifo_len = (uint8) ((READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT); + if (fifo_len >= pRxBuffer->Space) { + os_printf("buf full!!!\n\r"); + } + else { + buf_idx = 0; + while (buf_idx < fifo_len) { + buf_idx++; + fifo_data = (uint8) (READ_PERI_REG(UART_FIFO(UART0)) & 0xFF); + *(pRxBuffer->pInPos++) = fifo_data; + if (pRxBuffer->pInPos == (pRxBuffer->pUartBuff + pRxBuffer->UartBuffSize)) { + pRxBuffer->pInPos = pRxBuffer->pUartBuff; + } + } + pRxBuffer->Space -= fifo_len; + if (pRxBuffer->Space >= UART_FIFO_LEN) { + //os_printf("after rx enq buf enough\n\r"); + uart_rx_intr_enable(UART0); + } + } +} + +/** + * Schedule data to be sent + * @param pdata + * @param data_len + */ +void ICACHE_FLASH_ATTR +UART_SendAsync(char *pdata, uint16 data_len) +{ + if (pTxBuffer == NULL) { + info("\n\rnull, create buffer struct\n\r"); + pTxBuffer = UART_AsyncBufferInit(UART_TX_BUFFER_SIZE); + if (pTxBuffer != NULL) { + UART_WriteToAsyncBuffer(pTxBuffer, pdata, data_len); + } + else { + error("uart tx MALLOC no buf \n\r"); + } + } + else { + if (data_len <= pTxBuffer->Space) { + UART_WriteToAsyncBuffer(pTxBuffer, pdata, data_len); + } + else { + error("UART TX BUF FULL!!!!\n\r"); + } + } + + // Here we enable TX empty interrupt that will take care of sending the content + SET_PERI_REG_MASK(UART_CONF1(UART0), (UART_TX_EMPTY_THRESH_VAL & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S); + SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA); +} + + +//-------------------------------- +static void UART_TxFifoEnq(struct UartBuffer *pTxBuff, uint8 data_len, uint8 uart_no) +{ + uint8 i; + for (i = 0; i < data_len; i++) { + WRITE_PERI_REG(UART_FIFO(uart_no), *(pTxBuff->pOutPos++)); + if (pTxBuff->pOutPos == (pTxBuff->pUartBuff + pTxBuff->UartBuffSize)) { + pTxBuff->pOutPos = pTxBuff->pUartBuff; + } + } + pTxBuff->pOutPos = (pTxBuff->pUartBuff + (pTxBuff->pOutPos - pTxBuff->pUartBuff) % pTxBuff->UartBuffSize); + pTxBuff->Space += data_len; +} + + +/****************************************************************************** + * FunctionName : TxFromBuffer + * Description : get data from the tx buffer and fill the uart tx fifo, co-work with the uart fifo empty interrupt + * Parameters : uint8 uart_no - uart port num + * Returns : NONE +*******************************************************************************/ +void UART_DispatchFromTxBuffer(uint8 uart_no) +{ + const uint8 tx_fifo_len = (uint8) ((READ_PERI_REG(UART_STATUS(uart_no)) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT); + const uint8 fifo_remain = (uint8) (UART_FIFO_LEN - tx_fifo_len); + uint8 len_tmp; + uint16 data_len; + + if (pTxBuffer) { + data_len = (uint8) (pTxBuffer->UartBuffSize - pTxBuffer->Space); + if (data_len > fifo_remain) { + len_tmp = fifo_remain; + UART_TxFifoEnq(pTxBuffer, len_tmp, uart_no); + SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA); + } + else { + len_tmp = (uint8) data_len; + UART_TxFifoEnq(pTxBuffer, len_tmp, uart_no); + } + } + else { + error("pTxBuff null \n\r"); + } +} diff --git a/user/uart_buffer.h b/user/uart_buffer.h new file mode 100644 index 0000000..f8beedf --- /dev/null +++ b/user/uart_buffer.h @@ -0,0 +1,24 @@ +// +// Created by MightyPork on 2017/08/24. +// + +#ifndef ESP_VT100_FIRMWARE_UART_BUFFER_H +#define ESP_VT100_FIRMWARE_UART_BUFFER_H + +#include + +// the init func +void ICACHE_FLASH_ATTR UART_AllocBuffers(void); + +// read from rx buffer +uint16 ICACHE_FLASH_ATTR UART_ReadAsync(char *pdata, uint16 data_len); + +// write to tx buffer +void ICACHE_FLASH_ATTR UART_SendAsync(char *pdata, uint16 data_len); + +//move data from uart fifo to rx buffer +void UART_RxFifoDeq(void); +//move data from uart tx buffer to fifo +void UART_DispatchFromTxBuffer(uint8 uart_no); + +#endif //ESP_VT100_FIRMWARE_UART_BUFFER_H diff --git a/user/uart_handler.c b/user/uart_handler.c index 54d51b3..e969bae 100755 --- a/user/uart_handler.c +++ b/user/uart_handler.c @@ -14,6 +14,7 @@ #include #include "uart_driver.h" #include "uart_handler.h" +#include "uart_buffer.h" // messy irq/task based UART handling below @@ -57,6 +58,8 @@ void ICACHE_FLASH_ATTR UART_Init(void) /** Configure Rx on UART0 */ void ICACHE_FLASH_ATTR UART_SetupAsyncReceiver(void) { + UART_AllocBuffers(); + // Start the Rx reading task system_os_task(uart_recvTask, uart_recvTaskPrio, uart_recvTaskQueue, uart_recvTaskQueueLen); // set handler @@ -79,6 +82,9 @@ void ICACHE_FLASH_ATTR UART_SetupAsyncReceiver(void) // Enable IRQ in Extensa ETS_UART_INTR_ENABLE(); + + // Start the periodic reading event + system_os_post(uart_recvTaskPrio, 5, 0); } @@ -103,30 +109,41 @@ void uart_rx_intr_enable(uint8 uart_no) */ #define UART_GetRxFifoCount(uart_no) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT) - -void ICACHE_FLASH_ATTR UART_PollRx(void) -{ - uint8 fifo_len = (uint8) UART_GetRxFifoCount(UART0); - - for (uint8 idx = 0; idx < fifo_len; idx++) { - uint8 d_tmp = (uint8) (READ_PERI_REG(UART_FIFO(UART0)) & 0xFF); - UART_HandleRxByte(d_tmp); - } -} +// +//void ICACHE_FLASH_ATTR UART_PollRx(void) +//{ +// uint8 fifo_len = (uint8) UART_GetRxFifoCount(UART0); +// +// for (uint8 idx = 0; idx < fifo_len; idx++) { +// uint8 d_tmp = (uint8) (READ_PERI_REG(UART_FIFO(UART0)) & 0xFF); +// UART_HandleRxByte(d_tmp); +// } +//} static void ICACHE_FLASH_ATTR uart_recvTask(os_event_t *events) { + static char buf[200]; + if (events->sig == 0) { - UART_PollRx(); + UART_RxFifoDeq(); // clear irq flags WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR | UART_RXFIFO_TOUT_INT_CLR); // enable rx irq again uart_rx_intr_enable(UART0); - } else if (events->sig == 1) { + } + else if (events->sig == 1) { // ??? } + else if (events->sig == 5) { + // Send a few to the parser... + int bytes = UART_ReadAsync(buf, 200); + for (uint8 idx = 0; idx < bytes; idx++) { + UART_HandleRxByte(buf[idx]); + } + system_os_post(uart_recvTaskPrio, 5, 0); // call me later + } } @@ -169,6 +186,8 @@ uart0_rx_intr_handler(void *para) if (status_reg & UART_TXFIFO_EMPTY_INT_ST) { CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA); + UART_DispatchFromTxBuffer(UART0); +// WRITE_PERI_REG(UART_INT_CLR(UART0), UART_TXFIFO_EMPTY_INT_CLR); - is called by the dispatch func if more data is to be sent. } if (status_reg & UART_RXFIFO_OVF_INT_ST) { diff --git a/user/uart_handler.h b/user/uart_handler.h index 2d5e57f..5200a91 100755 --- a/user/uart_handler.h +++ b/user/uart_handler.h @@ -18,10 +18,11 @@ void UART_Init(void); /** Configure async Rx on UART0 */ void UART_SetupAsyncReceiver(void); -/** User must provide this func for handling received bytes */ +///** User must provide this func for handling received bytes */ extern void UART_HandleRxByte(char c); -/** Poll uart manually while waiting for something */ -void UART_PollRx(void); +void uart_rx_intr_disable(uint8 uart_no); + +void uart_rx_intr_enable(uint8 uart_no); #endif