diff options
| author | Bob McWhirter <[email protected]> | 2021-06-30 10:50:37 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-06-30 10:50:37 -0400 |
| commit | da014afb89c73570bdcde4070b94c7e3de6e7446 (patch) | |
| tree | 378e293c83e2c92615648916d4e0070a29981301 | |
| parent | d49adc98beebe5b7982204150ebdc0a485fefab2 (diff) | |
| parent | f3b9c977630a0a91eb80e730643760db50d22189 (diff) | |
Merge pull request #253 from bobmcwhirter/dma_tables
Generate dma-related macro tables.
| -rw-r--r-- | embassy-stm32/gen.py | 13 | ||||
| -rw-r--r-- | embassy-stm32/src/bdma/mod.rs | 69 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/mod.rs | 67 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/v2.rs | 338 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f4/mod.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 18 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/v1.rs | 29 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/usart.rs | 2 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/usart_dma.rs | 4 | ||||
| m--------- | stm32-data | 0 | ||||
| -rw-r--r-- | stm32-metapac/Cargo.toml | 1 | ||||
| -rw-r--r-- | stm32-metapac/gen/src/lib.rs | 124 |
12 files changed, 472 insertions, 197 deletions
diff --git a/embassy-stm32/gen.py b/embassy-stm32/gen.py index 386c5ce17..01c778716 100644 --- a/embassy-stm32/gen.py +++ b/embassy-stm32/gen.py | |||
| @@ -73,13 +73,16 @@ with open(output_file, 'w') as f: | |||
| 73 | pins.add(pin) | 73 | pins.add(pin) |
| 74 | singletons.append(pin) | 74 | singletons.append(pin) |
| 75 | 75 | ||
| 76 | if block_mod == 'dma': | 76 | # if block_mod == 'dma': |
| 77 | custom_singletons = True | 77 | # custom_singletons = True |
| 78 | for ch_num in range(8): | 78 | # for ch_num in range(8): |
| 79 | channel = f'{name}_CH{ch_num}' | 79 | # channel = f'{name}_CH{ch_num}' |
| 80 | singletons.append(channel) | 80 | # singletons.append(channel) |
| 81 | 81 | ||
| 82 | if not custom_singletons: | 82 | if not custom_singletons: |
| 83 | singletons.append(name) | 83 | singletons.append(name) |
| 84 | 84 | ||
| 85 | for (channel_id, defn) in core['dma_channels'].items(): | ||
| 86 | singletons.append( channel_id ) | ||
| 87 | |||
| 85 | f.write(f"embassy_extras::peripherals!({','.join(singletons)});") | 88 | f.write(f"embassy_extras::peripherals!({','.join(singletons)});") |
diff --git a/embassy-stm32/src/bdma/mod.rs b/embassy-stm32/src/bdma/mod.rs new file mode 100644 index 000000000..e85ade5df --- /dev/null +++ b/embassy-stm32/src/bdma/mod.rs | |||
| @@ -0,0 +1,69 @@ | |||
| 1 | #![macro_use] | ||
| 2 | |||
| 3 | #[cfg_attr(bdma_v1, path = "v1.rs")] | ||
| 4 | #[cfg_attr(bdma_v2, path = "v2.rs")] | ||
| 5 | mod _version; | ||
| 6 | |||
| 7 | #[allow(unused)] | ||
| 8 | pub use _version::*; | ||
| 9 | |||
| 10 | use crate::pac; | ||
| 11 | use crate::peripherals; | ||
| 12 | |||
| 13 | pub(crate) mod sealed { | ||
| 14 | use super::*; | ||
| 15 | |||
| 16 | pub trait Channel { | ||
| 17 | fn num(&self) -> u8; | ||
| 18 | |||
| 19 | fn dma_num(&self) -> u8 { | ||
| 20 | self.num() / 8 | ||
| 21 | } | ||
| 22 | fn ch_num(&self) -> u8 { | ||
| 23 | self.num() % 8 | ||
| 24 | } | ||
| 25 | fn regs(&self) -> pac::dma::Dma { | ||
| 26 | pac::DMA(self.num() as _) | ||
| 27 | } | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | pub trait Channel: sealed::Channel + Sized {} | ||
| 32 | |||
| 33 | macro_rules! impl_dma_channel { | ||
| 34 | ($channel_peri:ident, $dma_num:expr, $ch_num:expr) => { | ||
| 35 | impl Channel for peripherals::$channel_peri {} | ||
| 36 | impl sealed::Channel for peripherals::$channel_peri { | ||
| 37 | #[inline] | ||
| 38 | fn num(&self) -> u8 { | ||
| 39 | $dma_num * 8 + $ch_num | ||
| 40 | } | ||
| 41 | } | ||
| 42 | }; | ||
| 43 | } | ||
| 44 | |||
| 45 | /* | ||
| 46 | crate::pac::peripherals!( | ||
| 47 | (dma,DMA1) => { | ||
| 48 | impl_dma_channel!(DMA1_CH0, 0, 0); | ||
| 49 | impl_dma_channel!(DMA1_CH1, 0, 1); | ||
| 50 | impl_dma_channel!(DMA1_CH2, 0, 2); | ||
| 51 | impl_dma_channel!(DMA1_CH3, 0, 3); | ||
| 52 | impl_dma_channel!(DMA1_CH4, 0, 4); | ||
| 53 | impl_dma_channel!(DMA1_CH5, 0, 5); | ||
| 54 | impl_dma_channel!(DMA1_CH6, 0, 6); | ||
| 55 | impl_dma_channel!(DMA1_CH7, 0, 7); | ||
| 56 | }; | ||
| 57 | |||
| 58 | (dma,DMA2) => { | ||
| 59 | impl_dma_channel!(DMA2_CH0, 1, 0); | ||
| 60 | impl_dma_channel!(DMA2_CH1, 1, 1); | ||
| 61 | impl_dma_channel!(DMA2_CH2, 1, 2); | ||
| 62 | impl_dma_channel!(DMA2_CH3, 1, 3); | ||
| 63 | impl_dma_channel!(DMA2_CH4, 1, 4); | ||
| 64 | impl_dma_channel!(DMA2_CH5, 1, 5); | ||
| 65 | impl_dma_channel!(DMA2_CH6, 1, 6); | ||
| 66 | impl_dma_channel!(DMA2_CH7, 1, 7); | ||
| 67 | }; | ||
| 68 | ); | ||
| 69 | */ | ||
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 773cdc8b8..371741ffd 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs | |||
| @@ -7,61 +7,24 @@ mod _version; | |||
| 7 | #[allow(unused)] | 7 | #[allow(unused)] |
| 8 | pub use _version::*; | 8 | pub use _version::*; |
| 9 | 9 | ||
| 10 | use crate::pac; | 10 | use core::future::Future; |
| 11 | use crate::peripherals; | ||
| 12 | 11 | ||
| 13 | pub(crate) mod sealed { | 12 | pub trait WriteDma<T> { |
| 14 | use super::*; | 13 | type WriteDmaFuture<'a>: Future<Output = ()> + 'a |
| 14 | where | ||
| 15 | Self: 'a; | ||
| 15 | 16 | ||
| 16 | pub trait Channel { | 17 | fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a> |
| 17 | fn num(&self) -> u8; | 18 | where |
| 18 | 19 | T: 'a; | |
| 19 | fn dma_num(&self) -> u8 { | ||
| 20 | self.num() / 8 | ||
| 21 | } | ||
| 22 | fn ch_num(&self) -> u8 { | ||
| 23 | self.num() % 8 | ||
| 24 | } | ||
| 25 | fn regs(&self) -> pac::dma::Dma { | ||
| 26 | pac::DMA(self.num() as _) | ||
| 27 | } | ||
| 28 | } | ||
| 29 | } | 20 | } |
| 30 | 21 | ||
| 31 | pub trait Channel: sealed::Channel + Sized {} | 22 | pub trait ReadDma<T> { |
| 23 | type ReadDmaFuture<'a>: Future<Output = ()> + 'a | ||
| 24 | where | ||
| 25 | Self: 'a; | ||
| 32 | 26 | ||
| 33 | macro_rules! impl_dma_channel { | 27 | fn transfer<'a>(&'a mut self, src: *const u8, buf: &'a mut [u8]) -> Self::ReadDmaFuture<'a> |
| 34 | ($type:ident, $dma_num:expr, $ch_num:expr) => { | 28 | where |
| 35 | impl Channel for peripherals::$type {} | 29 | T: 'a; |
| 36 | impl sealed::Channel for peripherals::$type { | ||
| 37 | #[inline] | ||
| 38 | fn num(&self) -> u8 { | ||
| 39 | $dma_num * 8 + $ch_num | ||
| 40 | } | ||
| 41 | } | ||
| 42 | }; | ||
| 43 | } | 30 | } |
| 44 | |||
| 45 | crate::pac::peripherals!( | ||
| 46 | (dma,DMA1) => { | ||
| 47 | impl_dma_channel!(DMA1_CH0, 0, 0); | ||
| 48 | impl_dma_channel!(DMA1_CH1, 0, 1); | ||
| 49 | impl_dma_channel!(DMA1_CH2, 0, 2); | ||
| 50 | impl_dma_channel!(DMA1_CH3, 0, 3); | ||
| 51 | impl_dma_channel!(DMA1_CH4, 0, 4); | ||
| 52 | impl_dma_channel!(DMA1_CH5, 0, 5); | ||
| 53 | impl_dma_channel!(DMA1_CH6, 0, 6); | ||
| 54 | impl_dma_channel!(DMA1_CH7, 0, 7); | ||
| 55 | }; | ||
| 56 | |||
| 57 | (dma,DMA2) => { | ||
| 58 | impl_dma_channel!(DMA2_CH0, 1, 0); | ||
| 59 | impl_dma_channel!(DMA2_CH1, 1, 1); | ||
| 60 | impl_dma_channel!(DMA2_CH2, 1, 2); | ||
| 61 | impl_dma_channel!(DMA2_CH3, 1, 3); | ||
| 62 | impl_dma_channel!(DMA2_CH4, 1, 4); | ||
| 63 | impl_dma_channel!(DMA2_CH5, 1, 5); | ||
| 64 | impl_dma_channel!(DMA2_CH6, 1, 6); | ||
| 65 | impl_dma_channel!(DMA2_CH7, 1, 7); | ||
| 66 | }; | ||
| 67 | ); | ||
diff --git a/embassy-stm32/src/dma/v2.rs b/embassy-stm32/src/dma/v2.rs index e7bd69130..93b3cb869 100644 --- a/embassy-stm32/src/dma/v2.rs +++ b/embassy-stm32/src/dma/v2.rs | |||
| @@ -9,9 +9,14 @@ use crate::interrupt; | |||
| 9 | use crate::pac; | 9 | use crate::pac; |
| 10 | use crate::pac::dma::{regs, vals}; | 10 | use crate::pac::dma::{regs, vals}; |
| 11 | 11 | ||
| 12 | const DMAS: [pac::dma::Dma; 2] = [pac::DMA1, pac::DMA2]; | 12 | use crate::pac::dma_channels; |
| 13 | use crate::pac::interrupts; | ||
| 14 | use crate::pac::peripheral_count; | ||
| 15 | use crate::pac::peripheral_dma_channels; | ||
| 16 | use crate::pac::peripherals; | ||
| 17 | use crate::peripherals; | ||
| 13 | 18 | ||
| 14 | const CH_COUNT: usize = 16; | 19 | const CH_COUNT: usize = peripheral_count!(DMA) * 8; |
| 15 | const CH_STATUS_NONE: u8 = 0; | 20 | const CH_STATUS_NONE: u8 = 0; |
| 16 | const CH_STATUS_COMPLETED: u8 = 1; | 21 | const CH_STATUS_COMPLETED: u8 = 1; |
| 17 | const CH_STATUS_ERROR: u8 = 2; | 22 | const CH_STATUS_ERROR: u8 = 2; |
| @@ -35,15 +40,60 @@ impl State { | |||
| 35 | static STATE: State = State::new(); | 40 | static STATE: State = State::new(); |
| 36 | 41 | ||
| 37 | #[allow(unused)] // Used by usart/v1.rs which may or may not be enabled | 42 | #[allow(unused)] // Used by usart/v1.rs which may or may not be enabled |
| 43 | pub(crate) async unsafe fn transfer_p2m( | ||
| 44 | ch: &mut impl Channel, | ||
| 45 | ch_func: u8, | ||
| 46 | src: *const u8, | ||
| 47 | dst: &mut [u8], | ||
| 48 | ) { | ||
| 49 | let n = ch.num(); | ||
| 50 | let c = ch.regs(); | ||
| 51 | |||
| 52 | // ndtr is max 16 bits. | ||
| 53 | assert!(dst.len() <= 0xFFFF); | ||
| 54 | |||
| 55 | // Reset status | ||
| 56 | STATE.ch_status[n].store(CH_STATUS_NONE, Ordering::Relaxed); | ||
| 57 | |||
| 58 | unsafe { | ||
| 59 | c.par().write_value(src as _); | ||
| 60 | c.m0ar().write_value(dst.as_ptr() as _); | ||
| 61 | c.ndtr().write_value(regs::Ndtr(dst.len() as _)); | ||
| 62 | c.cr().write(|w| { | ||
| 63 | w.set_dir(vals::Dir::PERIPHERALTOMEMORY); | ||
| 64 | w.set_msize(vals::Size::BITS8); | ||
| 65 | w.set_psize(vals::Size::BITS8); | ||
| 66 | w.set_minc(vals::Inc::INCREMENTED); | ||
| 67 | w.set_pinc(vals::Inc::FIXED); | ||
| 68 | w.set_chsel(ch_func); | ||
| 69 | w.set_teie(true); | ||
| 70 | w.set_tcie(true); | ||
| 71 | w.set_en(true); | ||
| 72 | }); | ||
| 73 | } | ||
| 74 | |||
| 75 | let res = poll_fn(|cx| { | ||
| 76 | STATE.ch_wakers[n].register(cx.waker()); | ||
| 77 | match STATE.ch_status[n].load(Ordering::Acquire) { | ||
| 78 | CH_STATUS_NONE => Poll::Pending, | ||
| 79 | x => Poll::Ready(x), | ||
| 80 | } | ||
| 81 | }) | ||
| 82 | .await; | ||
| 83 | |||
| 84 | // TODO handle error | ||
| 85 | assert!(res == CH_STATUS_COMPLETED); | ||
| 86 | } | ||
| 87 | |||
| 88 | #[allow(unused)] // Used by usart/v1.rs which may or may not be enabled | ||
| 38 | pub(crate) async unsafe fn transfer_m2p( | 89 | pub(crate) async unsafe fn transfer_m2p( |
| 39 | ch: &mut impl Channel, | 90 | ch: &mut impl Channel, |
| 40 | ch_func: u8, | 91 | ch_func: u8, |
| 41 | src: &[u8], | 92 | src: &[u8], |
| 42 | dst: *mut u8, | 93 | dst: *mut u8, |
| 43 | ) { | 94 | ) { |
| 44 | let n = ch.num() as usize; | 95 | let n = ch.num(); |
| 45 | let r = ch.regs(); | 96 | let c = ch.regs(); |
| 46 | let c = r.st(ch.ch_num() as _); | ||
| 47 | 97 | ||
| 48 | // ndtr is max 16 bits. | 98 | // ndtr is max 16 bits. |
| 49 | assert!(src.len() <= 0xFFFF); | 99 | assert!(src.len() <= 0xFFFF); |
| @@ -55,6 +105,7 @@ pub(crate) async unsafe fn transfer_m2p( | |||
| 55 | c.par().write_value(dst as _); | 105 | c.par().write_value(dst as _); |
| 56 | c.m0ar().write_value(src.as_ptr() as _); | 106 | c.m0ar().write_value(src.as_ptr() as _); |
| 57 | c.ndtr().write_value(regs::Ndtr(src.len() as _)); | 107 | c.ndtr().write_value(regs::Ndtr(src.len() as _)); |
| 108 | compiler_fence(Ordering::AcqRel); | ||
| 58 | c.cr().write(|w| { | 109 | c.cr().write(|w| { |
| 59 | w.set_dir(vals::Dir::MEMORYTOPERIPHERAL); | 110 | w.set_dir(vals::Dir::MEMORYTOPERIPHERAL); |
| 60 | w.set_msize(vals::Size::BITS8); | 111 | w.set_msize(vals::Size::BITS8); |
| @@ -70,118 +121,211 @@ pub(crate) async unsafe fn transfer_m2p( | |||
| 70 | 121 | ||
| 71 | let res = poll_fn(|cx| { | 122 | let res = poll_fn(|cx| { |
| 72 | STATE.ch_wakers[n].register(cx.waker()); | 123 | STATE.ch_wakers[n].register(cx.waker()); |
| 73 | match STATE.ch_status[n].load(Ordering::Relaxed) { | 124 | match STATE.ch_status[n].load(Ordering::Acquire) { |
| 74 | CH_STATUS_NONE => Poll::Pending, | 125 | CH_STATUS_NONE => { |
| 126 | let left = c.ndtr().read().ndt(); | ||
| 127 | Poll::Pending | ||
| 128 | } | ||
| 75 | x => Poll::Ready(x), | 129 | x => Poll::Ready(x), |
| 76 | } | 130 | } |
| 77 | }) | 131 | }) |
| 78 | .await; | 132 | .await; |
| 79 | 133 | ||
| 134 | compiler_fence(Ordering::AcqRel); | ||
| 135 | |||
| 80 | // TODO handle error | 136 | // TODO handle error |
| 81 | assert!(res == CH_STATUS_COMPLETED); | 137 | assert!(res == CH_STATUS_COMPLETED); |
| 82 | } | 138 | } |
| 83 | 139 | ||
| 84 | unsafe fn on_irq() { | 140 | unsafe fn on_irq() { |
| 85 | for (dman, &dma) in DMAS.iter().enumerate() { | 141 | peripherals! { |
| 86 | for isrn in 0..2 { | 142 | (dma, $dma:ident) => { |
| 87 | let isr = dma.isr(isrn).read(); | 143 | for isrn in 0..2 { |
| 88 | dma.ifcr(isrn).write_value(isr); | 144 | let isr = pac::$dma.isr(isrn).read(); |
| 89 | 145 | pac::$dma.ifcr(isrn).write_value(isr); | |
| 90 | for chn in 0..4 { | 146 | let dman = <peripherals::$dma as sealed::Dma>::num() as usize; |
| 91 | let n = dman * 8 + isrn * 4 + chn; | 147 | |
| 92 | if isr.teif(chn) { | 148 | for chn in 0..4 { |
| 93 | STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Relaxed); | 149 | let n = dman * 8 + isrn * 4 + chn; |
| 94 | STATE.ch_wakers[n].wake(); | 150 | if isr.teif(chn) { |
| 95 | } else if isr.tcif(chn) { | 151 | STATE.ch_status[n].store(CH_STATUS_ERROR, Ordering::Release); |
| 96 | STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Relaxed); | 152 | STATE.ch_wakers[n].wake(); |
| 97 | STATE.ch_wakers[n].wake(); | 153 | } else if isr.tcif(chn) { |
| 154 | STATE.ch_status[n].store(CH_STATUS_COMPLETED, Ordering::Release); | ||
| 155 | STATE.ch_wakers[n].wake(); | ||
| 156 | } | ||
| 98 | } | 157 | } |
| 99 | } | 158 | } |
| 100 | } | 159 | }; |
| 101 | } | 160 | } |
| 102 | } | 161 | } |
| 103 | 162 | ||
| 104 | #[interrupt] | 163 | /// safety: must be called only once |
| 105 | unsafe fn DMA1_STREAM0() { | 164 | pub(crate) unsafe fn init() { |
| 106 | on_irq() | 165 | interrupts! { |
| 107 | } | 166 | (DMA, $irq:ident) => { |
| 108 | #[interrupt] | 167 | interrupt::$irq::steal().enable(); |
| 109 | unsafe fn DMA1_STREAM1() { | 168 | }; |
| 110 | on_irq() | 169 | } |
| 111 | } | ||
| 112 | #[interrupt] | ||
| 113 | unsafe fn DMA1_STREAM2() { | ||
| 114 | on_irq() | ||
| 115 | } | ||
| 116 | #[interrupt] | ||
| 117 | unsafe fn DMA1_STREAM3() { | ||
| 118 | on_irq() | ||
| 119 | } | ||
| 120 | #[interrupt] | ||
| 121 | unsafe fn DMA1_STREAM4() { | ||
| 122 | on_irq() | ||
| 123 | } | ||
| 124 | #[interrupt] | ||
| 125 | unsafe fn DMA1_STREAM5() { | ||
| 126 | on_irq() | ||
| 127 | } | ||
| 128 | #[interrupt] | ||
| 129 | unsafe fn DMA1_STREAM6() { | ||
| 130 | on_irq() | ||
| 131 | } | ||
| 132 | #[interrupt] | ||
| 133 | unsafe fn DMA1_STREAM7() { | ||
| 134 | on_irq() | ||
| 135 | } | ||
| 136 | #[interrupt] | ||
| 137 | unsafe fn DMA2_STREAM0() { | ||
| 138 | on_irq() | ||
| 139 | } | ||
| 140 | #[interrupt] | ||
| 141 | unsafe fn DMA2_STREAM1() { | ||
| 142 | on_irq() | ||
| 143 | } | ||
| 144 | #[interrupt] | ||
| 145 | unsafe fn DMA2_STREAM2() { | ||
| 146 | on_irq() | ||
| 147 | } | 170 | } |
| 148 | #[interrupt] | 171 | |
| 149 | unsafe fn DMA2_STREAM3() { | 172 | pub(crate) mod sealed { |
| 150 | on_irq() | 173 | use super::*; |
| 174 | |||
| 175 | pub trait Dma { | ||
| 176 | fn num() -> u8; | ||
| 177 | fn regs() -> &'static pac::dma::Dma; | ||
| 178 | } | ||
| 179 | |||
| 180 | pub trait Channel { | ||
| 181 | fn dma_regs() -> &'static pac::dma::Dma; | ||
| 182 | |||
| 183 | fn num(&self) -> usize; | ||
| 184 | |||
| 185 | fn ch_num(&self) -> u8; | ||
| 186 | |||
| 187 | fn regs(&self) -> pac::dma::St { | ||
| 188 | Self::dma_regs().st(self.ch_num() as _) | ||
| 189 | } | ||
| 190 | } | ||
| 191 | |||
| 192 | pub trait PeripheralChannel<PERI, OP>: Channel { | ||
| 193 | fn request(&self) -> u8; | ||
| 194 | } | ||
| 151 | } | 195 | } |
| 152 | #[interrupt] | 196 | |
| 153 | unsafe fn DMA2_STREAM4() { | 197 | pub trait Dma: sealed::Dma + Sized {} |
| 154 | on_irq() | 198 | pub trait Channel: sealed::Channel + Sized {} |
| 199 | pub trait PeripheralChannel<PERI, OP>: sealed::PeripheralChannel<PERI, OP> + Sized {} | ||
| 200 | |||
| 201 | macro_rules! impl_dma { | ||
| 202 | ($peri:ident, $num:expr) => { | ||
| 203 | impl Dma for peripherals::$peri {} | ||
| 204 | impl sealed::Dma for peripherals::$peri { | ||
| 205 | fn num() -> u8 { | ||
| 206 | $num | ||
| 207 | } | ||
| 208 | fn regs() -> &'static pac::dma::Dma { | ||
| 209 | &pac::$peri | ||
| 210 | } | ||
| 211 | } | ||
| 212 | }; | ||
| 155 | } | 213 | } |
| 156 | #[interrupt] | 214 | |
| 157 | unsafe fn DMA2_STREAM5() { | 215 | macro_rules! impl_dma_channel { |
| 158 | on_irq() | 216 | ($channel_peri:ident, $dma_peri:ident, $dma_num:expr, $ch_num:expr) => { |
| 217 | impl Channel for peripherals::$channel_peri {} | ||
| 218 | impl sealed::Channel for peripherals::$channel_peri { | ||
| 219 | #[inline] | ||
| 220 | fn dma_regs() -> &'static pac::dma::Dma { | ||
| 221 | &crate::pac::$dma_peri | ||
| 222 | } | ||
| 223 | |||
| 224 | fn num(&self) -> usize { | ||
| 225 | ($dma_num * 8) + $ch_num | ||
| 226 | } | ||
| 227 | |||
| 228 | fn ch_num(&self) -> u8 { | ||
| 229 | $ch_num | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 233 | impl<T> WriteDma<T> for peripherals::$channel_peri | ||
| 234 | where | ||
| 235 | Self: sealed::PeripheralChannel<T, M2P>, | ||
| 236 | T: 'static, | ||
| 237 | { | ||
| 238 | type WriteDmaFuture<'a> = impl Future<Output = ()>; | ||
| 239 | |||
| 240 | fn transfer<'a>(&'a mut self, buf: &'a [u8], dst: *mut u8) -> Self::WriteDmaFuture<'a> | ||
| 241 | where | ||
| 242 | T: 'a, | ||
| 243 | { | ||
| 244 | let request = sealed::PeripheralChannel::<T, M2P>::request(self); | ||
| 245 | unsafe { transfer_m2p(self, request, buf, dst) } | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | impl<T> ReadDma<T> for peripherals::$channel_peri | ||
| 250 | where | ||
| 251 | Self: sealed::PeripheralChannel<T, P2M>, | ||
| 252 | T: 'static, | ||
| 253 | { | ||
| 254 | type ReadDmaFuture<'a> = impl Future<Output = ()>; | ||
| 255 | |||
| 256 | fn transfer<'a>( | ||
| 257 | &'a mut self, | ||
| 258 | src: *const u8, | ||
| 259 | buf: &'a mut [u8], | ||
| 260 | ) -> Self::ReadDmaFuture<'a> | ||
| 261 | where | ||
| 262 | T: 'a, | ||
| 263 | { | ||
| 264 | let request = sealed::PeripheralChannel::<T, P2M>::request(self); | ||
| 265 | unsafe { transfer_p2m(self, request, src, buf) } | ||
| 266 | } | ||
| 267 | } | ||
| 268 | }; | ||
| 159 | } | 269 | } |
| 160 | #[interrupt] | 270 | |
| 161 | unsafe fn DMA2_STREAM6() { | 271 | peripherals! { |
| 162 | on_irq() | 272 | (dma, DMA1) => { |
| 273 | impl_dma!(DMA1, 0); | ||
| 274 | dma_channels! { | ||
| 275 | ($channel_peri:ident, DMA1, $channel_num:expr) => { | ||
| 276 | impl_dma_channel!($channel_peri, DMA1, 0, $channel_num); | ||
| 277 | }; | ||
| 278 | } | ||
| 279 | }; | ||
| 280 | (dma, DMA2) => { | ||
| 281 | impl_dma!(DMA2, 1); | ||
| 282 | dma_channels! { | ||
| 283 | ($channel_peri:ident, DMA2, $channel_num:expr) => { | ||
| 284 | impl_dma_channel!($channel_peri, DMA2, 1, $channel_num); | ||
| 285 | }; | ||
| 286 | } | ||
| 287 | }; | ||
| 163 | } | 288 | } |
| 164 | #[interrupt] | 289 | |
| 165 | unsafe fn DMA2_STREAM7() { | 290 | interrupts! { |
| 166 | on_irq() | 291 | (DMA, $irq:ident) => { |
| 292 | #[crate::interrupt] | ||
| 293 | unsafe fn $irq () { | ||
| 294 | on_irq() | ||
| 295 | } | ||
| 296 | }; | ||
| 167 | } | 297 | } |
| 168 | 298 | ||
| 169 | /// safety: must be called only once | 299 | pub struct P2M; |
| 170 | pub(crate) unsafe fn init() { | 300 | pub struct M2P; |
| 171 | interrupt::DMA1_STREAM0::steal().enable(); | 301 | |
| 172 | interrupt::DMA1_STREAM1::steal().enable(); | 302 | #[cfg(usart)] |
| 173 | interrupt::DMA1_STREAM2::steal().enable(); | 303 | use crate::usart; |
| 174 | interrupt::DMA1_STREAM3::steal().enable(); | 304 | use atomic_polyfill::compiler_fence; |
| 175 | interrupt::DMA1_STREAM4::steal().enable(); | 305 | peripheral_dma_channels! { |
| 176 | interrupt::DMA1_STREAM5::steal().enable(); | 306 | ($peri:ident, usart, $kind:ident, RX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr, $event_num:expr) => { |
| 177 | interrupt::DMA1_STREAM6::steal().enable(); | 307 | impl usart::RxDma<peripherals::$peri> for peripherals::$channel_peri { } |
| 178 | interrupt::DMA1_STREAM7::steal().enable(); | 308 | impl usart::sealed::RxDma<peripherals::$peri> for peripherals::$channel_peri { } |
| 179 | interrupt::DMA2_STREAM0::steal().enable(); | 309 | |
| 180 | interrupt::DMA2_STREAM1::steal().enable(); | 310 | impl sealed::PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri { |
| 181 | interrupt::DMA2_STREAM2::steal().enable(); | 311 | fn request(&self) -> u8 { |
| 182 | interrupt::DMA2_STREAM3::steal().enable(); | 312 | $event_num |
| 183 | interrupt::DMA2_STREAM4::steal().enable(); | 313 | } |
| 184 | interrupt::DMA2_STREAM5::steal().enable(); | 314 | } |
| 185 | interrupt::DMA2_STREAM6::steal().enable(); | 315 | |
| 186 | interrupt::DMA2_STREAM7::steal().enable(); | 316 | impl PeripheralChannel<peripherals::$peri, P2M> for peripherals::$channel_peri { } |
| 317 | }; | ||
| 318 | |||
| 319 | ($peri:ident, usart, $kind:ident, TX, $channel_peri:ident, $dma_peri:ident, $channel_num:expr, $event_num:expr) => { | ||
| 320 | impl usart::TxDma<peripherals::$peri> for peripherals::$channel_peri { } | ||
| 321 | impl usart::sealed::TxDma<peripherals::$peri> for peripherals::$channel_peri { } | ||
| 322 | |||
| 323 | impl sealed::PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri { | ||
| 324 | fn request(&self) -> u8 { | ||
| 325 | $event_num | ||
| 326 | } | ||
| 327 | } | ||
| 328 | |||
| 329 | impl PeripheralChannel<peripherals::$peri, M2P> for peripherals::$channel_peri { } | ||
| 330 | }; | ||
| 187 | } | 331 | } |
diff --git a/embassy-stm32/src/rcc/f4/mod.rs b/embassy-stm32/src/rcc/f4/mod.rs index 4b17bdf40..6000192b9 100644 --- a/embassy-stm32/src/rcc/f4/mod.rs +++ b/embassy-stm32/src/rcc/f4/mod.rs | |||
| @@ -132,7 +132,7 @@ impl RccExt for RCC { | |||
| 132 | ClockSrc::HSI16 => { | 132 | ClockSrc::HSI16 => { |
| 133 | // Enable HSI16 | 133 | // Enable HSI16 |
| 134 | unsafe { | 134 | unsafe { |
| 135 | rcc.cr().write(|w| w.set_hsion(true)); | 135 | rcc.cr().modify(|w| w.set_hsion(true)); |
| 136 | while !rcc.cr().read().hsirdy() {} | 136 | while !rcc.cr().read().hsirdy() {} |
| 137 | } | 137 | } |
| 138 | 138 | ||
| @@ -141,7 +141,7 @@ impl RccExt for RCC { | |||
| 141 | ClockSrc::HSE(freq) => { | 141 | ClockSrc::HSE(freq) => { |
| 142 | // Enable HSE | 142 | // Enable HSE |
| 143 | unsafe { | 143 | unsafe { |
| 144 | rcc.cr().write(|w| w.set_hseon(true)); | 144 | rcc.cr().modify(|w| w.set_hseon(true)); |
| 145 | while !rcc.cr().read().hserdy() {} | 145 | while !rcc.cr().read().hserdy() {} |
| 146 | } | 146 | } |
| 147 | 147 | ||
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index adf48c326..a75793f84 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -8,6 +8,7 @@ pub use _version::*; | |||
| 8 | 8 | ||
| 9 | use crate::gpio::Pin; | 9 | use crate::gpio::Pin; |
| 10 | use crate::pac::usart::Usart; | 10 | use crate::pac::usart::Usart; |
| 11 | use crate::rcc::RccPeripheral; | ||
| 11 | 12 | ||
| 12 | /// Serial error | 13 | /// Serial error |
| 13 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] | 14 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] |
| @@ -26,6 +27,9 @@ pub enum Error { | |||
| 26 | pub(crate) mod sealed { | 27 | pub(crate) mod sealed { |
| 27 | use super::*; | 28 | use super::*; |
| 28 | 29 | ||
| 30 | #[cfg(dma)] | ||
| 31 | use crate::dma::WriteDma; | ||
| 32 | |||
| 29 | pub trait Instance { | 33 | pub trait Instance { |
| 30 | fn regs(&self) -> Usart; | 34 | fn regs(&self) -> Usart; |
| 31 | } | 35 | } |
| @@ -44,14 +48,26 @@ pub(crate) mod sealed { | |||
| 44 | pub trait CkPin<T: Instance>: Pin { | 48 | pub trait CkPin<T: Instance>: Pin { |
| 45 | fn af_num(&self) -> u8; | 49 | fn af_num(&self) -> u8; |
| 46 | } | 50 | } |
| 51 | |||
| 52 | #[cfg(dma)] | ||
| 53 | pub trait RxDma<T: Instance> {} | ||
| 54 | |||
| 55 | #[cfg(dma)] | ||
| 56 | pub trait TxDma<T: Instance>: WriteDma<T> {} | ||
| 47 | } | 57 | } |
| 48 | pub trait Instance: sealed::Instance {} | 58 | |
| 59 | pub trait Instance: sealed::Instance + RccPeripheral {} | ||
| 49 | pub trait RxPin<T: Instance>: sealed::RxPin<T> {} | 60 | pub trait RxPin<T: Instance>: sealed::RxPin<T> {} |
| 50 | pub trait TxPin<T: Instance>: sealed::TxPin<T> {} | 61 | pub trait TxPin<T: Instance>: sealed::TxPin<T> {} |
| 51 | pub trait CtsPin<T: Instance>: sealed::CtsPin<T> {} | 62 | pub trait CtsPin<T: Instance>: sealed::CtsPin<T> {} |
| 52 | pub trait RtsPin<T: Instance>: sealed::RtsPin<T> {} | 63 | pub trait RtsPin<T: Instance>: sealed::RtsPin<T> {} |
| 53 | pub trait CkPin<T: Instance>: sealed::CkPin<T> {} | 64 | pub trait CkPin<T: Instance>: sealed::CkPin<T> {} |
| 54 | 65 | ||
| 66 | #[cfg(dma)] | ||
| 67 | pub trait RxDma<T: Instance>: sealed::RxDma<T> {} | ||
| 68 | #[cfg(dma)] | ||
| 69 | pub trait TxDma<T: Instance>: sealed::TxDma<T> {} | ||
| 70 | |||
| 55 | crate::pac::peripherals!( | 71 | crate::pac::peripherals!( |
| 56 | (usart, $inst:ident) => { | 72 | (usart, $inst:ident) => { |
| 57 | impl sealed::Instance for peripherals::$inst { | 73 | impl sealed::Instance for peripherals::$inst { |
diff --git a/embassy-stm32/src/usart/v1.rs b/embassy-stm32/src/usart/v1.rs index 1ec1f5b30..6c5a12441 100644 --- a/embassy-stm32/src/usart/v1.rs +++ b/embassy-stm32/src/usart/v1.rs | |||
| @@ -63,14 +63,14 @@ impl<'d, T: Instance> Uart<'d, T> { | |||
| 63 | rx: impl Unborrow<Target = impl RxPin<T>>, | 63 | rx: impl Unborrow<Target = impl RxPin<T>>, |
| 64 | tx: impl Unborrow<Target = impl TxPin<T>>, | 64 | tx: impl Unborrow<Target = impl TxPin<T>>, |
| 65 | config: Config, | 65 | config: Config, |
| 66 | pclk_freq: u32, | ||
| 67 | ) -> Self { | 66 | ) -> Self { |
| 68 | unborrow!(inner, rx, tx); | 67 | unborrow!(inner, rx, tx); |
| 69 | 68 | ||
| 70 | // TODO: enable in RCC | 69 | T::enable(); |
| 70 | let pclk_freq = T::frequency(); | ||
| 71 | 71 | ||
| 72 | // TODO: better calculation, including error checking and OVER8 if possible. | 72 | // TODO: better calculation, including error checking and OVER8 if possible. |
| 73 | let div = (pclk_freq + (config.baudrate / 2)) / config.baudrate; | 73 | let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate; |
| 74 | 74 | ||
| 75 | let r = inner.regs(); | 75 | let r = inner.regs(); |
| 76 | 76 | ||
| @@ -101,25 +101,16 @@ impl<'d, T: Instance> Uart<'d, T> { | |||
| 101 | } | 101 | } |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | #[cfg(dma_v2)] | 104 | #[cfg(dma)] |
| 105 | pub async fn write_dma( | 105 | pub async fn write_dma(&mut self, ch: &mut impl TxDma<T>, buffer: &[u8]) -> Result<(), Error> { |
| 106 | &mut self, | ||
| 107 | ch: &mut impl crate::dma::Channel, | ||
| 108 | buffer: &[u8], | ||
| 109 | ) -> Result<(), Error> { | ||
| 110 | let ch_func = 4; // USART3_TX | ||
| 111 | let r = self.inner.regs(); | ||
| 112 | |||
| 113 | unsafe { | 106 | unsafe { |
| 114 | r.cr3().write(|w| { | 107 | self.inner.regs().cr3().modify(|reg| { |
| 115 | w.set_dmat(true); | 108 | reg.set_dmat(true); |
| 116 | }); | 109 | }); |
| 117 | |||
| 118 | let dst = r.dr().ptr() as *mut u8; | ||
| 119 | |||
| 120 | crate::dma::transfer_m2p(ch, ch_func, buffer, dst).await; | ||
| 121 | } | 110 | } |
| 122 | 111 | let r = self.inner.regs(); | |
| 112 | let dst = r.dr().ptr() as *mut u8; | ||
| 113 | ch.transfer(buffer, dst).await; | ||
| 123 | Ok(()) | 114 | Ok(()) |
| 124 | } | 115 | } |
| 125 | 116 | ||
diff --git a/examples/stm32f4/src/bin/usart.rs b/examples/stm32f4/src/bin/usart.rs index f7b66f86b..42f154b05 100644 --- a/examples/stm32f4/src/bin/usart.rs +++ b/examples/stm32f4/src/bin/usart.rs | |||
| @@ -23,7 +23,7 @@ async fn main_task() { | |||
| 23 | let p = embassy_stm32::init(Default::default()); | 23 | let p = embassy_stm32::init(Default::default()); |
| 24 | 24 | ||
| 25 | let config = Config::default(); | 25 | let config = Config::default(); |
| 26 | let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config, 16_000_000); | 26 | let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config); |
| 27 | 27 | ||
| 28 | usart.bwrite_all(b"Hello Embassy World!\r\n").unwrap(); | 28 | usart.bwrite_all(b"Hello Embassy World!\r\n").unwrap(); |
| 29 | info!("wrote Hello, starting echo"); | 29 | info!("wrote Hello, starting echo"); |
diff --git a/examples/stm32f4/src/bin/usart_dma.rs b/examples/stm32f4/src/bin/usart_dma.rs index fae05b607..66ca6242b 100644 --- a/examples/stm32f4/src/bin/usart_dma.rs +++ b/examples/stm32f4/src/bin/usart_dma.rs | |||
| @@ -23,14 +23,14 @@ async fn main_task() { | |||
| 23 | let mut p = embassy_stm32::init(Default::default()); | 23 | let mut p = embassy_stm32::init(Default::default()); |
| 24 | 24 | ||
| 25 | let config = Config::default(); | 25 | let config = Config::default(); |
| 26 | let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config, 16_000_000); | 26 | let mut usart = Uart::new(p.USART3, p.PD9, p.PD8, config); |
| 27 | 27 | ||
| 28 | for n in 0u32.. { | 28 | for n in 0u32.. { |
| 29 | let mut s: String<128> = String::new(); | 29 | let mut s: String<128> = String::new(); |
| 30 | core::write!(&mut s, "Hello DMA World {}!\r\n", n).unwrap(); | 30 | core::write!(&mut s, "Hello DMA World {}!\r\n", n).unwrap(); |
| 31 | 31 | ||
| 32 | usart | 32 | usart |
| 33 | .write_dma(&mut p.DMA1_CH3, s.as_bytes()) | 33 | .write_dma(&mut p.DMA1_3, s.as_bytes()) |
| 34 | .await | 34 | .await |
| 35 | .unwrap(); | 35 | .unwrap(); |
| 36 | info!("wrote DMA"); | 36 | info!("wrote DMA"); |
diff --git a/stm32-data b/stm32-data | |||
| Subproject eb76ee900ac67b51497196572250323e82666b4 | Subproject 9856b11172ae27ffa60d339ac271d2d06c19075 | ||
diff --git a/stm32-metapac/Cargo.toml b/stm32-metapac/Cargo.toml index bed772c81..79f1c3746 100644 --- a/stm32-metapac/Cargo.toml +++ b/stm32-metapac/Cargo.toml | |||
| @@ -12,6 +12,7 @@ cortex-m-rt = { version = "0.6.8", optional = true } | |||
| 12 | # These are removed when generating the pre-generated crate using the tool at gen/. | 12 | # These are removed when generating the pre-generated crate using the tool at gen/. |
| 13 | [build-dependencies] | 13 | [build-dependencies] |
| 14 | stm32-metapac-gen = { path = "./gen" } | 14 | stm32-metapac-gen = { path = "./gen" } |
| 15 | regex = "1.5.4" | ||
| 15 | # END BUILD DEPENDENCIES | 16 | # END BUILD DEPENDENCIES |
| 16 | 17 | ||
| 17 | [features] | 18 | [features] |
diff --git a/stm32-metapac/gen/src/lib.rs b/stm32-metapac/gen/src/lib.rs index 9e7add452..a552c8cea 100644 --- a/stm32-metapac/gen/src/lib.rs +++ b/stm32-metapac/gen/src/lib.rs | |||
| @@ -27,6 +27,7 @@ pub struct Core { | |||
| 27 | pub name: String, | 27 | pub name: String, |
| 28 | pub peripherals: HashMap<String, Peripheral>, | 28 | pub peripherals: HashMap<String, Peripheral>, |
| 29 | pub interrupts: HashMap<String, u32>, | 29 | pub interrupts: HashMap<String, u32>, |
| 30 | pub dma_channels: HashMap<String, DmaChannel>, | ||
| 30 | } | 31 | } |
| 31 | 32 | ||
| 32 | #[derive(Debug, Eq, PartialEq, Clone, Deserialize)] | 33 | #[derive(Debug, Eq, PartialEq, Clone, Deserialize)] |
| @@ -46,6 +47,10 @@ pub struct Peripheral { | |||
| 46 | pub clock: Option<String>, | 47 | pub clock: Option<String>, |
| 47 | #[serde(default)] | 48 | #[serde(default)] |
| 48 | pub pins: Vec<Pin>, | 49 | pub pins: Vec<Pin>, |
| 50 | #[serde(default)] | ||
| 51 | pub dma_channels: HashMap<String, Vec<PeripheralDmaChannel>>, | ||
| 52 | #[serde(default)] | ||
| 53 | pub dma_requests: HashMap<String, u32>, | ||
| 49 | } | 54 | } |
| 50 | 55 | ||
| 51 | #[derive(Debug, Eq, PartialEq, Clone, Deserialize)] | 56 | #[derive(Debug, Eq, PartialEq, Clone, Deserialize)] |
| @@ -55,6 +60,18 @@ pub struct Pin { | |||
| 55 | pub af: Option<String>, | 60 | pub af: Option<String>, |
| 56 | } | 61 | } |
| 57 | 62 | ||
| 63 | #[derive(Debug, Eq, PartialEq, Clone, Deserialize)] | ||
| 64 | pub struct DmaChannel { | ||
| 65 | pub dma: String, | ||
| 66 | pub channel: u32, | ||
| 67 | } | ||
| 68 | |||
| 69 | #[derive(Debug, Eq, PartialEq, Clone, Deserialize, Hash)] | ||
| 70 | pub struct PeripheralDmaChannel { | ||
| 71 | pub channel: String, | ||
| 72 | pub request: Option<u32>, | ||
| 73 | } | ||
| 74 | |||
| 58 | struct BlockInfo { | 75 | struct BlockInfo { |
| 59 | /// usart_v1/USART -> usart | 76 | /// usart_v1/USART -> usart |
| 60 | module: String, | 77 | module: String, |
| @@ -110,6 +127,21 @@ fn find_reg_for_field<'c>( | |||
| 110 | }) | 127 | }) |
| 111 | } | 128 | } |
| 112 | 129 | ||
| 130 | fn make_peripheral_counts(out: &mut String, data: &HashMap<String, u8>) { | ||
| 131 | write!(out, | ||
| 132 | "#[macro_export] | ||
| 133 | macro_rules! peripheral_count {{ | ||
| 134 | ").unwrap(); | ||
| 135 | for (name, count) in data { | ||
| 136 | write!(out, | ||
| 137 | "({}) => ({});\n", | ||
| 138 | name, count, | ||
| 139 | ).unwrap(); | ||
| 140 | } | ||
| 141 | write!(out, | ||
| 142 | " }}\n").unwrap(); | ||
| 143 | } | ||
| 144 | |||
| 113 | fn make_table(out: &mut String, name: &str, data: &Vec<Vec<String>>) { | 145 | fn make_table(out: &mut String, name: &str, data: &Vec<Vec<String>>) { |
| 114 | write!( | 146 | write!( |
| 115 | out, | 147 | out, |
| @@ -123,7 +155,7 @@ macro_rules! {} {{ | |||
| 123 | ", | 155 | ", |
| 124 | name, name | 156 | name, name |
| 125 | ) | 157 | ) |
| 126 | .unwrap(); | 158 | .unwrap(); |
| 127 | 159 | ||
| 128 | for row in data { | 160 | for row in data { |
| 129 | write!(out, " __{}_inner!(({}));\n", name, row.join(",")).unwrap(); | 161 | write!(out, " __{}_inner!(({}));\n", name, row.join(",")).unwrap(); |
| @@ -134,7 +166,7 @@ macro_rules! {} {{ | |||
| 134 | " }}; | 166 | " }}; |
| 135 | }}" | 167 | }}" |
| 136 | ) | 168 | ) |
| 137 | .unwrap(); | 169 | .unwrap(); |
| 138 | } | 170 | } |
| 139 | 171 | ||
| 140 | pub struct Options { | 172 | pub struct Options { |
| @@ -220,6 +252,10 @@ pub fn gen(options: Options) { | |||
| 220 | let mut peripherals_table: Vec<Vec<String>> = Vec::new(); | 252 | let mut peripherals_table: Vec<Vec<String>> = Vec::new(); |
| 221 | let mut peripheral_pins_table: Vec<Vec<String>> = Vec::new(); | 253 | let mut peripheral_pins_table: Vec<Vec<String>> = Vec::new(); |
| 222 | let mut peripheral_rcc_table: Vec<Vec<String>> = Vec::new(); | 254 | let mut peripheral_rcc_table: Vec<Vec<String>> = Vec::new(); |
| 255 | let mut dma_channels_table: Vec<Vec<String>> = Vec::new(); | ||
| 256 | let mut dma_requests_table: Vec<Vec<String>> = Vec::new(); | ||
| 257 | let mut peripheral_dma_channels_table: Vec<Vec<String>> = Vec::new(); | ||
| 258 | let mut peripheral_counts: HashMap<String, u8> = HashMap::new(); | ||
| 223 | 259 | ||
| 224 | let dma_base = core | 260 | let dma_base = core |
| 225 | .peripherals | 261 | .peripherals |
| @@ -231,7 +267,23 @@ pub fn gen(options: Options) { | |||
| 231 | let gpio_base = core.peripherals.get(&"GPIOA".to_string()).unwrap().address; | 267 | let gpio_base = core.peripherals.get(&"GPIOA".to_string()).unwrap().address; |
| 232 | let gpio_stride = 0x400; | 268 | let gpio_stride = 0x400; |
| 233 | 269 | ||
| 270 | for (id, channel_info) in &core.dma_channels { | ||
| 271 | let mut row = Vec::new(); | ||
| 272 | row.push(id.clone()); | ||
| 273 | row.push(channel_info.dma.clone()); | ||
| 274 | row.push(channel_info.channel.to_string()); | ||
| 275 | dma_channels_table.push(row); | ||
| 276 | } | ||
| 277 | |||
| 278 | let number_suffix_re = Regex::new("^(.*?)[0-9]*$").unwrap(); | ||
| 279 | |||
| 234 | for (name, p) in &core.peripherals { | 280 | for (name, p) in &core.peripherals { |
| 281 | let captures = number_suffix_re.captures(&name).unwrap(); | ||
| 282 | let root_peri_name = captures.get(1).unwrap().as_str().to_string(); | ||
| 283 | peripheral_counts.insert( | ||
| 284 | root_peri_name.clone(), | ||
| 285 | peripheral_counts.get(&root_peri_name).map_or(1, |v| v + 1), | ||
| 286 | ); | ||
| 235 | let mut ir_peri = ir::Peripheral { | 287 | let mut ir_peri = ir::Peripheral { |
| 236 | name: name.clone(), | 288 | name: name.clone(), |
| 237 | array: None, | 289 | array: None, |
| @@ -257,13 +309,38 @@ pub fn gen(options: Options) { | |||
| 257 | peripheral_pins_table.push(row); | 309 | peripheral_pins_table.push(row); |
| 258 | } | 310 | } |
| 259 | 311 | ||
| 312 | for dma_request in &p.dma_requests { | ||
| 313 | let mut row = Vec::new(); | ||
| 314 | row.push(name.clone()); | ||
| 315 | row.push(dma_request.0.clone()); | ||
| 316 | row.push(dma_request.1.to_string()); | ||
| 317 | dma_requests_table.push(row); | ||
| 318 | } | ||
| 319 | |||
| 320 | for (event, dma_channels) in &p.dma_channels { | ||
| 321 | for channel in dma_channels.iter() { | ||
| 322 | let mut row = Vec::new(); | ||
| 323 | row.push(name.clone()); | ||
| 324 | row.push(bi.module.clone()); | ||
| 325 | row.push(bi.block.clone()); | ||
| 326 | row.push(event.clone()); | ||
| 327 | row.push(channel.channel.clone()); | ||
| 328 | row.push(core.dma_channels[&channel.channel].dma.clone()); | ||
| 329 | row.push(core.dma_channels[&channel.channel].channel.to_string()); | ||
| 330 | if let Some(request) = channel.request { | ||
| 331 | row.push(request.to_string()); | ||
| 332 | } | ||
| 333 | peripheral_dma_channels_table.push(row); | ||
| 334 | } | ||
| 335 | } | ||
| 336 | |||
| 260 | let mut peripheral_row = Vec::new(); | 337 | let mut peripheral_row = Vec::new(); |
| 261 | peripheral_row.push(bi.module.clone()); | 338 | peripheral_row.push(bi.module.clone()); |
| 262 | peripheral_row.push(name.clone()); | 339 | peripheral_row.push(name.clone()); |
| 263 | peripherals_table.push(peripheral_row); | 340 | peripherals_table.push(peripheral_row); |
| 264 | 341 | ||
| 265 | if let Some(old_version) = | 342 | if let Some(old_version) = |
| 266 | peripheral_versions.insert(bi.module.clone(), bi.version.clone()) | 343 | peripheral_versions.insert(bi.module.clone(), bi.version.clone()) |
| 267 | { | 344 | { |
| 268 | if old_version != bi.version { | 345 | if old_version != bi.version { |
| 269 | panic!( | 346 | panic!( |
| @@ -354,13 +431,13 @@ pub fn gen(options: Options) { | |||
| 354 | ]); | 431 | ]); |
| 355 | } | 432 | } |
| 356 | (None, Some(_)) => { | 433 | (None, Some(_)) => { |
| 357 | println!("Unable to find enable register for {}", name) | 434 | print!("Unable to find enable register for {}", name) |
| 358 | } | 435 | } |
| 359 | (Some(_), None) => { | 436 | (Some(_), None) => { |
| 360 | println!("Unable to find reset register for {}", name) | 437 | print!("Unable to find reset register for {}", name) |
| 361 | } | 438 | } |
| 362 | (None, None) => { | 439 | (None, None) => { |
| 363 | println!("Unable to find enable and reset register for {}", name) | 440 | print!("Unable to find enable and reset register for {}", name) |
| 364 | } | 441 | } |
| 365 | } | 442 | } |
| 366 | } | 443 | } |
| @@ -377,7 +454,17 @@ pub fn gen(options: Options) { | |||
| 377 | value: num, | 454 | value: num, |
| 378 | }); | 455 | }); |
| 379 | 456 | ||
| 380 | interrupt_table.push(vec![name.to_ascii_uppercase()]); | 457 | let name = name.to_ascii_uppercase(); |
| 458 | |||
| 459 | interrupt_table.push(vec![name.clone()]); | ||
| 460 | |||
| 461 | if name.starts_with("DMA") || name.contains("_DMA") { | ||
| 462 | interrupt_table.push(vec!["DMA".to_string(), name.clone()]); | ||
| 463 | } | ||
| 464 | |||
| 465 | if name.contains("EXTI") { | ||
| 466 | interrupt_table.push(vec!["EXTI".to_string(), name.clone()]); | ||
| 467 | } | ||
| 381 | } | 468 | } |
| 382 | 469 | ||
| 383 | ir.devices.insert("".to_string(), dev); | 470 | ir.devices.insert("".to_string(), dev); |
| @@ -385,11 +472,8 @@ pub fn gen(options: Options) { | |||
| 385 | let mut extra = format!( | 472 | let mut extra = format!( |
| 386 | "pub fn GPIO(n: usize) -> gpio::Gpio {{ | 473 | "pub fn GPIO(n: usize) -> gpio::Gpio {{ |
| 387 | gpio::Gpio(({} + {}*n) as _) | 474 | gpio::Gpio(({} + {}*n) as _) |
| 388 | }} | ||
| 389 | pub fn DMA(n: usize) -> dma::Dma {{ | ||
| 390 | dma::Dma(({} + {}*n) as _) | ||
| 391 | }}", | 475 | }}", |
| 392 | gpio_base, gpio_stride, dma_base, dma_stride, | 476 | gpio_base, gpio_stride, |
| 393 | ); | 477 | ); |
| 394 | 478 | ||
| 395 | let peripheral_version_table = peripheral_versions | 479 | let peripheral_version_table = peripheral_versions |
| @@ -402,7 +486,11 @@ pub fn gen(options: Options) { | |||
| 402 | make_table(&mut extra, "peripherals", &peripherals_table); | 486 | make_table(&mut extra, "peripherals", &peripherals_table); |
| 403 | make_table(&mut extra, "peripheral_versions", &peripheral_version_table); | 487 | make_table(&mut extra, "peripheral_versions", &peripheral_version_table); |
| 404 | make_table(&mut extra, "peripheral_pins", &peripheral_pins_table); | 488 | make_table(&mut extra, "peripheral_pins", &peripheral_pins_table); |
| 489 | make_table(&mut extra, "peripheral_dma_channels", &peripheral_dma_channels_table); | ||
| 405 | make_table(&mut extra, "peripheral_rcc", &peripheral_rcc_table); | 490 | make_table(&mut extra, "peripheral_rcc", &peripheral_rcc_table); |
| 491 | make_table(&mut extra, "dma_channels", &dma_channels_table); | ||
| 492 | make_table(&mut extra, "dma_requests", &dma_requests_table); | ||
| 493 | make_peripheral_counts(&mut extra, &peripheral_counts); | ||
| 406 | 494 | ||
| 407 | for (module, version) in peripheral_versions { | 495 | for (module, version) in peripheral_versions { |
| 408 | all_peripheral_versions.insert((module.clone(), version.clone())); | 496 | all_peripheral_versions.insert((module.clone(), version.clone())); |
| @@ -411,7 +499,7 @@ pub fn gen(options: Options) { | |||
| 411 | "#[path=\"../../peripherals/{}_{}.rs\"] pub mod {};\n", | 499 | "#[path=\"../../peripherals/{}_{}.rs\"] pub mod {};\n", |
| 412 | module, version, module | 500 | module, version, module |
| 413 | ) | 501 | ) |
| 414 | .unwrap(); | 502 | .unwrap(); |
| 415 | } | 503 | } |
| 416 | 504 | ||
| 417 | // Cleanups! | 505 | // Cleanups! |
| @@ -449,7 +537,7 @@ pub fn gen(options: Options) { | |||
| 449 | "PROVIDE({} = DefaultHandler);\n", | 537 | "PROVIDE({} = DefaultHandler);\n", |
| 450 | name.to_ascii_uppercase() | 538 | name.to_ascii_uppercase() |
| 451 | ) | 539 | ) |
| 452 | .unwrap(); | 540 | .unwrap(); |
| 453 | } | 541 | } |
| 454 | 542 | ||
| 455 | File::create(chip_dir.join("device.x")) | 543 | File::create(chip_dir.join("device.x")) |
| @@ -477,7 +565,7 @@ pub fn gen(options: Options) { | |||
| 477 | transform::NameKind::Enum => format!("vals::{}", s), | 565 | transform::NameKind::Enum => format!("vals::{}", s), |
| 478 | _ => s.to_string(), | 566 | _ => s.to_string(), |
| 479 | }) | 567 | }) |
| 480 | .unwrap(); | 568 | .unwrap(); |
| 481 | 569 | ||
| 482 | transform::sort::Sort {}.run(&mut ir).unwrap(); | 570 | transform::sort::Sort {}.run(&mut ir).unwrap(); |
| 483 | transform::Sanitize {}.run(&mut ir).unwrap(); | 571 | transform::Sanitize {}.run(&mut ir).unwrap(); |
| @@ -488,7 +576,7 @@ pub fn gen(options: Options) { | |||
| 488 | .join("src/peripherals") | 576 | .join("src/peripherals") |
| 489 | .join(format!("{}_{}.rs", module, version)), | 577 | .join(format!("{}_{}.rs", module, version)), |
| 490 | ) | 578 | ) |
| 491 | .unwrap(); | 579 | .unwrap(); |
| 492 | let data = items.to_string().replace("] ", "]\n"); | 580 | let data = items.to_string().replace("] ", "]\n"); |
| 493 | 581 | ||
| 494 | // Remove inner attributes like #![no_std] | 582 | // Remove inner attributes like #![no_std] |
| @@ -511,14 +599,14 @@ pub fn gen(options: Options) { | |||
| 511 | "#[cfg_attr(feature=\"{}_{}\", path = \"chips/{}_{}/pac.rs\")]", | 599 | "#[cfg_attr(feature=\"{}_{}\", path = \"chips/{}_{}/pac.rs\")]", |
| 512 | x, c, x, c | 600 | x, c, x, c |
| 513 | ) | 601 | ) |
| 514 | .unwrap(); | 602 | .unwrap(); |
| 515 | } else { | 603 | } else { |
| 516 | write!( | 604 | write!( |
| 517 | &mut paths, | 605 | &mut paths, |
| 518 | "#[cfg_attr(feature=\"{}\", path = \"chips/{}/pac.rs\")]", | 606 | "#[cfg_attr(feature=\"{}\", path = \"chips/{}/pac.rs\")]", |
| 519 | x, x | 607 | x, x |
| 520 | ) | 608 | ) |
| 521 | .unwrap(); | 609 | .unwrap(); |
| 522 | } | 610 | } |
| 523 | } | 611 | } |
| 524 | let mut contents: Vec<u8> = Vec::new(); | 612 | let mut contents: Vec<u8> = Vec::new(); |
| @@ -541,7 +629,7 @@ pub fn gen(options: Options) { | |||
| 541 | out_dir.join("src").join("common.rs"), | 629 | out_dir.join("src").join("common.rs"), |
| 542 | generate::COMMON_MODULE, | 630 | generate::COMMON_MODULE, |
| 543 | ) | 631 | ) |
| 544 | .unwrap(); | 632 | .unwrap(); |
| 545 | 633 | ||
| 546 | // Generate Cargo.toml | 634 | // Generate Cargo.toml |
| 547 | const BUILDDEP_BEGIN: &[u8] = b"# BEGIN BUILD DEPENDENCIES"; | 635 | const BUILDDEP_BEGIN: &[u8] = b"# BEGIN BUILD DEPENDENCIES"; |
