/* * File : usart.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006, RT-Thread Development Team * * 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 2 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, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Change Logs: * Date Author Notes * 2011-01-13 weety first version * 2013-07-21 weety using serial component */ #include #include #include #include struct at91_uart { AT91S_USART *port; int irq; }; /** * This function will handle serial port interrupt */ void rt_at91_usart_handler(int vector, void *param) { int status; struct at91_uart *uart; rt_device_t dev = (rt_device_t)param; uart = (struct at91_uart *)dev->user_data; status = uart->port->US_CSR; if (!(status & uart->port->US_IMR)) /* check actived and enabled interrupt */ { return; } rt_interrupt_enter(); rt_hw_serial_isr((struct rt_serial_device *)dev, RT_SERIAL_EVENT_RX_IND); rt_interrupt_leave(); } /** * UART device in RT-Thread */ static rt_err_t at91_usart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) { int div; int mode = 0; struct at91_uart *uart; RT_ASSERT(serial != RT_NULL); RT_ASSERT(cfg != RT_NULL); uart = (struct at91_uart *)serial->parent.user_data; uart->port->US_CR = AT91C_US_RSTTX | AT91C_US_RSTRX | AT91C_US_RXDIS | AT91C_US_TXDIS; mode |= AT91C_US_USMODE_NORMAL | AT91C_US_CLKS_CLOCK | AT91C_US_CHMODE_NORMAL; switch (cfg->data_bits) { case DATA_BITS_8: mode |= AT91C_US_CHRL_8_BITS; break; case DATA_BITS_7: mode |= AT91C_US_CHRL_7_BITS; break; case DATA_BITS_6: mode |= AT91C_US_CHRL_6_BITS; break; case DATA_BITS_5: mode |= AT91C_US_CHRL_5_BITS; break; default: mode |= AT91C_US_CHRL_8_BITS; break; } switch (cfg->stop_bits) { case STOP_BITS_2: mode |= AT91C_US_NBSTOP_2_BIT; break; case STOP_BITS_1: default: mode |= AT91C_US_NBSTOP_1_BIT; break; } switch (cfg->parity) { case PARITY_ODD: mode |= AT91C_US_PAR_ODD; break; case PARITY_EVEN: mode |= AT91C_US_PAR_EVEN; break; case PARITY_NONE: default: mode |= AT91C_US_PAR_NONE; break; } uart->port->US_MR = mode; /* Assume OVER is cleared and fractional baudrate generator is disabled */ div = (clk_get_rate(clk_get("mck")) / 16 + cfg->baud_rate/2) / cfg->baud_rate; uart->port->US_BRGR = div; uart->port->US_CR = AT91C_US_RXEN | AT91C_US_TXEN; uart->port->US_IER = AT91C_US_RXRDY; return RT_EOK; } static rt_err_t at91_usart_control(struct rt_serial_device *serial, int cmd, void *arg) { struct at91_uart* uart; RT_ASSERT(serial != RT_NULL); uart = (struct at91_uart *)serial->parent.user_data; switch (cmd) { case RT_DEVICE_CTRL_CLR_INT: /* disable rx irq */ rt_hw_interrupt_mask(uart->irq); break; case RT_DEVICE_CTRL_SET_INT: /* enable rx irq */ rt_hw_interrupt_umask(uart->irq); break; } return RT_EOK; } static int at91_usart_putc(struct rt_serial_device *serial, char c) { //rt_uint32_t level; struct at91_uart *uart = serial->parent.user_data; while (!(uart->port->US_CSR & AT91C_US_TXRDY)); uart->port->US_THR = c; return 1; } static int at91_usart_getc(struct rt_serial_device *serial) { int result; struct at91_uart *uart = serial->parent.user_data; if (uart->port->US_CSR & AT91C_US_RXRDY) { result = uart->port->US_RHR & 0xff; } else { result = -1; } return result; } static const struct rt_uart_ops at91_usart_ops = { at91_usart_configure, at91_usart_control, at91_usart_putc, at91_usart_getc, }; #if defined(RT_USING_DBGU) static struct rt_serial_device serial_dbgu; struct at91_uart dbgu = { (AT91PS_USART)AT91C_BASE_DBGU, AT91C_ID_SYS }; #endif #if defined(RT_USING_UART0) static struct rt_serial_device serial0; struct at91_uart uart0 = { AT91C_BASE_US0, AT91C_ID_US0 }; #endif #if defined(RT_USING_UART1) static struct rt_serial_device serial1; struct at91_uart uart1 = { AT91C_BASE_US1, AT91C_ID_US1 }; #endif #if defined(RT_USING_UART2) static struct rt_serial_device serial2; struct at91_uart uart2 = { AT91C_BASE_US2, AT91C_ID_US2 }; #endif #if defined(RT_USING_UART3) static struct rt_serial_device serial3; struct at91_uart uart3 = { AT91C_BASE_US3, AT91C_ID_US3 }; #endif void at91_usart_gpio_init(void) { #ifdef RT_USING_DBGU #define DRXD 12 // DBGU rx as Peripheral A on PB12 #define DTXD 13 // DBGU tx as Peripheral A on PB13 AT91C_BASE_PIOB->PIO_IDR, (1<PIO_PPUDR, (1<PIO_ASR, (1<PIO_PDR, (1<PMC_PCER, 1 << AT91C_ID_SYS; #endif #ifdef RT_USING_UART0 #define RXD0 18 // UART0 rx as Peripheral A on PB18 #define TXD0 19 // UART0 tx as Peripheral A on PB19 AT91C_BASE_PMC->PMC_PCER, 1 << AT91C_ID_US0; AT91C_BASE_PIOB->PIO_IDR, (1<PIO_PPUER, (1<PIO_PPUDR, (1<PIO_ASR, (1<PIO_PDR, (1<PMC_PCER, 1 << AT91C_ID_US1; AT91C_BASE_PIOB->PIO_IDR, (1<PIO_PPUER, (1<PIO_PPUDR, (1<PIO_ASR, (1<PIO_PDR, (1<PMC_PCER, 1 << AT91C_ID_US2; AT91C_BASE_PIOB->PIO_IDR, (1<PIO_PPUER, (1<PIO_PPUDR, (1<PIO_ASR, (1<PIO_PDR, (1<PMC_PCER, 1<PIO_IDR, (1<PIO_PPUER, (1<PIO_PPUDR, (1<PIO_ASR, (1<PIO_PDR, (1<