Skip to content

Commit

Permalink
Merge pull request #31 from decaday/feat/time-driver-0-2-0
Browse files Browse the repository at this point in the history
Bump embassy version, `embassy-time-driver 0.2.0` impl
  • Loading branch information
decaday authored Jan 25, 2025
2 parents 6d104f1 + 628f755 commit 30efcf4
Show file tree
Hide file tree
Showing 14 changed files with 279 additions and 423 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
rustup component add rust-src
rustup target add thumbv6m-none-eabi
- name: Build Only
run: cargo build --features py32f030k28,rt,embassy --target thumbv6m-none-eabi
run: cargo build --features py32f030k28 --target thumbv6m-none-eabi
- name: Build Examples
run: |
for d in $(ls -1 ./examples); do
Expand Down
31 changes: 10 additions & 21 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,13 @@ embassy-hal-internal = { version = "0.2.0", features = [
"cortex-m",
"prio-bits-4",
] }
embassy-sync = { version = "0.6.0", optional = true }
embassy-futures = { version = "0.1.1", optional = true }
embassy-time-driver = { version = "0.1.0", optional = true }
embassy-time = { version = "0.3.2", optional = true }
embassy-executor = { version = "0.6", features = [
"nightly",
"integrated-timers",
"arch-cortex-m",
] }
embassy-embedded-hal = { version = "0.2.0", default-features = false }
embassy-sync = { version = "0.6.2" }
embassy-futures = { version = "0.1.1" }
embassy-time-driver = { version = "0.2.0", optional = true }
embassy-time = { version = "0.4.0", optional = true }
embassy-time-queue-utils = { version = "0.1", optional = true }

embassy-embedded-hal = { version = "0.3.0", default-features = false }
embedded-storage = "0.3.1"


Expand All @@ -82,16 +79,14 @@ critical-section = { version = "1.1", features = ["std"] }
# cargo test --no-default-features --features "embassy time exti embassy-usb-driver-impl py32f072c1b"

[features]
default = ["rt", "memory-x", "defmt", "embassy", "time", "exti"]
default = ["rt", "memory-x", "defmt", "time", "exti"]

rt = ["py32-metapac/rt"]

defmt = ["dep:defmt", "dep:defmt-rtt", "embassy-usb-driver/defmt", "musb?/defmt"]

memory-x = ["py32-metapac/memory-x"]

embassy = ["dep:embassy-sync", "dep:embassy-futures", "dep:embassy-time-driver"]

time = ["dep:embassy-time", "embassy-embedded-hal/time"]

exti = []
Expand All @@ -111,15 +106,9 @@ time-driver-any = ["_time-driver"]
time-driver-tim1 = ["_time-driver"]
time-driver-tim3 = ["_time-driver"]
time-driver-tim15 = ["_time-driver"]
time-driver-systick = ["dep:portable-atomic", "_time-driver"]

time-driver-systick = ["portable-atomic"]

# td == time-driver, to avoid confliction
# By default, only one alarm is provided (similar to a 2-channel timer). Enabling this feature provides three alarms (similar to a 4-channel timer).
# Of course, this will also increase the execution time of the interrupt handler.
td-systick-multi-alarms = ["time-driver-systick"]

_time-driver = []
_time-driver = ["dep:embassy-time-driver", "time", "dep:embassy-time-queue-utils"]


[package.metadata.docs.rs]
Expand Down
6 changes: 3 additions & 3 deletions examples/heap-alloc-f030/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ edition = "2021"
cortex-m-rt = "0.7"
panic-probe = { version = "0.3", features = ["print-defmt"] }

embassy-sync = { version = "0.6.0", features = ["defmt"] }
embassy-executor = { version = "0.6.1", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-1_000"] }
embassy-sync = { version = "0.6.2", features = ["defmt"] }
embassy-executor = { version = "0.7.0", features = ["task-arena-size-2048", "arch-cortex-m", "executor-thread", "defmt"] }
embassy-time = { version = "0.4.0", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }

py32-hal = { path = "../../", features = [ "time-driver-tim3", "py32f030k28"]}
defmt = { version = "0.3", features = ["alloc"] }
Expand Down
1 change: 0 additions & 1 deletion examples/py32f030/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
[target.thumbv6m-none-eabi]
# probe-rs chip list | grep -i PY32
runner = 'probe-rs run --chip PY32F030x8'

# rustflags = [
# "-C", "linker=flip-link",
# ]
Expand Down
6 changes: 3 additions & 3 deletions examples/py32f030/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ cortex-m-rt = "0.7.3"
cortex-m-semihosting = { version = "0.5" }
panic-probe = { version = "0.3", features = ["print-defmt"] }

embassy-sync = { version = "0.6.0", features = ["defmt"] }
embassy-executor = { version = "0.6.1", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
embassy-sync = { version = "0.6.2", features = ["defmt"] }
embassy-executor = { version = "0.7.0", features = ["task-arena-size-2048", "arch-cortex-m", "executor-thread", "defmt"] }
embassy-time = { version = "0.4.0", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }

embedded-io = { version = "0.6.0" }
embedded-io-async = { version = "0.6.1" }
Expand Down
8 changes: 4 additions & 4 deletions examples/py32f072/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ cortex-m-rt = "0.7.3"
cortex-m-semihosting = { version = "0.5" }
panic-probe = { version = "0.3", features = ["print-defmt"] }

embassy-sync = { version = "0.6.0", features = ["defmt"] }
embassy-executor = { version = "0.6.1", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
embassy-sync = { version = "0.6.2", features = ["defmt"] }
embassy-executor = { version = "0.7.0", features = ["task-arena-size-4096", "arch-cortex-m", "executor-thread", "defmt"] }
embassy-time = { version = "0.4.0", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }

embedded-io = { version = "0.6.0" }
embedded-io-async = { version = "0.6.1" }
Expand All @@ -25,7 +25,7 @@ py32-hal = { path = "../../", features = [ "time-driver-tim15", "py32f072c1b", "
defmt = "0.3"
defmt-rtt = "0.4"
embassy-futures = "0.1.1"
embassy-usb = { version = "0.3.0", features = [ "defmt"]}
embassy-usb = { version = "0.4.0", features = [ "defmt"]}
usbd-hid = "0.8.2"

# embassy-usb-logger = "0.2.0"
Expand Down
6 changes: 3 additions & 3 deletions examples/systick-time-driver-f030/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ cortex-m-rt = "0.7.3"
cortex-m-semihosting = { version = "0.5" }
panic-probe = { version = "0.3", features = ["print-defmt"] }

embassy-sync = { version = "0.6.0", features = ["defmt"] }
embassy-executor = { version = "0.6.1", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
embassy-time = { version = "0.3.2", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-1_000"] }
embassy-sync = { version = "0.6.2", features = ["defmt"] }
embassy-executor = { version = "0.7.0", features = ["task-arena-size-2048", "arch-cortex-m", "executor-thread", "defmt"] }
embassy-time = { version = "0.4.0", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }

embedded-io = { version = "0.6.0" }
embedded-io-async = { version = "0.6.1" }
Expand Down
1 change: 0 additions & 1 deletion examples/systick-time-driver-f030/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use embassy_executor::Spawner;
use embassy_time::Timer;
use py32_hal::gpio::{Level, Output, Speed};
use py32_hal::rcc::{HsiFs, Pll, PllSource, Sysclk};
use py32_hal::time::Hertz;

use cortex_m::Peripherals;
use defmt::*;
Expand Down
7 changes: 2 additions & 5 deletions examples/usbd-f072/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,16 @@ cortex-m-rt = "0.7.3"
cortex-m-semihosting = { version = "0.5" }
panic-probe = { version = "0.3", features = ["print-defmt"] }

py32-hal = { path = "../../", default-features = false,features = [ "py32f072c1b",
"time-driver-tim15",
py32-hal = { path = "../../", default-features = false, features = [
"py32f072c1b",
"defmt",
"rt",
"memory-x",
"usb-device-impl",
"embassy"
]}

defmt = "0.3"
defmt-rtt = "0.4"
embassy-futures = "0.1.1"
embassy-usb = { version = "0.3.0", features = [ "defmt"]}
usbd-human-interface-device = { version = "0.5.0", features = [ "defmt"]}

portable-atomic = { version = "1.5", features = ["critical-section"] }
Expand Down
5 changes: 5 additions & 0 deletions src/embassy/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#[cfg(all(feature = "_time-driver", not(feature = "time-driver-systick")))]
pub mod time_driver;

#[cfg(feature = "time-driver-systick")]
pub mod systick_time_driver;
154 changes: 154 additions & 0 deletions src/embassy/systick_time_driver.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
use core::cell::{Cell, RefCell};
use core::task::Waker;

use cortex_m::peripheral::syst::SystClkSource;
use cortex_m::peripheral::SYST;
use cortex_m_rt::exception;

use critical_section::CriticalSection;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::blocking_mutex::Mutex;
use embassy_time_driver::{Driver, TICK_HZ};
use embassy_time_queue_utils::Queue;
use portable_atomic::{AtomicU64, Ordering};

// Alarm state structure to manage individual alarms
struct AlarmState {
timestamp: Cell<u64>,
}

unsafe impl Send for AlarmState {}

impl AlarmState {
const fn new() -> Self {
Self {
timestamp: Cell::new(u64::MAX),
}
}
}

// SysTick-based time driver implementation
pub(crate) struct SysTickDriver {
// Total number of ticks since system start
ticks: AtomicU64,
// Number of allocated alarms
alarm: Mutex<CriticalSectionRawMutex, AlarmState>,
queue: Mutex<CriticalSectionRawMutex, RefCell<Queue>>,
}

// Constant initialization for alarm states
#[allow(clippy::declare_interior_mutable_const)]
const ALARM_STATE_NEW: AlarmState = AlarmState::new();

// Macro to create a static driver instance
embassy_time_driver::time_driver_impl!(static DRIVER: SysTickDriver = SysTickDriver {
ticks: AtomicU64::new(0),
alarm: Mutex::const_new(CriticalSectionRawMutex::new(), ALARM_STATE_NEW),
queue: Mutex::new(RefCell::new(Queue::new()))
});

impl SysTickDriver {
// Initialize the SysTick driver
fn init(&'static self, _cs: CriticalSection, mut systick: SYST) -> bool {
// Calculate the reload value
let core_clock = unsafe { crate::rcc::get_freqs() }
.hclk1
.to_hertz()
.unwrap()
.0;

let reload_value = match (core_clock as u64).checked_div(TICK_HZ) {
Some(div) if div > 0 && div <= 0x00FFFFFF => (div - 1) as u32,
_ => panic!("Invalid SysTick reload value"), // Frequency not achievable
};
// let peripherals = unsafe { cortex_m::Peripherals::steal() };
// let mut systick = peripherals.SYST;

// Configure SysTick
systick.set_clock_source(SystClkSource::Core); // Use processor clock
systick.set_reload(reload_value);
systick.clear_current();
systick.enable_counter();
systick.enable_interrupt();

true
}

// SysTick interrupt handler
fn on_systick(&self) {
critical_section::with(|cs| {
// Increment global tick counter
let current_ticks = self.ticks.fetch_add(1, Ordering::Relaxed);
self.check_and_trigger_alarm(current_ticks, cs);
});
}

// Check if an alarm is due and trigger it if necessary
#[inline]
fn check_and_trigger_alarm(&self, current_time: u64, cs: CriticalSection) {
let alarm = &self.alarm.borrow(cs);
let alarm_timestamp = alarm.timestamp.get();

// Check if alarm is scheduled and due
if alarm_timestamp != u64::MAX && current_time >= alarm_timestamp {
let mut next = self
.queue
.borrow(cs)
.borrow_mut()
.next_expiration(current_time);
while !self.set_alarm(cs, next) {
next = self
.queue
.borrow(cs)
.borrow_mut()
.next_expiration(self.now());
}
}
}

// Set alarm timestamp
fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool {
if self.now() >= timestamp {
// Alarm time has passed, cannot set
return false;
}
self.alarm.borrow(cs).timestamp.set(timestamp);
if self.now() >= timestamp {
self.alarm.borrow(cs).timestamp.set(u64::MAX);
return false;
}
true
}
}

// Implement the Driver trait for SysTickDriver
impl Driver for SysTickDriver {
// Get current system time in ticks
fn now(&self) -> u64 {
self.ticks.load(Ordering::Relaxed)
}

fn schedule_wake(&self, at: u64, waker: &Waker) {
critical_section::with(|cs| {
let mut queue = self.queue.borrow(cs).borrow_mut();

if queue.schedule_wake(at, waker) {
let mut next = queue.next_expiration(self.now());
while !self.set_alarm(cs, next) {
next = queue.next_expiration(self.now());
}
}
})
}
}

// Initialization function
pub(crate) fn init(cs: CriticalSection, systick: SYST) {
DRIVER.init(cs, systick);
}

// SysTick interrupt handler (to be implemented in your interrupt vector)
#[exception]
fn SysTick() {
DRIVER.on_systick();
}
Loading

0 comments on commit 30efcf4

Please sign in to comment.