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(stm32): Add DMA based, ring-buffer based rx uart, v3 #1404

Merged
merged 12 commits into from
May 1, 2023

Conversation

rmja
Copy link
Contributor

@rmja rmja commented Apr 27, 2023

This PR replaces #1150. Comparing to that PR, this one has the following changes:

  • The implementation now aligns with the new stm32 dma module, thanks @Dirbaio!
  • Calls to read() now returns on either 1) idle line, or 2) ring buffer is at most half full. This is different from the previous pr, which would return a lot of 1 byte reads. Thank you @chemicstry for making me realize that it was actually not what I wanted. This is accomplished using half-transfer completed and full-transfer completed interrupts. Both seems to be supported on both dma and bdma.

The implementation still have the issue mentioned here: #1150 (comment)

Regarding the todos here: #1150 (comment). I have removed the exposure of ndtr from dma::RingBuffer to the uart so that the uart now simply calls ringbuf::reload_position() to align the position within the ring buffer to that of the actual running dma controller. BDMA and GPDMA is not implemented. I do not have any chips with those dma controllers, so maybe someone else should to this so that it can be tested.

The saturate_serial test utility inside tests/utils has an --idles switch which can be used to saturate the uart from a pc, but with random idles.

Because embassy-stm32 now can have tests, we should probably run them in ci. I do this locally to test the DmaRingBuffer: cargo test --no-default-features --features stm32f429ig.

cc @chemicstry @Dirbaio

@xoviat
Copy link
Contributor

xoviat commented Apr 30, 2023

These changes are needed to fix the build: rmja/embassy@99ade50. Other than that, I'm not pleased that we'll have a buffered.rs and an rx_ringbuffered.rs file in the uart mod. Perhaps a better name would be buffered_v2.rs? I also think it's unfortunate that write was not implemented, but that's understandable.

Anyway, the ringbuffer.rs is pub(crate), which is good; it can be modified internally to add bdma and gpdma later. And the implementation appears to be correct, and it is tested. So I don't have really anything to add there.

@Dirbaio
Copy link
Member

Dirbaio commented Apr 30, 2023

I'm working on adding BDMA+GPDMA right now, so no need to feature-gate it.

About naming: I've been thinking about it, and I think we need to make the buffered uart the "default", and name the non-buffered one "raw". See the discussions for the embedded-hal serial traits, where "buffered vs unbuffered" was discussed and the conclusion was most of the people are better off with the buffered impls. rust-embedded/embedded-hal#349

So it could be something like:

  • embassy_stm32::uart -> DMA-buffered (the one added in this PR)
  • embassy_stm32::uart::irq_driven -> IRQ-buffered (the current "buffered uart")
  • embassy_stm32::uart::raw -> raw, unbuffered

I think we should do it in a follow-up PR though: this one has been delayed enough, it's RX-only for now, and the change should be done in rp, nrf at the same time.

let dma = self.regs();
let channel_num = self.num();
let index = self.index();
// Manually process tcif in case transfer was completed and we are in a higher priority task.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the existing drivers already have this "problem", Making the interrupt a lower priority than the task that uses it is not supported. I wouldn't take measures to try to mitigateit.

Copy link
Contributor Author

@rmja rmja May 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I made this was that I at some point called get_complete_count() from a uart interrupt, and the priority relation between the uart and the dma controller is not strict. I can see now that I do not do this anymore, and so this could probably be removed. But it would open for future issues if someone accidently called get_complete_count() from a uart interrupt.


// First, figure out if tcif is set without a cs.
if isr_reg.read().tcif(channel_num % 4) && cr_reg.read().tcie() {
// Make tcif test again within a cs to avoid race when incrementing complete_count.
Copy link
Member

@Dirbaio Dirbaio May 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what race is this avoiding?

EDIT: I guess it was due to the separate process_tcif call. I've removed it, so I think this is not needed anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The race is not possible if it is guaranteed that the DMA interrupt always have the highest priority.

@Dirbaio Dirbaio force-pushed the stm32-uart-buffered-rx-v3 branch from 119aa3a to f987949 Compare May 1, 2023 16:18
@Dirbaio
Copy link
Member

Dirbaio commented May 1, 2023

  • removed process_tcif in DMA.
  • Added BDMA support
  • Feature-gated ringbuffer on chips with GPDMA for now. Circular mode in GPDMA is not trivial 😓. I'm fairly confident it can be done with the current architecture though, unlike with the previous one. It just requires learning how the crazy linked list descriptors work.
  • cleaned up test so that it passes in HIL.

bors try

bors bot added a commit that referenced this pull request May 1, 2023
@bors
Copy link
Contributor

bors bot commented May 1, 2023

try

Build failed:

@Dirbaio Dirbaio force-pushed the stm32-uart-buffered-rx-v3 branch 2 times, most recently from 80e9923 to 371f3ef Compare May 1, 2023 17:54
@Dirbaio
Copy link
Member

Dirbaio commented May 1, 2023

let's see if HIL tests pass. 🙏

bors r+

bors bot added a commit that referenced this pull request May 1, 2023
1404: feat(stm32): Add DMA based, ring-buffer based rx uart, v3 r=Dirbaio a=rmja

This PR replaces #1150. Comparing to that PR, this one has the following changes:

* The implementation now aligns with the new stm32 dma module, thanks `@Dirbaio!`
* Calls to `read()` now returns on either 1) idle line, or 2) ring buffer is at most half full. This is different from the previous pr, which would return a lot of 1 byte reads. Thank you `@chemicstry` for making me realize that it was actually not what I wanted. This is accomplished using half-transfer completed and full-transfer completed interrupts. Both seems to be supported on both dma and bdma.

The implementation still have the issue mentioned here: #1150 (comment)

Regarding the todos here: #1150 (comment). I have removed the exposure of ndtr from `dma::RingBuffer` to the uart so that the uart now simply calls `ringbuf::reload_position()` to align the position within the ring buffer to that of the actual running dma controller. BDMA and GPDMA is not implemented. I do not have any chips with those dma controllers, so maybe someone else should to this so that it can be tested.

The `saturate_serial` test utility inside `tests/utils` has an `--idles` switch which can be used to saturate the uart from a pc, but with random idles.

Because embassy-stm32 now can have tests, we should probably run them in ci. I do this locally to test the DmaRingBuffer:  `cargo test --no-default-features --features stm32f429ig`.

cc `@chemicstry` `@Dirbaio` 


Co-authored-by: pennae <[email protected]>
Co-authored-by: Rasmus Melchior Jacobsen <[email protected]>
Co-authored-by: Dario Nieuwenhuis <[email protected]>
@bors
Copy link
Contributor

bors bot commented May 1, 2023

Build failed:

@Dirbaio
Copy link
Member

Dirbaio commented May 1, 2023

bors r+

@bors
Copy link
Contributor

bors bot commented May 1, 2023

Merge conflict.

@Dirbaio Dirbaio force-pushed the stm32-uart-buffered-rx-v3 branch from 4890aa6 to 4efc3d5 Compare May 1, 2023 20:43
@Dirbaio
Copy link
Member

Dirbaio commented May 1, 2023

bors r+

bors bot added a commit that referenced this pull request May 1, 2023
1404: feat(stm32): Add DMA based, ring-buffer based rx uart, v3 r=Dirbaio a=rmja

This PR replaces #1150. Comparing to that PR, this one has the following changes:

* The implementation now aligns with the new stm32 dma module, thanks `@Dirbaio!`
* Calls to `read()` now returns on either 1) idle line, or 2) ring buffer is at most half full. This is different from the previous pr, which would return a lot of 1 byte reads. Thank you `@chemicstry` for making me realize that it was actually not what I wanted. This is accomplished using half-transfer completed and full-transfer completed interrupts. Both seems to be supported on both dma and bdma.

The implementation still have the issue mentioned here: #1150 (comment)

Regarding the todos here: #1150 (comment). I have removed the exposure of ndtr from `dma::RingBuffer` to the uart so that the uart now simply calls `ringbuf::reload_position()` to align the position within the ring buffer to that of the actual running dma controller. BDMA and GPDMA is not implemented. I do not have any chips with those dma controllers, so maybe someone else should to this so that it can be tested.

The `saturate_serial` test utility inside `tests/utils` has an `--idles` switch which can be used to saturate the uart from a pc, but with random idles.

Because embassy-stm32 now can have tests, we should probably run them in ci. I do this locally to test the DmaRingBuffer:  `cargo test --no-default-features --features stm32f429ig`.

cc `@chemicstry` `@Dirbaio` 


Co-authored-by: Rasmus Melchior Jacobsen <[email protected]>
Co-authored-by: Dario Nieuwenhuis <[email protected]>
@bors
Copy link
Contributor

bors bot commented May 1, 2023

Build failed:

@Dirbaio Dirbaio force-pushed the stm32-uart-buffered-rx-v3 branch from 4efc3d5 to 980205a Compare May 1, 2023 21:17
@Dirbaio Dirbaio force-pushed the stm32-uart-buffered-rx-v3 branch from 980205a to a1d4530 Compare May 1, 2023 21:35
@Dirbaio
Copy link
Member

Dirbaio commented May 1, 2023

bors r+

@bors
Copy link
Contributor

bors bot commented May 1, 2023

Build succeeded:

@bors bors bot merged commit 6096f0c into embassy-rs:master May 1, 2023
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.

3 participants