#![no_main] #![no_std] use cortex_m_rt::ExceptionFrame; use cortex_m_semihosting::hio; use panic_semihosting as _; use stm32f1xx_hal::{ prelude::*, pac, i2c::{BlockingI2c, Mode}, delay::Delay, }; use embedded_hal::digital::v2::{OutputPin, ToggleableOutputPin}; use hd44780_driver::{Cursor, CursorBlink, Display, DisplayMode, HD44780}; use si5351::{Si5351, Si5351Device}; use core::fmt::Write; fn print(step: usize) -> Result<(), core::fmt::Error> { let mut stdout = match hio::hstdout() { Ok(fd) => fd, Err(()) => return Err(core::fmt::Error), }; let language = "Rust"; let ranking = 1; write!(stdout, "{}: {} on embedded is #{}!\n", step, language, ranking)?; Ok(()) } #[cortex_m_rt::entry] fn main() -> ! { let cp = cortex_m::Peripherals::take().unwrap(); let dp = pac::Peripherals::take().unwrap(); let mut flash = dp.FLASH.constrain(); let mut rcc = dp.RCC.constrain(); let mut afio = dp.AFIO.constrain(&mut rcc.apb2); let clocks = rcc.cfgr.freeze(&mut flash.acr); let mut delay = Delay::new(cp.SYST, clocks); let mut gpiob = dp.GPIOB.split(&mut rcc.apb2); // Configure PB14 as output. (LED) let mut led = gpiob.pb14.into_push_pull_output(&mut gpiob.crh); led.set_low().unwrap(); // Configure I2C1 to be used for Si5351 and display let scl = gpiob.pb6.into_alternate_open_drain(&mut gpiob.crl); let sda = gpiob.pb7.into_alternate_open_drain(&mut gpiob.crl); let i2c = BlockingI2c::i2c1( dp.I2C1, (scl, sda), &mut afio.mapr, Mode::Standard { frequency: 100_000.hz(), }, clocks, &mut rcc.apb1, /* start_timeout_us */ 1000, /* start_retries */ 10, /* addr_timeout_us */ 1000, /* data_timeout_us */ 1000, ); let i2c_busmanager = shared_bus::CortexMBusManager::new(i2c); /* // Configure I2C2 let scl2 = gpiob.pb10.into_alternate_open_drain(&mut gpiob.crh); let sda2 = gpiob.pb11.into_alternate_open_drain(&mut gpiob.crh); let i2c2 = BlockingI2c::i2c2( dp.I2C2, (scl2, sda2), Mode::Fast { frequency: 400_000.hz(), duty_cycle: DutyCycle::Ratio2to1, }, clocks, &mut rcc.apb1, /* start_timeout_us */ 1000, /* start_retries */ 10, /* addr_timeout_us */ 1000, /* data_timeout_us */ 1000, ); */ const I2C_ADDRESS: u8 = 0b010_0000; // MCP23008, depending on solder bridges let mut lcd = match HD44780::new_i2c_mcp23008(i2c_busmanager.acquire(), I2C_ADDRESS, &mut delay) { Ok(lcd) => lcd, Err(_) => panic!("HD44780 init fail"), }; lcd.reset(&mut delay).unwrap(); lcd.clear(&mut delay).unwrap(); lcd.set_display_mode( DisplayMode { display: Display::On, cursor_visibility: Cursor::Invisible, cursor_blink: CursorBlink::Off, }, &mut delay).unwrap(); lcd.set_cursor_pos(0, &mut delay).unwrap(); lcd.write_str("Hello, world!", &mut delay).unwrap(); let ref_clock = 25_000_000; let mut siclock = Si5351Device::new(i2c_busmanager.acquire(), false, ref_clock); siclock.init(si5351::CrystalLoad::_10).unwrap(); siclock.set_frequency(si5351::PLL::B, si5351::ClockOutput::Clk0, 28_000_000 + 4_915_200).unwrap(); siclock.set_frequency(si5351::PLL::A, si5351::ClockOutput::Clk1, 144_000_000 + 28_000_000).unwrap(); siclock.set_frequency(si5351::PLL::A, si5351::ClockOutput::Clk2, 4_915_100).unwrap(); lcd.set_cursor_pos(0, &mut delay).unwrap(); lcd.write_str("Clocks set. ", &mut delay).unwrap(); let mut step = 0; print(step).unwrap(); loop { led.toggle().unwrap(); delay.delay_ms(600u32); lcd.set_cursor_pos(40, &mut delay).unwrap(); let mut string = arrayvec::ArrayString::<[_; 16]>::new(); write!(string, "Step {} ", step).unwrap(); lcd.write_str(&string, &mut delay).unwrap(); step += 1; } } #[cortex_m_rt::exception] fn HardFault(ef: &ExceptionFrame) -> ! { let periph = unsafe { cortex_m::Peripherals::steal() }; let hfsr = periph.SCB.hfsr.read(); let cfsr = periph.SCB.cfsr.read(); let mut stdout = match hio::hstdout() { Ok(fd) => fd, Err(()) => panic!("no stdout"), }; let _ = write!(stdout, "Hardfault {:x} {:x} at {:x}\n", hfsr, cfsr, ef.pc); cortex_m::asm::bkpt(); loop { } } #[cortex_m_rt::exception] fn DefaultHandler(irqn: i16) { let mut stdout = match hio::hstdout() { Ok(fd) => fd, Err(()) => panic!("no stdout"), }; let _ = write!(stdout, "Unhandled exception (IRQn = {})", irqn); cortex_m::asm::bkpt(); loop { } } /* code to discover i2c device address let mut stdout = hio::hstdout().unwrap(); loop { for addr in 0..127usize { let bytes = [0u8; 1]; let mut buffer = [0u8; 1]; match i2c.write_read(addr as u8, &bytes, &mut buffer) { Ok(()) => { write!(stdout, "{}: {}\n", addr, buffer[0]).unwrap(); }, Err(_) => { write!(stdout, "{}: fail\n", addr).unwrap(); }, } } } */