Skip to content
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

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft

Conversation

zpg6
Copy link

@zpg6 zpg6 commented Dec 30, 2024

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 📝

  • I have updated existing examples or added new ones (if applicable).
  • I have used cargo xtask fmt-packages command to ensure that all changed code is formatted correctly.
  • My changes were added to the CHANGELOG.md in the proper section.
  • I have added necessary changes to user code to the Migration Guide.
  • My changes are in accordance to the esp-rs API guidelines

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 break
  • send_break(bits: u32) - busy waits during the break

Open Items

  • How to retrieve the current baud rate for break duration calculation
  • How to perform async delay within the Uart (can I use embassy-time after(..).await?)

Testing

Tested with the added examples/uart_send_break and examples/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.

@zpg6
Copy link
Author

zpg6 commented Dec 30, 2024

Paused awaiting feedback on open items:


Baud Rate Retrieval

How best to retrieve the current baud rate for break duration calculation

Some Options

  1. Pull from registers and back-calculate (unsure of the edge cases of this)
  2. Keep stored somewhere
  3. Input it to the send_break function.
  4. Make send_break time-based not bit-time-based. No longer requiring baud rate calculation, and user specifies a time duration to break for.

Async Delay Time-Keeping

How to perform async delay within the Uart driver. Not sure if there is much precedent for this.

Some Options

  1. I can use embassy-time after(..).await
  2. Don't offer with async delay?
  3. ... not sure

@MabezDev
Copy link
Member

MabezDev commented Jan 3, 2025

Keep stored somewhere

I think storing the currently set value (essentially caching it) is the best option there.

How to perform async delay within the Uart driver. Not sure if there is much precedent for this.

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?

@zpg6
Copy link
Author

zpg6 commented Jan 3, 2025

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.

  1. Invert the TX line
  2. Wait (either async or blocking)
  3. Put back the TX line

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()
Copy link
Member

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.

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

Successfully merging this pull request may close these issues.

UART: transmitting BRK is not supported
2 participants