|
1 | 1 | #![no_std] |
2 | 2 | #![no_main] |
3 | 3 |
|
4 | | -use embedded_hal::digital::v2::InputPin; |
5 | | -use { |
6 | | - core::{ |
7 | | - panic::PanicInfo, |
8 | | - sync::atomic::{compiler_fence, Ordering}, |
9 | | - }, |
10 | | - hal::{ |
11 | | - gpio::{Input, Level, Pin, PullUp}, |
12 | | - gpiote::*, |
13 | | - ppi::{self, ConfigurablePpi, Ppi}, |
14 | | - }, |
15 | | - nrf52840_hal as hal, |
16 | | - rtic::cyccnt::U32Ext, |
17 | | - rtt_target::{rprintln, rtt_init_print}, |
18 | | -}; |
19 | | - |
20 | | -#[rtic::app(device = crate::hal::pac, peripherals = true, monotonic = rtic::cyccnt::CYCCNT)] |
21 | | -const APP: () = { |
22 | | - struct Resources { |
| 4 | +use {core::panic::PanicInfo, nrf52840_hal as hal, rtt_target::rprintln}; |
| 5 | + |
| 6 | +#[rtic::app(device = crate::hal::pac, peripherals = true, dispatchers = [SWI0_EGU0])] |
| 7 | +mod app { |
| 8 | + use embedded_hal::digital::v2::InputPin; |
| 9 | + use systick_monotonic::*; |
| 10 | + use { |
| 11 | + hal::{ |
| 12 | + gpio::{Input, Level, Pin, PullUp}, |
| 13 | + gpiote::*, |
| 14 | + ppi::{self, ConfigurablePpi, Ppi}, |
| 15 | + }, |
| 16 | + nrf52840_hal as hal, |
| 17 | + rtt_target::{rprintln, rtt_init_print}, |
| 18 | + }; |
| 19 | + |
| 20 | + #[monotonic(binds = SysTick, default = true)] |
| 21 | + type Timer = Systick<1_000_000>; |
| 22 | + |
| 23 | + #[shared] |
| 24 | + struct Shared { |
23 | 25 | gpiote: Gpiote, |
| 26 | + } |
| 27 | + |
| 28 | + #[local] |
| 29 | + struct Local { |
24 | 30 | btn1: Pin<Input<PullUp>>, |
25 | 31 | btn3: Pin<Input<PullUp>>, |
26 | 32 | btn4: Pin<Input<PullUp>>, |
27 | 33 | } |
28 | 34 |
|
29 | 35 | #[init] |
30 | | - fn init(mut ctx: init::Context) -> init::LateResources { |
| 36 | + fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) { |
31 | 37 | let _clocks = hal::clocks::Clocks::new(ctx.device.CLOCK).enable_ext_hfosc(); |
32 | 38 | rtt_init_print!(); |
33 | 39 | let p0 = hal::gpio::p0::Parts::new(ctx.device.P0); |
@@ -65,75 +71,63 @@ const APP: () = { |
65 | 71 | ppi0.set_event_endpoint(gpiote.channel2().event()); |
66 | 72 | ppi0.enable(); |
67 | 73 |
|
68 | | - // Enable the monotonic timer (CYCCNT) |
69 | | - ctx.core.DCB.enable_trace(); |
70 | | - ctx.core.DWT.enable_cycle_counter(); |
| 74 | + let mono = Systick::new(ctx.core.SYST, 64_000_000); |
71 | 75 |
|
72 | 76 | rprintln!("Press a button"); |
73 | 77 |
|
74 | | - init::LateResources { |
75 | | - gpiote, |
76 | | - btn1, |
77 | | - btn3, |
78 | | - btn4, |
79 | | - } |
80 | | - } |
81 | | - |
82 | | - #[idle] |
83 | | - fn idle(_: idle::Context) -> ! { |
84 | | - loop { |
85 | | - cortex_m::asm::wfi(); |
86 | | - } |
| 78 | + ( |
| 79 | + Shared { gpiote }, |
| 80 | + Local { btn1, btn3, btn4 }, |
| 81 | + init::Monotonics(mono), |
| 82 | + ) |
87 | 83 | } |
88 | 84 |
|
89 | | - #[task(binds = GPIOTE, resources = [gpiote], schedule = [debounce])] |
90 | | - fn on_gpiote(ctx: on_gpiote::Context) { |
91 | | - if ctx.resources.gpiote.channel0().is_event_triggered() { |
92 | | - rprintln!("Interrupt from channel 0 event"); |
93 | | - } |
94 | | - if ctx.resources.gpiote.port().is_event_triggered() { |
95 | | - rprintln!("Interrupt from port event"); |
96 | | - } |
97 | | - // Reset all events |
98 | | - ctx.resources.gpiote.reset_events(); |
99 | | - // Debounce |
100 | | - ctx.schedule.debounce(ctx.start + 3_000_000.cycles()).ok(); |
| 85 | + #[task(binds = GPIOTE, shared = [gpiote])] |
| 86 | + fn on_gpiote(mut ctx: on_gpiote::Context) { |
| 87 | + ctx.shared.gpiote.lock(|gpiote| { |
| 88 | + if gpiote.channel0().is_event_triggered() { |
| 89 | + rprintln!("Interrupt from channel 0 event"); |
| 90 | + } |
| 91 | + if gpiote.port().is_event_triggered() { |
| 92 | + rprintln!("Interrupt from port event"); |
| 93 | + } |
| 94 | + // Reset all events |
| 95 | + gpiote.reset_events(); |
| 96 | + // Debounce |
| 97 | + debounce::spawn_after(50.millis()).ok(); |
| 98 | + }); |
101 | 99 | } |
102 | 100 |
|
103 | | - #[task(resources = [gpiote, btn1, btn3, btn4])] |
104 | | - fn debounce(ctx: debounce::Context) { |
105 | | - let btn1_pressed = ctx.resources.btn1.is_low().unwrap(); |
106 | | - let btn3_pressed = ctx.resources.btn3.is_low().unwrap(); |
107 | | - let btn4_pressed = ctx.resources.btn4.is_low().unwrap(); |
108 | | - |
109 | | - if btn1_pressed { |
110 | | - rprintln!("Button 1 was pressed!"); |
111 | | - // Manually run "task out" operation (toggle) on channel 1 (toggles led1) |
112 | | - ctx.resources.gpiote.channel1().out(); |
113 | | - } |
114 | | - if btn3_pressed { |
115 | | - rprintln!("Button 3 was pressed!"); |
116 | | - // Manually run "task clear" on channel 1 (led1 on) |
117 | | - ctx.resources.gpiote.channel1().clear(); |
118 | | - } |
119 | | - if btn4_pressed { |
120 | | - rprintln!("Button 4 was pressed!"); |
121 | | - // Manually run "task set" on channel 1 (led1 off) |
122 | | - ctx.resources.gpiote.channel1().set(); |
123 | | - } |
| 101 | + #[task(shared = [gpiote], local = [btn1, btn3, btn4])] |
| 102 | + fn debounce(mut ctx: debounce::Context) { |
| 103 | + let btn1_pressed = ctx.local.btn1.is_low().unwrap(); |
| 104 | + let btn3_pressed = ctx.local.btn3.is_low().unwrap(); |
| 105 | + let btn4_pressed = ctx.local.btn4.is_low().unwrap(); |
| 106 | + |
| 107 | + ctx.shared.gpiote.lock(|gpiote| { |
| 108 | + if btn1_pressed { |
| 109 | + rprintln!("Button 1 was pressed!"); |
| 110 | + // Manually run "task out" operation (toggle) on channel 1 (toggles led1) |
| 111 | + gpiote.channel1().out(); |
| 112 | + } |
| 113 | + if btn3_pressed { |
| 114 | + rprintln!("Button 3 was pressed!"); |
| 115 | + // Manually run "task clear" on channel 1 (led1 on) |
| 116 | + gpiote.channel1().clear(); |
| 117 | + } |
| 118 | + if btn4_pressed { |
| 119 | + rprintln!("Button 4 was pressed!"); |
| 120 | + // Manually run "task set" on channel 1 (led1 off) |
| 121 | + gpiote.channel1().set(); |
| 122 | + } |
| 123 | + }); |
124 | 124 | } |
125 | | - |
126 | | - extern "C" { |
127 | | - fn SWI0_EGU0(); |
128 | | - } |
129 | | -}; |
| 125 | +} |
130 | 126 |
|
131 | 127 | #[inline(never)] |
132 | 128 | #[panic_handler] |
133 | 129 | fn panic(info: &PanicInfo) -> ! { |
134 | 130 | cortex_m::interrupt::disable(); |
135 | 131 | rprintln!("{}", info); |
136 | | - loop { |
137 | | - compiler_fence(Ordering::SeqCst); |
138 | | - } |
| 132 | + loop {} |
139 | 133 | } |
0 commit comments