/* * 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 #define RXRDY 0x01 #define TXRDY (1 << 1) typedef struct uartport { volatile rt_uint32_t CR; volatile rt_uint32_t MR; volatile rt_uint32_t IER; volatile rt_uint32_t IDR; volatile rt_uint32_t IMR; volatile rt_uint32_t CSR; volatile rt_uint32_t RHR; volatile rt_uint32_t THR; volatile rt_uint32_t BRGR; volatile rt_uint32_t RTOR; volatile rt_uint32_t TTGR; volatile rt_uint32_t reserved0[5]; volatile rt_uint32_t FIDI; volatile rt_uint32_t NER; volatile rt_uint32_t reserved1; volatile rt_uint32_t IFR; volatile rt_uint32_t reserved2[44]; volatile rt_uint32_t RPR; volatile rt_uint32_t RCR; volatile rt_uint32_t TPR; volatile rt_uint32_t TCR; volatile rt_uint32_t RNPR; volatile rt_uint32_t RNCR; volatile rt_uint32_t TNPR; volatile rt_uint32_t TNCR; volatile rt_uint32_t PTCR; volatile rt_uint32_t PTSR; }uartport; #define CIDR FIDI #define EXID NER #define FNR reserved1 #define DBGU ((struct uartport *)AT91SAM9260_BASE_DBGU) #define UART0 ((struct uartport *)AT91SAM9260_BASE_US0) #define UART1 ((struct uartport *)AT91SAM9260_BASE_US1) #define UART2 ((struct uartport *)AT91SAM9260_BASE_US2) #define UART3 ((struct uartport *)AT91SAM9260_BASE_US3) struct at91_uart { uartport *port; int irq; }; /** * This function will handle serial */ 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->CSR; if (!(status & uart->port->IMR)) { return; } rt_interrupt_enter(); rt_hw_serial_isr(dev); 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->CR = AT91_US_RSTTX | AT91_US_RSTRX | AT91_US_RXDIS | AT91_US_TXDIS; mode |= AT91_US_USMODE_NORMAL | AT91_US_USCLKS_MCK | AT91_US_CHMODE_NORMAL; switch (cfg->data_bits) { case DATA_BITS_8: mode |= AT91_US_CHRL_8; break; case DATA_BITS_7: mode |= AT91_US_CHRL_7; break; case DATA_BITS_6: mode |= AT91_US_CHRL_6; break; case DATA_BITS_5: mode |= AT91_US_CHRL_5; break; default: mode |= AT91_US_CHRL_8; break; } switch (cfg->stop_bits) { case STOP_BITS_2: mode |= AT91_US_NBSTOP_2; break; case STOP_BITS_1: default: mode |= AT91_US_NBSTOP_1; break; } switch (cfg->parity) { case PARITY_ODD: mode |= AT91_US_PAR_ODD; break; case PARITY_EVEN: mode |= AT91_US_PAR_EVEN; break; case PARITY_NONE: default: mode |= AT91_US_PAR_NONE; break; } uart->port->MR = mode; div = (clk_get_rate(clk_get("mck")) / 16 + cfg->baud_rate/2) / cfg->baud_rate; uart->port->BRGR = div; uart->port->CR = AT91_US_RXEN | AT91_US_TXEN; uart->port->IER = 0x01; 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->CSR & TXRDY)); uart->port->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->CSR & RXRDY) { result = uart->port->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; static struct serial_ringbuffer dbgu_int_rx; struct at91_uart dbgu = { DBGU, AT91_ID_SYS }; #endif #if defined(RT_USING_UART0) static struct rt_serial_device serial0; static struct serial_ringbuffer uart0_int_rx; struct at91_uart uart0 = { UART0, AT91SAM9260_ID_US0 }; #endif #if defined(RT_USING_UART1) static struct rt_serial_device serial1; static struct serial_ringbuffer uart1_int_rx; struct at91_uart uart1 = { UART1, AT91SAM9260_ID_US1 }; #endif #if defined(RT_USING_UART2) static struct rt_serial_device serial2; static struct serial_ringbuffer uart2_int_rx; struct at91_uart uart2 = { UART2, AT91SAM9260_ID_US2 }; #endif #if defined(RT_USING_UART3) static struct rt_serial_device serial3; static struct serial_ringbuffer uart3_int_rx; struct at91_uart uart3 = { UART3, AT91SAM9260_ID_US3 }; #endif void at91_usart_gpio_init(void) { rt_uint32_t val; #ifdef RT_USING_DBGU at91_sys_write(AT91_PIOB + PIO_IDR, (1<<14)|(1<<15)); //at91_sys_write(AT91_PIOB + PIO_PUER, (1<<6)); at91_sys_write(AT91_PIOB + PIO_PUDR, (1<<14)|(1<<15)); at91_sys_write(AT91_PIOB + PIO_ASR, (1<<14)|(1<<15)); at91_sys_write(AT91_PIOB + PIO_PDR, (1<<14)|(1<<15)); at91_sys_write(AT91_PMC_PCER, 1 << AT91_ID_SYS); #endif #ifdef RT_USING_UART0 at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_US0); at91_sys_write(AT91_PIOB + PIO_IDR, (1<<4)|(1<<5)); at91_sys_write(AT91_PIOB + PIO_PUER, (1<<4)); at91_sys_write(AT91_PIOB + PIO_PUDR, (1<<5)); at91_sys_write(AT91_PIOB + PIO_ASR, (1<<4)|(1<<5)); at91_sys_write(AT91_PIOB + PIO_PDR, (1<<4)|(1<<5)); #endif #ifdef RT_USING_UART1 at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_US1); at91_sys_write(AT91_PIOB + PIO_IDR, (1<<6)|(1<<7)); at91_sys_write(AT91_PIOB + PIO_PUER, (1<<6)); at91_sys_write(AT91_PIOB + PIO_PUDR, (1<<7)); at91_sys_write(AT91_PIOB + PIO_ASR, (1<<6)|(1<<7)); at91_sys_write(AT91_PIOB + PIO_PDR, (1<<6)|(1<<7)); #endif #ifdef RT_USING_UART2 at91_sys_write(AT91_PMC_PCER, 1 << AT91SAM9260_ID_US2); at91_sys_write(AT91_PIOB + PIO_IDR, (1<<8)|(1<<9)); at91_sys_write(AT91_PIOB + PIO_PUER, (1<<8)); at91_sys_write(AT91_PIOB + PIO_PUDR, (1<<9)); at91_sys_write(AT91_PIOB + PIO_ASR, (1<<8)|(1<<9)); at91_sys_write(AT91_PIOB + PIO_PDR, (1<<8)|(1<<9)); #endif #ifdef RT_USING_UART3 at91_sys_write(AT91_PMC_PCER, 1<