From a78a53bebdb77360a954f179d7fc01be6a91dc16 Mon Sep 17 00:00:00 2001 From: Priec Date: Thu, 4 Dec 2025 12:13:54 +0100 Subject: [PATCH] working scheduler --- blinky/.cargo/config.toml | 5 + blinky/.gitignore | 1 + blinky/Cargo.lock | 240 ++++++++++++++++++++++++++++++++++++++ blinky/Cargo.toml | 11 ++ blinky/memory.x | 5 + blinky/src/main.rs | 35 ++++++ scheduler/src/main.rs | 95 +++++++++++++-- 7 files changed, 384 insertions(+), 8 deletions(-) create mode 100644 blinky/.cargo/config.toml create mode 100644 blinky/.gitignore create mode 100644 blinky/Cargo.lock create mode 100644 blinky/Cargo.toml create mode 100644 blinky/memory.x create mode 100644 blinky/src/main.rs diff --git a/blinky/.cargo/config.toml b/blinky/.cargo/config.toml new file mode 100644 index 0000000..b078fc8 --- /dev/null +++ b/blinky/.cargo/config.toml @@ -0,0 +1,5 @@ +[target.thumbv7em-none-eabihf] +rustflags = ["-C", "link-arg=-Tlink.x"] + +[build] +target = "thumbv7em-none-eabihf" diff --git a/blinky/.gitignore b/blinky/.gitignore new file mode 100644 index 0000000..2f7896d --- /dev/null +++ b/blinky/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/blinky/Cargo.lock b/blinky/Cargo.lock new file mode 100644 index 0000000..e5ef32d --- /dev/null +++ b/blinky/Cargo.lock @@ -0,0 +1,240 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "cast" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" +dependencies = [ + "rustc_version 0.4.1", +] + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield", + "embedded-hal 0.2.7", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d4dec46b34c299ccf6b036717ae0fce602faa4f4fe816d9013b9a7c9f5ba6" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "panic-halt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812" + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver 1.0.27", +] + +[[package]] +name = "scheduler" +version = "0.1.0" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "embedded-hal 1.0.0", + "panic-halt", + "tm4c123x-hal", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "syn" +version = "2.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tm4c-hal" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5660cb98ccfcc6acec17e09976e163a929bd353336db113ec46863c3bc70f8f" +dependencies = [ + "cast", + "cortex-m", + "embedded-hal 0.2.7", + "nb 1.1.0", +] + +[[package]] +name = "tm4c123x" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbdca3909d1c9ab4aba7a85b6b606f90b1bf4ae19a14c9bc4772b02017a82aad" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "vcell", +] + +[[package]] +name = "tm4c123x-hal" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b116355b0e64f19a52a232f4f53e9ab536c47d7870ea46ef87b73f903a702f9a" +dependencies = [ + "cast", + "cortex-m", + "embedded-hal 0.2.7", + "nb 1.1.0", + "tm4c-hal", + "tm4c123x", + "void", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] diff --git a/blinky/Cargo.toml b/blinky/Cargo.toml new file mode 100644 index 0000000..6705211 --- /dev/null +++ b/blinky/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "scheduler" +version = "0.1.0" +edition = "2024" + +[dependencies] +cortex-m = "0.7.7" +cortex-m-rt = "0.7.3" +embedded-hal = "1.0.0" +panic-halt = "0.2.0" +tm4c123x-hal = { version = "0.10.1", features = ["rt"] } diff --git a/blinky/memory.x b/blinky/memory.x new file mode 100644 index 0000000..c140005 --- /dev/null +++ b/blinky/memory.x @@ -0,0 +1,5 @@ +MEMORY +{ + FLASH : ORIGIN = 0x00000000, LENGTH = 256K + RAM : ORIGIN = 0x20000000, LENGTH = 32K +} diff --git a/blinky/src/main.rs b/blinky/src/main.rs new file mode 100644 index 0000000..865d93a --- /dev/null +++ b/blinky/src/main.rs @@ -0,0 +1,35 @@ +#![no_std] +#![no_main] + +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) +} + +#[entry] +fn main() -> ! { + let p = Peripherals::take().unwrap(); + let mut sc = p.SYSCTL.constrain(); + let ports = p.GPIO_PORTF.split(&sc.power_control); + let mut led = ports.pf1.into_push_pull_output(); + + 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 + } +} diff --git a/scheduler/src/main.rs b/scheduler/src/main.rs index c0e02bb..a378d84 100644 --- a/scheduler/src/main.rs +++ b/scheduler/src/main.rs @@ -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); } }