extern "C" { #include #include #include #include } #include #include #include "bsp_clock.h" #include "bsp_uart.h" HardwareUart Serial0( 0 ); HardwareUart Serial1( 1 ); HardwareUart Serial2( 2 ); HardwareUart Serial3( 3 ); __attribute__((__interrupt__)) static void usart0_int_handler(void) { Serial0._isr(); } __attribute__((__interrupt__)) static void usart1_int_handler(void) { Serial1._isr(); } __attribute__((__interrupt__)) static void usart2_int_handler(void) { Serial2._isr(); } __attribute__((__interrupt__)) static void usart3_int_handler(void) { Serial3._isr(); } static const gpio_map_t usart0_gpio = { {AVR32_USART0_RXD_0_PIN, AVR32_USART0_RXD_0_FUNCTION}, // PA01 {AVR32_USART0_TXD_0_PIN, AVR32_USART0_TXD_0_FUNCTION} // PA00 }; static const gpio_map_t usart1_gpio = { {AVR32_USART1_RXD_0_1_PIN, AVR32_USART1_RXD_0_1_FUNCTION}, // PB11 {AVR32_USART1_TXD_0_1_PIN, AVR32_USART1_TXD_0_1_FUNCTION} // PB10 }; static const gpio_map_t usart2_gpio = { {AVR32_USART2_RXD_0_0_PIN, AVR32_USART2_RXD_0_0_FUNCTION}, // PA21 {AVR32_USART2_TXD_0_0_PIN, AVR32_USART2_TXD_0_0_FUNCTION} // PA20 }; static const gpio_map_t usart3_gpio = { {AVR32_USART3_RXD_0_0_PIN, AVR32_USART3_RXD_0_0_FUNCTION}, // PB01 {AVR32_USART3_TXD_0_0_PIN, AVR32_USART3_TXD_0_0_FUNCTION} // PB00 }; HardwareUart::HardwareUart( uint8_t portNum ): m_portNum(portNum), m_usart(NULL) { } void HardwareUart::begin( uint32_t baud ) { usart_options_t m_options; #if 1 // static constructor workaround if(this == &Serial0) m_portNum = 0; else if(this == &Serial1) m_portNum = 1; else if(this == &Serial2) m_portNum = 2; else if(this == &Serial3) m_portNum = 3; #endif // Assign GPIO to USART. switch(m_portNum) { case 0: m_usart = &AVR32_USART0; gpio_enable_module(usart0_gpio, sizeof(usart0_gpio) / sizeof(usart0_gpio[0])); break; case 1: m_usart = &AVR32_USART1; gpio_enable_module(usart1_gpio, sizeof(usart1_gpio) / sizeof(usart1_gpio[0])); break; case 2: m_usart = &AVR32_USART2; gpio_enable_module(usart2_gpio, sizeof(usart2_gpio) / sizeof(usart2_gpio[0])); break; case 3: m_usart = &AVR32_USART3; gpio_enable_module(usart3_gpio, sizeof(usart3_gpio) / sizeof(usart3_gpio[0])); break; default: m_usart = NULL; break; } if(!m_usart) return; m_options.baudrate = baud; m_options.charlength = 8; m_options.paritytype = USART_NO_PARITY; m_options.stopbits = USART_1_STOPBIT; m_options.channelmode = USART_NORMAL_CHMODE; // Initialize USART in RS232 mode. usart_init_rs232(m_usart, &m_options, sysclk_get_pba_hz()); // Disable all interrupts. Disable_global_interrupt(); switch(m_portNum) { case 0: INTC_register_interrupt(&usart0_int_handler, AVR32_USART0_IRQ, AVR32_INTC_INT0); break; case 1: INTC_register_interrupt(&usart1_int_handler, AVR32_USART1_IRQ, AVR32_INTC_INT0); break; case 2: INTC_register_interrupt(&usart2_int_handler, AVR32_USART2_IRQ, AVR32_INTC_INT0); break; case 3: INTC_register_interrupt(&usart3_int_handler, AVR32_USART3_IRQ, AVR32_INTC_INT0); break; } // clear FIFO buffers TxFifo.inptr = TxFifo.outptr = RxFifo.inptr = RxFifo.outptr = 0; // Enable USART Rx interrupt. m_usart->ier = AVR32_USART_IER_RXRDY_MASK; // Enable all interrupts. Enable_global_interrupt(); delay_ms(50); //print("m_portNum = %d\r\n", m_portNum); } void HardwareUart::end() { if(!m_usart) return; pcl_disable_module(AVR32_USART3_CLK_PBA); } void HardwareUart::putc(uint8_t c) { if(!m_usart) return; // wait until buffer has an empty slot. while (( (TxFifo.inptr+1) & UART_BUFF_MASK) == TxFifo.outptr) continue; //place character in buffer TxFifo.buff[TxFifo.inptr] = c; // increment in index TxFifo.inptr = (TxFifo.inptr + 1) & UART_BUFF_MASK; // start the TX sequence if not yet running if(!(TxFifo.outptr == TxFifo.inptr)) { // if TX buffer still not empty m_usart->ier = AVR32_USART_IER_TXEMPTY_MASK; // (re)enable TX interrupt; } } void HardwareUart::print(char ch) { putc(ch); } void HardwareUart::print(int num) { print("%d", num); } void HardwareUart::puts(const char *s) { while(*s) putc(*s++); } uint8_t HardwareUart::isrx() { if(!m_usart) return 0; //return (m_usart->csr & AVR32_USART_CSR_RXRDY_MASK) != 0; // checks if a character is present in the RX buffer return (RxFifo.inptr != RxFifo.outptr); } uint8_t HardwareUart::getc() { if(!m_usart) return 0; // wait until a character is present while (isrx()==0) continue; // get a character from RX buffer uint8_t c = RxFifo.buff[RxFifo.outptr]; // increment out index RxFifo.outptr = (RxFifo.outptr+1)&UART_BUFF_MASK; return c; } void HardwareUart::flushRx() { while(isrx()) getc(); } void HardwareUart::flushTx() { while(TxFifo.outptr!=TxFifo.inptr) continue; } void HardwareUart::_isr() { uint16_t temp; if(!m_usart) return; if(m_usart->csr & AVR32_USART_CSR_RXRDY_MASK) { // byte read and save to buffer RxFifo.buff[RxFifo.inptr] = ((m_usart->rhr & AVR32_USART_RHR_RXCHR_MASK) >> AVR32_USART_RHR_RXCHR_OFFSET) & 0xFF; temp = (RxFifo.inptr+1) & UART_BUFF_MASK; if(temp != RxFifo.outptr){ // avoid buffer overrun RxFifo.inptr = temp; } } if(m_usart->csr & AVR32_USART_CSR_TXEMPTY_MASK) { if(TxFifo.outptr==TxFifo.inptr) {// if buffer empty m_usart->idr = AVR32_USART_IER_TXEMPTY_MASK; // disable TX interrupt } else { // place the character to the data register m_usart->thr = TxFifo.buff[TxFifo.outptr++]; TxFifo.outptr &= UART_BUFF_MASK; // circular FIFO } } } /*------------------------------------------------------------------------/ / Universal string handler for user console interface /-------------------------------------------------------------------------/ / / Copyright (C) 2011, ChaN, all right reserved. / / * This software is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for / personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. / * Redistributions of source code must retain the above copyright notice. / /-------------------------------------------------------------------------*/ void HardwareUart::vprint ( const char* fmt, /* Pointer to the format string */ va_list arp /* Pointer to arguments */ ) { unsigned int r, i, j, w, f; unsigned long v; char s[16], c, d, *p; for (;;) { c = *fmt++; /* Get a char */ if (!c) break; /* End of format? */ if (c != '%') { /* Pass through it if not a % sequense */ putc(c); continue; } f = 0; c = *fmt++; /* Get first char of the sequense */ if (c == '0') { /* Flag: '0' padded */ f = 1; c = *fmt++; } else { if (c == '-') { /* Flag: left justified */ f = 2; c = *fmt++; } } for (w = 0; c >= '0' && c <= '9'; c = *fmt++) /* Minimum width */ w = w * 10 + c - '0'; if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ f |= 4; c = *fmt++; } if (!c) break; /* End of format? */ d = c; if (d >= 'a') d -= 0x20; switch (d) { /* Type is... */ case 'S' : /* String */ p = va_arg(arp, char*); for (j = 0; p[j]; j++) ; while (!(f & 2) && j++ < w) putc(' '); puts(p); while (j++ < w) putc(' '); continue; case 'C' : /* Character */ putc((char)va_arg(arp, int)); continue; case 'B' : /* Binary */ r = 2; break; case 'O' : /* Octal */ r = 8; break; case 'D' : /* Signed decimal */ case 'U' : /* Unsigned decimal */ r = 10; break; case 'X' : /* Hexdecimal */ r = 16; break; default: /* Unknown type (passthrough) */ putc(c); continue; } /* Get an argument and put it in numeral */ v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : (long)va_arg(arp, unsigned int)); if (d == 'D' && (v & 0x80000000)) { v = 0 - v; f |= 8; } i = 0; do { d = (char)(v % r); v /= r; if (d > 9) d += (c == 'x') ? 0x27 : 0x07; s[i++] = d + '0'; } while (v && i < sizeof(s)); if (f & 8) s[i++] = '-'; j = i; d = (f & 1) ? '0' : ' '; while (!(f & 2) && j++ < w) putc(d); do putc(s[--i]); while(i); while (j++ < w) putc(' '); } } void HardwareUart::print ( /* Put a formatted string to the default device */ const char* fmt, /* Pointer to the format string */ ... /* Optional arguments */ ) { va_list arp; va_start(arp, fmt); vprint(fmt, arp); va_end(arp); } int HardwareUart::gets ( /* 0:End of stream, 1:A line arrived */ char* buff, /* Pointer to the buffer */ int len /* Buffer length */ ) { int c, i; #define _LINE_ECHO 1 i = 0; for (;;) { c = getc(); /* Get a char from the incoming stream */ if (!c) return 0; /* End of stream? */ if (c == '\r') break; /* End of line? */ if (c == '\b' && i) { /* Back space? */ i--; if (_LINE_ECHO) putc(c); continue; } if (c >= ' ' && i < len - 1) { /* Visible chars */ buff[i++] = c; if (_LINE_ECHO) putc(c); } } buff[i] = 0; /* Terminate with a \0 */ if (_LINE_ECHO) putc('\n'); return 1; }