HAL_UART_Transmit_DMA transmits just once
#ifdef HWVR_AC_CG_NOV25
#include "lpuart.h"
#include "main.h"
UART_HandleTypeDef hlpuart1;
DMA_HandleTypeDef hdma_lpuart1_rx;
DMA_HandleTypeDef hdma_lpuart1_tx;
#define LPUART_RX_BUF_SIZE (uint8_t)1
static volatile uint8_t lpuart_rx_buffer[LPUART_RX_BUF_SIZE]; // Buffer for DMA reception
#define LPUART_TX_BUF_SIZE (uint8_t)64
static volatile uint8_t lpuart_tx_string[LPUART_TX_BUF_SIZE];
static uint8_t lpuart_tx_string_size = 0; // Size of the lpuart_tx_string buffer
#define LPUART_FLAG_RX_COMPLETE ((uint8_t)((uint8_t)1U<<(uint8_t)0U))
#define LPUART_FLAG_READY_TO_SEND ((uint8_t)((uint8_t)1U<<(uint8_t)1U))
#define LPUART_FLAG_TX_ONGOING ((uint8_t)((uint8_t)1U<<(uint8_t)2U))
static volatile uint8_t lpuart_flag = 0;
void_const_uint8_t_p_callback_t lpuart_fill_callback = NULL; // Callback for the loop function
void_void_callback_t lpuart_loop_callback = NULL; // Callback for the loop function
static volatile uint32_t last_timestamp = 0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == LPUART1)
{
// Handle reception complete
if(lpuart_fill_callback != NULL)
{
lpuart_fill_callback((uint8_t *)&(lpuart_rx_buffer[0])); // Call the fill callback with the received data
lpuart_flag |= LPUART_FLAG_RX_COMPLETE; // Set the flag to indicate UART RX complete
last_timestamp = HAL_GetTick(); // Update the timestamp of the last reception
}
}
}
void HAL_UARTEx_TxFifoEmptyCallback(UART_HandleTypeDef *huart)
{
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == LPUART1)
{
// Handle transmission complete
// You can perform additional actions here if needed
lpuart_flag &= ~LPUART_FLAG_TX_ONGOING; // Clear the flag to indicate UART TX complete
}
}
/**
* @brief LPUART1 Initialization Function
* None
* @retval None
*/
mid_error_t MX_LPUART1_UART_Init(void)
{
/* USER CODE BEGIN LPUART1_Init 0 */
/* USER CODE END LPUART1_Init 0 */
/* USER CODE BEGIN LPUART1_Init 1 */
/* USER CODE END LPUART1_Init 1 */
/* USER CODE BEGIN LPUART1_Init 0 */
/* USER CODE END LPUART1_Init 0 */
/* USER CODE BEGIN LPUART1_Init 1 */
/* USER CODE END LPUART1_Init 1 */
hlpuart1.Instance = LPUART1;
hlpuart1.Init.BaudRate = 115200;
hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
hlpuart1.Init.StopBits = UART_STOPBITS_1;
hlpuart1.Init.Parity = UART_PARITY_NONE;
hlpuart1.Init.Mode = UART_MODE_TX_RX;
hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
hlpuart1.FifoMode = UART_FIFOMODE_DISABLE;
if (HAL_UART_Init(&hlpuart1) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&hlpuart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&hlpuart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&hlpuart1) != HAL_OK)
{
Error_Handler();
}
__HAL_UART_ENABLE_IT(&hlpuart1, UART_IT_TC);
if(HAL_UART_Receive_DMA(&hlpuart1,(uint8_t *)lpuart_rx_buffer, (uint8_t)LPUART_RX_BUF_SIZE) != HAL_OK)
{
return MID_ERROR_GENERAL;
}
// Start reception in DMA mode with a buffer of 256 bytes
/* USER CODE BEGIN LPUART1_Init 2 */
return MID_ERROR_OK;
/* USER CODE END LPUART1_Init 2 */
}
mid_error_t lpuart_dma_init()
{
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
RCC_PeriphCLKInitTypeDef PeriphClkInit = { 0 };
__HAL_RCC_DMA1_CLK_ENABLE();
/* USER CODE BEGIN LPUART1_MspInit 0 */
/* USER CODE END LPUART1_MspInit 0 */
/** Initializes the peripherals clocks
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPUART1;
PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
return MID_ERROR_GENERAL ;
}
/* Peripheral clock enable */
__HAL_RCC_LPUART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**LPUART1 GPIO Configuration
PA2 ------> LPUART1_TX
PA3 ------> LPUART1_RX
*/
GPIO_InitStruct.Pin = serial_tx_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_LPUART1;
HAL_GPIO_Init(serial_tx_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = serial_rx_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF6_LPUART1;
HAL_GPIO_Init(serial_rx_GPIO_Port, &GPIO_InitStruct);
/* LPUART1 DMA Init */
/* LPUART1_RX Init */
hdma_lpuart1_rx.Instance = DMA1_Channel2;
hdma_lpuart1_rx.Init.Request = DMA_REQUEST_LPUART1_RX;
hdma_lpuart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_lpuart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_lpuart1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_lpuart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_lpuart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_lpuart1_rx.Init.Mode = DMA_CIRCULAR;
hdma_lpuart1_rx.Init.Priority = DMA_PRIORITY_LOW;
/* LPUART1_TX Init */
hdma_lpuart1_tx.Instance = DMA1_Channel3;
hdma_lpuart1_tx.Init.Request = DMA_REQUEST_LPUART1_TX;
hdma_lpuart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_lpuart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_lpuart1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_lpuart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_lpuart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_lpuart1_tx.Init.Mode = DMA_NORMAL;
hdma_lpuart1_tx.Init.Priority = DMA_PRIORITY_LOW;
if (HAL_DMA_Init(&hdma_lpuart1_rx) != HAL_OK)
{
return MID_ERROR_GENERAL ;
}
if (HAL_DMA_Init(&hdma_lpuart1_tx) != HAL_OK)
{
return MID_ERROR_GENERAL ;
}
__HAL_LINKDMA(&hlpuart1, hdmarx, hdma_lpuart1_rx);
__HAL_LINKDMA(&hlpuart1, hdmatx, hdma_lpuart1_tx);
/* USER CODE BEGIN LPUART1_MspInit 1 */
/* USER CODE END LPUART1_MspInit 1 */
return MID_ERROR_OK ;
}
mid_error_t lpuart_init(void_const_uint8_t_p_callback_t checking_reception_fill_callback_in, void_void_callback_t checking_reception_loop_callback_in)
{
lpuart_set_rx_callback(checking_reception_fill_callback_in);
lpuart_set_loop_callback(checking_reception_loop_callback_in);
if(lpuart_dma_init() != MID_ERROR_OK)
{
return MID_ERROR_GENERAL;
}
if(MX_LPUART1_UART_Init() != MID_ERROR_OK)
{
return MID_ERROR_GENERAL;
}
if(HAL_UART_Receive_DMA(&hlpuart1, (uint8_t *)lpuart_rx_buffer, LPUART_RX_BUF_SIZE) != HAL_OK)
{
return MID_ERROR_GENERAL;
}
return MID_ERROR_OK;
}
mid_error_t lpuart_loop()
{
if (lpuart_flag & LPUART_FLAG_RX_COMPLETE && (HAL_GetTick() - last_timestamp > 10))
{
lpuart_flag &= ~LPUART_FLAG_RX_COMPLETE; // Clear the UART RX complete flag
//uint8_t uart_tx_single_char[1] = {0xCC};
lpuart_loop_callback(); // Call the loop callback function if set
//HAL_UART_Transmit_DMA(&huart1, uart_tx_single_char, 1);
}
else if (lpuart_flag & LPUART_FLAG_READY_TO_SEND)
{
lpuart_flag &= ~LPUART_FLAG_READY_TO_SEND; // Clear the UART TX complete flag
if (lpuart_tx_string_size > 0)
{
// lpuart_tx_string[lpuart_tx_string_size] = '\0'; // Null-terminate the string
// if(HAL_UART_Transmit_DMA(&hlpuart1, (const uint8_t *) lpuart_tx_string, (uint8_t)lpuart_tx_string_size) != HAL_OK)
if(HAL_UART_Transmit_DMA(&hlpuart1, (const uint8_t *) lpuart_tx_string, (uint8_t)lpuart_tx_string_size) != HAL_OK)
{
lpuart_tx_string_size = 0; // Reset the size after sending
return MID_ERROR_GENERAL;
}
else
{
//lpuart_flag |= LPUART_FLAG_TX_ONGOING; // Set the flag to indicate UART TX ongoing
lpuart_tx_string_size = 0; // Reset the size after sending
}
}
else
{
// No data to send, handle as needed
}
}
return MID_ERROR_OK;
}
mid_error_t lpuart_send_data(const uint8_t* data_in, size_t size_in)
{
// This function is a placeholder for sending data over UART.
// Implement the actual data sending logic here.
// For example, you can use HAL_UART_Transmit() to send data.
memset((void *)lpuart_tx_string, 0, LPUART_TX_BUF_SIZE); // Clear the transmit buffer after sending
for (uint8_t i = 0; i < size_in; i++) {
if (i < LPUART_TX_BUF_SIZE)
{
lpuart_tx_string[i] = data_in[i]; // Copy data to the transmit buffer
}
else
{
break; // Prevent buffer overflow
}
}
//lpuart_tx_string[0] = 0x2;
lpuart_tx_string_size = size_in; // Set the size of the data to send
lpuart_flag |= LPUART_FLAG_READY_TO_SEND; // Set the flag to indicate UART RX complete
return MID_ERROR_OK;
}
void lpuart_set_rx_callback(void_const_uint8_t_p_callback_t callback_in)
{
if (callback_in == NULL)
{
// Handle the case where no callback is set, if needed
return;
}
lpuart_fill_callback = callback_in; // Set the fill callback function
}
void lpuart_set_tx_callback(void_void_callback_t callback_in)
{
// Not implemented yet
}
void lpuart_set_loop_callback(void_void_callback_t callback_in)
{
if (callback_in == NULL)
{
// Handle the case where no callback is set, if needed
return;
}
lpuart_loop_callback = callback_in; // Set the loop callback function
}
#endif // HWVR_AC_CG_NOV25
I used the dma with the usart1 and I didn't have any problem... but I wanted to change pinout and use the lpuart and now I am just able to use the HAL_UART_Transmit_DMA once.
PD: I think I solved this problem. But I have another question: the problem occurs because the pinout of the pcb changed so I decided to use the LPUART1 instead of the USART1. It is ok to use 2 different build configurations -or more- for 2 different hardware pinout?? Thank you all.
