cancel
Showing results for 
Search instead for 
Did you mean: 

Stm32cubeL0 loop in USART IT

gwendal
Associate
Posted on September 11, 2014 at 17:54

Im using STM32Cube_FW_L0_V1.1.0 on a STM32L052C8T6

Why there is some loops into TX and RX IT functions?

For example:

in 

UART_Receive_IT()

At the end of the reception there is:

 while(HAL_IS_BIT_SET(huart->Instance->ISR, UART_FLAG_RXNE))

 

      {

 

      }

and in  

UART_Transmit_IT()

at the end of the sending there is a call to:

UART_WaitOnFlagUntilTimeout().

which is a blocking function

It is very dangerous to have such loop in a IRQ handler it can cause an overrun or worst.

For example when the last Byte is transmit you can't receive any byte without having an overrun because the IT handler is waiting for the TX Byte to be transmit :(

Is it done on purpose or have you an explanation for this?

Gwendal

#rtfm #stm32cube-stm32l0xx
5 REPLIES 5
Andrew Neil
Evangelist III
Posted on September 11, 2014 at 21:06

''It is very dangerous to have such loop in a IRQ handler''

Yes, but these are

not

Interrupt handlers!

gwendal
Associate
Posted on September 12, 2014 at 09:37

Before answer to quickly you must read twice my question:

I'm not talking about 

HAL_UART_Transmit_IT() which

is not an IRQ handler, but

UART_Transmit_IT()

which is called by

HAL_UART_IRQHandler()

-> IRQ handler.

Documentation for this function:

/**

  * @brief Send an amount of data in interrupt mode

  *       

  Function called under interruption only,

once

  *         interruptions have been enabled by HAL_UART_Transmit_IT()

  * @param  huart: UART handle

  * @retval HAL status

  */

(same for

UART_Receive_IT()

)

So before answer with RTFM please  read carefully the question.

Posted on September 12, 2014 at 19:05

HiGwendal,

We understand that this is a limitationthat some of you are experiencing, and we have it already in the STM32Cube HAL bugs list that will be fixed in next releases of STM32CubeL0. In the meantime, you can find below the UART_Transmit_IT() and UART_Receive_IT() APIs to avoid the waiting loop under IRQ:

/**
* @brief Sends an amount of data in non blocking mode.
* @param huart: Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart)
{
uint16_t* tmp;
uint32_t tmp1 = 0;
tmp1 = huart->State;
if((tmp1 == HAL_UART_STATE_BUSY_TX) || (tmp1 == HAL_UART_STATE_BUSY_TX_RX))
{
if(huart->Init.WordLength == UART_WORDLENGTH_9B)
{
tmp = (uint16_t*) huart->pTxBuffPtr;
huart->Instance->DR = (uint16_t)(*tmp & (uint16_t)0x01FF);
if(huart->Init.Parity == UART_PARITY_NONE)
{
huart->pTxBuffPtr += 2;
}
else
{
huart->pTxBuffPtr += 1;
}
} 
else
{
huart->Instance->DR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0x00FF);
}
if(--huart->TxXferCount == 0)
{
/* Disable the UART Transmit Complete Interrupt */
__HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
/* Enable the UART Transmit Complete Interrupt */ 
__HAL_UART_ENABLE_IT(huart, UART_IT_TC);
}
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}

/**
* @brief Wraps up transmission in non blocking mode.
* @param huart: pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart)
{
/* Disable the UART Transmit Complete Interrupt */ 
__HAL_UART_DISABLE_IT(huart, UART_IT_TC);
/* Check if a receive process is ongoing or not */
if(huart->State == HAL_UART_STATE_BUSY_TX_RX) 
{
huart->State = HAL_UART_STATE_BUSY_RX;
}
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_TxCpltCallback(huart);
return HAL_OK;
}

/**
* @brief Receives an amount of data in non blocking mode 
* @param huart: Pointer to a UART_HandleTypeDef structure that contains
* the configuration information for the specified UART module.
* @retval HAL status
*/
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
{
uint16_t* tmp;
uint32_t tmp1 = 0;
tmp1 = huart->State; 
if((tmp1 == HAL_UART_STATE_BUSY_RX) || (tmp1 == HAL_UART_STATE_BUSY_TX_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 += 2;
}
else
{
*tmp = (uint16_t)(huart->Instance->DR & (uint16_t)0x00FF);
huart->pRxBuffPtr += 1;
}
}
else
{
if(huart->Init.Parity == UART_PARITY_NONE)
{
*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
}
else
{
*huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
}
}
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;
}
return HAL_OK;
}
else
{
return HAL_BUSY; 
}
}

Thanks for the report.Keep an eye out for the next update!
chetan
Associate II
Posted on October 28, 2014 at 07:48

Hi,

I am using STM32F4 Eval board and 

trying to check UART_Hyperterminal_IT example provided with HAL.  Sometime code loops inside HAL_UART_IRQHandler in UART_Transmit_IT with huart->State as HAL_UART_STATE_READY. Is there any bug with this HAL lib code. Also Can you provide me the pending bug list with HAL.

I am migrating my code from STD lib to HAL and really stuck whether to do it or not.

 

Chetan

Posted on October 28, 2014 at 09:19

Hi Chetan,

Please try to write your post in a new discussion.

Regards,

Heisenberg.