uart.c: rx overflow fix and tx simplification
* fixes the clearing of the rx ringbuffer on rx-overflow * removes tx_level and tx_cts by restricting the ringbuffer to at least one slot empty * agnostic of the details of the tx irq: works for uarts that generate tx interrupts on !tx-full or on tx-empty. * only rx_produce and tx_consume need to be volatile
This commit is contained in:
parent
35250f5b11
commit
097248bce9
|
@ -13,39 +13,37 @@
|
||||||
|
|
||||||
static char rx_buf[UART_RINGBUFFER_SIZE_RX];
|
static char rx_buf[UART_RINGBUFFER_SIZE_RX];
|
||||||
static volatile unsigned int rx_produce;
|
static volatile unsigned int rx_produce;
|
||||||
static volatile unsigned int rx_consume;
|
static unsigned int rx_consume;
|
||||||
|
|
||||||
#define UART_RINGBUFFER_SIZE_TX 128
|
#define UART_RINGBUFFER_SIZE_TX 128
|
||||||
#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX-1)
|
#define UART_RINGBUFFER_MASK_TX (UART_RINGBUFFER_SIZE_TX-1)
|
||||||
|
|
||||||
static char tx_buf[UART_RINGBUFFER_SIZE_TX];
|
static char tx_buf[UART_RINGBUFFER_SIZE_TX];
|
||||||
static unsigned int tx_produce;
|
static unsigned int tx_produce;
|
||||||
static unsigned int tx_consume;
|
static volatile unsigned int tx_consume;
|
||||||
static volatile int tx_cts;
|
|
||||||
static volatile int tx_level;
|
|
||||||
|
|
||||||
void uart_isr(void)
|
void uart_isr(void)
|
||||||
{
|
{
|
||||||
unsigned int stat;
|
unsigned int stat, rx_produce_next;
|
||||||
|
|
||||||
stat = uart_ev_pending_read();
|
stat = uart_ev_pending_read();
|
||||||
|
|
||||||
if(stat & UART_EV_RX) {
|
if(stat & UART_EV_RX) {
|
||||||
while(!uart_rxempty_read()) {
|
while(!uart_rxempty_read()) {
|
||||||
rx_buf[rx_produce] = uart_rxtx_read();
|
rx_produce_next = (rx_produce + 1) & UART_RINGBUFFER_MASK_RX;
|
||||||
rx_produce = (rx_produce + 1) & UART_RINGBUFFER_MASK_RX;
|
if(rx_produce_next != rx_consume) {
|
||||||
|
rx_buf[rx_produce] = uart_rxtx_read();
|
||||||
|
rx_produce = rx_produce_next;
|
||||||
|
}
|
||||||
uart_ev_pending_write(UART_EV_RX);
|
uart_ev_pending_write(UART_EV_RX);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(stat & UART_EV_TX) {
|
if(stat & UART_EV_TX) {
|
||||||
uart_ev_pending_write(UART_EV_TX);
|
uart_ev_pending_write(UART_EV_TX);
|
||||||
if(tx_level == 0)
|
while((tx_consume != tx_produce) && !uart_txfull_read()) {
|
||||||
tx_cts = 1;
|
|
||||||
while(tx_level > 0 && !uart_txfull_read()) {
|
|
||||||
uart_rxtx_write(tx_buf[tx_consume]);
|
uart_rxtx_write(tx_buf[tx_consume]);
|
||||||
tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX;
|
tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX;
|
||||||
tx_level--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +53,12 @@ char uart_read(void)
|
||||||
{
|
{
|
||||||
char c;
|
char c;
|
||||||
|
|
||||||
while(rx_consume == rx_produce);
|
if(irq_getie()) {
|
||||||
|
while(rx_consume == rx_produce);
|
||||||
|
} else if (rx_consume == rx_produce) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
c = rx_buf[rx_consume];
|
c = rx_buf[rx_consume];
|
||||||
rx_consume = (rx_consume + 1) & UART_RINGBUFFER_MASK_RX;
|
rx_consume = (rx_consume + 1) & UART_RINGBUFFER_MASK_RX;
|
||||||
return c;
|
return c;
|
||||||
|
@ -69,45 +72,45 @@ int uart_read_nonblock(void)
|
||||||
void uart_write(char c)
|
void uart_write(char c)
|
||||||
{
|
{
|
||||||
unsigned int oldmask;
|
unsigned int oldmask;
|
||||||
|
unsigned int tx_produce_next = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX;
|
||||||
|
|
||||||
if(irq_getie()) {
|
if(irq_getie()) {
|
||||||
while(tx_level == UART_RINGBUFFER_SIZE_TX);
|
while(tx_produce_next == tx_consume);
|
||||||
|
} else if(tx_produce_next == tx_consume) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
oldmask = irq_getmask();
|
oldmask = irq_getmask();
|
||||||
irq_setmask(0);
|
irq_setmask(oldmask & ~(1 << UART_INTERRUPT));
|
||||||
|
#if 0
|
||||||
if(tx_cts) {
|
while((tx_consume != tx_produce) && !uart_txfull_read()) {
|
||||||
tx_cts = 0;
|
uart_rxtx_write(tx_buf[tx_consume]);
|
||||||
uart_rxtx_write(c);
|
tx_consume = (tx_consume + 1) & UART_RINGBUFFER_MASK_TX;
|
||||||
} else {
|
}
|
||||||
|
#endif
|
||||||
|
if((tx_consume != tx_produce) || uart_txfull_read()) {
|
||||||
tx_buf[tx_produce] = c;
|
tx_buf[tx_produce] = c;
|
||||||
tx_produce = (tx_produce + 1) & UART_RINGBUFFER_MASK_TX;
|
tx_produce = tx_produce_next;
|
||||||
tx_level++;
|
} else {
|
||||||
|
uart_rxtx_write(c);
|
||||||
}
|
}
|
||||||
irq_setmask(oldmask);
|
irq_setmask(oldmask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_init(void)
|
void uart_init(void)
|
||||||
{
|
{
|
||||||
unsigned int mask;
|
|
||||||
|
|
||||||
rx_produce = 0;
|
rx_produce = 0;
|
||||||
rx_consume = 0;
|
rx_consume = 0;
|
||||||
|
|
||||||
tx_produce = 0;
|
tx_produce = 0;
|
||||||
tx_consume = 0;
|
tx_consume = 0;
|
||||||
tx_cts = 1;
|
|
||||||
tx_level = 0;
|
|
||||||
|
|
||||||
uart_ev_pending_write(uart_ev_pending_read());
|
uart_ev_pending_write(uart_ev_pending_read());
|
||||||
uart_ev_enable_write(UART_EV_TX | UART_EV_RX);
|
uart_ev_enable_write(UART_EV_TX | UART_EV_RX);
|
||||||
mask = irq_getmask();
|
irq_setmask(irq_getmask() | (1 << UART_INTERRUPT));
|
||||||
mask |= 1 << UART_INTERRUPT;
|
|
||||||
irq_setmask(mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void uart_sync(void)
|
void uart_sync(void)
|
||||||
{
|
{
|
||||||
while(!tx_cts);
|
while(tx_consume != tx_produce);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue