Electronic – STM32 starts timing out receiving data UART after reading 1 byte

esp8266serialstm32uart

I am having trouble using the UART on the STM32F103 where it stops receiving data, while not setting any of the error flags.

The UART device is an ESP8266 at 115,200 baud. I am sending it AT\r\n. The ESP8266 echoes back each byte I send — I am able to receive these echoes. However, when it comes to reading the response after the echos (OK + some newlines), it times out after receiving one byte.

Here is the entire transaction, as seen on a logic analyzer.

logic analyzer traces

STM32 sends: A T \r \n
ESP8266 sends: A T \r \r \n \r \n O K \r \n

In my code, I send one byte, then receive one byte until the payload is sent. Then, I'm attempting to listen for the remaining 7 bytes (\n \r \n O K \r \n) one-by-one. I receive the \n, then the communication times out after 5 seconds (using the debugger, I see it's waiting on the RXNE flag.)

When the timeout occurs, I see that none of the error flags (ORE NE FE PE) are set in the SR register.

If I attempt to read two bits at a time, the very first HAL_UART_Receive call times out.

The program creates some debugging info (below) as it sends each byte and received the echo, then attempts to receive the response. The code for the program is in a gist.

I've been banging my head against this for several hours. What could cause this behaviour?

Sending 4 bytes: AT(\r\n)
  Echo:
    Byte 0: sent 65, echo 65 (ORE 0) // A
    Byte 1: sent 84, echo 84 (ORE 0) // T
    Byte 2: sent 13, echo 13 (ORE 0) // \r
    Byte 3: sent 10, echo 13 (ORE 0) // \n, echo \r
  Receive:
    Recv 10  // \n
    Recv fail
    RXNE: 0 ORE: 0 NE: 0 FE: 0 PE: 0

Excerpt of code that attempts to read the bytes after the sending completes (full code):

while (1) {
    uint8_t recvChar;
    if (HAL_UART_Receive(&Device_UART_Handle, &recvChar, 1, 5000) != HAL_OK) {
        printf("    Recv fail\r\n");
        printf("    RXNE: %d ORE: %d NE: %d FE: %d PE: %d\r\n",
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_RXNE),
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_ORE),
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_NE),
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_FE),
            __HAL_UART_GET_FLAG(&Device_UART_Handle, UART_FLAG_PE));
        while(1) {}
    }
    printf("    Recv %d\r\n", recvChar);
}

Best Answer

Chances are you are missing most of the reply because the extensive logging in your receive loop takes so long that it can't catch the next character. Even if whatever you are sending printf() output to is an order of magnitude faster than the 115200 baud response from the ESP8266, you are generating so many characters of output for each one received that it's most probable you cannot keep up.

During the initial stage when only one response character was being generated for each character sent, you could perhaps get away with it, but once the ESP8266 is free to keep a 115200 baud channel full, you have to be able to keep up with that.

Console output is indeed useful, but you have to account for the time it takes, queue it up for later output, pull incoming characters into a receive queue using a UART ISR, or something like that.

Related Topic