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_buffer.c b/user/uart_buffer.c index 70965bc..952fde1 100644 --- a/user/uart_buffer.c +++ b/user/uart_buffer.c @@ -8,7 +8,7 @@ #include #include -#define UART_TX_BUFFER_SIZE 512 //Ring buffer length of tx buffer +#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 { @@ -83,7 +83,6 @@ static void UART_WriteToAsyncBuffer(struct UartBuffer *pCur, const char *pdata, pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize); pCur->Space -= (data_len - tail_len); } - } /****************************************************************************** @@ -98,6 +97,11 @@ void ICACHE_FLASH_ATTR UART_FreeAsyncBuffer(struct UartBuffer *pBuff) 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 @@ -139,6 +143,7 @@ UART_ReadAsync(char *pdata, uint16 data_len) pRxBuffer->Space += len_tmp; } } + // this maybe shouldnt be here?? if (pRxBuffer->Space >= UART_FIFO_LEN) { uart_rx_intr_enable(UART0); } @@ -146,13 +151,13 @@ UART_ReadAsync(char *pdata, uint16 data_len) } //move data from uart fifo to rx buffer -void UART_RxFifoDeq(void) +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) { - os_printf("buf full!!!\n\r"); + UART_WriteChar(UART1, '%', 100); } else { buf_idx = 0; @@ -165,8 +170,8 @@ void UART_RxFifoDeq(void) } } pRxBuffer->Space -= fifo_len; + if (pRxBuffer->Space >= UART_FIFO_LEN) { - //os_printf("after rx enq buf enough\n\r"); uart_rx_intr_enable(UART0); } } @@ -175,29 +180,32 @@ void UART_RxFifoDeq(void) /** * Schedule data to be sent * @param pdata - * @param data_len + * @param data_len - can be -1 for strlen */ void ICACHE_FLASH_ATTR -UART_SendAsync(char *pdata, uint16 data_len) +UART_SendAsync(const char *pdata, int16_t 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); + 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 { - error("UART TX BUF FULL!!!!\n\r"); + 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); @@ -233,7 +241,7 @@ void UART_DispatchFromTxBuffer(uint8 uart_no) uint8 len_tmp; uint16 data_len; - if (pTxBuffer) { +// if (pTxBuffer) { data_len = (uint8) (pTxBuffer->UartBuffSize - pTxBuffer->Space); if (data_len > fifo_remain) { len_tmp = fifo_remain; @@ -244,8 +252,8 @@ void UART_DispatchFromTxBuffer(uint8 uart_no) len_tmp = (uint8) data_len; UART_TxFifoEnq(pTxBuffer, len_tmp, uart_no); } - } - else { - error("pTxBuff null \n\r"); - } +// } +// else { +// error("pTxBuff null \n\r"); +// } } diff --git a/user/uart_buffer.h b/user/uart_buffer.h index f8beedf..f11cfd4 100644 --- a/user/uart_buffer.h +++ b/user/uart_buffer.h @@ -8,17 +8,19 @@ #include // the init func -void ICACHE_FLASH_ATTR UART_AllocBuffers(void); +void UART_AllocBuffers(void); // read from rx buffer -uint16 ICACHE_FLASH_ATTR UART_ReadAsync(char *pdata, uint16 data_len); +uint16 UART_ReadAsync(char *pdata, uint16 data_len); // write to tx buffer -void ICACHE_FLASH_ATTR UART_SendAsync(char *pdata, uint16 data_len); +void UART_SendAsync(const char *pdata, int16_t data_len); //move data from uart fifo to rx buffer -void UART_RxFifoDeq(void); +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 e969bae..59d8f67 100755 --- a/user/uart_handler.c +++ b/user/uart_handler.c @@ -19,11 +19,21 @@ // 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) @@ -62,14 +72,16 @@ void ICACHE_FLASH_ATTR UART_SetupAsyncReceiver(void) // 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); @@ -82,32 +94,12 @@ 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); } // ---- 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); -} - - -/** - * @brief get number of bytes in UART tx fifo - * @param UART number - */ -#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) @@ -120,29 +112,67 @@ void uart_rx_intr_enable(uint8 uart_no) // } //} - -static void ICACHE_FLASH_ATTR uart_recvTask(os_event_t *events) +/** + * This is the system task handling UART Rx bytes. + * The function must be re-entrant. + * + * @param events + */ +static void uart_recvTask(os_event_t *events) { - static char buf[200]; +//#define PROCESS_CHUNK_LEN 64 +// static char buf[PROCESS_CHUNK_LEN]; if (events->sig == 0) { - UART_RxFifoDeq(); + 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); + + // Trigger the Reading task + system_os_post(uart_processTaskPrio, 5, 0); } else if (events->sig == 1) { // ??? } - else if (events->sig == 5) { +// 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, 200); + int bytes = UART_ReadAsync(buf, PROCESS_CHUNK_LEN); for (uint8 idx = 0; idx < bytes; idx++) { UART_HandleRxByte(buf[idx]); } - system_os_post(uart_recvTaskPrio, 5, 0); // call me later + + // ask for another run + if (UART_AsyncRxCount() > 0) { + system_os_post(uart_processTaskPrio, 5, 0); + } } } @@ -172,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) { @@ -187,10 +217,13 @@ 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. +// 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 5200a91..80ef4e6 100755 --- a/user/uart_handler.h +++ b/user/uart_handler.h @@ -18,11 +18,25 @@ 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); -void uart_rx_intr_disable(uint8 uart_no); +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); +} -void uart_rx_intr_enable(uint8 uart_no); +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