#![no_std] #![no_main] use core::cell::RefCell; use core::ptr::read_volatile; use cortex_m::interrupt::Mutex; use panic_halt as _; use cortex_m_rt::{entry, exception}; use cortex_m_semihosting::hprintln; use stm32f1::stm32f103; use stm32f1::stm32f103::interrupt; static mut SYS_TICK: u32 = 0; static I2C1: Mutex>> = Mutex::new(RefCell::new(None)); fn get_sys_tick() -> u32 { unsafe { read_volatile(&raw const SYS_TICK) } } #[exception] fn SysTick() { unsafe { SYS_TICK += 1; } } fn toggle_mcu_led(gpioa: &mut stm32f103::GPIOA) { gpioa.odr.modify(|r, w| { match r.odr3().bit() { true => w.odr3().clear_bit(), false => w.odr3().set_bit(), } }); } #[interrupt] fn I2C1_EV() { cortex_m::interrupt::free(|cs| { if let Some(ref mut i2c1) = *I2C1.borrow(cs).borrow_mut() { if i2c1.sr1.read().addr().bit_is_set() { let _ = i2c1.sr2.read(); i2c1.dr.write(|w| w.dr().bits(0xAA)); } } }); } #[entry] fn main() -> ! { let peripherals = stm32f103::Peripherals::take().unwrap(); let core_peripherals = cortex_m::Peripherals::take().unwrap(); let mut syst = core_peripherals.SYST; let i2c1 = peripherals.I2C1; let mut gpioa = peripherals.GPIOA; // Enable Cortex-M SysTick peripherals.STK.ctrl.modify(|_,w| w.tickint().set_bit()); // Enable Systick Interrupt syst.set_reload(1_000 - 1); // Set period to 1ms syst.clear_current(); // Clear the current value register syst.enable_counter(); // Enable SysTick // Enable clock for GPIOA by setting IOPAEN in RCC APB2ENR peripherals.RCC.apb2enr.modify(|_, w| w.iopaen().set_bit()); gpioa.crl.modify(|_, w| w.mode3().output()); gpioa.crl.modify(|_, w| w.cnf3().push_pull()); gpioa.odr.modify(|_, w| w.odr3().high()); // Init i2c // Configure i2c clock peripherals.RCC.cfgr.modify(|_, w| w.ppre1().div2()); peripherals.RCC.apb1enr.modify(|_, w| w.i2c1en().enabled()); // Enable i2c clock peripherals.RCC.apb2enr.modify(|_,w| w.iopben().enabled()); // Set GPIO pin configurations peripherals.GPIOB.crl.modify(|_,w| w.mode6().output50()); peripherals.GPIOB.crl.modify(|_,w| w.mode7().output50()); peripherals.GPIOB.crl.modify(|_,w| w.cnf6().alt_open_drain()); peripherals.GPIOB.crl.modify(|_,w| w.cnf7().alt_open_drain()); // Configure peripheral i2c1.cr1.modify(|_,w| w.pe().enabled()); i2c1.cr1.modify(|_,w| w.smbus().i2c()); i2c1.cr1.modify(|_, w| w.ack().set_bit()); i2c1.oar1.modify(|_,w| w.add().bits(0x32 << 1)); i2c1.oar1.modify(|_,w| w.addmode().add7()); // Pass peripheral reference to global static cortex_m::interrupt::free(|cs| { i2c1.cr2.modify(|_,w| w.itevten().enabled()); i2c1.cr2.modify(|_,w| w.itbufen().enabled()); *I2C1.borrow(cs).borrow_mut() = Some(i2c1); // I don't understand why this is unsafe or how I could make it safe. unsafe { cortex_m::peripheral::NVIC::unmask(stm32f1::stm32f103::interrupt::I2C1_EV); } }); let mut timer_ms = 500; loop { let current_value = get_sys_tick(); if current_value >= timer_ms { toggle_mcu_led(&mut gpioa); timer_ms = current_value + 500; } } }