added async buffers for uart0, maybe improved byte drop ratio

pull/111/merge
Ondřej Hruška 7 years ago
parent acd8801d33
commit 357c81ba07
  1. 2
      esphttpdconfig.mk
  2. 4
      user/ansi_parser_callbacks.c
  3. 4
      user/ascii.h
  4. 7
      user/cgi_sockets.c
  5. 10
      user/serial.c
  6. 62
      user/uart_buffer.c
  7. 10
      user/uart_buffer.h
  8. 4
      user/uart_driver.c
  9. 4
      user/uart_driver.h
  10. 97
      user/uart_handler.c
  11. 20
      user/uart_handler.h

@ -51,4 +51,4 @@ GLOBAL_CFLAGS = \
-DDEBUG_ANSI_NOIMPL=0 \
-DHTTPD_MAX_BACKLOG_SIZE=8192 \
-DDEBUG_INPUT=0 \
-DDEBUG_HEAP=1 \
-DDEBUG_HEAP=1

@ -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);
}
/**

@ -40,6 +40,10 @@ enum ASCII_CODES {
US = 31,
SP = 32,
DEL = 127,
// aliases
XON = DC1,
XOFF = DC3,
};
#endif //ESP_VT100_FIRMWARE_ASCII_H

@ -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:")) {

@ -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

@ -8,7 +8,7 @@
#include <esp8266.h>
#include <uart_register.h>
#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");
// }
}

@ -8,17 +8,19 @@
#include <esp8266.h>
// 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

@ -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);

@ -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);

@ -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);
}
}

@ -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

Loading…
Cancel
Save