STM32_ExtendedLibs/STM32_General/Src/general_uart.c
Razvalyaev 141ea6bac9 Переструктурирование:
- MyLibs - максимально платформонезависимые библиотеки (кроме разве что RTT)
- RTT
- STM32_General - библиотеки для периферии stm32
2025-10-21 05:03:54 +03:00

384 lines
12 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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