X-Git-Url: https://git.cryptolib.org/?a=blobdiff_plain;f=uart.c;h=e35106cf816ae683822a74712dcee12d654ca973;hb=96ebafd201c9e8441c7677577b24aa402c1defc6;hp=68aaac48e006d7ee48bbc3248586e1f42ba45453;hpb=79c9a6582ba071646a3062175715f59ebe210603;p=avr-crypto-lib.git diff --git a/uart.c b/uart.c index 68aaac4..e35106c 100644 --- a/uart.c +++ b/uart.c @@ -1,9 +1,26 @@ +/* uart.c */ +/* + This file is part of the Crypto-avr-lib/microcrypt-lib. + Copyright (C) 2008 Daniel Otte (daniel.otte@rub.de) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ /* USART-Init beim ATmegaXX */ #include "config.h" #include -//#include #include #include @@ -18,9 +35,42 @@ #define URSEL UMSEL #endif +#ifdef ATMEGA644 +#define UCSRB UCSR0B +#define UCSRC UCSR0C +#define UDR UDR0 +#define UBRRH UBRR0H +#define UBRRL UBRR0L +#define URSEL UMSEL00 +#define USART_UDRE_vect USART0_UDRE_vect +#define USART_RXC_vect USART0_RX_vect +#define UDRIE UDRIE0 +#define TXEN TXEN0 +#define UMSEL UMSEL0 +#define RXEN RXEN0 +#define RXCIE RXCIE0 +#define UCSZ0 UCSZ00 +#define UCSRA UCSR0A +#define UDRE UDRE0 +#define RXC RXC0 +#endif + + +#ifdef UART_XON_XOFF + #ifdef UART_INTERRUPT + void uart_insertc(char c); + #else + #define uart_insertc uart_putc + #endif /* UART_INTERRUPT */ +#endif #define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUD_RATE)*16L)-1) +#ifdef UART_XON_XOFF + typedef enum{go=1,nogo=0} gonogo; + static gonogo txon=go; + static gonogo rxon=go; +#endif #ifdef UART_INTERRUPT volatile static char rxbuf[UART_RXBUFSIZE]; @@ -28,8 +78,11 @@ volatile static char txbuf[UART_TXBUFSIZE]; volatile static char *volatile rxhead, *volatile rxtail; volatile static char *volatile txhead, *volatile txtail; +#ifdef UART_HOOK + void (*uart_hook) (uint8_t) = (void*)0; /* this is a pointer to a function ;-) */ +#endif -SIGNAL(SIG_UART_DATA) { +ISR(USART_UDRE_vect) { #ifdef UART_LEDS PORTC ^= 0x01; #endif @@ -37,39 +90,89 @@ SIGNAL(SIG_UART_DATA) { if ( txhead == txtail ) { UCSRB &= ~(1 << UDRIE); /* disable data register empty IRQ */ } else { + #ifdef UART_XON_XOFF + while(txon==nogo) + ; + #endif UDR = *txtail; /* schreibt das Zeichen x auf die Schnittstelle */ if (++txtail == (txbuf + UART_TXBUFSIZE)) txtail = txbuf; } } -SIGNAL(SIG_UART_RECV) { +ISR(USART_RXC_vect) { int diff; - + char c; +#ifdef UART_HOOK + static volatile uint8_t hook_running=0; +#endif #ifdef UART_LEDS PORTC ^= 0x02; #endif - + c=UDR; + #ifdef UART_XON_XOFF + if (c==XON){ + txon=go; + return; + } + if (c==XOFF){ + txon=nogo; + return; + } + #endif /* buffer full? */ diff = rxhead - rxtail; - if ( diff < 0 ) diff += UART_RXBUFSIZE; + if (diff < 0) diff += UART_RXBUFSIZE; /* diff is the amount of bytes in buffer */ if (diff < UART_RXBUFSIZE -1) { // buffer NOT full - *rxhead = UDR; - if (++rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf; +#ifdef UART_HOOK + if(!hook_running && uart_hook){ + uint8_t t=c; + hook_running = 1; + sei(); /* reenable interrupts, avoid recursion!!! */ + do { + uart_hook(t); + } while(uart_getc_nb((char*)&t)); + hook_running = 0; + } else { + *rxhead = c; + ++rxhead; + if (rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf; + } +#else + *rxhead = c; + ++rxhead; + if (rxhead == (rxbuf + UART_RXBUFSIZE)) + rxhead = rxbuf; +#endif } else { - UDR; //reads the buffer to clear the interrupt condition + //reads the buffer to clear the interrupt condition } +#ifdef UART_XON_XOFF + if((diff > UART_XON_XOFF_THRESHOLD_1) && (rxon==go)){ + rxon=nogo; + uart_insertc(XOFF); + } + if((diff < UART_XON_XOFF_THRESHOLD_2) && (rxon==nogo)){ + rxon=go; + uart_insertc(XON); + } +#endif } #endif // UART_INTERRUPT -void uart_init(void) { +void uart_init() { PORTD |= 0x01; //Pullup an RXD an - + UCSRB |= (1<>8); @@ -81,11 +184,32 @@ void uart_init(void) { txhead = txtail = txbuf; // activate rx IRQ - UCSRB |= (1 << RXCIE); + UCSRB |= _BV(RXCIE) | _BV(UDRIE); + sei(); +// #ifdef ATMEGA644 +// UCSRB |= _BV(UDRIE); +// #endif #endif // UART_INTERRUPT } #ifdef UART_INTERRUPT +#ifdef UART_XON_XOFF + +void uart_insertc(char c){ + volatile int diff; + do { + diff = txhead - txtail; + if ( diff < 0 ) diff += UART_TXBUFSIZE; + } while ( diff >= UART_TXBUFSIZE -1 ); + + cli(); + if (--txtail == (txbuf-1)) txtail += UART_TXBUFSIZE; + *txtail = c; + + UCSRB |= (1 << UDRIE); /* enable data register empty IRQ */ + sei(); +} +#endif /* UART_XON_XOFF */ void uart_putc(char c) { volatile int diff; @@ -104,8 +228,13 @@ void uart_putc(char c) { } #else // WITHOUT INTERRUPT void uart_putc(char c) { - while (!(UCSRA & (1<>4)&0xf]); uart_putc(table[(*((char*)buf))&0xf]); uart_putc(' '); - buf=(char*)buf+1; + buf=(uint8_t*)buf+1; } } @@ -142,18 +271,28 @@ char uart_getc(void) { char val; - while(rxhead==rxtail) ; + while(rxhead==rxtail) + ; val = *rxtail; - if (++rxtail == (rxbuf + UART_RXBUFSIZE)) rxtail = rxbuf; + ++rxtail; + if (rxtail == (rxbuf + UART_RXBUFSIZE)) + rxtail = rxbuf; return val; } #else // WITHOUT INTERRUPT char uart_getc(void) { - while (!(UCSRA & (1<