libbase: blocking UART write if IRQs are enabled

This commit is contained in:
Sebastien Bourdeauducq 2012-02-07 15:12:27 +01:00
parent 73fce59631
commit 755079d7fa
1 changed files with 10 additions and 3 deletions

View File

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