-
-
Notifications
You must be signed in to change notification settings - Fork 7k
Way to check if Serial.write() will block or way to have it fail instead of block. [imported] #672
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
Comments
What I think that happens here is that the the serial buffer fills up when printing from inside an ISR. While the ISR is running, no other interrupts can be triggered, meaning the "byte sent" interrupt from the serial is never triggered, and thus HardwareSerial::write hangs forever waiting for some space in the buffer. Your proposed fix works, but still requires manual action to make things work. Since this case should be detectable (before entering the wait loop inside HardwareSerial::write you can simply check if interrupts are disabled), I think we can fix this automatically (Automatically discarding data without the user asking for it is of course bad, but it would only happen where it now does a hard lockup, compared to which discarding data is of course perfectly fine). A second alternative that I could imagine is to actually start polling the serial hardware inside the while loop (if we know the interrupt won't fire). Not sure how well that would work, but it would cause the least surprise for anyone debugging an ISR (it would cause additional delays, but people will expect delays, not discarded data and lockups). |
#1147 points out that calling flush() from an ISR will cause an automatic lockup in the same way, so flush() should probably receive the same treatment. |
When interrupts are disabled, writing to HardwareSerial could cause a lockup. When the tx buffer is full, a busy-wait loop is used to wait for the interrupt handler to free up a byte in the buffer. However, when interrupts are disabled, this will of course never happen and the Arduino will lock up. This often caused lockups when doing (big) debug printing from an interrupt handler. Additionally, calling flush() with interrupts disabled while transmission was in progress would also cause a lockup. When interrupts are disabled, the code now actively checks the UDRE (UART Data Register Empty) and calls the interrupt handler to free up room if the bit is set. This can lead to delays in interrupt handlers when the serial buffer is full, but a delay is of course always preferred to a lockup. Closes: arduino#672 References: arduino#1147
This introduces two new methods, Serial.setBlocking() and Serial.getBlocking(), which can be used to enable or disable blocking. References: arduino#672 --- TODO: This commit is probably not ready to merge, I'm not sure what the proper API for this feature would be (the current enum approach requires qualifying the constants with HardwareSerial:: for example). I'm also not sure where and how to add the new function to a keywords.txt file.
When interrupts are disabled, writing to HardwareSerial could cause a lockup. When the tx buffer is full, a busy-wait loop is used to wait for the interrupt handler to free up a byte in the buffer. However, when interrupts are disabled, this will of course never happen and the Arduino will lock up. This often caused lockups when doing (big) debug printing from an interrupt handler. Additionally, calling flush() with interrupts disabled while transmission was in progress would also cause a lockup. When interrupts are disabled, the code now actively checks the UDRE (UART Data Register Empty) and calls the interrupt handler to free up room if the bit is set. This can lead to delays in interrupt handlers when the serial buffer is full, but a delay is of course always preferred to a lockup. Closes: arduino#672 References: arduino#1147
When interrupts are disabled, writing to HardwareSerial could cause a lockup. When the tx buffer is full, a busy-wait loop is used to wait for the interrupt handler to free up a byte in the buffer. However, when interrupts are disabled, this will of course never happen and the Arduino will lock up. This often caused lockups when doing (big) debug printing from an interrupt handler. Additionally, calling flush() with interrupts disabled while transmission was in progress would also cause a lockup. When interrupts are disabled, the code now actively checks the UDRE (UART Data Register Empty) and calls the interrupt handler to free up room if the bit is set. This can lead to delays in interrupt handlers when the serial buffer is full, but a delay is of course always preferred to a lockup. Closes: arduino#672 References: arduino#1147
Merged the fix, to be released in 1.5.6. |
This is Issue 672 moved from a Google Code project.
Added by 2011-10-08T16:59:01.000Z by [email protected].
Please review that bug for more context and additional comments, but update this bug.
Original labels: Type-Defect, Priority-Medium, Component-Core
Original description
What steps will reproduce the problem?
What is the expected output? What do you see instead?
The interrupt should trigger, but the serial shouldn't print out until the ISR is done under the new scheme of non-blocking serial writes. This happens most of the time.
However, sometimes, when the ISR is triggered, the serial still starts printing a few characters, doesn't finish, and hangs the processor. Even when the pin 2 grounding is removed, and the ISR should finish, it stays stuck there, and I have to use the hardware reset button to get it to work again.
The ISR does not hang the processor when the serial print is removed, so I'm pretty sure the problem is in there somewhere. This all seems to happen more often when the interrupt is rapidly triggered back and forth, though I'm not absolutely sure of this.
What version of the Arduino software are you using? On what operating
system? Which Arduino board are you using?
I'm using Arduino RC1, downloaded on 10/8/11, on MAC OSX 10.6.8. This problem occurs on both the Arduino Uno and the Bare Bones Board clone running the non-optiboot Duemilanove firmware.
The text was updated successfully, but these errors were encountered: