diff options
| author | Dario Nieuwenhuis <[email protected]> | 2020-12-29 00:05:52 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2020-12-29 00:05:52 +0100 |
| commit | 0750234fbead723138d6d1ebb0635a55c82923e0 (patch) | |
| tree | 72ad5602247511068c7085bdb622f55057a82d29 | |
| parent | b01a88a839c2ac1eec68442f6cddf0c0a887cfa7 (diff) | |
WIP owned irqs
| -rw-r--r-- | embassy-macros/src/lib.rs | 62 | ||||
| -rw-r--r-- | embassy-nrf/src/interrupt.rs | 112 | ||||
| -rw-r--r-- | embassy-nrf/src/lib.rs | 6 | ||||
| -rw-r--r-- | embassy-nrf/src/qspi.rs | 13 | ||||
| -rw-r--r-- | embassy/src/interrupt.rs | 76 | ||||
| -rw-r--r-- | embassy/src/lib.rs | 1 | ||||
| -rw-r--r-- | examples/src/bin/qspi.rs | 5 |
7 files changed, 205 insertions, 70 deletions
diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs index b11fc4ae9..091e08cfa 100644 --- a/embassy-macros/src/lib.rs +++ b/embassy-macros/src/lib.rs | |||
| @@ -98,3 +98,65 @@ pub fn task(args: TokenStream, item: TokenStream) -> TokenStream { | |||
| 98 | }; | 98 | }; |
| 99 | result.into() | 99 | result.into() |
| 100 | } | 100 | } |
| 101 | |||
| 102 | #[proc_macro] | ||
| 103 | pub fn interrupt_declare(item: TokenStream) -> TokenStream { | ||
| 104 | let name = syn::parse_macro_input!(item as syn::Ident); | ||
| 105 | let name = format_ident!("{}", name); | ||
| 106 | let name_interrupt = format_ident!("{}Interrupt", name); | ||
| 107 | let name_handler = format!("__EMBASSY_{}_HANDLER", name); | ||
| 108 | |||
| 109 | let result = quote! { | ||
| 110 | #[allow(non_camel_case_types)] | ||
| 111 | pub struct #name_interrupt(()); | ||
| 112 | unsafe impl OwnedInterrupt for #name_interrupt { | ||
| 113 | type Priority = Priority; | ||
| 114 | fn number(&self) -> u8 { | ||
| 115 | Interrupt::#name as u8 | ||
| 116 | } | ||
| 117 | unsafe fn __handler(&self) -> &'static ::core::sync::atomic::AtomicPtr<u32> { | ||
| 118 | #[export_name = #name_handler] | ||
| 119 | static HANDLER: ::core::sync::atomic::AtomicPtr<u32> = ::core::sync::atomic::AtomicPtr::new(::core::ptr::null_mut()); | ||
| 120 | &HANDLER | ||
| 121 | } | ||
| 122 | } | ||
| 123 | }; | ||
| 124 | result.into() | ||
| 125 | } | ||
| 126 | |||
| 127 | #[proc_macro] | ||
| 128 | pub fn interrupt_take(item: TokenStream) -> TokenStream { | ||
| 129 | let name = syn::parse_macro_input!(item as syn::Ident); | ||
| 130 | let name = format!("{}", name); | ||
| 131 | let name_interrupt = format_ident!("{}Interrupt", name); | ||
| 132 | let name_handler = format!("__EMBASSY_{}_HANDLER", name); | ||
| 133 | |||
| 134 | let result = quote! { | ||
| 135 | { | ||
| 136 | #[allow(non_snake_case)] | ||
| 137 | #[export_name = #name] | ||
| 138 | pub unsafe extern "C" fn trampoline() { | ||
| 139 | extern "C" { | ||
| 140 | #[link_name = #name_handler] | ||
| 141 | static HANDLER: ::core::sync::atomic::AtomicPtr<u32>; | ||
| 142 | } | ||
| 143 | |||
| 144 | let p = HANDLER.load(::core::sync::atomic::Ordering::Acquire); | ||
| 145 | if !p.is_null() { | ||
| 146 | let f: fn() = ::core::mem::transmute(p); | ||
| 147 | f() | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | static TAKEN: ::core::sync::atomic::AtomicBool = ::core::sync::atomic::AtomicBool::new(false); | ||
| 152 | |||
| 153 | if TAKEN.compare_and_swap(false, true, ::core::sync::atomic::Ordering::AcqRel) { | ||
| 154 | panic!("IRQ Already taken"); | ||
| 155 | } | ||
| 156 | |||
| 157 | let irq: interrupt::#name_interrupt = unsafe { ::core::mem::transmute(()) }; | ||
| 158 | irq | ||
| 159 | } | ||
| 160 | }; | ||
| 161 | result.into() | ||
| 162 | } | ||
diff --git a/embassy-nrf/src/interrupt.rs b/embassy-nrf/src/interrupt.rs index 17fc9ab34..3afded553 100644 --- a/embassy-nrf/src/interrupt.rs +++ b/embassy-nrf/src/interrupt.rs | |||
| @@ -5,12 +5,13 @@ | |||
| 5 | 5 | ||
| 6 | use core::sync::atomic::{compiler_fence, Ordering}; | 6 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 7 | 7 | ||
| 8 | use crate::pac::{NVIC, NVIC_PRIO_BITS}; | 8 | use crate::pac::NVIC_PRIO_BITS; |
| 9 | 9 | ||
| 10 | // Re-exports | 10 | // Re-exports |
| 11 | pub use crate::pac::Interrupt; | 11 | pub use crate::pac::Interrupt; |
| 12 | pub use crate::pac::Interrupt::*; // needed for cortex-m-rt #[interrupt] | 12 | pub use crate::pac::Interrupt::*; // needed for cortex-m-rt #[interrupt] |
| 13 | pub use cortex_m::interrupt::{CriticalSection, Mutex}; | 13 | pub use cortex_m::interrupt::{CriticalSection, Mutex}; |
| 14 | pub use embassy::interrupt::{declare, take, OwnedInterrupt}; | ||
| 14 | 15 | ||
| 15 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | 16 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] |
| 16 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 17 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -26,14 +27,8 @@ pub enum Priority { | |||
| 26 | Level7 = 7, | 27 | Level7 = 7, |
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | impl Priority { | 30 | impl From<u8> for Priority { |
| 30 | #[inline] | 31 | fn from(priority: u8) -> Self { |
| 31 | fn to_nvic(self) -> u8 { | ||
| 32 | (self as u8) << (8 - NVIC_PRIO_BITS) | ||
| 33 | } | ||
| 34 | |||
| 35 | #[inline] | ||
| 36 | fn from_nvic(priority: u8) -> Self { | ||
| 37 | match priority >> (8 - NVIC_PRIO_BITS) { | 32 | match priority >> (8 - NVIC_PRIO_BITS) { |
| 38 | 0 => Self::Level0, | 33 | 0 => Self::Level0, |
| 39 | 1 => Self::Level1, | 34 | 1 => Self::Level1, |
| @@ -48,6 +43,12 @@ impl Priority { | |||
| 48 | } | 43 | } |
| 49 | } | 44 | } |
| 50 | 45 | ||
| 46 | impl From<Priority> for u8 { | ||
| 47 | fn from(p: Priority) -> Self { | ||
| 48 | (p as u8) << (8 - NVIC_PRIO_BITS) | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 51 | #[inline] | 52 | #[inline] |
| 52 | pub fn free<F, R>(f: F) -> R | 53 | pub fn free<F, R>(f: F) -> R |
| 53 | where | 54 | where |
| @@ -77,53 +78,46 @@ where | |||
| 77 | } | 78 | } |
| 78 | } | 79 | } |
| 79 | 80 | ||
| 80 | #[inline] | 81 | declare!(POWER_CLOCK); |
| 81 | pub fn enable(irq: Interrupt) { | 82 | declare!(RADIO); |
| 82 | unsafe { | 83 | declare!(UARTE0_UART0); |
| 83 | NVIC::unmask(irq); | 84 | declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); |
| 84 | } | 85 | declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); |
| 85 | } | 86 | declare!(NFCT); |
| 86 | 87 | declare!(GPIOTE); | |
| 87 | #[inline] | 88 | declare!(SAADC); |
| 88 | pub fn disable(irq: Interrupt) { | 89 | declare!(TIMER0); |
| 89 | NVIC::mask(irq); | 90 | declare!(TIMER1); |
| 90 | } | 91 | declare!(TIMER2); |
| 91 | 92 | declare!(RTC0); | |
| 92 | #[inline] | 93 | declare!(TEMP); |
| 93 | pub fn is_active(irq: Interrupt) -> bool { | 94 | declare!(RNG); |
| 94 | NVIC::is_active(irq) | 95 | declare!(ECB); |
| 95 | } | 96 | declare!(CCM_AAR); |
| 96 | 97 | declare!(WDT); | |
| 97 | #[inline] | 98 | declare!(RTC1); |
| 98 | pub fn is_enabled(irq: Interrupt) -> bool { | 99 | declare!(QDEC); |
| 99 | NVIC::is_enabled(irq) | 100 | declare!(COMP_LPCOMP); |
| 100 | } | 101 | declare!(SWI0_EGU0); |
| 101 | 102 | declare!(SWI1_EGU1); | |
| 102 | #[inline] | 103 | declare!(SWI2_EGU2); |
| 103 | pub fn is_pending(irq: Interrupt) -> bool { | 104 | declare!(SWI3_EGU3); |
| 104 | NVIC::is_pending(irq) | 105 | declare!(SWI4_EGU4); |
| 105 | } | 106 | declare!(SWI5_EGU5); |
| 106 | 107 | declare!(TIMER3); | |
| 107 | #[inline] | 108 | declare!(TIMER4); |
| 108 | pub fn pend(irq: Interrupt) { | 109 | declare!(PWM0); |
| 109 | NVIC::pend(irq) | 110 | declare!(PDM); |
| 110 | } | 111 | declare!(MWU); |
| 111 | 112 | declare!(PWM1); | |
| 112 | #[inline] | 113 | declare!(PWM2); |
| 113 | pub fn unpend(irq: Interrupt) { | 114 | declare!(SPIM2_SPIS2_SPI2); |
| 114 | NVIC::unpend(irq) | 115 | declare!(RTC2); |
| 115 | } | 116 | declare!(I2S); |
| 116 | 117 | declare!(FPU); | |
| 117 | #[inline] | 118 | declare!(USBD); |
| 118 | pub fn get_priority(irq: Interrupt) -> Priority { | 119 | declare!(UARTE1); |
| 119 | Priority::from_nvic(NVIC::get_priority(irq)) | 120 | declare!(QSPI); |
| 120 | } | 121 | declare!(CRYPTOCELL); |
| 121 | 122 | declare!(PWM3); | |
| 122 | #[inline] | 123 | declare!(SPIM3); |
| 123 | pub fn set_priority(irq: Interrupt, prio: Priority) { | ||
| 124 | unsafe { | ||
| 125 | cortex_m::peripheral::Peripherals::steal() | ||
| 126 | .NVIC | ||
| 127 | .set_priority(irq, prio.to_nvic()) | ||
| 128 | } | ||
| 129 | } | ||
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 0ca328138..ccfcc0681 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs | |||
| @@ -51,11 +51,11 @@ pub use nrf52840_hal as hal; | |||
| 51 | // This mod MUST go first, so that the others see its macros. | 51 | // This mod MUST go first, so that the others see its macros. |
| 52 | pub(crate) mod fmt; | 52 | pub(crate) mod fmt; |
| 53 | 53 | ||
| 54 | pub mod buffered_uarte; | 54 | //pub mod buffered_uarte; |
| 55 | pub mod gpiote; | 55 | //pub mod gpiote; |
| 56 | pub mod interrupt; | 56 | pub mod interrupt; |
| 57 | #[cfg(feature = "52840")] | 57 | #[cfg(feature = "52840")] |
| 58 | pub mod qspi; | 58 | pub mod qspi; |
| 59 | pub mod rtc; | 59 | //pub mod rtc; |
| 60 | 60 | ||
| 61 | pub use cortex_m_rt::interrupt; | 61 | pub use cortex_m_rt::interrupt; |
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index 79fc7029c..8833afbdc 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs | |||
| @@ -2,6 +2,7 @@ use crate::fmt::{assert, assert_eq, panic, *}; | |||
| 2 | use core::future::Future; | 2 | use core::future::Future; |
| 3 | 3 | ||
| 4 | use crate::hal::gpio::{Output, Pin as GpioPin, Port as GpioPort, PushPull}; | 4 | use crate::hal::gpio::{Output, Pin as GpioPin, Port as GpioPort, PushPull}; |
| 5 | use crate::interrupt::{OwnedInterrupt, QSPIInterrupt}; | ||
| 5 | use crate::pac::{Interrupt, QSPI}; | 6 | use crate::pac::{Interrupt, QSPI}; |
| 6 | 7 | ||
| 7 | pub use crate::pac::qspi::ifconfig0::ADDRMODE_A as AddressMode; | 8 | pub use crate::pac::qspi::ifconfig0::ADDRMODE_A as AddressMode; |
| @@ -59,7 +60,7 @@ fn port_bit(port: GpioPort) -> bool { | |||
| 59 | } | 60 | } |
| 60 | 61 | ||
| 61 | impl Qspi { | 62 | impl Qspi { |
| 62 | pub fn new(qspi: QSPI, config: Config) -> Self { | 63 | pub fn new(qspi: QSPI, irq: QSPIInterrupt, config: Config) -> Self { |
| 63 | qspi.psel.sck.write(|w| { | 64 | qspi.psel.sck.write(|w| { |
| 64 | let pin = &config.pins.sck; | 65 | let pin = &config.pins.sck; |
| 65 | let w = unsafe { w.pin().bits(pin.pin()) }; | 66 | let w = unsafe { w.pin().bits(pin.pin()) }; |
| @@ -146,9 +147,10 @@ impl Qspi { | |||
| 146 | // Enable READY interrupt | 147 | // Enable READY interrupt |
| 147 | SIGNAL.reset(); | 148 | SIGNAL.reset(); |
| 148 | qspi.intenset.write(|w| w.ready().set()); | 149 | qspi.intenset.write(|w| w.ready().set()); |
| 149 | interrupt::set_priority(Interrupt::QSPI, interrupt::Priority::Level7); | 150 | |
| 150 | interrupt::unpend(Interrupt::QSPI); | 151 | irq.set_handler(irq_handler); |
| 151 | interrupt::enable(Interrupt::QSPI); | 152 | irq.unpend(); |
| 153 | irq.enable(); | ||
| 152 | 154 | ||
| 153 | Self { inner: qspi } | 155 | Self { inner: qspi } |
| 154 | } | 156 | } |
| @@ -347,8 +349,7 @@ impl Flash for Qspi { | |||
| 347 | 349 | ||
| 348 | static SIGNAL: Signal<()> = Signal::new(); | 350 | static SIGNAL: Signal<()> = Signal::new(); |
| 349 | 351 | ||
| 350 | #[interrupt] | 352 | unsafe fn irq_handler() { |
| 351 | unsafe fn QSPI() { | ||
| 352 | let p = crate::pac::Peripherals::steal().QSPI; | 353 | let p = crate::pac::Peripherals::steal().QSPI; |
| 353 | if p.events_ready.read().events_ready().bit_is_set() { | 354 | if p.events_ready.read().events_ready().bit_is_set() { |
| 354 | p.events_ready.reset(); | 355 | p.events_ready.reset(); |
diff --git a/embassy/src/interrupt.rs b/embassy/src/interrupt.rs new file mode 100644 index 000000000..fee52b326 --- /dev/null +++ b/embassy/src/interrupt.rs | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | use core::mem; | ||
| 2 | use core::ptr; | ||
| 3 | use core::sync::atomic::{AtomicBool, AtomicPtr, Ordering}; | ||
| 4 | use cortex_m::peripheral::NVIC; | ||
| 5 | |||
| 6 | pub use embassy_macros::interrupt_declare as declare; | ||
| 7 | pub use embassy_macros::interrupt_take as take; | ||
| 8 | |||
| 9 | struct NrWrap(u8); | ||
| 10 | unsafe impl cortex_m::interrupt::Nr for NrWrap { | ||
| 11 | fn nr(&self) -> u8 { | ||
| 12 | self.0 | ||
| 13 | } | ||
| 14 | } | ||
| 15 | |||
| 16 | pub unsafe trait OwnedInterrupt { | ||
| 17 | type Priority: From<u8> + Into<u8> + Copy; | ||
| 18 | fn number(&self) -> u8; | ||
| 19 | #[doc(hidden)] | ||
| 20 | unsafe fn __handler(&self) -> &'static AtomicPtr<u32>; | ||
| 21 | |||
| 22 | fn set_handler(&self, handler: unsafe fn()) { | ||
| 23 | unsafe { self.__handler() }.store(handler as *mut u32, Ordering::Release); | ||
| 24 | } | ||
| 25 | |||
| 26 | #[inline] | ||
| 27 | fn enable(&self) { | ||
| 28 | unsafe { | ||
| 29 | NVIC::unmask(NrWrap(self.number())); | ||
| 30 | } | ||
| 31 | } | ||
| 32 | |||
| 33 | #[inline] | ||
| 34 | fn disable(&self) { | ||
| 35 | NVIC::mask(NrWrap(self.number())); | ||
| 36 | } | ||
| 37 | |||
| 38 | #[inline] | ||
| 39 | fn is_active(&self) -> bool { | ||
| 40 | NVIC::is_active(NrWrap(self.number())) | ||
| 41 | } | ||
| 42 | |||
| 43 | #[inline] | ||
| 44 | fn is_enabled(&self) -> bool { | ||
| 45 | NVIC::is_enabled(NrWrap(self.number())) | ||
| 46 | } | ||
| 47 | |||
| 48 | #[inline] | ||
| 49 | fn is_pending(&self) -> bool { | ||
| 50 | NVIC::is_pending(NrWrap(self.number())) | ||
| 51 | } | ||
| 52 | |||
| 53 | #[inline] | ||
| 54 | fn pend(&self) { | ||
| 55 | NVIC::pend(NrWrap(self.number())) | ||
| 56 | } | ||
| 57 | |||
| 58 | #[inline] | ||
| 59 | fn unpend(&self) { | ||
| 60 | NVIC::unpend(NrWrap(self.number())) | ||
| 61 | } | ||
| 62 | |||
| 63 | #[inline] | ||
| 64 | fn get_priority(&self) -> Self::Priority { | ||
| 65 | Self::Priority::from(NVIC::get_priority(NrWrap(self.number()))) | ||
| 66 | } | ||
| 67 | |||
| 68 | #[inline] | ||
| 69 | fn set_priority(&self, prio: Self::Priority) { | ||
| 70 | unsafe { | ||
| 71 | cortex_m::peripheral::Peripherals::steal() | ||
| 72 | .NVIC | ||
| 73 | .set_priority(NrWrap(self.number()), prio.into()) | ||
| 74 | } | ||
| 75 | } | ||
| 76 | } | ||
diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs index 49ba8eea8..bc06ebd13 100644 --- a/embassy/src/lib.rs +++ b/embassy/src/lib.rs | |||
| @@ -9,6 +9,7 @@ pub(crate) mod fmt; | |||
| 9 | 9 | ||
| 10 | pub mod executor; | 10 | pub mod executor; |
| 11 | pub mod flash; | 11 | pub mod flash; |
| 12 | pub mod interrupt; | ||
| 12 | pub mod io; | 13 | pub mod io; |
| 13 | pub mod rand; | 14 | pub mod rand; |
| 14 | pub mod time; | 15 | pub mod time; |
diff --git a/examples/src/bin/qspi.rs b/examples/src/bin/qspi.rs index 644018e2d..a7d47f79c 100644 --- a/examples/src/bin/qspi.rs +++ b/examples/src/bin/qspi.rs | |||
| @@ -13,7 +13,7 @@ use nrf52840_hal::gpio; | |||
| 13 | use embassy::executor::{task, Executor}; | 13 | use embassy::executor::{task, Executor}; |
| 14 | use embassy::flash::Flash; | 14 | use embassy::flash::Flash; |
| 15 | use embassy::util::Forever; | 15 | use embassy::util::Forever; |
| 16 | use embassy_nrf::qspi; | 16 | use embassy_nrf::{interrupt, qspi}; |
| 17 | 17 | ||
| 18 | const PAGE_SIZE: usize = 4096; | 18 | const PAGE_SIZE: usize = 4096; |
| 19 | 19 | ||
| @@ -68,7 +68,8 @@ async fn run() { | |||
| 68 | deep_power_down: None, | 68 | deep_power_down: None, |
| 69 | }; | 69 | }; |
| 70 | 70 | ||
| 71 | let mut q = qspi::Qspi::new(p.QSPI, config); | 71 | let irq = interrupt::take!(QSPI); |
| 72 | let mut q = qspi::Qspi::new(p.QSPI, irq, config); | ||
| 72 | 73 | ||
| 73 | let mut id = [1; 3]; | 74 | let mut id = [1; 3]; |
| 74 | q.custom_instruction(0x9F, &[], &mut id).await.unwrap(); | 75 | q.custom_instruction(0x9F, &[], &mut id).await.unwrap(); |
