mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-28 12:50:53 +00:00
Implement DelayMs and DelayUs traits from embedded-hal
This commit is contained in:
parent
a9cf53a001
commit
9a030cbf78
@ -10,7 +10,7 @@ The various packages in this repository may or may not build at any given time.
|
||||
|
||||
## What is working?
|
||||
|
||||
For the **ESP32** and **ESP32-C3**, the `GPIO`, `TIMG` and `UART` peripherals have (probably incomplete) implementations which are nonetheless functional. These packages include examples to demonstrate these peripherals.
|
||||
For the **ESP32** and **ESP32-C3**, the `GPIO`, `TIMG` and `UART` peripherals have (probably incomplete) implementations which are nonetheless functional. Both of the aforementioned chips also have implmented the `DelayUs` and `DelayMs` traits from `embedded-hal`. These packages include examples to demonstrate these peripherals.
|
||||
|
||||
## What is NOT working?
|
||||
|
||||
|
95
esp-hal-common/src/delay.rs
Normal file
95
esp-hal-common/src/delay.rs
Normal file
@ -0,0 +1,95 @@
|
||||
use embedded_hal::blocking::delay::{DelayMs, DelayUs};
|
||||
|
||||
pub use self::delay::Delay;
|
||||
|
||||
impl<T> DelayMs<T> for Delay
|
||||
where
|
||||
T: Into<u32>,
|
||||
{
|
||||
fn delay_ms(&mut self, ms: T) {
|
||||
for _ in 0..ms.into() {
|
||||
self.delay_us(1000u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DelayUs<T> for Delay
|
||||
where
|
||||
T: Into<u32>,
|
||||
{
|
||||
fn delay_us(&mut self, us: T) {
|
||||
self.delay(us.into());
|
||||
}
|
||||
}
|
||||
|
||||
// The delay implementation for RISC-V devices (ESP32-C3) uses the `SYSTIMER`
|
||||
// peripheral, as unfortunately this device does NOT implement the `mcycle` CSR.
|
||||
#[cfg(feature = "esp32c3")]
|
||||
mod delay {
|
||||
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;
|
||||
|
||||
pub struct Delay {
|
||||
systimer: SYSTIMER,
|
||||
}
|
||||
|
||||
impl Delay {
|
||||
pub fn new(systimer: SYSTIMER) -> Self {
|
||||
Self { systimer }
|
||||
}
|
||||
|
||||
pub fn delay(&self, us: u32) {
|
||||
let t0 = self.unit0_value();
|
||||
let clocks = (us as u64 * CLK_FREQ_HZ) / 1_000_000;
|
||||
|
||||
while self.unit0_value().wrapping_sub(t0) <= clocks {}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn unit0_value(&self) -> u64 {
|
||||
self.systimer
|
||||
.unit0_op
|
||||
.write(|w| w.timer_unit0_update().set_bit());
|
||||
|
||||
while !self
|
||||
.systimer
|
||||
.unit0_op
|
||||
.read()
|
||||
.timer_unit0_value_valid()
|
||||
.bit_is_set()
|
||||
{}
|
||||
|
||||
let value_lo = self.systimer.unit0_value_lo.read().bits();
|
||||
let value_hi = self.systimer.unit0_value_hi.read().bits();
|
||||
|
||||
((value_hi as u64) << 32) | value_lo as u64
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The delay implementation for Xtensa devices (ESP32, ESP32-S2, ESP32-S3) uses
|
||||
// the built-in timer from the `xtensa_lx` crate.
|
||||
#[cfg(not(feature = "esp32c3"))]
|
||||
mod delay {
|
||||
// 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;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Delay;
|
||||
|
||||
impl Delay {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
}
|
||||
|
||||
pub fn delay(&self, us: u32) {
|
||||
let clocks = (us as u64 * CLK_FREQ_HZ) / 1_000_000;
|
||||
xtensa_lx::timer::delay(clocks as u32);
|
||||
}
|
||||
}
|
||||
}
|
@ -9,11 +9,13 @@ pub use esp32s2_pac as pac;
|
||||
#[cfg(feature = "esp32s3")]
|
||||
pub use esp32s3_pac as pac;
|
||||
|
||||
pub mod delay;
|
||||
pub mod gpio;
|
||||
pub mod prelude;
|
||||
pub mod serial;
|
||||
pub mod timer;
|
||||
|
||||
pub use delay::Delay;
|
||||
pub use gpio::*;
|
||||
pub use serial::Serial;
|
||||
pub use timer::Timer;
|
||||
|
@ -1,4 +1,5 @@
|
||||
pub use embedded_hal::{
|
||||
blocking::delay::{DelayMs as _, DelayUs as _},
|
||||
digital::v2::{
|
||||
InputPin as _,
|
||||
OutputPin as _,
|
||||
|
@ -1,8 +1,7 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32_hal::{gpio::IO, pac::Peripherals, prelude::*, Timer};
|
||||
use nb::block;
|
||||
use esp32_hal::{gpio::IO, pac::Peripherals, prelude::*, Delay, Timer};
|
||||
use panic_halt as _;
|
||||
use xtensa_lx_rt::entry;
|
||||
|
||||
@ -10,18 +9,23 @@ use xtensa_lx_rt::entry;
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take().unwrap();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let mut led = io.pins.gpio15.into_push_pull_output();
|
||||
// Disable the TIMG watchdog timer.
|
||||
let mut timer0 = Timer::new(peripherals.TIMG0);
|
||||
|
||||
// Disable watchdog timer
|
||||
timer0.disable();
|
||||
|
||||
// Set GPIO15 as an output, and set its state high initially.
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let mut led = io.pins.gpio15.into_push_pull_output();
|
||||
|
||||
led.set_high().unwrap();
|
||||
timer0.start(10_000_000u64);
|
||||
|
||||
// Initialize the Delay peripheral, and use it to toggle the LED state in a
|
||||
// loop.
|
||||
let mut delay = Delay::new();
|
||||
|
||||
loop {
|
||||
led.toggle().unwrap();
|
||||
block!(timer0.wait()).unwrap();
|
||||
delay.delay_ms(500u32);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![no_std]
|
||||
|
||||
pub use embedded_hal as ehal;
|
||||
pub use esp_hal_common::{pac, prelude, Serial, Timer};
|
||||
pub use esp_hal_common::{pac, prelude, Delay, Serial, Timer};
|
||||
|
||||
pub use self::gpio::IO;
|
||||
|
||||
@ -45,8 +45,9 @@ pub unsafe extern "C" fn ESP32Reset() -> ! {
|
||||
xtensa_lx_rt::Reset();
|
||||
}
|
||||
|
||||
/// The esp32 has a first stage bootloader that handles loading program data into the right place
|
||||
/// therefore we skip loading it again.
|
||||
/// The ESP32 has a first stage bootloader that handles loading program data
|
||||
/// into the right place therefore we skip loading it again.
|
||||
#[doc(hidden)]
|
||||
#[no_mangle]
|
||||
#[rustfmt::skip]
|
||||
pub extern "Rust" fn __init_data() -> bool {
|
||||
|
@ -1,8 +1,7 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use esp32c3_hal::{gpio::IO, pac::Peripherals, prelude::*, RtcCntl, Timer};
|
||||
use nb::block;
|
||||
use esp32c3_hal::{gpio::IO, pac::Peripherals, prelude::*, Delay, RtcCntl, Timer};
|
||||
use panic_halt as _;
|
||||
use riscv_rt::entry;
|
||||
|
||||
@ -10,23 +9,29 @@ use riscv_rt::entry;
|
||||
fn main() -> ! {
|
||||
let peripherals = Peripherals::take().unwrap();
|
||||
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let mut led = io.pins.gpio5.into_push_pull_output();
|
||||
// Disable the watchdog timers. For the ESP32-C3, this includes the Super WDT,
|
||||
// the RTC WDT, and the TIMG WDTs.
|
||||
let rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL);
|
||||
let mut timer0 = Timer::new(peripherals.TIMG0);
|
||||
let mut timer1 = Timer::new(peripherals.TIMG1);
|
||||
|
||||
// Disable watchdog timers
|
||||
rtc_cntl.set_super_wdt_enable(false);
|
||||
rtc_cntl.set_wdt_enable(false);
|
||||
timer0.disable();
|
||||
timer1.disable();
|
||||
|
||||
// Set GPIO5 as an output, and set its state high initially.
|
||||
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
let mut led = io.pins.gpio5.into_push_pull_output();
|
||||
|
||||
led.set_high().unwrap();
|
||||
timer0.start(10_000_000u64);
|
||||
|
||||
// Initialize the Delay peripheral, and use it to toggle the LED state in a
|
||||
// loop.
|
||||
let mut delay = Delay::new(peripherals.SYSTIMER);
|
||||
|
||||
loop {
|
||||
led.toggle().unwrap();
|
||||
block!(timer0.wait()).unwrap();
|
||||
delay.delay_ms(500u32);
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![no_std]
|
||||
|
||||
pub use embedded_hal as ehal;
|
||||
pub use esp_hal_common::{pac, prelude, Serial, Timer};
|
||||
pub use esp_hal_common::{pac, prelude, Delay, Serial, Timer};
|
||||
|
||||
pub mod gpio;
|
||||
pub mod rtc_cntl;
|
||||
|
@ -1,7 +1,7 @@
|
||||
#![no_std]
|
||||
|
||||
pub use embedded_hal as ehal;
|
||||
pub use esp_hal_common::{pac, prelude, Serial, Timer};
|
||||
pub use esp_hal_common::{pac, prelude, Delay, Serial, Timer};
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn DefaultHandler(_level: u32, _interrupt: pac::Interrupt) {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#![no_std]
|
||||
|
||||
pub use embedded_hal as ehal;
|
||||
pub use esp_hal_common::{pac, prelude, Serial, Timer};
|
||||
pub use esp_hal_common::{pac, prelude, Delay, Serial, Timer};
|
||||
|
Loading…
x
Reference in New Issue
Block a user