From 910010ba22437efe5777e95ddba0793c96b4d6d7 Mon Sep 17 00:00:00 2001 From: Gabe Venberg Date: Fri, 1 Dec 2023 16:23:48 -0600 Subject: [PATCH] rtic heartbeat --- Cargo.toml | 2 + src/main.rs | 455 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 261 insertions(+), 196 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9878b8f..a8c5137 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,8 +7,10 @@ license = "MIT OR Apache-2.0" [dependencies] cortex-m = {version = "0.7"} cortex-m-rt = "0.7" +cortex-m-rtic = "1.1.4" embedded-hal = { version = "0.2.5", features = ["unproven"] } embedded-alloc = "0.5.1" +rp2040-monotonic = "1.3.0" defmt = "0.3" defmt-rtt = "0.4" diff --git a/src/main.rs b/src/main.rs index 2807908..73a3ecc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,208 +1,271 @@ #![no_std] #![no_main] -extern crate alloc; -use alloc::format; -use core::fmt::Write; -use cortex_m::delay::Delay; -use defmt_rtt as _; -use embedded_alloc::Heap; -use embedded_hal::{digital::v2::OutputPin, spi::MODE_0}; -use hd44780::{bus::FourBitBus, HD44780}; -use panic_probe as _; +#[rtic::app( + device = rp_pico::hal::pac, + dispatchers = [TIMER_IRQ_1] + )] +mod app { + extern crate alloc; + use alloc::format; + use core::fmt::Write; + use cortex_m::delay::Delay; + use defmt_rtt as _; + use embedded_alloc::Heap; + use embedded_hal::{ + digital::v2::{OutputPin, ToggleableOutputPin}, + spi::MODE_0, + }; + use hd44780::{bus::FourBitBus, HD44780}; + use panic_probe as _; -use rp_pico::{ - entry, - hal::{ - clocks::{init_clocks_and_plls, Clock}, - fugit::RateExtU32, - gpio::{ - self, - bank0::{ - Gpio0, Gpio1, Gpio14, Gpio16, Gpio17, Gpio18, Gpio19, Gpio2, Gpio20, Gpio21, - Gpio25, Gpio3, Gpio4, Gpio5, + use rp2040_monotonic::{fugit::Duration, Rp2040Monotonic}; + + use rp_pico::{ + hal::{ + clocks::{init_clocks_and_plls, Clock}, + fugit::RateExtU32, + gpio::{ + self, + bank0::{ + Gpio0, Gpio1, Gpio14, Gpio16, Gpio17, Gpio18, Gpio19, Gpio2, Gpio20, Gpio21, + Gpio25, Gpio3, Gpio4, Gpio5, + }, + FunctionSio, FunctionSpi, FunctionUart, Pin, PullDown, SioOutput, }, - FunctionSio, FunctionSpi, FunctionUart, Pin, PullDown, SioOutput, + sio::Sio, + spi::{self, Spi}, + uart::{self, UartConfig, UartPeripheral}, + watchdog::Watchdog, }, - pac, - sio::Sio, - spi::{self, Spi}, - uart::{self, UartConfig, UartPeripheral}, - watchdog::Watchdog, - }, - pac::{SPI0, UART0}, - Pins, -}; - -use hd44780_driver as hd44780; -use max31855::{Max31855, Unit}; - -#[global_allocator] -static HEAP: Heap = Heap::empty(); - -fn write_lcd( - lcd: &mut hd44780::HD44780, - delay: &mut Delay, - string: &str, -) { - lcd.reset(delay).unwrap(); - lcd.clear(delay).unwrap(); - lcd.write_str(string, delay).unwrap(); -} - -type Uart = UartPeripheral< - uart::Enabled, - UART0, - ( - Pin, - Pin, - ), ->; - -type Led = Pin, PullDown>; - -type ExternalLed = Pin, PullDown>; - -type ThermocoupleSpi = Spi< - spi::Enabled, - SPI0, - ( - Pin, - Pin, - Pin, - ), ->; - -type Lcd = HD44780< - FourBitBus< - Pin, PullDown>, - Pin, PullDown>, - Pin, PullDown>, - Pin, PullDown>, - Pin, PullDown>, - Pin, PullDown>, - >, ->; - -struct Thermocouple { - cs: Pin, PullDown>, - spi: ThermocoupleSpi, -} - -impl Thermocouple { - fn read_temp( - &mut self, - ) -> Result> { - self.spi.read_thermocouple(&mut self.cs, Unit::Celsius) - } -} - -#[entry] -fn main() -> ! { - let mut pac = pac::Peripherals::take().unwrap(); - let core = pac::CorePeripherals::take().unwrap(); - let mut watchdog = Watchdog::new(pac.WATCHDOG); - let sio = Sio::new(pac.SIO); - - // 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(); - - //initalize the heap - { - use core::mem::MaybeUninit; - const HEAP_SIZE: usize = 1024; - static mut HEAP_MEM: [MaybeUninit; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE]; - unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) } - } - - let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); - - let pins = Pins::new( - pac.IO_BANK0, - pac.PADS_BANK0, - sio.gpio_bank0, - &mut pac.RESETS, - ); - - let mut uart: Uart = UartPeripheral::new( - pac.UART0, - (pins.gpio0.into_function(), pins.gpio1.into_function()), - &mut pac.RESETS, - ) - .enable( - UartConfig::new( - 9600u32.Hz(), - rp_pico::hal::uart::DataBits::Eight, - None, - rp_pico::hal::uart::StopBits::One, - ), - clocks.peripheral_clock.freq(), - ) - .unwrap(); - - defmt::info!("Program start"); - writeln!(uart, "Program start\r",).unwrap(); - - let mut led_pin: Led = pins.led.into_push_pull_output(); - let mut external_led_pin: ExternalLed = pins.gpio14.into_push_pull_output(); - - //cs - let thermometer_spi_device = pac.SPI0; - let mut thermocouple = Thermocouple { - cs: pins - .gpio5 - .into_push_pull_output_in_state(gpio::PinState::Low), - - spi: Spi::<_, _, _, 8>::new( - thermometer_spi_device, - ( - //mosi - pins.gpio3.into_function::(), - //miso/do - pins.gpio4.into_function::(), - //clk - pins.gpio2.into_function::(), - ), - ) - .init(&mut pac.RESETS, 125_000_000u32.Hz(), 4u32.MHz(), MODE_0), + pac::{SPI0, UART0}, + Pins, }; - let mut lcd: Lcd = hd44780::HD44780::new_4bit( - pins.gpio16.into_push_pull_output(), //rs - pins.gpio17.into_push_pull_output(), //enable - pins.gpio18.into_push_pull_output(), //d4 - pins.gpio19.into_push_pull_output(), //d5 - pins.gpio20.into_push_pull_output(), //d6 - pins.gpio21.into_push_pull_output(), //d6 - &mut delay, - ) - .unwrap(); + use hd44780_driver as hd44780; + use max31855::{Max31855, Unit}; - write_lcd(&mut lcd, &mut delay, "Starting"); - loop { - led_pin.set_high().unwrap(); - external_led_pin.set_low().unwrap(); - delay.delay_ms(500); - led_pin.set_low().unwrap(); - external_led_pin.set_high().unwrap(); - delay.delay_ms(500); - match thermocouple.read_temp() { - Ok(v) => { - writeln!(uart, "Current: {} \r", v).unwrap(); - write_lcd(&mut lcd, &mut delay, &format!("{:02.2} C", v)) - } - Err(e) => defmt::error!("error reading temp {}", defmt::Debug2Format(&e)), + #[global_allocator] + static HEAP: Heap = Heap::empty(); + + const MONO_NUM: u32 = 1; + const MONO_DENOM: u32 = 1000000; + const ONE_SEC_TICKS: u64 = 1000000; + + type Uart = UartPeripheral< + uart::Enabled, + UART0, + ( + Pin, + Pin, + ), + >; + + type Led = Pin, PullDown>; + + type ExternalLed = Pin, PullDown>; + + type ThermocoupleSpi = Spi< + spi::Enabled, + SPI0, + ( + Pin, + Pin, + Pin, + ), + >; + + type Lcd = HD44780< + FourBitBus< + Pin, PullDown>, + Pin, PullDown>, + Pin, PullDown>, + Pin, PullDown>, + Pin, PullDown>, + Pin, PullDown>, + >, + >; + + #[monotonic(binds = TIMER_IRQ_0, default = true)] + type Rp2040Mono = Rp2040Monotonic; + + struct Thermocouple { + cs: Pin, PullDown>, + spi: ThermocoupleSpi, + } + + impl Thermocouple { + fn read_temp( + &mut self, + ) -> Result> + { + self.spi.read_thermocouple(&mut self.cs, Unit::Celsius) + } + } + + fn write_lcd(lcd: &mut Lcd, delay: &mut Delay, string: &str) { + lcd.reset(delay).unwrap(); + lcd.clear(delay).unwrap(); + lcd.write_str(string, delay).unwrap(); + } + + #[shared] + struct Shared { + delay: Delay, + } + + #[local] + struct Local { + led: Led, + thermocouple: Thermocouple, + lcd: Lcd, + external_led: ExternalLed, + } + + #[init] + fn init(mut ctx: init::Context) -> (Shared, Local, init::Monotonics) { + let mut watchdog = Watchdog::new(ctx.device.WATCHDOG); + let sio = Sio::new(ctx.device.SIO); + + // 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, + ctx.device.XOSC, + ctx.device.CLOCKS, + ctx.device.PLL_SYS, + ctx.device.PLL_USB, + &mut ctx.device.RESETS, + &mut watchdog, + ) + .ok() + .unwrap(); + + //initalize the heap + { + use core::mem::MaybeUninit; + const HEAP_SIZE: usize = 1024; + static mut HEAP_MEM: [MaybeUninit; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE]; + unsafe { HEAP.init(HEAP_MEM.as_ptr() as usize, HEAP_SIZE) } + } + + let mut delay = + cortex_m::delay::Delay::new(ctx.core.SYST, clocks.system_clock.freq().to_Hz()); + + let pins = Pins::new( + ctx.device.IO_BANK0, + ctx.device.PADS_BANK0, + sio.gpio_bank0, + &mut ctx.device.RESETS, + ); + + let mut uart: Uart = UartPeripheral::new( + ctx.device.UART0, + (pins.gpio0.into_function(), pins.gpio1.into_function()), + &mut ctx.device.RESETS, + ) + .enable( + UartConfig::new( + 9600u32.Hz(), + rp_pico::hal::uart::DataBits::Eight, + None, + rp_pico::hal::uart::StopBits::One, + ), + clocks.peripheral_clock.freq(), + ) + .unwrap(); + + defmt::info!("Program start"); + writeln!(uart, "Program start\r",).unwrap(); + + let mut led_pin: Led = pins.led.into_push_pull_output(); + let mut external_led_pin: ExternalLed = pins.gpio14.into_push_pull_output(); + + //cs + let thermometer_spi_device = ctx.device.SPI0; + let thermocouple = Thermocouple { + cs: pins + .gpio5 + .into_push_pull_output_in_state(gpio::PinState::Low), + + spi: Spi::<_, _, _, 8>::new( + thermometer_spi_device, + ( + //mosi + pins.gpio3.into_function::(), + //miso/do + pins.gpio4.into_function::(), + //clk + pins.gpio2.into_function::(), + ), + ) + .init( + &mut ctx.device.RESETS, + 125_000_000u32.Hz(), + 4u32.MHz(), + MODE_0, + ), }; + + let mut lcd: Lcd = hd44780::HD44780::new_4bit( + pins.gpio16.into_push_pull_output(), //rs + pins.gpio17.into_push_pull_output(), //enable + pins.gpio18.into_push_pull_output(), //d4 + pins.gpio19.into_push_pull_output(), //d5 + pins.gpio20.into_push_pull_output(), //d6 + pins.gpio21.into_push_pull_output(), //d6 + &mut delay, + ) + .unwrap(); + + let mono = Rp2040Mono::new(ctx.device.TIMER); + + write_lcd(&mut lcd, &mut delay, "Starting"); + + ( + Shared { delay }, + Local { + led: led_pin, + thermocouple, + lcd, + external_led: external_led_pin, + }, + init::Monotonics(mono), + ) + + // loop { + // led_pin.set_high().unwrap(); + // external_led_pin.set_low().unwrap(); + // delay.delay_ms(500); + // led_pin.set_low().unwrap(); + // external_led_pin.set_high().unwrap(); + // delay.delay_ms(500); + // match thermocouple.read_temp() { + // Ok(v) => { + // writeln!(uart, "Current: {} \r", v).unwrap(); + // write_lcd(&mut lcd, &mut delay, &format!("{:02.2} C", v)) + // } + // Err(e) => defmt::error!("error reading temp {}", defmt::Debug2Format(&e)), + // }; + // } + } + #[task(local = [led])] + fn heartbeat(ctx: heartbeat::Context) { + // Flicker the built-in LED + ctx.local.led.toggle().unwrap(); + + // Re-spawn this task after 1 second + let one_second = Duration::::from_ticks(ONE_SEC_TICKS); + heartbeat::spawn_after(one_second).unwrap(); + } + #[task(local = [external_led])] + fn second_heartbeat(ctx: second_heartbeat::Context) { + // Flicker the built-in LED + ctx.local.external_led.toggle().unwrap(); + + // Re-spawn this task after 1 second + let one_and_one_half_second = + Duration::::from_ticks((ONE_SEC_TICKS as f32 * 1.5) as u64); + heartbeat::spawn_after(one_and_one_half_second).unwrap(); } }