diff options
| -rw-r--r-- | embassy-stm32/src/dma/bdma.rs | 19 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/dma.rs | 56 |
2 files changed, 36 insertions, 39 deletions
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index 29c9fd592..b4c77757e 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs | |||
| @@ -59,7 +59,7 @@ unsafe fn on_irq() { | |||
| 59 | let isr = pac::$dma.isr().read(); | 59 | let isr = pac::$dma.isr().read(); |
| 60 | let dman = dma_num!($dma); | 60 | let dman = dma_num!($dma); |
| 61 | 61 | ||
| 62 | for chn in 0..crate::pac::dma_channels_count!($dma) { | 62 | for chn in 0..pac::dma_channels_count!($dma) { |
| 63 | let cr = pac::$dma.ch(chn).cr(); | 63 | let cr = pac::$dma.ch(chn).cr(); |
| 64 | if isr.tcif(chn) && cr.read().tcie() { | 64 | if isr.tcif(chn) && cr.read().tcie() { |
| 65 | cr.write(|_| ()); // Disable channel interrupts with the default value. | 65 | cr.write(|_| ()); // Disable channel interrupts with the default value. |
| @@ -90,9 +90,8 @@ pac::dma_channels! { | |||
| 90 | impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { | 90 | impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { |
| 91 | 91 | ||
| 92 | unsafe fn start_write<W: Word>(&mut self, request: Request, buf: &[W], reg_addr: *mut W) { | 92 | unsafe fn start_write<W: Word>(&mut self, request: Request, buf: &[W], reg_addr: *mut W) { |
| 93 | low_level_api::reset_status(crate::pac::$dma_peri, $channel_num); | ||
| 94 | low_level_api::start_transfer( | 93 | low_level_api::start_transfer( |
| 95 | crate::pac::$dma_peri, | 94 | pac::$dma_peri, |
| 96 | $channel_num, | 95 | $channel_num, |
| 97 | #[cfg(any(bdma_v2, dmamux))] | 96 | #[cfg(any(bdma_v2, dmamux))] |
| 98 | request, | 97 | request, |
| @@ -112,9 +111,8 @@ pac::dma_channels! { | |||
| 112 | 111 | ||
| 113 | unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W) { | 112 | unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W) { |
| 114 | let buf = [repeated]; | 113 | let buf = [repeated]; |
| 115 | low_level_api::reset_status(crate::pac::$dma_peri, $channel_num); | ||
| 116 | low_level_api::start_transfer( | 114 | low_level_api::start_transfer( |
| 117 | crate::pac::$dma_peri, | 115 | pac::$dma_peri, |
| 118 | $channel_num, | 116 | $channel_num, |
| 119 | #[cfg(any(bdma_v2, dmamux))] | 117 | #[cfg(any(bdma_v2, dmamux))] |
| 120 | request, | 118 | request, |
| @@ -132,9 +130,8 @@ pac::dma_channels! { | |||
| 132 | } | 130 | } |
| 133 | 131 | ||
| 134 | unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *mut W, buf: &mut [W]) { | 132 | unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *mut W, buf: &mut [W]) { |
| 135 | low_level_api::reset_status(crate::pac::$dma_peri, $channel_num); | ||
| 136 | low_level_api::start_transfer( | 133 | low_level_api::start_transfer( |
| 137 | crate::pac::$dma_peri, | 134 | pac::$dma_peri, |
| 138 | $channel_num, | 135 | $channel_num, |
| 139 | #[cfg(any(bdma_v2, dmamux))] | 136 | #[cfg(any(bdma_v2, dmamux))] |
| 140 | request, | 137 | request, |
| @@ -152,14 +149,14 @@ pac::dma_channels! { | |||
| 152 | } | 149 | } |
| 153 | 150 | ||
| 154 | fn request_stop(&mut self){ | 151 | fn request_stop(&mut self){ |
| 155 | unsafe {low_level_api::request_stop(crate::pac::$dma_peri, $channel_num);} | 152 | unsafe {low_level_api::request_stop(pac::$dma_peri, $channel_num);} |
| 156 | } | 153 | } |
| 157 | 154 | ||
| 158 | fn is_running(&self) -> bool { | 155 | fn is_running(&self) -> bool { |
| 159 | unsafe {low_level_api::is_running(crate::pac::$dma_peri, $channel_num)} | 156 | unsafe {low_level_api::is_running(pac::$dma_peri, $channel_num)} |
| 160 | } | 157 | } |
| 161 | fn remaining_transfers(&mut self) -> u16 { | 158 | fn remaining_transfers(&mut self) -> u16 { |
| 162 | unsafe {low_level_api::get_remaining_transfers(crate::pac::$dma_peri, $channel_num)} | 159 | unsafe {low_level_api::get_remaining_transfers(pac::$dma_peri, $channel_num)} |
| 163 | } | 160 | } |
| 164 | 161 | ||
| 165 | fn set_waker(&mut self, waker: &Waker) { | 162 | fn set_waker(&mut self, waker: &Waker) { |
| @@ -198,6 +195,8 @@ mod low_level_api { | |||
| 198 | ) { | 195 | ) { |
| 199 | let ch = dma.ch(channel_number as _); | 196 | let ch = dma.ch(channel_number as _); |
| 200 | 197 | ||
| 198 | reset_status(dma, channel_number); | ||
| 199 | |||
| 201 | #[cfg(dmamux)] | 200 | #[cfg(dmamux)] |
| 202 | super::super::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request); | 201 | super::super::dmamux::configure_dmamux(dmamux_regs, dmamux_ch_num, request); |
| 203 | 202 | ||
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index 05d62ef8f..efe4d1d9d 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs | |||
| @@ -85,17 +85,15 @@ pac::dma_channels! { | |||
| 85 | ($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $dmamux:tt) => { | 85 | ($channel_peri:ident, $dma_peri:ident, dma, $channel_num:expr, $dmamux:tt) => { |
| 86 | impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { | 86 | impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { |
| 87 | unsafe fn start_write<W: Word>(&mut self, request: Request, buf: &[W], reg_addr: *mut W) { | 87 | unsafe fn start_write<W: Word>(&mut self, request: Request, buf: &[W], reg_addr: *mut W) { |
| 88 | let isrn = $channel_num as usize / 4; | ||
| 89 | let isrbit = $channel_num as usize % 4; | ||
| 90 | low_level_api::reset_status(&crate::pac::$dma_peri, isrn, isrbit); | ||
| 91 | low_level_api::start_transfer( | 88 | low_level_api::start_transfer( |
| 89 | pac::$dma_peri, | ||
| 90 | $channel_num, | ||
| 92 | request, | 91 | request, |
| 93 | vals::Dir::MEMORYTOPERIPHERAL, | 92 | vals::Dir::MEMORYTOPERIPHERAL, |
| 94 | reg_addr as *const u32, | 93 | reg_addr as *const u32, |
| 95 | buf.as_ptr() as *mut u32, | 94 | buf.as_ptr() as *mut u32, |
| 96 | buf.len(), | 95 | buf.len(), |
| 97 | true, | 96 | true, |
| 98 | crate::pac::$dma_peri.st($channel_num as _), | ||
| 99 | vals::Size::from(W::bits()), | 97 | vals::Size::from(W::bits()), |
| 100 | #[cfg(dmamux)] | 98 | #[cfg(dmamux)] |
| 101 | <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, | 99 | <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, |
| @@ -106,17 +104,15 @@ pac::dma_channels! { | |||
| 106 | 104 | ||
| 107 | unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W) { | 105 | unsafe fn start_write_repeated<W: Word>(&mut self, request: Request, repeated: W, count: usize, reg_addr: *mut W) { |
| 108 | let buf = [repeated]; | 106 | let buf = [repeated]; |
| 109 | let isrn = $channel_num as usize / 4; | ||
| 110 | let isrbit = $channel_num as usize % 4; | ||
| 111 | low_level_api::reset_status(&crate::pac::$dma_peri, isrn, isrbit); | ||
| 112 | low_level_api::start_transfer( | 107 | low_level_api::start_transfer( |
| 108 | pac::$dma_peri, | ||
| 109 | $channel_num, | ||
| 113 | request, | 110 | request, |
| 114 | vals::Dir::MEMORYTOPERIPHERAL, | 111 | vals::Dir::MEMORYTOPERIPHERAL, |
| 115 | reg_addr as *const u32, | 112 | reg_addr as *const u32, |
| 116 | buf.as_ptr() as *mut u32, | 113 | buf.as_ptr() as *mut u32, |
| 117 | count, | 114 | count, |
| 118 | false, | 115 | false, |
| 119 | crate::pac::$dma_peri.st($channel_num as _), | ||
| 120 | vals::Size::from(W::bits()), | 116 | vals::Size::from(W::bits()), |
| 121 | #[cfg(dmamux)] | 117 | #[cfg(dmamux)] |
| 122 | <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, | 118 | <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, |
| @@ -126,17 +122,15 @@ pac::dma_channels! { | |||
| 126 | } | 122 | } |
| 127 | 123 | ||
| 128 | unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *mut W, buf: &mut [W]) { | 124 | unsafe fn start_read<W: Word>(&mut self, request: Request, reg_addr: *mut W, buf: &mut [W]) { |
| 129 | let isrn = $channel_num as usize / 4; | ||
| 130 | let isrbit = $channel_num as usize % 4; | ||
| 131 | low_level_api::reset_status(&crate::pac::$dma_peri, isrn, isrbit); | ||
| 132 | low_level_api::start_transfer( | 125 | low_level_api::start_transfer( |
| 126 | pac::$dma_peri, | ||
| 127 | $channel_num, | ||
| 133 | request, | 128 | request, |
| 134 | vals::Dir::PERIPHERALTOMEMORY, | 129 | vals::Dir::PERIPHERALTOMEMORY, |
| 135 | reg_addr as *const u32, | 130 | reg_addr as *const u32, |
| 136 | buf.as_ptr() as *mut u32, | 131 | buf.as_ptr() as *mut u32, |
| 137 | buf.len(), | 132 | buf.len(), |
| 138 | true, | 133 | true, |
| 139 | crate::pac::$dma_peri.st($channel_num as _), | ||
| 140 | vals::Size::from(W::bits()), | 134 | vals::Size::from(W::bits()), |
| 141 | #[cfg(dmamux)] | 135 | #[cfg(dmamux)] |
| 142 | <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, | 136 | <Self as super::dmamux::sealed::MuxChannel>::DMAMUX_REGS, |
| @@ -146,15 +140,15 @@ pac::dma_channels! { | |||
| 146 | } | 140 | } |
| 147 | 141 | ||
| 148 | fn request_stop(&mut self) { | 142 | fn request_stop(&mut self) { |
| 149 | unsafe {low_level_api::request_stop(&crate::pac::$dma_peri, $channel_num);} | 143 | unsafe {low_level_api::request_stop(pac::$dma_peri, $channel_num);} |
| 150 | } | 144 | } |
| 151 | 145 | ||
| 152 | fn is_running(&self) -> bool { | 146 | fn is_running(&self) -> bool { |
| 153 | unsafe {low_level_api::is_running(&crate::pac::$dma_peri, $channel_num)} | 147 | unsafe {low_level_api::is_running(pac::$dma_peri, $channel_num)} |
| 154 | } | 148 | } |
| 155 | 149 | ||
| 156 | fn remaining_transfers(&mut self) -> u16 { | 150 | fn remaining_transfers(&mut self) -> u16 { |
| 157 | unsafe {low_level_api::get_remaining_transfers(&crate::pac::$dma_peri, $channel_num)} | 151 | unsafe {low_level_api::get_remaining_transfers(pac::$dma_peri, $channel_num)} |
| 158 | } | 152 | } |
| 159 | 153 | ||
| 160 | fn set_waker(&mut self, waker: &Waker) { | 154 | fn set_waker(&mut self, waker: &Waker) { |
| @@ -179,13 +173,14 @@ mod low_level_api { | |||
| 179 | use super::*; | 173 | use super::*; |
| 180 | 174 | ||
| 181 | pub unsafe fn start_transfer( | 175 | pub unsafe fn start_transfer( |
| 176 | dma: pac::dma::Dma, | ||
| 177 | channel_number: u8, | ||
| 182 | request: Request, | 178 | request: Request, |
| 183 | dir: vals::Dir, | 179 | dir: vals::Dir, |
| 184 | peri_addr: *const u32, | 180 | peri_addr: *const u32, |
| 185 | mem_addr: *mut u32, | 181 | mem_addr: *mut u32, |
| 186 | mem_len: usize, | 182 | mem_len: usize, |
| 187 | incr_mem: bool, | 183 | incr_mem: bool, |
| 188 | ch: crate::pac::dma::St, | ||
| 189 | data_size: vals::Size, | 184 | data_size: vals::Size, |
| 190 | #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux, | 185 | #[cfg(dmamux)] dmamux_regs: pac::dmamux::Dmamux, |
| 191 | #[cfg(dmamux)] dmamux_ch_num: u8, | 186 | #[cfg(dmamux)] dmamux_ch_num: u8, |
| @@ -196,6 +191,9 @@ mod low_level_api { | |||
| 196 | // "Preceding reads and writes cannot be moved past subsequent writes." | 191 | // "Preceding reads and writes cannot be moved past subsequent writes." |
| 197 | fence(Ordering::SeqCst); | 192 | fence(Ordering::SeqCst); |
| 198 | 193 | ||
| 194 | reset_status(dma, channel_number); | ||
| 195 | |||
| 196 | let ch = dma.st(channel_number as _); | ||
| 199 | ch.par().write_value(peri_addr as u32); | 197 | ch.par().write_value(peri_addr as u32); |
| 200 | ch.m0ar().write_value(mem_addr as u32); | 198 | ch.m0ar().write_value(mem_addr as u32); |
| 201 | ch.ndtr().write_value(regs::Ndtr(mem_len as _)); | 199 | ch.ndtr().write_value(regs::Ndtr(mem_len as _)); |
| @@ -223,34 +221,31 @@ mod low_level_api { | |||
| 223 | } | 221 | } |
| 224 | 222 | ||
| 225 | /// Stops the DMA channel. | 223 | /// Stops the DMA channel. |
| 226 | pub unsafe fn request_stop(dma: &pac::dma::Dma, channel_number: u8) { | 224 | pub unsafe fn request_stop(dma: pac::dma::Dma, channel_number: u8) { |
| 227 | // Reset status | ||
| 228 | let isrn = channel_number as usize / 4; | ||
| 229 | let isrbit = channel_number as usize % 4; | ||
| 230 | reset_status(dma, isrn, isrbit); | ||
| 231 | |||
| 232 | // get a handle on the channel itself | 225 | // get a handle on the channel itself |
| 233 | let ch = dma.st(channel_number as _); | 226 | let ch = dma.st(channel_number as _); |
| 234 | 227 | ||
| 235 | // Disable the channel and interrupts with the default value. | 228 | // Disable the channel. Keep the IEs enabled so the irqs still fire. |
| 236 | ch.cr().write(|_| ()); | 229 | ch.cr().write(|w| { |
| 230 | w.set_teie(true); | ||
| 231 | w.set_tcie(true); | ||
| 232 | }); | ||
| 237 | 233 | ||
| 238 | // "Subsequent reads and writes cannot be moved ahead of preceding reads." | 234 | // "Subsequent reads and writes cannot be moved ahead of preceding reads." |
| 239 | fence(Ordering::SeqCst); | 235 | fence(Ordering::SeqCst); |
| 240 | } | 236 | } |
| 241 | 237 | ||
| 242 | /// Gets the running status of the channel | 238 | /// Gets the running status of the channel |
| 243 | pub unsafe fn is_running(dma: &pac::dma::Dma, ch: u8) -> bool { | 239 | pub unsafe fn is_running(dma: pac::dma::Dma, ch: u8) -> bool { |
| 244 | // get a handle on the channel itself | 240 | // get a handle on the channel itself |
| 245 | let ch = dma.st(ch as _); | 241 | let ch = dma.st(ch as _); |
| 246 | 242 | // Get whether it's enabled (running) | |
| 247 | // Wait for the transfer to complete when it was ongoing. | ||
| 248 | ch.cr().read().en() | 243 | ch.cr().read().en() |
| 249 | } | 244 | } |
| 250 | 245 | ||
| 251 | /// Gets the total remaining transfers for the channel | 246 | /// Gets the total remaining transfers for the channel |
| 252 | /// Note: this will be zero for transfers that completed without cancellation. | 247 | /// Note: this will be zero for transfers that completed without cancellation. |
| 253 | pub unsafe fn get_remaining_transfers(dma: &pac::dma::Dma, ch: u8) -> u16 { | 248 | pub unsafe fn get_remaining_transfers(dma: pac::dma::Dma, ch: u8) -> u16 { |
| 254 | // get a handle on the channel itself | 249 | // get a handle on the channel itself |
| 255 | let ch = dma.st(ch as _); | 250 | let ch = dma.st(ch as _); |
| 256 | // read the remaining transfer count. If this is zero, the transfer completed fully. | 251 | // read the remaining transfer count. If this is zero, the transfer completed fully. |
| @@ -262,7 +257,10 @@ mod low_level_api { | |||
| 262 | STATE.ch_wakers[state_number].register(waker); | 257 | STATE.ch_wakers[state_number].register(waker); |
| 263 | } | 258 | } |
| 264 | 259 | ||
| 265 | pub unsafe fn reset_status(dma: &crate::pac::dma::Dma, isrn: usize, isrbit: usize) { | 260 | pub unsafe fn reset_status(dma: pac::dma::Dma, channel_number: u8) { |
| 261 | let isrn = channel_number as usize / 4; | ||
| 262 | let isrbit = channel_number as usize % 4; | ||
| 263 | |||
| 266 | dma.ifcr(isrn).write(|w| { | 264 | dma.ifcr(isrn).write(|w| { |
| 267 | w.set_tcif(isrbit, true); | 265 | w.set_tcif(isrbit, true); |
| 268 | w.set_teif(isrbit, true); | 266 | w.set_teif(isrbit, true); |
