diff options
| -rw-r--r-- | embassy-stm32/build.rs | 49 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/bdma.rs | 40 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/dma.rs | 36 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/mod.rs | 5 |
4 files changed, 65 insertions, 65 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 02d47da81..0db5e7e2a 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -105,46 +105,37 @@ fn main() { | |||
| 105 | // ======== | 105 | // ======== |
| 106 | // Generate DMA IRQs. | 106 | // Generate DMA IRQs. |
| 107 | 107 | ||
| 108 | let mut dma_irqs: HashSet<&str> = HashSet::new(); | 108 | let mut dma_irqs: HashMap<&str, Vec<(&str, &str)>> = HashMap::new(); |
| 109 | let mut bdma_irqs: HashSet<&str> = HashSet::new(); | ||
| 110 | 109 | ||
| 111 | for p in METADATA.peripherals { | 110 | for p in METADATA.peripherals { |
| 112 | if let Some(r) = &p.registers { | 111 | if let Some(r) = &p.registers { |
| 113 | match r.kind { | 112 | if r.kind == "dma" || r.kind == "bdma" { |
| 114 | "dma" => { | 113 | for irq in p.interrupts { |
| 115 | for irq in p.interrupts { | 114 | dma_irqs |
| 116 | dma_irqs.insert(irq.interrupt); | 115 | .entry(irq.interrupt) |
| 117 | } | 116 | .or_default() |
| 118 | } | 117 | .push((p.name, irq.signal)); |
| 119 | "bdma" => { | ||
| 120 | for irq in p.interrupts { | ||
| 121 | bdma_irqs.insert(irq.interrupt); | ||
| 122 | } | ||
| 123 | } | 118 | } |
| 124 | _ => {} | ||
| 125 | } | 119 | } |
| 126 | } | 120 | } |
| 127 | } | 121 | } |
| 128 | 122 | ||
| 129 | let tokens: Vec<_> = dma_irqs.iter().map(|s| format_ident!("{}", s)).collect(); | 123 | for (irq, channels) in dma_irqs { |
| 130 | g.extend(quote! { | 124 | let irq = format_ident!("{}", irq); |
| 131 | #( | ||
| 132 | #[crate::interrupt] | ||
| 133 | unsafe fn #tokens () { | ||
| 134 | crate::dma::dma::on_irq(); | ||
| 135 | } | ||
| 136 | )* | ||
| 137 | }); | ||
| 138 | 125 | ||
| 139 | let tokens: Vec<_> = bdma_irqs.iter().map(|s| format_ident!("{}", s)).collect(); | 126 | let channels = channels |
| 140 | g.extend(quote! { | 127 | .iter() |
| 141 | #( | 128 | .map(|(dma, ch)| format_ident!("{}_{}", dma, ch)); |
| 129 | |||
| 130 | g.extend(quote! { | ||
| 142 | #[crate::interrupt] | 131 | #[crate::interrupt] |
| 143 | unsafe fn #tokens () { | 132 | unsafe fn #irq () { |
| 144 | crate::dma::bdma::on_irq(); | 133 | #( |
| 134 | <crate::peripherals::#channels as crate::dma::sealed::Channel>::on_irq(); | ||
| 135 | )* | ||
| 145 | } | 136 | } |
| 146 | )* | 137 | }); |
| 147 | }); | 138 | } |
| 148 | 139 | ||
| 149 | // ======== | 140 | // ======== |
| 150 | // Generate RccPeripheral impls | 141 | // Generate RccPeripheral impls |
diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index 105bea50e..ec557da30 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs | |||
| @@ -38,26 +38,6 @@ impl State { | |||
| 38 | 38 | ||
| 39 | static STATE: State = State::new(); | 39 | static STATE: State = State::new(); |
| 40 | 40 | ||
| 41 | pub(crate) unsafe fn on_irq() { | ||
| 42 | foreach_peripheral! { | ||
| 43 | (bdma, BDMA1) => { | ||
| 44 | // BDMA1 in H7 doesn't use DMAMUX, which breaks | ||
| 45 | }; | ||
| 46 | (bdma, $dma:ident) => { | ||
| 47 | let isr = pac::$dma.isr().read(); | ||
| 48 | foreach_dma_channel! { | ||
| 49 | ($channel_peri:ident, $dma, bdma, $channel_num:expr, $index:expr, $dmamux:tt) => { | ||
| 50 | let cr = pac::$dma.ch($channel_num).cr(); | ||
| 51 | if isr.tcif($channel_num) && cr.read().tcie() { | ||
| 52 | cr.write(|_| ()); // Disable channel interrupts with the default value. | ||
| 53 | STATE.ch_wakers[$index].wake(); | ||
| 54 | } | ||
| 55 | }; | ||
| 56 | } | ||
| 57 | }; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | /// safety: must be called only once | 41 | /// safety: must be called only once |
| 62 | pub(crate) unsafe fn init() { | 42 | pub(crate) unsafe fn init() { |
| 63 | foreach_interrupt! { | 43 | foreach_interrupt! { |
| @@ -150,6 +130,12 @@ foreach_dma_channel! { | |||
| 150 | fn set_waker(&mut self, waker: &Waker) { | 130 | fn set_waker(&mut self, waker: &Waker) { |
| 151 | unsafe { low_level_api::set_waker($index, waker) } | 131 | unsafe { low_level_api::set_waker($index, waker) } |
| 152 | } | 132 | } |
| 133 | |||
| 134 | fn on_irq() { | ||
| 135 | unsafe { | ||
| 136 | low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, $index); | ||
| 137 | } | ||
| 138 | } | ||
| 153 | } | 139 | } |
| 154 | 140 | ||
| 155 | impl crate::dma::Channel for crate::peripherals::$channel_peri {} | 141 | impl crate::dma::Channel for crate::peripherals::$channel_peri {} |
| @@ -243,4 +229,18 @@ mod low_level_api { | |||
| 243 | w.set_teif(channel_number as _, true); | 229 | w.set_teif(channel_number as _, true); |
| 244 | }); | 230 | }); |
| 245 | } | 231 | } |
| 232 | |||
| 233 | /// Safety: Must be called with a matching set of parameters for a valid dma channel | ||
| 234 | pub unsafe fn on_irq_inner(dma: pac::bdma::Dma, channel_num: u8, index: u8) { | ||
| 235 | let channel_num = channel_num as usize; | ||
| 236 | let index = index as usize; | ||
| 237 | |||
| 238 | let isr = dma.isr().read(); | ||
| 239 | let cr = dma.ch(channel_num).cr(); | ||
| 240 | |||
| 241 | if isr.tcif(channel_num) && cr.read().tcie() { | ||
| 242 | cr.write(|_| ()); // Disable channel interrupts with the default value. | ||
| 243 | STATE.ch_wakers[index].wake(); | ||
| 244 | } | ||
| 245 | } | ||
| 246 | } | 246 | } |
diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index 95a6eea2f..9ef7e4288 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs | |||
| @@ -36,22 +36,6 @@ impl State { | |||
| 36 | 36 | ||
| 37 | static STATE: State = State::new(); | 37 | static STATE: State = State::new(); |
| 38 | 38 | ||
| 39 | pub(crate) unsafe fn on_irq() { | ||
| 40 | foreach_peripheral! { | ||
| 41 | (dma, $dma:ident) => { | ||
| 42 | foreach_dma_channel! { | ||
| 43 | ($channel_peri:ident, $dma, dma, $channel_num:expr, $index:expr, $dmamux:tt) => { | ||
| 44 | let cr = pac::$dma.st($channel_num).cr(); | ||
| 45 | if pac::$dma.isr($channel_num/4).read().tcif($channel_num%4) && cr.read().tcie() { | ||
| 46 | cr.write(|_| ()); // Disable channel interrupts with the default value. | ||
| 47 | STATE.ch_wakers[$index].wake(); | ||
| 48 | } | ||
| 49 | }; | ||
| 50 | } | ||
| 51 | }; | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | /// safety: must be called only once | 39 | /// safety: must be called only once |
| 56 | pub(crate) unsafe fn init() { | 40 | pub(crate) unsafe fn init() { |
| 57 | foreach_interrupt! { | 41 | foreach_interrupt! { |
| @@ -137,6 +121,12 @@ foreach_dma_channel! { | |||
| 137 | fn set_waker(&mut self, waker: &Waker) { | 121 | fn set_waker(&mut self, waker: &Waker) { |
| 138 | unsafe {low_level_api::set_waker($index, waker )} | 122 | unsafe {low_level_api::set_waker($index, waker )} |
| 139 | } | 123 | } |
| 124 | |||
| 125 | fn on_irq() { | ||
| 126 | unsafe { | ||
| 127 | low_level_api::on_irq_inner(pac::$dma_peri, $channel_num, $index); | ||
| 128 | } | ||
| 129 | } | ||
| 140 | } | 130 | } |
| 141 | 131 | ||
| 142 | impl crate::dma::Channel for crate::peripherals::$channel_peri { } | 132 | impl crate::dma::Channel for crate::peripherals::$channel_peri { } |
| @@ -240,4 +230,18 @@ mod low_level_api { | |||
| 240 | w.set_teif(isrbit, true); | 230 | w.set_teif(isrbit, true); |
| 241 | }); | 231 | }); |
| 242 | } | 232 | } |
| 233 | |||
| 234 | /// Safety: Must be called with a matching set of parameters for a valid dma channel | ||
| 235 | pub unsafe fn on_irq_inner(dma: pac::dma::Dma, channel_num: u8, index: u8) { | ||
| 236 | let channel_num = channel_num as usize; | ||
| 237 | let index = index as usize; | ||
| 238 | |||
| 239 | let cr = dma.st(channel_num).cr(); | ||
| 240 | let isr = dma.isr(channel_num / 4).read(); | ||
| 241 | |||
| 242 | if isr.tcif(channel_num % 4) && cr.read().tcie() { | ||
| 243 | cr.write(|_| ()); // Disable channel interrupts with the default value. | ||
| 244 | STATE.ch_wakers[index].wake(); | ||
| 245 | } | ||
| 246 | } | ||
| 243 | } | 247 | } |
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 6bca969c8..4768a448c 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs | |||
| @@ -88,6 +88,11 @@ pub(crate) mod sealed { | |||
| 88 | 88 | ||
| 89 | /// Sets the waker that is called when this channel stops (either completed or manually stopped) | 89 | /// Sets the waker that is called when this channel stops (either completed or manually stopped) |
| 90 | fn set_waker(&mut self, waker: &Waker); | 90 | fn set_waker(&mut self, waker: &Waker); |
| 91 | |||
| 92 | /// This is called when this channel triggers an interrupt. | ||
| 93 | /// Note: Because some channels share an interrupt, this function might be | ||
| 94 | /// called for a channel that didn't trigger an interrupt. | ||
| 95 | fn on_irq(); | ||
| 91 | } | 96 | } |
| 92 | } | 97 | } |
| 93 | 98 | ||
