diff --git a/.vscode/settings.json b/.vscode/settings.json index 6b17def..d49e011 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,6 +3,6 @@ "rust-analyzer.cargo.target": "thumbv6m-none-eabi", "rust-analyzer.cargo.features": [ "rt", - "stm32g071" + "stm32g081" ] } diff --git a/Cargo.toml b/Cargo.toml index 3c3a2ef..3e87d31 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,41 +17,31 @@ default-target = "thumbv6m-none-eabi" [dependencies] cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } -nb = "1.0.0" -fugit = "0.3.5" +nb = "1.1.0" +fugit = "0.3.7" +embedded-hal = "1.0.0" +bare-metal = "1.0.0" [dependencies.stm32g0] version = "0.15.1" features = ["rt"] -[dependencies.bare-metal] -version = "1.0.0" - -[dependencies.embedded-hal] -features = ["unproven"] -version = "0.2.6" - [dependencies.void] default-features = false version = "1.0.2" [dev-dependencies] -cortex-m-rt = "0.7.1" -cortex-m-rtic = "1.0.0" -cortex-m-semihosting = "0.3.5" -embedded-graphics = "0.5" -embedded-sdmmc = "0.2.1" -infrared = "0.11.0" -panic-halt = "0.2.0" -panic-semihosting = "0.5.3" -smart-leds = "0.3.0" -st7735-lcd = "0.6.1" -ws2812-spi = { version = "0.3.0", features = [] } +cortex-m-rt = "0.7.5" +cortex-m-rtic = "1.1.4" +cortex-m-semihosting = "0.5.0" +panic-halt = "1.0.0" +panic-semihosting = "0.6.0" [features] default = ["i2c-blocking"] device-selected = [] rt = ["stm32g0/rt"] +defmt = ["embedded-hal/defmt-03"] stm32g030 = ["stm32g0/stm32g030", "stm32g0x0", "device-selected"] stm32g070 = ["stm32g0/stm32g070", "stm32g0x0", "device-selected"] stm32g031 = ["stm32g0/stm32g031", "stm32g0x1", "device-selected"] diff --git a/LICENSE-MIT b/LICENSE-MIT index 9bf1e9d..a58cd5c 100644 --- a/LICENSE-MIT +++ b/LICENSE-MIT @@ -1,6 +1,6 @@ MIT LICENSE -Copyright (c) 2018-2023 Vitaly Domnikov +Copyright (c) 2018-2024 Vitaly Domnikov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/examples/adc.rs b/examples/adc.rs index e7fdbee..37771cd 100644 --- a/examples/adc.rs +++ b/examples/adc.rs @@ -41,6 +41,6 @@ fn main() -> ! { loop { let u_mv = adc.read_voltage(&mut adc_pin).expect("adc read failed"); let u_bat = adc.read_voltage(&mut vbat).expect("adc read failed"); - hprintln!("VBat: {}mV | PA0: {}mV", u_bat * 3, u_mv).unwrap(); + hprintln!("VBat: {}mV | PA0: {}mV", u_bat * 3, u_mv); } } diff --git a/examples/adc_ext_trig_double_dma_serial.rs b/examples/adc_ext_trig_double_dma_serial.rs index ff42922..dd618a2 100644 --- a/examples/adc_ext_trig_double_dma_serial.rs +++ b/examples/adc_ext_trig_double_dma_serial.rs @@ -2,7 +2,6 @@ // command build: cargo build --example adc_ext_trig_double_dma_serial --features stm32g031 // command run: cargo run --example adc_ext_trig_double_dma_serial --features stm32g031 -#![deny(warnings)] #![no_main] #![no_std] @@ -24,14 +23,12 @@ use rt::entry; use core::cell::RefCell; use cortex_m::interrupt::Mutex; +use crate::hal::analog::adc::DmaMode; +use crate::hal::analog::adc::InjectMode; use crate::hal::stm32::{interrupt, Interrupt}; use hal::analog::adc::{InjTrigSource, Precision, SampleTime}; //, VTemp - use hal::dma::{self, Channel, Target}; -use crate::hal::analog::adc::DmaMode; -use crate::hal::analog::adc::InjectMode; - // Make dma globally available static G_DMA: Mutex>> = Mutex::new(RefCell::new(None)); @@ -120,10 +117,10 @@ fn main() -> ! { .set_peripheral_address(adc_data_register_addr, false); dma.ch1.set_transfer_length(adc_buffer1.len() as u16); - hprintln!("adc_data_register_addr {:?}", adc_buffer1_addr).unwrap(); // will output addr in dec - // in gdb read the data bytes with: x /32xh 0x??????? (last is addr in hex) - // or put addr in dec format: x /32xh 536878092 - // https://sourceware.org/gdb/current/onlinedocs/gdb/Memory.html + hprintln!("adc_data_register_addr {:?}", adc_buffer1_addr); // will output addr in dec + // in gdb read the data bytes with: x /32xh 0x??????? (last is addr in hex) + // or put addr in dec format: x /32xh 536878092 + // https://sourceware.org/gdb/current/onlinedocs/gdb/Memory.html // dma ch1 reads from ADC register into memory dma.ch1.select_peripheral(hal::dmamux::DmaMuxIndex::ADC); @@ -162,9 +159,9 @@ fn main() -> ! { adc.set_sample_time(SampleTime::T_80); adc.set_precision(Precision::B_12); let mut pa3 = gpioa.pa5.into_analog(); - let u_raw: u32 = adc.read(&mut pa3).expect("adc read failed"); + let u_raw = adc.read(&mut pa3).expect("adc read failed"); let u = u_raw.saturating_sub(32) as f32 / 4_096_f32 * 3.3; - hprintln!("u: {:.4} V ", u).unwrap(); + hprintln!("u: {:.4} V ", u); adc.set_oversampling_ratio(adc::OversamplingRatio::X_16); adc.set_oversampling_shift(4); diff --git a/examples/blinky_random.rs b/examples/blinky_random.rs index a7a601f..31da5af 100644 --- a/examples/blinky_random.rs +++ b/examples/blinky_random.rs @@ -29,16 +29,16 @@ fn main() -> ! { let mut rng = dp.RNG.constrain(Config::default(), &mut rcc); let mut random_bytes = [0u16; 3]; match rng.fill(&mut random_bytes) { - Ok(()) => hprintln!("random bytes: {:?}", random_bytes).unwrap(), - Err(err) => hprintln!("RNG error: {:?}", err).unwrap(), + Ok(()) => hprintln!("random bytes: {:?}", random_bytes), + Err(err) => hprintln!("RNG error: {:?}", err), } loop { match rng.gen_range(20, 200) { Ok(period) => { - led.toggle().unwrap(); + led.toggle().ok(); delay.delay(period.millis()); } - Err(err) => hprintln!("RNG error: {:?}", err).unwrap(), + Err(err) => hprintln!("RNG error: {:?}", err), } } } @@ -46,6 +46,6 @@ fn main() -> ! { #[allow(clippy::empty_loop)] #[exception] unsafe fn HardFault(ef: &ExceptionFrame) -> ! { - hprintln!("Hard fault {:#?}", ef).unwrap(); + hprintln!("Hard fault {:#?}", ef); loop {} } diff --git a/examples/button.rs b/examples/button.rs index 9e9d9c4..09eac53 100644 --- a/examples/button.rs +++ b/examples/button.rs @@ -21,7 +21,7 @@ fn main() -> ! { let mut delay = cp.SYST.delay(&mut rcc); let gpioc = dp.GPIOC.split(&mut rcc); - let button = gpioc.pc13.into_pull_up_input(); + let mut button = gpioc.pc13.into_pull_up_input(); let gpioa = dp.GPIOA.split(&mut rcc); let mut led = gpioa.pa5.into_push_pull_output(); diff --git a/examples/crc.rs b/examples/crc.rs index 25304b4..8834a52 100644 --- a/examples/crc.rs +++ b/examples/crc.rs @@ -34,8 +34,7 @@ fn main() -> ! { "crc32: 0x{:x}, crc32b: 0x{:x}", hash_sum, hash_sum ^ 0xffff_ffff - ) - .unwrap(); + ); crc.reset(); crc.feed(b"The quick brown fox jumps over the lazy dog"); @@ -44,7 +43,6 @@ fn main() -> ! { "crc32: 0x{:x}, crc32b: 0x{:x}", hash_sum, hash_sum ^ 0xffff_ffff - ) - .unwrap(); + ); } } diff --git a/examples/dac.rs b/examples/dac.rs index 60b6512..fd2ec75 100644 --- a/examples/dac.rs +++ b/examples/dac.rs @@ -12,10 +12,10 @@ extern crate panic_halt; extern crate stm32g0xx_hal as hal; use hal::analog::dac::GeneratorConfig; -use hal::hal::Direction; use hal::prelude::*; use hal::rcc::Config; use hal::stm32; +use hal::timer::qei::Direction; use rt::entry; #[entry] diff --git a/examples/flash.rs b/examples/flash.rs index 863cc3b..bb57f16 100644 --- a/examples/flash.rs +++ b/examples/flash.rs @@ -35,10 +35,9 @@ fn main() -> ! { hprintln!( "{:02X?}", u64::from_le_bytes((&buffer[0..8]).try_into().expect("never fails")) - ) - .ok(); + ); } - Err(_) => hprintln!("Cannot unlock flash").unwrap(), + Err(_) => hprintln!("Cannot unlock flash"), } loop {} diff --git a/examples/hello.rs b/examples/hello.rs index 4ee4a47..a794870 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -14,7 +14,7 @@ use rt::entry; #[allow(clippy::empty_loop)] #[entry] fn main() -> ! { - hprintln!("Hello, STM32G0!").unwrap(); + hprintln!("Hello, STM32G0!"); loop {} } diff --git a/examples/i2c.rs b/examples/i2c.rs index 550f4f6..6421dca 100644 --- a/examples/i2c.rs +++ b/examples/i2c.rs @@ -31,8 +31,8 @@ fn main() -> ! { let buf: [u8; 1] = [0]; loop { match i2c.write(0x3c, &buf) { - Ok(_) => hprintln!("ok").unwrap(), - Err(err) => hprintln!("error: {:?}", err).unwrap(), + Ok(_) => hprintln!("ok"), + Err(err) => hprintln!("error: {:?}", err), } } } diff --git a/examples/ir_remote.rs b/examples/ir_remote.rs deleted file mode 100644 index cfa94ea..0000000 --- a/examples/ir_remote.rs +++ /dev/null @@ -1,89 +0,0 @@ -#![no_std] -#![no_main] -#![deny(warnings)] - -extern crate cortex_m; -extern crate cortex_m_rt as rt; -extern crate panic_halt; -extern crate rtic; -extern crate stm32g0xx_hal as hal; - -use hal::exti::Event; -use hal::gpio::SignalEdge; -use hal::prelude::*; -use hal::rcc; -use hal::stm32; -use hal::time::*; -use hal::timer::pwm::PwmPin; -use hal::timer::{self, Timer}; -use infrared::protocols::nec::NecCommand; -use infrared::{protocols::Nec, Sender}; -use rtic::app; - -const IR_SAMPLERATE: Hertz = Hertz::kHz(20); -const STROBE_COMMAND: NecCommand = NecCommand { - addr: 0, - cmd: 15, - repeat: false, -}; - -type IrPin = PwmPin; -type IrTimer = Timer; - -#[app(device = hal::stm32, peripherals = true)] -mod app { - use super::*; - - #[shared] - struct Shared { - transmitter: Sender, - } - - #[local] - struct Local { - timer: IrTimer, - exti: stm32::EXTI, - } - - #[init] - fn init(mut ctx: init::Context) -> (Shared, Local, init::Monotonics) { - let mut rcc = ctx.device.RCC.freeze(rcc::Config::pll()); - - let gpiob = ctx.device.GPIOB.split(&mut rcc); - let gpioc = ctx.device.GPIOC.split(&mut rcc); - - gpioc.pc13.listen(SignalEdge::Falling, &mut ctx.device.EXTI); - - let mut timer = ctx.device.TIM16.timer(&mut rcc); - timer.start(IR_SAMPLERATE.into_duration()); - timer.listen(); - - let carrier_timer = ctx.device.TIM17.pwm(38.kHz(), &mut rcc); - let mut ir_pin = carrier_timer.bind_pin(gpiob.pb9); - ir_pin.set_duty(ir_pin.get_max_duty() / 2); - let transmitter = Sender::new(IR_SAMPLERATE.raw(), ir_pin); - - ( - Shared { transmitter }, - Local { - timer, - exti: ctx.device.EXTI, - }, - init::Monotonics(), - ) - } - - #[task(binds = TIM16, local = [timer], shared = [transmitter])] - fn timer_tick(mut ctx: timer_tick::Context) { - ctx.shared.transmitter.lock(|tx| tx.tick()); - ctx.local.timer.clear_irq(); - } - - #[task(binds = EXTI4_15, local = [exti], shared = [transmitter])] - fn button_click(mut ctx: button_click::Context) { - ctx.shared - .transmitter - .lock(|tx| tx.load(&STROBE_COMMAND).expect("failed to send IR command")); - ctx.local.exti.unpend(Event::GPIO13); - } -} diff --git a/examples/qei.rs b/examples/qei.rs index ae3a4d2..3d3c2aa 100644 --- a/examples/qei.rs +++ b/examples/qei.rs @@ -21,13 +21,13 @@ fn main() -> ! { let gpioa = dp.GPIOA.split(&mut rcc); let gpioc = dp.GPIOC.split(&mut rcc); - let switch = gpioc.pc5.into_pull_up_input(); + let mut switch = gpioc.pc5.into_pull_up_input(); let qei = dp.TIM1.qei((gpioa.pa8, gpioa.pa9), &mut rcc); loop { let count = qei.count(); if switch.is_low().unwrap() { - hprintln!("Counter: {}", count).unwrap(); + hprintln!("Counter: {}", count); } } } diff --git a/examples/rtic.rs b/examples/rtic.rs index dca8460..5460d71 100644 --- a/examples/rtic.rs +++ b/examples/rtic.rs @@ -71,7 +71,7 @@ mod app { fn button_click(ctx: button_click::Context) { let date = ctx.local.rtc.get_date(); let time = ctx.local.rtc.get_time(); - hprintln!("Button pressed @ {:?} {:?}", date, time).unwrap(); + hprintln!("Button pressed @ {:?} {:?}", date, time); ctx.local.exti.unpend(Event::GPIO13); } diff --git a/examples/rtic_low_power.rs b/examples/rtic_low_power.rs index e003ee1..fb08f17 100644 --- a/examples/rtic_low_power.rs +++ b/examples/rtic_low_power.rs @@ -37,7 +37,7 @@ mod app { let gpioc = ctx.device.GPIOC.split(&mut rcc); let led = gpioa.pa5.into_push_pull_output(); - let button = gpioc.pc13.listen(SignalEdge::Falling, &mut exti); + let mut button = gpioc.pc13.listen(SignalEdge::Falling, &mut exti); let mut power = ctx.device.PWR.constrain(&mut rcc); power.set_mode(PowerMode::UltraLowPower(LowPowerMode::StopMode2)); diff --git a/examples/sdcard.rs b/examples/sdcard.rs deleted file mode 100644 index 4bac8c3..0000000 --- a/examples/sdcard.rs +++ /dev/null @@ -1,89 +0,0 @@ -#![deny(warnings)] -#![deny(unsafe_code)] -#![no_main] -#![no_std] - -extern crate cortex_m; -extern crate cortex_m_rt as rt; -extern crate cortex_m_semihosting as sh; -extern crate nb; -extern crate panic_semihosting; -extern crate stm32g0xx_hal as hal; - -use core::fmt::Write; - -use embedded_sdmmc::{Controller, SdMmcSpi, TimeSource, Timestamp, VolumeIdx}; -use hal::hal::digital::v1_compat::OldOutputPin; -use hal::prelude::*; -use hal::rcc; -use hal::serial; -use hal::spi; -use hal::stm32; -use rt::entry; - -#[allow(clippy::empty_loop)] -#[entry] -fn main() -> ! { - let dp = stm32::Peripherals::take().expect("cannot take peripherals"); - let cp = cortex_m::Peripherals::take().expect("cannot take core peripherals"); - - let mut rcc = dp.RCC.freeze(rcc::Config::pll()); - let mut _delay = cp.SYST.delay(&mut rcc); - let gpioa = dp.GPIOA.split(&mut rcc); - let gpiob = dp.GPIOB.split(&mut rcc); - - let mut uart = dp - .USART2 - .usart( - (gpioa.pa2, gpioa.pa3), - serial::FullConfig::default(), - &mut rcc, - ) - .unwrap(); - - let sdmmc_spi = dp.SPI1.spi( - (gpiob.pb3, gpiob.pb4, gpiob.pb5), - spi::MODE_0, - 400.kHz(), - &mut rcc, - ); - - let sdmmc_cs = OldOutputPin::new(gpioa.pa8.into_push_pull_output()); - let mut controller = Controller::new(SdMmcSpi::new(sdmmc_spi, sdmmc_cs), FakeTime {}); - - writeln!(uart, "Init SD card...\r").unwrap(); - match controller.device().init() { - Ok(_) => { - write!(uart, "Card size... ").unwrap(); - match controller.device().card_size_bytes() { - Ok(size) => writeln!(uart, "{}\r", size).unwrap(), - Err(e) => writeln!(uart, "Err: {:?}", e).unwrap(), - } - writeln!(uart, "Volume 0:\r").unwrap(); - match controller.get_volume(VolumeIdx(0)) { - Ok(volume) => { - let root_dir = controller.open_root_dir(&volume).unwrap(); - writeln!(uart, "Listing root directory:\r").unwrap(); - controller - .iterate_dir(&volume, &root_dir, |x| { - writeln!(uart, "Found: {:?}\r", x.name).unwrap(); - }) - .unwrap(); - writeln!(uart, "End of listing\r").unwrap(); - } - Err(e) => writeln!(uart, "Err: {:?}", e).unwrap(), - } - } - Err(e) => writeln!(uart, "{:?}!", e).unwrap(), - } - - loop {} -} - -struct FakeTime; - -impl TimeSource for FakeTime { - fn get_timestamp(&self) -> Timestamp { - Timestamp::from_calendar(1019, 11, 24, 3, 40, 31).unwrap() - } -} diff --git a/examples/st7735_lcd.rs b/examples/st7735_lcd.rs deleted file mode 100644 index 3228c3d..0000000 --- a/examples/st7735_lcd.rs +++ /dev/null @@ -1,54 +0,0 @@ -#![deny(warnings)] -#![deny(unsafe_code)] -#![no_main] -#![no_std] - -extern crate cortex_m; -extern crate cortex_m_rt as rt; -extern crate cortex_m_semihosting as sh; -extern crate nb; -extern crate panic_halt; -extern crate stm32g0xx_hal as hal; - -use embedded_graphics::image::Image16BPP; -use embedded_graphics::prelude::*; -use embedded_graphics::primitives::rectangle::Rectangle; -use hal::prelude::*; -use hal::rcc; -use hal::spi; -use hal::stm32; -use rt::entry; -use st7735_lcd::{self, Orientation}; - -#[entry] -fn main() -> ! { - let dp = stm32::Peripherals::take().expect("cannot take peripherals"); - let cp = cortex_m::Peripherals::take().expect("cannot take core peripherals"); - let mut rcc = dp.RCC.freeze(rcc::Config::pll()); - - let mut delay = cp.SYST.delay(&mut rcc); - let gpioa = dp.GPIOA.split(&mut rcc); - let dc = gpioa.pa1.into_push_pull_output(); - let rst = gpioa.pa10.into_push_pull_output(); - let spi = dp.SPI2.spi( - (gpioa.pa0, gpioa.pa9, gpioa.pa4), - spi::MODE_0, - 8.MHz(), - &mut rcc, - ); - - let mut disp = st7735_lcd::ST7735::new(spi, dc, rst, false, true); - disp.init(&mut delay).unwrap(); - disp.set_orientation(&Orientation::Landscape).unwrap(); - let black_backdrop = - Rectangle::new(Coord::new(0, 0), Coord::new(160, 128)).fill(Some(0x0000u16.into())); - disp.draw(black_backdrop.into_iter()); - let ferris = Image16BPP::new(include_bytes!("./ferris.raw"), 86, 64); - let mut cnt = 0; - loop { - cnt = (cnt + 1) % 100; - disp.draw(black_backdrop.into_iter()); - disp.draw(ferris.translate(Coord::new(cnt, cnt)).into_iter()); - delay.delay(200.millis()); - } -} diff --git a/examples/stopwatch.rs b/examples/stopwatch.rs index 7bda17d..8b1a14a 100644 --- a/examples/stopwatch.rs +++ b/examples/stopwatch.rs @@ -34,22 +34,22 @@ fn main() -> ! { let elapsed_us = stopwatch.trace(|| { delay.delay(100.micros()); }); - hprintln!("Delay: 100 us -> {}", elapsed_us).unwrap(); + hprintln!("Delay: 100 us -> {}", elapsed_us); timer.start(100.micros()); let elapsed_us = stopwatch.trace(|| { block!(timer.wait()).unwrap(); }); - hprintln!("Timer: 100 us -> {}", elapsed_us).unwrap(); + hprintln!("Timer: 100 us -> {}", elapsed_us); let elapsed_us = stopwatch.trace(calc_something); - hprintln!("Calc @ 16 MHz: {}", elapsed_us).unwrap(); + hprintln!("Calc @ 16 MHz: {}", elapsed_us); let rcc = rcc.freeze(Config::new(SysClockSrc::PLL)); stopwatch.set_clock(rcc.clocks.apb_tim_clk); let elapsed_us = stopwatch.trace(calc_something); - hprintln!("Calc @ 64 MHz: {}", elapsed_us).unwrap(); + hprintln!("Calc @ 64 MHz: {}", elapsed_us); loop {} } diff --git a/examples/watchdog.rs b/examples/watchdog.rs index 9aaf2f6..e1a6881 100644 --- a/examples/watchdog.rs +++ b/examples/watchdog.rs @@ -21,7 +21,7 @@ fn main() -> ! { let mut rcc = dp.RCC.constrain(); let mut delay = cp.SYST.delay(&mut rcc); - hprintln!("Watchdog").unwrap(); + hprintln!("Watchdog"); let mut watchdog = dp.WWDG.constrain(&mut rcc); // let mut watchdog = dp.IWDG.constrain(); diff --git a/examples/ws2812_spi.rs b/examples/ws2812_spi.rs deleted file mode 100644 index 52ddfed..0000000 --- a/examples/ws2812_spi.rs +++ /dev/null @@ -1,56 +0,0 @@ -#![deny(warnings)] -#![deny(unsafe_code)] -#![no_main] -#![no_std] - -extern crate cortex_m; -extern crate cortex_m_rt as rt; -extern crate cortex_m_semihosting as sh; -extern crate nb; -extern crate panic_halt; -extern crate stm32g0xx_hal as hal; - -use hal::prelude::*; -use hal::rcc::{self, PllConfig}; -use hal::spi; -use hal::stm32; -use rt::entry; -use smart_leds::{SmartLedsWrite, RGB}; -use ws2812_spi as ws2812; - -#[entry] -fn main() -> ! { - let dp = stm32::Peripherals::take().expect("cannot take peripherals"); - let cp = cortex_m::Peripherals::take().expect("cannot take core peripherals"); - - // Configure APB bus clock to 48MHz, cause ws2812 requires 3Mbps SPI - let pll_cfg = PllConfig::with_hsi(4, 24, 2); - let rcc_cfg = rcc::Config::pll().pll_cfg(pll_cfg); - let mut rcc = dp.RCC.freeze(rcc_cfg); - - let mut delay = cp.SYST.delay(&mut rcc); - let gpioa = dp.GPIOA.split(&mut rcc); - let spi = dp.SPI2.spi( - (spi::NoSck, spi::NoMiso, gpioa.pa10), - ws2812::MODE, - 3.MHz(), - &mut rcc, - ); - let mut ws = ws2812::Ws2812::new(spi); - - let mut cnt: usize = 0; - let mut data: [RGB; 64] = [RGB::default(); 64]; - loop { - for (idx, color) in data.iter_mut().enumerate() { - *color = match (cnt + idx) % 8 { - 0 => RGB { r: 8, g: 0, b: 0 }, - 1 => RGB { r: 0, g: 4, b: 0 }, - 2 => RGB { r: 0, g: 0, b: 2 }, - _ => RGB { r: 0, g: 0, b: 0 }, - }; - } - ws.write(data.iter().cloned()).unwrap(); - cnt += 1; - delay.delay(50.millis()); - } -} diff --git a/src/analog/adc.rs b/src/analog/adc.rs index ba54f1e..b784203 100644 --- a/src/analog/adc.rs +++ b/src/analog/adc.rs @@ -1,10 +1,16 @@ //! # Analog to Digital converter +use core::convert::Infallible; use core::ptr; use crate::gpio::*; use crate::rcc::{Enable, Rcc}; use crate::stm32::ADC; -use hal::adc::{Channel, OneShot}; + +pub trait Channel { + type ID; + + fn channel() -> Self::ID; +} /// ADC Result Alignment #[derive(Eq, PartialEq)] @@ -226,9 +232,9 @@ impl Adc { /// If oversampling is enabled, the return value is scaled down accordingly. /// The product of the return value and any ADC reading always gives correct voltage in 4096ths of mV /// regardless of oversampling and shift settings provided that these settings remain the same. - pub fn read_vref(&mut self) -> nb::Result { + pub fn read_vref(&mut self) -> nb::Result { let mut vref = VRef::new(); - let vref_val: u32 = if vref.enabled(self) { + let vref_val = if vref.enabled(self) { self.read(&mut vref)? } else { vref.enable(self); @@ -244,7 +250,7 @@ impl Adc { // RM0454 14.9 Calculating the actual VDDA voltage using the internal reference voltage // V_DDA = 3 V x VREFINT_CAL / VREFINT_DATA - let vref = (vref_cal * 3_000_u32 / vref_val) as u16; + let vref = (vref_cal * 3_000_u32 / vref_val as u32) as u16; self.vref_cache = Some(vref); Ok(vref) } @@ -252,7 +258,7 @@ impl Adc { /// Get VREF value using cached value if possible /// /// See `read_vref` for more details. - pub fn get_vref_cached(&mut self) -> nb::Result { + pub fn get_vref_cached(&mut self) -> nb::Result { if let Some(vref) = self.vref_cache { Ok(vref) } else { @@ -263,16 +269,51 @@ impl Adc { pub fn read_voltage>( &mut self, pin: &mut PIN, - ) -> nb::Result { + ) -> nb::Result { let vref = self.get_vref_cached()?; - self.read(pin).map(|raw: u32| { - let adc_mv = (vref as u32 * raw) >> 12; + self.read(pin).map(|raw| { + let adc_mv = (vref as u32 * raw as u32) >> 12; adc_mv as u16 }) } - pub fn read_temperature(&mut self) -> nb::Result { + pub fn read>( + &mut self, + _pin: &mut PIN, + ) -> nb::Result { + self.power_up(); + self.rb.cfgr1.modify(|_, w| { + w.res() + .bits(self.precision as u8) + .align() + .bit(self.align == Align::Left) + }); + + self.rb + .smpr + .modify(|_, w| w.smp1().bits(self.sample_time as u8)); + + self.rb + .chselr0() + .modify(|_, w| unsafe { w.chsel().bits(1 << PIN::channel()) }); + + self.rb.isr.modify(|_, w| w.eos().set_bit()); + self.rb.cr.modify(|_, w| w.adstart().set_bit()); + while self.rb.isr.read().eos().bit_is_clear() {} + + let res = self.rb.dr.read().bits() as u16; + let val = if self.align == Align::Left && self.precision == Precision::B_6 { + res << 8 + } else { + res + }; + + self.power_down(); + Ok(val) + } + + pub fn read_temperature(&mut self) -> nb::Result { let mut vtemp = VTemp::new(); let vtemp_voltage: u16 = if vtemp.enabled(self) { self.read_voltage(&mut vtemp)? @@ -387,46 +428,6 @@ impl DmaMode for Adc { } } -impl OneShot for Adc -where - WORD: From, - PIN: Channel, -{ - type Error = (); - - fn read(&mut self, _pin: &mut PIN) -> nb::Result { - self.power_up(); - self.rb.cfgr1.modify(|_, w| { - w.res() - .bits(self.precision as u8) - .align() - .bit(self.align == Align::Left) - }); - - self.rb - .smpr - .modify(|_, w| w.smp1().bits(self.sample_time as u8)); - - self.rb - .chselr0() - .modify(|_, w| unsafe { w.chsel().bits(1 << PIN::channel()) }); - - self.rb.isr.modify(|_, w| w.eos().set_bit()); - self.rb.cr.modify(|_, w| w.adstart().set_bit()); - while self.rb.isr.read().eos().bit_is_clear() {} - - let res = self.rb.dr.read().bits() as u16; - let val = if self.align == Align::Left && self.precision == Precision::B_6 { - res << 8 - } else { - res - }; - - self.power_down(); - Ok(val.into()) - } -} - macro_rules! int_adc { ($($Chan:ident: ($chan:expr, $en:ident)),+ $(,)*) => { $( diff --git a/src/analog/dac.rs b/src/analog/dac.rs index a1d9677..da5094a 100644 --- a/src/analog/dac.rs +++ b/src/analog/dac.rs @@ -6,7 +6,7 @@ use core::mem::MaybeUninit; use crate::gpio::{DefaultMode, PA4, PA5}; use crate::rcc::*; use crate::stm32::DAC; -use hal::blocking::delay::DelayUs; +use hal::delay::DelayNs; pub trait DacOut { fn set_value(&mut self, val: V); @@ -156,7 +156,7 @@ macro_rules! dac { /// disabled. pub fn calibrate_buffer(self, delay: &mut T) -> $CX where - T: DelayUs, + T: DelayNs, { let dac = unsafe { &(*DAC::ptr()) }; dac.cr.modify(|_, w| w.$en().clear_bit()); @@ -165,7 +165,7 @@ macro_rules! dac { let mut trim = 0; while true { dac.ccr.modify(|_, w| unsafe { w.$trim().bits(trim) }); - delay.delay_us(64_u32); + delay.delay_us(64_000_u32); if dac.sr.read().$cal_flag().bit() { break; } diff --git a/src/dma.rs b/src/dma.rs index 1cb74fb..fe7a10f 100644 --- a/src/dma.rs +++ b/src/dma.rs @@ -161,7 +161,9 @@ pub trait Channel: private::Channel { /// Panics if this channel is enabled. fn set_transfer_length(&mut self, len: u16) { assert!(!self.is_enabled()); - + #[cfg(not(any(feature = "stm32g070")))] + self.ch().ndtr.write(|w| w.ndt().bits(len)); + #[cfg(feature = "stm32g070")] self.ch().ndtr.write(|w| unsafe { w.ndt().bits(len) }); } @@ -181,6 +183,9 @@ pub trait Channel: private::Channel { /// Set the priority level of this channel fn set_priority_level(&mut self, priority: Priority) { let pl = priority.into(); + #[cfg(not(any(feature = "stm32g070")))] + self.ch().cr.modify(|_, w| w.pl().bits(pl)); + #[cfg(feature = "stm32g070")] self.ch().cr.modify(|_, w| unsafe { w.pl().bits(pl) }); } @@ -242,8 +247,6 @@ pub trait Channel: private::Channel { } } -// TODO: Blocked by https://github.com/stm32-rs/stm32-rs/pull/695 -#[cfg(any(feature = "stm32g030", feature = "stm32g031", feature = "stm32g041"))] macro_rules! dma { ( channels: { @@ -258,7 +261,6 @@ macro_rules! dma { use crate::dmamux; use crate::rcc::{Enable, Reset}; use crate::stm32::{self, DMA}; - use crate::dmamux::DmaMuxExt; /// DMA channels @@ -332,19 +334,18 @@ macro_rules! dma { } } -// TODO: Blocked by https://github.com/stm32-rs/stm32-rs/pull/695 -// #[cfg(any(feature = "stm32g070", feature = "stm32g071", feature = "stm32g081"))] -// dma!( -// channels: { -// C1: (ch1, htif1, tcif1, teif1, gif1, chtif1, ctcif1, cteif1, cgif1, C0), -// C2: (ch2, htif2, tcif2, teif2, gif2, chtif2, ctcif2, cteif2, cgif2, C1), -// C3: (ch3, htif3, tcif3, teif3, gif3, chtif3, ctcif3, cteif3, cgif3, C2), -// C4: (ch4, htif4, tcif4, teif4, gif4, chtif4, ctcif4, cteif4, cgif4, C3), -// C5: (ch5, htif5, tcif5, teif5, gif5, chtif5, ctcif5, cteif5, cgif5, C4), -// C6: (ch6, htif6, tcif6, teif6, gif6, chtif6, ctcif6, cteif6, cgif6, C5), -// C7: (ch7, htif7, tcif7, teif7, gif7, chtif7, ctcif7, cteif7, cgif7, C6), -// }, -// ); +#[cfg(any(feature = "stm32g070", feature = "stm32g071", feature = "stm32g081"))] +dma!( + channels: { + C1: (ch1, htif1, tcif1, teif1, gif1, chtif1, ctcif1, cteif1, cgif1, C0), + C2: (ch2, htif2, tcif2, teif2, gif2, chtif2, ctcif2, cteif2, cgif2, C1), + C3: (ch3, htif3, tcif3, teif3, gif3, chtif3, ctcif3, cteif3, cgif3, C2), + C4: (ch4, htif4, tcif4, teif4, gif4, chtif4, ctcif4, cteif4, cgif4, C3), + C5: (ch5, htif5, tcif5, teif5, gif5, chtif5, ctcif5, cteif5, cgif5, C4), + C6: (ch6, htif6, tcif6, teif6, gif6, chtif6, ctcif6, cteif6, cgif6, C5), + C7: (ch7, htif7, tcif7, teif7, gif7, chtif7, ctcif7, cteif7, cgif7, C6), + }, +); #[cfg(any(feature = "stm32g030", feature = "stm32g031", feature = "stm32g041"))] dma!( @@ -357,7 +358,6 @@ dma!( }, ); -#[cfg(any(feature = "stm32g030", feature = "stm32g031", feature = "stm32g041"))] impl DmaExt for DMA { type Channels = Channels; diff --git a/src/gpio.rs b/src/gpio.rs index c2755a4..9f4664e 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -3,8 +3,7 @@ use core::marker::PhantomData; use crate::rcc::Rcc; use core::convert::Infallible; -use embedded_hal::digital::v2::PinState; -use hal::digital::v2::{toggleable, InputPin, OutputPin, StatefulOutputPin}; +use hal::digital::{ErrorType, InputPin, OutputPin, PinState, StatefulOutputPin}; /// Default pin mode pub type DefaultMode = Analog; @@ -95,21 +94,23 @@ unsafe impl Sync for Pin {} // threads unsafe impl Send for Pin {} +impl ErrorType for Pin> { + type Error = Infallible; +} + impl StatefulOutputPin for Pin> { #[inline(always)] - fn is_set_high(&self) -> Result { + fn is_set_high(&mut self) -> Result { self.is_set_low().map(|v| !v) } #[inline(always)] - fn is_set_low(&self) -> Result { + fn is_set_low(&mut self) -> Result { Ok(unsafe { (*self.port).is_set_low(self.i) }) } } impl OutputPin for Pin> { - type Error = Infallible; - #[inline(always)] fn set_high(&mut self) -> Result<(), Self::Error> { unsafe { (*self.port).set_high(self.i) }; @@ -123,32 +124,30 @@ impl OutputPin for Pin> { } } -impl toggleable::Default for Pin> {} - impl InputPin for Pin> { - type Error = Infallible; - #[inline(always)] - fn is_high(&self) -> Result { + fn is_high(&mut self) -> Result { self.is_low().map(|v| !v) } #[inline(always)] - fn is_low(&self) -> Result { + fn is_low(&mut self) -> Result { Ok(unsafe { (*self.port).is_low(self.i) }) } } -impl InputPin for Pin> { +impl ErrorType for Pin> { type Error = Infallible; +} +impl InputPin for Pin> { #[inline(always)] - fn is_high(&self) -> Result { + fn is_high(&mut self) -> Result { self.is_low().map(|v| !v) } #[inline(always)] - fn is_low(&self) -> Result { + fn is_low(&mut self) -> Result { Ok(unsafe { (*self.port).is_low(self.i) }) } } @@ -190,7 +189,6 @@ macro_rules! gpio { pub mod $gpiox { use core::convert::Infallible; use core::marker::PhantomData; - use hal::digital::v2::{toggleable, InputPin, OutputPin, StatefulOutputPin}; use crate::stm32::{EXTI, $GPIOX}; use crate::exti::{ExtiExt, Event}; use crate::rcc::{Enable, Rcc}; @@ -223,9 +221,11 @@ macro_rules! gpio { _mode: PhantomData, } - impl OutputPin for $PXx> { + impl ErrorType for $PXx> { type Error = Infallible; + } + impl OutputPin for $PXx> { fn set_high(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) }; @@ -240,45 +240,42 @@ macro_rules! gpio { } impl StatefulOutputPin for $PXx> { - fn is_set_high(&self) -> Result { + fn is_set_high(&mut self) -> Result { let is_set_high = !self.is_set_low()?; Ok(is_set_high) } - fn is_set_low(&self) -> Result { + fn is_set_low(&mut self) -> Result { // NOTE(unsafe) atomic read with no side effects let is_set_low = unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << self.i) == 0 }; Ok(is_set_low) } } - impl toggleable::Default for $PXx> { - } - impl InputPin for $PXx> { - type Error = Infallible; - - fn is_high(&self) -> Result { + fn is_high(&mut self) -> Result { let is_high = !self.is_low()?; Ok(is_high) } - fn is_low(&self) -> Result { + fn is_low(&mut self) -> Result { // NOTE(unsafe) atomic read with no side effects let is_low = unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }; Ok(is_low) } } - impl InputPin for $PXx> { + impl ErrorType for $PXx> { type Error = Infallible; + } - fn is_high(&self) -> Result { + impl InputPin for $PXx> { + fn is_high(&mut self) -> Result { let is_high = !self.is_low()?; Ok(is_high) } - fn is_low(&self) -> Result { + fn is_low(&mut self) -> Result { // NOTE(unsafe) atomic read with no side effects let is_low = unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }; Ok(is_low) @@ -529,9 +526,11 @@ macro_rules! gpio { } } - impl OutputPin for $PXi> { + impl ErrorType for $PXi> { type Error = Infallible; + } + impl OutputPin for $PXi> { fn set_high(&mut self) -> Result<(), Self::Error> { self.internal_set_state(PinState::High); Ok(()) @@ -544,30 +543,25 @@ macro_rules! gpio { } impl StatefulOutputPin for $PXi> { - fn is_set_high(&self) -> Result { + fn is_set_high(&mut self) -> Result { let is_set_high = !self.is_set_low()?; Ok(is_set_high) } - fn is_set_low(&self) -> Result { + fn is_set_low(&mut self) -> Result { // NOTE(unsafe) atomic read with no side effects let is_set_low = unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 }; Ok(is_set_low) } } - impl toggleable::Default for $PXi> { - } - impl InputPin for $PXi> { - type Error = Infallible; - - fn is_high(&self) -> Result { + fn is_high(&mut self) -> Result { let is_high = !self.is_low()?; Ok(is_high) } - fn is_low(&self) -> Result { + fn is_low(&mut self) -> Result { // NOTE(unsafe) atomic read with no side effects let is_low = unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }; Ok(is_low) @@ -584,15 +578,17 @@ macro_rules! gpio { } } - impl InputPin for $PXi> { + impl ErrorType for $PXi> { type Error = Infallible; + } - fn is_high(&self) -> Result { + impl InputPin for $PXi> { + fn is_high(&mut self) -> Result { let is_high = !self.is_low()?; Ok(is_high) } - fn is_low(&self) -> Result { + fn is_low(&mut self) -> Result { // NOTE(unsafe) atomic read with no side effects let is_low = unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }; Ok(is_low) diff --git a/src/i2c/blocking.rs b/src/i2c/blocking.rs index 6398e75..81db20a 100644 --- a/src/i2c/blocking.rs +++ b/src/i2c/blocking.rs @@ -4,7 +4,6 @@ use crate::i2c::config::Config; use crate::i2c::{self, Error, I2c, I2cDirection, I2cExt, SCLPin, SDAPin}; use crate::rcc::*; use crate::stm32::{I2C1, I2C2}; -use hal::blocking::i2c::{Read, Write, WriteRead}; pub trait I2cSlave { /// Enable/Disable Slave Byte Control. Default SBC is switched on. @@ -86,7 +85,7 @@ macro_rules! busy_wait { // in case of a master write_read operation, this flag is the only exit for the function. // Leave the bit set, so it can be detected in the wait_addressed function if $idx == $buflen { - return Ok( () ) + return Ok(()) } else { return Err(Error::IncorrectFrameSize($idx)) } @@ -95,7 +94,7 @@ macro_rules! busy_wait { // Clear the stop condition flag $i2c.icr.write(|w| w.stopcf().set_bit()); if $idx == $buflen { - return Ok( () ) + return Ok(()) } else if $idx == 0 { return Err(Error::Nack) @@ -238,15 +237,13 @@ macro_rules! i2c { } } - impl WriteRead for I2c<$I2CX, SDA, SCL> { - type Error = Error; - - fn write_read( + impl I2c<$I2CX, SDA, SCL> { + pub fn write_read( &mut self, addr: u8, snd_buffer: &[u8], rcv_buffer: &mut [u8], - ) -> Result<(), Self::Error> { + ) -> Result<(), Error> { // TODO support transfers of more than 255 bytes let sndlen = snd_buffer.len(); let rcvlen = rcv_buffer.len(); @@ -323,10 +320,8 @@ macro_rules! i2c { } } - impl Write for I2c<$I2CX, SDA, SCL> { - type Error = Error; - - fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { + impl I2c<$I2CX, SDA, SCL> { + pub fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { let buflen = bytes.len(); assert!(buflen < 256 && buflen > 0); @@ -363,10 +358,8 @@ macro_rules! i2c { } } - impl Read for I2c<$I2CX, SDA, SCL> { - type Error = Error; - - fn read(&mut self, addr: u8, bytes: &mut [u8]) -> Result<(), Self::Error> { + impl I2c<$I2CX, SDA, SCL> { + pub fn read(&mut self, addr: u8, bytes: &mut [u8]) -> Result<(), Error> { let buflen = bytes.len(); // TODO support transfers of more than 255 bytes assert!(buflen < 256 && buflen > 0); @@ -407,7 +400,6 @@ macro_rules! i2c { } impl I2cSlave for I2c<$I2CX, SDA, SCL> { - fn slave_sbc(&mut self, sbc_enabled: bool) { // Enable Slave byte control self.i2c.cr1.modify(|_, w| w.sbc().bit(sbc_enabled) ); @@ -506,6 +498,30 @@ macro_rules! i2c { } } } + + impl hal::i2c::ErrorType for I2c<$I2CX, SDA, SCL> { + type Error = Error; + } + + impl hal::i2c::I2c for I2c<$I2CX, SDA, SCL> { + fn transaction( + &mut self, + address: hal::i2c::SevenBitAddress, + operations: &mut [hal::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + for op in operations { + match op { + hal::i2c::Operation::Read(buffer) => { + self.read(address, buffer)?; + } + hal::i2c::Operation::Write(buffer) => { + self.write(address, buffer)?; + } + } + } + Ok(()) + } + } } } diff --git a/src/i2c/mod.rs b/src/i2c/mod.rs index 42dada4..2967134 100644 --- a/src/i2c/mod.rs +++ b/src/i2c/mod.rs @@ -11,6 +11,7 @@ pub mod config; use crate::rcc::*; pub use config::Config; +use hal::i2c::{ErrorKind, NoAcknowledgeSource}; #[derive(Debug, Clone, Copy)] pub enum SlaveAddressMask { @@ -63,6 +64,18 @@ pub enum Error { IncorrectFrameSize(usize), } +impl hal::i2c::Error for Error { + fn kind(&self) -> ErrorKind { + match self { + Error::Overrun => ErrorKind::Overrun, + Error::BusError => ErrorKind::Bus, + Error::ArbitrationLost => ErrorKind::ArbitrationLoss, + Error::Nack => ErrorKind::NoAcknowledge(NoAcknowledgeSource::Unknown), + _ => ErrorKind::Other, + } + } +} + /// I2C SDA pin pub trait SDAPin { fn setup(&self); diff --git a/src/i2c/nonblocking.rs b/src/i2c/nonblocking.rs index 00ad3aa..9263bc2 100644 --- a/src/i2c/nonblocking.rs +++ b/src/i2c/nonblocking.rs @@ -441,8 +441,6 @@ macro_rules! i2c { } // i2c impl I2cMaster for I2c<$I2CX, SDA, SCL> { - - fn master_write(&mut self, addr: u16, data: &[u8]) -> nb::Result<(), Error>{ // Check if the bus is free if self.i2c.cr2.read().start().bit_is_set() { @@ -556,7 +554,6 @@ macro_rules! i2c { } impl I2cSlave for I2c<$I2CX, SDA, SCL> { - fn slave_sbc(&mut self, sbc_enabled: bool) { // enable acknowlidge control self.i2c.cr1.modify(|_, w| w.sbc().bit(sbc_enabled) ); @@ -606,6 +603,30 @@ macro_rules! i2c { } } + impl hal::i2c::ErrorType for I2c<$I2CX, SDA, SCL> { + type Error = Error; + } + + impl hal::i2c::I2c for I2c<$I2CX, SDA, SCL> { + fn transaction( + &mut self, + address: hal::i2c::SevenBitAddress, + operations: &mut [hal::i2c::Operation<'_>], + ) -> Result<(), Self::Error> { + for op in operations { + match op { + hal::i2c::Operation::Read(buffer) => { + self.read(address, buffer)?; + } + hal::i2c::Operation::Write(buffer) => { + self.write(address, buffer)?; + } + } + } + Ok(()) + } + } + } } diff --git a/src/prelude.rs b/src/prelude.rs index c5980d9..e6bd386 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,9 +1,3 @@ -pub use hal::adc::OneShot as _; -pub use hal::digital::v2::*; -pub use hal::prelude::*; -pub use hal::watchdog::Watchdog as _; -pub use hal::watchdog::WatchdogEnable as _; - pub use crate::analog::adc::AdcExt as _; #[cfg(any(feature = "stm32g071", feature = "stm32g081"))] pub use crate::analog::comparator::ComparatorExt as _; @@ -17,6 +11,7 @@ pub use crate::analog::dac::DacExt as _; pub use crate::analog::dac::DacOut as _; pub use crate::crc::CrcExt as _; pub use crate::timer::delay::DelayExt as _; +pub use hal::digital::*; // pub use crate::dma::CopyDma as _; pub use crate::dma::DmaExt as _; // pub use crate::dma::ReadDma as _; diff --git a/src/rng.rs b/src/rng.rs index 833f964..027380d 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -1,7 +1,6 @@ use core::cmp; use core::mem; -use crate::hal::blocking::rng; use crate::rcc::{Enable, Rcc, Reset}; use crate::stm32::RNG; @@ -130,6 +129,10 @@ impl Rng { } Ok(()) } + + pub fn read(&mut self, buffer: &mut [u8]) -> Result<(), ErrorKind> { + self.fill(buffer) + } } impl core::iter::Iterator for Rng { @@ -140,14 +143,6 @@ impl core::iter::Iterator for Rng { } } -impl rng::Read for Rng { - type Error = ErrorKind; - - fn read(&mut self, buffer: &mut [u8]) -> Result<(), Self::Error> { - self.fill(buffer) - } -} - macro_rules! rng_core { ($($type:ty),+) => { $( diff --git a/src/serial/usart.rs b/src/serial/usart.rs index 54555bc..304b745 100644 --- a/src/serial/usart.rs +++ b/src/serial/usart.rs @@ -1,14 +1,11 @@ -use core::fmt; -use core::marker::PhantomData; - use crate::dma; use crate::dmamux::DmaMuxIndex; use crate::gpio::{AltFunction, *}; -use crate::prelude::*; use crate::rcc::*; use crate::serial::config::*; use crate::stm32::*; - +use core::fmt; +use core::marker::PhantomData; use cortex_m::interrupt; use nb::block; @@ -175,33 +172,13 @@ where } } -pub trait SerialExt { +pub trait SerialExt { fn usart>( self, pins: PINS, - config: Config, + config: CONFIG, rcc: &mut Rcc, - ) -> Result, InvalidConfig>; -} - -impl fmt::Write for Serial -where - Serial: hal::serial::Write, -{ - fn write_str(&mut self, s: &str) -> fmt::Result { - let _ = s.as_bytes().iter().map(|c| block!(self.write(*c))).last(); - Ok(()) - } -} - -impl fmt::Write for Tx -where - Tx: hal::serial::Write, -{ - fn write_str(&mut self, s: &str) -> fmt::Result { - let _ = s.as_bytes().iter().map(|c| block!(self.write(*c))).last(); - Ok(()) - } + ) -> Result, InvalidConfig>; } macro_rules! uart_shared { @@ -290,10 +267,8 @@ macro_rules! uart_shared { } } - impl hal::serial::Read for Rx<$USARTX, Config> { - type Error = Error; - - fn read(&mut self) -> nb::Result { + impl Rx<$USARTX, Config> { + pub fn read(&mut self) -> nb::Result { let usart = unsafe { &(*$USARTX::ptr()) }; let isr = usart.isr.read(); Err( @@ -318,16 +293,13 @@ macro_rules! uart_shared { } } - impl hal::serial::Read for Serial<$USARTX, Config> { - type Error = Error; - - fn read(&mut self) -> nb::Result { + impl Serial<$USARTX, Config> { + pub fn read(&mut self) -> nb::Result { self.rx.read() } } impl Tx<$USARTX, Config> { - /// Starts listening for an interrupt event pub fn listen(&mut self) { let usart = unsafe { &(*$USARTX::ptr()) }; @@ -348,10 +320,8 @@ macro_rules! uart_shared { } - impl hal::serial::Write for Tx<$USARTX, Config> { - type Error = Error; - - fn flush(&mut self) -> nb::Result<(), Self::Error> { + impl Tx<$USARTX, Config> { + pub fn flush(&mut self) -> nb::Result<(), nb::Error> { let usart = unsafe { &(*$USARTX::ptr()) }; if usart.isr.read().tc().bit_is_set() { Ok(()) @@ -360,7 +330,7 @@ macro_rules! uart_shared { } } - fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { + pub fn write(&mut self, byte: u8) -> nb::Result<(), nb::Error> { let usart = unsafe { &(*$USARTX::ptr()) }; if usart.isr.read().txe().bit_is_set() { usart.tdr.write(|w| unsafe { w.bits(byte as u32) }); @@ -371,21 +341,17 @@ macro_rules! uart_shared { } } - impl hal::serial::Write for Serial<$USARTX, Config> { - type Error = Error; - - fn flush(&mut self) -> nb::Result<(), Self::Error> { + impl Serial<$USARTX, Config> { + pub fn flush(&mut self) -> nb::Result<(), nb::Error> { self.tx.flush() } - fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { + pub fn write(&mut self, byte: u8) -> nb::Result<(), nb::Error> { self.tx.write(byte) } } - impl Serial<$USARTX, Config> { - /// Separates the serial struct into separate channel objects for sending (Tx) and /// receiving (Rx) pub fn split(self) -> (Tx<$USARTX, Config>, Rx<$USARTX, Config>) { @@ -395,7 +361,6 @@ macro_rules! uart_shared { } impl dma::Target for Rx<$USARTX, Config> { - fn dmamux(&self) -> DmaMuxIndex { DmaMuxIndex::$dmamux_rx } @@ -418,7 +383,6 @@ macro_rules! uart_shared { } impl dma::Target for Tx<$USARTX, Config> { - fn dmamux(&self) -> DmaMuxIndex { DmaMuxIndex::$dmamux_tx } @@ -493,6 +457,7 @@ macro_rules! uart_basic { .ps() .bit(config.parity == Parity::ParityOdd) }); + #[allow(unused_unsafe)] usart.cr2.write(|w| unsafe { w.stop() .bits(match config.stopbits { @@ -565,6 +530,20 @@ macro_rules! uart_basic { .write(|w| unsafe { w.bits(event.val() & mask) }); } } + + impl fmt::Write for Tx<$USARTX, BasicConfig> { + fn write_str(&mut self, s: &str) -> fmt::Result { + let _ = s.as_bytes().iter().map(|c| block!(self.write(*c))).last(); + Ok(()) + } + } + + impl fmt::Write for Serial<$USARTX, BasicConfig> { + fn write_str(&mut self, s: &str) -> fmt::Result { + let _ = s.as_bytes().iter().map(|c| block!(self.write(*c))).last(); + Ok(()) + } + } }; } @@ -703,6 +682,7 @@ macro_rules! uart_full { .write(|w| unsafe { w.bits(event.val() & mask) }); } } + impl Tx<$USARTX, FullConfig> { /// Returns true if the tx fifo threshold has been reached. pub fn fifo_threshold_reached(&self) -> bool { @@ -731,6 +711,20 @@ macro_rules! uart_full { usart.isr.read().rxft().bit_is_set() } } + + impl fmt::Write for Tx<$USARTX, FullConfig> { + fn write_str(&mut self, s: &str) -> fmt::Result { + let _ = s.as_bytes().iter().map(|c| block!(self.write(*c))).last(); + Ok(()) + } + } + + impl fmt::Write for Serial<$USARTX, FullConfig> { + fn write_str(&mut self, s: &str) -> fmt::Result { + let _ = s.as_bytes().iter().map(|c| block!(self.write(*c))).last(); + Ok(()) + } + } }; } diff --git a/src/spi.rs b/src/spi.rs index 34b8c08..3959e19 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -3,7 +3,8 @@ use crate::rcc::*; use crate::stm32::{SPI1, SPI2}; use crate::time::Hertz; use core::{cell, ptr}; -pub use hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; +pub use hal::spi::*; +use nb::block; /// SPI error #[derive(Debug)] @@ -16,6 +17,16 @@ pub enum Error { Crc, } +impl hal::spi::Error for Error { + fn kind(&self) -> ErrorKind { + match self { + Error::Overrun => ErrorKind::Overrun, + Error::ModeFault => ErrorKind::ModeFault, + Error::Crc => ErrorKind::Other, + } + } +} + /// A filler type for when the SCK pin is unnecessary pub struct NoSck; /// A filler type for when the Miso pin is unnecessary @@ -229,10 +240,8 @@ macro_rules! spi { } } - impl hal::spi::FullDuplex for Spi<$SPIX, PINS> { - type Error = Error; - - fn read(&mut self) -> nb::Result { + impl Spi<$SPIX, PINS> { + pub fn read(&mut self) -> nb::Result { let sr = self.spi.sr.read(); Err(if sr.ovr().bit_is_set() { @@ -252,7 +261,7 @@ macro_rules! spi { }) } - fn send(&mut self, byte: u8) -> nb::Result<(), Error> { + pub fn send(&mut self, byte: u8) -> nb::Result<(), Error> { let sr = self.spi.sr.read(); Err(if sr.ovr().bit_is_set() { @@ -272,9 +281,46 @@ macro_rules! spi { } } - impl ::hal::blocking::spi::transfer::Default for Spi<$SPIX, PINS> {} + impl ErrorType for Spi<$SPIX, PINS> { + type Error = Error; + } + + impl SpiBus for Spi<$SPIX, PINS> { + fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { + for word in words.iter_mut() { + *word = block!(self.read())?; + } + Ok(()) + } + + fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { + for word in words.iter() { + block!(self.send(word.clone()))?; + block!(self.read())?; + } + Ok(()) + } + + fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { + for (r, w) in read.iter_mut().zip(write.iter()) { + block!(self.send(w.clone()))?; + *r = block!(self.read())?; + } + Ok(()) + } - impl ::hal::blocking::spi::write::Default for Spi<$SPIX, PINS> {} + fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { + for word in words.iter_mut() { + block!(self.send(word.clone()))?; + *word = block!(self.read())?; + } + Ok(()) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } + } } } diff --git a/src/timer/delay.rs b/src/timer/delay.rs index d5d066b..f34877c 100644 --- a/src/timer/delay.rs +++ b/src/timer/delay.rs @@ -2,7 +2,7 @@ use core::cmp; use cortex_m::peripheral::{syst::SystClkSource, SYST}; use fugit::ExtU32; -use hal::blocking::delay::{DelayMs, DelayUs}; +use hal::delay::DelayNs; use crate::rcc::*; use crate::stm32::*; @@ -47,39 +47,9 @@ impl Delay { } } -impl DelayUs for Delay { - fn delay_us(&mut self, us: u32) { - self.delay(us.micros()) - } -} - -impl DelayUs for Delay { - fn delay_us(&mut self, us: u16) { - self.delay_us(us as u32) - } -} - -impl DelayUs for Delay { - fn delay_us(&mut self, us: u8) { - self.delay_us(us as u32) - } -} - -impl DelayMs for Delay { - fn delay_ms(&mut self, ms: u32) { - self.delay_us(ms.saturating_mul(1_000)); - } -} - -impl DelayMs for Delay { - fn delay_ms(&mut self, ms: u16) { - self.delay_ms(ms as u32); - } -} - -impl DelayMs for Delay { - fn delay_ms(&mut self, ms: u8) { - self.delay_ms(ms as u32); +impl DelayNs for Delay { + fn delay_ns(&mut self, ns: u32) { + self.delay(ns.nanos()) } } @@ -123,39 +93,9 @@ macro_rules! delays { } } - impl DelayUs for Delay<$TIM> { - fn delay_us(&mut self, us: u32) { - self.delay(us.micros()) - } - } - - impl DelayUs for Delay<$TIM> { - fn delay_us(&mut self, us: u16) { - self.delay_us(us as u32) - } - } - - impl DelayUs for Delay<$TIM> { - fn delay_us(&mut self, us: u8) { - self.delay_us(us as u32) - } - } - - impl DelayMs for Delay<$TIM> { - fn delay_ms(&mut self, ms: u32) { - self.delay_us(ms.saturating_mul(1_000)); - } - } - - impl DelayMs for Delay<$TIM> { - fn delay_ms(&mut self, ms: u16) { - self.delay_ms(ms as u32); - } - } - - impl DelayMs for Delay<$TIM> { - fn delay_ms(&mut self, ms: u8) { - self.delay_ms(ms as u32); + impl DelayNs for Delay<$TIM> { + fn delay_ns(&mut self, ns: u32) { + self.delay(ns.nanos()) } } diff --git a/src/timer/mod.rs b/src/timer/mod.rs index 4b426c9..0030ff0 100644 --- a/src/timer/mod.rs +++ b/src/timer/mod.rs @@ -5,7 +5,6 @@ use crate::time::{Hertz, MicroSecond}; use core::marker::PhantomData; use cortex_m::peripheral::syst::SystClkSource; use cortex_m::peripheral::SYST; -use hal::timer::{CountDown, Periodic}; use void::Void; pub mod delay; @@ -70,21 +69,6 @@ impl Timer { } } -impl CountDown for Timer { - type Time = MicroSecond; - - fn start(&mut self, timeout: T) - where - T: Into, - { - self.start(timeout.into()) - } - - fn wait(&mut self) -> nb::Result<(), Void> { - self.wait() - } -} - pub trait TimerExt { fn timer(self, rcc: &mut Rcc) -> Timer; } @@ -95,8 +79,6 @@ impl TimerExt for SYST { } } -impl Periodic for Timer {} - macro_rules! timers { ($($TIM:ident: ($tim:ident, $cnt:ident $(,$cnt_h:ident)*),)+) => { $( @@ -196,23 +178,6 @@ macro_rules! timers { Timer::$tim(self, rcc) } } - - impl CountDown for Timer<$TIM> { - type Time = MicroSecond; - - fn start(&mut self, timeout: T) - where - T: Into, - { - self.start(timeout.into()) - } - - fn wait(&mut self) -> nb::Result<(), Void> { - self.wait() - } - } - - impl Periodic for Timer<$TIM> {} )+ } } diff --git a/src/timer/pwm.rs b/src/timer/pwm.rs index facc4e4..55d0853 100644 --- a/src/timer/pwm.rs +++ b/src/timer/pwm.rs @@ -6,6 +6,7 @@ use crate::stm32::*; use crate::time::Hertz; use crate::timer::pins::TimerPin; use crate::timer::*; +use embedded_hal::pwm::{ErrorKind, ErrorType, SetDutyCycle}; pub enum OutputCompareMode { Frozen = 0, @@ -106,16 +107,15 @@ macro_rules! pwm { pub fn set_freq(&mut self, freq: Hertz) { let ratio = self.clk / freq; let psc = (ratio - 1) / 0xffff; - let arr = ratio / (psc + 1) - 1; - - unsafe { - self.tim.psc.write(|w| w.psc().bits(psc as u16)); - self.tim.arr.write(|w| w.$arr().bits(arr as u16)); - $( + self.tim.psc.write(|w| w.psc().bits(psc as u16)); + $( + let arr = ratio / (psc + 1) - 1; + unsafe { + self.tim.arr.write(|w| w.$arr().bits(arr as u16)); self.tim.arr.modify(|_, w| w.$arr_h().bits((arr >> 16) as u16)); - )* - self.tim.cr1.write(|w| w.cen().set_bit()) - } + } + )* + self.tim.cr1.write(|w| w.cen().set_bit()) } /// Starts listening pub fn listen(&mut self) { @@ -166,16 +166,14 @@ macro_rules! pwm_hal { ($CH:ty, $ccxe:ident, $ccmrx_output:ident, $ocxpe:ident, $ocxm:ident, $ccrx:ident, $ccrx_l:ident, $ccrx_h:ident),)+ ) => { $( - impl hal::PwmPin for PwmPin<$TIMX, $CH> { - type Duty = u32; - - fn disable(&mut self) { + impl PwmPin<$TIMX, $CH> { + pub fn disable(&mut self) { unsafe { (*$TIMX::ptr()).ccer.modify(|_, w| w.$ccxe().clear_bit()); } } - fn enable(&mut self) { + pub fn enable(&mut self) { unsafe { let tim = &*$TIMX::ptr(); tim.$ccmrx_output().modify(|_, w| w.$ocxpe().set_bit().$ocxm().bits(6)); @@ -183,18 +181,33 @@ macro_rules! pwm_hal { } } - fn get_duty(&self) -> u32 { + pub fn get_duty(&self) -> u32 { unsafe { (*$TIMX::ptr()).$ccrx.read().bits() } } - fn get_max_duty(&self) -> u32 { + pub fn get_max_duty(&self) -> u32 { unsafe { (*$TIMX::ptr()).arr.read().bits() } } - fn set_duty(&mut self, duty: u32) { + pub fn set_duty(&mut self, duty: u32) { unsafe { (*$TIMX::ptr()).$ccrx.write(|w| w.bits(duty)) } } } + + impl ErrorType for PwmPin<$TIMX, $CH> { + type Error = ErrorKind; + } + + impl SetDutyCycle for PwmPin<$TIMX, $CH> { + fn max_duty_cycle(&self) -> u16 { + self.get_max_duty() as u16 + } + + fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> { + self.set_duty(duty as u32); + Ok(()) + } + } )+ }; } @@ -211,16 +224,14 @@ macro_rules! pwm_advanced_hal { ) ,)+ ) => { $( - impl hal::PwmPin for PwmPin<$TIMX, $CH> { - type Duty = u16; - - fn disable(&mut self) { + impl PwmPin<$TIMX, $CH> { + pub fn disable(&mut self) { unsafe { (*$TIMX::ptr()).ccer.modify(|_, w| w.$ccxe().clear_bit()); } } - fn enable(&mut self) { + pub fn enable(&mut self) { unsafe { let tim = &*$TIMX::ptr(); tim.$ccmrx_output().modify(|_, w| w.$ocxpe().set_bit().$ocxm().bits(6)); @@ -234,19 +245,34 @@ macro_rules! pwm_advanced_hal { } } - fn get_duty(&self) -> u16 { + pub fn get_duty(&self) -> u16 { unsafe { (*$TIMX::ptr()).$ccrx.read().$ccrx().bits() } } - fn get_max_duty(&self) -> u16 { + pub fn get_max_duty(&self) -> u16 { unsafe { (*$TIMX::ptr()).arr.read().arr().bits() } } - fn set_duty(&mut self, duty: u16) { + pub fn set_duty(&mut self, duty: u16) { unsafe { (*$TIMX::ptr()).$ccrx.write(|w| w.$ccrx().bits(duty)) } } } + impl ErrorType for PwmPin<$TIMX, $CH> { + type Error = ErrorKind; + } + + impl SetDutyCycle for PwmPin<$TIMX, $CH> { + fn max_duty_cycle(&self) -> u16 { + self.get_max_duty() as u16 + } + + fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> { + self.set_duty(duty); + Ok(()) + } + } + impl PwmPinMode for PwmPin<$TIMX, $CH>{ fn set_compare_mode(&mut self, mode: OutputCompareMode) { unsafe { diff --git a/src/timer/qei.rs b/src/timer/qei.rs index a78d22f..a0d525c 100644 --- a/src/timer/qei.rs +++ b/src/timer/qei.rs @@ -1,5 +1,4 @@ //! Quadrature Encoder Interface -use crate::hal::{self, Direction}; use crate::rcc::*; #[cfg(feature = "stm32g0x1")] @@ -10,6 +9,12 @@ use crate::stm32::{TIM1, TIM3}; use crate::timer::pins::TimerPin; use crate::timer::*; +/// Counting direction +pub enum Direction { + Upcounting, + Downcounting, +} + pub struct Qei { tim: TIM, pins: PINS, @@ -84,20 +89,16 @@ macro_rules! qei { pub fn release(self) -> ($TIMX, PINS) { (self.tim, self.pins.release()) } - } - - impl hal::Qei for Qei<$TIMX, PINS> { - type Count = u16; - fn count(&self) -> u16 { + pub fn count(&self) -> u16 { self.tim.cnt.read().$cnt().bits() } - fn direction(&self) -> Direction { + pub fn direction(&self) -> Direction { if self.tim.cr1.read().dir().bit_is_clear() { - hal::Direction::Upcounting + Direction::Upcounting } else { - hal::Direction::Downcounting + Direction::Downcounting } } } diff --git a/src/watchdog.rs b/src/watchdog.rs index a1999b2..f490cc1 100644 --- a/src/watchdog.rs +++ b/src/watchdog.rs @@ -2,7 +2,6 @@ use crate::prelude::*; use crate::rcc::{Enable, Rcc}; use crate::stm32::{IWDG, WWDG}; use crate::time::{Hertz, MicroSecond}; -use hal::watchdog; pub struct IndependedWatchdog { iwdg: IWDG, @@ -41,23 +40,6 @@ impl IndependedWatchdog { } } -impl watchdog::Watchdog for IndependedWatchdog { - fn feed(&mut self) { - self.feed(); - } -} - -impl watchdog::WatchdogEnable for IndependedWatchdog { - type Time = MicroSecond; - - fn start(&mut self, period: T) - where - T: Into, - { - self.start(period.into()) - } -} - pub trait IWDGExt { fn constrain(self) -> IndependedWatchdog; } @@ -121,23 +103,6 @@ impl WindowWatchdog { } } -impl watchdog::Watchdog for WindowWatchdog { - fn feed(&mut self) { - self.feed(); - } -} - -impl watchdog::WatchdogEnable for WindowWatchdog { - type Time = MicroSecond; - - fn start(&mut self, period: T) - where - T: Into, - { - self.start(period.into()) - } -} - pub trait WWDGExt { fn constrain(self, rcc: &mut Rcc) -> WindowWatchdog; }