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/esphttpdconfig.mk b/esphttpdconfig.mk
index e29783b..16155c4 100644
--- a/esphttpdconfig.mk
+++ b/esphttpdconfig.mk
@@ -51,4 +51,4 @@ GLOBAL_CFLAGS = \
-DDEBUG_ANSI_NOIMPL=0 \
-DHTTPD_MAX_BACKLOG_SIZE=8192 \
-DDEBUG_INPUT=0 \
- -DDEBUG_HEAP=1 \
+ -DDEBUG_HEAP=1
diff --git a/user/ansi_parser_callbacks.c b/user/ansi_parser_callbacks.c
index 35c9ea6..58a121f 100644
--- a/user/ansi_parser_callbacks.c
+++ b/user/ansi_parser_callbacks.c
@@ -10,6 +10,7 @@
#include "uart_driver.h"
#include "cgi_sockets.h"
#include "version.h"
+#include "uart_buffer.h"
/**
* Send a response to UART0
@@ -18,7 +19,8 @@
void ICACHE_FLASH_ATTR
apars_respond(const char *str)
{
- UART_WriteString(UART0, str, UART_TIMEOUT_US);
+ UART_SendAsync(str, -1);
+ //UART_WriteString(UART0, str, UART_TIMEOUT_US);
}
/**
diff --git a/user/ascii.h b/user/ascii.h
index 55f5cdd..ac191f5 100644
--- a/user/ascii.h
+++ b/user/ascii.h
@@ -40,6 +40,10 @@ enum ASCII_CODES {
US = 31,
SP = 32,
DEL = 127,
+
+ // aliases
+ XON = DC1,
+ XOFF = DC3,
};
#endif //ESP_VT100_FIRMWARE_ASCII_H
diff --git a/user/cgi_sockets.c b/user/cgi_sockets.c
index 9a49cbc..a50e68f 100644
--- a/user/cgi_sockets.c
+++ b/user/cgi_sockets.c
@@ -5,6 +5,7 @@
#include "cgi_sockets.h"
#include "uart_driver.h"
#include "screen.h"
+#include "uart_buffer.h"
#define SOCK_BUF_LEN 1024
static char sock_buff[SOCK_BUF_LEN];
@@ -113,13 +114,13 @@ void ICACHE_FLASH_ATTR updateSockRx(Websock *ws, char *data, int len, int flags)
if (strstarts(data, "STR:")) {
// pass string verbatim
- UART_WriteString(UART0, data+4, UART_TIMEOUT_US);
+ UART_SendAsync(data+4, -1);
}
else if (strstarts(data, "BTN:")) {
// send button as low ASCII value 1-9
- int btnNum = data[4] - '0';
+ u8 btnNum = (u8) (data[4] - '0');
if (btnNum > 0 && btnNum < 10) {
- UART_WriteChar(UART0, (unsigned char)btnNum, UART_TIMEOUT_US);
+ UART_SendAsync((const char *) &btnNum, 1);
}
}
else if (strstarts(data, "TAP:")) {
diff --git a/user/serial.c b/user/serial.c
index 056a86c..67e7ba3 100644
--- a/user/serial.c
+++ b/user/serial.c
@@ -30,7 +30,7 @@ static void buf_pop(void *unused)
lb_ls++;
if (lb_ls >= LOGBUF_SIZE) lb_ls = 0;
- if (OK == UART_WriteCharCRLF(UART1, logbuf[lb_ls], 2000)) {
+ if (OK == UART_WriteCharCRLF(UART1, logbuf[lb_ls], 1000)) {
quantity--;
} else {
// try another time
@@ -40,6 +40,11 @@ static void buf_pop(void *unused)
}
}
+LOCAL void my_putc(char c)
+{
+ UART_WriteCharCRLF(UART1, (u8) c, 10);
+}
+
/**
* Init the serial ports
*/
@@ -50,8 +55,9 @@ void ICACHE_FLASH_ATTR serialInitBase(void)
UART_SetParity(UART1, PARITY_NONE);
UART_SetStopBits(UART1, ONE_STOP_BIT);
UART_SetBaudrate(UART1, BIT_RATE_115200);
- //UART_SetPrintPort(UART1);
+ UART_SetPrintPort(UART1);
os_install_putc1(buf_putc);
+ //os_install_putc1(my_putc);
UART_SetupAsyncReceiver();
// 1 ms timer
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..952fde1
--- /dev/null
+++ b/user/uart_buffer.c
@@ -0,0 +1,259 @@
+//
+// 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 256 //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);
+}
+
+u16 ICACHE_FLASH_ATTR UART_AsyncRxCount(void)
+{
+ return (u16) (pRxBuffer->UartBuffSize - pRxBuffer->Space);
+}
+
+/**
+ * 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;
+ }
+ }
+ // this maybe shouldnt be here??
+ if (pRxBuffer->Space >= UART_FIFO_LEN) {
+ uart_rx_intr_enable(UART0);
+ }
+ return len_tmp;
+}
+
+//move data from uart fifo to rx buffer
+void UART_RxFifoCollect(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) {
+ UART_WriteChar(UART1, '%', 100);
+ }
+ 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) {
+ uart_rx_intr_enable(UART0);
+ }
+ }
+}
+
+/**
+ * Schedule data to be sent
+ * @param pdata
+ * @param data_len - can be -1 for strlen
+ */
+void ICACHE_FLASH_ATTR
+UART_SendAsync(const char *pdata, int16_t data_len)
+{
+ u16 real_len = (u16) data_len;
+ if (data_len <= 0) real_len = (u16) strlen(pdata);
+
+// if (pTxBuffer == NULL) {
+// printf("init tx buf\n\r");
+// pTxBuffer = UART_AsyncBufferInit(UART_TX_BUFFER_SIZE);
+// if (pTxBuffer != NULL) {
+// UART_WriteToAsyncBuffer(pTxBuffer, pdata, real_len);
+// }
+// else {
+// printf("tx alloc fail\r\n");
+// }
+// }
+// else {
+ if (real_len <= pTxBuffer->Space) {
+ UART_WriteToAsyncBuffer(pTxBuffer, pdata, real_len);
+ }
+ else {
+ UART_WriteChar(UART1, '^', 100);
+ }
+// }
+
+ // 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..f11cfd4
--- /dev/null
+++ b/user/uart_buffer.h
@@ -0,0 +1,26 @@
+//
+// 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 UART_AllocBuffers(void);
+
+// read from rx buffer
+uint16 UART_ReadAsync(char *pdata, uint16 data_len);
+
+// write to tx buffer
+void UART_SendAsync(const char *pdata, int16_t data_len);
+
+//move data from uart fifo to rx buffer
+void UART_RxFifoCollect(void);
+//move data from uart tx buffer to fifo
+void UART_DispatchFromTxBuffer(uint8 uart_no);
+
+u16 UART_AsyncRxCount(void);
+
+#endif //ESP_VT100_FIRMWARE_UART_BUFFER_H
diff --git a/user/uart_driver.c b/user/uart_driver.c
index 9425113..a210668 100755
--- a/user/uart_driver.c
+++ b/user/uart_driver.c
@@ -84,7 +84,7 @@ bool ICACHE_FLASH_ATTR UART_CheckOutputFinished(UARTn uart_no, uint32 time_out_u
uint8 tx_fifo_len;
while (1) {
- tx_fifo_len = UART_TxQueLen(uart_no);
+ tx_fifo_len = UART_TxFifoCount(uart_no);
// TODO If using output circbuf, check if empty
@@ -162,7 +162,7 @@ STATUS UART_WriteChar(UARTn uart_no, uint8 c, uint32 timeout_us)
uint32 t_s = system_get_time();
while ((system_get_time() - t_s) < timeout_us) {
- uint8 fifo_cnt = UART_TxQueLen(uart_no);
+ uint8 fifo_cnt = UART_TxFifoCount(uart_no);
if (fifo_cnt < UART_TX_FULL_THRESH_VAL) {
WRITE_PERI_REG(UART_FIFO(uart_no), c);
diff --git a/user/uart_driver.h b/user/uart_driver.h
index 8a95c0d..c3d9bfd 100755
--- a/user/uart_driver.h
+++ b/user/uart_driver.h
@@ -172,8 +172,8 @@ extern UartDevice UartDev;
//==============================================
// FIFO used count
-#define UART_TxQueLen(uart_no) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT)
-#define UART_RxQueLen(uart_no) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT)
+#define UART_TxFifoCount(uart_no) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT)
+#define UART_RxFifoCount(uart_no) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT)
STATUS UART_WriteCharCRLF(UARTn uart_no, uint8 c, uint32 timeout_us);
STATUS UART_WriteChar(UARTn uart_no, uint8 c, uint32 timeout_us);
diff --git a/user/uart_handler.c b/user/uart_handler.c
index 54d51b3..59d8f67 100755
--- a/user/uart_handler.c
+++ b/user/uart_handler.c
@@ -14,15 +14,26 @@
#include
#include "uart_driver.h"
#include "uart_handler.h"
+#include "uart_buffer.h"
// messy irq/task based UART handling below
static void uart0_rx_intr_handler(void *para);
+
static void uart_recvTask(os_event_t *events);
+static void uart_processTask(os_event_t *events);
+
+// Those heavily affect the byte loss ratio
+#define PROCESS_CHUNK_LEN 1
+#define FIFO_FULL_THRES 4
#define uart_recvTaskPrio 1
-#define uart_recvTaskQueueLen 15
+#define uart_recvTaskQueueLen 25
static os_event_t uart_recvTaskQueue[uart_recvTaskQueueLen];
+//
+#define uart_processTaskPrio 0
+#define uart_processTaskQueueLen 25
+static os_event_t uart_processTaskQueue[uart_processTaskQueueLen];
/** Clear the fifos */
void ICACHE_FLASH_ATTR clear_rxtx(int uart_no)
@@ -57,16 +68,20 @@ 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);
+ system_os_task(uart_processTask, uart_processTaskPrio, uart_processTaskQueue, uart_processTaskQueueLen);
+
// set handler
ETS_UART_INTR_ATTACH((void *)uart0_rx_intr_handler, &(UartDev.rcv_buff)); // the buf will be used as an arg
// fifo threshold config (max: UART_RXFIFO_FULL_THRHD = 127)
- uint32_t conf = ((90) << UART_RXFIFO_FULL_THRHD_S);
+ uint32_t conf = ((FIFO_FULL_THRES & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S);
conf |= ((0x10 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S);
// timeout config
- conf |= ((0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S); // timeout threshold
+ conf |= ((0x06 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S); // timeout threshold
conf |= UART_RX_TOUT_EN; // enable timeout
WRITE_PERI_REG(UART_CONF1(UART0), conf);
@@ -85,48 +100,80 @@ void ICACHE_FLASH_ATTR UART_SetupAsyncReceiver(void)
// ---- async receive stuff ----
-void uart_rx_intr_disable(uint8 uart_no)
-{
- CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
-}
-
-
-void uart_rx_intr_enable(uint8 uart_no)
-{
- SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
-}
+//
+//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);
+// }
+//}
/**
- * @brief get number of bytes in UART tx fifo
- * @param UART number
+ * This is the system task handling UART Rx bytes.
+ * The function must be re-entrant.
+ *
+ * @param events
*/
-#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)
+static void uart_recvTask(os_event_t *events)
{
- 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);
- }
-}
-
+//#define PROCESS_CHUNK_LEN 64
+// static char buf[PROCESS_CHUNK_LEN];
-static void ICACHE_FLASH_ATTR uart_recvTask(os_event_t *events)
-{
if (events->sig == 0) {
- UART_PollRx();
+ UART_RxFifoCollect();
// 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) {
+
+ // Trigger the Reading task
+ system_os_post(uart_processTaskPrio, 5, 0);
+ }
+ else if (events->sig == 1) {
// ???
}
+// else if (events->sig == 5) {
+// // Send a few to the parser...
+// int bytes = UART_ReadAsync(buf, PROCESS_CHUNK_LEN);
+// for (uint8 idx = 0; idx < bytes; idx++) {
+// UART_HandleRxByte(buf[idx]);
+// }
+//
+// // ask for another run
+// if (UART_AsyncRxCount() > 0) {
+// system_os_post(uart_recvTaskPrio, 5, 0);
+// }
+// }
+}
+
+
+/**
+ * This is the system task handling UART Rx bytes.
+ * The function must be re-entrant.
+ *
+ * @param events
+ */
+static void uart_processTask(os_event_t *events)
+{
+ static char buf[PROCESS_CHUNK_LEN];
+
+ if (events->sig == 5) {
+ // Send a few to the parser...
+ int bytes = UART_ReadAsync(buf, PROCESS_CHUNK_LEN);
+ for (uint8 idx = 0; idx < bytes; idx++) {
+ UART_HandleRxByte(buf[idx]);
+ }
+
+ // ask for another run
+ if (UART_AsyncRxCount() > 0) {
+ system_os_post(uart_processTaskPrio, 5, 0);
+ }
+ }
}
@@ -155,7 +202,7 @@ uart0_rx_intr_handler(void *para)
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
// run handler
- system_os_post(uart_recvTaskPrio, 0, 0); /* -> notify the polling thread */
+ system_os_post(uart_recvTaskPrio, 0, 1); /* -> notify the polling thread */
}
if (status_reg & UART_RXFIFO_TOUT_INT_ST) {
@@ -169,9 +216,14 @@ 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) {
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_OVF_INT_CLR);
+
+ // overflow error
+ UART_WriteChar(UART1, '!', 100);
}
}
diff --git a/user/uart_handler.h b/user/uart_handler.h
index 2d5e57f..80ef4e6 100755
--- a/user/uart_handler.h
+++ b/user/uart_handler.h
@@ -21,7 +21,22 @@ void UART_SetupAsyncReceiver(void);
/** 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);
+static inline void uart_rx_intr_disable(uint8 uart_no)
+{
+ CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
+}
+
+static inline void uart_rx_intr_enable(uint8 uart_no)
+{
+ SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA | UART_RXFIFO_TOUT_INT_ENA);
+}
+
+/**
+ * @brief get number of bytes in UART tx fifo
+ * @param UART number
+ */
+static inline u8 UART_GetRxFifoCount(u8 uart_no) {
+ return (u8) ((READ_PERI_REG(UART_STATUS((uart_no))) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT);
+}
#endif