Skip to content

Hardware serial port RX locks up after overrun error. #494

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
benwaffle opened this issue Apr 5, 2019 · 18 comments
Closed

Hardware serial port RX locks up after overrun error. #494

benwaffle opened this issue Apr 5, 2019 · 18 comments

Comments

@benwaffle
Copy link
Contributor

benwaffle commented Apr 5, 2019

Describe the bug
When you run the following code, and start spamming words (followed by the enter key) on your keyboard, eventually it stops reading data. You can also lock it up by just hitting enter without any letters. The USART1 interrupt stops firing, because the code seems to fail to set TXEIE. It also appears to only happen when there's an overrun error as verified by looking at USART_SR with gdb.

To Reproduce

#include <Arduino.h>

void setup() {
    Serial.begin(9600);
    Serial.println("hello");
}

void loop() {
    if (Serial.available() > 0) {
        printf("Serial available: %d\n", Serial.available());
        char buf[128] = {0};
        char *line = buf;
        size_t nbytes;
        if ((nbytes = Serial.readBytesUntil('\n', buf, sizeof buf)) == 0) {
            printf("# error: no data read from serial\n");
            return;
        }

        printf("# read %d [%s]\n", nbytes, line);
        printf("rest = %d\n", Serial.available());
    }
}

Steps to reproduce the behavior:

  1. Run code
  2. Open a serial monitor (e.g. pio device monitor)
  3. Spam stuff into the serial console. (Or just hit enter)
  4. See it lock up and refuse to take more input.

Expected behavior
Continue receiving input, possibly by dropping the next character.

Desktop (please complete the following information):

  • OS: Mac OS 10.14.3
  • Platformio: 3.6.6
  • STM32 core version: 1.5.0
  • Upload method: STLink

Board (please complete the following information):

  • Name: Bluepill 128k
@benwaffle
Copy link
Contributor Author

benwaffle commented Apr 5, 2019

@fpistm
Copy link
Member

fpistm commented Apr 5, 2019

Hi @benwaffle
Seems similar to #467.

@benwaffle
Copy link
Contributor Author

benwaffle commented Apr 5, 2019

I tried the 2 patches from @ppescher but that did not fix it

@fpistm
Copy link
Member

fpistm commented Apr 5, 2019

Ok. Thanks for the test.

@uzi18
Copy link

uzi18 commented Apr 5, 2019

sizeof(buf)

@benwaffle
Copy link
Contributor Author

@uzi18 The code compiles just fine. You only need the parenthesis for types, not variables.

@ppescher
Copy link
Contributor

ppescher commented Apr 7, 2019

Hi @benwaffle
It may not work for you because you are using printf(). Try to only use Serial.print()/println().

@benwaffle
Copy link
Contributor Author

benwaffle commented Apr 7, 2019

I will try that, but printf() uses uart_debug_write() which uses the synchronous HAL_UART_Transmit(), without interrupts.

@ppescher
Copy link
Contributor

ppescher commented Apr 7, 2019

@benwaffle the issue is with __HAL_LOCK(huart) which is not a real mutex or critical section. If a receive interrupt fires in between __HAL_LOCK/__HAL_UNLOCK the interrupt flag will not be re-enabled, like I describe in #467
My solution provides a critical section only for HAL_UART_Receive_IT/Transmit_IT, but not for HAL_UART_Transmit. You might try to wrap this function call with HAL_NVIC_DisableIRQ/EnableIRQ inside uart_debug_write(), like I did for uart_attach_rx_callback/tx_callback. Or you might just not use printf().

@fpistm
Copy link
Member

fpistm commented Apr 8, 2019

I didn't see you used printf which is mainly used for debug purpose.
So mixing Serial and printf on the same uart is not a good solution.

@benwaffle
Copy link
Contributor Author

@ppescher, thank you, disabling the IRQ in uart_debug_write() fixes the issue for printf(). I made a PR, #496, but I need some help with a few things for it.

@ppescher
Copy link
Contributor

ppescher commented Apr 10, 2019 via email

@benwaffle
Copy link
Contributor Author

@ppescher good catch, that makes it easier

@ShenRen
Copy link

ShenRen commented Apr 13, 2019

I am happy to see the bug which have a improvement measure new.
@ppescher your PR only work for port of stm32 mcu, If i using stm32f4xxx , how should I chenge zhe code in function void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart);
#496

@benwaffle
Copy link
Contributor Author

@ShenRen you shouldn't need to. To clear the error bit on STM32F1 (and I assume F4 as well), you just need to read the error flag and then read to the data register, which the code is doing.

@ppescher
Copy link
Contributor

@ShenRen you are right that my patch in HAL_UART_ErrorCallback() only affect STM32L4. I'm not sure how it should be handled for the other STM32 series: it may well be that the conditional compilation is not needed at all and the code can be the same for all MCU families.
I'm only using STM32L4, so I have no way to test it. It could help if you tested the PR #496 with your hardware, or maybe @benwaffle or @fpistm could review it.

@fpistm
Copy link
Member

fpistm commented Apr 15, 2019

About HAL_UART_ErrorCallback for STM32F1, I've made an update here to properly clear flags:
fpistm@cd9a01c

@fpistm
Copy link
Member

fpistm commented Apr 19, 2019

Resolved thanks #502

@fpistm fpistm closed this as completed Apr 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants