Skip to main content
mrsmile
Associate III
June 6, 2023
Solved

How to transmit five byte data transmit in UART_DMA?

  • June 6, 2023
  • 10 replies
  • 8789 views

I already try for send five byte data in UART DMA. I am using the controller in STM32G030K6T6. Data transmition is working properly but output is did not taken properly. The problem was am transmit data five bytes for UART_DMA but DMA transmit only two bytes data. HAL_UART_Transmit_DMA call in timer interrupt handler to check the output for just now. The output is came but this is not proper output. this method for just call in to the interrupt handler output is continuously came for five bytes data. I need a output for 500 millisec once Five Bytes data transmit.  I attach the output for picture and code. please tell what can I do for next step.


_legacyfs_online_stmicro_images_0693W00000bVgJtQAK.png
_legacyfs_online_stmicro_images_0693W00000bVgJjQAK.png

#include "main.h"
 
 TIM_HandleTypeDef htim3;
 
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart2_tx;
 
/* USER CODE BEGIN PV */
 
uint16_t tim=0;
 
uint8_t tx_buf[5]= {0x01,0x02,0x03,0x04,0x05};
 
 
/* USER CODE END PV */
 
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM3_Init(void);
 
int main(void)
{
 
 HAL_Init();
 
 
 SystemClock_Config();
 
 
 MX_GPIO_Init();
 MX_DMA_Init();
 MX_USART2_UART_Init();
 MX_TIM3_Init();
 /* USER CODE BEGIN 2 */
	
	HAL_TIM_Base_Start_IT(&htim3);
	HAL_UART_Transmit_DMA(&huart2, tx_buf, sizeof(tx_buf)); // 500 msec once
 /* USER CODE END 2 */
 
 while (1)
 {
 
 }
}
 
void TIM3_IRQHandler(void)
{
 /* USER CODE BEGIN TIM3_IRQn 0 */
 
 /* USER CODE END TIM3_IRQn 0 */
 HAL_TIM_IRQHandler(&htim3);
 /* USER CODE BEGIN TIM3_IRQn 1 */
		 tim++;	
	
	 if(tim==500)
	 {
		__HAL_DMA_ENABLE(huart2.hdmatx);
		 tx_buf[0] = 0x01;
		 tx_buf[1] = 0x02;
		 tx_buf[2] = 0x03;
		 tx_buf[3] = 0x04;
		 tx_buf[4] = 0x05;
 	 		tim=0; 	
		__HAL_DMA_DISABLE(huart2.hdmatx);
	 }
 /* USER CODE END TIM3_IRQn 1 */
}

This topic has been closed for replies.
Best answer by RomainR.

it is already declared and initialized as global.

volatile uint16_t prevTick=0;

But it's not correct, you must declare it as uint32_t because Systick timer is a 24bit down counter size.

And it should not be volatile.

Take a look at step 2°) in my example. and apply it:

int main(void)
{
 /* USER CODE BEGIN 1 */
 uint32_t prevTick = 0;
 
 /* USER CODE END 1 */
 
 /* MCU Configuration--------------------------------------------------------*/
 
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();

Then put a breakpoint into stm32g0xx_it.c into following Systick Interrupt handler at line HAL_IncTick(); This to validate Systick interrupt is enabled and is working.

/**
 * @brief This function handles System tick timer.
 */
void SysTick_Handler(void)
{
 /* USER CODE BEGIN SysTick_IRQn 0 */
 
 /* USER CODE END SysTick_IRQn 0 */
 HAL_IncTick();
 /* USER CODE BEGIN SysTick_IRQn 1 */
 
 /* USER CODE END SysTick_IRQn 1 */
}

Good luck

10 replies

RomainR.
ST Employee
June 6, 2023

Hello @mrsmile (Community Member)

To better understand your use case and according your diagram, you want to send 5 bytes with UART and DMA, then wait a delay of 500ms ... send again 5 bytes and so on ?  

Regards,

Romain,

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
mrsmile
mrsmileAuthor
Associate III
June 6, 2023

yes, I want to send 5 bytes wit UART and DMA, then wait a delay 500 ms. if you know guide me.

RomainR.
ST Employee
June 6, 2023

Yes here my example in 4 steps:

1°) Create this global variable after your buffer: dmaXferCptl 

/* USER CODE BEGIN PV */
uint8_t tx_buf[5]= {0x01 ,0x02 ,0x03, 0x04, 0x05};
volatile uint8_t dmaXferCptl = 0;
/* USER CODE END PV */

2°) Create a local variable in main function.

/* USER CODE BEGIN 1 */
 uint32_t prevTick = 0;
/* USER CODE END 1 */

3°) Create the UART callback to update this variables somewhere in user code begin 4.

/* USER CODE BEGIN 4 */
/**
 * @brief Tx Transfer completed callback.
 * @param huart UART handle.
 * @retval None
 */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
 if (huart->Instance == USART2)
 {
 dmaXferCptl = 1;
 }
}
/* USER CODE END 4 */

4°) Implement while loop in main function without using GP Timer, you can use Systick.

/* Infinite loop */
 /* USER CODE BEGIN WHILE */
 while (1)
 {
 /* Wait 500ms before sending UART bufer */
 if ((HAL_GetTick() - prevTick ) > 500)
 {
 if (HAL_UART_Transmit_DMA(&huart2, (uint8_t *)tx_buf, 5) != HAL_OK)
 {
 /* Manage UART DMA Transfert here */
 Error_Handler();
 }
 /* Wait DMA Transfert complete */
 while (dmaXferCptl == 0){;}
 dmaXferCptl = 0;
 /* Toggle a Led for fun */
 HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_5);
 prevTick = HAL_GetTick();
 
 }
 /* USER CODE END WHILE */
 
 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */

Can you try it and let me know?

Regards,

Romain,

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
mrsmile
mrsmileAuthor
Associate III
June 6, 2023

How can I generate (HAL_GetTick() - prevTick ) > 500 this delay. out is continuously send the data.

#include "main.h"
 
 TIM_HandleTypeDef htim3;
 
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart2_tx;
 
/* USER CODE BEGIN PV */
 
uint16_t tim=0;
 
uint8_t tx_buf[5]= {0x01,0x02,0x03,0x04,0x05};
volatile uint8_t test_flag=0;
 
/* USER CODE END PV */
 
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM3_Init(void);
 
int main(void)
{
 
 HAL_Init();
 
 
 SystemClock_Config();
 
 
 MX_GPIO_Init();
 MX_DMA_Init();
 MX_USART2_UART_Init();
 MX_TIM3_Init();
 /* USER CODE BEGIN 2 */
	
	HAL_TIM_Base_Start_IT(&htim3);
//	HAL_UART_Transmit_DMA(&huart2, tx_buf, sizeof(tx_buf)); // 500 msec once
 /* USER CODE END 2 */
 
 while (1)
 {
		if ((HAL_GetTick() - tim ) > 500)
 {
 if (HAL_UART_Transmit_DMA(&huart2, (uint8_t *)tx_buf, 5) != HAL_OK)
 {
 Error_Handler();
 }
 }
		 while (test_flag == 0){;}
 test_flag = 0;
 tim = HAL_GetTick();	}}


_legacyfs_online_stmicro_images_0693W00000bViA0QAK.png.

RomainR.
ST Employee
June 6, 2023

This delay is generated by cpu CM0 Systick Timer and it is normally enabled when you generate a STM32CubeMX project.

The Systick is configured by HAL_Init() below to generate an interrupt every ms.

Do you use STM32CubeMX, STM32G0 HAL library?

In other case, share your full code.

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
mrsmile
mrsmileAuthor
Associate III
June 6, 2023

ok I will share. how initialize prevtick variable and condition can not enter the uart call back function. flag is not enable.

#include "main.h"
 
 TIM_HandleTypeDef htim3;
 
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart2_tx;
 
/* USER CODE BEGIN PV */
 
uint16_t tim=0;
 
uint8_t tx_buf[5]= {0x01,0x02,0x03,0x04,0x05};
volatile uint8_t test_flag=0; uint16_t prevTick=0;
 
/* USER CODE END PV */
 
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_TIM3_Init(void);
 
int main(void)
{
 
 HAL_Init();
 
 
 SystemClock_Config();
 
 
 MX_GPIO_Init();
 MX_DMA_Init();
 MX_USART2_UART_Init();
 MX_TIM3_Init();
 /* USER CODE BEGIN 2 */
	
	HAL_TIM_Base_Start_IT(&htim3);
//	HAL_UART_Transmit_DMA(&huart2, tx_buf, sizeof(tx_buf)); // 500 msec once
 /* USER CODE END 2 */
 
 while (1)
 {
		if ((HAL_GetTick() - prevTick ) > 500)
 {
 if (HAL_UART_Transmit_DMA(&huart2, (uint8_t *)tx_buf, 5) != HAL_OK)
 {
 Error_Handler();
 }
 }
		 while (test_flag == 0){;}
 test_flag = 0;
 prevTick = HAL_GetTick();		 
		
		
//	 if(tim==500)
//	 {
//		 
//		 if (HAL_UART_Transmit_DMA(&huart2, (uint8_t *)tx_buf, 5) != HAL_OK)
// {
// Error_Handler();
// }
//		 		 while (test_flag == 0){;}
// test_flag = 0;
//					 tim=0;
					 
					 
//		__HAL_DMA_ENABLE(huart2.hdmatx);
//		 tx_buf[0] = 0x01;
//		 tx_buf[1] = 0x02;
//		 tx_buf[2] = 0x03;
//		 tx_buf[3] = 0x04;
//		 tx_buf[4] = 0x05;
// 	 		tim=0; 	
//		__HAL_DMA_DISABLE(huart2.hdmatx);
		 }
//	 }
		
		
}
 
void TIM3_IRQHandler(void)
{
 /* USER CODE END TIM3_IRQn 0 */
 HAL_TIM_IRQHandler(&htim3);
 /* USER CODE BEGIN TIM3_IRQn 1 */
		 tim++;	 // 500 ms timer increament
	
 
 /* USER CODE END TIM3_IRQn 1 */
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance == USART2)
	{
		test_flag =1;
	}
	
}
 
 
void SystemClock_Config(void)
{
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 
 /** Configure the main internal regulator output voltage
 */
 HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
 
 /** Initializes the RCC Oscillators according to the specified parameters
 * in the RCC_OscInitTypeDef structure.
 */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
 RCC_OscInitStruct.HSIState = RCC_HSI_ON;
 RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
 RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
 RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV1;
 RCC_OscInitStruct.PLL.PLLN = 8;
 RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
 RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 Error_Handler();
 }
 
 /** Initializes the CPU, AHB and APB buses clocks
 */
 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
 |RCC_CLOCKTYPE_PCLK1;
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
 
 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
 {
 Error_Handler();
 }
}
 
/**
 * @brief TIM3 Initialization Function
 * @param None
 * @retval None
 */
static void MX_TIM3_Init(void)
{
 
 /* USER CODE BEGIN TIM3_Init 0 */
 
 /* USER CODE END TIM3_Init 0 */
 
 TIM_ClockConfigTypeDef sClockSourceConfig = {0};
 TIM_MasterConfigTypeDef sMasterConfig = {0};
 
 /* USER CODE BEGIN TIM3_Init 1 */
 
 /* USER CODE END TIM3_Init 1 */
 htim3.Instance = TIM3;
 htim3.Init.Prescaler = 2;
 htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
 htim3.Init.Period = 22999;
 htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
 if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
 {
 Error_Handler();
 }
 sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
 if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
 {
 Error_Handler();
 }
 sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
 if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN TIM3_Init 2 */
 
 /* USER CODE END TIM3_Init 2 */
 
}
 
/**
 * @brief USART2 Initialization Function
 * @param None
 * @retval None
 */
static void MX_USART2_UART_Init(void)
{
 
 /* USER CODE BEGIN USART2_Init 0 */
 
 /* USER CODE END USART2_Init 0 */
 
 /* USER CODE BEGIN USART2_Init 1 */
 
 /* USER CODE END USART2_Init 1 */
 huart2.Instance = USART2;
 huart2.Init.BaudRate = 9600;
 huart2.Init.WordLength = UART_WORDLENGTH_8B;
 huart2.Init.StopBits = UART_STOPBITS_1;
 huart2.Init.Parity = UART_PARITY_NONE;
 huart2.Init.Mode = UART_MODE_TX;
 huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
 huart2.Init.OverSampling = UART_OVERSAMPLING_16;
 huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
 huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
 huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
 if (HAL_UART_Init(&huart2) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN USART2_Init 2 */
 
 /* USER CODE END USART2_Init 2 */
 
}
 
/**
 * Enable DMA controller clock
 */
static void MX_DMA_Init(void)
{
 
 /* DMA controller clock enable */
 __HAL_RCC_DMA1_CLK_ENABLE();
 
 /* DMA interrupt init */
 /* DMA1_Channel1_IRQn interrupt configuration */
 HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
 
}
 
/**
 * @brief GPIO Initialization Function
 * @param None
 * @retval None
 */
static void MX_GPIO_Init(void)
{
 GPIO_InitTypeDef GPIO_InitStruct = {0};
 
 /* GPIO Ports Clock Enable */
 __HAL_RCC_GPIOC_CLK_ENABLE();
 __HAL_RCC_GPIOA_CLK_ENABLE();
 
 /*Configure GPIO pin : PC15 */
 GPIO_InitStruct.Pin = GPIO_PIN_15;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
 GPIO_InitStruct.Alternate = GPIO_AF1_OSC;
 HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
}
 
/* USER CODE BEGIN 4 */
 
/* USER CODE END 4 */
 
/**
 * @brief This function is executed in case of error occurrence.
 * @retval None
 */
void Error_Handler(void)
{
 /* USER CODE BEGIN Error_Handler_Debug */
 /* User can add his own implementation to report the HAL error return state */
 __disable_irq();
 while (1)
 {
 }
 /* USER CODE END Error_Handler_Debug */
}
 
#ifdef USE_FULL_ASSERT
/**
 * @brief Reports the name of the source file and the source line number
 * where the assert_param error has occurred.
 * @param file: pointer to the source file name
 * @param line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t *file, uint32_t line)
{
 /* USER CODE BEGIN 6 */
 /* User can add his own implementation to report the file name and line number,
 ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
 /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

RomainR.
RomainR.Best answer
ST Employee
June 6, 2023

it is already declared and initialized as global.

volatile uint16_t prevTick=0;

But it's not correct, you must declare it as uint32_t because Systick timer is a 24bit down counter size.

And it should not be volatile.

Take a look at step 2°) in my example. and apply it:

int main(void)
{
 /* USER CODE BEGIN 1 */
 uint32_t prevTick = 0;
 
 /* USER CODE END 1 */
 
 /* MCU Configuration--------------------------------------------------------*/
 
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();

Then put a breakpoint into stm32g0xx_it.c into following Systick Interrupt handler at line HAL_IncTick(); This to validate Systick interrupt is enabled and is working.

/**
 * @brief This function handles System tick timer.
 */
void SysTick_Handler(void)
{
 /* USER CODE BEGIN SysTick_IRQn 0 */
 
 /* USER CODE END SysTick_IRQn 0 */
 HAL_IncTick();
 /* USER CODE BEGIN SysTick_IRQn 1 */
 
 /* USER CODE END SysTick_IRQn 1 */
}

Good luck

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
mrsmile
mrsmileAuthor
Associate III
June 6, 2023

same problem continued. uart call back function does not run and flag is not enable.

RomainR.
ST Employee
June 6, 2023

So, zip your full project and share it here, I will look it.

What is your board?

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
mrsmile
mrsmileAuthor
Associate III
June 6, 2023

I attach my full code.

RomainR.
ST Employee
June 6, 2023

A similar question for a same device is active.

https://community.st.com/s/question/0D53W00002HkOODSA3/stm32g030-uartdma

Does it comes from you too?

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
mrsmile
mrsmileAuthor
Associate III
June 6, 2023

this question is another member post.

RomainR.
ST Employee
June 6, 2023

Here back a working solution. I tested it on STM32G030 and I get array buffer bytes every 500ms.

In your initial USART_ChecK, the Systick interrupt never happens. I don't know why?

Let try it and let me know ?

Best regards,

Romain,

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
RomainR.
ST Employee
June 6, 2023

I join as an attachment a capture using oscilloscope.

C1: Is the USART2 DMA transfer each 500ms (small vertical yellow line each 500ms) corresponding to HAL_UART_Transmit_DMA()

And

Z1: Is zoom window of one vertical yellow line, it shows the bytes array transmitted.


_legacyfs_online_stmicro_images_0693W00000bVj7rQAC.png

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
mrsmile
mrsmileAuthor
Associate III
June 7, 2023

ok, which code your using. are you using systick timer code.

RomainR.
ST Employee
June 7, 2023

Hi @mrsmile (Community Member)

I use the code USART_CheK_ST in the archive that I send to you. It uses the Systick Timer and that's the capture I show.

Does it works now for you?

Does it helps?

Thank you for feedback.

romain

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
mrsmile
mrsmileAuthor
Associate III
June 7, 2023

Thank you so much your response @RomainR.​ sir, code is working properly sir and Five bytes data send UART_DMA in 500 ms once working good.

RomainR.
ST Employee
June 7, 2023

Very good new.

In this case, thank you to apply the following below:

In order to give better visibility on the answered topics, please click on 'Select as Best' on the reply which solved your issue or answered your question. See also 'Best Answers'

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
mrsmile
mrsmileAuthor
Associate III
June 9, 2023

Hi @RomainR.​  sir,

 when i generated a new project and i followed the step to have provided me but it doesn't work it get stuck in error handler. Can you please explain me the process you have done.

Karl Yamashita
Lead III
June 13, 2023

Sorry, late reply. I started to write code but i got busy so couldn't finish it until now.

Actually you need to look at the HAL status. Maybe as a stripped down code that only transmit, then it may work when HAL_UART_TxCpltCallback is called and you set a flag.

ST has poor example code that doesn't show how to recover if a transmit (or receive) returns HAL_BUSY. Instead of calling Error_Handler they should show how to set a flag and check if you need to try to send the data again.

The below code shows how to set a flag if HAL_BUSY is returned and how to continue trying to send again. I am using a ring buffer that can currently hold up to 4 queues with up to 128 bytes. If the transmit fails then it won't increment the queue until HAL_OK all the while you can still add data to the queue without corrupting the pending queue to be sent.

/*
 * PollingRoutine.c
 *
 * Created on: Jun 6, 2023
 * Author: karl.yamashita
 */
 
 
#include "main.h"
 
extern UART_HandleTypeDef huart2;
 
UART_TxDataStruct uart2_tx = {0};
uint32_t prevTick = 0;
 
uint8_t tx_buf[5]= {0x01,0x02,0x03,0x04,0x05};
 // called before main while loop
void PollingInit(void)
{
 
}
 
// called from inside main while loop
void PollingRoutine(void)
{
	if ((HAL_GetTick() - prevTick ) > 500)
	{
		UART_AddMessage(tx_buf, 5);
		HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
		prevTick = HAL_GetTick();
	}
 
	UART_Transmit(&uart2_tx);
}
 
/*
 * Description: Add data to queue to be sent
 */
void UART_AddMessage(uint8_t *data, uint32_t size)
{
	memcpy(&uart2_tx.Queue[uart2_tx.ptr.index_IN].data, data, size);
	uart2_tx.uartBufferSize = size;
	RingBuff_Ptr_Input(&uart2_tx.ptr, UART_QUEUE_SIZE);
}
 
/*
 * Description: Check if there is a message to be sent. Only increment output queue if status return HAL_OK.
 *				If HAL_BUSY then HAL did not accept the new data pointer so we need to try and send again on next go around
 */
void UART_Transmit(UART_TxDataStruct *buf)
{
	if(buf->ptr.cnt_Handle)
	{
		if(HAL_UART_Transmit_DMA(&huart2, buf->Queue[buf->ptr.index_OUT].data, buf->uartBufferSize) == HAL_OK)
		{
			RingBuff_Ptr_Output(&buf->ptr, UART_QUEUE_SIZE); //
		}
	}
}

/*
 * PollingRoutine.h
 *
 * Created on: Jun 6, 2023
 * Author: karl.yamashita
 */
 
#ifndef INC_POLLINGROUTINE_H_
#define INC_POLLINGROUTINE_H_
 
 
#define UART_BUFFER_SIZE 128
#define UART_QUEUE_SIZE 4 // increase if many messages are placed in queue before UART can finished with first message in order to avoid a buffer overrun
 
typedef struct
{
	struct
	{
		uint8_t data[UART_BUFFER_SIZE];
	}Queue[UART_QUEUE_SIZE];
	uint32_t uartBufferSize; // the size of data to be received in the DMA
	RING_BUFF_STRUCT ptr;
}UART_TxDataStruct;
 
void PollingInit(void);
void PollingRoutine(void);
 
void UART_AddMessage(uint8_t *data, uint32_t size);
void UART_Transmit(UART_TxDataStruct *buf);
 
#endif /* INC_POLLINGROUTINE_H_ */

/*
 * RingBuffer.c
 *
 * Created on: Sep 18, 2019
 * Author: Karl
 *
 *
*/
 
#include "main.h"
#include "ringBuffer.h"
 
 
void RingBuff_Ptr_Reset(RING_BUFF_STRUCT *ptr) {
	ptr->index_IN = 0;
	ptr->index_OUT = 0;
 
	ptr->cnt_Handle = 0;
	ptr->cnt_OverFlow = 0;
}
 
void RingBuff_Ptr_Input(RING_BUFF_STRUCT *ptr, uint32_t bufferSize) {
	ptr->index_IN++;
	if (ptr->index_IN >= bufferSize)
		ptr->index_IN = 0;
 
	ptr->cnt_Handle++;
	if (ptr->index_IN == ptr->index_OUT) {
		ptr->cnt_OverFlow++;
		if (ptr->cnt_OverFlow > RING_BUFF_OVERFLOW_SIZE)
			ptr->cnt_OverFlow = 0;
		if (ptr->index_IN == 0) {
			ptr->index_OUT = bufferSize - 1;
		} else {
			ptr->index_OUT = ptr->index_IN - 1;
		}
		ptr->cnt_Handle = 1;
	}
}
 
void RingBuff_Ptr_Output(RING_BUFF_STRUCT *ptr, uint32_t bufferSize) {
	if (ptr->cnt_Handle) {
		ptr->index_OUT++;
		if (ptr->index_OUT >= bufferSize)
			ptr->index_OUT = 0;
		ptr->cnt_Handle--;
	}
}

#ifndef RING_BUFFER_H
#define RING_BUFFER_H
 
#include "main.h"
 
#define RING_BUFF_OVERFLOW_SIZE 100
 
typedef struct {
	uint32_t index_IN; // pointer to where the data will be save to
	uint32_t index_OUT; // pointer to next available data in buffer if cnt_handle is not zero
	uint32_t cnt_Handle; // if not zero then message available
	uint32_t cnt_OverFlow; // has overflow if not zero
}RING_BUFF_STRUCT;
 
void RingBuff_Ptr_Reset(RING_BUFF_STRUCT *ptr);
void RingBuff_Ptr_Input(RING_BUFF_STRUCT *ptr, uint32_t bufferSize);
void RingBuff_Ptr_Output(RING_BUFF_STRUCT *ptr, uint32_t bufferSize);
 
 
 
#endif // RING_BUFFER_H

If a reply has proven helpful, click on Accept as Solution so that it'll show at top of the post.CAN Jammer an open source CAN bus hacking toolCANableV3 Open Source