diff options
Diffstat (limited to 'embassy-mspm0/src/lib.rs')
| -rw-r--r-- | embassy-mspm0/src/lib.rs | 115 |
1 files changed, 112 insertions, 3 deletions
diff --git a/embassy-mspm0/src/lib.rs b/embassy-mspm0/src/lib.rs index 7ff60e946..bb8d91403 100644 --- a/embassy-mspm0/src/lib.rs +++ b/embassy-mspm0/src/lib.rs | |||
| @@ -13,6 +13,7 @@ pub(crate) mod fmt; | |||
| 13 | // This must be declared early as well for | 13 | // This must be declared early as well for |
| 14 | mod macros; | 14 | mod macros; |
| 15 | 15 | ||
| 16 | pub mod dma; | ||
| 16 | pub mod gpio; | 17 | pub mod gpio; |
| 17 | pub mod timer; | 18 | pub mod timer; |
| 18 | pub mod uart; | 19 | pub mod uart; |
| @@ -59,22 +60,106 @@ pub(crate) use mspm0_metapac as pac; | |||
| 59 | 60 | ||
| 60 | pub use crate::_generated::interrupt; | 61 | pub use crate::_generated::interrupt; |
| 61 | 62 | ||
| 63 | /// Macro to bind interrupts to handlers. | ||
| 64 | /// | ||
| 65 | /// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) | ||
| 66 | /// and implements the right [`Binding`]s for it. You can pass this struct to drivers to | ||
| 67 | /// prove at compile-time that the right interrupts have been bound. | ||
| 68 | /// | ||
| 69 | /// Example of how to bind one interrupt: | ||
| 70 | /// | ||
| 71 | /// ```rust,ignore | ||
| 72 | /// use embassy_nrf::{bind_interrupts, spim, peripherals}; | ||
| 73 | /// | ||
| 74 | /// bind_interrupts!( | ||
| 75 | /// /// Binds the SPIM3 interrupt. | ||
| 76 | /// struct Irqs { | ||
| 77 | /// SPIM3 => spim::InterruptHandler<peripherals::SPI3>; | ||
| 78 | /// } | ||
| 79 | /// ); | ||
| 80 | /// ``` | ||
| 81 | /// | ||
| 82 | /// Example of how to bind multiple interrupts in a single macro invocation: | ||
| 83 | /// | ||
| 84 | /// ```rust,ignore | ||
| 85 | /// use embassy_nrf::{bind_interrupts, spim, twim, peripherals}; | ||
| 86 | /// | ||
| 87 | /// bind_interrupts!(struct Irqs { | ||
| 88 | /// SPIM3 => spim::InterruptHandler<peripherals::SPI3>; | ||
| 89 | /// TWISPI0 => twim::InterruptHandler<peripherals::TWISPI0>; | ||
| 90 | /// }); | ||
| 91 | /// ``` | ||
| 92 | |||
| 93 | // developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`. | ||
| 94 | #[macro_export] | ||
| 95 | macro_rules! bind_interrupts { | ||
| 96 | ($(#[$attr:meta])* $vis:vis struct $name:ident { | ||
| 97 | $( | ||
| 98 | $(#[cfg($cond_irq:meta)])? | ||
| 99 | $irq:ident => $( | ||
| 100 | $(#[cfg($cond_handler:meta)])? | ||
| 101 | $handler:ty | ||
| 102 | ),*; | ||
| 103 | )* | ||
| 104 | }) => { | ||
| 105 | #[derive(Copy, Clone)] | ||
| 106 | $(#[$attr])* | ||
| 107 | $vis struct $name; | ||
| 108 | |||
| 109 | $( | ||
| 110 | #[allow(non_snake_case)] | ||
| 111 | #[no_mangle] | ||
| 112 | $(#[cfg($cond_irq)])? | ||
| 113 | unsafe extern "C" fn $irq() { | ||
| 114 | $( | ||
| 115 | $(#[cfg($cond_handler)])? | ||
| 116 | <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt(); | ||
| 117 | |||
| 118 | )* | ||
| 119 | } | ||
| 120 | |||
| 121 | $(#[cfg($cond_irq)])? | ||
| 122 | $crate::bind_interrupts!(@inner | ||
| 123 | $( | ||
| 124 | $(#[cfg($cond_handler)])? | ||
| 125 | unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {} | ||
| 126 | )* | ||
| 127 | ); | ||
| 128 | )* | ||
| 129 | }; | ||
| 130 | (@inner $($t:tt)*) => { | ||
| 131 | $($t)* | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 62 | /// `embassy-mspm0` global configuration. | 135 | /// `embassy-mspm0` global configuration. |
| 63 | #[non_exhaustive] | 136 | #[non_exhaustive] |
| 64 | #[derive(Clone, Copy)] | 137 | #[derive(Clone, Copy)] |
| 65 | pub struct Config { | 138 | pub struct Config { |
| 66 | // TODO | 139 | // TODO: OSC configuration. |
| 140 | /// The size of DMA block transfer burst. | ||
| 141 | /// | ||
| 142 | /// If this is set to a value | ||
| 143 | pub dma_burst_size: dma::BurstSize, | ||
| 144 | |||
| 145 | /// Whether the DMA channels are used in a fixed priority or a round robin fashion. | ||
| 146 | /// | ||
| 147 | /// If [`false`], the DMA priorities are fixed. | ||
| 148 | /// | ||
| 149 | /// If [`true`], after a channel finishes a transfer it becomes the lowest priority. | ||
| 150 | pub dma_round_robin: bool, | ||
| 67 | } | 151 | } |
| 68 | 152 | ||
| 69 | impl Default for Config { | 153 | impl Default for Config { |
| 70 | fn default() -> Self { | 154 | fn default() -> Self { |
| 71 | Self { | 155 | Self { |
| 72 | // TODO | 156 | dma_burst_size: dma::BurstSize::Complete, |
| 157 | dma_round_robin: false, | ||
| 73 | } | 158 | } |
| 74 | } | 159 | } |
| 75 | } | 160 | } |
| 76 | 161 | ||
| 77 | pub fn init(_config: Config) -> Peripherals { | 162 | pub fn init(config: Config) -> Peripherals { |
| 78 | critical_section::with(|cs| { | 163 | critical_section::with(|cs| { |
| 79 | let peripherals = Peripherals::take_with_cs(cs); | 164 | let peripherals = Peripherals::take_with_cs(cs); |
| 80 | 165 | ||
| @@ -112,9 +197,33 @@ pub fn init(_config: Config) -> Peripherals { | |||
| 112 | crate::interrupt::typelevel::GPIOA::enable(); | 197 | crate::interrupt::typelevel::GPIOA::enable(); |
| 113 | } | 198 | } |
| 114 | 199 | ||
| 200 | // SAFETY: Peripherals::take_with_cs will only be run once or panic. | ||
| 201 | unsafe { dma::init(cs, config.dma_burst_size, config.dma_round_robin) }; | ||
| 202 | |||
| 115 | #[cfg(feature = "_time-driver")] | 203 | #[cfg(feature = "_time-driver")] |
| 116 | time_driver::init(cs); | 204 | time_driver::init(cs); |
| 117 | 205 | ||
| 118 | peripherals | 206 | peripherals |
| 119 | }) | 207 | }) |
| 120 | } | 208 | } |
| 209 | |||
| 210 | pub(crate) mod sealed { | ||
| 211 | #[allow(dead_code)] | ||
| 212 | pub trait Sealed {} | ||
| 213 | } | ||
| 214 | |||
| 215 | struct BitIter(u32); | ||
| 216 | |||
| 217 | impl Iterator for BitIter { | ||
| 218 | type Item = u32; | ||
| 219 | |||
| 220 | fn next(&mut self) -> Option<Self::Item> { | ||
| 221 | match self.0.trailing_zeros() { | ||
| 222 | 32 => None, | ||
| 223 | b => { | ||
| 224 | self.0 &= !(1 << b); | ||
| 225 | Some(b) | ||
| 226 | } | ||
| 227 | } | ||
| 228 | } | ||
| 229 | } | ||
