Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add flipperzero::furi::kernel module #180

Merged
merged 1 commit into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
### Added

- `flipperzero::dialogs::DialogFileBrowserOptions`
- `flipperzero::furi::kernel` module exposing most `furi_kernel_*` APIs

### Changed

Expand Down
90 changes: 90 additions & 0 deletions crates/flipperzero/src/furi/kernel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
//! Furi Kernel primitives.

use flipperzero_sys as sys;
use ufmt::derive::uDebug;

use crate::furi;

/// Check if CPU is in IRQ; or kernel running and IRQ is masked.
pub fn is_irq_or_masked() -> bool {
unsafe { sys::furi_kernel_is_irq_or_masked() }
}

/// Check if kernel is running.
pub fn is_running() -> bool {
unsafe { sys::furi_kernel_is_running() }
}

/// Kernel lock state.
#[derive(Clone, Copy, Debug, PartialEq, Eq, uDebug)]
pub enum LockState {
/// normal scheduling
Unlocked = 0,
/// scheduling paused
Locked = 1,
}

impl From<i32> for LockState {
fn from(value: i32) -> Self {
match value {
0 => LockState::Unlocked,
// Assume any non-zero value is `Locked``.
// This can be modified if new lock states are added in the future.
_ => LockState::Locked,
}
}
}

impl From<LockState> for i32 {
fn from(value: LockState) -> Self {
value as i32
}
}

/// Lock kernel, pause process scheduling.
///
/// <div class="warning">This should never be called in an interrupt request context.</div>
///
/// Returns previous lock state.
pub fn lock() -> furi::Result<LockState> {
let status = sys::furi::Status::from(unsafe { sys::furi_kernel_lock() });

status.err_or_else(|status| status.0.into())
}

/// Unlock kernel, resume process scheduling.
///
/// <div class="warning">This should never be called in an interrupt request context.</div>
///
/// Returns previous lock state.
pub fn unlock() -> furi::Result<LockState> {
let status = sys::furi::Status::from(unsafe { sys::furi_kernel_unlock() });

status.err_or_else(|status| status.0.into())
}

/// Restore kernel lock state.
///
/// <div class="warning">This should never be called in an interrupt request context.</div>
///
/// Returns previous lock state.
pub fn restore_lock(state: LockState) -> furi::Result<LockState> {
let status = sys::furi::Status::from(unsafe { sys::furi_kernel_restore_lock(state.into()) });

status.err_or_else(|status| status.0.into())
dcoles marked this conversation as resolved.
Show resolved Hide resolved
}

/// Return kernel tick frequency in hertz.
#[inline]
pub fn get_tick_frequency() -> u32 {
unsafe { sys::furi_kernel_get_tick_frequency() }
}

/// Return current kernel tick value.
///
/// The duration of a tick depends on kernel configuration.
/// The value can be discovered with [`get_tick_frequency`].
#[inline]
pub fn get_tick() -> u32 {
unsafe { sys::furi_get_tick() }
}
1 change: 1 addition & 0 deletions crates/flipperzero/src/furi/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Furi API.

pub mod io;
pub mod kernel;
pub mod log;
pub mod message_queue;
pub mod rng;
Expand Down
9 changes: 5 additions & 4 deletions crates/flipperzero/src/furi/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ use core::cmp::Ordering;
use core::iter::Sum;
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};

use flipperzero_sys as sys;
use ufmt::derive::uDebug;

use crate::furi;

/// Maximum number of ticks a [`Duration`] can contain to be usable with [`Instant`].
const MAX_INTERVAL_DURATION_TICKS: u32 = u32::MAX / 2;

Expand All @@ -16,7 +17,7 @@ const MILLIS_PER_SEC: u32 = 1_000;

/// Converts the given number of nanoseconds to ticks.
fn ns_to_ticks(nanos: u64) -> u64 {
let rate = unsafe { sys::furi_kernel_get_tick_frequency() };
let rate = furi::kernel::get_tick_frequency();
if rate == MILLIS_PER_SEC {
// This can be up to around 2^45 ticks.
nanos / NANOS_PER_MILLI
Expand All @@ -31,7 +32,7 @@ fn ns_to_ticks(nanos: u64) -> u64 {
///
/// The upper 2 bits of the return value will always be zero.
fn ticks_to_ns(ticks: u32) -> u64 {
let rate = unsafe { sys::furi_kernel_get_tick_frequency() };
let rate = furi::kernel::get_tick_frequency();
if rate == MILLIS_PER_SEC {
// This can be up to around 2^52 nanoseconds.
(ticks as u64) * NANOS_PER_MILLI
Expand All @@ -49,7 +50,7 @@ impl Instant {
/// Returns an instant corresponding to "now".
#[must_use]
pub fn now() -> Instant {
Instant(unsafe { sys::furi_get_tick() })
Instant(furi::kernel::get_tick())
}

/// Returns the amount of time elapsed from another instant to this one.
Expand Down
Loading