//! Interacts with AXP173 present on my custom board #![no_std] #![no_main] extern crate cortex_m; #[macro_use] extern crate cortex_m_rt as rt; extern crate panic_semihosting; extern crate stm32wb_hal as hal; use crate::hal::pac; use cortex_m_semihosting::hprintln; use crate::hal::i2c::I2c; use crate::rt::entry; use hal::prelude::*; use hal::rcc::{ApbDivider, Config, HDivider, HseDivider, PllConfig, PllSrc, SysClkSrc, UsbClkSrc}; use rt::ExceptionFrame; use axp173::{ AdcSampleRate, AdcSettings, Axp173, ChargingCurrent, Ldo, LdoKind, ShutdownLongPressTime, TsPinMode, }; use hal::flash::FlashExt; use embedded_hal::digital::v2::InputPin; const IMU_REPORTING_RATE_HZ: u16 = 1; const IMU_REPORTING_INTERVAL_MS: u16 = (1000 / IMU_REPORTING_RATE_HZ); #[exception] #[allow(non_snake_case)] fn HardFault(ef: &ExceptionFrame) -> ! { panic!("HardFault at {:#?}", ef); } #[exception] #[allow(non_snake_case)] fn DefaultHandler(irqn: i16) { panic!("Unhandled exception (IRQn = {})", irqn); } #[entry] #[inline(never)] fn main() -> ! { let cp = cortex_m::Peripherals::take().unwrap(); let syst = cp.SYST; let dp = pac::Peripherals::take().unwrap(); let rcc = dp.RCC.constrain(); let clock_config = Config::new(SysClkSrc::Pll(PllSrc::Hse(HseDivider::NotDivided))) .cpu1_hdiv(HDivider::NotDivided) .cpu2_hdiv(HDivider::Div2) .apb1_div(ApbDivider::NotDivided) .apb2_div(ApbDivider::NotDivided) .pll_cfg(PllConfig { m: 2, n: 12, r: 3, q: Some(4), p: Some(3), }) .usb_src(UsbClkSrc::PllQ); /* hal::smps::Smps::enable(); while !hal::smps::Smps::is_enabled() { cortex_m::asm::nop(); }*/ /* let clock_config = Config::new(SysClkSrc::HseSys(HseDivider::NotDivided)) .cpu1_hdiv(HDivider::NotDivided) .cpu2_hdiv(HDivider::NotDivided) .apb1_div(ApbDivider::NotDivided) .apb2_div(ApbDivider::NotDivided);*/ let mut rcc = rcc.apply_clock_config(clock_config, &mut dp.FLASH.constrain().acr); let mut delay = hal::delay::Delay::new(syst, rcc.clocks.clone()); let mut gpiob = dp.GPIOB.split(&mut rcc); // On the board under test, I2C pull-ups are controlled via pin let mut pull_ups = gpiob .pb5 .into_push_pull_output(&mut gpiob.moder, &mut gpiob.otyper); let _ = pull_ups.set_high(); let scl = gpiob .pb6 .into_floating_input(&mut gpiob.moder, &mut gpiob.pupdr); if scl.is_low().unwrap() { hprintln!("SCL is LOW").unwrap(); } let sda = gpiob .pb7 .into_floating_input(&mut gpiob.moder, &mut gpiob.pupdr); if sda.is_low().unwrap() { hprintln!("SDA is LOW").unwrap(); } let scl = scl.into_open_drain_output(&mut gpiob.moder, &mut gpiob.otyper); let scl = scl.into_af4(&mut gpiob.moder, &mut gpiob.afrl); let sda = sda.into_open_drain_output(&mut gpiob.moder, &mut gpiob.otyper); let sda = sda.into_af4(&mut gpiob.moder, &mut gpiob.afrl); let i2c = I2c::i2c1(dp.I2C1, (scl, sda), 100.khz(), &mut rcc); let mut axp173 = Axp173::new(i2c); // Check the presence of AXP173 match axp173.init() { Ok(_) => { hprintln!("AXP173 found").unwrap(); } Err(e) => { panic!("{:?}", e); } } // Set charging current to 100mA axp173 .set_charging_current(ChargingCurrent::CURRENT_100MA) .unwrap(); // 25Hz sample rate, Disable TS, enable current sensing ADC axp173 .set_adc_settings( AdcSettings::default() .set_adc_sample_rate(AdcSampleRate::RATE_25HZ) .ts_adc(false) .set_ts_pin_mode(TsPinMode::SHUT_DOWN) .vbus_voltage_adc(true) .vbus_current_adc(true) .batt_voltage_adc(true) .batt_current_adc(true), ) .unwrap(); axp173.set_coulomb_counter(true).unwrap(); axp173.resume_coulomb_counter().unwrap(); axp173 .set_shutdown_long_press_time(ShutdownLongPressTime::SEC_4) .unwrap(); axp173.set_shutdown_long_press(false).unwrap(); axp173.disable_ldo(&LdoKind::LDO2).unwrap(); // LDO3 -> 2.8V /*axp173 .enable_ldo(&Ldo::ldo3_with_voltage(10, true)) .unwrap(); */ delay.delay_ms(500_u16); //status(&mut axp173); loop { status(&mut axp173); delay.delay_ms(500_u16); } loop { cortex_m::asm::nop(); } } fn status< E: core::fmt::Debug, T: embedded_hal::blocking::i2c::WriteRead + embedded_hal::blocking::i2c::Write, >( axp173: &mut Axp173, ) { // Is the device connected to the USB power supply? /*if axp173.vbus_present().unwrap() { hprintln!("VBUS is present").unwrap(); } else { hprintln!("VBUS is not present").unwrap(); } // Is the battery connected to the device? if axp173.battery_present().unwrap() { hprintln!("Battery is present").unwrap(); } else { hprintln!("Battery is not present").unwrap(); } // Is the battery currently being charged? if axp173.battery_charging().unwrap() { hprintln!("Battery is charging").unwrap(); } else { hprintln!("Battery is not charging").unwrap(); } let vbus = axp173.vbus_voltage().unwrap(); hprintln!("VBUS: {}", vbus.as_volts()).unwrap(); let vbus = axp173.vbus_current().unwrap(); hprintln!("VBUS current: {} mA", vbus.as_milliamps()).unwrap(); let batt = axp173.batt_voltage().unwrap(); hprintln!("Batt: {} V", batt.as_volts()).unwrap(); let batt_charge = axp173.batt_charge_current().unwrap(); let batt_discharge = axp173.batt_discharge_current().unwrap(); hprintln!( "Batt: ^ {} mA | v {} mA", batt_charge.as_milliamps(), batt_discharge.as_milliamps() ) .unwrap(); hprintln!( "Charge coulombs: {}", axp173.read_charge_coulomb_counter().unwrap() ) .unwrap(); hprintln!( "Discharge coulombs: {}", axp173.read_discharge_coulomb_counter().unwrap() ) .unwrap(); let ldo = axp173.read_ldo(LdoKind::LDO2).unwrap(); hprintln!( "LDO2: enabled: {}, voltage: {} V", ldo.enabled(), ldo.voltage().0 as f32 / 1000.0, ) .unwrap(); let ldo = axp173.read_ldo(LdoKind::LDO3).unwrap(); hprintln!( "LDO3: enabled: {}, voltage: {} V", ldo.enabled(), ldo.voltage().0 as f32 / 1000.0, ) .unwrap(); let ldo = axp173.read_ldo(LdoKind::LDO4).unwrap(); hprintln!( "LDO4: enabled: {}, voltage: {} V", ldo.enabled(), ldo.voltage().0 as f32 / 1000.0, ) .unwrap(); hprintln!("-----------------------").unwrap(); */ let batt_charge = axp173.batt_charge_current().unwrap(); let batt_discharge = axp173.batt_discharge_current().unwrap(); hprintln!( "Batt: ^ {} mA | v {} mA", batt_charge.as_milliamps(), batt_discharge.as_milliamps() ) .unwrap(); }