#![no_std]
#![no_main]
use panic_halt as _;
use rp2040_hal as hal;
use hal::pac;
use core::cell::RefCell;
use critical_section::Mutex;
use embedded_hal::digital::v2::ToggleableOutputPin;
use fugit::MicrosDurationU32;
use pac::interrupt;
use rp2040_hal::clocks::Clock;
use rp2040_hal::timer::Alarm;
use rp2040_hal::vector_table::VectorTable;
static mut RAM_VTABLE: VectorTable = VectorTable::new();
type LedAndAlarm = (
hal::gpio::Pin<hal::gpio::bank0::Gpio25, hal::gpio::PushPullOutput>,
hal::timer::Alarm0,
);
static mut LED_AND_ALARM: Mutex<RefCell<Option<LedAndAlarm>>> = Mutex::new(RefCell::new(None));
const SLOW_BLINK_INTERVAL_US: MicrosDurationU32 = MicrosDurationU32::secs(1);
const FAST_BLINK_INTERVAL_US: MicrosDurationU32 = MicrosDurationU32::millis(300);
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_GENERIC_03H;
const XTAL_FREQ_HZ: u32 = 12_000_000u32;
#[rp2040_hal::entry]
fn main() -> ! {
let mut pac = pac::Peripherals::take().unwrap();
let core = pac::CorePeripherals::take().unwrap();
let mut watchdog = hal::Watchdog::new(pac.WATCHDOG);
let sio = hal::Sio::new(pac.SIO);
let ppb = &mut pac.PPB;
unsafe {
RAM_VTABLE.init(ppb);
RAM_VTABLE.register_handler(pac::Interrupt::TIMER_IRQ_0 as usize, timer_irq0_replacement);
}
let clocks = hal::clocks::init_clocks_and_plls(
XTAL_FREQ_HZ,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
pac.PLL_USB,
&mut pac.RESETS,
&mut watchdog,
)
.ok()
.unwrap();
let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());
let pins = hal::gpio::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);
let led_pin = pins.gpio25.into_push_pull_output();
let mut timer = hal::Timer::new(pac.TIMER, &mut pac.RESETS);
critical_section::with(|cs| {
let mut alarm = timer.alarm_0().unwrap();
let _ = alarm.schedule(SLOW_BLINK_INTERVAL_US);
alarm.enable_interrupt();
unsafe {
LED_AND_ALARM.borrow(cs).replace(Some((led_pin, alarm)));
}
});
unsafe {
pac::NVIC::unmask(pac::Interrupt::TIMER_IRQ_0);
}
delay.delay_ms(5000);
unsafe {
critical_section::with(|_| {
RAM_VTABLE.activate(ppb);
});
}
loop {
cortex_m::asm::wfi();
}
}
#[interrupt]
fn TIMER_IRQ_0() {
critical_section::with(|cs| {
let ledalarm = unsafe { LED_AND_ALARM.borrow(cs).take() };
if let Some((mut led, mut alarm)) = ledalarm {
alarm.clear_interrupt();
let _ = alarm.schedule(SLOW_BLINK_INTERVAL_US);
led.toggle().unwrap();
unsafe {
LED_AND_ALARM
.borrow(cs)
.replace_with(|_| Some((led, alarm)));
}
}
});
}
extern "C" fn timer_irq0_replacement() {
critical_section::with(|cs| {
let ledalarm = unsafe { LED_AND_ALARM.borrow(cs).take() };
if let Some((mut led, mut alarm)) = ledalarm {
alarm.clear_interrupt();
let _ = alarm.schedule(FAST_BLINK_INTERVAL_US);
led.toggle().unwrap();
unsafe {
LED_AND_ALARM
.borrow(cs)
.replace_with(|_| Some((led, alarm)));
}
}
});
}