230 lines
4.4 KiB
C
230 lines
4.4 KiB
C
#include <util/util.h>
|
|
#include <sys/atomic.h>
|
|
|
|
#include <avr/io.h>
|
|
#include <avr/interrupt.h>
|
|
#include <avr/wdt.h>
|
|
|
|
#include <io/usart.h>
|
|
#include <io/pipe.h>
|
|
|
|
#if defined( __AVR_AT90CAN128__ ) || defined ( __AVR_ATmega1284P__ ) || defined ( __AVR_ATmega1284__ )
|
|
#define HAS_USART0
|
|
#define USARTS 2
|
|
#else
|
|
#define USARTS 1
|
|
#endif
|
|
|
|
int at90_usart_configure (usart_t *usart,uint32_t baud,uint32_t config);
|
|
int at90_usart_mode_set (usart_t *usart,uint16_t mode);
|
|
int at90_usart_mode_clear (usart_t *usart,uint16_t mode);
|
|
|
|
typedef struct
|
|
{
|
|
volatile uint8_t UCSRA;
|
|
volatile uint8_t UCSRB;
|
|
volatile uint8_t UCSRC;
|
|
volatile uint8_t reserved;
|
|
union
|
|
{
|
|
volatile uint16_t UBRR;
|
|
struct
|
|
{
|
|
volatile uint8_t UBRRL;
|
|
volatile uint8_t UBRRH;
|
|
};
|
|
};
|
|
volatile uint8_t UDR;
|
|
} at90_usart_regs_t;
|
|
|
|
/*
|
|
struct at90_usart_regs* _at90_hw[] = {
|
|
(struct at90_usart*)0xC0,
|
|
(struct at90_usart*)0xC8
|
|
};
|
|
*/
|
|
|
|
typedef struct {
|
|
usart_t usart;
|
|
at90_usart_regs_t
|
|
*hw;
|
|
} at90_usart_t;
|
|
|
|
|
|
at90_usart_t at90_usarts[] = {
|
|
|
|
#if defined( HAS_USART0 )
|
|
// usart0
|
|
{
|
|
usart: {
|
|
configure: at90_usart_configure,
|
|
mode_set: at90_usart_mode_set,
|
|
mode_clear: at90_usart_mode_clear
|
|
},
|
|
hw: (at90_usart_regs_t*)0xC0
|
|
},
|
|
#endif
|
|
|
|
// usart1
|
|
{
|
|
usart: {
|
|
configure: at90_usart_configure,
|
|
mode_set: at90_usart_mode_set,
|
|
mode_clear: at90_usart_mode_clear
|
|
},
|
|
hw: (at90_usart_regs_t*)0xC8
|
|
}
|
|
};
|
|
|
|
usart_t* usart_device_get(int usart)
|
|
{
|
|
if ((usart >= 0) && (usart < USARTS)){
|
|
return &(at90_usarts[usart].usart);
|
|
};
|
|
return NULL;
|
|
};
|
|
|
|
int at90_usart_configure(usart_t *_usart,uint32_t baud,uint32_t config)
|
|
{
|
|
ATOMIC
|
|
at90_usart_t *usart = (at90_usart_t*)_usart;
|
|
|
|
uint32_t ubr = (__freq_cpu / ( 16 * baud )) - 1;
|
|
uint8_t b,c;
|
|
|
|
usart->hw->UCSRB = 0;
|
|
|
|
b = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1);
|
|
c = 0;
|
|
|
|
if (config & USART_PAR_E)
|
|
c |= _BV(UPM11);
|
|
else if (config & USART_PAR_O)
|
|
c |= _BV(UPM11) | _BV(UPM10);
|
|
|
|
if (config & USART_STOP2)
|
|
c |= _BV(USBS1);
|
|
|
|
if (config & USART_6BIT)
|
|
c |= _BV(UCSZ10);
|
|
else if (config & USART_7BIT)
|
|
c |= _BV(UCSZ11);
|
|
else if (config & USART_8BIT)
|
|
c |= _BV(UCSZ10) | _BV(UCSZ11);
|
|
|
|
|
|
usart->hw->UBRR = ubr;
|
|
usart->hw->UCSRA = 0; //_BV(U2X1);
|
|
usart->hw->UCSRC = c;
|
|
usart->hw->UCSRB = b;
|
|
|
|
return 0;
|
|
};
|
|
|
|
int at90_usart_mode_set (usart_t *_usart,uint16_t mode){
|
|
at90_usart_t *usart = (at90_usart_t*)_usart;
|
|
|
|
if (mode & USART_MODE_TX){
|
|
usart->hw->UCSRB |= _BV(UDRIE1);
|
|
};
|
|
|
|
if (mode & USART_MODE_RX){
|
|
usart->hw->UCSRB |= _BV(RXCIE1);
|
|
};
|
|
|
|
return ESUCCESS;
|
|
};
|
|
int at90_usart_mode_clear (usart_t *_usart,uint16_t mode){
|
|
at90_usart_t *usart = (at90_usart_t*)_usart;
|
|
|
|
if (mode & USART_MODE_TX){
|
|
usart->hw->UCSRB &= ~_BV(UDRIE1);
|
|
};
|
|
|
|
if (mode & USART_MODE_RX){
|
|
usart->hw->UCSRB &= ~_BV(RXCIE1);
|
|
};
|
|
|
|
return ESUCCESS;
|
|
};
|
|
|
|
|
|
|
|
#if defined( HAS_USART0 )
|
|
|
|
VECT(USART0_UDRE_vect){
|
|
|
|
#if defined(__USART_BUFFER__) // buffer based i/o
|
|
if (buffer_free( &(at90_usarts[0].usart.tx) ) > 0){
|
|
at90_usarts[0].hw->UDR = buffer_byte( &(at90_usarts[0].usart.tx) );
|
|
} else {
|
|
at90_usarts[0].hw->UCSRB &= ~_BV(UDRIE1);
|
|
};
|
|
#else
|
|
|
|
int ch = usart_fifo_read( &(at90_usarts[0].usart.tx) );
|
|
if (ch < 0){
|
|
at90_usarts[0].hw->UCSRB &= ~_BV(UDRIE1);
|
|
} else {
|
|
at90_usarts[0].hw->UDR = ch;
|
|
};
|
|
|
|
#endif
|
|
};
|
|
|
|
VECT(USART0_RX_vect){
|
|
|
|
#if defined(__USART_BUFFER__) // buffer based i/o
|
|
if (buffer_free( &(at90_usarts[0].usart.rx) ) > 0){
|
|
buffer_byte( &(at90_usarts[0].usart.rx) ) = at90_usarts[0].hw->UDR;
|
|
} else {
|
|
at90_usarts[0].hw->UDR;
|
|
};
|
|
#else
|
|
|
|
usart_fifo_write( &(at90_usarts[0].usart.rx), at90_usarts[0].hw->UDR );
|
|
|
|
#endif
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
VECT(USART1_UDRE_vect){
|
|
|
|
#if defined(__USART_BUFFER__) // buffer based i/o
|
|
if (buffer_free( &(at90_usarts[USARTS - 1].usart.tx) ) > 0){
|
|
at90_usarts[USARTS - 1].hw->UDR = buffer_byte( &(at90_usarts[USARTS - 1].usart.tx) );
|
|
} else {
|
|
at90_usarts[USARTS - 1].hw->UCSRB &= ~_BV(UDRIE1);
|
|
};
|
|
#else
|
|
|
|
int ch = usart_fifo_read( &(at90_usarts[USARTS - 1].usart.tx) );
|
|
if (ch < 0){
|
|
at90_usarts[USARTS - 1].hw->UCSRB &= ~_BV(UDRIE1);
|
|
} else {
|
|
at90_usarts[USARTS - 1].hw->UDR = ch;
|
|
};
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
VECT(USART1_RX_vect){
|
|
|
|
#if defined(__USART_BUFFER__) // buffer based i/o
|
|
if (buffer_free( &(at90_usarts[USARTS - 1].usart.rx) ) > 0){
|
|
buffer_byte( &(at90_usarts[USARTS - 1].usart.rx) ) = at90_usarts[USARTS - 1].hw->UDR;
|
|
} else {
|
|
at90_usarts[USARTS - 1].hw->UDR;
|
|
};
|
|
#else
|
|
|
|
usart_fifo_write( &(at90_usarts[USARTS - 1].usart.rx), at90_usarts[USARTS - 1].hw->UDR );
|
|
|
|
#endif
|
|
|
|
};
|
|
|