diff --git a/esp-hal-common/Cargo.toml b/esp-hal-common/Cargo.toml index ccefe18b412..583456a549a 100644 --- a/esp-hal-common/Cargo.toml +++ b/esp-hal-common/Cargo.toml @@ -13,6 +13,7 @@ license = "MIT OR Apache-2.0" [dependencies] cfg-if = "1.0" embedded-hal = { version = "0.2", features = ["unproven"] } +fugit = "0.3" nb = "1.0" paste = "1.0" procmacros = { path = "../esp-hal-procmacros", package = "esp-hal-procmacros" } diff --git a/esp-hal-common/src/delay.rs b/esp-hal-common/src/delay.rs index b81f59434b1..452e06f06ee 100644 --- a/esp-hal-common/src/delay.rs +++ b/esp-hal-common/src/delay.rs @@ -30,13 +30,14 @@ where #[cfg(feature = "esp32c3")] mod delay { + use fugit::HertzU64; + use crate::pac::SYSTIMER; // The counters and comparators are driven using `XTAL_CLK`. The average clock // frequency is fXTAL_CLK/2.5, which is 16 MHz. The timer counting is // incremented by 1/16 μs on each `CNT_CLK` cycle. - const CLK_FREQ_HZ: u64 = 16_000_000; - + const CLK_FREQ_HZ: HertzU64 = HertzU64::MHz(16); /// Delay driver /// /// Uses the `SYSTIMER` peripheral for counting clock cycles, as @@ -60,7 +61,7 @@ mod delay { /// Delay for the specified number of microseconds pub fn delay(&self, us: u32) { let t0 = self.unit0_value(); - let clocks = (us as u64 * CLK_FREQ_HZ) / 1_000_000; + let clocks = (us as u64 * CLK_FREQ_HZ.raw()) / HertzU64::MHz(1).raw(); while self.unit0_value().wrapping_sub(t0) <= clocks {} } @@ -89,9 +90,12 @@ mod delay { #[cfg(not(feature = "esp32c3"))] mod delay { + + use fugit::HertzU64; + // FIXME: The ESP32-S2 and ESP32-S3 have fixed crystal frequencies of 40MHz. // This will not always be the case when using the ESP32. - const CLK_FREQ_HZ: u64 = 40_000_000; + const CLK_FREQ_HZ: HertzU64 = HertzU64::MHz(40); /// Delay driver /// @@ -107,7 +111,7 @@ mod delay { /// Delay for the specified number of microseconds pub fn delay(&self, us: u32) { - let clocks = (us as u64 * CLK_FREQ_HZ) / 1_000_000; + let clocks = (us as u64 * CLK_FREQ_HZ.raw()) / HertzU64::MHz(1).raw(); xtensa_lx::timer::delay(clocks as u32); } } diff --git a/esp-hal-common/src/i2c.rs b/esp-hal-common/src/i2c.rs index 181ca6754d3..d451062b91f 100644 --- a/esp-hal-common/src/i2c.rs +++ b/esp-hal-common/src/i2c.rs @@ -4,6 +4,7 @@ use core::convert::TryInto; use embedded_hal::blocking::i2c::*; +use fugit::HertzU32; use crate::{ gpio::{InputPin, OutputPin}, @@ -13,13 +14,13 @@ use crate::{ cfg_if::cfg_if! { if #[cfg(feature = "esp32c3")] { - const SOURCE_CLK_FREQ: u32 = 40_000_000; + const SOURCE_CLK_FREQ: HertzU32 = HertzU32::MHz(40); } else if #[cfg(feature = "esp32")] { - const SOURCE_CLK_FREQ: u32 = 80_000_000; + const SOURCE_CLK_FREQ: HertzU32 = HertzU32::MHz(80); } else if #[cfg(feature = "esp32s2")] { - const SOURCE_CLK_FREQ: u32 = 80_000_000; + const SOURCE_CLK_FREQ: HertzU32 = HertzU32::MHz(80); } else { - const SOURCE_CLK_FREQ: u32 = 40_000_000; + const SOURCE_CLK_FREQ: HertzU32 = HertzU32::MHz(40); } } @@ -218,7 +219,7 @@ where i2c: T, mut sda: SDA, mut scl: SCL, - frequency: u32, + frequency: HertzU32, system: &mut System, ) -> Result { enable_peripheral(&i2c, system); @@ -311,7 +312,7 @@ pub trait Instance { fn i2c_number(&self) -> usize; - fn setup(&mut self, frequency: u32) -> Result<(), SetupError> { + fn setup(&mut self, frequency: HertzU32) -> Result<(), SetupError> { // Reset entire peripheral (also resets fifo) self.reset(); @@ -423,21 +424,25 @@ pub trait Instance { /// Sets the frequency of the I2C interface by calculating and applying the /// associated timings - fn set_frequency(&mut self, source_clk: u32, bus_freq: u32) -> Result<(), SetupError> { + fn set_frequency( + &mut self, + source_clk: HertzU32, + bus_freq: HertzU32, + ) -> Result<(), SetupError> { cfg_if::cfg_if! { if #[cfg(any(feature = "esp32s3", feature = "esp32c3"))] { // C3 and S3 have a clock devider mechanism, which we want to configure // as high as possible. - let sclk_div: u8 = (source_clk / (bus_freq * 1024) + 1) + let sclk_div: u8 = (source_clk.raw() / (bus_freq.raw() * 1024) + 1) .try_into() .map_err(|_| SetupError::InvalidClkConfig)?; - let half_cycle: u16 = ((source_clk / sclk_div as u32 / bus_freq / 2) as u32) + let half_cycle: u16 = ((source_clk.raw() / sclk_div as u32 / bus_freq.raw() / 2) as u32) .try_into() .map_err(|_| SetupError::InvalidClkConfig)?; } else { // For EPS32 and the S2 variant no clock divider mechanism exists. - let half_cycle: u16 = (source_clk / (bus_freq * 2) as u32) + let half_cycle: u16 = (source_clk.raw() / (bus_freq.raw() * 2) as u32) .try_into() .map_err(|_| SetupError::InvalidClkConfig)?; } @@ -448,14 +453,14 @@ pub trait Instance { // but improves readability) cfg_if::cfg_if! { if #[cfg(feature = "esp32c3")] { - let scl_wait_high: u8 = (if bus_freq <= 50000 { 0 } else { half_cycle / 8 }) + let scl_wait_high: u8 = (if bus_freq.raw() <= 50000 { 0 } else { half_cycle / 8 }) .try_into() .map_err(|_| SetupError::InvalidClkConfig)?; let scl_high: u16 = half_cycle - scl_wait_high as u16; let sda_hold = half_cycle / 4; let sda_sample = scl_high / 2; } else if #[cfg(feature = "esp32s3")] { - let scl_high = if bus_freq <= 50000 { half_cycle } else { half_cycle / 5 * 4 + 4 }; + let scl_high = if bus_freq.raw() <= 50000 { half_cycle } else { half_cycle / 5 * 4 + 4 }; let scl_wait_high: u8 = (half_cycle - scl_high).try_into().map_err(|_| SetupError::InvalidClkConfig)?; let sda_hold = half_cycle / 2; let sda_sample = half_cycle / 2; diff --git a/esp-hal-common/src/prelude.rs b/esp-hal-common/src/prelude.rs index d6bdf629fce..f48c252d8fa 100644 --- a/esp-hal-common/src/prelude.rs +++ b/esp-hal-common/src/prelude.rs @@ -13,3 +13,4 @@ pub use embedded_hal::{ }, prelude::*, }; +pub use fugit::{ExtU32 as _, ExtU64 as _, RateExtU32 as _, RateExtU64 as _}; diff --git a/esp-hal-common/src/pulse_control.rs b/esp-hal-common/src/pulse_control.rs index e5e02800d48..0675b2cea47 100644 --- a/esp-hal-common/src/pulse_control.rs +++ b/esp-hal-common/src/pulse_control.rs @@ -80,6 +80,8 @@ use core::slice::Iter; +use fugit::NanosDurationU32; + use crate::{ gpio::{types::OutputSignal, OutputPin}, pac::RMT, @@ -169,11 +171,11 @@ pub struct PulseCode { /// Logical output level in the first pulse code interval pub level1: bool, /// Length of the first pulse code interval (in clock cycles) - pub length1: u16, + pub length1: NanosDurationU32, /// Logical output level in the second pulse code interval pub level2: bool, /// Length of the second pulse code interval (in clock cycles) - pub length2: u16, + pub length2: NanosDurationU32, } /// Convert a pulse code structure into a u32 value that can be written @@ -185,7 +187,7 @@ impl From for u32 { // little-endian // The length1 value resides in bits [14:0] - let mut entry: u32 = p.length1 as u32; + let mut entry: u32 = p.length1.ticks() as u32; // If level1 is high, set bit 15, otherwise clear it if p.level1 { @@ -202,7 +204,7 @@ impl From for u32 { } // The length2 value resides in bits [30:16] - entry |= (p.length2 as u32) << 16; + entry |= (p.length2.ticks() as u32) << 16; entry } diff --git a/esp-hal-common/src/spi.rs b/esp-hal-common/src/spi.rs index be6b03132b9..3f5aa797478 100644 --- a/esp-hal-common/src/spi.rs +++ b/esp-hal-common/src/spi.rs @@ -15,7 +15,7 @@ //! mosi, //! miso, //! cs, -//! 100_000, +//! 100u32.kHz(), //! embedded_hal::spi::MODE_0, //! &mut peripherals.SYSTEM, //! ); @@ -24,6 +24,7 @@ use core::convert::Infallible; use embedded_hal::spi::{FullDuplex, Mode}; +use fugit::{HertzU32, RateExtU32}; use crate::{ pac::spi2::RegisterBlock, @@ -57,7 +58,7 @@ where mut mosi: MOSI, mut miso: MISO, mut cs: CS, - frequency: u32, + frequency: HertzU32, mode: Mode, system: &mut System, ) -> Self { @@ -184,15 +185,17 @@ pub trait Instance { } // taken from https://github.com/apache/incubator-nuttx/blob/8267a7618629838231256edfa666e44b5313348e/arch/risc-v/src/esp32c3/esp32c3_spi.c#L496 - fn setup(&mut self, frequency: u32) { - const APB_CLK_FREQ: u32 = 80_000_000; // TODO this might not be always true + fn setup(&mut self, frequency: HertzU32) { + // FIXME: this might not be always true + let apb_clk_freq: HertzU32 = 80u32.MHz(); + let reg_val: u32; let duty_cycle = 128; // In HW, n, h and l fields range from 1 to 64, pre ranges from 1 to 8K. // The value written to register is one lower than the used value. - if frequency > ((APB_CLK_FREQ / 4) * 3) { + if frequency > ((apb_clk_freq / 4) * 3) { // Using APB frequency directly will give us the best result here. reg_val = 1 << 31; } else { @@ -219,7 +222,7 @@ pub trait Instance { * pre = round((APB_CLK_FREQ / n) / frequency) */ - pre = ((APB_CLK_FREQ as i32/ n) + (frequency as i32 / 2)) / frequency as i32; + pre = ((apb_clk_freq.raw() as i32/ n) + (frequency.raw() as i32 / 2)) / frequency.raw() as i32; if pre <= 0 { pre = 1; @@ -229,7 +232,7 @@ pub trait Instance { pre = 16; } - errval = (APB_CLK_FREQ as i32 / (pre as i32 * n as i32) - frequency as i32).abs(); + errval = (apb_clk_freq.raw() as i32 / (pre as i32 * n as i32) - frequency.raw() as i32).abs(); if bestn == -1 || errval <= besterr { besterr = errval; bestn = n as i32; diff --git a/esp-hal-common/src/utils/smart_leds_adapter.rs b/esp-hal-common/src/utils/smart_leds_adapter.rs index 408ef8a9d2a..ab8a24607d6 100644 --- a/esp-hal-common/src/utils/smart_leds_adapter.rs +++ b/esp-hal-common/src/utils/smart_leds_adapter.rs @@ -13,6 +13,7 @@ use core::{marker::PhantomData, slice::IterMut}; +use fugit::NanosDuration; use smart_leds_trait::{SmartLedsWrite, RGB8}; #[cfg(any(feature = "esp32", feature = "esp32s2"))] @@ -42,10 +43,14 @@ const SK68XX_T0L_NS: u32 = SK68XX_CODE_PERIOD - SK68XX_T0H_NS; const SK68XX_T1H_NS: u32 = 640; const SK68XX_T1L_NS: u32 = SK68XX_CODE_PERIOD - SK68XX_T1H_NS; -const SK68XX_T0H_CYCLES: u16 = ((SK68XX_T0H_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500) as u16; -const SK68XX_T0L_CYCLES: u16 = ((SK68XX_T0L_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500) as u16; -const SK68XX_T1H_CYCLES: u16 = ((SK68XX_T1H_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500) as u16; -const SK68XX_T1L_CYCLES: u16 = ((SK68XX_T1L_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500) as u16; +const SK68XX_T0H_CYCLES: NanosDuration = + NanosDuration::::from_ticks((SK68XX_T0H_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500); +const SK68XX_T0L_CYCLES: NanosDuration = + NanosDuration::::from_ticks((SK68XX_T0L_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500); +const SK68XX_T1H_CYCLES: NanosDuration = + NanosDuration::::from_ticks((SK68XX_T1H_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500); +const SK68XX_T1L_CYCLES: NanosDuration = + NanosDuration::::from_ticks((SK68XX_T1L_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500); /// All types of errors that can happen during the conversion and transmission /// of LED commands diff --git a/esp32-hal/Cargo.toml b/esp32-hal/Cargo.toml index 395010b2a30..f0f846cbaab 100644 --- a/esp32-hal/Cargo.toml +++ b/esp32-hal/Cargo.toml @@ -26,6 +26,7 @@ categories = [ [dependencies] bare-metal = "1.0" embedded-hal = { version = "0.2", features = ["unproven"] } +fugit = "0.3" nb = "1.0" void = { version = "1.0", default-features = false } xtensa-lx = { version = "0.7", features = ["esp32"] } diff --git a/esp32-hal/examples/i2c_display.rs b/esp32-hal/examples/i2c_display.rs index af24caa8057..cc36dbc2d3f 100644 --- a/esp32-hal/examples/i2c_display.rs +++ b/esp32-hal/examples/i2c_display.rs @@ -49,7 +49,7 @@ fn main() -> ! { peripherals.I2C0, io.pins.gpio32, io.pins.gpio33, - 100_000, + 100u32.kHz(), &mut peripherals.DPORT, ) .unwrap(); diff --git a/esp32-hal/examples/spi_loopback.rs b/esp32-hal/examples/spi_loopback.rs index 5fceec6b59f..a22bc63c4f7 100644 --- a/esp32-hal/examples/spi_loopback.rs +++ b/esp32-hal/examples/spi_loopback.rs @@ -47,18 +47,18 @@ fn main() -> ! { mosi, miso, cs, - 100_000, + 100u32.kHz(), embedded_hal::spi::MODE_0, &mut peripherals.DPORT, ); - let delay = Delay::new(); + let mut delay = Delay::new(); loop { let mut data = [0xde, 0xca, 0xfb, 0xad]; spi.transfer(&mut data).unwrap(); writeln!(serial0, "{:x?}", data).ok(); - delay.delay(250_000); + delay.delay_ms(250u32); } } diff --git a/esp32c3-hal/Cargo.toml b/esp32c3-hal/Cargo.toml index c3d72950baf..4e3239ab720 100644 --- a/esp32c3-hal/Cargo.toml +++ b/esp32c3-hal/Cargo.toml @@ -26,9 +26,10 @@ categories = [ [dependencies] bare-metal = "1.0" embedded-hal = { version = "0.2", features = ["unproven"] } +fugit = "0.3" nb = "1.0" -r0 = "1.0.0" -riscv = "0.8.0" +r0 = "1.0" +riscv = "0.8" riscv-rt = { version = "0.8", optional = true } void = { version = "1.0", default-features = false } diff --git a/esp32c3-hal/examples/i2c_display.rs b/esp32c3-hal/examples/i2c_display.rs index 3b72e444d10..c0bf1171cd9 100644 --- a/esp32c3-hal/examples/i2c_display.rs +++ b/esp32c3-hal/examples/i2c_display.rs @@ -47,7 +47,7 @@ fn main() -> ! { peripherals.I2C0, io.pins.gpio1, io.pins.gpio2, - 100_000, + 100u32.kHz(), &mut peripherals.SYSTEM, ) .unwrap(); diff --git a/esp32c3-hal/examples/spi_loopback.rs b/esp32c3-hal/examples/spi_loopback.rs index f217a79d39e..7aa8688ac02 100644 --- a/esp32c3-hal/examples/spi_loopback.rs +++ b/esp32c3-hal/examples/spi_loopback.rs @@ -55,18 +55,18 @@ fn main() -> ! { mosi, miso, cs, - 100_000, + 100u32.kHz(), embedded_hal::spi::MODE_0, &mut peripherals.SYSTEM, ); - let delay = Delay::new(peripherals.SYSTIMER); + let mut delay = Delay::new(peripherals.SYSTIMER); loop { let mut data = [0xde, 0xca, 0xfb, 0xad]; spi.transfer(&mut data).unwrap(); writeln!(serial0, "{:x?}", data).ok(); - delay.delay(250_000); + delay.delay_ms(250u32); } } diff --git a/esp32s2-hal/Cargo.toml b/esp32s2-hal/Cargo.toml index 74989681f8b..76b2002aa87 100644 --- a/esp32s2-hal/Cargo.toml +++ b/esp32s2-hal/Cargo.toml @@ -26,6 +26,7 @@ categories = [ [dependencies] bare-metal = "1.0" embedded-hal = { version = "0.2", features = ["unproven"] } +fugit = "0.3" nb = "1.0" void = { version = "1.0", default-features = false } xtensa-lx = { version = "0.7", features = ["esp32s2"] } diff --git a/esp32s2-hal/examples/i2c_display.rs b/esp32s2-hal/examples/i2c_display.rs index 9bcaf9df39c..83eab78ba8f 100644 --- a/esp32s2-hal/examples/i2c_display.rs +++ b/esp32s2-hal/examples/i2c_display.rs @@ -49,7 +49,7 @@ fn main() -> ! { peripherals.I2C0, io.pins.gpio35, io.pins.gpio36, - 100_000, + 100u32.kHz(), &mut peripherals.SYSTEM, ) .unwrap(); diff --git a/esp32s2-hal/examples/spi_loopback.rs b/esp32s2-hal/examples/spi_loopback.rs index 2dbace3cecf..f12ab252190 100644 --- a/esp32s2-hal/examples/spi_loopback.rs +++ b/esp32s2-hal/examples/spi_loopback.rs @@ -47,18 +47,18 @@ fn main() -> ! { mosi, miso, cs, - 100_000, + 100u32.kHz(), embedded_hal::spi::MODE_0, &mut peripherals.SYSTEM, ); - let delay = Delay::new(); + let mut delay = Delay::new(); loop { let mut data = [0xde, 0xca, 0xfb, 0xad]; spi.transfer(&mut data).unwrap(); writeln!(serial0, "{:x?}", data).ok(); - delay.delay(250_000); + delay.delay_ms(250u32); } } diff --git a/esp32s3-hal/Cargo.toml b/esp32s3-hal/Cargo.toml index b71fd17d8f9..3bc894c1070 100644 --- a/esp32s3-hal/Cargo.toml +++ b/esp32s3-hal/Cargo.toml @@ -26,6 +26,7 @@ categories = [ [dependencies] bare-metal = "1.0" embedded-hal = { version = "0.2", features = ["unproven"] } +fugit = "0.3" nb = "1.0" void = { version = "1.0", default-features = false } xtensa-lx = { version = "0.7", features = ["esp32s3"] } diff --git a/esp32s3-hal/examples/i2c_display.rs b/esp32s3-hal/examples/i2c_display.rs index 86c4063a6bd..e7ea8d6ef7d 100644 --- a/esp32s3-hal/examples/i2c_display.rs +++ b/esp32s3-hal/examples/i2c_display.rs @@ -49,7 +49,7 @@ fn main() -> ! { peripherals.I2C0, io.pins.gpio1, io.pins.gpio2, - 100_000, + 100u32.kHz(), &mut peripherals.SYSTEM, ) .unwrap(); diff --git a/esp32s3-hal/examples/spi_loopback.rs b/esp32s3-hal/examples/spi_loopback.rs index 7eb8de26150..157861f4d5e 100644 --- a/esp32s3-hal/examples/spi_loopback.rs +++ b/esp32s3-hal/examples/spi_loopback.rs @@ -47,18 +47,18 @@ fn main() -> ! { mosi, miso, cs, - 100_000, + 100u32.kHz(), embedded_hal::spi::MODE_0, &mut peripherals.SYSTEM, ); - let delay = Delay::new(); + let mut delay = Delay::new(); loop { let mut data = [0xde, 0xca, 0xfb, 0xad]; spi.transfer(&mut data).unwrap(); writeln!(serial0, "{:x?}", data).ok(); - delay.delay(250_000); + delay.delay_ms(250u32); } }