aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/build.rs49
-rw-r--r--embassy-stm32/src/dma/bdma.rs40
-rw-r--r--embassy-stm32/src/dma/dma.rs36
-rw-r--r--embassy-stm32/src/dma/mod.rs5
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
39static STATE: State = State::new(); 39static STATE: State = State::new();
40 40
41pub(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
62pub(crate) unsafe fn init() { 42pub(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
37static STATE: State = State::new(); 37static STATE: State = State::new();
38 38
39pub(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
56pub(crate) unsafe fn init() { 40pub(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