2015-01-12 05:00 AM
I'm baffled by a bit of code that results in a lockup in my application (On n STM32F429I-
DISCO) related to a UART receive ISR. The code receives characters one at a time as it needs to handle variable length messages. To do that it issues a read request within the receive data ISR:[code]HAL_StatusTypeDef st;void HAL_UART_RxCpltCallback( UART_HandleTypeDef * huart){/* Character by character interrupt callback Ugh! HAL has no concept of receiving variable length messages so we do that at application level. Here the RxXferCount==0 means the 1 character receive buffer has been exhausted and the receiver disablked. We need to store the character and reissue the read. */ if( huart->State != HAL_UART_STATE_RESET) { if(!huart->RxXferCount) { // character received? RxBuffer[RxBufferHead] = *RxBufferIT; RxBufferHead = (RxBufferHead + 1) % RX_BUFFER_SIZE; if((st=HAL_UART_Receive_IT(&UartHandle, (uint8_t *)RxBufferIT, 1)) != HAL_OK) { HAL_UART_Receive_IT(huart, (uint8_t *)RxBufferIT, 1); Error_Handler(); } } }}[/code](Error_Handler(); turns on an LED and goes into an infinite loop.)I can break on the line prior to the call to Error_Handler() and find that the return status from HAL_UART_Receive_IT(); is HAL_BUSY. If I step through a second call to HAL_UART_Receive_IT(), all works well. If I program a loop to repeat the call to HAL_UART_Receive_IT() until it no longer returns HAL_BUSY it can repeat up to 100,000 times without ever returning a good status. Within HAL_UART_Receive_IT() I set a breakpoint on the line where it returns HAL_BUSY and execution never stops at the breakpoint. Woaking back up the call stack, HAL_UART_RxCpltCallback(huart); mis called from within this bit of code (in UART_Receive_IT(UART_HandleTypeDef *huart) in stm32f4xx_hal_uart.c):[code] if(--huart->RxXferCount == 0) { __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE); /* Check if a transmit process is ongoing or not */ if(huart->State == HAL_UART_STATE_BUSY_TX_RX) { huart->State = HAL_UART_STATE_BUSY_TX; } else { /* Disable the UART Parity Error Interrupt */ __HAL_UART_DISABLE_IT(huart, UART_IT_PE); /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ __HAL_UART_DISABLE_IT(huart, UART_IT_ERR); huart->State = HAL_UART_STATE_READY; } HAL_UART_RxCpltCallback(huart); return HAL_OK; }[/code]It seems that the state (huart->State) should either be HAL_UART_STATE_BUSY_TX or HAL_UART_STATE_READY, neither of which should cause this path to be taken in the code.All I can think of is that some memory access is being optimized away (Optimization within IAR EWARM set to low) but I cannot see where that would be happening.The definition for the UART handle is:UART_HandleTypeDef UartHandle;and if I try to add the volatile keyword to it, the compiler spits out:[code]Error[Pe147]: declaration is incompatible with ''struct <unnamed> volatile UartHandle'' (declared <SRCREF line=44>at line 44</SRCREF>) C:\STM32Cube_FW_F4_V1.3.0\Projects\STM32F429I-Discovery\Applications\STemWin\WiFi with STemWin_HelloWorld\Src\main.c 44[/code]
whicl leads me to believe it is already declared volatile through some magic I do not understand. (The typedef for UART_HandleTypeDef does not mention volatile) And since the handle is passed though the ISR chain as a pointer, I do not see how the volatile keyword would be honored unless the library code included it with the signature for the ISR related procedures.I'm at a loss as to what to try to fix this since I cannot figure out what is causing it in the first place. Many thanks for suggestions on where to look!2015-01-13 05:08 AM
Hi,
Concerning the HAL_UART_RxCpltCallback(), there is no need to call twice HAL_UART_Receive_IT() to have your application working:if((st=HAL_UART_Receive_IT(&UartHandle, (uint8_t *)RxBufferIT, 1)) != HAL_OK)
{
HAL_UART_Receive_IT(huart, (uint8_t *)RxBufferIT, 1);
// This Line is obsolete
Error_Handler();
}
WithinHAL_UART_Receive_IT() I set a breakpoint on the line where it returns HAL_BUSY and execution never stops at the breakpoint.
This is a normal behavior when you call just one time the HAL_UART_Receive_IT() in the HAL_UART_RxCpltCallback(). Could you please confirm, this behavior is observed with how many calls? For the UART handler you don’t need to declare it as volatile, the “State�? parameter in the UART_HandleTypeDef is already declared as volatile (__IO) by the HAL UART driver__IO HAL_UART_StateTypeDef State; /* UART communication state */
Conclusion:
From our side this is a compiler issue, and here bellow some ways to be checked in your application:
if((st=HAL_UART_Receive_IT(&UartHandle, (uint8_t *)RxBufferIT, 1)) != HAL_OK)
{
By
st = HAL_UART_Receive_IT(&UartHandle, (uint8_t *)RxBufferIT, 1);
if(st != HAL_OK)
{
2015-01-13 11:41 AM
Hi
Heisenberg,
Many thanks for the reply and suggestions. At present I'm working on another part of the system but I will get back to this and unless the issue magically goes away, I will be following your suggestions.
The extra call was there as a debugging aid BTW. I thought I could identify the problem by stepping through the code after the bad status had been returned. Unfortunately that turned out not to be the case.Thanks,hank (Not your brother-in-law ;) )2015-01-15 06:15 AM
Hi Hank,
Thanks anyway. Please continue providing valuable feedbacks.Cheers,Heisenberg.PS: Not you brother-in-law too :D