/* * File : usart.c * This file is part of RT-Thread RTOS * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rt-thread.org/license/LICENSE * * Change Logs: * Date Author Notes * 2017-12-12 Bluebear233 first implementation */ #include #include #include #include /* Private Define ---------------------------------------------------------------*/ #define USEING_UART0 //Tx:PG2 Rx:PG1 /* Private Typedef --------------------------------------------------------------*/ struct usart { rt_serial_t dev; UART_T *usart_base; }; typedef struct usart* usart_t; /* Private functions ------------------------------------------------------------*/ static rt_err_t usart_gpio_configure(struct rt_serial_device *serial); static rt_err_t usart_configure(struct rt_serial_device *serial, struct serial_configure *cfg); static rt_err_t usart_control(struct rt_serial_device *serial, int cmd, void *arg); static int usart_send(struct rt_serial_device *serial, char c); static int usart_receive(struct rt_serial_device *serial); static void rt_hw_uart_register(usart_t uart, UART_T *uart_base, char *name); static void uart_isr(usart_t serial); //static rt_err_t stm32_uart_tx_dma_configure(rt_stm32_uart_t *serial, rt_bool_t bool); //static rt_err_t stm32_uart_tx_dma_nvic(rt_stm32_uart_t *serial, rt_bool_t bool); /* Private Variables ------------------------------------------------------------*/ static const struct rt_uart_ops stm32_uart_ops = { usart_configure, usart_control, usart_send, usart_receive, RT_NULL }; static const struct serial_configure stm32_uart_default_config = RT_SERIAL_CONFIG_DEFAULT; #ifdef USEING_UART0 struct usart uart0; #endif /* Interrupt Handle Funtion ----------------------------------------------------*/ #ifdef USEING_UART0 /* 串口0 中断入口 */ void UART0_IRQHandler(void) { uart_isr(&uart0); } #endif /** * 中断处理函数 */ static void uart_isr(usart_t serial) { // 获取串口基地址 UART_T *uart_base = ((usart_t)serial)->usart_base; // 获取中断事件 uint32_t u32IntSts= uart_base->INTSTS; // 接收中断 if(u32IntSts & (UART_INTSTS_RDAINT_Msk | UART_INTSTS_RXTOINT_Msk)) { rt_hw_serial_isr(&serial->dev, RT_SERIAL_EVENT_RX_IND); } } /** * 串口端口配置 */ static rt_err_t usart_gpio_configure(struct rt_serial_device *serial) { // 获取串口基地址 UART_T *uart_base = ((usart_t)serial)->usart_base; switch((uint32_t)uart_base) { case UART0_BASE: SYS->GPG_MFPL = SYS_GPG_MFPL_PG1MFP_UART0_RXD | SYS_GPG_MFPL_PG2MFP_UART0_TXD; break; default: rt_kprintf("unknow uart module\n"); RT_ASSERT(0); } return RT_EOK; } /** * 串口配置 */ static rt_err_t usart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) { // 获取串口基地址 UART_T *uart_base = ((usart_t)serial)->usart_base; uint32_t uart_module = 0; uint32_t uart_word_len = 0; uint32_t uart_stop_bit = 0; uint32_t uart_parity = 0; uint32_t uart_irq_channel = 0; switch((uint32_t)uart_base) { case UART0_BASE: uart_module = UART0_MODULE; uart_irq_channel = UART0_IRQn; break; default: rt_kprintf("unknow uart module\n"); RT_ASSERT(0); } /* Enable IP clock */ CLK_EnableModuleClock(uart_module); /* Select IP clock source */ CLK_SetModuleClock(uart_module, CLK_CLKSEL1_UARTSEL_HXT, CLK_CLKDIV0_UART(1)); /* check baudrate */ RT_ASSERT(cfg->baud_rate != 0); /* check word len */ switch(cfg->data_bits) { case DATA_BITS_5: uart_word_len = UART_WORD_LEN_5; break; case DATA_BITS_6: uart_word_len = UART_WORD_LEN_6; break; case DATA_BITS_7: uart_word_len = UART_WORD_LEN_7; break; case DATA_BITS_8: uart_word_len = UART_WORD_LEN_8; break; default: rt_kprintf("unsupose data len"); RT_ASSERT(0); } /* check stop bit */ switch(cfg->stop_bits) { case STOP_BITS_1: uart_stop_bit = UART_STOP_BIT_1; break; case STOP_BITS_2: uart_stop_bit = UART_STOP_BIT_2; break; default: rt_kprintf("unsupose stop bit"); RT_ASSERT(0); } /* check stop bit */ switch(cfg->parity) { case PARITY_NONE: uart_parity = UART_PARITY_NONE; break; case PARITY_ODD: uart_parity = UART_PARITY_ODD; break; case PARITY_EVEN: uart_parity = UART_PARITY_EVEN; break; default: rt_kprintf("unsupose parity"); RT_ASSERT(0); } /* Open uart */ { uint8_t u8UartClkSrcSel; uint32_t u32ClkTbl[4] = {__HXT, 0, __HIRC, __HIRC}; uint32_t u32Clk; uint32_t u32Baud_Div; u32ClkTbl[1] = CLK_GetPLLClockFreq(); u8UartClkSrcSel = (CLK->CLKSEL1 & CLK_CLKSEL1_UARTSEL_Msk) >> CLK_CLKSEL1_UARTSEL_Pos; uart_base->FUNCSEL = UART_FUNCSEL_UART; uart_base->LINE = uart_word_len | uart_stop_bit | uart_parity; uart_base->FIFO = 6 << UART_FIFO_RFITL_Pos; uart_base->TOUT = (1 << UART_TOUT_DLY_Pos) | (40 << UART_TOUT_TOIC_Pos); u32Clk = (u32ClkTbl[u8UartClkSrcSel]) / (((CLK->CLKDIV0 & CLK_CLKDIV0_UARTDIV_Msk) >> CLK_CLKDIV0_UARTDIV_Pos) + 1); u32Baud_Div = UART_BAUD_MODE2_DIVIDER(u32Clk, cfg->baud_rate); if (u32Baud_Div > 0xFFFF) uart_base->BAUD = (UART_BAUD_MODE0 | UART_BAUD_MODE0_DIVIDER(u32Clk, cfg->baud_rate)); else uart_base->BAUD = (UART_BAUD_MODE2 | u32Baud_Div); } /* config nvic */ NVIC_EnableIRQ(uart_irq_channel); /* config gpio */ usart_gpio_configure(serial); return RT_EOK; } /** * 串口中断控制 */ static rt_err_t usart_control(struct rt_serial_device *serial, int cmd, void *arg) { rt_err_t result = RT_EOK; rt_uint32_t flag; // 获取串口基地址 UART_T *uart_base = ((usart_t)serial)->usart_base; switch ((uint32_t) arg) { case RT_DEVICE_FLAG_INT_RX: flag = UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk | UART_INTEN_TOCNTEN_Msk; switch (cmd) { case RT_DEVICE_CTRL_CLR_INT: UART_DISABLE_INT(uart_base, flag); break; case RT_DEVICE_CTRL_SET_INT: UART_ENABLE_INT(uart_base, flag); break; default: RT_ASSERT(0); } break; // TODO 完善DMA接口 // case RT_DEVICE_FLAG_DMA_TX: // USART_DMACmd(dev->usart_base, USART_DMAReq_Tx, ENABLE); // stm32_uart_tx_dma_configure(dev, RT_TRUE); // stm32_uart_tx_dma_nvic(dev, RT_TRUE); // break; default: RT_ASSERT(0) ; } return result; return RT_EOK; } /** * 串口发送函数 */ static int usart_send(struct rt_serial_device *serial, char c) { // 获取串口基地址 UART_T *uart_base = ((usart_t)serial)->usart_base; // 等待FIFO 发送 while(uart_base->FIFOSTS & UART_FIFOSTS_TXFULL_Msk); // 发送字符 uart_base->DAT = c; return 1; } /** * 串口接收函数 */ static int usart_receive(struct rt_serial_device *serial) { // 获取串口基地址 UART_T *uart_base = ((usart_t)serial)->usart_base; // 如果FIFO 为空返回 if(uart_base->FIFOSTS & UART_FIFOSTS_RXEMPTY_Msk) { return -1; } return UART_READ(uart_base); } /** * @brief 串口设备注册 * @param uart : UART设备结构体 * @param uart_base : STM32 UART外设基地址 * @param name : STM32 UART设备名 * @param tx_dma_channel : STM32 UART TX的DMA通道基地址(可选) */ static void rt_hw_uart_register(usart_t usart, UART_T * uart_base, char *name) { rt_uint32_t flag; RT_ASSERT(usart != RT_NULL); RT_ASSERT(uart_base != RT_NULL); // 没有定义对应的硬件I2C if (!(uart_base == UART0 || uart_base == UART1 || uart_base == UART2 || uart_base == UART3 || uart_base == UART4 || uart_base == UART5)) { RT_ASSERT(0); } usart->usart_base = uart_base; usart->dev.ops = &stm32_uart_ops; usart->dev.config = stm32_uart_default_config; flag = RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX; rt_hw_serial_register(&usart->dev, name, flag, RT_NULL); } /** * 硬件串口注册 */ void rt_hw_usart_init(void) { #ifdef USEING_UART0 rt_hw_uart_register(&uart0, UART0, "uart0"); #endif }