Arduino_Core_STM32
Arduino_Core_STM32 copied to clipboard
STM32F10xx Serial bus fault on large data
Describe the bug When sending large amounts of data over Serial Monitor (string len > 204 ), the processor enters a hard fault.
Hard fault status register (SCB_HFSR) 0xE000ED2C has bit 30 set to 1 (FORCED: Forced hard fault, 1: Forced hard fault.) Configurable fault status register (SCB_CFSR) 0xE000ED28 has bit 10 set to 1 (IMPRECISERR: Imprecise data bus error)
To Reproduce On the latest 2.0.0 core
- Upload the following minimal Arduino sketch to the board as usual
void setup() {
Serial.begin(9600);
}
void loop (void) {
if (Serial.available()) Serial.print((char)Serial.read());
}
- Connect using the serial monitor and send the following
One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. He lay on his armour-like back, and if he lifted his head a little he could see his brown belly, slightly domed and divided by arches into stiff sections. The bedding was hardly able to cover it and seemed ready to slide off any moment. His many legs, pitifully thin compared with the size of the rest of him, waved about helplessly as he looked. "What's happened to me?" he thought.
Expected behavior The text is written back in the Serial monitor.
Screenshots If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
- OS: Linux 5.12.5-arch1-1
- Arduino IDE version: 1.8.15
- STM32 core version: 2.0.0
- Tools menu settings if not the default: USB Support: CDC Supersede Serial
- Upload method: STM32CubeProgrammer(SWD)
Board (please complete the following information):
- Name: BluePill STM32F103C8T6 Medium-density with 128K Flash
- Hardware Revision: Rev X/ N/A
Additional context
I have bisected this git repository and identified the issue as originating in commit 00acff6c9a834ae628af846264618fb9c08bd046 by @fpistm which updated the HAL Drivers to v1.1.5 for STM32f1xx. The commit before 242671d30bf6614e0e4744f3d600c90ccf7b5124 using HAL v1.1.4 works perfectly as expected.
I attach three screenshots showing the hard fault, the frozen serial monitor, and the working behaviour.

Hi @chrysophylax It's failed due to the CDC queue which are full and so set the application buffer to NULL for next dequeue but USB continue to receive without checking the buffer validity while it should wait space to release PMA buffer. The update remove this part of code as all HAL/LL PCD/USB have been reworked: https://github.com/stm32duino/Arduino_Core_STM32/commit/07c4ee4260306624c03db14ed5d5b99c8a22dbdf
I will try to correct this issue but not so easy. One workaround could be to increase the buffer size. https://github.com/stm32duino/Arduino_Core_STM32/blob/0686e2d5a873e16842e9f61dcb69fd095893e8f2/cores/arduino/stm32/usb/cdc/cdc_queue.h#L57
Definitely hoping for a fix here 😔
Is there a workaround for this?
@benguild, as said @fpistm,
One workaround could be to increase the buffer size
But size depends on your needs, depends on your application, so it is up to you to implement it: Arduino_Core_STM32/cores/arduino/stm32/usb/cdc/cdc_queue.h
https://github.com/stm32duino/Arduino_Core_STM32/blob/0686e2d5a873e16842e9f61dcb69fd095893e8f2/cores/arduino/stm32/usb/cdc/cdc_queue.h#L57
What's the recommended maximum value, and do I just replace the value in the library for the board? I can tune it down from there if I can at least try it out without it panicking.
What's the recommended maximum value, and do I just replace the value in the library for the board?
There is not recommended value, as it depends on application. Up to you to test. Yes, replace it in the library. Arduino_Core_STM32/cores/arduino/stm32/usb/cdc/cdc_queue.h
There is not recommended value, as it depends on application. Up to you to test.
What's the maximum? And what are the side effects? Is it possible to brick the board this way or enter a state where it can't be reflashed?
I changed the multiplier from * 3 on RX to 42 and it seems fine. Not sure if that's excessive or not, but yeah the board works normally now.
There is not recommended value, as it depends on application. Up to you to test.
What's the maximum? And what are the side effects? Is it possible to brick the board this way or enter a state where it can't be reflashed?
CDC_QUEUE_MAX_PACKET_SIZE is 64 so for 42 you allocate 2688 bytes.
CDC_QUEUE_MAX_PACKET_SIZEis 64 so for 42 you allocate 2688 bytes.
How quickly does this get cleared? What's the effective RX rate?
It depends of several stuff. Host PC, user application, .... The main issue here is when there is no more space in the Rx buffer the USB should stop transfer until a free room is available.
this is kind of 'off-topic', under bulk transfer section, under 'OUT' https://www.usbmadesimple.co.uk/ums_3.htm if the device can't accept the data, it is supposed to send 'NAK', i'm not sure if this is possible in the usb code. this would likely also need some rounds of tests if this is done. e.g. could we keep sending 'NAK' if the device is perpetually busy? An unorthodox 'flow control' sort of.
As for the sketch sending data to the host. i'd think it'd be necessary to check Serial.availableForWrite() if the data should not be lost before doing Serial.write() or Serial.print(). Otherwise, i'd think Serial should simply overwrite old data in the buffer, or just drop the latest addition. The host can't be deemed to be 'always there'.
either way, it seemed quite possible for a 'dead lock' situation to happen.
With this bug I can't use a newer core than 1.9.0
Is there another way, than increase CDC_RECEIVE_QUEUE_BUFFER_SIZE in in the library? Arduino_Core_STM32/cores/arduino/stm32/usb/cdc/cdc_queue.h
Currently not as the fix is not so simple to deploy.
Is there a way to increase CDC_RECEIVE_QUEUE_BUFFER_SIZE without change a file in the core?
No
at the moment, i'd suggest this as a partial solution, you could copy the relevant codes for the usb stack etc and perhaps place that in the sketch folder etc. it may take editing the codes. and omit selecting usb-cdc if you are using that particular set of things in the stack. there are some occasions like SPI etc where I need some custom functionalities i'd do that. for SPI i simply omit the library and copy the SPI library codes into the sketch folder and make a custom SPI driver