|
|
@ -8,8 +8,8 @@ |
|
|
|
#include <esp8266.h> |
|
|
|
#include <esp8266.h> |
|
|
|
#include <uart_register.h> |
|
|
|
#include <uart_register.h> |
|
|
|
|
|
|
|
|
|
|
|
#define UART_TX_BUFFER_SIZE 512 //Ring buffer length of tx buffer
|
|
|
|
//#define buf_dbg(format, ...) printf(format "\r\n", ##__VA_ARGS__)
|
|
|
|
#define UART_RX_BUFFER_SIZE 600 //Ring buffer length of rx buffer
|
|
|
|
#define buf_dbg(format, ...) (void)format |
|
|
|
|
|
|
|
|
|
|
|
struct UartBuffer { |
|
|
|
struct UartBuffer { |
|
|
|
uint32 UartBuffSize; |
|
|
|
uint32 UartBuffSize; |
|
|
@ -22,12 +22,15 @@ struct UartBuffer { |
|
|
|
static struct UartBuffer *pTxBuffer = NULL; |
|
|
|
static struct UartBuffer *pTxBuffer = NULL; |
|
|
|
static struct UartBuffer *pRxBuffer = NULL; |
|
|
|
static struct UartBuffer *pRxBuffer = NULL; |
|
|
|
|
|
|
|
|
|
|
|
static struct UartBuffer *UART_AsyncBufferInit(uint32 buf_size); |
|
|
|
static u8 rxArray[UART_RX_BUFFER_SIZE]; |
|
|
|
|
|
|
|
static u8 txArray[UART_TX_BUFFER_SIZE]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct UartBuffer *UART_AsyncBufferInit(uint32 buf_size, u8 *buffer); |
|
|
|
|
|
|
|
|
|
|
|
void ICACHE_FLASH_ATTR UART_AllocBuffers(void) |
|
|
|
void ICACHE_FLASH_ATTR UART_AllocBuffers(void) |
|
|
|
{ |
|
|
|
{ |
|
|
|
pTxBuffer = UART_AsyncBufferInit(UART_TX_BUFFER_SIZE); |
|
|
|
pTxBuffer = UART_AsyncBufferInit(UART_TX_BUFFER_SIZE, txArray); |
|
|
|
pRxBuffer = UART_AsyncBufferInit(UART_RX_BUFFER_SIZE); |
|
|
|
pRxBuffer = UART_AsyncBufferInit(UART_RX_BUFFER_SIZE, rxArray); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
/******************************************************************************
|
|
|
@ -37,7 +40,7 @@ void ICACHE_FLASH_ATTR UART_AllocBuffers(void) |
|
|
|
* Returns : NONE |
|
|
|
* Returns : NONE |
|
|
|
*******************************************************************************/ |
|
|
|
*******************************************************************************/ |
|
|
|
static struct UartBuffer *ICACHE_FLASH_ATTR |
|
|
|
static struct UartBuffer *ICACHE_FLASH_ATTR |
|
|
|
UART_AsyncBufferInit(uint32 buf_size) |
|
|
|
UART_AsyncBufferInit(uint32 buf_size, u8 *buffer) |
|
|
|
{ |
|
|
|
{ |
|
|
|
uint32 heap_size = system_get_free_heap_size(); |
|
|
|
uint32 heap_size = system_get_free_heap_size(); |
|
|
|
if (heap_size <= buf_size) { |
|
|
|
if (heap_size <= buf_size) { |
|
|
@ -47,7 +50,7 @@ UART_AsyncBufferInit(uint32 buf_size) |
|
|
|
else { |
|
|
|
else { |
|
|
|
struct UartBuffer *pBuff = (struct UartBuffer *) malloc(sizeof(struct UartBuffer)); |
|
|
|
struct UartBuffer *pBuff = (struct UartBuffer *) malloc(sizeof(struct UartBuffer)); |
|
|
|
pBuff->UartBuffSize = buf_size; |
|
|
|
pBuff->UartBuffSize = buf_size; |
|
|
|
pBuff->pUartBuff = (uint8 *) malloc(pBuff->UartBuffSize); |
|
|
|
pBuff->pUartBuff = buffer != NULL ? buffer : (uint8 *) malloc(pBuff->UartBuffSize); |
|
|
|
pBuff->pInPos = pBuff->pUartBuff; |
|
|
|
pBuff->pInPos = pBuff->pUartBuff; |
|
|
|
pBuff->pOutPos = pBuff->pUartBuff; |
|
|
|
pBuff->pOutPos = pBuff->pUartBuff; |
|
|
|
pBuff->Space = (uint16) pBuff->UartBuffSize; |
|
|
|
pBuff->Space = (uint16) pBuff->UartBuffSize; |
|
|
@ -55,6 +58,13 @@ UART_AsyncBufferInit(uint32 buf_size) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void ICACHE_FLASH_ATTR |
|
|
|
|
|
|
|
UART_AsyncBufferReset(struct UartBuffer *pBuff) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
pBuff->pInPos = pBuff->pUartBuff; |
|
|
|
|
|
|
|
pBuff->pOutPos = pBuff->pUartBuff; |
|
|
|
|
|
|
|
pBuff->Space = (uint16) pBuff->UartBuffSize; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Copy data onto Buffer |
|
|
|
* Copy data onto Buffer |
|
|
@ -67,23 +77,30 @@ UART_WriteToAsyncBuffer(struct UartBuffer *pCur, const char *pdata, uint16 data_ |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (data_len == 0) return; |
|
|
|
if (data_len == 0) return; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buf_dbg("WTAB %d, space %d", data_len, pCur->Space); |
|
|
|
|
|
|
|
|
|
|
|
uint16 tail_len = (uint16) (pCur->pUartBuff + pCur->UartBuffSize - pCur->pInPos); |
|
|
|
uint16 tail_len = (uint16) (pCur->pUartBuff + pCur->UartBuffSize - pCur->pInPos); |
|
|
|
if (tail_len >= data_len) { //do not need to loop back the queue
|
|
|
|
if (tail_len >= data_len) { //do not need to loop back the queue
|
|
|
|
|
|
|
|
buf_dbg("tail %d, no fold", tail_len); |
|
|
|
memcpy(pCur->pInPos, pdata, data_len); |
|
|
|
memcpy(pCur->pInPos, pdata, data_len); |
|
|
|
pCur->pInPos += (data_len); |
|
|
|
pCur->pInPos += (data_len); |
|
|
|
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize); |
|
|
|
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize); |
|
|
|
pCur->Space -= data_len; |
|
|
|
pCur->Space -= data_len; |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
|
|
|
|
buf_dbg("tail only %d, folding", tail_len); |
|
|
|
memcpy(pCur->pInPos, pdata, tail_len); |
|
|
|
memcpy(pCur->pInPos, pdata, tail_len); |
|
|
|
|
|
|
|
buf_dbg("chunk 1, %d", tail_len); |
|
|
|
pCur->pInPos += (tail_len); |
|
|
|
pCur->pInPos += (tail_len); |
|
|
|
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize); |
|
|
|
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize); |
|
|
|
pCur->Space -= tail_len; |
|
|
|
pCur->Space -= tail_len; |
|
|
|
|
|
|
|
buf_dbg("chunk 2, %d", data_len - tail_len); |
|
|
|
memcpy(pCur->pInPos, pdata + tail_len, data_len - tail_len); |
|
|
|
memcpy(pCur->pInPos, pdata + tail_len, data_len - tail_len); |
|
|
|
pCur->pInPos += (data_len - tail_len); |
|
|
|
pCur->pInPos += (data_len - tail_len); |
|
|
|
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize); |
|
|
|
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize); |
|
|
|
pCur->Space -= (data_len - tail_len); |
|
|
|
pCur->Space -= (data_len - tail_len); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
buf_dbg("new space %d", pCur->Space); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
/******************************************************************************
|
|
|
@ -158,9 +175,8 @@ void UART_RxFifoCollect(void) |
|
|
|
uint8 fifo_data; |
|
|
|
uint8 fifo_data; |
|
|
|
fifo_len = (uint8) ((READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT); |
|
|
|
fifo_len = (uint8) ((READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT); |
|
|
|
if (fifo_len >= pRxBuffer->Space) { |
|
|
|
if (fifo_len >= pRxBuffer->Space) { |
|
|
|
// try to read at least the bit we can
|
|
|
|
|
|
|
|
fifo_len = (uint8) (pRxBuffer->Space - 1); |
|
|
|
fifo_len = (uint8) (pRxBuffer->Space - 1); |
|
|
|
UART_WriteChar(UART1, '%', 1); |
|
|
|
UART_WriteChar(UART1, '#', 10); |
|
|
|
// discard contents of the FIFO - would loop forever
|
|
|
|
// discard contents of the FIFO - would loop forever
|
|
|
|
buf_idx = 0; |
|
|
|
buf_idx = 0; |
|
|
|
while (buf_idx < fifo_len) { |
|
|
|
while (buf_idx < fifo_len) { |
|
|
@ -193,35 +209,30 @@ u16 ICACHE_FLASH_ATTR UART_AsyncTxGetEmptySpace(void) |
|
|
|
return pTxBuffer->Space; |
|
|
|
return pTxBuffer->Space; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
u16 ICACHE_FLASH_ATTR UART_AsyncTxCount(void) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return (u16) (pTxBuffer->UartBuffSize - pTxBuffer->Space); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Schedule data to be sent |
|
|
|
* Schedule data to be sent |
|
|
|
* @param pdata |
|
|
|
* @param pdata |
|
|
|
* @param data_len - can be -1 for strlen |
|
|
|
* @param data_len - can be -1 for strlen |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
void ICACHE_FLASH_ATTR |
|
|
|
void ICACHE_FLASH_ATTR |
|
|
|
UART_SendAsync(const char *pdata, int16_t data_len) |
|
|
|
UART_SendAsync(const char *pdata, int data_len) |
|
|
|
{ |
|
|
|
{ |
|
|
|
u16 real_len = (u16) data_len; |
|
|
|
size_t real_len = (data_len) <= 0 ? strlen(pdata) : (size_t) data_len; |
|
|
|
if (data_len <= 0) real_len = (u16) strlen(pdata); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if (pTxBuffer == NULL) {
|
|
|
|
buf_dbg("Send Async %d", real_len); |
|
|
|
// printf("init tx buf\n\r");
|
|
|
|
if (real_len <= pTxBuffer->Space) { |
|
|
|
// pTxBuffer = UART_AsyncBufferInit(UART_TX_BUFFER_SIZE);
|
|
|
|
buf_dbg("accepted, space %d", pTxBuffer->Space); |
|
|
|
// if (pTxBuffer != NULL) {
|
|
|
|
UART_WriteToAsyncBuffer(pTxBuffer, pdata, (uint16) real_len); |
|
|
|
// UART_WriteToAsyncBuffer(pTxBuffer, pdata, real_len);
|
|
|
|
} |
|
|
|
// }
|
|
|
|
else { |
|
|
|
// else {
|
|
|
|
buf_dbg("FULL!"); |
|
|
|
// printf("tx alloc fail\r\n");
|
|
|
|
UART_WriteChar(UART1, '=', 10); |
|
|
|
// }
|
|
|
|
} |
|
|
|
// }
|
|
|
|
|
|
|
|
// else {
|
|
|
|
|
|
|
|
if (real_len <= pTxBuffer->Space) { |
|
|
|
|
|
|
|
UART_WriteToAsyncBuffer(pTxBuffer, pdata, real_len); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else { |
|
|
|
|
|
|
|
UART_WriteChar(UART1, '^', 1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Here we enable TX empty interrupt that will take care of sending the content
|
|
|
|
// 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_CONF1(UART0), (UART_TX_EMPTY_THRESH_VAL & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S); |
|
|
@ -257,8 +268,8 @@ void UART_DispatchFromTxBuffer(uint8 uart_no) |
|
|
|
uint8 len_tmp; |
|
|
|
uint8 len_tmp; |
|
|
|
uint16 data_len; |
|
|
|
uint16 data_len; |
|
|
|
|
|
|
|
|
|
|
|
// if (pTxBuffer) {
|
|
|
|
data_len = (uint16) (pTxBuffer->UartBuffSize - pTxBuffer->Space); |
|
|
|
data_len = (uint8) (pTxBuffer->UartBuffSize - pTxBuffer->Space); |
|
|
|
buf_dbg("rem %d",data_len); |
|
|
|
if (data_len > fifo_remain) { |
|
|
|
if (data_len > fifo_remain) { |
|
|
|
len_tmp = fifo_remain; |
|
|
|
len_tmp = fifo_remain; |
|
|
|
UART_TxFifoEnq(pTxBuffer, len_tmp, uart_no); |
|
|
|
UART_TxFifoEnq(pTxBuffer, len_tmp, uart_no); |
|
|
@ -268,8 +279,9 @@ void UART_DispatchFromTxBuffer(uint8 uart_no) |
|
|
|
len_tmp = (uint8) data_len; |
|
|
|
len_tmp = (uint8) data_len; |
|
|
|
UART_TxFifoEnq(pTxBuffer, len_tmp, uart_no); |
|
|
|
UART_TxFifoEnq(pTxBuffer, len_tmp, uart_no); |
|
|
|
|
|
|
|
|
|
|
|
// we get one more IT after fifo ends even if we have 0 more bytes
|
|
|
|
// We get one more IT after fifo ends even if we have 0 more bytes,
|
|
|
|
// for notify
|
|
|
|
// for notify. Otherwise we would say we have space while the FIFO
|
|
|
|
|
|
|
|
// was still running
|
|
|
|
if (next_empty_it_only_for_notify) { |
|
|
|
if (next_empty_it_only_for_notify) { |
|
|
|
notify_empty_txbuf(); |
|
|
|
notify_empty_txbuf(); |
|
|
|
next_empty_it_only_for_notify = 0; |
|
|
|
next_empty_it_only_for_notify = 0; |
|
|
@ -279,9 +291,4 @@ void UART_DispatchFromTxBuffer(uint8 uart_no) |
|
|
|
SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA); |
|
|
|
SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
// else {
|
|
|
|
|
|
|
|
// error("pTxBuff null \n\r");
|
|
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|