cancel
Showing results for 
Search instead for 
Did you mean: 

Can I retrigger a HAL_UART_Receive_IT() in HAL_UART_RxCpltCallback() ?

magene
Senior II

I'm trying to talk to a device that sends a 122 byte message every 500 milliseconds at 115.2 KBaud. I can make it work with HAL_UART_Receive_IT() in a while loop as shown here.

#include <stm32l4xx_hal.h>
#include <stm32_hal_legacy.h>
 
#include <iostream>
#include <string.h>
using namespace std;
	
#ifdef __cplusplus
extern "C"
#endif
	
void SysTick_Handler(void)
{
	HAL_IncTick();
	HAL_SYSTICK_IRQHandler();
}
 
void lpuart1RXIdleCallback(UART_HandleTypeDef *huart);
void configureUART();
 
static UART_HandleTypeDef s_UARTHandle = UART_HandleTypeDef();
 
#define RXBufferSize 122
static uint8_t RXBuffer[RXBufferSize];
extern "C" void LPUART1_IRQHandler()
{
	HAL_UART_IRQHandler(&s_UARTHandle);
}
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	cout << uwTick << "  RXBuffer: " << RXBuffer;
}
 
int main(void)
{
	HAL_Init();
 
	configureUART();
	
	while (1)
	{
		memset(RXBuffer, 0, sizeof(RXBuffer));
		HAL_UART_Receive_IT(&s_UARTHandle, RXBuffer, RXBufferSize);
		HAL_Delay(400);
	}
}

I'd like to make the 500 millisecond much, much less. Seems like I should be able to execute the HAL_UART_Receive_IT() once and then re-execute it in the HAL_UART_RXCpltCallback() like this but the HAL_UART_RXCpltCallback() doesn't ever get called.

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	memset(RXBuffer, 0, sizeof(RXBuffer));
	HAL_UART_Receive_IT(&s_UARTHandle, RXBuffer, RXBufferSize);
 
	cout << uwTick << "  RXBuffer: " << RXBuffer << endl;
}
 
int main(void)
{
	HAL_Init();
 
	configureUART();
	
	memset(RXBuffer, 0, sizeof(RXBuffer));
	cout << "Sending first Receive_IT()" << endl;
	HAL_UART_Receive_IT(&s_UARTHandle, RXBuffer, RXBufferSize);
 
	cout << "Starting while loop" << endl;
	while (1)
	{
		//		memset(RXBuffer, 0, sizeof(RXBuffer));
		//		HAL_UART_Receive_IT(&s_UARTHandle, RXBuffer, RXBufferSize);
		//		HAL_Delay(400);
	}
}

Any help will be greatly appreciated, thanks.

And here's configUART() for reference

void configureUART()
{
	__LPUART1_CLK_ENABLE();
	__GPIOC_CLK_ENABLE();
	
	GPIO_InitTypeDef GPIO_InitStructure;
 
	GPIO_InitStructure.Pin = GPIO_PIN_1;
	GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStructure.Alternate = GPIO_AF8_LPUART1;
	GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
	GPIO_InitStructure.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
	
	GPIO_InitStructure.Pin = GPIO_PIN_0;
	GPIO_InitStructure.Mode = GPIO_MODE_AF_OD;
	GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
	HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
	
	s_UARTHandle.Instance = LPUART1;
	s_UARTHandle.Init.BaudRate = 115200;
	s_UARTHandle.Init.WordLength = UART_WORDLENGTH_8B;
	s_UARTHandle.Init.StopBits = UART_STOPBITS_1;
	s_UARTHandle.Init.Parity = UART_PARITY_NONE;
	s_UARTHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	s_UARTHandle.Init.Mode = UART_MODE_TX_RX;
	
	if (HAL_UART_Init(&s_UARTHandle) != HAL_OK)
	{
		cout << "Error in UART_Init" << endl;
		while (1) {}
	}
	
	NVIC_EnableIRQ(LPUART1_IRQn);
}

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

> Can I retrigger a HAL_UART_Receive_IT() in HAL_UART_RxCpltCallback() ?

Yes, you can. Debug the program and see why yours is getting stuck in an error/idle state.

Verify that HAL_UART_Receive_IT returns HAL_OK every time you call it.

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

3 REPLIES 3
TDK
Guru

> Can I retrigger a HAL_UART_Receive_IT() in HAL_UART_RxCpltCallback() ?

Yes, you can. Debug the program and see why yours is getting stuck in an error/idle state.

Verify that HAL_UART_Receive_IT returns HAL_OK every time you call it.

If you feel a post has answered your question, please click "Accept as Solution".
magene
Senior II

@TDK​ Well that was it, many thanks. I should have figured that out on my own but now I've got "Always check the return value" in my list of best practices. Here's what I'm doing now if anyone else is interested.

HAL_UART_StateTypeDef uartStateReturn;
HAL_StatusTypeDef halStatusReturn;
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	cout << endl << uwTick << "  RXBuffer: " << RXBuffer << endl;
}
 
int main(void)
{
	HAL_Init();
 
	configureUART();
	
	cout << "Checking UART State in main" << endl;
	uartStateReturn = HAL_UART_GetState(&s_UARTHandle);
	if (uartStateReturn != 32)
	{
		uartStateReturn = HAL_UART_GetState(&s_UARTHandle);
		cout << "HAL_UART_GetState: " << uartStateReturn << endl; 
		HAL_Delay(100);
	}
	else
		cout << "HAL_UART_GetState == 32" << endl;
 
	cout << "Starting while loop" << endl;
	while (1)
	{
		memset(RXBuffer, 0, sizeof(RXBuffer));
		halStatusReturn = HAL_UART_Receive_IT(&s_UARTHandle, RXBuffer, RXBufferSize);
		while (halStatusReturn != HAL_OK)
		{
			//cout << uwTick << "  Sent HAL_UART_Receive_IT, return: " << halStatusReturn << endl;
			HAL_Delay(1);
			halStatusReturn = HAL_UART_Receive_IT(&s_UARTHandle, RXBuffer, RXBufferSize);
		}
	}
}

Thanks again.

magene
Senior II

BTW, the next step is to write the data out to SD card. My plan is to have a RXBuffer1 and a RXBuffer2. The first HAL_UART_Receive_IT will use RXBuffer1. When that data arrives, I can send the next HAL_UART_Receive_IT with RXBuffer2 while I write RXBuffer1 out to the SD card, then switch back to RXBuffer1 and so on for a couple of hours of data. I'll keep increasing the rate at which messages get sent until the SD card can't keep up.