working scheduler
This commit is contained in:
@@ -1,23 +1,102 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
use cortex_m::peripheral::syst::SystClkSource;
|
||||
use cortex_m_rt::entry;
|
||||
use panic_halt as _;
|
||||
use tm4c123x_hal::{Peripherals, prelude::*};
|
||||
use tm4c123x_hal::tm4c123x as _;
|
||||
use embedded_hal::digital::OutputPin;
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
static SYS_TICKS: AtomicU32 = AtomicU32::new(0);
|
||||
|
||||
#[cortex_m_rt::exception]
|
||||
fn SysTick() {
|
||||
SYS_TICKS.fetch_add(1, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn millis() -> u32 {
|
||||
SYS_TICKS.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn busy_delay(ms: u32) {
|
||||
let start = millis();
|
||||
while millis() - start < ms {}
|
||||
}
|
||||
|
||||
fn task1() { busy_delay(10_000); }
|
||||
fn task2() { busy_delay(10_000); }
|
||||
fn task3() { busy_delay(10_000); }
|
||||
fn task4() { busy_delay(10_000); }
|
||||
fn opt1() { busy_delay(3_000); }
|
||||
fn opt2() { busy_delay(4_000); }
|
||||
|
||||
struct Task {
|
||||
name: &'static str,
|
||||
duration_ms: u32,
|
||||
active: bool,
|
||||
func: fn(),
|
||||
}
|
||||
|
||||
static TASKS_MAIN: [Task; 4] = [
|
||||
Task { name: "T1", duration_ms: 10_000, active: true, func: task1 },
|
||||
Task { name: "T2", duration_ms: 10_000, active: true, func: task2 },
|
||||
Task { name: "T3", duration_ms: 10_000, active: true, func: task3 },
|
||||
Task { name: "T4", duration_ms: 10_000, active: true, func: task4 },
|
||||
];
|
||||
|
||||
static TASKS_OPT: [Task; 2] = [
|
||||
Task { name: "Opt1", duration_ms: 3_000, active: true, func: opt1 },
|
||||
Task { name: "Opt2", duration_ms: 4_000, active: true, func: opt2 },
|
||||
];
|
||||
|
||||
const MAJOR_FRAME_MS: u32 = 120_000;
|
||||
|
||||
fn run_optionals(tasks: &[Task], mut remaining: u32) {
|
||||
for t in tasks {
|
||||
if t.duration_ms <= remaining {
|
||||
(t.func)();
|
||||
remaining -= t.duration_ms;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn scheduler(tasks_main: &[Task], tasks_optional: &[Task]) {
|
||||
let start_time = millis();
|
||||
|
||||
for t in tasks_main {
|
||||
(t.func)();
|
||||
}
|
||||
|
||||
let elapsed = millis() - start_time;
|
||||
|
||||
if elapsed < MAJOR_FRAME_MS {
|
||||
run_optionals(tasks_optional, MAJOR_FRAME_MS - elapsed);
|
||||
}
|
||||
|
||||
// Wait out the frame so each cycle lasts exactly 120 s
|
||||
while millis() - start_time < MAJOR_FRAME_MS {}
|
||||
}
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
let cp = cortex_m::Peripherals::take().unwrap();
|
||||
let p = Peripherals::take().unwrap();
|
||||
|
||||
// System control and clock
|
||||
let mut sc = p.SYSCTL.constrain();
|
||||
let ports = p.GPIO_PORTF.split(&sc.power_control);
|
||||
let mut led = ports.pf1.into_push_pull_output();
|
||||
let clocks = sc.clock_setup.freeze(); // default 16 MHz
|
||||
|
||||
// SysTick 1 ms tick
|
||||
let mut syst = cp.SYST;
|
||||
syst.set_clock_source(SystClkSource::Core);
|
||||
syst.set_reload(16_000 - 1); // 16 MHz / 16_000 = 1 kHz
|
||||
syst.clear_current();
|
||||
syst.enable_counter();
|
||||
syst.enable_interrupt();
|
||||
|
||||
loop {
|
||||
led.set_high();
|
||||
cortex_m::asm::delay(1_000_000); // ~0.5 s @ 16 MHz
|
||||
led.set_low();
|
||||
cortex_m::asm::delay(1_000_000); // ~0.5 s
|
||||
scheduler(&TASKS_MAIN, &TASKS_OPT);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user