From 755079d7fafabbc6be7cc189ab326d1c777cb29c Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Tue, 7 Feb 2012 15:12:27 +0100 Subject: [PATCH] libbase: blocking UART write if IRQs are enabled --- software/libbase/uart.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/software/libbase/uart.c b/software/libbase/uart.c index 248e5f527..e4e87ad68 100644 --- a/software/libbase/uart.c +++ b/software/libbase/uart.c @@ -23,8 +23,6 @@ /* * Buffer sizes must be a power of 2 so that modulos can be computed * with logical AND. - * RX functions are written in such a way that they do not require locking. - * TX functions already implement locking. */ #define UART_RINGBUFFER_SIZE_RX 128 @@ -41,6 +39,7 @@ static char tx_buf[UART_RINGBUFFER_SIZE_TX]; static unsigned int tx_produce; static unsigned int tx_consume; static volatile int tx_cts; +static volatile int tx_level; void uart_isr(void) { @@ -54,9 +53,10 @@ void uart_isr(void) } if(stat & UART_EV_TX) { - if(tx_produce != tx_consume) { + if(tx_level > 0) { CSR_UART_RXTX = tx_buf[tx_consume]; tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX; + tx_level--; } else tx_cts = 1; } @@ -84,6 +84,10 @@ void uart_write(char c) { unsigned int oldmask; + if(irq_getie()) { + while(tx_level == UART_RINGBUFFER_SIZE_TX); + } + oldmask = irq_getmask(); irq_setmask(0); @@ -93,6 +97,7 @@ void uart_write(char c) } else { tx_buf[tx_produce] = c; tx_produce = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX; + tx_level++; } irq_setmask(oldmask); } @@ -103,9 +108,11 @@ void uart_init(void) rx_produce = 0; rx_consume = 0; + tx_produce = 0; tx_consume = 0; tx_cts = 1; + tx_level = 0; /* ack any events */ CSR_UART_EV_PENDING = CSR_UART_EV_PENDING;