Skip to main content
Visitor II
November 17, 2024
Solved

G070KBT6 - HAL_UART_Receive function return HAL_TIMEOUT early.

  • November 17, 2024
  • 2 replies
  • 1358 views

I called the "HAL_UART_Receive" function in my "at_send_cmd" function and set its timeout parameter to 30 seconds, but I observed that the function immediately returned HAL_TIMEOUT.
My SysTick should be working properly, and I can use the HAL_Delay function normally.

When I call the "at_send_cmd" function, it can send data normally, but cannot receive data normally because of timeout.

 

#include "atcmd.h"

uint8_t at_rx_buffer[512];

static void at_clean_buffer(UART_HandleTypeDef* usart){
	uint8_t buffer;

	while (HAL_UART_Receive(usart, &buffer, 1, 0) == HAL_OK);
}

uint16_t at_send_cmd(UART_HandleTypeDef* usart, const char* cmd, uint8_t offset, uint8_t rx_length, uint16_t timeout){
	uint8_t i = 3, result;
	uint16_t cmd_length = strlen(cmd);

	while (i > 0){
		at_clean_buffer(usart);
		HAL_UART_Transmit(usart, (const uint8_t*)cmd, cmd_length, 3000);

		if ((result = HAL_UART_Receive(usart, at_rx_buffer, cmd_length + offset + rx_length, timeout)) == HAL_OK){
			at_rx_buffer[cmd_length + offset + rx_length] = '\0';
			return cmd_length + offset;
		}else if (result == HAL_TIMEOUT){
			printf("Timeout.\r\n");
		}

		i--;
	}

	return 0;
}

 

 

uint8_t ec800m_mqtt_connect(){
	if (USART == NULL) return 0;

	uint16_t index;

	//Set MQTT Config
	at_send_cmd(USART, EC800M_CMD_CONFIG, 0, 2, AT_TIMEOUT);
	HAL_Delay(1000);

	//Open
	if ((index = at_send_cmd(USART, EC800M_CMD_OPEN, 0, 15, 30000)) != 0){
		printf("%s\r\n", at_rx_buffer + index);
	}else{
		printf("Error.\r\n", index);
	}
	HAL_Delay(1000);

	//Connect
	at_send_cmd(USART, EC800M_CMD_CONN, 0, 2, 30000);

	return 0;
}

 

 

 

/**
 * @brief Receive an amount of data in blocking mode.
 * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
 * the received data is handled as a set of u16. In this case, Size must indicate the number
 * of u16 available through pData.
 * @note When FIFO mode is enabled, the RXFNE flag is set as long as the RXFIFO
 * is not empty. Read operations from the RDR register are performed when
 * RXFNE flag is set. From hardware perspective, RXFNE flag and
 * RXNE are mapped on the same bit-field.
 * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
 * address of user data buffer for storing data to be received, should be aligned on a half word frontier
 * (16 bits) (as received data will be handled using u16 pointer cast). Depending on compilation chain,
 * use of specific alignment compilation directives or pragmas might be required
 * to ensure proper alignment for pData.
 * @PAram huart UART handle.
 * @PAram pData Pointer to data buffer (u8 or u16 data elements).
 * @PAram Size Amount of data elements (u8 or u16) to be received.
 * @PAram Timeout Timeout duration.
 * @retval HAL status
 */
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
 uint8_t *pdata8bits;
 uint16_t *pdata16bits;
 uint16_t uhMask;
 uint32_t tickstart;

 /* Check that a Rx process is not already ongoing */
 if (huart->RxState == HAL_UART_STATE_READY)
 {
 if ((pData == NULL) || (Size == 0U))
 {
 return HAL_ERROR;
 }

 /* In case of 9bits/No Parity transfer, pData buffer provided as input parameter
 should be aligned on a u16 frontier, as data to be received from RDR will be
 handled through a u16 cast. */
 if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
 {
 if ((((uint32_t)pData) & 1U) != 0U)
 {
 return HAL_ERROR;
 }
 }

 huart->ErrorCode = HAL_UART_ERROR_NONE;
 huart->RxState = HAL_UART_STATE_BUSY_RX;
 huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;

 /* Init tickstart for timeout management */
 tickstart = HAL_GetTick();

 huart->RxXferSize = Size;
 huart->RxXferCount = Size;

 /* Computation of UART mask to apply to RDR register */
 UART_MASK_COMPUTATION(huart);
 uhMask = huart->Mask;

 /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
 if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
 {
 pdata8bits = NULL;
 pdata16bits = (uint16_t *) pData;
 }
 else
 {
 pdata8bits = pData;
 pdata16bits = NULL;
 }

 /* as long as data have to be received */
 while (huart->RxXferCount > 0U)
 {
 if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
 {
 huart->RxState = HAL_UART_STATE_READY;

 return HAL_TIMEOUT;
 }
 if (pdata8bits == NULL)
 {
 *pdata16bits = (uint16_t)(huart->Instance->RDR & uhMask);
 pdata16bits++;
 }
 else
 {
 *pdata8bits = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask);
 pdata8bits++;
 }
 huart->RxXferCount--;
 }

 /* At end of Rx process, restore huart->RxState to Ready */
 huart->RxState = HAL_UART_STATE_READY;

 return HAL_OK;
 }
 else
 {
 return HAL_BUSY;
 }
}

Hope someone can help me :(

    This topic has been closed for replies.
    Best answer by MM..1

    Oh yes you try clear FIFO then ok read Solved: Re: HAL_UART_Receive() always timeout. - STMicroelectronics Community

    2 replies

    Graduate II
    November 17, 2024

    Why your clean buf receive ??

    jgwsjgsgsAuthor
    Visitor II
    November 17, 2024

    Mainly, I don't want the previous data to affect my program. Before sending the AT command, the buffer will be cleared first.

    Graduate II
    November 17, 2024

     

    static void at_clean_buffer(UART_HandleTypeDef* usart){
    	uint8_t buffer;
    
    	while (HAL_UART_Receive(usart, &buffer, 1, 0) == HAL_OK);
    }

     

    use receive to clear buf is absurd or your mistake... simply memset buffer to zero, but no internal buffer variable, this is next absurd.

    Super User
    November 17, 2024

    > called the "HAL_UART_Receive" function in my "at_send_cmd" function and set its timeout parameter to 30 seconds,

    The first call to at_send_cmd() is with AT_TIMEOUT, what's that value?

    Btw. Cube/HAL is open source so you can debug it as your own code.

    JW

     

    jgwsjgsgsAuthor
    Visitor II
    November 17, 2024

    AT_TIMEOUT is 3000, but it also cannot block the specified time.