diff options
| author | etiennecollin <[email protected]> | 2025-08-25 21:10:59 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2025-09-05 14:43:29 +0200 |
| commit | fec14213ea7b79badc14eae38c4a0b0197499f3f (patch) | |
| tree | 8e2abe6de562d98cead117cbcc7321198fa0577a /embassy-stm32/src | |
| parent | 7d224d94c47e4e457aed7c4832be8b4a52dfcef8 (diff) | |
fix: modified dma channel state management
See
https://github.com/embassy-rs/embassy/pull/3923#discussion_r2094570176
Diffstat (limited to 'embassy-stm32/src')
| -rw-r--r-- | embassy-stm32/src/dma/gpdma/mod.rs | 66 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/gpdma/ringbuffered.rs | 54 | ||||
| -rw-r--r-- | embassy-stm32/src/ucpd.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/ringbuffered.rs | 2 |
4 files changed, 80 insertions, 46 deletions
diff --git a/embassy-stm32/src/dma/gpdma/mod.rs b/embassy-stm32/src/dma/gpdma/mod.rs index 2132f070a..d06eac60e 100644 --- a/embassy-stm32/src/dma/gpdma/mod.rs +++ b/embassy-stm32/src/dma/gpdma/mod.rs | |||
| @@ -341,21 +341,25 @@ impl AnyChannel { | |||
| 341 | ch.cr().modify(|w| w.set_en(true)); | 341 | ch.cr().modify(|w| w.set_en(true)); |
| 342 | } | 342 | } |
| 343 | 343 | ||
| 344 | fn request_stop(&self) { | 344 | fn request_suspend(&self) { |
| 345 | let info = self.info(); | 345 | let info = self.info(); |
| 346 | let ch = info.dma.ch(info.num); | 346 | let ch = info.dma.ch(info.num); |
| 347 | 347 | ||
| 348 | ch.cr().modify(|w| w.set_susp(true)) | 348 | ch.cr().modify(|w| w.set_susp(true)) |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | fn request_pause(&self) { | 351 | fn request_resume(&self) { |
| 352 | let info = self.info(); | 352 | let info = self.info(); |
| 353 | let ch = info.dma.ch(info.num); | 353 | let ch = info.dma.ch(info.num); |
| 354 | 354 | ||
| 355 | // Disable the channel without overwriting the existing configuration | 355 | ch.cr().modify(|w| w.set_susp(false)); |
| 356 | ch.cr().modify(|w| { | 356 | } |
| 357 | w.set_en(false); | 357 | |
| 358 | }); | 358 | fn request_reset(&self) { |
| 359 | let info = self.info(); | ||
| 360 | let ch = info.dma.ch(info.num); | ||
| 361 | |||
| 362 | ch.cr().modify(|w| w.set_reset(true)); | ||
| 359 | } | 363 | } |
| 360 | 364 | ||
| 361 | fn is_running(&self) -> bool { | 365 | fn is_running(&self) -> bool { |
| @@ -406,11 +410,26 @@ impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { | |||
| 406 | Self { channel } | 410 | Self { channel } |
| 407 | } | 411 | } |
| 408 | 412 | ||
| 409 | /// Request the transfer to stop. | 413 | /// Request the transfer to suspend. |
| 414 | /// | ||
| 415 | /// To resume the transfer, call [`request_resume`](Self::request_resume) again. | ||
| 410 | /// | 416 | /// |
| 411 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | 417 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. |
| 412 | pub fn request_stop(&mut self) { | 418 | pub fn request_suspend(&mut self) { |
| 413 | self.channel.request_stop() | 419 | self.channel.request_suspend() |
| 420 | } | ||
| 421 | |||
| 422 | /// Request the transfer to resume after being suspended. | ||
| 423 | pub fn request_resume(&mut self) { | ||
| 424 | self.channel.request_resume() | ||
| 425 | } | ||
| 426 | |||
| 427 | /// Request the DMA to reset. | ||
| 428 | /// | ||
| 429 | /// The configuration for this channel will **not be preserved**. If you need to restart the transfer | ||
| 430 | /// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead. | ||
| 431 | pub fn request_reset(&mut self) { | ||
| 432 | self.channel.request_reset() | ||
| 414 | } | 433 | } |
| 415 | 434 | ||
| 416 | /// Return whether this transfer is still running. | 435 | /// Return whether this transfer is still running. |
| @@ -440,7 +459,7 @@ impl<'a, const ITEM_COUNT: usize> LinkedListTransfer<'a, ITEM_COUNT> { | |||
| 440 | 459 | ||
| 441 | impl<'a, const ITEM_COUNT: usize> Drop for LinkedListTransfer<'a, ITEM_COUNT> { | 460 | impl<'a, const ITEM_COUNT: usize> Drop for LinkedListTransfer<'a, ITEM_COUNT> { |
| 442 | fn drop(&mut self) { | 461 | fn drop(&mut self) { |
| 443 | self.request_stop(); | 462 | self.request_suspend(); |
| 444 | while self.is_running() {} | 463 | while self.is_running() {} |
| 445 | 464 | ||
| 446 | // "Subsequent reads and writes cannot be moved ahead of preceding reads." | 465 | // "Subsequent reads and writes cannot be moved ahead of preceding reads." |
| @@ -589,21 +608,26 @@ impl<'a> Transfer<'a> { | |||
| 589 | Self { channel } | 608 | Self { channel } |
| 590 | } | 609 | } |
| 591 | 610 | ||
| 592 | /// Request the transfer to stop. | 611 | /// Request the transfer to suspend. |
| 593 | /// The configuration for this channel will **not be preserved**. If you need to restart the transfer | 612 | /// |
| 594 | /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. | 613 | /// To resume the transfer, call [`request_resume`](Self::request_resume) again. |
| 595 | /// | 614 | /// |
| 596 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | 615 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. |
| 597 | pub fn request_stop(&mut self) { | 616 | pub fn request_suspend(&mut self) { |
| 598 | self.channel.request_stop() | 617 | self.channel.request_suspend() |
| 599 | } | 618 | } |
| 600 | 619 | ||
| 601 | /// Request the transfer to pause, keeping the existing configuration for this channel. | 620 | /// Request the transfer to resume after being suspended. |
| 602 | /// To restart the transfer, call [`start`](Self::start) again. | 621 | pub fn request_resume(&mut self) { |
| 622 | self.channel.request_resume() | ||
| 623 | } | ||
| 624 | |||
| 625 | /// Request the DMA to reset. | ||
| 603 | /// | 626 | /// |
| 604 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | 627 | /// The configuration for this channel will **not be preserved**. If you need to restart the transfer |
| 605 | pub fn request_pause(&mut self) { | 628 | /// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead. |
| 606 | self.channel.request_pause() | 629 | pub fn request_reset(&mut self) { |
| 630 | self.channel.request_reset() | ||
| 607 | } | 631 | } |
| 608 | 632 | ||
| 609 | /// Return whether this transfer is still running. | 633 | /// Return whether this transfer is still running. |
| @@ -633,7 +657,7 @@ impl<'a> Transfer<'a> { | |||
| 633 | 657 | ||
| 634 | impl<'a> Drop for Transfer<'a> { | 658 | impl<'a> Drop for Transfer<'a> { |
| 635 | fn drop(&mut self) { | 659 | fn drop(&mut self) { |
| 636 | self.request_stop(); | 660 | self.request_suspend(); |
| 637 | while self.is_running() {} | 661 | while self.is_running() {} |
| 638 | 662 | ||
| 639 | // "Subsequent reads and writes cannot be moved ahead of preceding reads." | 663 | // "Subsequent reads and writes cannot be moved ahead of preceding reads." |
diff --git a/embassy-stm32/src/dma/gpdma/ringbuffered.rs b/embassy-stm32/src/dma/gpdma/ringbuffered.rs index 87c482bfb..4532bda57 100644 --- a/embassy-stm32/src/dma/gpdma/ringbuffered.rs +++ b/embassy-stm32/src/dma/gpdma/ringbuffered.rs | |||
| @@ -139,21 +139,26 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { | |||
| 139 | DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); | 139 | DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | /// Request the DMA to stop. | 142 | /// Request the DMA to suspend. |
| 143 | /// The configuration for this channel will **not be preserved**. If you need to restart the transfer | 143 | /// |
| 144 | /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. | 144 | /// To resume the transfer, call [`request_resume`](Self::request_resume) again. |
| 145 | /// | 145 | /// |
| 146 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | 146 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. |
| 147 | pub fn request_stop(&mut self) { | 147 | pub fn request_suspend(&mut self) { |
| 148 | self.channel.request_stop() | 148 | self.channel.request_suspend() |
| 149 | } | ||
| 150 | |||
| 151 | /// Request the DMA to resume transfers after being suspended. | ||
| 152 | pub fn request_resume(&mut self) { | ||
| 153 | self.channel.request_resume() | ||
| 149 | } | 154 | } |
| 150 | 155 | ||
| 151 | /// Request the transfer to pause, keeping the existing configuration for this channel. | 156 | /// Request the DMA to reset. |
| 152 | /// To restart the transfer, call [`start`](Self::start) again. | ||
| 153 | /// | 157 | /// |
| 154 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | 158 | /// The configuration for this channel will **not be preserved**. If you need to restart the transfer |
| 155 | pub fn request_pause(&mut self) { | 159 | /// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead. |
| 156 | self.channel.request_pause() | 160 | pub fn request_reset(&mut self) { |
| 161 | self.channel.request_reset() | ||
| 157 | } | 162 | } |
| 158 | 163 | ||
| 159 | /// Return whether DMA is still running. | 164 | /// Return whether DMA is still running. |
| @@ -185,7 +190,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> { | |||
| 185 | 190 | ||
| 186 | impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { | 191 | impl<'a, W: Word> Drop for ReadableRingBuffer<'a, W> { |
| 187 | fn drop(&mut self) { | 192 | fn drop(&mut self) { |
| 188 | self.request_stop(); | 193 | self.request_suspend(); |
| 189 | while self.is_running() {} | 194 | while self.is_running() {} |
| 190 | 195 | ||
| 191 | // "Subsequent reads and writes cannot be moved ahead of preceding reads." | 196 | // "Subsequent reads and writes cannot be moved ahead of preceding reads." |
| @@ -285,21 +290,26 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { | |||
| 285 | DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); | 290 | DmaCtrlImpl(self.channel.reborrow()).set_waker(waker); |
| 286 | } | 291 | } |
| 287 | 292 | ||
| 288 | /// Request the DMA to stop. | 293 | /// Request the DMA to suspend. |
| 289 | /// The configuration for this channel will **not be preserved**. If you need to restart the transfer | 294 | /// |
| 290 | /// at a later point with the same configuration, see [`request_pause`](Self::request_pause) instead. | 295 | /// To resume the transfer, call [`request_resume`](Self::request_resume) again. |
| 291 | /// | 296 | /// |
| 292 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | 297 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. |
| 293 | pub fn request_stop(&mut self) { | 298 | pub fn request_suspend(&mut self) { |
| 294 | self.channel.request_stop() | 299 | self.channel.request_suspend() |
| 300 | } | ||
| 301 | |||
| 302 | /// Request the DMA to resume transfers after being suspended. | ||
| 303 | pub fn request_resume(&mut self) { | ||
| 304 | self.channel.request_resume() | ||
| 295 | } | 305 | } |
| 296 | 306 | ||
| 297 | /// Request the transfer to pause, keeping the existing configuration for this channel. | 307 | /// Request the DMA to reset. |
| 298 | /// To restart the transfer, call [`start`](Self::start) again. | ||
| 299 | /// | 308 | /// |
| 300 | /// This doesn't immediately stop the transfer, you have to wait until [`is_running`](Self::is_running) returns false. | 309 | /// The configuration for this channel will **not be preserved**. If you need to restart the transfer |
| 301 | pub fn request_pause(&mut self) { | 310 | /// at a later point with the same configuration, see [`request_suspend`](Self::request_suspend) instead. |
| 302 | self.channel.request_pause() | 311 | pub fn request_reset(&mut self) { |
| 312 | self.channel.request_reset() | ||
| 303 | } | 313 | } |
| 304 | 314 | ||
| 305 | /// Return whether DMA is still running. | 315 | /// Return whether DMA is still running. |
| @@ -331,7 +341,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> { | |||
| 331 | 341 | ||
| 332 | impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { | 342 | impl<'a, W: Word> Drop for WritableRingBuffer<'a, W> { |
| 333 | fn drop(&mut self) { | 343 | fn drop(&mut self) { |
| 334 | self.request_stop(); | 344 | self.request_suspend(); |
| 335 | while self.is_running() {} | 345 | while self.is_running() {} |
| 336 | 346 | ||
| 337 | // "Subsequent reads and writes cannot be moved ahead of preceding reads." | 347 | // "Subsequent reads and writes cannot be moved ahead of preceding reads." |
diff --git a/embassy-stm32/src/ucpd.rs b/embassy-stm32/src/ucpd.rs index 0a80adb8f..967e43a8a 100644 --- a/embassy-stm32/src/ucpd.rs +++ b/embassy-stm32/src/ucpd.rs | |||
| @@ -490,14 +490,14 @@ impl<'d, T: Instance> PdPhy<'d, T> { | |||
| 490 | let sr = r.sr().read(); | 490 | let sr = r.sr().read(); |
| 491 | 491 | ||
| 492 | if sr.rxhrstdet() { | 492 | if sr.rxhrstdet() { |
| 493 | dma.request_stop(); | 493 | dma.request_suspend(); |
| 494 | 494 | ||
| 495 | // Clean and re-enable hard reset receive interrupt. | 495 | // Clean and re-enable hard reset receive interrupt. |
| 496 | r.icr().write(|w| w.set_rxhrstdetcf(true)); | 496 | r.icr().write(|w| w.set_rxhrstdetcf(true)); |
| 497 | r.imr().modify(|w| w.set_rxhrstdetie(true)); | 497 | r.imr().modify(|w| w.set_rxhrstdetie(true)); |
| 498 | Poll::Ready(Err(RxError::HardReset)) | 498 | Poll::Ready(Err(RxError::HardReset)) |
| 499 | } else if sr.rxmsgend() { | 499 | } else if sr.rxmsgend() { |
| 500 | dma.request_stop(); | 500 | dma.request_suspend(); |
| 501 | // Should be read immediately on interrupt. | 501 | // Should be read immediately on interrupt. |
| 502 | rxpaysz = r.rx_payszr().read().rxpaysz().into(); | 502 | rxpaysz = r.rx_payszr().read().rxpaysz().into(); |
| 503 | 503 | ||
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index 5f4e87834..bea56c991 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs | |||
| @@ -165,7 +165,7 @@ impl<'d> RingBufferedUartRx<'d> { | |||
| 165 | 165 | ||
| 166 | /// Stop DMA backed UART receiver | 166 | /// Stop DMA backed UART receiver |
| 167 | fn stop_uart(&mut self) { | 167 | fn stop_uart(&mut self) { |
| 168 | self.ring_buf.request_pause(); | 168 | self.ring_buf.request_suspend(); |
| 169 | 169 | ||
| 170 | let r = self.info.regs; | 170 | let r = self.info.regs; |
| 171 | // clear all interrupts and DMA Rx Request | 171 | // clear all interrupts and DMA Rx Request |
