cancel
Showing results for 
Search instead for 
Did you mean: 

G070KBT6 - HAL_UART_Receive function return HAL_TIMEOUT early.

jgwsjgsgs
Associate II

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; } }
View more

Hope someone can help me :(

1 ACCEPTED SOLUTION

Accepted Solutions
8 REPLIES 8
MM..1
Chief III

Why your clean buf receive ??

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

 

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.

waclawek.jan
Super User

> 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

 

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

Now I use interrupts to receive data instead of blocking, so the problem has been solved. I should try this solution in the future. Anyway, thank you for your help.

Clearing the UART_FLAG_ORE is useful, although I don't quite understand how this issue occurs.