From 3578ea097b25dd7ba6f2f10403338d7222db1657 Mon Sep 17 00:00:00 2001 From: nalydmerc Date: Tue, 8 Apr 2025 18:07:30 -0400 Subject: [PATCH] WIP --- src/main.rs | 116 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 68 insertions(+), 48 deletions(-) diff --git a/src/main.rs b/src/main.rs index 0eca4ef..3068df4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,20 +1,19 @@ #![no_std] #![no_main] +use core::cell::RefCell; use core::ptr::read_volatile; -use cortex_m::peripheral; -// pick a panicking behavior -use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics -// use panic_abort as _; // requires nightly -// use panic_itm as _; // logs messages over ITM; requires ITM support -// use panic_semihosting as _; // logs messages to the host stderr; requires a debugger +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) } @@ -25,8 +24,8 @@ fn SysTick() { unsafe { SYS_TICK += 1; } } -fn toggle_mcu_led(peripherals: &mut stm32f103::Peripherals) { - peripherals.GPIOA.odr.modify(|r, w| { +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(), @@ -34,52 +33,70 @@ fn toggle_mcu_led(peripherals: &mut stm32f103::Peripherals) { }); } -fn i2c1_write(i2c: &stm32f103::I2C1, addr: &u8, data: &[u8]) { - i2c.cr1.modify(|_,w| w.start().set_bit()); +fn i2c1_write(addr: &u8, data: &[u8]) { + cortex_m::interrupt::free(|cs| { + if let Some(ref mut i2c1) = *I2C1.borrow(cs).borrow_mut() { + i2c1.cr1.modify(|_,w| w.start().set_bit()); + + while i2c1.sr1.read().sb().bit_is_clear() {} + + i2c1.dr.write(|w| w.dr().bits(*addr)); + + while i2c1.sr1.read().addr().bit_is_clear() {} + let _ = i2c1.sr2.read(); + + for byte in data { + i2c1.dr.write(|w| w.dr().bits(*byte)); + while i2c1.sr1.read().tx_e().bit_is_clear() {} + } + + while i2c1.sr1.read().btf().bit_is_clear() {} + + i2c1.cr1.modify(|_,w| w.stop().set_bit()); + } + }); +} - while i2c.sr1.read().sb().bit_is_clear() {} - - i2c.dr.write(|w| w.dr().bits(*addr)); - - while i2c.sr1.read().addr().bit_is_clear() {} - - // 5. Clear the ADDR flag by reading SR2. - let _ = i2c.sr2.read(); - - for byte in data { - i2c.dr.write(|w| w.dr().bits(*byte)); - while i2c.sr1.read().tx_e().bit_is_clear() {} - } - - while i2c.sr1.read().btf().bit_is_clear() {} - - i2c.cr1.modify(|_,w| w.stop().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 mut peripherals = stm32f103::Peripherals::take().unwrap(); - let mut core_peripherals = cortex_m::Peripherals::take().unwrap(); + 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 - core_peripherals.SYST.set_reload(1_000 - 1); // Set period to 1ms - core_peripherals.SYST.clear_current(); // Clear the current value register - core_peripherals.SYST.enable_counter(); // Enable SysTick + 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()); - peripherals.GPIOA.crl.modify(|_, w| w.mode3().output()); - peripherals.GPIOA.crl.modify(|_, w| w.cnf3().push_pull()); - peripherals.GPIOA.odr.modify(|_, w| w.odr3().high()); + 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.apb2enr.modify(|_,w| w.iopben().enabled()); - peripherals.RCC.cfgr.modify(|_, w| w.ppre1().div4()); + 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()); @@ -89,26 +106,29 @@ fn main() -> ! { peripherals.GPIOB.crl.modify(|_,w| w.cnf7().alt_open_drain()); // Configure peripheral - peripherals.I2C1.cr2.modify(|_,w| unsafe { w.freq().bits(0x02) }); - peripherals.I2C1.trise.write(|w| w.trise().bits(0x09)); - peripherals.I2C1.cr1.modify(|_,w| w.pe().enabled()); - peripherals.I2C1.ccr.modify(|_,w| w.f_s().standard()); - peripherals.I2C1.ccr.modify(|_,w| unsafe { w.ccr().bits(0x04) }); + i2c1.cr1.modify(|_,w| w.pe().enabled()); + i2c1.cr1.modify(|_,w| w.smbus().i2c()); + i2c1.oar1.modify(|_,w| w.add().bits(0x32)); + 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 { - // your code goes here let current_value = get_sys_tick(); if current_value >= timer_ms { - toggle_mcu_led(&mut peripherals); + toggle_mcu_led(&mut gpioa); timer_ms = current_value + 500; - let addr: u8 = 0x0a; - let data: [u8;4] = [0x01, 0x02, 0x03, 0x04]; - - i2c1_write(&peripherals.I2C1, &addr, &data); } } }