cancel
Showing results for 
Search instead for 
Did you mean: 

CubeMX - UART receive complete interrupt

sincoon
Associate II

Posted on June 05, 2015 at 17:08

I'm a little bit confusing with question of UART. So, I need to receive data through UART from PC. Ok, as said in stm32f4xx_hal_uart.c file:

*** Interrupt mode IO operation ***

===================================

[..]

(+) Send an amount of data in non blocking mode using HAL_UART_Transmit_IT()

(+) At transmission end of transfer HAL_UART_TxCpltCallback is executed and user can

add his own code by customization of function pointer HAL_UART_TxCpltCallback

(+) Receive an amount of data in non blocking mode using HAL_UART_Receive_IT()

(+) At reception end of transfer HAL_UART_RxCpltCallback is executed and user can

add his own code by customization of function pointer HAL_UART_RxCpltCallback

(+) In case of transfer Error, HAL_UART_ErrorCallback() function is executed and user can

add his own code by customization of function pointer HAL_UART_ErrorCallback

this way is also used in examples (UART_Hyperterminal_IT, etc).

Does it means that there are no way to get interrupt on data ready in UART buffer?

Ok, another question. Code in hyperterminal example:

int main(void)
{ 
/*hardware configuration*/
if(HAL_UART_Init(&UartHandle) != HAL_OK)
{
/* Turn LED3 on: in case of Initialization Error */
BSP_LED_On(LED3);
while(1)
{
}
}
/*##-2- Start the transmission process #####################################*/ 
/* While the UART in reception process, user can transmit data through 
''aTxBuffer'' buffer */
if(HAL_UART_Transmit_IT(&UartHandle, (uint8_t*)aTxStartMessage, TXSTARTMESSAGESIZE)!= HAL_OK)
{
/* Turn LED3 on: Transfer error in transmission process */
BSP_LED_On(LED3);
while(1)
{
} 
}
/*##-3- Put UART peripheral in reception process ###########################*/ 
/* Any data received will be stored ''aRxBuffer'' buffer : the number max of 
data received is 10 */
if(HAL_UART_Receive_IT(&UartHandle, (uint8_t *)aRxBuffer, RXBUFFERSIZE) != HAL_OK)
{
/* Turn LED3 on: Transfer error in reception process */
BSP_LED_On(LED3);
while(1)
{
} 
}
/*##-4- Wait for the end of the transfer ###################################*/ 
/* Before starting a new communication transfer, you need to check the current 
state of the peripheral; if it’s busy you need to wait for the end of current
transfer before starting a new one.
For simplicity reasons, this example is just waiting till the end of the 
transfer, but application may perform other tasks while transfer operation
is ongoing. */ 
while (HAL_UART_GetState(&UartHandle) != HAL_UART_STATE_READY)
{
} 
/*##-5- Send the received Buffer ###########################################*/ 
if(HAL_UART_Transmit_IT(&UartHandle, (uint8_t*)aRxBuffer, RXBUFFERSIZE)!= HAL_OK)
{
/* Turn LED3 on: Transfer error in transmission process */
BSP_LED_On(LED3);
while(1)
{
} 
}
/*##-6- Wait for the end of the transfer ###################################*/ 
while (HAL_UART_GetState(&UartHandle) != HAL_UART_STATE_READY)
{
}
/*##-7- Send the End Message ###############################################*/ 
if(HAL_UART_Transmit_IT(&UartHandle, (uint8_t*)aTxEndMessage, TXENDMESSAGESIZE)!= HAL_OK)
{
/* Turn LED3 on: Transfer error in transmission process */
BSP_LED_On(LED3);
while(1)
{
} 
}
/*##-8- Wait for the end of the transfer ###################################*/ 
while (HAL_UART_GetState(&UartHandle) != HAL_UART_STATE_READY)
{
}
/* Infinite loop */ 
while (1)
{
}
}

Why all this stuff, like HAL_UART_Receive_IT,

HAL_UART_Transmit_IT, etc. are NOT in last endless while loop? Does this means that I'll receive data only once? If not, does this means that I need call HAL_UART_Receive_IT in loop?

All this question is because previously, in SPL, there was clear interrupt, which invokes at UART events and I could check, if this interrupt is due to receiving.

17 REPLIES 17
Posted on July 20, 2017 at 17:44

For what it's worth, I have a working UART implementation using the DMA - but *only* in circular mode.  It avoids the ISR LOCK problem.

Thus, if used, it works without having to modify the library code or accommodate the issue in any other way.

The only potential error I found is that the pointer passed into the Receive function doesn't cause the received data to be placed into the location pointed to, it always arrives in the location originally pointed to provided in the first call - but this just may be a bit of laziness in the original programmer's part where they didn't want to write a separate function that excluded the pointer.  However, this requires a separate small receive buffer.

Example of (possible) error:

/* initial call */

p = &RecvBuffer [ 0 ];

HAL_UART_Receive_DMA ( &huart3, p, 1 );

/* in the Callback function */

p = &RecvBuffer [  TailPtr ];

HAL_UART_Receive_DMA ( &huart3, p, 1 );

/* Character still shows up in RecvBuffer [ 0 ] regardless of TailPtr's value. */

No need to go through all these other gyrations in this thread - just use the Circular DMA feature - but use a separate receive buffer and transfer the data from it to your ring buffer in the callback function.  

I have had 100% success with using only the RECEIVE on DMA.  The transmit still uses _IT - but that's largely because the transmit isn't re-cocked inside the ISR - whereas the receive must be.  I have had several UARTS simultaneously receiving and transmitting for days on end at 115.2K baud using common (shared) call-back functions.  

Posted on July 28, 2017 at 11:00

Hello Marcus,

This means, that you should copy these 4 functions from stm32f7xx_hal_uart.c to customUart.c.

For your second part of the question: I included the source for emCustomUart.h in my post.

Konami
Senior
Posted on October 05, 2017 at 21:32

Is this still the best solution to buffering UART RX data one byte at a time? Has anyone tried using the older libraries instead that didn't have these issues?

Posted on October 05, 2017 at 21:44

The SPL and the HARDWARE interrupt on every byte, the USART has no FIFO, just a single byte holding buffer.

One can also trivially build an RX FIFO using circular DMA of desired depth. Think data rate vs consumption rate/periodicity.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Tamas Novak
Associate III
Posted on October 06, 2017 at 23:00

I think I've found a better solution. I modified  UART_Receive_IT (without leading HAL_!! It is at the end of stm32f0xx_hal_uart.c, line 2755 at my version. This file is copied to my project subdir, so I may modify it.)

The following code part would decrement the amount remaining and turn IT off when received amount of data is reached:

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;

    }

I commented the above lines out, and inserted a custom callback instead:

HAL_UART_RxByteCallback(huart);

This callback gets the single received byte in rx buffer. 

Take care, because huart->pRxBuffPtr  is still incremented. Remove '++' from the line

      *huart->pRxBuffPtr++ = (uint8_t)(uhdata & (uint8_t)uhMask);

to prevent pointer incrementing  when using a single byte buffer only.

Harvinder  Singh
Associate
Posted on June 28, 2018 at 15:34

Actually  i want to read data from Rx pin of the uart using HAL libraries .I am using HAL_UART_RECIEVE _IT function but not able to get any data .So can anyone please let me know how to implelent it

thank you

harvinder singh

Posted on June 28, 2018 at 18:27

See

STM32Cube_FW_F4_V1.21.0\Projects\STM32446E_EVAL\Applications\USB_Device\CDC_Standalone\Src\usbd_cdc_interface.c

STM32Cube_FW_F4_V1.21.0\Projects\STM32446E_EVAL\Examples\UART\UART_HyperTerminal_IT\Src\main.c

STM32Cube_FW_F4_V1.21.0\Projects\STM32F4-Discovery\Examples\UART\UART_TwoBoards_ComIT\Src\main.c

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 29, 2018 at 02:08

if you want help, please start your own thread, carefully describing what point you are at.