Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/time types #64

Merged
merged 4 commits into from
May 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions esp-hal-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
14 changes: 9 additions & 5 deletions esp-hal-common/src/delay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {}
}
Expand Down Expand Up @@ -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
///
Expand All @@ -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);
}
}
Expand Down
29 changes: 17 additions & 12 deletions esp-hal-common/src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use core::convert::TryInto;

use embedded_hal::blocking::i2c::*;
use fugit::HertzU32;

use crate::{
gpio::{InputPin, OutputPin},
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -218,7 +219,7 @@ where
i2c: T,
mut sda: SDA,
mut scl: SCL,
frequency: u32,
frequency: HertzU32,
system: &mut System,
) -> Result<Self, SetupError> {
enable_peripheral(&i2c, system);
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -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)?;
}
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions esp-hal-common/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ pub use embedded_hal::{
},
prelude::*,
};
pub use fugit::{ExtU32 as _, ExtU64 as _, RateExtU32 as _, RateExtU64 as _};
10 changes: 6 additions & 4 deletions esp-hal-common/src/pulse_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@

use core::slice::Iter;

use fugit::NanosDurationU32;

use crate::{
gpio::{types::OutputSignal, OutputPin},
pac::RMT,
Expand Down Expand Up @@ -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
Expand All @@ -185,7 +187,7 @@ impl From<PulseCode> 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 {
Expand All @@ -202,7 +204,7 @@ impl From<PulseCode> for u32 {
}

// The length2 value resides in bits [30:16]
entry |= (p.length2 as u32) << 16;
entry |= (p.length2.ticks() as u32) << 16;

entry
}
Expand Down
17 changes: 10 additions & 7 deletions esp-hal-common/src/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
//! mosi,
//! miso,
//! cs,
//! 100_000,
//! 100u32.kHz(),
//! embedded_hal::spi::MODE_0,
//! &mut peripherals.SYSTEM,
//! );
Expand All @@ -24,6 +24,7 @@
use core::convert::Infallible;

use embedded_hal::spi::{FullDuplex, Mode};
use fugit::{HertzU32, RateExtU32};

use crate::{
pac::spi2::RegisterBlock,
Expand Down Expand Up @@ -57,7 +58,7 @@ where
mut mosi: MOSI,
mut miso: MISO,
mut cs: CS,
frequency: u32,
frequency: HertzU32,
mode: Mode,
system: &mut System,
) -> Self {
Expand Down Expand Up @@ -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 {
Expand All @@ -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;
Expand All @@ -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;
Expand Down
13 changes: 9 additions & 4 deletions esp-hal-common/src/utils/smart_leds_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))]
Expand Down Expand Up @@ -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<u32> =
NanosDuration::<u32>::from_ticks((SK68XX_T0H_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500);
const SK68XX_T0L_CYCLES: NanosDuration<u32> =
NanosDuration::<u32>::from_ticks((SK68XX_T0L_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500);
const SK68XX_T1H_CYCLES: NanosDuration<u32> =
NanosDuration::<u32>::from_ticks((SK68XX_T1H_NS * (SOURCE_CLK_FREQ / 1_000_000)) / 500);
const SK68XX_T1L_CYCLES: NanosDuration<u32> =
NanosDuration::<u32>::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
Expand Down
1 change: 1 addition & 0 deletions esp32-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
2 changes: 1 addition & 1 deletion esp32-hal/examples/i2c_display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fn main() -> ! {
peripherals.I2C0,
io.pins.gpio32,
io.pins.gpio33,
100_000,
100u32.kHz(),
&mut peripherals.DPORT,
)
.unwrap();
Expand Down
6 changes: 3 additions & 3 deletions esp32-hal/examples/spi_loopback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
5 changes: 3 additions & 2 deletions esp32c3-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }

Expand Down
2 changes: 1 addition & 1 deletion esp32c3-hal/examples/i2c_display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ fn main() -> ! {
peripherals.I2C0,
io.pins.gpio1,
io.pins.gpio2,
100_000,
100u32.kHz(),
&mut peripherals.SYSTEM,
)
.unwrap();
Expand Down
6 changes: 3 additions & 3 deletions esp32c3-hal/examples/spi_loopback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
1 change: 1 addition & 0 deletions esp32s2-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
2 changes: 1 addition & 1 deletion esp32s2-hal/examples/i2c_display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ fn main() -> ! {
peripherals.I2C0,
io.pins.gpio35,
io.pins.gpio36,
100_000,
100u32.kHz(),
&mut peripherals.SYSTEM,
)
.unwrap();
Expand Down
Loading