From da34d97efb21719b2b332f8c60b2750d11bcde1f Mon Sep 17 00:00:00 2001 From: Otto Mattik Date: Thu, 8 Jul 2021 18:10:55 +0200 Subject: git: update to v1.0 --- avr/usart.c | 569 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 569 insertions(+) create mode 100644 avr/usart.c (limited to 'avr/usart.c') diff --git a/avr/usart.c b/avr/usart.c new file mode 100644 index 0000000..ed5dabf --- /dev/null +++ b/avr/usart.c @@ -0,0 +1,569 @@ +/************************************************************************/ +/* */ +/* File: avr/usart.c */ +/* Description: serial line device. */ +/* Version: 1.0 */ +/* Author: Otto Mattik */ +/* */ +/* (C)Copyright Otto Mattik 2014-2021. */ +/* */ +/* This file is a part of 'armen' (a tiny operating system). */ +/* 'armen' is distributed under the CeCILL-V2.1 licence. For more */ +/* details about this licence, please visit the website cecill.info */ +/* */ +/************************************************************************/ + +#ifndef AVR_UART_C + #error "do not use this code directly, it must be included via avr_uart.c" +#endif + +/* +#define OUTPUT_INTERRUPT +*/ + +#include +#include + +/* + * the uart is configured with 8 data bits, no parity and 1 stop bit. +*/ + +#if defined(__AVR_ATtiny841__) + + #define UART0_INPUT_PIN PA2 /* receive */ + #define UART0_OUTPUT_PIN PA1 /* transmit */ + #define UART0_CONFIG_PINS() (\ + DDRA = (DDRA|(1<>8, UBRR0L = (b)&0xFF\ + ) +#define UART0_CONFIG_DEVICE() (\ + UCSR0B = (1<>8, UBRR1L = (b)&0xFF\ + ) +#define UART1_CONFIG_DEVICE() (\ + UCSR1B = (1<>8, UBRR2L = (b)&0xFF\ + ) +#define UART2_CONFIG_DEVICE() (\ + UCSR2B = (1<>8, UBRR3L = (b)&0xFF\ + ) +#define UART3_CONFIG_DEVICE() (\ + UCSR3B = (1<= 2) +ISR( UART1_INPUT_INT ) +{ + uint8_t byte = UART1_RX_BYTE; + _uart_recv_byte( 1, byte ); +} +#endif + +#if (ARMEN_UARTS >= 3) +ISR( UART2_INPUT_INT ) +{ + uint8_t byte = UART2_RX_BYTE; + _uart_recv_byte( 2, byte ); +} +#endif + +#if (ARMEN_UARTS == 4) +ISR( UART3_INPUT_INT ) +{ + uint8_t byte = UART3_RX_BYTE; + _uart_recv_byte( 3, byte ); +} +#endif + +/* + * occurs at end of byte transmission +*/ +#ifdef OUTPUT_INTERRUPT + ISR( UART0_OUTPUT_INT ) + { + uarts[0].state &= ~UART_TX_PROGRESS; + UART0_TX_INT_DISABLE( ); + } + + #if (ARMEN_UARTS >= 2) + ISR( UART1_OUTPUT_INT ) + { + uarts[1].state &= ~UART_TX_PROGRESS; + UART1_TX_INT_DISABLE( ); + } + #endif + + #if (ARMEN_UARTS >= 3) + ISR( UART2_OUTPUT_INT ) + { + uarts[2].state &= ~UART_TX_PROGRESS; + UART2_TX_INT_DISABLE( ); + } + #endif + + #if (ARMEN_UARTS == 4) + ISR( UART3_OUTPUT_INT ) + { + uarts[3].state &= ~UART_TX_PROGRESS; + UART3_TX_INT_DISABLE( ); + } + #endif +#endif + +/* + * initialize device + * + * input: + * device identifier + * config uart configuration + * output: + * 0 if success, otherwise -1 +*/ +static int8_t _uart_open( uint8_t device, uint8_t config ) +{ + uint8_t bauds = config & BAUDRATE; + uint16_t ubrr = uart_bauds[bauds]; + +#ifdef CHECK_PARAM + if( (uarts[device].state & UART_OPEN) != 0 || bauds > B115200 ) + return( -1 ); +#endif + uarts[device].rx_head = uarts[device].rx_tail = 0; + uarts[device].state = (config & UART_CONFIG_MASK) | UART_OPEN; + uarts[device].rx_head = uarts[device].rx_tail = 0; + if( device == 0 ) + { + UART0_CONFIG( ubrr ); + UART0_RX_INT_ENABLE( ); + } +#if (ARMEN_UARTS >= 2) + else if( device == 1 ) + { + UART1_CONFIG( ubrr ); + UART1_RX_INT_ENABLE( ); + } +#endif +#if (ARMEN_UARTS >= 3) + else if( device == 2 ) + { + UART2_CONFIG( ubrr ); + UART2_RX_INT_ENABLE( ); + } +#endif +#if (ARMEN_UARTS == 4) + else + { + UART3_CONFIG( ubrr ); + UART3_RX_INT_ENABLE( ); + } +#endif +} + +/* + * release device + * + * input: + * device identifier + * output: + * 0 if success, otherwise -1 +*/ +static int8_t _uart_close( uint8_t device ) +{ +#ifdef CHECK_PARAM + if( (uarts[device].state & UART_OPEN) == 0 ) + return( -1 ); +#endif + if( device == 0 ) + { + UART0_RX_INT_DISABLE( ); +#ifdef OUTPUT_INTERRUPT + UART0_TX_INT_DISABLE( ); +#endif + } +#if (ARMEN_UARTS >= 2) + else if( device == 1 ) + { + UART1_RX_INT_DISABLE( ); + #ifdef OUTPUT_INTERRUPT + UART1_TX_INT_DISABLE( ); + #endif + } +#endif +#if (ARMEN_UARTS >= 3) + else if( device == 2 ) + { + UART2_RX_INT_DISABLE( ); + #ifdef OUTPUT_INTERRUPT + UART2_TX_INT_DISABLE( ); + #endif + } +#endif +#if (ARMEN_UARTS == 4) + else + { + UART3_RX_INT_DISABLE( ); + #ifdef OUTPUT_INTERRUPT + UART3_TX_INT_DISABLE( ); + #endif + } +#endif + uarts[device].state = 0; + uarts[device].rx_head = uarts[device].rx_tail = 0; + return( 0 ); +} + +/* + * read from device + * + * input: + * device identifier + * byte address of byte to read + * output: + * 0 if success, otherwise -1 +*/ +static int8_t _uart_read( uint8_t device, uint8_t* byte ) +{ + uint8_t tail; + +#ifdef CHECK_PARAM + if( (uarts[device].state & UART_OPEN) == 0 || byte == (uint8_t*)0 ) + return( -1 ); +#endif + tail = uarts[device].rx_tail; + if( tail == uarts[device].rx_head ) + wait_event( EVENT_UART0 + device ); + if( ++tail == (UART_RX_BUFFER_SIZE + 1) ) + tail = 0; + *byte = uarts[device].rx_buffer[tail]; + uarts[device].rx_tail = tail; + return( 0 ); +} + +/* + * write to device + * + * input: + * device identifier + * byte byte to write + * output: + * 0 if success, otherwise -1 +*/ +static int8_t _uart_write( uint8_t device, uint8_t byte ) +{ + if( (uarts[device].state & UART_OPEN) == 0 ) + return( -1 ); + +#ifdef OUTPUT_INTERRUPT + uarts[device].state |= UART_TX_PROGRESS; +#endif + if( uarts[device].state & ECHOO ) + uarts[device].state |= UART_ECHOO_CHECK; + if( device == 0 ) + { +#ifdef OUTPUT_INTERRUPT + UART0_TX_BYTE = byte; + UART0_TX_INT_ENABLE( ); +#else + while( UART0_TX_NOT_READY( ) ) ; + UART0_TX_BYTE = byte; +#endif + } +#if (ARMEN_UARTS >= 2) + else if( device == 1 ) + { + #ifdef OUTPUT_INTERRUPT + UART1_TX_BYTE = byte; + UART1_TX_INT_ENABLE( ); + #else + while( UART1_TX_NOT_READY( ) ) ; + UART1_TX_BYTE = byte; + #endif + } +#endif +#if (ARMEN_UARTS >= 3) + else if( device == 2 ) + { + #ifdef OUTPUT_INTERRUPT + UART2_TX_BYTE = byte; + UART2_TX_INT_ENABLE( ); + #else + while( UART2_TX_NOT_READY( ) ) ; + UART2_TX_BYTE = byte; + #endif + } +#endif +#if (ARMEN_UARTS == 4) + else + { + #ifdef OUTPUT_INTERRUPT + UART3_TX_BYTE = byte; + UART3_TX_INT_ENABLE( ); + #else + while( UART3_TX_NOT_READY( ) ) ; + UART3_TX_BYTE = byte; + #endif + } +#endif + +#ifdef OUTPUT_INTERRUPT + while( uarts[device].state & UART_TX_PROGRESS ) ; +#else + if( device == 0 ) + while( UART0_TX_NOT_READY( ) ) ; + #if (ARMEN_UARTS >= 2) + else if( device == 1 ) + while( UART1_TX_NOT_READY( ) ) ; + #endif + #if (ARMEN_UARTS >= 3) + else if( device == 2 ) + while( UART2_TX_NOT_READY( ) ) ; + #endif + #if (ARMEN_UARTS == 4) + else + while( UART3_TX_NOT_READY( ) ) ; + #endif +#endif + if( uarts[device].state & ECHOO ) + { + while( uarts[device].state & UART_ECHOO_CHECK ) ; + if( uarts[device].cd_byte != byte ) + return( -1 ); + } + return( 0 ); +} + +/* + * device special feature + * + * input: + * device identifier + * request device dependent + * args list of arguments + * output: + * 0 if success, otherwise -1 +*/ +#ifdef UART_IOCTL +static int8_t _uart_ioctl( uint8_t device, uint8_t request, va_list args ) +{ + if( (uarts[device].state & UART_OPEN) != 0 ) + { + if( request == UART_GETP ) + { + uint8_t* p = va_arg( args, uint8_t* ); + + *p = uarts[device].state & UART_CONFIG_MASK; + return( 0 ) + } + } + return( -1 ); +} +#endif + -- cgit v1.2.1