#![allow(non_snake_case, non_camel_case_types, non_upper_case_globals)]
use core::{
ffi::{c_char, c_ulong, c_void},
ptr,
};
use bytemuck::Zeroable;
unsafe extern "C" {
pub unsafe static mut pxCurrentTCB: TaskHandle_t;
#[cfg_attr(feature = "pros", link_name = "rtos_suspend_all")]
pub safe fn vTaskSuspendAll();
pub unsafe fn uxTaskGetSystemState(
pxTaskStatusArray: *mut TaskStatus_t,
uxArraySize: UBaseType_t,
pulTotalRunTime: *mut c_ulong,
) -> UBaseType_t;
pub unsafe fn vTaskGetInfo(
xTask: TaskHandle_t,
pxTaskStatus: *mut TaskStatus_t,
xGetFreeStackSpace: BaseType_t,
eState: eTaskState,
);
}
#[derive(Debug, Clone, Copy, Zeroable, PartialEq, Eq)]
#[repr(C)]
pub struct TaskHandle_t(pub *mut c_void);
impl TaskHandle_t {
pub const CURRENT: Self = Self(ptr::null_mut());
}
#[derive(Debug, Clone, Copy, Zeroable, PartialEq, Eq)]
#[repr(C)]
pub struct TaskStatus_t {
pub xHandle: TaskHandle_t,
pub pcTaskName: *const c_char,
pub xTaskNumber: u32,
pub eCurrentState: eTaskState,
pub uxCurrentPriority: u32,
pub uxBasePriority: u32,
pub ulRunTimeCounter: u32,
pub pxStackBase: StackType_t,
pub usStackHighWaterMark: u16,
}
impl TaskStatus_t {
fn tcb_ptr(&self) -> *mut TaskControlBlock {
self.xHandle.0.cast()
}
pub unsafe fn sp(&self) -> u32 {
let stack_ptr = unsafe { (*self.tcb_ptr()).stack_ptr };
stack_ptr + size_of::<SavedTaskContextFPU>() as u32
}
pub unsafe fn set_sp(&self, mut sp: u32, update_ctx: bool) {
sp -= size_of::<SavedTaskContextFPU>() as u32;
unsafe {
let old_ctx = self.saved_context();
(*self.tcb_ptr()).stack_ptr = sp;
if update_ctx {
ptr::copy(old_ctx, sp as *mut SavedTaskContextFPU, 1);
}
}
}
pub unsafe fn saved_context(&self) -> *mut SavedTaskContextFPU {
unsafe {
let stack_ptr = (*self.tcb_ptr()).stack_ptr;
let ctx = stack_ptr as *mut SavedTaskContextFPU;
let is_fpu = (*ctx).ulPortTaskHasFPUContext != 0;
if is_fpu {
ctx
} else {
unimplemented!("tasks without fpu contexts")
}
}
}
}
unsafe impl Send for TaskStatus_t {}
#[derive(Debug, Clone, Copy, Zeroable, PartialEq, Eq)]
#[repr(C)]
pub struct eTaskState(u32);
impl eTaskState {
pub const RUNNING: Self = Self(0);
pub const READY: Self = Self(1);
pub const BLOCKED: Self = Self(2);
pub const SUSPENDED: Self = Self(3);
pub const DELETED: Self = Self(4);
}
#[repr(C)]
struct TaskControlBlock {
stack_ptr: u32,
}
#[repr(C)]
pub struct SavedTaskContextFPU {
ulPortTaskHasFPUContext: u32,
pub fpu: FPUContext,
pub base: BaseContext,
}
impl SavedTaskContextFPU {
pub fn new(fpu: FPUContext, base: BaseContext) -> Self {
Self {
ulPortTaskHasFPUContext: 1,
fpu,
base,
}
}
}
#[repr(C)]
pub struct FPUContext {
pub fpscr: u32,
pub d16_d31: [[u32; 2]; 16],
pub d0_d15: [[u32; 2]; 16],
}
#[repr(C)]
pub struct BaseContext {
pub ulCriticalNesting: u32,
pub gp_registers: [u32; 13],
pub lr: u32,
pub pc: u32,
pub spsr: u32,
}
pub type StackType_t = u32;
pub type BaseType_t = i32;
pub type UBaseType_t = u32;
pub const pdFALSE: i32 = 0;