aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2020-12-29 00:05:52 +0100
committerDario Nieuwenhuis <[email protected]>2020-12-29 00:05:52 +0100
commit0750234fbead723138d6d1ebb0635a55c82923e0 (patch)
tree72ad5602247511068c7085bdb622f55057a82d29
parentb01a88a839c2ac1eec68442f6cddf0c0a887cfa7 (diff)
WIP owned irqs
-rw-r--r--embassy-macros/src/lib.rs62
-rw-r--r--embassy-nrf/src/interrupt.rs112
-rw-r--r--embassy-nrf/src/lib.rs6
-rw-r--r--embassy-nrf/src/qspi.rs13
-rw-r--r--embassy/src/interrupt.rs76
-rw-r--r--embassy/src/lib.rs1
-rw-r--r--examples/src/bin/qspi.rs5
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]
103pub 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]
128pub 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
6use core::sync::atomic::{compiler_fence, Ordering}; 6use core::sync::atomic::{compiler_fence, Ordering};
7 7
8use crate::pac::{NVIC, NVIC_PRIO_BITS}; 8use crate::pac::NVIC_PRIO_BITS;
9 9
10// Re-exports 10// Re-exports
11pub use crate::pac::Interrupt; 11pub use crate::pac::Interrupt;
12pub use crate::pac::Interrupt::*; // needed for cortex-m-rt #[interrupt] 12pub use crate::pac::Interrupt::*; // needed for cortex-m-rt #[interrupt]
13pub use cortex_m::interrupt::{CriticalSection, Mutex}; 13pub use cortex_m::interrupt::{CriticalSection, Mutex};
14pub 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
29impl Priority { 30impl 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
46impl 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]
52pub fn free<F, R>(f: F) -> R 53pub fn free<F, R>(f: F) -> R
53where 54where
@@ -77,53 +78,46 @@ where
77 } 78 }
78} 79}
79 80
80#[inline] 81declare!(POWER_CLOCK);
81pub fn enable(irq: Interrupt) { 82declare!(RADIO);
82 unsafe { 83declare!(UARTE0_UART0);
83 NVIC::unmask(irq); 84declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);
84 } 85declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1);
85} 86declare!(NFCT);
86 87declare!(GPIOTE);
87#[inline] 88declare!(SAADC);
88pub fn disable(irq: Interrupt) { 89declare!(TIMER0);
89 NVIC::mask(irq); 90declare!(TIMER1);
90} 91declare!(TIMER2);
91 92declare!(RTC0);
92#[inline] 93declare!(TEMP);
93pub fn is_active(irq: Interrupt) -> bool { 94declare!(RNG);
94 NVIC::is_active(irq) 95declare!(ECB);
95} 96declare!(CCM_AAR);
96 97declare!(WDT);
97#[inline] 98declare!(RTC1);
98pub fn is_enabled(irq: Interrupt) -> bool { 99declare!(QDEC);
99 NVIC::is_enabled(irq) 100declare!(COMP_LPCOMP);
100} 101declare!(SWI0_EGU0);
101 102declare!(SWI1_EGU1);
102#[inline] 103declare!(SWI2_EGU2);
103pub fn is_pending(irq: Interrupt) -> bool { 104declare!(SWI3_EGU3);
104 NVIC::is_pending(irq) 105declare!(SWI4_EGU4);
105} 106declare!(SWI5_EGU5);
106 107declare!(TIMER3);
107#[inline] 108declare!(TIMER4);
108pub fn pend(irq: Interrupt) { 109declare!(PWM0);
109 NVIC::pend(irq) 110declare!(PDM);
110} 111declare!(MWU);
111 112declare!(PWM1);
112#[inline] 113declare!(PWM2);
113pub fn unpend(irq: Interrupt) { 114declare!(SPIM2_SPIS2_SPI2);
114 NVIC::unpend(irq) 115declare!(RTC2);
115} 116declare!(I2S);
116 117declare!(FPU);
117#[inline] 118declare!(USBD);
118pub fn get_priority(irq: Interrupt) -> Priority { 119declare!(UARTE1);
119 Priority::from_nvic(NVIC::get_priority(irq)) 120declare!(QSPI);
120} 121declare!(CRYPTOCELL);
121 122declare!(PWM3);
122#[inline] 123declare!(SPIM3);
123pub 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.
52pub(crate) mod fmt; 52pub(crate) mod fmt;
53 53
54pub mod buffered_uarte; 54//pub mod buffered_uarte;
55pub mod gpiote; 55//pub mod gpiote;
56pub mod interrupt; 56pub mod interrupt;
57#[cfg(feature = "52840")] 57#[cfg(feature = "52840")]
58pub mod qspi; 58pub mod qspi;
59pub mod rtc; 59//pub mod rtc;
60 60
61pub use cortex_m_rt::interrupt; 61pub 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, *};
2use core::future::Future; 2use core::future::Future;
3 3
4use crate::hal::gpio::{Output, Pin as GpioPin, Port as GpioPort, PushPull}; 4use crate::hal::gpio::{Output, Pin as GpioPin, Port as GpioPort, PushPull};
5use crate::interrupt::{OwnedInterrupt, QSPIInterrupt};
5use crate::pac::{Interrupt, QSPI}; 6use crate::pac::{Interrupt, QSPI};
6 7
7pub use crate::pac::qspi::ifconfig0::ADDRMODE_A as AddressMode; 8pub use crate::pac::qspi::ifconfig0::ADDRMODE_A as AddressMode;
@@ -59,7 +60,7 @@ fn port_bit(port: GpioPort) -> bool {
59} 60}
60 61
61impl Qspi { 62impl 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
348static SIGNAL: Signal<()> = Signal::new(); 350static SIGNAL: Signal<()> = Signal::new();
349 351
350#[interrupt] 352unsafe fn irq_handler() {
351unsafe 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 @@
1use core::mem;
2use core::ptr;
3use core::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
4use cortex_m::peripheral::NVIC;
5
6pub use embassy_macros::interrupt_declare as declare;
7pub use embassy_macros::interrupt_take as take;
8
9struct NrWrap(u8);
10unsafe impl cortex_m::interrupt::Nr for NrWrap {
11 fn nr(&self) -> u8 {
12 self.0
13 }
14}
15
16pub 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
10pub mod executor; 10pub mod executor;
11pub mod flash; 11pub mod flash;
12pub mod interrupt;
12pub mod io; 13pub mod io;
13pub mod rand; 14pub mod rand;
14pub mod time; 15pub 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;
13use embassy::executor::{task, Executor}; 13use embassy::executor::{task, Executor};
14use embassy::flash::Flash; 14use embassy::flash::Flash;
15use embassy::util::Forever; 15use embassy::util::Forever;
16use embassy_nrf::qspi; 16use embassy_nrf::{interrupt, qspi};
17 17
18const PAGE_SIZE: usize = 4096; 18const 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();