122 lines
3.5 KiB
Rust
122 lines
3.5 KiB
Rust
use core::{
|
|
cell::UnsafeCell,
|
|
ffi::{c_void, CStr},
|
|
marker::PhantomPinned,
|
|
mem::{size_of, transmute},
|
|
panic::{RefUnwindSafe, UnwindSafe},
|
|
ptr::null_mut,
|
|
str,
|
|
};
|
|
|
|
use crate::{
|
|
bindings::{
|
|
rt_context_init, rt_syscall, rt_syscall_args, rt_syscall_pend, rt_syscall_push,
|
|
rt_syscall_record, rt_task, rt_task_drop_privilege, rt_task_enable_fp, rt_task_exit,
|
|
rt_task_name, rt_task_sleep, rt_task_sleep_periodic, rt_task_state, rt_task_yield,
|
|
RT_STACK_MIN,
|
|
},
|
|
list::list_init,
|
|
tick::Utick,
|
|
};
|
|
|
|
pub const STACK_MIN: usize = RT_STACK_MIN as usize;
|
|
|
|
pub struct Task {
|
|
t: UnsafeCell<rt_task>,
|
|
_pin_marker: PhantomPinned,
|
|
}
|
|
|
|
unsafe impl Send for Task {}
|
|
unsafe impl Sync for Task {}
|
|
impl UnwindSafe for Task {}
|
|
impl RefUnwindSafe for Task {}
|
|
|
|
pub fn yield_() {
|
|
unsafe { rt_task_yield() }
|
|
}
|
|
|
|
pub fn sleep(ticks: Utick) {
|
|
unsafe { rt_task_sleep(ticks) }
|
|
}
|
|
|
|
pub fn sleep_periodic(last_wake_tick: &mut Utick, period: Utick) {
|
|
unsafe { rt_task_sleep_periodic(last_wake_tick, period) }
|
|
}
|
|
|
|
pub fn exit() -> ! {
|
|
unsafe { rt_task_exit() }
|
|
}
|
|
|
|
pub fn name() -> &'static str {
|
|
unsafe { str::from_utf8_unchecked(CStr::from_ptr(rt_task_name()).to_bytes()) }
|
|
}
|
|
|
|
pub fn enable_fp() {
|
|
unsafe { rt_task_enable_fp() }
|
|
}
|
|
|
|
pub fn drop_privilege() {
|
|
unsafe { rt_task_drop_privilege() }
|
|
}
|
|
|
|
impl Task {
|
|
pub const fn init(task: &'static Task, name: &'static CStr, priority: u32) -> Task {
|
|
let t = unsafe { &*(task.t.get() as *const rt_task) };
|
|
Task {
|
|
t: UnsafeCell::new(rt_task {
|
|
list: list_init(&t.list),
|
|
sleep_list: list_init(&t.sleep_list),
|
|
ctx: null_mut(),
|
|
list_head: null_mut(),
|
|
record: rt_syscall_record {
|
|
next: null_mut(),
|
|
args: unsafe { transmute([0u8; size_of::<rt_syscall_args>()]) },
|
|
syscall: rt_syscall::RT_SYSCALL_TASK_READY,
|
|
},
|
|
priority,
|
|
base_priority: priority,
|
|
state: rt_task_state::RT_TASK_STATE_EXITED,
|
|
wake_tick: 0,
|
|
mutex_list: list_init(&t.mutex_list),
|
|
name: name.as_ptr(),
|
|
}),
|
|
_pin_marker: PhantomPinned,
|
|
}
|
|
}
|
|
|
|
pub fn start(&mut self, f: extern "C" fn(), stack: &mut [u8]) {
|
|
let t = self.t.get_mut();
|
|
unsafe {
|
|
t.ctx = rt_context_init(Some(f), stack.as_mut_ptr() as *mut c_void, stack.len());
|
|
rt_syscall_push(&mut t.record);
|
|
rt_syscall_pend();
|
|
}
|
|
}
|
|
}
|
|
|
|
#[macro_export]
|
|
macro_rules! task {
|
|
($fn: ident $params: tt, $stack_size: expr, $priority: expr) => {
|
|
$crate::paste::paste! {
|
|
{
|
|
static mut [< $fn:upper _TASK >]: rt::task::Task = rt::task::Task::init(
|
|
unsafe { &[< $fn:upper _TASK >] },
|
|
unsafe { core::ffi::CStr::from_bytes_with_nul_unchecked(core::concat!(core::stringify!($fn), "\0").as_bytes()) },
|
|
$priority,
|
|
);
|
|
static mut [< $fn:upper _TASK_STACK >]: [u8; $stack_size] = [0u8; $stack_size];
|
|
extern "C" fn [< $fn _c >]() {
|
|
$fn $params
|
|
}
|
|
unsafe {
|
|
[< $fn:upper _TASK >].start([< $fn _c >], [< $fn:upper _TASK_STACK >].as_mut_slice());
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
($fn: ident, $stack_size: expr, $priority: expr) => {
|
|
rt::task!($fn(), $stack_size, $priority);
|
|
};
|
|
}
|