/** ************************************************************************** * @file general_uart.c * @brief Модуль для инициализации UART. ************************************************************************** Реализация функций для работы с UART: - Инициализация UART и его линий RX/TX - Настройка DMA для UART - Настройка GPIO для UART - Настройка NVIC и тактирования UART **************************************************************************/ #include "general_uart.h" #include "general_gpio.h" //------------------------------------------------------------------- //------------------------UART INIT FUNCTIONS------------------------ /** * @brief Инициализация UART с помощью структуры UART_SettingsTypeDef. * @param suart Указатель на структуру с настройками UART. * @return HAL status. * @details * Инициализирует UART и его GPIO и при необходимости DMA. * Настройка аналогична HAL_UART_Init * @code * suart.huart.Init... * @endcode * но дополнительно надо прописать пины RX/TX @ref UART_SettingsTypeDef * @code * suart->GPIOx, suart->GPIO_PIN_RX, suart->GPIO_PIN_TX * @endcode */ HAL_StatusTypeDef UART_Base_Init(UART_SettingsTypeDef *suart) { // function takes setting structure for init // check is settings are valid if(UART_Check_Init_Struct(suart) != HAL_OK) return HAL_ERROR; suart->huart.Init.Mode = UART_MODE_TX_RX; UART_MspInit(&suart->huart); if (HAL_UART_Init(&suart->huart) != HAL_OK) { MyLibs_Error_Handler(); return HAL_ERROR; } // init gpio from UARTSettings structure UART_GPIO_Init(suart->GPIOx, suart->GPIO_PIN_RX, suart->GPIO_PIN_TX); __HAL_UART_ENABLE_IT(&suart->huart, UART_IT_IDLE); // init dma from UARTSettings structure if need if (suart->DMAChannel != 0) UART_DMA_Init(&suart->huart, suart->huart.hdmarx, suart->DMAChannel, suart->DMA_CHANNEL_X); return HAL_OK; } /** * @brief Инициализация GPIO для UART. * @param GPIOx Порт для настройки. * @param GPIO_PIN_RX Пин для приема. * @param GPIO_PIN_TX Пин для передачи. */ void UART_GPIO_Init(GPIO_TypeDef *GPIOx, uint16_t GPIO_PIN_RX, uint16_t GPIO_PIN_TX) { // function takes port and pins (for rx and tx) GPIO_InitTypeDef GPIO_InitStruct = {0}; // choose port for enable clock GPIO_Clock_Enable(GPIOx); //USART3 GPIO Configuration //GPIO_PIN_TX ------> USART_TX //GPIO_PIN_RX ------> USART_RX #if defined(STM32F4xx) // gpio init for 407 GPIO_InitStruct.Pin = GPIO_PIN_TX|GPIO_PIN_RX; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF7_USART3; HAL_GPIO_Init(GPIOx, &GPIO_InitStruct); #elif defined(STM32F1xx) // gpio init for atm403/stm103 //GPIO_PIN_TX ------> USART_TX GPIO_InitStruct.Pin = GPIO_PIN_TX; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOx, &GPIO_InitStruct); // GPIO_PIN_RX ------> USART_RX GPIO_InitStruct.Pin = GPIO_PIN_RX; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOx, &GPIO_InitStruct); #endif } /** * @brief Инициализация DMA для UART. * @param huart Указатель на хендл UART. * @param hdma_rx Указатель на хендл DMA для линии приема UART. * @param DMAChannel Указатель на канал DMA/поток DMA в STM32F407. * @param DMA_CHANNEL_X Канал DMA. */ void UART_DMA_Init(UART_HandleTypeDef *huart, DMA_HandleTypeDef *hdma_rx, DMA_Stream_TypeDef *DMAChannel, uint32_t DMA_CHANNEL_X) { // function takes uart and dma handlers and dmachannel for uart // for now only dma rx is supported, tx maybe later if needed // calc defines on boot_project_setup.h /* USART3 DMA Init */ /* USART3_RX Init */ hdma_rx->Instance = DMAChannel; #if defined(STM32F4xx) // dma channel choose for 407 hdma_rx->Init.Channel = DMA_CHANNEL_X; #endif hdma_rx->Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_rx->Init.PeriphInc = DMA_PINC_DISABLE; hdma_rx->Init.MemInc = DMA_MINC_ENABLE; hdma_rx->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_rx->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_rx->Init.Mode = DMA_CIRCULAR; hdma_rx->Init.Priority = DMA_PRIORITY_LOW; if (HAL_DMA_Init(hdma_rx) != HAL_OK) { MyLibs_Error_Handler(); } __USER_LINKDMA(huart,hdmarx,hdma_rx); // __USER_LINKDMA is need because __HAL_LINKDMA is written for global defined hdma_rx // so you get error because hal uses . insted of -> } /** * @brief Настройка тактирования и прерываний UART. * @param huart Указатель на хендл UART. * @note Чтобы не генерировать функцию с иницилизацией неиспользуемых UART, дефайнами @ref UART_INIT в @ref general_uart.h определяются используемые UART. */ void UART_MspInit(UART_HandleTypeDef *huart) // analog for hal function { // __RCC_DMA_UART_CLK_ENABLE(); // /* DMA interrupt init */ // /* DMA1_Stream1_IRQn interrupt configuration */ // HAL_NVIC_SetPriority(DMA_UART_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(DMA_UART_IRQn); // rcc, dma and interrupt init for USARTs // GPIO init was moved to own functions UART_GPIO_Init if(0); #ifdef USE_USART1 else if(huart->Instance==USART1) { /* DMA2 clock enable */ __HAL_RCC_DMA2_CLK_ENABLE(); /* DMA interrupt init */ HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); /* USART1 clock enable */ __HAL_RCC_USART1_CLK_ENABLE(); /* USART1 interrupt Init */ HAL_NVIC_SetPriority(USART1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART1_IRQn); } #endif // USE_USART1 #ifdef USE_USART2 else if(huart->Instance==USART2) { /* DMA1 clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA interrupt init */ HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); /* USART2 clock enable */ __HAL_RCC_USART2_CLK_ENABLE(); /* USART2 interrupt Init */ HAL_NVIC_SetPriority(USART2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART2_IRQn); } #endif // USE_USART2 #ifdef USE_USART3 else if(huart->Instance==USART3) { /* DMA1 clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA interrupt init */ HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn); /* USART3 clock enable */ __HAL_RCC_USART3_CLK_ENABLE(); /* USART3 interrupt Init */ HAL_NVIC_SetPriority(USART3_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART3_IRQn); } #endif // USE_USART3 #ifdef USE_UART4 else if(huart->Instance==UART4) { /* DMA1 clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA interrupt init */ HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn); /* UART4 clock enable */ __HAL_RCC_UART4_CLK_ENABLE(); /* UART4 interrupt Init */ HAL_NVIC_SetPriority(UART4_IRQn, 0, 0); HAL_NVIC_EnableIRQ(UART4_IRQn); } #endif // USE_UART4 #ifdef USE_UART5 else if(huart->Instance==UART5) { /* DMA1 clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* DMA interrupt init */ HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn); /* UART5 clock enable */ __HAL_RCC_DMA1_CLK_ENABLE(); /* UART5 interrupt Init */ HAL_NVIC_SetPriority(UART5_IRQn, 0, 0); HAL_NVIC_EnableIRQ(UART5_IRQn); } #endif // USE_UART5 #ifdef USE_USART6 else if(huart->Instance==USART6) { /* DMA2 clock enable */ __HAL_RCC_DMA2_CLK_ENABLE(); /* DMA interrupt init */ HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn); /* USART6 clock enable */ __HAL_RCC_USART6_CLK_ENABLE(); /* USART6 interrupt Init */ HAL_NVIC_SetPriority(USART6_IRQn, 0, 0); HAL_NVIC_EnableIRQ(USART6_IRQn); } #endif // USE_USART6 } /** * @brief Деинициализация тактирования и прерываний UART. * @param huart Указатель на хендл UART. * @note Чтобы не генерировать функцию с деиницилизацией неиспользуемых UART, дефайнами @ref UART_INIT в @ref general_uart.h определяются используемые UART. */ void UART_MspDeInit(UART_HandleTypeDef *huart) // analog for hal function { // rcc, dma and interrupt init for USARTs // GPIO init was moved to own functions UART_GPIO_Init if(0); #ifdef USE_USART1 else if(huart->Instance==USART1) { // /* DMA2 clock enable */ // __HAL_RCC_DMA2_CLK_ENABLE(); // /* DMA interrupt init */ // HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn); /* USART1 clock reset */ __HAL_RCC_USART1_FORCE_RESET(); __HAL_RCC_USART1_RELEASE_RESET(); } #endif // USE_USART1 #ifdef USE_USART2 else if(huart->Instance==USART2) { // /* DMA1 clock enable */ // __HAL_RCC_DMA1_CLK_ENABLE(); // /* DMA interrupt init */ // HAL_NVIC_SetPriority(DMA1_Stream5_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(DMA1_Stream5_IRQn); /* USART2 clock reset */ __HAL_RCC_USART2_FORCE_RESET(); __HAL_RCC_USART2_RELEASE_RESET(); } #endif // USE_USART2 #ifdef USE_USART3 else if(huart->Instance==USART3) { // /* DMA1 clock enable */ // __HAL_RCC_DMA1_CLK_ENABLE(); // /* DMA interrupt init */ // HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn); /* USART3 clock reset */ __HAL_RCC_USART3_FORCE_RESET(); __HAL_RCC_USART3_RELEASE_RESET(); } #endif // USE_USART3 #ifdef USE_UART4 else if(huart->Instance==UART4) { // /* DMA1 clock enable */ // __HAL_RCC_DMA1_CLK_ENABLE(); // /* DMA interrupt init */ // HAL_NVIC_SetPriority(DMA1_Stream2_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(DMA1_Stream2_IRQn); /* UART4 clock reset */ __HAL_RCC_UART4_FORCE_RESET(); __HAL_RCC_UART4_RELEASE_RESET(); } #endif // USE_UART4 #ifdef USE_UART5 else if(huart->Instance==UART5) { // /* DMA1 clock enable */ // __HAL_RCC_DMA1_CLK_ENABLE(); // /* DMA interrupt init */ // HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn); /* UART5 clock reset */ __HAL_RCC_UART5_FORCE_RESET(); __HAL_RCC_UART5_RELEASE_RESET(); } #endif // USE_UART5 #ifdef USE_USART6 else if(huart->Instance==USART6) { // /* DMA2 clock enable */ // __HAL_RCC_DMA2_CLK_ENABLE(); // /* DMA interrupt init */ // HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0); // HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn); /* USART6 clock reset */ __HAL_RCC_USART6_FORCE_RESET(); __HAL_RCC_USART6_RELEASE_RESET(); } #endif // USE_USART6 } /** * @brief Проверка корректности структуры инициализации UART. * @param suart Указатель на структуру с настройками UART. * @return HAL status. */ HAL_StatusTypeDef UART_Check_Init_Struct(UART_SettingsTypeDef *suart) { // check is settings are valid if (!IS_UART_INSTANCE(suart->huart.Instance)) return HAL_ERROR; if (!IS_UART_BAUDRATE(suart->huart.Init.BaudRate) || (suart->huart.Init.BaudRate == NULL)) return HAL_ERROR; if (!IS_GPIO_ALL_INSTANCE(suart->GPIOx)) return HAL_ERROR; if (!IS_GPIO_PIN(suart->GPIO_PIN_RX) && !IS_GPIO_PIN(suart->GPIO_PIN_TX)) // if both pins arent set up return HAL_ERROR; return HAL_OK; } //------------------------UART INIT FUNCTIONS------------------------ //-------------------------------------------------------------------