|
1 | 1 | #![no_std]
|
2 | 2 | #![no_main]
|
3 | 3 |
|
| 4 | +use core::cell::RefCell; |
| 5 | +use core::sync::atomic::{AtomicU32, Ordering}; |
| 6 | +use core::task::Waker; |
| 7 | +use cortex_m::peripheral::{syst::SystClkSource, SYST}; |
4 | 8 | use embassy_executor::Spawner;
|
5 | 9 | use embassy_stm32::gpio::{Level, Output, Speed};
|
6 |
| -use embassy_time::Timer; |
| 10 | +use embassy_stm32::pac::{self}; |
| 11 | +use embassy_stm32::peripherals::PB7; |
| 12 | +use embassy_time::{Timer}; |
7 | 13 | use panic_halt as _;
|
8 | 14 |
|
| 15 | +use critical_section::{CriticalSection, Mutex}; |
| 16 | +use embassy_time_driver::Driver; |
| 17 | +use embassy_time_queue_utils::Queue; |
| 18 | + |
| 19 | +/* |
| 20 | +use stm32f4xx_hal::{ |
| 21 | + prelude::*, |
| 22 | +}; |
| 23 | +
|
| 24 | + */ |
| 25 | + |
| 26 | +struct MyDriver { |
| 27 | + ticks: AtomicU32, |
| 28 | + queue: Mutex<RefCell<Queue>>, |
| 29 | + next: AtomicU32, |
| 30 | +} |
| 31 | + |
| 32 | +impl MyDriver { |
| 33 | + const fn new() -> Self { |
| 34 | + Self { |
| 35 | + ticks: AtomicU32::new(0), |
| 36 | + queue: Mutex::new(RefCell::new(Queue::new())), |
| 37 | + next: AtomicU32::new(0), |
| 38 | + } |
| 39 | + } |
| 40 | + |
| 41 | + /// Called from SysTick interrupt to increment ticks and process wakeups |
| 42 | + fn on_tick(&self) { |
| 43 | + let ticks = self.ticks.fetch_add(1, Ordering::Relaxed) + 1; |
| 44 | + let next = self.next.load(Ordering::Relaxed); |
| 45 | + if ticks >= next { |
| 46 | + critical_section::with(|cs| { |
| 47 | + let now = self.now(); |
| 48 | + let mut queue = self.queue.borrow(cs).borrow_mut(); |
| 49 | + self.next.store(queue.next_expiration(now) as u32, Ordering::Relaxed); |
| 50 | + }); |
| 51 | + } |
| 52 | + } |
| 53 | + |
| 54 | + fn set_alarm(&self, cs: &CriticalSection, at: u64) -> bool { |
| 55 | + self.next.store(at as u32, Ordering::Relaxed); |
| 56 | + true |
| 57 | + } |
| 58 | +} |
| 59 | + |
| 60 | +impl Driver for MyDriver { |
| 61 | + fn now(&self) -> u64 { |
| 62 | + self.ticks.load(Ordering::Relaxed) as u64 |
| 63 | + } |
| 64 | + |
| 65 | + fn schedule_wake(&self, at: u64, waker: &Waker) { |
| 66 | + critical_section::with(|cs| { |
| 67 | + let mut queue = self.queue.borrow(cs).borrow_mut(); |
| 68 | + if queue.schedule_wake(at, waker) { |
| 69 | + let mut next = queue.next_expiration(self.now()); |
| 70 | + while !self.set_alarm(&cs, next) { |
| 71 | + next = queue.next_expiration(self.now()); |
| 72 | + } |
| 73 | + } |
| 74 | + }); |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +embassy_time_driver::time_driver_impl!(static DRIVER: MyDriver = MyDriver::new()); |
| 79 | + |
9 | 80 | #[embassy_executor::main]
|
10 | 81 | async fn main(_spawner: Spawner) {
|
11 |
| - let p = embassy_stm32::init(Default::default()); |
| 82 | + //let dp = stm32f4xx_hal::pac::Peripherals::take().unwrap(); |
| 83 | + |
| 84 | + let cp = cortex_m::Peripherals::take().unwrap(); |
| 85 | + |
| 86 | + let clocks = 48_000_000; // setup_clocks(dp.RCC); |
| 87 | + |
| 88 | + // Set PB7 to push-pull output |
| 89 | + pac::GPIOB |
| 90 | + .moder() |
| 91 | + .modify(|w| w.set_moder(7, pac::gpio::vals::Moder::OUTPUT)); |
| 92 | + pac::GPIOB |
| 93 | + .otyper() |
| 94 | + .modify(|w| w.set_ot(7, pac::gpio::vals::Ot::PUSH_PULL)); |
| 95 | + pac::GPIOB |
| 96 | + .ospeedr() |
| 97 | + .modify(|w| w.set_ospeedr(7, pac::gpio::vals::Ospeedr::HIGH_SPEED)); |
| 98 | + pac::GPIOB |
| 99 | + .pupdr() |
| 100 | + .modify(|w| w.set_pupdr(7, pac::gpio::vals::Pupdr::FLOATING)); |
12 | 101 |
|
13 |
| - let mut led = Output::new(p.PB7, Level::High, Speed::Low); |
| 102 | + // SAFETY: PB7 is not used anywhere else |
| 103 | + let led = unsafe { Output::new(PB7::steal(), Level::High, Speed::Low) }; |
14 | 104 |
|
| 105 | + // Setup SysTick for 1 kHz ticks (1ms) |
| 106 | + let mut syst = cp.SYST; |
| 107 | + syst.set_clock_source(SystClkSource::Core); |
| 108 | + syst.set_reload(clocks / 1000 - 1); |
| 109 | + syst.clear_current(); |
| 110 | + syst.enable_counter(); |
| 111 | + syst.enable_interrupt(); |
| 112 | + |
| 113 | + blink_loop(led).await; |
| 114 | +} |
| 115 | + |
| 116 | +async fn blink_loop(mut led: Output<'static>) { |
15 | 117 | loop {
|
16 | 118 | led.set_high();
|
17 | 119 | Timer::after_millis(300).await;
|
18 |
| - |
19 | 120 | led.set_low();
|
20 | 121 | Timer::after_millis(300).await;
|
21 | 122 | }
|
22 | 123 | }
|
| 124 | + |
| 125 | +#[cortex_m_rt::exception] |
| 126 | +fn SysTick() { |
| 127 | + critical_section::with(|cs| { |
| 128 | + // Call the driver's tick handler |
| 129 | + DRIVER.on_tick(); |
| 130 | + }); |
| 131 | +} |
0 commit comments