zephyr/
sys.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// Copyright (c) 2024 Linaro LTD
// SPDX-License-Identifier: Apache-2.0

//! Zephyr 'sys' module.
//!
//! The `zephyr-sys` crate contains the direct C bindings to the Zephyr API.  All of these are
//! unsafe.
//!
//! This module `zephyr::sys` contains thin wrappers to these C bindings, that can be used without
//! unsafe, but as unchanged as possible.

use zephyr_sys::k_timeout_t;

pub mod queue;
pub mod sync;
pub mod thread;

// These two constants are not able to be captured by bindgen.  It is unlikely that these values
// would change in the Zephyr headers, but there will be an explicit test to make sure they are
// correct.

/// Represents a timeout with an infinite delay.
///
/// Low-level Zephyr constant.  Calls using this value will wait as long as necessary to perform
/// the requested operation.
pub const K_FOREVER: k_timeout_t = k_timeout_t { ticks: -1 };

/// Represents a null timeout delay.
///
/// Low-level Zephyr Constant.  Calls using this value will not wait if the operation cannot be
/// performed immediately.
pub const K_NO_WAIT: k_timeout_t = k_timeout_t { ticks: 0 };

/// Return the current uptime of the system in ms.
///
/// Direct Zephyr call.  Precision is limited by the system tick timer.
#[inline]
pub fn uptime_get() -> i64 {
    unsafe {
        crate::raw::k_uptime_get()
    }
}

pub mod critical {
    //! Zephyr implementation of critical sections.
    //!
    //! Critical sections from Rust are handled with a single Zephyr spinlock.  This doesn't allow
    //! any nesting, but neither does the `critical-section` crate.
    //!
    //! This provides the underlying critical section crate, which is useful for external crates
    //! that want this interface.  However, it isn't a particularly hygienic interface to use.  For
    //! something a bit nicer, please see [`sync::SpinMutex`].

    use core::{ffi::c_int, ptr::addr_of_mut};

    use critical_section::RawRestoreState;
    use zephyr_sys::{k_spinlock, k_spin_lock, k_spin_unlock, k_spinlock_key_t};

    struct ZephyrCriticalSection;
    critical_section::set_impl!(ZephyrCriticalSection);

    // The critical section shares a single spinlock.
    static mut LOCK: k_spinlock = unsafe { core::mem::zeroed() };

    unsafe impl critical_section::Impl for ZephyrCriticalSection {
        unsafe fn acquire() -> RawRestoreState {
            let res = k_spin_lock(addr_of_mut!(LOCK));
            res.key as RawRestoreState
        }

        unsafe fn release(token: RawRestoreState) {
            k_spin_unlock(addr_of_mut!(LOCK),
                          k_spinlock_key_t {
                              key: token as c_int,
                          });
        }
    }
}