2024-11-16 07:14 PM - edited 2024-11-16 07:28 PM
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 :(
Solved! Go to Solution.
2024-11-17 12:15 AM
Oh yes you try clear FIFO then ok read Solved: Re: HAL_UART_Receive() always timeout. - STMicroelectronics Community
2024-11-16 11:33 PM
Why your clean buf receive ??
2024-11-16 11:38 PM
Mainly, I don't want the previous data to affect my program. Before sending the AT command, the buffer will be cleared first.
2024-11-16 11:58 PM - edited 2024-11-16 11:59 PM
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.
2024-11-17 12:14 AM
> 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
2024-11-17 12:15 AM
Oh yes you try clear FIFO then ok read Solved: Re: HAL_UART_Receive() always timeout. - STMicroelectronics Community
2024-11-17 12:19 AM
AT_TIMEOUT is 3000, but it also cannot block the specified time.
2024-11-17 12:35 AM
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.
2024-11-17 05:07 AM
Clearing the UART_FLAG_ORE is useful, although I don't quite understand how this issue occurs.