-
Notifications
You must be signed in to change notification settings - Fork 1.2k
feat(stm32): Add DMA based, ring-buffer based rx uart, v3 #1404
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
Conversation
These changes are needed to fix the build: rmja/embassy@99ade50. Other than that, I'm not pleased that we'll have a Anyway, the |
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 So it could be something like:
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. |
embassy-stm32/src/dma/dma.rs
Outdated
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. |
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.
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.
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.
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.
embassy-stm32/src/dma/dma.rs
Outdated
|
||
// 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. |
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.
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.
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.
The race is not possible if it is guaranteed that the DMA interrupt always have the highest priority.
119aa3a
to
f987949
Compare
bors try |
tryBuild failed: |
80e9923
to
371f3ef
Compare
let's see if HIL tests pass. 🙏 bors r+ |
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]>
Build failed: |
bors r+ |
Merge conflict. |
4890aa6
to
4efc3d5
Compare
bors r+ |
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]>
Build failed: |
4efc3d5
to
980205a
Compare
980205a
to
a1d4530
Compare
bors r+ |
Build succeeded: |
This PR replaces #1150. Comparing to that PR, this one has the following changes:
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 callsringbuf::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 insidetests/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