/* * 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 */ }