-
Notifications
You must be signed in to change notification settings - Fork 235
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
feat: uart tx software break #2872
base: main
Are you sure you want to change the base?
Conversation
Paused awaiting feedback on open items: Baud Rate RetrievalHow best to retrieve the current baud rate for break duration calculation Some Options
Async Delay Time-KeepingHow to perform async delay within the Uart driver. Not sure if there is much precedent for this. Some Options
|
I think storing the currently set value (essentially caching it) is the best option there.
Why would you need to do this? Can this not be done outside the driver? In other words, can't we just delay after sending the break? |
With my method, the break is for the duration you choose.
The duration you wait may depend on people's use cases. But a default duration might be what would minimally trigger the break interrupt on ESP. I think just one bit time past the stop bit - so for 8N1 it would be min13 bits? Anyways, 13bits at 19200 is almost a millisecond wasted to busy wait if not for an async offering. |
/// the break is just is busy-waiting. | ||
pub fn send_break(&mut self, bits: u32) { | ||
// Invert the TX line | ||
self.register_block() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is quite right, we should be using the tx_brk
register bit and the txbrk_conf
(I think it's idle_conf
on the esp32/esp32s2).
See the esp-idf impl here: https://github.com/espressif/esp-idf/blob/b5ac4fbdf9e9fb320bb0a98ee4fbaa18f8566f37/components/hal/esp32s3/include/hal/uart_ll.h#L535-L543
You can then wait for an UART_INTR_TX_BRK_DONE
interrupt to fire to implement this in an async way, and just wait on reading the status registers for the blocking one. This completely avoids the delay issue you mentioned below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't know about this, let me test with it a bit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MabezDev Ah I do know about this. Coming from IDF land, there is a function uart_write_bytes_with_break
that will send a break AFTER the data is transmitted. For some use cases like mine, automotive LIN, I want to have a break at the START of a data transmission.
As I understand, when the txd_brk
is set, the ESP internally doesn't act upon it until the next non-zero-length transmission finishes and then sends a break. There is no way to alter this behavior I'm aware of.
My solution circumvents this, and works such that a break sent on TX can be detected reliably by the ESPs own break detection on the RX. (Assuming the minimum bit duration is met as mentioned above.)
The function uart_write_bytes_with_break() is similar to uart_write_bytes() but adds a serial break signal at the end of the transmission. A 'serial break signal' means holding the TX line low for a period longer than one data frame.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going off of ESP32 technical reference manual:
https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
UART_TX_DONE_INT
: Triggered when the transmitter has sent out all FIFO data.UART_TX_BRK_IDLE_DONE_INT
: Triggered when the transmitter’s idle state has been kept to a minimum
after sending the last data.UART_TX_BRK_DONE_INT
: Triggered when the transmitter completes sending NULL characters, after all
data in transmit-FIFO are sent.
These descriptions are a bit tough to understand, but I think they confirm the behavior "break gets sent after completion of non-zero-length transmission".
Thank you for your contribution!
We appreciate the time and effort you've put into this pull request.
To help us review it efficiently, please ensure you've gone through the following checklist:
Submission Checklist 📝
cargo xtask fmt-packages
command to ensure that all changed code is formatted correctly.CHANGELOG.md
in the proper section.Extra:
Pull Request Details 📖
Description
Closes #2752
Adding ability to send a software break on the UART TX line. This is achieved by inverting the TX line, waiting some time, and then reverting the line back. The duration to leave it inverted (the break duration) is kept in
bit time
- the time it takes to send one bit at the current baud rate.New Functions:
send_break_async(bits: u32)
- async delay during the breaksend_break(bits: u32)
- busy waits during the breakOpen Items
after(..).await
?)Testing
Tested with the added
examples/uart_send_break
andexamples/uart_send_break_async
on my pocket oscilloscope and visually with the helper LED toggle also in each example.Since I also have open PR #2858 for detecting breaks - these can eventually be tested together in HIL.