use core::ops::Range;
use r3_core::kernel::{InterruptNum, InterruptPriority};
pub const INTERRUPT_PRIORITY_RANGE: Range<InterruptPriority> = 0..256;
pub const INTERRUPT_SYSTICK: InterruptNum = 15;
pub const INTERRUPT_EXTERNAL0: InterruptNum = 16;
pub const INTERRUPT_NUM_RANGE: Range<InterruptNum> = 0..256;
pub trait ThreadingOptions {
const CPU_LOCK_PRIORITY_MASK: u8 = 0;
const USE_WFI: bool = true;
unsafe fn interrupt_stack_top() -> usize {
#[cfg(target_os = "none")]
{
let peripherals = unsafe { cortex_m::Peripherals::steal() };
unsafe { (peripherals.SCB.vtor.read() as *const usize).read_volatile() }
}
#[cfg(not(target_os = "none"))]
panic!("unsupported target")
}
}
pub unsafe trait EntryPoint {
unsafe fn start() -> !;
const HANDLE_PEND_SV: unsafe extern "C" fn();
}
#[macro_export]
macro_rules! use_port {
(unsafe $vis:vis struct $Traits:ident) => {
$vis struct $Traits;
mod port_arm_m_impl {
use super::$Traits;
use $crate::r3_core::kernel::{
ClearInterruptLineError, EnableInterruptLineError, InterruptNum, InterruptPriority,
PendInterruptLineError, QueryInterruptLineError, SetInterruptLinePriorityError,
};
use $crate::r3_kernel::{
Port, TaskCb, PortToKernel, PortInterrupts, PortThreading, UTicks, PortTimer,
};
use $crate::core::ops::Range;
use $crate::threading::{
imp::{State, TaskState, PortInstance},
cfg::{ThreadingOptions, EntryPoint},
};
static PORT_STATE: State = $crate::r3_core::utils::Init::INIT;
unsafe impl PortInstance for $Traits {
$crate::r3_portkit::sym::sym_static!(
#[sym(p_port_state)] fn port_state() -> &State { &PORT_STATE });
}
unsafe impl PortThreading for $Traits {
type PortTaskState = TaskState;
#[allow(clippy::declare_interior_mutable_const)]
const PORT_TASK_STATE_INIT: Self::PortTaskState =
$crate::r3_core::utils::Init::INIT;
const STACK_DEFAULT_SIZE: usize = 2048;
const STACK_ALIGN: usize = 8;
#[inline(always)]
unsafe fn dispatch_first_task() -> ! {
PORT_STATE.dispatch_first_task::<Self>()
}
#[inline(always)]
unsafe fn yield_cpu() {
PORT_STATE.yield_cpu::<Self>()
}
#[inline(always)]
unsafe fn exit_and_dispatch(task: &'static TaskCb<Self>) -> ! {
PORT_STATE.exit_and_dispatch::<Self>(task);
}
#[inline(always)]
unsafe fn enter_cpu_lock() {
PORT_STATE.enter_cpu_lock::<Self>()
}
#[inline(always)]
unsafe fn leave_cpu_lock() {
PORT_STATE.leave_cpu_lock::<Self>()
}
#[inline(always)]
unsafe fn initialize_task_state(task: &'static TaskCb<Self>) {
PORT_STATE.initialize_task_state::<Self>(task)
}
#[inline(always)]
fn is_cpu_lock_active() -> bool {
PORT_STATE.is_cpu_lock_active::<Self>()
}
#[inline(always)]
fn is_task_context() -> bool {
PORT_STATE.is_task_context::<Self>()
}
#[inline(always)]
fn is_interrupt_context() -> bool {
PORT_STATE.is_interrupt_context::<Self>()
}
#[inline(always)]
fn is_scheduler_active() -> bool {
PORT_STATE.is_scheduler_active::<Self>()
}
}
unsafe impl PortInterrupts for $Traits {
const MANAGED_INTERRUPT_PRIORITY_RANGE: Range<InterruptPriority> =
(<$Traits as ThreadingOptions>::CPU_LOCK_PRIORITY_MASK as _)..256;
unsafe fn set_interrupt_line_priority(
line: InterruptNum,
priority: InterruptPriority,
) -> Result<(), SetInterruptLinePriorityError> {
PORT_STATE.set_interrupt_line_priority::<Self>(line, priority)
}
unsafe fn enable_interrupt_line(line: InterruptNum) -> Result<(), EnableInterruptLineError> {
PORT_STATE.enable_interrupt_line::<Self>(line)
}
unsafe fn disable_interrupt_line(line: InterruptNum) -> Result<(), EnableInterruptLineError> {
PORT_STATE.disable_interrupt_line::<Self>(line)
}
unsafe fn pend_interrupt_line(line: InterruptNum) -> Result<(), PendInterruptLineError> {
PORT_STATE.pend_interrupt_line::<Self>(line)
}
unsafe fn clear_interrupt_line(line: InterruptNum) -> Result<(), ClearInterruptLineError> {
PORT_STATE.clear_interrupt_line::<Self>(line)
}
unsafe fn is_interrupt_line_pending(
line: InterruptNum,
) -> Result<bool, QueryInterruptLineError> {
PORT_STATE.is_interrupt_line_pending::<Self>(line)
}
}
unsafe impl EntryPoint for $Traits {
#[inline]
unsafe fn start() -> ! {
unsafe { PORT_STATE.port_boot::<$Traits>() }
}
const HANDLE_PEND_SV: unsafe extern "C" fn() =
State::handle_pend_sv::<$Traits>;
}
}
const _: () = $crate::threading::imp::validate::<$Traits>();
};
}