/* * File : usart.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006-2013, RT-Thread Development Team * * 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 * 2009-01-05 Bernard the first version * 2010-03-29 Bernard remove interrupt Tx and DMA Rx mode * 2013-05-13 aozima update for kehong-lingtai. * 2015-01-31 armink make sure the serial transmit complete in putc() * 2016-05-13 armink add DMA Rx mode * 2017-01-19 aubr.cool add interrupt Tx mode * 2017-04-13 aubr.cool correct Rx parity err * 2017-10-20 ZYH porting to HAL Libraries(with out DMA) */ #include "board.h" #include /* STM32 uart driver */ struct stm32_uart { UART_HandleTypeDef huart; IRQn_Type irq; }; static rt_err_t stm32_configure(struct rt_serial_device *serial, struct serial_configure *cfg) { struct stm32_uart *uart; RT_ASSERT(serial != RT_NULL); RT_ASSERT(cfg != RT_NULL); uart = (struct stm32_uart *)serial->parent.user_data; uart->huart.Init.BaudRate = cfg->baud_rate; uart->huart.Init.HwFlowCtl = UART_HWCONTROL_NONE; uart->huart.Init.Mode = UART_MODE_TX_RX; uart->huart.Init.OverSampling = UART_OVERSAMPLING_16; switch (cfg->data_bits) { case DATA_BITS_8: uart->huart.Init.WordLength = UART_WORDLENGTH_8B; break; case DATA_BITS_9: uart->huart.Init.WordLength = UART_WORDLENGTH_9B; break; default: uart->huart.Init.WordLength = UART_WORDLENGTH_8B; break; } switch (cfg->stop_bits) { case STOP_BITS_1: uart->huart.Init.StopBits = UART_STOPBITS_1; break; case STOP_BITS_2: uart->huart.Init.StopBits = UART_STOPBITS_2; break; default: uart->huart.Init.StopBits = UART_STOPBITS_1; break; } switch (cfg->parity) { case PARITY_NONE: uart->huart.Init.Parity = UART_PARITY_NONE; break; case PARITY_ODD: uart->huart.Init.Parity = UART_PARITY_ODD; break; case PARITY_EVEN: uart->huart.Init.Parity = UART_PARITY_EVEN; break; default: uart->huart.Init.Parity = UART_PARITY_NONE; break; } if (HAL_UART_Init(&uart->huart) != HAL_OK) { return RT_ERROR; } return RT_EOK; } static rt_err_t stm32_control(struct rt_serial_device *serial, int cmd, void *arg) { struct stm32_uart* uart; // rt_uint32_t ctrl_arg = (rt_uint32_t)(arg); RT_ASSERT(serial != RT_NULL); uart = (struct stm32_uart *)serial->parent.user_data; switch (cmd) { /* disable interrupt */ case RT_DEVICE_CTRL_CLR_INT: /* disable rx irq */ NVIC_DisableIRQ(uart->irq); /* disable interrupt */ __HAL_UART_DISABLE_IT(&uart->huart, USART_IT_RXNE); break; /* enable interrupt */ case RT_DEVICE_CTRL_SET_INT: /* enable rx irq */ NVIC_EnableIRQ(uart->irq); /* enable interrupt */ __HAL_UART_ENABLE_IT(&uart->huart, USART_IT_RXNE); break; } return RT_EOK; } static int stm32_putc(struct rt_serial_device *serial, char c) { struct stm32_uart* uart; RT_ASSERT(serial != RT_NULL); uart = (struct stm32_uart *)serial->parent.user_data; while(__HAL_UART_GET_FLAG(&uart->huart,UART_FLAG_TXE) == RESET); uart->huart.Instance->DR = c; return 1; } static int stm32_getc(struct rt_serial_device *serial) { int ch; struct stm32_uart* uart; RT_ASSERT(serial != RT_NULL); uart = (struct stm32_uart *)serial->parent.user_data; ch = -1; if (__HAL_UART_GET_FLAG(&uart->huart,UART_FLAG_RXNE) != RESET) { ch = uart->huart.Instance->DR & 0xff; } return ch; } /** * Uart common interrupt process. This need add to uart ISR. * * @param serial serial device */ static void uart_isr(struct rt_serial_device *serial) { struct stm32_uart *uart = (struct stm32_uart *) serial->parent.user_data; RT_ASSERT(uart != RT_NULL); if((__HAL_UART_GET_FLAG(&uart->huart, UART_FLAG_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&uart->huart,UART_IT_RXNE) != RESET)) { rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); __HAL_UART_CLEAR_FLAG(&uart->huart,UART_FLAG_RXNE); } } static const struct rt_uart_ops stm32_uart_ops = { stm32_configure, stm32_control, stm32_putc, stm32_getc, }; #if defined(RT_USING_UART1) /* UART1 device driver structure */ struct stm32_uart uart1 = { {USART1}, USART1_IRQn }; struct rt_serial_device serial1; void USART1_IRQHandler(void) { /* enter interrupt */ rt_interrupt_enter(); uart_isr(&serial1); /* leave interrupt */ rt_interrupt_leave(); } #endif /* RT_USING_UART1 */ #if defined(RT_USING_UART2) /* UART1 device driver structure */ struct stm32_uart uart2 = { {USART2}, USART2_IRQn }; struct rt_serial_device serial2; void USART2_IRQHandler(void) { /* enter interrupt */ rt_interrupt_enter(); uart_isr(&serial2); /* leave interrupt */ rt_interrupt_leave(); } #endif /* RT_USING_UART2 */ #if defined(RT_USING_UART3) /* UART1 device driver structure */ struct stm32_uart uart3 = { {USART3}, USART3_IRQn }; struct rt_serial_device serial3; void USART3_IRQHandler(void) { /* enter interrupt */ rt_interrupt_enter(); uart_isr(&serial3); /* leave interrupt */ rt_interrupt_leave(); } #endif /* RT_USING_UART2 */ static void MX_USART_UART_Init(UART_HandleTypeDef* uartHandle); void rt_hw_usart_init(void) { struct stm32_uart* uart; struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; __HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); #if defined(RT_USING_UART1) uart = &uart1; config.baud_rate = BAUD_RATE_115200; serial1.ops = &stm32_uart_ops; serial1.config = config; MX_USART_UART_Init(&uart->huart); /* register UART1 device */ rt_hw_serial_register(&serial1, "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX , uart); #endif /* RT_USING_UART1 */ #if defined(RT_USING_UART2) uart = &uart2; config.baud_rate = BAUD_RATE_115200; serial2.ops = &stm32_uart_ops; serial2.config = config; MX_USART_UART_Init(&uart->huart); /* register UART1 device */ rt_hw_serial_register(&serial2, "uart2", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX , uart); #endif /* RT_USING_UART1 */ #if defined(RT_USING_UART3) uart = &uart3; config.baud_rate = BAUD_RATE_115200; serial3.ops = &stm32_uart_ops; serial3.config = config; MX_USART_UART_Init(&uart->huart); /* register UART1 device */ rt_hw_serial_register(&serial3, "uart3", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX , uart); #endif /* RT_USING_UART1 */ } static void MX_USART_UART_Init(UART_HandleTypeDef* uartHandle) { uartHandle->Init.BaudRate = 115200; uartHandle->Init.WordLength = UART_WORDLENGTH_8B; uartHandle->Init.StopBits = UART_STOPBITS_1; uartHandle->Init.Parity = UART_PARITY_NONE; uartHandle->Init.Mode = UART_MODE_TX_RX; uartHandle->Init.HwFlowCtl = UART_HWCONTROL_NONE; uartHandle->Init.OverSampling = UART_OVERSAMPLING_16; RT_ASSERT(HAL_UART_Init(uartHandle) == HAL_OK); } /* USART2 init function */ void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) { GPIO_InitTypeDef GPIO_InitStruct; if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspInit 0 */ /* USER CODE END USART1_MspInit 0 */ /* USART1 clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART1 interrupt Init */ HAL_NVIC_SetPriority(USART1_IRQn, 5, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspInit 1 */ /* USER CODE END USART1_MspInit 1 */ } else if(uartHandle->Instance==USART2) { /* USER CODE BEGIN USART2_MspInit 0 */ /* USER CODE END USART2_MspInit 0 */ /* USART2 clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USART2 interrupt Init */ HAL_NVIC_SetPriority(USART2_IRQn, 5, 0); HAL_NVIC_EnableIRQ(USART2_IRQn); /* USER CODE BEGIN USART2_MspInit 1 */ /* USER CODE END USART2_MspInit 1 */ } else if(uartHandle->Instance==USART3) { /* USER CODE BEGIN USART3_MspInit 0 */ /* USER CODE END USART3_MspInit 0 */ /* USART3 clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); /**USART3 GPIO Configuration PB10 ------> USART3_TX PB11 ------> USART3_RX */ GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_11; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* USART3 interrupt Init */ HAL_NVIC_SetPriority(USART3_IRQn, 5, 0); HAL_NVIC_EnableIRQ(USART3_IRQn); /* USER CODE BEGIN USART3_MspInit 1 */ /* USER CODE END USART3_MspInit 1 */ } } void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle) { if(uartHandle->Instance==USART1) { /* USER CODE BEGIN USART1_MspDeInit 0 */ /* USER CODE END USART1_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART1_CLK_DISABLE(); /**USART1 GPIO Configuration PA9 ------> USART1_TX PA10 ------> USART1_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10); /* USART1 interrupt Deinit */ HAL_NVIC_DisableIRQ(USART1_IRQn); /* USER CODE BEGIN USART1_MspDeInit 1 */ /* USER CODE END USART1_MspDeInit 1 */ } else if(uartHandle->Instance==USART2) { /* USER CODE BEGIN USART2_MspDeInit 0 */ /* USER CODE END USART2_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART2_CLK_DISABLE(); /**USART2 GPIO Configuration PA2 ------> USART2_TX PA3 ------> USART2_RX */ HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3); /* USART2 interrupt Deinit */ HAL_NVIC_DisableIRQ(USART2_IRQn); /* USER CODE BEGIN USART2_MspDeInit 1 */ /* USER CODE END USART2_MspDeInit 1 */ } else if(uartHandle->Instance==USART3) { /* USER CODE BEGIN USART3_MspDeInit 0 */ /* USER CODE END USART3_MspDeInit 0 */ /* Peripheral clock disable */ __HAL_RCC_USART3_CLK_DISABLE(); /**USART3 GPIO Configuration PB10 ------> USART3_TX PB11 ------> USART3_RX */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_11); /* USART3 interrupt Deinit */ HAL_NVIC_DisableIRQ(USART3_IRQn); /* USER CODE BEGIN USART3_MspDeInit 1 */ /* USER CODE END USART3_MspDeInit 1 */ } }