#![no_main] #![no_std] use embedded_hal::digital::v2::*; use embedded_hal::prelude::*; use msp430_rt::entry; use msp430fr2x5x_hal::{ clock::{ClockConfig, DcoclkFreqSel, MclkDiv, SmclkDiv}, fram::Fram, gpio::Batch, pmm::Pmm, timer::{CapCmp, SubTimer, Timer, TimerConfig, TimerDiv, TimerExDiv, TimerParts3, TimerPeriph}, watchdog::Wdt, }; use nb::block; use panic_msp430 as _; use void::ResultVoidExt; // 0.5 second on, 0.5 second off #[entry] fn main() -> ! { let periph = msp430fr2355::Peripherals::take().unwrap(); let mut fram = Fram::new(periph.FRCTL); Wdt::constrain(periph.WDT_A); let pmm = Pmm::new(periph.PMM); let p1 = Batch::new(periph.P1) .config_pin0(|p| p.to_output()) .split(&pmm); let mut p1_0 = p1.pin0; let (_smclk, aclk) = ClockConfig::new(periph.CS) .mclk_dcoclk(DcoclkFreqSel::_1MHz, MclkDiv::_1) .smclk_on(SmclkDiv::_1) .aclk_vloclk() .freeze(&mut fram); let parts = TimerParts3::new( periph.TB0, TimerConfig::aclk(&aclk).clk_div(TimerDiv::_2, TimerExDiv::_5), ); let mut timer = parts.timer; let mut subtimer = parts.subtimer2; set_time(&mut timer, &mut subtimer, 500); loop { block!(subtimer.wait()).void_unwrap(); p1_0.set_high().void_unwrap(); // first 0.5 s of timer countdown expires while subtimer expires, so this should only block // for 0.5 s block!(timer.wait()).void_unwrap(); p1_0.set_low().void_unwrap(); } } fn set_time, C>( timer: &mut Timer, subtimer: &mut SubTimer, delay: u16, ) { timer.start(delay + delay); subtimer.set_count(delay); } // The compiler will emit calls to the abort() compiler intrinsic if debug assertions are // enabled (default for dev profile). MSP430 does not actually have meaningful abort() support // so for now, we create our own in each application where debug assertions are present. #[no_mangle] extern "C" fn abort() -> ! { panic!(); }