mirror of
https://github.com/esp-rs/esp-idf-hal.git
synced 2025-09-30 13:50:53 +00:00
Split the notification mechanism from the executor module
This commit is contained in:
parent
1138d3e21c
commit
2cb816c6d4
@ -40,7 +40,7 @@ fn main() -> Result<(), EspError> {
|
|||||||
// The benefit with this approach over checking a global static variable is
|
// The benefit with this approach over checking a global static variable is
|
||||||
// that the scheduler can hold the task, and resume when signaled
|
// that the scheduler can hold the task, and resume when signaled
|
||||||
// so no spinlock is needed
|
// so no spinlock is needed
|
||||||
let event_id = esp_idf_hal::task::wait_notification(None);
|
let event_id = esp_idf_hal::task::wait_notification(esp_idf_hal::delay::BLOCK);
|
||||||
|
|
||||||
// Note that the println functions are to slow for 200us
|
// Note that the println functions are to slow for 200us
|
||||||
// Even if we just send one charachter we can not go below 1ms per msg
|
// Even if we just send one charachter we can not go below 1ms per msg
|
||||||
|
135
src/task.rs
135
src/task.rs
@ -1,12 +1,10 @@
|
|||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::ptr::{self, NonNull};
|
use core::ptr::{self, NonNull};
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
use core::time::Duration;
|
|
||||||
|
|
||||||
use esp_idf_sys::*;
|
use esp_idf_sys::*;
|
||||||
|
|
||||||
use crate::cpu::Core;
|
use crate::cpu::Core;
|
||||||
use crate::delay::TickType;
|
|
||||||
use crate::interrupt;
|
use crate::interrupt;
|
||||||
|
|
||||||
/// Creates a FreeRTOS task.
|
/// Creates a FreeRTOS task.
|
||||||
@ -107,7 +105,7 @@ pub fn current() -> Option<TaskHandle_t> {
|
|||||||
|
|
||||||
pub fn wait_any_notification() {
|
pub fn wait_any_notification() {
|
||||||
loop {
|
loop {
|
||||||
if let Some(notification) = wait_notification(None) {
|
if let Some(notification) = wait_notification(crate::delay::BLOCK) {
|
||||||
if notification != 0 {
|
if notification != 0 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -115,23 +113,15 @@ pub fn wait_any_notification() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn wait_notification(duration: Option<Duration>) -> Option<u32> {
|
pub fn wait_notification(timeout: TickType_t) -> Option<u32> {
|
||||||
let mut notification = 0_u32;
|
let mut notification = 0_u32;
|
||||||
|
|
||||||
#[cfg(esp_idf_version = "4.3")]
|
#[cfg(esp_idf_version = "4.3")]
|
||||||
let notified =
|
let notified = unsafe { xTaskNotifyWait(0, u32::MAX, &mut notification, timeout) } != 0;
|
||||||
unsafe { xTaskNotifyWait(0, u32::MAX, &mut notification, TickType::from(duration).0) } != 0;
|
|
||||||
|
|
||||||
#[cfg(not(esp_idf_version = "4.3"))]
|
#[cfg(not(esp_idf_version = "4.3"))]
|
||||||
let notified = unsafe {
|
let notified =
|
||||||
xTaskGenericNotifyWait(
|
unsafe { xTaskGenericNotifyWait(0, 0, u32::MAX, &mut notification, timeout) } != 0;
|
||||||
0,
|
|
||||||
0,
|
|
||||||
u32::MAX,
|
|
||||||
&mut notification,
|
|
||||||
TickType::from(duration).0,
|
|
||||||
)
|
|
||||||
} != 0;
|
|
||||||
|
|
||||||
if notified {
|
if notified {
|
||||||
Some(notification)
|
Some(notification)
|
||||||
@ -731,47 +721,55 @@ pub mod embassy_sync {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(
|
#[cfg(all(feature = "alloc", target_has_atomic = "ptr"))]
|
||||||
feature = "edge-executor",
|
pub mod notification {
|
||||||
feature = "alloc",
|
|
||||||
target_has_atomic = "ptr"
|
|
||||||
))]
|
|
||||||
pub mod executor {
|
|
||||||
use core::sync::atomic::{AtomicPtr, Ordering};
|
use core::sync::atomic::{AtomicPtr, Ordering};
|
||||||
use core::{mem, ptr};
|
use core::{mem, ptr};
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use alloc::sync::{Arc, Weak};
|
use alloc::sync::{Arc, Weak};
|
||||||
|
|
||||||
|
use esp_idf_sys::TickType_t;
|
||||||
|
|
||||||
use crate::task;
|
use crate::task;
|
||||||
|
|
||||||
pub use edge_executor::*;
|
|
||||||
|
|
||||||
pub type EspExecutor<'a, const C: usize, S> = Executor<'a, C, FreeRtosMonitor, S>;
|
|
||||||
pub type EspBlocker = Blocker<FreeRtosMonitor>;
|
|
||||||
|
|
||||||
#[cfg(esp_idf_version_major = "4")]
|
#[cfg(esp_idf_version_major = "4")]
|
||||||
pub struct FreeRtosMonitor(Arc<AtomicPtr<core::ffi::c_void>>, *const ());
|
pub type Task = core::ffi::c_void;
|
||||||
|
|
||||||
#[cfg(not(esp_idf_version_major = "4"))]
|
#[cfg(not(esp_idf_version_major = "4"))]
|
||||||
pub struct FreeRtosMonitor(Arc<AtomicPtr<esp_idf_sys::tskTaskControlBlock>>, *const ());
|
pub type Task = esp_idf_sys::tskTaskControlBlock;
|
||||||
|
|
||||||
impl FreeRtosMonitor {
|
pub struct Monitor(Arc<AtomicPtr<Task>>, *const ());
|
||||||
pub fn new() -> Self {
|
|
||||||
Self(
|
impl Monitor {
|
||||||
Arc::new(AtomicPtr::new(task::current().unwrap())),
|
pub fn current() -> Self {
|
||||||
ptr::null(),
|
unsafe { Self::new(task::current().unwrap()) }
|
||||||
)
|
}
|
||||||
|
|
||||||
|
pub unsafe fn new(task: *const Task) -> Self {
|
||||||
|
Self(Arc::new(AtomicPtr::new(task as *mut _)), ptr::null())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn notifier(&self) -> Notifier {
|
||||||
|
Notifier(Arc::downgrade(&self.0))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wait_any(&self) {
|
||||||
|
task::wait_any_notification();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wait(&self, timeout: TickType_t) -> Option<u32> {
|
||||||
|
task::wait_notification(timeout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FreeRtosMonitor {
|
impl Default for Monitor {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new()
|
Self::current()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for FreeRtosMonitor {
|
impl Drop for Monitor {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let mut arc = mem::replace(&mut self.0, Arc::new(AtomicPtr::new(ptr::null_mut())));
|
let mut arc = mem::replace(&mut self.0, Arc::new(AtomicPtr::new(ptr::null_mut())));
|
||||||
|
|
||||||
@ -786,37 +784,60 @@ pub mod executor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Monitor for FreeRtosMonitor {
|
pub struct Notifier(Weak<AtomicPtr<Task>>);
|
||||||
type Notify = FreeRtosMonitorNotify;
|
|
||||||
|
|
||||||
fn notifier(&self) -> Self::Notify {
|
impl Notifier {
|
||||||
FreeRtosMonitorNotify(Arc::downgrade(&self.0))
|
pub fn notify_any(&self) {
|
||||||
}
|
self.notify(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Wait for FreeRtosMonitor {
|
pub fn notify(&self, notification: u32) {
|
||||||
fn wait(&self) {
|
|
||||||
task::wait_any_notification();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(esp_idf_version_major = "4")]
|
|
||||||
pub struct FreeRtosMonitorNotify(Weak<AtomicPtr<core::ffi::c_void>>);
|
|
||||||
|
|
||||||
#[cfg(not(esp_idf_version_major = "4"))]
|
|
||||||
pub struct FreeRtosMonitorNotify(Weak<AtomicPtr<esp_idf_sys::tskTaskControlBlock>>);
|
|
||||||
|
|
||||||
impl Notify for FreeRtosMonitorNotify {
|
|
||||||
fn notify(&self) {
|
|
||||||
if let Some(notify) = self.0.upgrade() {
|
if let Some(notify) = self.0.upgrade() {
|
||||||
let freertos_task = notify.load(Ordering::SeqCst);
|
let freertos_task = notify.load(Ordering::SeqCst);
|
||||||
|
|
||||||
if !freertos_task.is_null() {
|
if !freertos_task.is_null() {
|
||||||
unsafe {
|
unsafe {
|
||||||
task::notify(freertos_task, 1);
|
task::notify(freertos_task, notification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(all(
|
||||||
|
feature = "edge-executor",
|
||||||
|
feature = "alloc",
|
||||||
|
target_has_atomic = "ptr"
|
||||||
|
))]
|
||||||
|
pub mod executor {
|
||||||
|
use super::notification;
|
||||||
|
|
||||||
|
pub use edge_executor::*;
|
||||||
|
|
||||||
|
pub type EspExecutor<'a, const C: usize, S> = Executor<'a, C, FreeRtosMonitor, S>;
|
||||||
|
pub type EspBlocker = Blocker<FreeRtosMonitor>;
|
||||||
|
|
||||||
|
pub type FreeRtosMonitor = notification::Monitor;
|
||||||
|
pub type FreeRtosNotify = notification::Notifier;
|
||||||
|
|
||||||
|
impl Monitor for notification::Monitor {
|
||||||
|
type Notify = notification::Notifier;
|
||||||
|
|
||||||
|
fn notifier(&self) -> Self::Notify {
|
||||||
|
notification::Monitor::notifier(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Wait for notification::Monitor {
|
||||||
|
fn wait(&self) {
|
||||||
|
notification::Monitor::wait_any(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Notify for notification::Notifier {
|
||||||
|
fn notify(&self) {
|
||||||
|
notification::Notifier::notify_any(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user