From 7b0df2649af57d4a1ac019cda5eb0e261b5d97de Mon Sep 17 00:00:00 2001 From: schodet Date: Mon, 28 Jun 2004 20:44:13 +0000 Subject: Add: gestion d'un ring buffer par interruptions. --- n/avr/rs232/avrconfig.h | 20 ++++- n/avr/rs232/rs232.c | 189 ++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 191 insertions(+), 18 deletions(-) (limited to 'n/avr') diff --git a/n/avr/rs232/avrconfig.h b/n/avr/rs232/avrconfig.h index a497a22..b661fe9 100644 --- a/n/avr/rs232/avrconfig.h +++ b/n/avr/rs232/avrconfig.h @@ -33,13 +33,27 @@ /** Baudrate : 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 76800, * 115200, 230400, 250000, 500000, 1000000. */ #define AC_RS232_BAUDRATE 115200 -/** Choose between interrupt (1) or polling (0). */ -#define AC_RS232_INTERRUPT 0 +/** Send mode : + * - POLLING : no interrupts; + * - RING : interrupts, ring buffer; + * - PACKETS : interrupts, by packets delimited by SOP and EOP + * (unimplemented). */ +#define AC_RS232_SEND_MODE POLLING +/** Recv mode, same as send mode. */ +#define AC_RS232_RECV_MODE POLLING /** Parity : ODD, EVEN, NONE. */ #define AC_RS232_PARITY ODD /** Stop bits : 1, 2. */ #define AC_RS232_STOP_BITS 2 -/** Character size : 5, 6, 7, 8, 9. */ +/** Character size : 5, 6, 7, 8, 9 (only 8 implemented). */ #define AC_RS232_CHAR_SIZE 8 +/** SOP (Start of packet) caracter. */ +#define AC_RS232_SOP(c) ((c) == '!') +/** EOP (End of packet) caracter. */ +#define AC_RS232_EOP(c) ((c) == '\r') +/** Send buffer size, should be power of 2 for RING mode. */ +#define AC_RS232_SEND_BUFFER_SIZE 32 +/** Recv buffer size, should be power of 2 for RING mode. */ +#define AC_RS232_RECV_BUFFER_SIZE 32 #endif /* avrconfig_h */ diff --git a/n/avr/rs232/rs232.c b/n/avr/rs232/rs232.c index 91efa44..6022aa0 100644 --- a/n/avr/rs232/rs232.c +++ b/n/avr/rs232/rs232.c @@ -24,29 +24,42 @@ #include "rs232.h" #include +#include +#include /* Tested AVR check. */ #if defined (__AVR_ATmega8__) -# define SELECTOR _BV (URSEL) #elif defined (__AVR_ATmega8535__) -# define SELECTOR _BV (URSEL) #elif defined (__AVR_ATmega128__) -# define UBRRH UBRR0H -# define UBRRL UBRR0L -# define UCSRA UCSR0A -# define UCSRB UCSR0B -# define UCSRC UCSR0C -# define UDR UDR0 -# define SELECTOR 0 #else # warning "rs232: not tested on this chip." #endif -/* Unimplemented features. */ -#if AC_RS232_INTERRUPT -# error "rs232: interrupts to be implemented." +/* UART number. */ +#if !defined (UBRRH) +# if defined (UBRR0H) +# define UBRRH UBRR0H +# define UBRRL UBRR0L +# define UCSRA UCSR0A +# define UCSRB UCSR0B +# define UCSRC UCSR0C +# define UDR UDR0 +# define SIG_UART_RECV SIG_UART0_RECV +# define SIG_UART_DATA SIG_UART0_DATA +# define PE UPE +# else +# error "rs232: canot find UBRR." +# endif +#endif + +/* UR selector. */ +#if defined (URSEL) +# define SELECTOR _BV (URSEL) +#else +# define SELECTOR 0 #endif +/* Unimplemented features. */ #if AC_RS232_CHAR_SIZE != 8 # error "rs232: char size != 8 not implemented." #endif @@ -63,6 +76,21 @@ #warning "rs232: baud rate error > 0." #endif +/* Mode. */ +#define POLLING 0 +#define RING 1 +#define PACKETS 2 +#define SEND_MODE AC_RS232_SEND_MODE +#define RECV_MODE AC_RS232_RECV_MODE +#if RECV_MODE == POLLING +# define RECV_IE 0 +#else +# define RECV_IE _BV (RXCIE) +#endif +#if SEND_MODE == PACKETS || RECV_MODE == PACKETS +# error "rs232: packet mode not implemented." +#endif + /* Parity. */ #define ODD (_BV (UPM1) | _BV (UPM0)) #define EVEN _BV (UPM1) @@ -81,6 +109,46 @@ /* Character size. */ #define CHAR_SIZE (_BV (UCSZ1) | _BV (UCSZ0)) +/* Buffers. */ +#if SEND_MODE == RING || SEND_MODE == PACKETS +# define SEND_BUFFER_SIZE AC_RS232_SEND_BUFFER_SIZE +#endif +#if SEND_MODE == RING +# define SEND_BUFFER_MASK (SEND_BUFFER_SIZE - 1) +# if SEND_BUFFER_SIZE & SEND_BUFFER_MASK +# error "rs232: send buffer size must be a power of 2." +# endif +#endif +#if RECV_MODE == RING || RECV_MODE == PACKETS +# define RECV_BUFFER_SIZE AC_RS232_RECV_BUFFER_SIZE +#endif +#if RECV_MODE == RING +# define RECV_BUFFER_MASK (RECV_BUFFER_SIZE - 1) +# if RECV_BUFFER_SIZE & RECV_BUFFER_MASK +# error "rs232: recv buffer size must be a power of 2." +# endif +#endif + +/* Send buffer. */ +#if SEND_MODE != POLLING +uint8_t rs232_send_buffer[SEND_BUFFER_SIZE]; +#endif +#if SEND_MODE == RING +volatile uint8_t rs232_send_head, rs232_send_tail; +#endif + +/* Recv buffer. */ +#if RECV_MODE != POLLING +uint8_t rs232_recv_buffer[RECV_BUFFER_SIZE]; +#endif +#if RECV_MODE == RING +volatile uint8_t rs232_recv_head, rs232_recv_tail; +#endif + +/* Last error code. */ +#define ERROR_BITS (_BV (FE) | _BV (DOR) | _BV (PE)) +volatile uint8_t rs232_error_code; + /* +AutoDec */ /* -AutoDec */ @@ -94,22 +162,113 @@ rs232_init (void) UCSRA = 0; /* Set format and enable rs232. */ UCSRC = SELECTOR | PARITY | STOP_BITS | CHAR_SIZE; - UCSRB = _BV (RXEN) | _BV (TXEN); + UCSRB = RECV_IE | _BV (RXEN) | _BV (TXEN); +#if RECV_MODE == RING + rs232_recv_head = 0; + rs232_recv_tail = 0; +#endif +#if SEND_MODE == RING + rs232_send_head = 0; + rs232_send_tail = 0; +#endif + rs232_error_code = 0; } /** Read a char. */ -unsigned char +uint8_t rs232_getc (void) { +#if RECV_MODE == POLLING + uint8_t tmperr; loop_until_bit_is_set (UCSRA, RXC); + tmperr = UCSRA & ERROR_BITS; + if (tmperr) + rs232_error_code = tmperr; return UDR; +#elif RECV_MODE == RING + uint8_t tmptail = rs232_recv_tail; + while (rs232_recv_head == tmptail) + ; + tmptail = (tmptail + 1) & RECV_BUFFER_MASK; + rs232_recv_tail = tmptail; + return rs232_recv_buffer[tmptail]; +#endif } /** Write a char. */ void -rs232_putc (unsigned char c) +rs232_putc (uint8_t c) { +#if SEND_MODE == POLLING loop_until_bit_is_set (UCSRA, UDRE); UDR = c; +#elif SEND_MODE == RING + uint8_t tmphead; + tmphead = (rs232_send_head + 1) & SEND_BUFFER_MASK; + while (tmphead == rs232_send_tail) + ; + rs232_send_buffer[tmphead] = c; + rs232_send_head = tmphead; + UCSRB |= _BV (UDRIE); +#endif +} + +/** Retrieve error condition, 0 if no error. */ +uint8_t +rs232_error (void) +{ + return rs232_error_code; +} + +/** Retrieve availlable chars. */ +uint8_t +rs232_poll (void) +{ +#if RECV_MODE == POLLING + return UCSRA & RXC; +#elif RECV_MODE == RING + return (rs232_recv_head - rs232_recv_tail) & RECV_BUFFER_MASK; +#endif +} + +#if RECV_MODE == RING + +/* Handle received char for ring buffer. */ +INTERRUPT (SIG_UART_RECV) +{ + uint8_t c; + uint8_t tmphead; + uint8_t tmperr; + tmperr = UCSRA & ERROR_BITS; + if (tmperr) + rs232_error_code = tmperr; + c = UDR; + tmphead = (rs232_recv_head + 1) & RECV_BUFFER_MASK; + rs232_recv_head = tmphead; + /* If overflowed, clear the receive buffer. */ + if (tmphead == rs232_recv_tail) + rs232_error_code = 0xff; + rs232_recv_buffer[tmphead] = c; +} + +#endif /* RECV_MODE == RING */ + +#if SEND_MODE == RING + +/** Handle data register empty for ring buffer. */ +INTERRUPT (SIG_UART_DATA) +{ + uint8_t tmptail; + if (rs232_send_head != rs232_send_tail) + { + tmptail = (rs232_send_tail + 1) & SEND_BUFFER_MASK; + rs232_send_tail = tmptail; + UDR = rs232_send_buffer[tmptail]; + } + else + { + UCSRB &= ~_BV (UDRIE); + } } +#endif /* SEND_MODE == RING */ -- cgit v1.2.3