Add a minimal HAL crate for the ESP32-C3 with a serial example
This commit is contained in:
parent
e4052593de
commit
64d9430d84
7
esp32c3-hal/.cargo/config.toml
Normal file
7
esp32c3-hal/.cargo/config.toml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
[target.riscv32imc-unknown-none-elf]
|
||||||
|
rustflags = [
|
||||||
|
"-C", "link-arg=-Tesp32c3-link.x",
|
||||||
|
]
|
||||||
|
|
||||||
|
[build]
|
||||||
|
target = "riscv32imc-unknown-none-elf"
|
||||||
26
esp32c3-hal/Cargo.toml
Normal file
26
esp32c3-hal/Cargo.toml
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
[package]
|
||||||
|
name = "esp32c3-hal"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bare-metal = "1.0"
|
||||||
|
embedded-hal = { version = "0.2", features = ["unproven"] }
|
||||||
|
nb = "1.0"
|
||||||
|
riscv = "0.7"
|
||||||
|
void = { version = "1.0", default-features = false }
|
||||||
|
|
||||||
|
[dependencies.esp32c3]
|
||||||
|
path = "../../esp-pacs/esp32c3"
|
||||||
|
|
||||||
|
[dependencies.riscv-rt]
|
||||||
|
git = "https://github.com/MabezDev/riscv-rt"
|
||||||
|
rev = "6b55e4aa3895924e31bcd151f2f0ab840836fa07"
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
panic-halt = "0.2"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["rt"]
|
||||||
|
rt = ["esp32c3/rt", "riscv-rt"]
|
||||||
1
esp32c3-hal/README.md
Normal file
1
esp32c3-hal/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# esp32c3-hal
|
||||||
16
esp32c3-hal/build.rs
Normal file
16
esp32c3-hal/build.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
use std::{env, fs::File, io::Write, path::PathBuf};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Put the linker script somewhere the linker can find it
|
||||||
|
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||||
|
File::create(out.join("memory.x"))
|
||||||
|
.unwrap()
|
||||||
|
.write_all(include_bytes!("esp32c3-memory.x"))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
println!("cargo:rustc-link-search={}", out.display());
|
||||||
|
|
||||||
|
// Only re-run the build script when memory.x is changed,
|
||||||
|
// instead of when any part of the source code changes.
|
||||||
|
println!("cargo:rerun-if-changed=memory.x");
|
||||||
|
}
|
||||||
2
esp32c3-hal/esp32c3-link.x
Normal file
2
esp32c3-hal/esp32c3-link.x
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
INCLUDE esp32c3-memory.x
|
||||||
|
INCLUDE link.x
|
||||||
15
esp32c3-hal/esp32c3-memory.x
Normal file
15
esp32c3-hal/esp32c3-memory.x
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
/* 400K of on soc RAM, 16K reserved for cache */
|
||||||
|
ICACHE : ORIGIN = 0x4037C000, LENGTH = 0x4000
|
||||||
|
IRAM : ORIGIN = 0x4037C000 + 0x4000, LENGTH = 400K - 0x4000
|
||||||
|
/* 384K of on soc ROM */
|
||||||
|
IROM : ORIGIN = 0x42000020, LENGTH = 0x60000
|
||||||
|
}
|
||||||
|
|
||||||
|
REGION_ALIAS("REGION_TEXT", IRAM);
|
||||||
|
REGION_ALIAS("REGION_RODATA", IRAM);
|
||||||
|
REGION_ALIAS("REGION_DATA", IRAM);
|
||||||
|
REGION_ALIAS("REGION_BSS", IRAM);
|
||||||
|
REGION_ALIAS("REGION_HEAP", IRAM);
|
||||||
|
REGION_ALIAS("REGION_STACK", IRAM);
|
||||||
29
esp32c3-hal/examples/serial.rs
Normal file
29
esp32c3-hal/examples/serial.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use core::fmt::Write;
|
||||||
|
|
||||||
|
use esp32c3_hal::{pac, prelude::*, RtcCntl, Serial, Timer};
|
||||||
|
use nb::block;
|
||||||
|
use panic_halt as _;
|
||||||
|
use riscv_rt::entry;
|
||||||
|
|
||||||
|
#[entry]
|
||||||
|
fn main() -> ! {
|
||||||
|
let peripherals = pac::Peripherals::take().unwrap();
|
||||||
|
|
||||||
|
let rtc_cntl = RtcCntl::new(peripherals.RTC_CNTL);
|
||||||
|
let mut timer0 = Timer::new(peripherals.TIMG0);
|
||||||
|
let mut serial0 = Serial::new(peripherals.UART0).unwrap();
|
||||||
|
|
||||||
|
rtc_cntl.set_super_wdt_enable(false);
|
||||||
|
rtc_cntl.set_wdt_enable(false);
|
||||||
|
timer0.disable();
|
||||||
|
|
||||||
|
timer0.start(10_000_000u64);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
writeln!(serial0, "Hello world!").unwrap();
|
||||||
|
block!(timer0.wait()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
13
esp32c3-hal/src/lib.rs
Normal file
13
esp32c3-hal/src/lib.rs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#![no_std]
|
||||||
|
|
||||||
|
pub use embedded_hal as ehal;
|
||||||
|
pub use esp32c3 as pac;
|
||||||
|
|
||||||
|
pub mod prelude;
|
||||||
|
pub mod rtc_cntl;
|
||||||
|
pub mod serial;
|
||||||
|
pub mod timer;
|
||||||
|
|
||||||
|
pub use rtc_cntl::RtcCntl;
|
||||||
|
pub use serial::Serial;
|
||||||
|
pub use timer::Timer;
|
||||||
9
esp32c3-hal/src/prelude.rs
Normal file
9
esp32c3-hal/src/prelude.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
pub use embedded_hal::{
|
||||||
|
digital::v2::{
|
||||||
|
InputPin as _,
|
||||||
|
OutputPin as _,
|
||||||
|
StatefulOutputPin as _,
|
||||||
|
ToggleableOutputPin as _,
|
||||||
|
},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
47
esp32c3-hal/src/rtc_cntl.rs
Normal file
47
esp32c3-hal/src/rtc_cntl.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
use crate::pac::RTC_CNTL;
|
||||||
|
|
||||||
|
pub struct RtcCntl {
|
||||||
|
rtc_cntl: RTC_CNTL,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RtcCntl {
|
||||||
|
pub fn new(rtc_cntl: RTC_CNTL) -> Self {
|
||||||
|
Self { rtc_cntl }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_super_wdt_enable(&self, enable: bool) {
|
||||||
|
self.set_swd_write_protection(false);
|
||||||
|
|
||||||
|
self.rtc_cntl
|
||||||
|
.rtc_swd_conf
|
||||||
|
.write(|w| w.swd_auto_feed_en().bit(!enable));
|
||||||
|
|
||||||
|
self.set_swd_write_protection(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_swd_write_protection(&self, enable: bool) {
|
||||||
|
let wkey = if enable { 0u32 } else { 0x8F1D_312A };
|
||||||
|
|
||||||
|
self.rtc_cntl
|
||||||
|
.rtc_swd_wprotect
|
||||||
|
.write(|w| unsafe { w.swd_wkey().bits(wkey) });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_wdt_enable(&self, enable: bool) {
|
||||||
|
self.set_wdt_write_protection(false);
|
||||||
|
|
||||||
|
self.rtc_cntl
|
||||||
|
.rtc_wdtconfig0
|
||||||
|
.write(|w| w.wdt_en().bit(enable));
|
||||||
|
|
||||||
|
self.set_wdt_write_protection(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_wdt_write_protection(&self, enable: bool) {
|
||||||
|
let wkey = if enable { 0u32 } else { 0x50D8_3AA1 };
|
||||||
|
|
||||||
|
self.rtc_cntl
|
||||||
|
.rtc_wdtwprotect
|
||||||
|
.write(|w| unsafe { w.wdt_wkey().bits(wkey) });
|
||||||
|
}
|
||||||
|
}
|
||||||
171
esp32c3-hal/src/serial.rs
Normal file
171
esp32c3-hal/src/serial.rs
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
//! UART Functionality (UART)
|
||||||
|
//!
|
||||||
|
//! Reference: ESP32-C3 TRM v0.3 Section 20 (as TRM)
|
||||||
|
//!
|
||||||
|
//! The ESP32-C3 has two identical UART groups UART0 and UART1.
|
||||||
|
//!
|
||||||
|
//! TODO:
|
||||||
|
//! - Interrupt support
|
||||||
|
|
||||||
|
use embedded_hal::serial::{Read, Write};
|
||||||
|
|
||||||
|
use crate::pac::{uart0::RegisterBlock, UART0, UART1};
|
||||||
|
|
||||||
|
const UART_FIFO_SIZE: u16 = 128;
|
||||||
|
|
||||||
|
/// UART-specific errors
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Error {}
|
||||||
|
|
||||||
|
/// UART peripheral (UART)
|
||||||
|
pub struct Serial<T> {
|
||||||
|
uart: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> Serial<T> {
|
||||||
|
pub fn new(uart: T) -> Result<Self, Error> {
|
||||||
|
let mut serial = Serial { uart };
|
||||||
|
serial.uart.disable_rx_interrupts();
|
||||||
|
serial.uart.disable_tx_interrupts();
|
||||||
|
Ok(serial)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Instance {
|
||||||
|
/// Return registerblock of uart instance as if it were UART0
|
||||||
|
fn as_uart0(&self) -> &RegisterBlock;
|
||||||
|
|
||||||
|
/// Clear and disable all tx-related interrupts
|
||||||
|
fn disable_tx_interrupts(&mut self) {
|
||||||
|
// Disable UART TX interrupts
|
||||||
|
self.as_uart0().int_clr.write(|w| {
|
||||||
|
w.txfifo_empty_int_clr()
|
||||||
|
.set_bit()
|
||||||
|
.tx_brk_done_int_clr()
|
||||||
|
.set_bit()
|
||||||
|
.tx_brk_idle_done_int_clr()
|
||||||
|
.set_bit()
|
||||||
|
.tx_done_int_clr()
|
||||||
|
.set_bit()
|
||||||
|
});
|
||||||
|
|
||||||
|
self.as_uart0().int_ena.write(|w| {
|
||||||
|
w.txfifo_empty_int_ena()
|
||||||
|
.clear_bit()
|
||||||
|
.tx_brk_done_int_ena()
|
||||||
|
.clear_bit()
|
||||||
|
.tx_brk_idle_done_int_ena()
|
||||||
|
.clear_bit()
|
||||||
|
.tx_done_int_ena()
|
||||||
|
.clear_bit()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clear and disable all rx-related interrupts
|
||||||
|
fn disable_rx_interrupts(&mut self) {
|
||||||
|
// Disable UART RX interrupts
|
||||||
|
self.as_uart0().int_clr.write(|w| {
|
||||||
|
w.rxfifo_full_int_clr()
|
||||||
|
.set_bit()
|
||||||
|
.rxfifo_ovf_int_clr()
|
||||||
|
.set_bit()
|
||||||
|
.rxfifo_tout_int_clr()
|
||||||
|
.set_bit()
|
||||||
|
});
|
||||||
|
|
||||||
|
self.as_uart0().int_ena.write(|w| {
|
||||||
|
w.rxfifo_full_int_ena()
|
||||||
|
.clear_bit()
|
||||||
|
.rxfifo_ovf_int_ena()
|
||||||
|
.clear_bit()
|
||||||
|
.rxfifo_tout_int_ena()
|
||||||
|
.clear_bit()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the number of occupied entries in the tx fifo buffer
|
||||||
|
fn get_tx_fifo_count(&mut self) -> u16 {
|
||||||
|
self.as_uart0().status.read().txfifo_cnt().bits()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the number of occupied entries in the rx fifo buffer
|
||||||
|
fn get_rx_fifo_count(&mut self) -> u16 {
|
||||||
|
self.as_uart0().status.read().rxfifo_cnt().bits()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the UART TX statemachine is is idle
|
||||||
|
fn is_tx_idle(&mut self) -> bool {
|
||||||
|
self.as_uart0().fsm_status.read().st_utx_out().bits() == 0x0u8
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if the UART RX statemachine is is idle
|
||||||
|
fn is_rx_idle(&mut self) -> bool {
|
||||||
|
self.as_uart0().fsm_status.read().st_urx_out().bits() == 0x0u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write half of a serial interface
|
||||||
|
impl<T: Instance> Write<u8> for Serial<T> {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
/// Writes a single word to the serial interface
|
||||||
|
fn write(&mut self, word: u8) -> nb::Result<(), Self::Error> {
|
||||||
|
if self.uart.get_tx_fifo_count() >= UART_FIFO_SIZE {
|
||||||
|
Err(nb::Error::WouldBlock)
|
||||||
|
} else {
|
||||||
|
self.uart
|
||||||
|
.as_uart0()
|
||||||
|
.fifo
|
||||||
|
.write(|w| unsafe { w.rxfifo_rd_byte().bits(word) });
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ensures that none of the previously written words are still buffered
|
||||||
|
fn flush(&mut self) -> nb::Result<(), Self::Error> {
|
||||||
|
if self.uart.is_tx_idle() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(nb::Error::WouldBlock)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write half of a serial interface
|
||||||
|
impl<T: Instance> Read<u8> for Serial<T> {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
/// Reads a single word from the serial interface
|
||||||
|
fn read(&mut self) -> nb::Result<u8, Self::Error> {
|
||||||
|
if self.uart.get_rx_fifo_count() > 0 {
|
||||||
|
Ok(self.uart.as_uart0().fifo.read().rxfifo_rd_byte().bits())
|
||||||
|
} else {
|
||||||
|
Err(nb::Error::WouldBlock)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> core::fmt::Write for Serial<T> {
|
||||||
|
fn write_str(&mut self, s: &str) -> core::fmt::Result {
|
||||||
|
s.as_bytes()
|
||||||
|
.iter()
|
||||||
|
.try_for_each(|c| nb::block!(self.write(*c)))
|
||||||
|
.map_err(|_| core::fmt::Error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Specific instance implementation for the UART0 peripheral
|
||||||
|
impl Instance for UART0 {
|
||||||
|
#[inline(always)]
|
||||||
|
fn as_uart0(&self) -> &RegisterBlock {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Specific instance implementation for the UART1 peripheral
|
||||||
|
impl Instance for UART1 {
|
||||||
|
#[inline(always)]
|
||||||
|
fn as_uart0(&self) -> &RegisterBlock {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
200
esp32c3-hal/src/timer.rs
Normal file
200
esp32c3-hal/src/timer.rs
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
use embedded_hal::{
|
||||||
|
timer::{Cancel, CountDown, Periodic},
|
||||||
|
watchdog::WatchdogDisable,
|
||||||
|
};
|
||||||
|
use void::Void;
|
||||||
|
|
||||||
|
use crate::pac::{timg0::RegisterBlock, TIMG0, TIMG1};
|
||||||
|
|
||||||
|
pub struct Timer<T> {
|
||||||
|
timg: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Error {
|
||||||
|
/// Report that the timer is active and certain management
|
||||||
|
/// operations cannot be performed safely
|
||||||
|
TimerActive,
|
||||||
|
/// Report that the timer is inactive and thus not
|
||||||
|
/// ever reaching any potentially configured alarm value
|
||||||
|
TimerInactive,
|
||||||
|
/// Report that the alarm functionality is disabled
|
||||||
|
AlarmInactive,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Timer<T>
|
||||||
|
where
|
||||||
|
T: Instance,
|
||||||
|
{
|
||||||
|
pub fn new(timg: T) -> Self {
|
||||||
|
Self { timg }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Instance {
|
||||||
|
fn as_timg0(&self) -> &RegisterBlock;
|
||||||
|
|
||||||
|
fn reset_counter(&mut self) {
|
||||||
|
self.as_timg0()
|
||||||
|
.t0loadlo
|
||||||
|
.write(|w| unsafe { w.t0_load_lo().bits(0) });
|
||||||
|
|
||||||
|
self.as_timg0()
|
||||||
|
.t0loadhi
|
||||||
|
.write(|w| unsafe { w.t0_load_hi().bits(0) });
|
||||||
|
|
||||||
|
self.as_timg0()
|
||||||
|
.t0load
|
||||||
|
.write(|w| unsafe { w.t0_load().bits(1) });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_counter_active(&mut self, state: bool) {
|
||||||
|
self.as_timg0().t0config.modify(|_, w| w.t0_en().bit(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_counter_active(&mut self) -> bool {
|
||||||
|
self.as_timg0().t0config.read().t0_en().bit_is_set()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_counter_decrementing(&mut self, decrementing: bool) {
|
||||||
|
self.as_timg0()
|
||||||
|
.t0config
|
||||||
|
.modify(|_, w| w.t0_increase().bit(!decrementing));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_auto_reload(&mut self, auto_reload: bool) {
|
||||||
|
self.as_timg0()
|
||||||
|
.t0config
|
||||||
|
.modify(|_, w| w.t0_autoreload().bit(auto_reload));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_alarm_active(&mut self, state: bool) {
|
||||||
|
self.as_timg0()
|
||||||
|
.t0config
|
||||||
|
.modify(|_, w| w.t0_alarm_en().bit(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_alarm_active(&mut self) -> bool {
|
||||||
|
self.as_timg0().t0config.read().t0_alarm_en().bit_is_set()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_alarm_value(&mut self, value: u64) {
|
||||||
|
let value = value & 0x3F_FFFF_FFFF_FFFF;
|
||||||
|
let high = (value >> 32) as u32;
|
||||||
|
let low = (value & 0xFFFF_FFFF) as u32;
|
||||||
|
|
||||||
|
self.as_timg0()
|
||||||
|
.t0alarmlo
|
||||||
|
.write(|w| unsafe { w.t0_alarm_lo().bits(low) });
|
||||||
|
self.as_timg0()
|
||||||
|
.t0alarmhi
|
||||||
|
.write(|w| unsafe { w.t0_alarm_hi().bits(high) });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_wdt_enabled(&mut self, enabled: bool) {
|
||||||
|
self.as_timg0()
|
||||||
|
.wdtwprotect
|
||||||
|
.write(|w| unsafe { w.wdt_wkey().bits(0u32) });
|
||||||
|
|
||||||
|
self.as_timg0()
|
||||||
|
.wdtconfig0
|
||||||
|
.write(|w| w.wdt_en().bit(enabled));
|
||||||
|
|
||||||
|
self.as_timg0()
|
||||||
|
.wdtwprotect
|
||||||
|
.write(|w| unsafe { w.wdt_wkey().bits(0x50D8_3AA1u32) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> CountDown for Timer<T>
|
||||||
|
where
|
||||||
|
T: Instance,
|
||||||
|
{
|
||||||
|
type Time = u64;
|
||||||
|
|
||||||
|
fn start<Time>(&mut self, timeout: Time)
|
||||||
|
where
|
||||||
|
Time: Into<u64>,
|
||||||
|
{
|
||||||
|
self.timg.set_counter_active(false);
|
||||||
|
self.timg.set_alarm_active(false);
|
||||||
|
|
||||||
|
self.timg.reset_counter();
|
||||||
|
self.timg.load_alarm_value(timeout.into());
|
||||||
|
|
||||||
|
self.timg.set_counter_decrementing(false);
|
||||||
|
self.timg.set_auto_reload(true);
|
||||||
|
self.timg.set_counter_active(true);
|
||||||
|
self.timg.set_alarm_active(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wait(&mut self) -> nb::Result<(), Void> {
|
||||||
|
if !self.timg.is_counter_active() {
|
||||||
|
panic!("Called wait on an inactive timer!");
|
||||||
|
}
|
||||||
|
|
||||||
|
let int_raw_is_clear = self
|
||||||
|
.timg
|
||||||
|
.as_timg0()
|
||||||
|
.int_raw_timg
|
||||||
|
.read()
|
||||||
|
.t0_int_raw()
|
||||||
|
.bit_is_clear();
|
||||||
|
|
||||||
|
if int_raw_is_clear {
|
||||||
|
Err(nb::Error::WouldBlock)
|
||||||
|
} else {
|
||||||
|
self.timg
|
||||||
|
.as_timg0()
|
||||||
|
.int_clr_timg
|
||||||
|
.write(|w| w.t0_int_clr().set_bit());
|
||||||
|
|
||||||
|
self.timg.set_alarm_active(true);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Periodic for Timer<T> where T: Instance {}
|
||||||
|
|
||||||
|
impl<T> Cancel for Timer<T>
|
||||||
|
where
|
||||||
|
T: Instance,
|
||||||
|
{
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn cancel(&mut self) -> Result<(), Error> {
|
||||||
|
if !self.timg.is_counter_active() {
|
||||||
|
return Err(Error::TimerInactive);
|
||||||
|
} else if !self.timg.is_alarm_active() {
|
||||||
|
return Err(Error::AlarmInactive);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.timg.set_counter_active(false);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> WatchdogDisable for Timer<T>
|
||||||
|
where
|
||||||
|
T: Instance,
|
||||||
|
{
|
||||||
|
fn disable(&mut self) {
|
||||||
|
self.timg.set_wdt_enabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instance for TIMG0 {
|
||||||
|
#[inline(always)]
|
||||||
|
fn as_timg0(&self) -> &RegisterBlock {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Instance for TIMG1 {
|
||||||
|
#[inline(always)]
|
||||||
|
fn as_timg0(&self) -> &RegisterBlock {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user