mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-11-25 21:19:35 +01:00
Add SYSTIMER based ESP32-C3 monotonic (#972)
* add esp32c3 monotonic * fix tests
This commit is contained in:
parent
6e68a5e615
commit
805ea267a8
12 changed files with 395 additions and 9 deletions
34
ci/expected/esp32c3/monotonic.run
Normal file
34
ci/expected/esp32c3/monotonic.run
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
QEMU 8.2.0 monitor - type 'help' for more information
|
||||||
|
(qemu) q[K
|
||||||
|
ESP-ROM:esp32c3-api1-20210207
|
||||||
|
Build:Feb 7 2021
|
||||||
|
rst:0x1 (POWERON),boot:0x8 (SPI_FAST_FLASH_BOOT)
|
||||||
|
SPIWP:0xee
|
||||||
|
mode:DIO, clock div:2
|
||||||
|
load:0x3fcd5820,len:0x1714
|
||||||
|
load:0x403cc710,len:0x968
|
||||||
|
load:0x403ce710,len:0x2f9c
|
||||||
|
entry 0x403cc710
|
||||||
|
[0;32mI (0) boot: ESP-IDF v5.1.2-342-gbcf1645e44 2nd stage bootloader[0m
|
||||||
|
[0;32mI (0) boot: compile time Dec 12 2023 10:50:58[0m
|
||||||
|
[0;32mI (0) boot: chip revision: v0.3[0m
|
||||||
|
[0;32mI (0) boot.esp32c3: SPI Speed : 40MHz[0m
|
||||||
|
[0;32mI (0) boot.esp32c3: SPI Mode : SLOW READ[0m
|
||||||
|
[0;32mI (0) boot.esp32c3: SPI Flash Size : 4MB[0m
|
||||||
|
[0;32mI (0) boot: Enabling RNG early entropy source...[0m
|
||||||
|
[0;32mI (1) boot: Partition Table:[0m
|
||||||
|
[0;32mI (1) boot: ## Label Usage Type ST Offset Length[0m
|
||||||
|
[0;32mI (1) boot: 0 nvs WiFi data 01 02 00009000 00006000[0m
|
||||||
|
[0;32mI (1) boot: 1 phy_init RF data 01 01 0000f000 00001000[0m
|
||||||
|
[0;32mI (1) boot: 2 factory factory app 00 00 00010000 003f0000[0m
|
||||||
|
[0;32mI (1) boot: End of partition table[0m
|
||||||
|
[0;32mI (1) esp_image: REDACTED
|
||||||
|
[0;32mI (3) esp_image: REDACTED
|
||||||
|
[0;32mI (3) esp_image: REDACTED
|
||||||
|
[0;32mI (8) esp_image: REDACTED
|
||||||
|
[0;32mI (11) boot: Loaded app from partition at offset 0x10000[0m
|
||||||
|
[0;32mI (11) boot: Disabling RNG early entropy source...[0m
|
||||||
|
init
|
||||||
|
hello from bar
|
||||||
|
hello from baz
|
||||||
|
hello from foo
|
|
@ -1,6 +1,6 @@
|
||||||
[target.riscv32imc-unknown-none-elf]
|
[target.riscv32imc-unknown-none-elf]
|
||||||
# Real hardware
|
# Real hardware
|
||||||
#runner = "espflash flash --monitor"
|
# runner = "espflash flash --monitor"
|
||||||
|
|
||||||
# QEMU emulator
|
# QEMU emulator
|
||||||
runner = "./runner.sh"
|
runner = "./runner.sh"
|
||||||
|
@ -14,6 +14,3 @@ rustflags = [
|
||||||
]
|
]
|
||||||
|
|
||||||
target = "riscv32imc-unknown-none-elf"
|
target = "riscv32imc-unknown-none-elf"
|
||||||
|
|
||||||
[unstable]
|
|
||||||
build-std = ["core"]
|
|
||||||
|
|
78
examples/esp32c3/Cargo.lock
generated
78
examples/esp32c3/Cargo.lock
generated
|
@ -144,6 +144,15 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
|
checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "embedded-hal-async"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884"
|
||||||
|
dependencies = [
|
||||||
|
"embedded-hal 1.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "enum-as-inner"
|
name = "enum-as-inner"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -285,6 +294,7 @@ dependencies = [
|
||||||
"esp-println",
|
"esp-println",
|
||||||
"esp32c3 0.22.0",
|
"esp32c3 0.22.0",
|
||||||
"rtic",
|
"rtic",
|
||||||
|
"rtic-monotonics",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -384,6 +394,30 @@ dependencies = [
|
||||||
"gcd",
|
"gcd",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-task",
|
||||||
|
"pin-project-lite",
|
||||||
|
"pin-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gcd"
|
name = "gcd"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
|
@ -479,6 +513,18 @@ version = "1.0.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "portable-atomic"
|
name = "portable-atomic"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
@ -611,6 +657,14 @@ dependencies = [
|
||||||
"rtic-macros",
|
"rtic-macros",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rtic-common"
|
||||||
|
version = "1.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"critical-section",
|
||||||
|
"portable-atomic",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rtic-core"
|
name = "rtic-core"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -628,6 +682,30 @@ dependencies = [
|
||||||
"syn 2.0.53",
|
"syn 2.0.53",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rtic-monotonics"
|
||||||
|
version = "2.0.2"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"esp32c3 0.22.0",
|
||||||
|
"fugit",
|
||||||
|
"portable-atomic",
|
||||||
|
"riscv",
|
||||||
|
"rtic-time",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rtic-time"
|
||||||
|
version = "2.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"critical-section",
|
||||||
|
"embedded-hal 1.0.0",
|
||||||
|
"embedded-hal-async",
|
||||||
|
"fugit",
|
||||||
|
"futures-util",
|
||||||
|
"rtic-common",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.14"
|
version = "1.0.14"
|
||||||
|
|
|
@ -8,6 +8,7 @@ license = "MIT OR Apache-2.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rtic = {path = "../../rtic/"}
|
rtic = {path = "../../rtic/"}
|
||||||
|
rtic-monotonics = {path = "../../rtic-monotonics/"}
|
||||||
esp-hal = { version = "0.16.1", features = ["esp32c3", "direct-vectoring", "interrupt-preemption"] }
|
esp-hal = { version = "0.16.1", features = ["esp32c3", "direct-vectoring", "interrupt-preemption"] }
|
||||||
esp-backtrace = { version = "0.11.0", features = [
|
esp-backtrace = { version = "0.11.0", features = [
|
||||||
"esp32c3",
|
"esp32c3",
|
||||||
|
@ -21,4 +22,4 @@ esp-println = { version = "0.9.0", features = ["esp32c3", "uart"] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
test-critical-section = []
|
test-critical-section = []
|
||||||
riscv-esp32c3-backend = ["rtic/riscv-esp32c3-backend"]
|
riscv-esp32c3-backend = ["rtic/riscv-esp32c3-backend", "rtic-monotonics/esp32c3-systimer"]
|
||||||
|
|
|
@ -15,12 +15,24 @@ This crate uses the most convenient option in ``cargo-espflash`` and ``espflash`
|
||||||
|
|
||||||
## Running the crate
|
## Running the crate
|
||||||
|
|
||||||
|
Uncomment the
|
||||||
|
|
||||||
|
```runner = "espflash flash --monitor"```
|
||||||
|
|
||||||
|
line in ``.cargo/config.toml``
|
||||||
|
|
||||||
|
and comment out (or remove)
|
||||||
|
|
||||||
|
```runner = "./runner.sh"```
|
||||||
|
|
||||||
|
Now, running
|
||||||
|
|
||||||
```cargo run --example sw_and_hw --features=riscv-esp32c3-backend (--release)```
|
```cargo run --example sw_and_hw --features=riscv-esp32c3-backend (--release)```
|
||||||
|
|
||||||
should do the trick.
|
in the root of this crate should do the trick.
|
||||||
|
|
||||||
# Expected behavior
|
# Expected behavior
|
||||||
The program
|
The example ``sw_and_hw``
|
||||||
- Prints ``init``
|
- Prints ``init``
|
||||||
- Enters a high prio task
|
- Enters a high prio task
|
||||||
- During the execution of the high prio task, the button should be non-functional
|
- During the execution of the high prio task, the button should be non-functional
|
||||||
|
@ -31,3 +43,9 @@ The program
|
||||||
- Exits the low prio task
|
- Exits the low prio task
|
||||||
- Prints ``idle``
|
- Prints ``idle``
|
||||||
|
|
||||||
|
The example ``monotonic``
|
||||||
|
- Prints ``init``
|
||||||
|
- Spawns the ``foo``, ``bar``, ``baz`` tasks (because of hardware interrupt latency dispatch, the order here may vary).
|
||||||
|
- Each task prints ``hello from $TASK`` on entry
|
||||||
|
- The tasks wait for 1, 2, 3 seconds respectively
|
||||||
|
- Once the wait period is over, each task exits printing ``bye from $TASK`` (now in the proper order).
|
||||||
|
|
51
examples/esp32c3/examples/monotonic.rs
Normal file
51
examples/esp32c3/examples/monotonic.rs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#![no_main]
|
||||||
|
#![no_std]
|
||||||
|
use esp_backtrace as _;
|
||||||
|
#[rtic::app(device = esp32c3, dispatchers = [])]
|
||||||
|
mod app {
|
||||||
|
use rtic_monotonics::esp32c3::prelude::*;
|
||||||
|
esp32c3_systimer_monotonic!(Mono);
|
||||||
|
use esp_hal as _;
|
||||||
|
use esp_println::println;
|
||||||
|
|
||||||
|
#[shared]
|
||||||
|
struct Shared {}
|
||||||
|
|
||||||
|
#[local]
|
||||||
|
struct Local {}
|
||||||
|
|
||||||
|
#[init]
|
||||||
|
fn init(cx: init::Context) -> (Shared, Local) {
|
||||||
|
println!("init");
|
||||||
|
let timer = cx.device.SYSTIMER;
|
||||||
|
|
||||||
|
Mono::start(timer);
|
||||||
|
|
||||||
|
foo::spawn().unwrap();
|
||||||
|
bar::spawn().unwrap();
|
||||||
|
baz::spawn().unwrap();
|
||||||
|
|
||||||
|
(Shared {}, Local {})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[task]
|
||||||
|
async fn foo(_cx: foo::Context) {
|
||||||
|
println!("hello from foo");
|
||||||
|
Mono::delay(2_u64.secs()).await;
|
||||||
|
println!("bye from foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[task]
|
||||||
|
async fn bar(_cx: bar::Context) {
|
||||||
|
println!("hello from bar");
|
||||||
|
Mono::delay(3_u64.secs()).await;
|
||||||
|
println!("bye from bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[task]
|
||||||
|
async fn baz(_cx: baz::Context) {
|
||||||
|
println!("hello from baz");
|
||||||
|
Mono::delay(4_u64.secs()).await;
|
||||||
|
println!("bye from baz");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
#[rtic::app(device = esp32c3, dispatchers=[FROM_CPU_INTR0, FROM_CPU_INTR1])]
|
#[rtic::app(device = esp32c3, dispatchers=[FROM_CPU_INTR0, FROM_CPU_INTR1])]
|
||||||
mod app {
|
mod app {
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "nightly-2023-11-14"
|
channel = "stable"
|
||||||
components = ["rust-src"]
|
components = ["rust-src"]
|
||||||
targets = ["riscv32imc-unknown-none-elf"]
|
targets = ["riscv32imc-unknown-none-elf"]
|
||||||
|
|
|
@ -13,6 +13,9 @@ For each category, *Added*, *Changed*, *Fixed* add new entries at the top!
|
||||||
|
|
||||||
## v2.0.2 - 2024-07-05
|
## v2.0.2 - 2024-07-05
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- `SYSTIMER` based monotonic for the ESP32-C3
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fix `stm32` monotonic for timer peripherals with only two clock compare modules
|
- Fix `stm32` monotonic for timer peripherals with only two clock compare modules
|
||||||
|
|
|
@ -31,6 +31,7 @@ features = [
|
||||||
"stm32_tim4",
|
"stm32_tim4",
|
||||||
"stm32_tim5",
|
"stm32_tim5",
|
||||||
"stm32_tim15",
|
"stm32_tim15",
|
||||||
|
"esp32c3-systimer",
|
||||||
]
|
]
|
||||||
rustdoc-flags = ["--cfg", "docsrs"]
|
rustdoc-flags = ["--cfg", "docsrs"]
|
||||||
|
|
||||||
|
@ -65,6 +66,11 @@ stm32-metapac = { version = "15.0.0", optional = true }
|
||||||
# i.MX RT
|
# i.MX RT
|
||||||
imxrt-ral = { version = "0.5.3", optional = true }
|
imxrt-ral = { version = "0.5.3", optional = true }
|
||||||
|
|
||||||
|
|
||||||
|
esp32c3 = {version = "0.22.0", optional = true }
|
||||||
|
riscv = {version = "0.11.1", optional = true }
|
||||||
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
proc-macro2 = { version = "1.0.36", optional = true }
|
proc-macro2 = { version = "1.0.36", optional = true }
|
||||||
quote = { version = "1.0.15", optional = true }
|
quote = { version = "1.0.15", optional = true }
|
||||||
|
@ -104,6 +110,9 @@ imxrt = ["dep:cortex-m", "dep:imxrt-ral"]
|
||||||
imxrt_gpt1 = ["imxrt"]
|
imxrt_gpt1 = ["imxrt"]
|
||||||
imxrt_gpt2 = ["imxrt"]
|
imxrt_gpt2 = ["imxrt"]
|
||||||
|
|
||||||
|
# ESP32-C3 Timer
|
||||||
|
esp32c3-systimer = ["dep:esp32c3", "dep:riscv"]
|
||||||
|
|
||||||
# STM32 timers
|
# STM32 timers
|
||||||
# Use as `features = ["stm32g081kb", "stm32_tim15"]`
|
# Use as `features = ["stm32g081kb", "stm32_tim15"]`
|
||||||
stm32_tim2 = []
|
stm32_tim2 = []
|
||||||
|
|
193
rtic-monotonics/src/esp32c3.rs
Normal file
193
rtic-monotonics/src/esp32c3.rs
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
//! [`Monotonic`](rtic_time::Monotonic) implementation for ESP32C3's SYSTIMER.
|
||||||
|
//!
|
||||||
|
//! Always runs at a fixed rate of 16 MHz.
|
||||||
|
//!
|
||||||
|
//! # Example
|
||||||
|
//!
|
||||||
|
//! ```
|
||||||
|
//! use rtic_monotonics::esp32c3::prelude::*;
|
||||||
|
//!
|
||||||
|
//! esp32c3_systimer_monotonic!(Mono);
|
||||||
|
//!
|
||||||
|
//! fn init() {
|
||||||
|
//! # // This is normally provided by the selected PAC
|
||||||
|
//! # let timer = unsafe { esp32c3::Peripherals::steal() }.SYSTIMER;
|
||||||
|
//! #
|
||||||
|
//! // Start the monotonic
|
||||||
|
//! Mono::start(timer);
|
||||||
|
//! }
|
||||||
|
//!
|
||||||
|
//! async fn usage() {
|
||||||
|
//! loop {
|
||||||
|
//! // Use the monotonic
|
||||||
|
//! let timestamp = Mono::now();
|
||||||
|
//! Mono::delay(100.millis()).await;
|
||||||
|
//! }
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
|
|
||||||
|
/// Common definitions and traits for using the RP2040 timer monotonic
|
||||||
|
pub mod prelude {
|
||||||
|
pub use crate::esp32c3_systimer_monotonic;
|
||||||
|
|
||||||
|
pub use crate::Monotonic;
|
||||||
|
|
||||||
|
pub use fugit::{self, ExtU64, ExtU64Ceil};
|
||||||
|
}
|
||||||
|
use crate::TimerQueueBackend;
|
||||||
|
use esp32c3::{INTERRUPT_CORE0, SYSTIMER};
|
||||||
|
use rtic_time::timer_queue::TimerQueue;
|
||||||
|
|
||||||
|
/// Timer implementing [`TimerQueueBackend`].
|
||||||
|
pub struct TimerBackend;
|
||||||
|
|
||||||
|
impl TimerBackend {
|
||||||
|
/// Starts the monotonic timer.
|
||||||
|
///
|
||||||
|
/// **Do not use this function directly.**
|
||||||
|
///
|
||||||
|
/// Use the prelude macros instead.
|
||||||
|
pub fn _start(timer: SYSTIMER) {
|
||||||
|
const INTERRUPT_MAP_BASE: u32 = 0x600c2000;
|
||||||
|
let interrupt_number = 37 as isize;
|
||||||
|
let cpu_interrupt_number = 31 as isize;
|
||||||
|
unsafe {
|
||||||
|
let intr_map_base = INTERRUPT_MAP_BASE as *mut u32;
|
||||||
|
intr_map_base
|
||||||
|
.offset(interrupt_number)
|
||||||
|
.write_volatile(cpu_interrupt_number as u32);
|
||||||
|
//map peripheral interrupt to CPU interrupt
|
||||||
|
(*INTERRUPT_CORE0::ptr())
|
||||||
|
.cpu_int_enable()
|
||||||
|
.modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits())); //enable the CPU interupt.
|
||||||
|
let intr = INTERRUPT_CORE0::ptr();
|
||||||
|
let intr_prio_base = (*intr).cpu_int_pri_0().as_ptr();
|
||||||
|
|
||||||
|
intr_prio_base
|
||||||
|
.offset(cpu_interrupt_number)
|
||||||
|
.write_volatile(15 as u32);
|
||||||
|
}
|
||||||
|
timer.conf().write(|w| w.timer_unit0_work_en().set_bit());
|
||||||
|
timer
|
||||||
|
.conf()
|
||||||
|
.write(|w| w.timer_unit1_core0_stall_en().clear_bit());
|
||||||
|
TIMER_QUEUE.initialize(Self {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static TIMER_QUEUE: TimerQueue<TimerBackend> = TimerQueue::new();
|
||||||
|
use esp32c3;
|
||||||
|
impl TimerQueueBackend for TimerBackend {
|
||||||
|
type Ticks = u64;
|
||||||
|
fn now() -> Self::Ticks {
|
||||||
|
let peripherals = unsafe { esp32c3::Peripherals::steal() };
|
||||||
|
peripherals
|
||||||
|
.SYSTIMER
|
||||||
|
.unit0_op()
|
||||||
|
.write(|w| w.timer_unit0_update().set_bit());
|
||||||
|
// this must be polled until value is valid
|
||||||
|
while {
|
||||||
|
peripherals
|
||||||
|
.SYSTIMER
|
||||||
|
.unit0_op()
|
||||||
|
.read()
|
||||||
|
.timer_unit0_value_valid()
|
||||||
|
== false
|
||||||
|
} {}
|
||||||
|
let instant: u64 = (peripherals.SYSTIMER.unit0_value_lo().read().bits() as u64)
|
||||||
|
| ((peripherals.SYSTIMER.unit0_value_hi().read().bits() as u64) << 32);
|
||||||
|
instant
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_compare(instant: Self::Ticks) {
|
||||||
|
let systimer = unsafe { esp32c3::Peripherals::steal() }.SYSTIMER;
|
||||||
|
systimer
|
||||||
|
.target0_conf()
|
||||||
|
.write(|w| w.target0_timer_unit_sel().set_bit());
|
||||||
|
systimer
|
||||||
|
.target0_conf()
|
||||||
|
.write(|w| w.target0_period_mode().clear_bit());
|
||||||
|
systimer
|
||||||
|
.target0_lo()
|
||||||
|
.write(|w| unsafe { w.bits((instant & 0xFFFFFFFF).try_into().unwrap()) });
|
||||||
|
systimer
|
||||||
|
.target0_hi()
|
||||||
|
.write(|w| unsafe { w.bits((instant >> 32).try_into().unwrap()) });
|
||||||
|
systimer
|
||||||
|
.comp0_load()
|
||||||
|
.write(|w| w.timer_comp0_load().set_bit()); //sync period to comp register
|
||||||
|
systimer.conf().write(|w| w.target0_work_en().set_bit());
|
||||||
|
systimer.int_ena().write(|w| w.target0().set_bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear_compare_flag() {
|
||||||
|
unsafe { esp32c3::Peripherals::steal() }
|
||||||
|
.SYSTIMER
|
||||||
|
.int_clr()
|
||||||
|
.write(|w| w.target0().bit(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pend_interrupt() {
|
||||||
|
extern "C" {
|
||||||
|
fn cpu_int_31_handler();
|
||||||
|
}
|
||||||
|
//run the timer interrupt handler in a critical section to emulate a max priority
|
||||||
|
//interrupt.
|
||||||
|
//since there is no hardware support for pending a timer interrupt.
|
||||||
|
riscv::interrupt::disable();
|
||||||
|
unsafe { cpu_int_31_handler() };
|
||||||
|
unsafe { riscv::interrupt::enable() };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn timer_queue() -> &'static TimerQueue<Self> {
|
||||||
|
&TIMER_QUEUE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create an ESP32-C3 SysTimer based monotonic and register the necessary interrupt for it.
|
||||||
|
///
|
||||||
|
/// See [`crate::esp32c3`] for more details.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `name` - The name that the monotonic type will have.
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! esp32c3_systimer_monotonic {
|
||||||
|
($name:ident) => {
|
||||||
|
/// A `Monotonic` based on the ESP32-C3 SysTimer peripheral.
|
||||||
|
pub struct $name;
|
||||||
|
|
||||||
|
impl $name {
|
||||||
|
/// Starts the `Monotonic`.
|
||||||
|
///
|
||||||
|
/// This method must be called only once.
|
||||||
|
pub fn start(timer: esp32c3::SYSTIMER) {
|
||||||
|
#[export_name = "cpu_int_31_handler"]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
unsafe extern "C" fn Systimer() {
|
||||||
|
use $crate::TimerQueueBackend;
|
||||||
|
$crate::esp32c3::TimerBackend::timer_queue().on_monotonic_interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
$crate::esp32c3::TimerBackend::_start(timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl $crate::TimerQueueBasedMonotonic for $name {
|
||||||
|
type Backend = $crate::esp32c3::TimerBackend;
|
||||||
|
type Instant = $crate::fugit::Instant<
|
||||||
|
<Self::Backend as $crate::TimerQueueBackend>::Ticks,
|
||||||
|
1,
|
||||||
|
16_000_000,
|
||||||
|
>;
|
||||||
|
type Duration = $crate::fugit::Duration<
|
||||||
|
<Self::Backend as $crate::TimerQueueBackend>::Ticks,
|
||||||
|
1,
|
||||||
|
16_000_000,
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
|
||||||
|
$crate::rtic_time::impl_embedded_hal_delay_fugit!($name);
|
||||||
|
$crate::rtic_time::impl_embedded_hal_async_delay_fugit!($name);
|
||||||
|
};
|
||||||
|
}
|
|
@ -39,6 +39,9 @@ pub use rtic_time::{
|
||||||
TimeoutError,
|
TimeoutError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "esp32c3-systimer")]
|
||||||
|
pub mod esp32c3;
|
||||||
|
|
||||||
#[cfg(feature = "cortex-m-systick")]
|
#[cfg(feature = "cortex-m-systick")]
|
||||||
pub mod systick;
|
pub mod systick;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue