Skip to main content
Manojkumar Subramaniam
Associate III
January 21, 2019
Question

UART hal RX interrupt modification

  • January 21, 2019
  • 11 replies
  • 3504 views

My scenario I have a master controller keep sending 30Bytes of data with every 500ms..

Issue when use to my slave controller is :

HAL_UART_Receive_IT(&huart1, varPtr, 20);

the packet might not be received properly as the slave is hot swapped.. it can be listening while the transmission going... so that HAL function get's crazy as it's using some pointer increment... So i was looking for a way for sync the start, my master always start with sending a char 'H' so in someway i have to keep the counter resetting to start point when first byte is not 'H'..

I did this hack it only works once why ? my hack start from line 34 to 45

static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
 uint16_t* tmp;
 
 /* Check that a Rx process is ongoing */
 if(huart->RxState == HAL_UART_STATE_BUSY_RX) 
 {
 if(huart->Init.WordLength == UART_WORDLENGTH_9B)
 {
 tmp = (uint16_t*) huart->pRxBuffPtr;
 if(huart->Init.Parity == UART_PARITY_NONE)
 {
 *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF);
 huart->pRxBuffPtr += 2U;
 }
 else
 {
 *tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x00FF);
 //if the pRx
 if( (huart->pRxBuffPtr == varPtr) && ( (uint8_t)(huart->Instance->DR & 0xFF) != 'H' ) )
 {
 	huart->pRxBuffPtr = varPtr;
 }
 else
 {
 huart->pRxBuffPtr += 1U;
 }
 }
 }
 else
 {
 if(huart->Init.Parity == UART_PARITY_NONE)
 {
 	 // *tmp = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
 	 if( (huart->pRxBuffPtr == varPtr) && ( (uint8_t)(huart->Instance->DR & 0xFF) != 'H' ) )
 	 {
 
 	 	huart->pRxBuffPtr = varPtr;
 	 	*huart->pRxBuffPtr = 'F';
 	 }
 	 else
 	 {
 	 //huart->pRxBuffPtr += 1U;
 	 *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
 	 }
 
 
 }
 else
 {
 *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
 }
 }
 
 if(--huart->RxXferCount == 0U)
 {
 /* Disable the UART Parity Error Interrupt and RXNE interrupt*/
 CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
 
 /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
 CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
 
 /* Rx process is completed, restore huart->RxState to Ready */
 huart->RxState = HAL_UART_STATE_READY;
 
 HAL_UART_RxCpltCallback(huart);
 
 return HAL_OK;
 }
 return HAL_OK;
 }
 else
 {
 return HAL_BUSY;
 }
}

This topic has been closed for replies.

11 replies

Tesla DeLorean
Guru
January 21, 2019

uint16_t* tmp;

...

*tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x00FF);

Should probably make sure the code path that gets you there actually initializes the pointer.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Manojkumar Subramaniam
Associate III
January 21, 2019

fixed check again... :)

Tesla DeLorean
Guru
January 21, 2019

No, still wrong. Would also recommend not editing the top post as it damages thread integrity and context of answers/responses.

Couldn't you have just initialized the pointer properly?

Reading DR multiple times is not going to result in the correct response.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
S.Ma
Principal
January 21, 2019

Make sure in the code that the pointer never exceed a max value or it may go out of bound. It is also assumed that H won't occur within a valid data stream.

Manojkumar Subramaniam
Associate III
January 21, 2019

see updated edited the code but still not working..

After Forever
Senior III
January 21, 2019
 if( (huart->pRxBuffPtr == varPtr) && ( (uint8_t)(huart->Instance->DR & 0xFF) != 'H' ) )
 {
 huart->pRxBuffPtr = varPtr;
 *huart->pRxBuffPtr = 'F';
 }
 else
 {
 *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
 }

I don't get it, if you are checking in the if that "huart->pRxBuffPtr == varPtr" then why are you doing "huart->pRxBuffPtr = varPtr;"? Either the check is unnecessary/mistake, or the assignment.

Tesla DeLorean
Guru
January 21, 2019

Reading the DR twice will also be problematic

Does the pointer need to advance in 'F' case?

Unsure of the logic involved here

{
 uint8_t data = (uint8_t)(huart->Instance->DR & 0xFF) ; // Read once
 if( (huart->pRxBuffPtr == varPtr) && (data != 'H' ) ) // correct comparison?
 {
 huart->pRxBuffPtr = varPtr;
 *huart->pRxBuffPtr = 'F'; // Should pointer advance?
 }
 else
 {
 *huart->pRxBuffPtr++ =data;
 }
}

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Manojkumar Subramaniam
Associate III
January 21, 2019

the reason i did that was because my header frame packet starts with 'H' and varPtr checking to see if it's still at first byte... ideally the first byte should be 'H' if it's not don't allow the pointer to increment and write F to varPtr[0]; to indicate Failed

S.Ma
Principal
January 21, 2019

I would recommend to change the message formatting to follow the universally known text terminal mode and searching for "\n" as termination character. When doing something quite well used, it's easier to find others helping in the details or on the web.

Manojkumar Subramaniam
Associate III
January 21, 2019
 else
 
 {
 
 uint8_t data = (uint8_t)(huart->Instance->DR & 0xFF);
 
 if(huart->Init.Parity == UART_PARITY_NONE)
 
 {
 
 
 
 	 if( (huart->pRxBuffPtr == varPtr) && ( data != 'H' ) )
 
 	 {
 
 
 
 	 	huart->pRxBuffPtr = varPtr;
 
 	 	*huart->pRxBuffPtr = 'F';
 
 	 	//__HAL_UART_FLUSH_DRREGISTER(huart);
 
 	 }
 
 	 else
 
 	 {
 
 	 *huart->pRxBuffPtr = data;
 
 	 huart->pRxBuffPtr += 1U;
 
 	 //*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
 
 	 }
 
 
 
 
 
 }
 
 else
 
 {
 
 *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
 
 }
 
 }

This is the current code but still have issue when I send say Hell which is 4bytes and then Hello55 which matches 7 bytes which the hello55 is shifted by some positon on the buffer variable...

Manojkumar Subramaniam
Associate III
January 21, 2019

Hi Guys i seemed to fixed my issue by using this code.. but I am open to feedback to make this code better.

Earlier my data was not fully receiving because of this if(--huart->RxXferCount == 0U) decrement the count so to solve that i returned from function once i found the data is not synced..

 //*tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x00FF);
 //if the pRx
 	 uint8_t data = (uint8_t)(huart->Instance->DR & 0xFF);
 if( (huart->pRxBuffPtr == varPtr) && ( data != 'H' ) )
 {
 	huart->pRxBuffPtr = varPtr;
 }
 else
 {
 huart->pRxBuffPtr += 1U;
 }
 }
 }
 else
 {
 uint8_t data = (uint8_t)(huart->Instance->DR & 0xFF);
 if(huart->Init.Parity == UART_PARITY_NONE)
 {
 
 	 if( (huart->pRxBuffPtr == varPtr) && ( data != 'H' ) )
 	 {
 
 	 	huart->pRxBuffPtr = varPtr;
 	 	*huart->pRxBuffPtr = 'F';
 	 	huart->RxState = HAL_UART_STATE_READY;
 	 	CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
 	 	CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
 	 	//__HAL_UART_FLUSH_DRREGISTER(huart);
 	 	HAL_UART_Receive_IT(huart,varPtr,7);
 	 	return HAL_BUSY;
 
 	 }
 	 else
 	 {
 	 *huart->pRxBuffPtr = data;
 	 huart->pRxBuffPtr += 1U;
 	 //*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
 	 }
 
 
 }
 else
 {
 *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
 }