Implement thread-safe uart

This commit is contained in:
me-no-dev 2016-10-14 03:07:21 +03:00
parent 17c8ceb1b9
commit 242bca9451

View File

@ -40,14 +40,21 @@ static int s_uart_debug_nr = 0;
struct uart_struct_t { struct uart_struct_t {
uart_dev_t * dev; uart_dev_t * dev;
xSemaphoreHandle lock;
uint8_t num; uint8_t num;
xQueueHandle queue; xQueueHandle queue;
}; };
#define UART_MUTEX_LOCK() do {} while (xSemaphoreTake(uart->lock, portMAX_DELAY) != pdPASS)
#define UART_MUTEX_UNLOCK() xSemaphoreGive(uart->lock)
#define UART_MUTEX_LOCK_NUM(i) if(_uart_bus_array[i].lock != NULL) do {} while (xSemaphoreTake(_uart_bus_array[i].lock, portMAX_DELAY) != pdPASS)
#define UART_MUTEX_UNLOCK_NUM(i) if(_uart_bus_array[i].lock != NULL) xSemaphoreGive(_uart_bus_array[i].lock)
static uart_t _uart_bus_array[3] = { static uart_t _uart_bus_array[3] = {
{(volatile uart_dev_t *)(DR_REG_UART_BASE), 0, NULL}, {(volatile uart_dev_t *)(DR_REG_UART_BASE), NULL, 0, NULL},
{(volatile uart_dev_t *)(DR_REG_UART1_BASE), 1, NULL}, {(volatile uart_dev_t *)(DR_REG_UART1_BASE), NULL, 1, NULL},
{(volatile uart_dev_t *)(DR_REG_UART2_BASE), 2, NULL} {(volatile uart_dev_t *)(DR_REG_UART2_BASE), NULL, 2, NULL}
}; };
static void IRAM_ATTR _uart_isr(void *arg) static void IRAM_ATTR _uart_isr(void *arg)
@ -88,6 +95,7 @@ void uartDisableGlobalInterrupt()
void uartEnableInterrupt(uart_t* uart) void uartEnableInterrupt(uart_t* uart)
{ {
UART_MUTEX_LOCK();
uart->dev->conf1.rxfifo_full_thrhd = 112; uart->dev->conf1.rxfifo_full_thrhd = 112;
uart->dev->conf1.rx_tout_thrhd = 2; uart->dev->conf1.rx_tout_thrhd = 2;
uart->dev->conf1.rx_tout_en = 1; uart->dev->conf1.rx_tout_en = 1;
@ -97,13 +105,16 @@ void uartEnableInterrupt(uart_t* uart)
uart->dev->int_clr.val = 0xffffffff; uart->dev->int_clr.val = 0xffffffff;
intr_matrix_set(xPortGetCoreID(), UART_INTR_SOURCE(uart->num), ETS_UART_INUM); intr_matrix_set(xPortGetCoreID(), UART_INTR_SOURCE(uart->num), ETS_UART_INUM);
UART_MUTEX_UNLOCK();
} }
void uartDisableInterrupt(uart_t* uart) void uartDisableInterrupt(uart_t* uart)
{ {
UART_MUTEX_LOCK();
uart->dev->conf1.val = 0; uart->dev->conf1.val = 0;
uart->dev->int_ena.val = 0; uart->dev->int_ena.val = 0;
uart->dev->int_clr.val = 0xffffffff; uart->dev->int_clr.val = 0xffffffff;
UART_MUTEX_UNLOCK();
} }
void uartDetachRx(uart_t* uart) void uartDetachRx(uart_t* uart)
@ -155,6 +166,13 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
uart_t* uart = &_uart_bus_array[uart_nr]; uart_t* uart = &_uart_bus_array[uart_nr];
if(uart->lock == NULL) {
uart->lock = xSemaphoreCreateMutex();
if(uart->lock == NULL) {
return NULL;
}
}
if(queueLen && uart->queue == NULL) { if(queueLen && uart->queue == NULL) {
uart->queue = xQueueCreate(queueLen, sizeof(uint8_t)); //initialize the queue uart->queue = xQueueCreate(queueLen, sizeof(uint8_t)); //initialize the queue
if(uart->queue == NULL) { if(uart->queue == NULL) {
@ -164,7 +182,9 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
uartFlush(uart); uartFlush(uart);
uartSetBaudRate(uart, baudrate); uartSetBaudRate(uart, baudrate);
UART_MUTEX_LOCK();
uart->dev->conf0.val = config; uart->dev->conf0.val = config;
UART_MUTEX_UNLOCK();
if(rxPin != -1) { if(rxPin != -1) {
uartAttachRx(uart, rxPin, inverted); uartAttachRx(uart, rxPin, inverted);
@ -183,6 +203,7 @@ void uartEnd(uart_t* uart)
return; return;
} }
UART_MUTEX_LOCK();
if(uart->queue != NULL) { if(uart->queue != NULL) {
vQueueDelete(uart->queue); vQueueDelete(uart->queue);
} }
@ -191,6 +212,7 @@ void uartEnd(uart_t* uart)
uartDetachTx(uart); uartDetachTx(uart);
uart->dev->conf0.val = 0; uart->dev->conf0.val = 0;
UART_MUTEX_UNLOCK();
} }
uint32_t uartAvailable(uart_t* uart) uint32_t uartAvailable(uart_t* uart)
@ -230,8 +252,10 @@ void uartWrite(uart_t* uart, uint8_t c)
if(uart == NULL) { if(uart == NULL) {
return; return;
} }
UART_MUTEX_LOCK();
while(uart->dev->status.rxfifo_cnt == 0x7F); while(uart->dev->status.rxfifo_cnt == 0x7F);
uart->dev->fifo.rw_byte = c; uart->dev->fifo.rw_byte = c;
UART_MUTEX_UNLOCK();
} }
void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len) void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len)
@ -239,12 +263,14 @@ void uartWriteBuf(uart_t* uart, const uint8_t * data, size_t len)
if(uart == NULL) { if(uart == NULL) {
return; return;
} }
UART_MUTEX_LOCK();
while(len) { while(len) {
while(len && uart->dev->status.rxfifo_cnt < 0x7F) { while(len && uart->dev->status.rxfifo_cnt < 0x7F) {
uart->dev->fifo.rw_byte = *data++; uart->dev->fifo.rw_byte = *data++;
len--; len--;
} }
} }
UART_MUTEX_UNLOCK();
} }
void uartFlush(uart_t* uart) void uartFlush(uart_t* uart)
@ -253,6 +279,7 @@ void uartFlush(uart_t* uart)
return; return;
} }
UART_MUTEX_LOCK();
while(uart->dev->status.txfifo_cnt); while(uart->dev->status.txfifo_cnt);
uart->dev->conf0.txfifo_rst = 1; uart->dev->conf0.txfifo_rst = 1;
@ -260,6 +287,7 @@ void uartFlush(uart_t* uart)
uart->dev->conf0.rxfifo_rst = 1; uart->dev->conf0.rxfifo_rst = 1;
uart->dev->conf0.rxfifo_rst = 0; uart->dev->conf0.rxfifo_rst = 0;
UART_MUTEX_UNLOCK();
} }
void uartSetBaudRate(uart_t* uart, uint32_t baud_rate) void uartSetBaudRate(uart_t* uart, uint32_t baud_rate)
@ -267,9 +295,11 @@ void uartSetBaudRate(uart_t* uart, uint32_t baud_rate)
if(uart == NULL) { if(uart == NULL) {
return; return;
} }
UART_MUTEX_LOCK();
uint32_t clk_div = ((UART_CLK_FREQ<<4)/baud_rate); uint32_t clk_div = ((UART_CLK_FREQ<<4)/baud_rate);
uart->dev->clk_div.div_int = clk_div>>4 ; uart->dev->clk_div.div_int = clk_div>>4 ;
uart->dev->clk_div.div_frag = clk_div & 0xf; uart->dev->clk_div.div_frag = clk_div & 0xf;
UART_MUTEX_UNLOCK();
} }
uint32_t uartGetBaudRate(uart_t* uart) uint32_t uartGetBaudRate(uart_t* uart)
@ -283,20 +313,26 @@ uint32_t uartGetBaudRate(uart_t* uart)
static void IRAM_ATTR uart0_write_char(char c) static void IRAM_ATTR uart0_write_char(char c)
{ {
UART_MUTEX_LOCK_NUM(0);
while(((ESP_REG(0x01C+DR_REG_UART_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F); while(((ESP_REG(0x01C+DR_REG_UART_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
ESP_REG(DR_REG_UART_BASE) = c; ESP_REG(DR_REG_UART_BASE) = c;
UART_MUTEX_UNLOCK_NUM(0);
} }
static void IRAM_ATTR uart1_write_char(char c) static void IRAM_ATTR uart1_write_char(char c)
{ {
UART_MUTEX_LOCK_NUM(1);
while(((ESP_REG(0x01C+DR_REG_UART1_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F); while(((ESP_REG(0x01C+DR_REG_UART1_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
ESP_REG(DR_REG_UART1_BASE) = c; ESP_REG(DR_REG_UART1_BASE) = c;
UART_MUTEX_UNLOCK_NUM(1);
} }
static void IRAM_ATTR uart2_write_char(char c) static void IRAM_ATTR uart2_write_char(char c)
{ {
UART_MUTEX_LOCK_NUM(2);
while(((ESP_REG(0x01C+DR_REG_UART2_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F); while(((ESP_REG(0x01C+DR_REG_UART2_BASE) >> UART_TXFIFO_CNT_S) & 0x7F) == 0x7F);
ESP_REG(DR_REG_UART2_BASE) = c; ESP_REG(DR_REG_UART2_BASE) = c;
UART_MUTEX_UNLOCK_NUM(2);
} }
void uartSetDebug(uart_t* uart) void uartSetDebug(uart_t* uart)