/* * File : drv_uart.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2017, 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 * 2017-05-30 Bernard the first version * 2018-03-15 flyingcys add amebaz */ #include #include #include #include "board.h" #include "drv_uart.h" struct device_uart { serial_t serial; rt_uint32_t irqno; }; #ifdef RT_USING_UART0 static struct rt_serial_device serial0; static struct device_uart uart0; #endif static rt_err_t ameba_uart_configure (struct rt_serial_device *serial, struct serial_configure *cfg); static rt_err_t ameba_uart_control (struct rt_serial_device *serial, int cmd, void *arg); static int ameba_uart_putc (struct rt_serial_device *serial, char c); static int ameba_uart_getc (struct rt_serial_device *serial); static rt_size_t ameba_uart_dma_transmit (struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction); static void ameba_uart_irq(uint32_t id, SerialIrq event); const struct rt_uart_ops _uart_ops = { ameba_uart_configure, ameba_uart_control, ameba_uart_putc, ameba_uart_getc, ameba_uart_dma_transmit }; /* * UART interface */ static rt_err_t ameba_uart_configure (struct rt_serial_device *serial, struct serial_configure *cfg) { rt_uint32_t baud_div; struct device_uart * uart; RT_ASSERT(serial != RT_NULL); serial->config = *cfg; uart = serial->parent.user_data; RT_ASSERT(uart != RT_NULL); /* Set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */ serial_format(&uart->serial, 8, ParityNone, 1); /* set baudrate */ serial_baud(&uart->serial, 115200); return (RT_EOK); } static rt_err_t ameba_uart_control (struct rt_serial_device *serial, int cmd, void *arg) { struct device_uart * uart; uart = serial->parent.user_data; RT_ASSERT(uart != RT_NULL); switch (cmd) { case RT_DEVICE_CTRL_CLR_INT: /* Disable the UART Interrupt */ serial_irq_set(&uart->serial, RxIrq, 0); serial_irq_handler(&uart->serial, RT_NULL, 0); break; case RT_DEVICE_CTRL_SET_INT: /* install interrupt */ serial_irq_handler(&uart->serial, ameba_uart_irq, (uint32_t)serial); /* Enable the UART Interrupt */ serial_irq_set(&uart->serial, RxIrq, 1); break; } return (RT_EOK); } static int ameba_uart_putc (struct rt_serial_device *serial, char c) { struct device_uart* uart; uart = serial->parent.user_data; /* FIFO status, contain valid data */ /* write data */ serial_putc(&uart->serial, c); return (1); } static int ameba_uart_getc (struct rt_serial_device *serial) { struct device_uart* uart = serial->parent.user_data; if(!serial_readable(&uart->serial)) return -1; /* Receive Data Available */ return serial_getc(&uart->serial); } static rt_size_t ameba_uart_dma_transmit (struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, int direction) { return (0); } static void ameba_uart_irq(uint32_t id, SerialIrq event) { struct rt_serial_device *serial = (struct rt_serial_device *)id; if(event == RxIrq) { rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); } else if(event == TxIrq) { } } static rt_err_t dbg_configure(struct rt_serial_device *serial, struct serial_configure *cfg); static rt_err_t dbg_control(struct rt_serial_device *serial, int cmd, void *arg); static int dbg_putc(struct rt_serial_device *serial, char c); static int dbg_getc(struct rt_serial_device *serial); static struct rt_serial_device ameba_dbg_serial; const struct rt_uart_ops _ambed_dbg_ops = { dbg_configure, dbg_control, dbg_putc, dbg_getc, RT_NULL, }; static rt_err_t dbg_configure(struct rt_serial_device *serial, struct serial_configure *cfg) { LOGUART_SetBaud(115200); return RT_EOK; } void dbg_uart_irq_handler(void * data) { u32 IrqEn = DiagGetIsrEnReg(); DiagSetIsrEnReg(0); rt_hw_serial_isr(&ameba_dbg_serial, RT_SERIAL_EVENT_RX_IND); DiagSetIsrEnReg(IrqEn); } static rt_err_t dbg_control(struct rt_serial_device *serial, int cmd, void *arg) { switch (cmd) { case RT_DEVICE_CTRL_CLR_INT: /* Disable the UART Interrupt */ NVIC_DisableIRQ(UART_LOG_IRQ); /* this is rom_code_patch */ break; case RT_DEVICE_CTRL_SET_INT: /* install interrupt */ DIAG_UartReInit((IRQ_FUN) dbg_uart_irq_handler); /* Enable the UART Interrupt */ NVIC_SetPriority(UART_LOG_IRQ, 10); /* this is rom_code_patch */ break; } return (RT_EOK); } static int dbg_putc(struct rt_serial_device *serial, char c) { DiagPutChar(c); return 1; }; static int dbg_getc(struct rt_serial_device *serial) { int c = -1; if(!UART_Readable(UART2_DEV)) return -1; c = DiagGetChar(_FALSE); return c; } /* * UART Initiation */ int rt_hw_uart_init(void) { struct rt_serial_device *serial; struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; #ifdef RT_USING_UART0 { struct device_uart *uart; serial = &serial0; uart = &uart0; /* Init UART Hardware */ serial_init(&uart->serial, UART_TX, UART_RX); serial->ops = &_uart_ops; serial->config = config; serial->config.baud_rate = 115200; uart->irqno = UART0_IRQ; rt_hw_serial_register(serial, "uart0", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart); } #endif { serial = &ameba_dbg_serial; serial->ops = &_ambed_dbg_ops; serial->config = config; rt_hw_serial_register(serial, RT_CONSOLE_DEVICE_NAME, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, RT_NULL); } return 0; }