From 762a42ef835d3692bf0d9bea19f5cfd9cb673a33 Mon Sep 17 00:00:00 2001 From: Leo C Date: Sun, 27 Jul 2014 22:58:42 +0200 Subject: [PATCH] Remove flow control, factor out ring buffer --- avr/ring.h | 74 ++++++++++++++++++++++++++++++ avr/serial.c | 126 ++++++--------------------------------------------- 2 files changed, 87 insertions(+), 113 deletions(-) create mode 100644 avr/ring.h diff --git a/avr/ring.h b/avr/ring.h new file mode 100644 index 0000000..d57f9aa --- /dev/null +++ b/avr/ring.h @@ -0,0 +1,74 @@ +#ifndef RING_H +#define RING_H + +struct ring { + uint8_t *data; + uint_fast8_t mask; + volatile uint_fast8_t begin; + volatile uint_fast8_t end; +}; + + +static inline +void ring_init(struct ring *ring, uint8_t *buf, int size) +{ + ring->data = buf; + ring->mask = (size-1) & 0xff; + ring->begin = 0; + ring->end = 0; +} + +static inline +int ring_write_ch(struct ring *ring, uint8_t ch) +{ + uint_fast8_t ep = ring->end; + + ring->data[ep] = ch; + ep = (ep + 1) & ring->mask; + + if ((ep) != ring->begin) { + ring->end = ep; + return 1; + } + + return -1; +} + +#if 0 +static inline +int ring_write(struct ring *ring, uint8_t *data, int size) +{ + int i; + + for (i = 0; i < size; i++) { + if (ring_write_ch(ring, data[i]) < 0) + return -i; + } + + return i; +} +#endif + +static inline +int ring_read_ch(struct ring *ring) +{ + int ret = -1; + uint_fast8_t bp = ring->begin; + + if (bp != ring->end) { + ret = ring->data[bp]; + ring->begin = (bp + 1) & ring->mask; + } + + return ret; +} + + +static inline +int_fast8_t ring_is_empty(struct ring *ring) +{ + return ring->begin == ring->end; +} + +#endif /* RING_H */ + diff --git a/avr/serial.c b/avr/serial.c index 4b3cd42..2d2c551 100644 --- a/avr/serial.c +++ b/avr/serial.c @@ -7,6 +7,7 @@ #include #include +#include "ring.h" #include "serial.h" @@ -14,31 +15,9 @@ static int _write(char c, FILE *stream); static FILE mystdout = FDEV_SETUP_STREAM(_write, NULL, _FDEV_SETUP_WRITE); -#define CTL_S ('S'-'@') /* DC3 (Stop) */ -#define CTL_Q ('Q'-'@') /* DC1 (Start) */ -typedef enum { - IDLE, - ACTIVE, - REQ_STOP, - REQ_CONT, - STOPPED -} xmit_stat_t; - -static volatile uint8_t stat_tx; -static volatile uint8_t stat_rx; - - -struct ring { - uint8_t *data; - uint_fast8_t mask; - volatile uint_fast8_t begin; - volatile uint_fast8_t end; -}; - - -#define BUFFER_SIZE 256 +#define BUFFER_SIZE 64 #if ((BUFFER_SIZE-1) & BUFFER_SIZE) # error: BUFFER_SIZE not power of 2 @@ -54,60 +33,6 @@ uint8_t rx_ring_buffer[BUFFER_SIZE]; uint8_t tx_ring_buffer[BUFFER_SIZE]; -static void ring_init(struct ring *ring, uint8_t *buf, int size) -{ - ring->data = buf; - ring->mask = (size-1) & 0xff; - ring->begin = 0; - ring->end = 0; -} - -static int ring_write_ch(struct ring *ring, uint8_t ch) -{ - uint_fast8_t ep = (ring->end + 1) & ring->mask; - - if ((ep) != ring->begin) { - ring->data[ring->end] = ch; - ring->end = ep; - return 1; - } - - return -1; -} - -#if 0 -static int ring_write(struct ring *ring, uint8_t *data, int size) -{ - int i; - - for (i = 0; i < size; i++) { - if (ring_write_ch(ring, data[i]) < 0) - return -i; - } - - return i; -} -#endif - -static int ring_read_ch(struct ring *ring) -{ - int ret = -1; - uint_fast8_t i = ring->begin; - - if (i != ring->end) { - ret = ring->data[i]; - ring->begin = (i +1) & ring->mask; - } - - return ret; -} - - -static int_fast8_t ring_is_empty(struct ring *ring) -{ - return ring->begin == ring->end; -} - /* Initialize UART */ @@ -122,17 +47,14 @@ void usart0_setup(void) { ring_init(&rx_ring, rx_ring_buffer, BUFFER_SIZE); ring_init(&tx_ring, tx_ring_buffer, BUFFER_SIZE); - stat_tx = ACTIVE; - stat_rx = ACTIVE; - - UCSR0A = _BV(U2X0); - UBRR0L = F_CPU / BAUD / 8 - 1; + UCSR0A = 0; + UBRR0 = F_CPU / BAUD / 16 - 1; UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0); UCSR0C = 3 << UCSZ00; }; } - +/*--------------------------------------------------------------------------*/ /* UART RXC interrupt */ @@ -141,41 +63,23 @@ ISR(USART0_RX_vect) uint8_t d; d = UDR0; - - switch (d) { - case CTL_S: - stat_tx = REQ_STOP; - break; - case CTL_Q: - if ((stat_tx == STOPPED) || stat_tx == REQ_STOP) { - UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0) | _BV(UDRIE0); - stat_tx = ACTIVE; - } - break; - default: - ring_write_ch(&rx_ring, d); - break; - } + ring_write_ch(&rx_ring, d); } /* UART UDRE interrupt */ ISR(USART0_UDRE_vect) { - uint8_t s; + int d = ring_read_ch(&tx_ring); - s = !ring_is_empty(&tx_ring); - if ((s == 0) || (stat_tx != ACTIVE)) { + if (d < 0) { + /* Disable TX empty interrupt. */ UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0); - if (s) - stat_tx = STOPPED; } else { - UDR0 = ring_read_ch(&tx_ring); + UDR0 = d; } } - - /*--------------------------------------------------------------------------*/ void serial_setup(void) @@ -206,12 +110,8 @@ void serial_putc(uint8_t data) { while (ring_write_ch(&tx_ring, data) < 0) ; - switch (stat_tx) { - case ACTIVE: - default: - /* Enable the TXE interrupt. */ - UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0) | _BV(UDRIE0); - break; - } + + /* Enable the TXE interrupt. */ + UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0) | _BV(UDRIE0); } -- 2.39.2