//! Shows how to use a QEI wrapper on an stm32f103xx. #![no_main] // Don't use the Rust standard bootstrap. We will provide our own. #![no_std] // Don't use the Rust standard library. We are building a binary that can run on its own. extern crate cortex_m; // Low-level functions for ARM Cortex-M3 processor in STM32 Blue Pill. #[macro_use(entry, exception)] // Import macros from the following crates, extern crate cortex_m_rt; // Startup and runtime functions for ARM Cortex-M3. extern crate cortex_m_semihosting; // Debug console functions for ARM Cortex-M3. extern crate panic_semihosting; // Panic reporting functions, which transmit to the debug console. extern crate stm32f103xx_hal as bluepill_hal; // Hardware Abstraction Layer (HAL) for STM32 Blue Pill. #[macro_use] extern crate stm32f103xx; extern crate nb; extern crate embedded_hal; extern crate pid_control; extern crate qei; use cortex_m::Peripherals as CortexPeripherals; use bluepill_hal::prelude::*; // Define HAL traits. use bluepill_hal::qei::Qei; use bluepill_hal::stm32f103xx as f103; use bluepill_hal::stm32f103xx::Peripherals; use core::fmt::Write; // Provides writeln() function for debug console output. use cortex_m_rt::ExceptionFrame; // Stack frame for exception handling. use cortex_m_semihosting::hio; // For displaying messages on the debug console. // Clocks, flash memory, GPIO for the STM32 Blue Pill. use f103::Interrupt; use qei::QeiManager; // Black Pill starts execution at function main(). entry!(main); // A quick type alias for the qei pins type QeiPins = ( bluepill_hal::gpio::gpiob::PB6>, bluepill_hal::gpio::gpiob::PB7>, ); static mut QEIM: Option>> = None; fn tim2_interrupt() { unsafe { // Clear interrupt pending flag; (*f103::TIM2::ptr()).sr.modify(|_, w| w.uif().clear_bit()); // Take a sample QEIM.as_mut().unwrap().sample_unwrap(); }; } fn main() -> ! { let mut debug_out = hio::hstdout().unwrap(); let bluepill = Peripherals::take().unwrap(); let cortex = CortexPeripherals::take().unwrap(); let mut nvic = cortex.NVIC; let mut rcc = bluepill.RCC.constrain(); let mut flash = bluepill.FLASH.constrain(); let mut afio = bluepill.AFIO.constrain(&mut rcc.apb2); // Configure the clock tree let clocks = rcc.cfgr.freeze(&mut flash.acr); // Initialize the GPIO pins let gpiob = bluepill.GPIOB.split(&mut rcc.apb2); let pb6 = gpiob.pb6; let pb7 = gpiob.pb7; // Use tim2 to sample at 1kHz the qei counter let mut tim2 = bluepill_hal::timer::Timer::tim2(bluepill.TIM2, 1000.hz(), clocks, &mut rcc.apb1); // Set up tim4 on pb6 and pb7 to be in encoder mode let qei = Qei::tim4(bluepill.TIM4, (pb6, pb7), &mut afio.mapr, &mut rcc.apb1); unsafe { QEIM = Some(QeiManager::new(qei)); } // Enable the interrupts for tim2 nvic.enable(Interrupt::TIM2); tim2.listen(bluepill_hal::timer::Event::Update); loop { // Print using hstdio the qei value writeln!( debug_out, "Count : {}", unsafe { QEIM.as_mut().unwrap().count()}, ) .unwrap(); } } // Declare the tim2 interrupt interrupt!(TIM2, tim2_interrupt); // For any hard faults, show a message on the debug console and stop. exception!(HardFault, hard_fault); fn hard_fault(ef: &ExceptionFrame) -> ! { panic!("Hard fault: {:#?}", ef); } // For any unhandled interrupts, show a message on the debug console and stop. exception!(*, default_handler); fn default_handler(irqn: i16) { panic!("Unhandled exception (IRQn = {})", irqn); }