From 94c5c2a3662d832999c2700227c3aab35427301d Mon Sep 17 00:00:00 2001 From: hodasemi Date: Mon, 2 Jan 2023 10:26:40 +0100 Subject: [PATCH] Start implementing interrupt --- rust/pico/Cargo.toml | 2 + rust/pico/src/main.rs | 244 +++++++++++++++++++++++++----------------- 2 files changed, 147 insertions(+), 99 deletions(-) diff --git a/rust/pico/Cargo.toml b/rust/pico/Cargo.toml index 2bed9c7..c1591b3 100644 --- a/rust/pico/Cargo.toml +++ b/rust/pico/Cargo.toml @@ -6,6 +6,8 @@ version = "0.1.0" [dependencies] cortex-m = "0.7.6" cortex-m-rt = "0.7.2" +cortex-m-rtic = "1.1.2" +fugit = "0.3.6" embedded-hal = { version = "0.2.7", features = ["unproven"] } embedded-time = "0.12.1" diff --git a/rust/pico/src/main.rs b/rust/pico/src/main.rs index 1d6a031..3f99f8e 100644 --- a/rust/pico/src/main.rs +++ b/rust/pico/src/main.rs @@ -1,125 +1,171 @@ -//! Blinks the LED on a Pico board -//! -//! This will blink an LED attached to GP25, which is the pin the Pico uses for the on-board LED. #![no_std] #![no_main] mod serial; -use bsp::entry; -use embedded_hal::digital::v2::OutputPin; use panic_probe as _; -// Provide an alias for our BSP so we can switch targets quickly. -// Uncomment the BSP you included in Cargo.toml, the rest of the code does not need to change. -use rp_pico as bsp; +#[rtic::app(device = rp_pico::hal::pac, peripherals = true)] +mod app { + // Provide an alias for our BSP so we can switch targets quickly. + // Uncomment the BSP you included in Cargo.toml, the rest of the code does not need to change. + use rp_pico as bsp; -use bsp::hal::{ - clocks::{init_clocks_and_plls, Clock}, - pac, - rom_data::reset_to_usb_boot, - sio::Sio, - usb::UsbBus, - watchdog::Watchdog, - Adc, -}; + use bsp::hal::{ + clocks::{init_clocks_and_plls, Clock}, + gpio::{bank0::Gpio26, Floating, Input, Pin}, + rom_data::reset_to_usb_boot, + sio::Sio, + timer::{Alarm, Alarm0}, + usb::UsbBus, + watchdog::Watchdog, + Adc, Timer, + }; -use embedded_hal::adc::OneShot; + use fugit::MicrosDurationU32; -use usb_device::{class_prelude::*, prelude::*}; + use embedded_hal::{adc::OneShot, digital::v2::OutputPin}; + use usb_device::{class_prelude::*, prelude::*}; -use crate::serial::{Commands, Serial}; + use crate::serial::{Commands, Serial}; -#[entry] -fn main() -> ! { - let mut pac = pac::Peripherals::take().unwrap(); - let core = pac::CorePeripherals::take().unwrap(); - let mut watchdog = Watchdog::new(pac.WATCHDOG); + const SCAN_TIME_US: MicrosDurationU32 = MicrosDurationU32::secs(1); - // External high-speed crystal on the pico board is 12Mhz - let external_xtal_freq_hz = 12_000_000u32; - let clocks = init_clocks_and_plls( - external_xtal_freq_hz, - pac.XOSC, - pac.CLOCKS, - pac.PLL_SYS, - pac.PLL_USB, - &mut pac.RESETS, - &mut watchdog, - ) - .ok() - .unwrap(); + struct Data { + i: usize, + usb_bus: UsbBusAllocator, + usb_dev: UsbDevice<'static, UsbBus>, - let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); + serial: Serial<'static>, - let sio = Sio::new(pac.SIO); + adc: Adc, + adc_pin_0: Pin>, + } - let pins = bsp::Pins::new( - pac.IO_BANK0, - pac.PADS_BANK0, - sio.gpio_bank0, - &mut pac.RESETS, - ); + #[shared] + struct Shared { + timer: Timer, + alarm: Alarm0, - let mut led_pin = pins.led.into_push_pull_output(); + data: Data, + } - led_pin.set_low().unwrap(); + #[local] + struct Local {} - // Set up the USB driver - let usb_bus = UsbBusAllocator::new(UsbBus::new( - pac.USBCTRL_REGS, - pac.USBCTRL_DPRAM, - clocks.usb_clock, - true, - &mut pac.RESETS, - )); - - let mut serial = Serial::new(&usb_bus); - - // Create a USB device with a fake VID and PID - let mut usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) - .manufacturer("Fake company") - .product("Serial port") - .serial_number("TEST") - .device_class(2) // from: https://www.usb.org/defined-class-codes - .build(); - - let mut adc = Adc::new(pac.ADC, &mut pac.RESETS); - - let mut adc_pin_0 = pins.gpio26.into_floating_input(); - // let mut adc_pin_1 = pins.gpio27.into_floating_input(); - // let mut adc_pin_2 = pins.gpio28.into_floating_input(); - - let mut i = 0; - - loop { - // serial.write("test".as_bytes()); - - // serial_send(&mut serial, "test"); - // delay.delay_ms(1000); - - i += 1; - - if i == 100 { - i = 0; - - let adc_0_value: u16 = adc.read(&mut adc_pin_0).unwrap(); - // let adc_1_value: u16 = adc.read(&mut adc_pin_1).unwrap(); - // let adc_2_value: u16 = adc.read(&mut adc_pin_2).unwrap(); - - serial.send(adc_0_value); + #[init] + fn init(c: init::Context) -> (Shared, Local, init::Monotonics) { + // Soft-reset does not release the hardware spinlocks + // Release them now to avoid a deadlock after debug or watchdog reset + unsafe { + bsp::hal::sio::spinlock_reset(); } - delay.delay_ms(8); + let mut resets = c.device.RESETS; + let mut watchdog = Watchdog::new(c.device.WATCHDOG); - if usb_dev.poll(&mut [&mut serial]) { - if let Some(command) = serial.read() { - match command { - Commands::Reset => reset_to_usb_boot(0, 0), + let external_xtal_freq_hz = 12_000_000u32; + let clocks = init_clocks_and_plls( + external_xtal_freq_hz, + c.device.XOSC, + c.device.CLOCKS, + c.device.PLL_SYS, + c.device.PLL_USB, + &mut resets, + &mut watchdog, + ) + .ok() + .unwrap(); + + let sio = Sio::new(c.device.SIO); + let pins = rp_pico::Pins::new( + c.device.IO_BANK0, + c.device.PADS_BANK0, + sio.gpio_bank0, + &mut resets, + ); + + let mut timer = Timer::new(c.device.TIMER, &mut resets); + let mut alarm = timer.alarm_0().unwrap(); + let _ = alarm.schedule(SCAN_TIME_US); + alarm.enable_interrupt(); + + let mut led_pin = pins.led.into_push_pull_output(); + + led_pin.set_low().unwrap(); + + // Set up the USB driver + let usb_bus = UsbBusAllocator::new(UsbBus::new( + c.device.USBCTRL_REGS, + c.device.USBCTRL_DPRAM, + clocks.usb_clock, + true, + &mut resets, + )); + + let serial = Serial::new(&usb_bus); + + // Create a USB device with a fake VID and PID + let usb_dev = UsbDeviceBuilder::new(&usb_bus, UsbVidPid(0x16c0, 0x27dd)) + .manufacturer("Fake company") + .product("Serial port") + .serial_number("TEST") + .device_class(2) // from: https://www.usb.org/defined-class-codes + .build(); + + let adc = Adc::new(c.device.ADC, &mut resets); + + let adc_pin_0 = pins.gpio26.into_floating_input(); + // let mut adc_pin_1 = pins.gpio27.into_floating_input(); + // let mut adc_pin_2 = pins.gpio28.into_floating_input(); + + let data = Data { + i: 0, + usb_bus, + usb_dev, + + serial, + + adc, + adc_pin_0, + }; + + (Shared { timer, alarm, data }, Local {}, init::Monotonics()) + } + + #[task( + binds = TIMER_IRQ_0, + priority = 1, + shared = [timer, alarm, data], + local = [tog: bool = true], + )] + fn timer_irq(mut c: timer_irq::Context) { + c.shared.data.lock(|data| { + data.i += 1; + + if data.i == 100 { + data.i = 0; + + let adc_0_value: u16 = data.adc.read(&mut data.adc_pin_0).unwrap(); + // let adc_1_value: u16 = adc.read(&mut adc_pin_1).unwrap(); + // let adc_2_value: u16 = adc.read(&mut adc_pin_2).unwrap(); + + data.serial.send(adc_0_value); + } + + if data.usb_dev.poll(&mut [&mut data.serial]) { + if let Some(command) = data.serial.read() { + match command { + Commands::Reset => reset_to_usb_boot(0, 0), + } } } - } + }); + + let mut alarm = c.shared.alarm; + (alarm).lock(|a| { + a.clear_interrupt(); + let _ = a.schedule(SCAN_TIME_US); + }); } } - -// End of file