#![no_main] #![no_std] use defmt_rtt as _; // global logger use panic_probe as _; use stm32f1xx_hal as _; // same panicking *behavior* as `panic-probe` but doesn't print a panic message // this prevents the panic message being printed *twice* when `defmt::panic` is invoked #[defmt::panic_handler] fn panic() -> ! { cortex_m::asm::udf() } use rtic::app; mod si5153; #[app(device = stm32f1xx_hal::pac)] mod app { use stm32f1xx_hal::{ delay::Delay, gpio::{gpiob, gpioc, Alternate, Floating, Input, OpenDrain, Output, PushPull}, i2c, i2c::BlockingI2c, pac::I2C1, pac::{self, Interrupt}, prelude::*, prelude::*, serial::{Config, Serial}, stm32, timer::{Event, Timer}, }; use nmea0183::{datetime::Time, ParseResult, Parser}; use crate::si5153::Si5153; type AppI2C1 = BlockingI2c< I2C1, ( gpiob::PB6>, gpiob::PB7>, ), >; #[shared] struct Shared { i2c: AppI2C1, time: Time, } #[local] struct Local { gps_parser: Parser, usart: Serial< stm32::USART3, ( gpiob::PB10>, gpiob::PB11>, ), >, board_led: gpioc::PC13>, pll: Si5153, } #[init] fn init(_: init::Context) -> (Shared, Local, init::Monotonics) { // Get access to the core peripherals from the cortex-m crate let cp = cortex_m::Peripherals::take().unwrap(); // Get access to the device specific peripherals from the peripheral access crate let dp = pac::Peripherals::take().unwrap(); // Take ownership over the raw flash and rcc devices and convert them into the corresponding // HAL structs let mut flash = dp.FLASH.constrain(); let mut rcc = dp.RCC.constrain(); // Freeze the configuration of all the clocks in the system and store the frozen frequencies in // `clocks` let clocks = rcc .cfgr .use_hse(8.mhz()) .sysclk(72.mhz()) .pclk1(36.mhz()) .freeze(&mut flash.acr); defmt::info!("Clock Setup done"); let mut timer = Timer::tim2(dp.TIM2, &clocks, &mut rcc.apb1).start_count_down(1.khz()); // Generate an interrupt when the timer expires timer.listen(Event::Update); // Acquire the GPIOC peripheral let mut gpiob = dp.GPIOB.split(&mut rcc.apb2); let mut gpioc = dp.GPIOC.split(&mut rcc.apb2); let mut afio = dp.AFIO.constrain(&mut rcc.apb2); let board_led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh); // USART3 // Configure pb10 as a push_pull output, this will be the tx pin let tx = gpiob.pb10.into_alternate_push_pull(&mut gpiob.crh); // Take ownership over pb11 let rx = gpiob.pb11; // Set up the usart device. Taks ownership over the USART register and tx/rx pins. The rest of // the registers are used to enable and configure the device. let usart = Serial::usart3( dp.USART3, (tx, rx), &mut afio.mapr, Config::default().baudrate(9600.bps()), clocks, &mut rcc.apb1, ); let gps_parser = Parser::new(); let scl = gpiob.pb6.into_alternate_open_drain(&mut gpiob.crl); let sda = gpiob.pb7.into_alternate_open_drain(&mut gpiob.crl); let i2c = i2c::BlockingI2c::i2c1( dp.I2C1, (scl, sda), &mut afio.mapr, i2c::Mode::Standard { frequency: 400_000.hz(), }, clocks, &mut rcc.apb1, 5, 1, 5, 5, ); let pll = Si5153::new(&i2c); let time = Time { hours: 0, minutes: 0, seconds: 0.0, }; ( Shared { i2c, time }, Local { gps_parser, usart, board_led, pll, }, init::Monotonics(), ) } #[task(binds = USART3, local=[usart, board_led, gps_parser], shared=[time])] fn usart3(mut ctx: usart3::Context) { match ctx.local.usart.read() { Ok(byte) => { ctx.local.board_led.toggle().unwrap(); if let Some(result) = ctx.local.gps_parser.parse_from_byte(byte) { match result { Ok(ParseResult::GGA(Some(gga))) => { ctx.shared.time.lock(|time| { time.hours = gga.time.hours; time.minutes = gga.time.minutes; time.seconds = gga.time.seconds; }); /* self.locator = loc::locator_from_coordinates( gga.latitude.as_f64(), gga.longitude.as_f64(), ); defmt::info!("Got GGA. New locator: {}", self.locator.as_str()); */ } Ok(_) => {} // Some other sentences.. Err(_) => {} // Got parse error } } } Err(nb::Error::WouldBlock) => {} Err(nb::Error::Other(_)) => {} } } #[task(binds = TIM2, shared=[time])] fn tim2(mut ctx: tim2::Context) { ctx.shared.time.lock(|time| { time.seconds += 0.001; if time.seconds >= 60.0 { time.seconds -= 60.0; time.minutes += 1; } if time.minutes == 60 { time.minutes = 0; time.hours += 1; } if time.hours == 24 { time.hours = 0; } }); } }