Skip to content

Commit

Permalink
riot-rs-threads: cortex_m: make sched() less hacky
Browse files Browse the repository at this point in the history
  • Loading branch information
kaspar030 committed May 2, 2024
1 parent 41f1301 commit 67d5a40
Showing 1 changed file with 42 additions and 53 deletions.
95 changes: 42 additions & 53 deletions src/riot-rs-threads/src/arch/cortex_m.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use super::Arch;
use core::arch::asm;
use core::ptr::write_volatile;
use cortex_m::peripheral::SCB;
use critical_section::CriticalSection;

use crate::{cleanup, THREADS};

Expand Down Expand Up @@ -75,9 +74,7 @@ unsafe extern "C" fn PendSV() {
unsafe {
asm!(
"
cpsid i
bl {sched}
cpsie i
cmp r0, #0
/* label rules:
* - number only
Expand Down Expand Up @@ -108,9 +105,7 @@ unsafe extern "C" fn PendSV() {
unsafe {
asm!(
"
cpsid i
bl sched
cpsie i
cmp r0, #0
beq 99f
Expand Down Expand Up @@ -168,55 +163,49 @@ unsafe extern "C" fn PendSV() {
/// This function is called in PendSV.
// TODO: make arch independent, or move to arch
#[no_mangle]
unsafe fn sched() -> usize {
// SAFETY: interrupts are disabled by caller
let cs = unsafe { CriticalSection::new() };
let next_pid;

unsafe fn sched() -> u128 {
loop {
{
if let Some(pid) = (unsafe { &*THREADS.as_ptr(cs) }).runqueue.get_next() {
next_pid = pid;
break;
}
}
//pm_set_lowest();
cortex_m::asm::wfi();
unsafe { cortex_m::interrupt::enable() };
cortex_m::asm::isb();
// pending interrupts would now get to run their ISRs
cortex_m::interrupt::disable();
}

let threads = unsafe { &mut *THREADS.as_ptr(cs) };
let current_high_regs;

if let Some(current_pid) = threads.current_pid() {
if next_pid == current_pid {
return 0;
if let Some(res) = critical_section::with(|cs| {
let threads = unsafe { &mut *THREADS.as_ptr(cs) };
let next_pid = match threads.runqueue.get_next() {
Some(pid) => pid,
None => {
cortex_m::asm::wfi();
return None;
}
};

let current_high_regs;
if let Some(current_pid) = threads.current_pid() {
if next_pid == current_pid {
return Some(0);
}

threads.threads[current_pid as usize].sp = cortex_m::register::psp::read() as usize;
threads.current_thread = Some(next_pid);

current_high_regs = threads.threads[current_pid as usize].data.as_ptr();
} else {
threads.current_thread = Some(next_pid);
current_high_regs = core::ptr::null();
};

let next = &threads.threads[next_pid as usize];
let next_sp = next.sp as usize;
let next_high_regs = next.data.as_ptr() as usize;

// PendSV expects these three pointers in r0, r1 and r2:
// r0 = &next.sp
// r1 = &current.high_regs
// r2 = &next.high_regs
// On Cortex-M, a u128 as return value is passed in registers r0-r3.
// So let's use that.
let res: u128 =
// (r0) (r1) (r2)
(next_sp as u128) | ((current_high_regs as u128) << 32) | ((next_high_regs as u128) << 64);
Some(res)
}) {
break res;
}
//println!("current: {} next: {}", current_pid, next_pid);
threads.threads[current_pid as usize].sp = cortex_m::register::psp::read() as usize;
threads.current_thread = Some(next_pid);
current_high_regs = threads.threads[current_pid as usize].data.as_ptr();
} else {
threads.current_thread = Some(next_pid);
current_high_regs = core::ptr::null();
}

let next = &threads.threads[next_pid as usize];
let next_sp = next.sp;
let next_high_regs = next.data.as_ptr();

//println!("old_sp: {:x} next.sp: {:x}", old_sp, next_sp);

// PendSV expects these three pointers in r0, r1 and r2:
// r1= &current.high_regs
// r2= &next.high_regs
// r0 = &next.sp (implicitly done here via return value)
//
// write to registers manually, as ABI would return the values via stack
unsafe { asm!("", in("r1") current_high_regs, in("r2") next_high_regs) };

next_sp
}

0 comments on commit 67d5a40

Please sign in to comment.