zephyr/sys.rs
1// Copyright (c) 2024 Linaro LTD
2// SPDX-License-Identifier: Apache-2.0
3
4//! Zephyr 'sys' module.
5//!
6//! The `zephyr-sys` crate contains the direct C bindings to the Zephyr API. All of these are
7//! unsafe.
8//!
9//! This module `zephyr::sys` contains thin wrappers to these C bindings, that can be used without
10//! unsafe, but as unchanged as possible.
11
12use zephyr_sys::k_timeout_t;
13
14pub mod queue;
15pub mod sync;
16pub mod thread;
17
18// These two constants are not able to be captured by bindgen. It is unlikely that these values
19// would change in the Zephyr headers, but there will be an explicit test to make sure they are
20// correct.
21
22/// Represents a timeout with an infinite delay.
23///
24/// Low-level Zephyr constant. Calls using this value will wait as long as necessary to perform
25/// the requested operation.
26pub const K_FOREVER: k_timeout_t = k_timeout_t { ticks: -1 };
27
28/// Represents a null timeout delay.
29///
30/// Low-level Zephyr Constant. Calls using this value will not wait if the operation cannot be
31/// performed immediately.
32pub const K_NO_WAIT: k_timeout_t = k_timeout_t { ticks: 0 };
33
34/// Return the current uptime of the system in ms.
35///
36/// Direct Zephyr call. Precision is limited by the system tick timer.
37#[inline]
38pub fn uptime_get() -> i64 {
39 unsafe { crate::raw::k_uptime_get() }
40}
41
42// The below implementation, based on interrupt locking has only been tested on single CPU. The
43// implementation suggests it should work on SMP, and can be tested. The docs for irq_lock()
44// explicitly state that it cannot be used from userspace. Unfortunately, spinlocks have
45// incompatible semantics with critical sections, so to work with userspace we'd need probably a
46// syscall.
47#[cfg(CONFIG_USERSPACE)]
48compile_error!("Critical-section implementation does not work with CONFIG_USERSPACE");
49
50pub mod critical {
51 //! Zephyr implementation of critical sections.
52 //!
53 //! The critical-section crate explicitly states that critical sections can be nested.
54 //! Unfortunately, Zephyr spinlocks cannot be nested. It is possible to nest different ones,
55 //! but the critical-section implementation API doesn't give access to the stack.
56
57 use core::{
58 ffi::c_int,
59 sync::atomic::{fence, Ordering},
60 };
61
62 use critical_section::RawRestoreState;
63 use zephyr_sys::{zr_irq_lock, zr_irq_unlock};
64
65 struct ZephyrCriticalSection;
66 critical_section::set_impl!(ZephyrCriticalSection);
67
68 unsafe impl critical_section::Impl for ZephyrCriticalSection {
69 unsafe fn acquire() -> RawRestoreState {
70 let res = zr_irq_lock();
71 fence(Ordering::Acquire);
72 res as RawRestoreState
73 }
74
75 unsafe fn release(token: RawRestoreState) {
76 fence(Ordering::Release);
77 zr_irq_unlock(token as c_int);
78 }
79 }
80}