From 97de1e7407327b2569d37dcbe60b5b6a30df60a2 Mon Sep 17 00:00:00 2001 From: michael Date: Tue, 2 Feb 2021 09:33:38 +0800 Subject: bsp:ls1b:rework uart driver and fix some bugs to make it work. tested on ls1b dev board which make by Loongson(GuangZhou) --- bsp/ls1bdev/drivers/drv_uart.c | 222 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) create mode 100644 bsp/ls1bdev/drivers/drv_uart.c (limited to 'bsp/ls1bdev/drivers/drv_uart.c') diff --git a/bsp/ls1bdev/drivers/drv_uart.c b/bsp/ls1bdev/drivers/drv_uart.c new file mode 100644 index 0000000000..8f469f26ed --- /dev/null +++ b/bsp/ls1bdev/drivers/drv_uart.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-05-08 zhuangwei the first version + * 2021-02-02 michael5hzg@gmail.com adapt to ls1b + */ +#include +#include +#include +#include "drv_uart.h" +#include "ls1b_pin.h" +#include "ls1b_uart.h" + +/* STM32 uart driver */ +struct rt_uart_ls1b +{ + ls1b_uart_t UARTx; + rt_uint32_t IRQ; +}; + +static rt_err_t ls1b_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + struct rt_uart_ls1b *uart_dev = RT_NULL; + ls1b_uart_info_t uart_info = {0}; + + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + uart_dev = (struct rt_uart_ls1b *)serial->parent.user_data; + + // 初始化串口 + uart_info.UARTx = uart_dev->UARTx; + uart_info.baudrate = cfg->baud_rate; + uart_info.rx_enable = TRUE; + uart_init(&uart_info); + + return RT_EOK; + +} + +static rt_err_t ls1b_uart_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + struct rt_uart_ls1b *uart_dev = RT_NULL; + + RT_ASSERT(serial != RT_NULL); + uart_dev = (struct rt_uart_ls1b *)serial->parent.user_data; + + switch (cmd) + { + case RT_DEVICE_CTRL_CLR_INT: /* disable rx irq */ + rt_hw_interrupt_mask(uart_dev->IRQ); + break; + + case RT_DEVICE_CTRL_SET_INT: /* enable rx irq */ + rt_hw_interrupt_umask(uart_dev->IRQ); + break; + + default: + break; + } + + return RT_EOK; + +} + +static int ls1b_uart_putc(struct rt_serial_device *serial, char c) +{ + struct rt_uart_ls1b *uart_dev = RT_NULL; + + RT_ASSERT(serial != RT_NULL); + + uart_dev = (struct rt_uart_ls1b *)serial->parent.user_data; + uart_putc(uart_dev->UARTx, c); + + return 1; +} + +static int ls1b_uart_getc(struct rt_serial_device *serial) +{ + struct rt_uart_ls1b *uart_dev = RT_NULL; + + RT_ASSERT(serial != RT_NULL); + + uart_dev = (struct rt_uart_ls1b *)serial->parent.user_data; + void *uart_base = uart_get_base(uart_dev->UARTx); + + if (LSR_RXRDY & reg_read_8(uart_base + LS1B_UART_LSR_OFFSET)) + { + return reg_read_8(uart_base + LS1B_UART_DAT_OFFSET); + } + + return -1; +} + +/* UART interrupt handler */ +static void uart_irq_handler(int vector, void *param) +{ + struct rt_serial_device *serial = (struct rt_serial_device *)param; + struct rt_uart_ls1b *uart_dev = RT_NULL; + + RT_ASSERT(serial != RT_NULL); + + uart_dev = (struct rt_uart_ls1b *)serial->parent.user_data; + void *uart_base = uart_get_base(uart_dev->UARTx); + unsigned char iir = reg_read_8(uart_base + LS1B_UART_IIR_OFFSET); + + // 判断是否为接收超时或接收到有效数据 + if ((IIR_RXTOUT & iir) || (IIR_RXRDY & iir)) + { + rt_interrupt_enter(); + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); + rt_interrupt_leave(); + } + +} + +static const struct rt_uart_ops ls1b_uart_ops = +{ + ls1b_uart_configure, + ls1b_uart_control, + ls1b_uart_putc, + ls1b_uart_getc, +}; + + +#if defined(RT_USING_UART1) +struct rt_uart_ls1b uart1 = +{ + LS1B_UART1, + LS1B_UART1_IRQ, +}; +struct rt_serial_device serial1; +#endif /* RT_USING_UART1 */ + +#if defined(RT_USING_UART2) +struct rt_uart_ls1b uart2 = +{ + LS1B_UART2, + LS1B_UART2_IRQ, +}; +struct rt_serial_device serial2; +#endif /* RT_USING_UART2 */ + + +#if defined(RT_USING_UART3) +struct rt_uart_ls1b uart3 = +{ + LS1B_UART3, + LS1B_UART3_IRQ, +}; +struct rt_serial_device serial3; +#endif /* RT_USING_UART3 */ + +#if defined(RT_USING_UART4) +struct rt_uart_ls1b uart4 = +{ + LS1B_UART4, + LS1B_UART4_IRQ, +}; +struct rt_serial_device serial4; +#endif /* RT_USING_UART4 */ + +#if defined(RT_USING_UART5) +struct rt_uart_ls1b uart5 = +{ + LS1B_UART5, + LS1B_UART5_IRQ, +}; +struct rt_serial_device serial5; +#endif /* RT_USING_UART5 */ + + + +void rt_hw_uart_init(void) +{ + struct rt_uart_ls1b *uart; + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; + +#ifdef RT_USING_UART5 + uart = &uart5; + + serial5.ops = &ls1b_uart_ops; + serial5.config = config; + + rt_hw_interrupt_install(uart->IRQ, uart_irq_handler, &serial5, "UART5"); + + /* register UART5 device */ + rt_hw_serial_register(&serial5, + "uart5", + //RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_RX, + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + uart); +#endif /* RT_USING_UART5 */ + + +#ifdef RT_USING_UART2 + uart = &uart2; + + serial2.ops = &ls1b_uart_ops; + serial2.config = config; + + pin_set_purpose(36, PIN_PURPOSE_OTHER); + pin_set_purpose(37, PIN_PURPOSE_OTHER); + pin_set_remap(36, PIN_REMAP_SECOND); + pin_set_remap(37, PIN_REMAP_SECOND); + + rt_hw_interrupt_install(uart->IRQ, uart_irq_handler, &serial2, "UART2"); + + /* register UART2 device */ + rt_hw_serial_register(&serial2, + "uart2", + //RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_RX, + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, + uart); +#endif /* RT_USING_UART2 */ + +} + -- cgit v1.3.1