Compare commits

..

11 Commits

13 changed files with 34 additions and 57 deletions

View File

@ -1,7 +1,6 @@
[target.armv7-none-eabihf] [target.armv7-none-eabihf]
rustflags = [ rustflags = [
"-C", "link-arg=-Tlink.x", "-C", "link-arg=-Tlink.x",
"-C", "target-feature=a9,armv7-a,neon",
"-C", "target-cpu=cortex-a9", "-C", "target-cpu=cortex-a9",
] ]

4
Cargo.lock generated
View File

@ -34,9 +34,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "compiler_builtins" name = "compiler_builtins"
version = "0.1.49" version = "0.1.70"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20b1438ef42c655665a8ab2c1c6d605a305f031d38d9be689ddfef41a20f3aa2" checksum = "80873f979f0a344a4ade87c2f70d9ccf5720b83b10c97ec7cd745895d021e85a"
[[package]] [[package]]
name = "core_io" name = "core_io"

View File

@ -4,7 +4,7 @@
"emit-debug-gdb-scripts": false, "emit-debug-gdb-scripts": false,
"env": "", "env": "",
"executables": true, "executables": true,
"features": "+v7,+vfp3,-d32,+thumb2,-neon", "features": "+v7,+vfp3,-d32,+thumb2,+neon,+a9,+armv7-a",
"is-builtin": false, "is-builtin": false,
"linker": "rust-lld", "linker": "rust-lld",
"linker-flavor": "ld.lld", "linker-flavor": "ld.lld",

View File

@ -1,8 +1,6 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
#![allow(incomplete_features)]
#![feature(naked_functions)] #![feature(naked_functions)]
#![feature(asm)]
#![feature(inline_const)] #![feature(inline_const)]
extern crate alloc; extern crate alloc;

6
flake.lock generated
View File

@ -2,11 +2,11 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1736867362, "lastModified": 1739206421,
"narHash": "sha256-i/UJ5I7HoqmFMwZEH6vAvBxOrjjOJNU739lnZnhUln8=", "narHash": "sha256-PwQASeL2cGVmrtQYlrBur0U20Xy07uSWVnFup2PHnDs=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "9c6b49aeac36e2ed73a8c472f1546f6d9cf1addc", "rev": "44534bc021b85c8d78e465021e21f33b856e2540",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@ -11,7 +11,7 @@
let let
pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import rust-overlay) crosspkgs-overlay ]; }; pkgs = import nixpkgs { system = "x86_64-linux"; overlays = [ (import rust-overlay) crosspkgs-overlay ]; };
rust = pkgs.rust-bin.nightly."2021-09-01".default.override { rust = pkgs.rust-bin.nightly."2022-04-01".default.override {
extensions = [ "rust-src" ]; extensions = [ "rust-src" ];
targets = [ ]; targets = [ ];
}; };
@ -113,7 +113,7 @@
}; };
}; };
nativeBuildInputs = [ cargo-xbuild pkgs.llvmPackages_13.clang-unwrapped ]; nativeBuildInputs = [ cargo-xbuild pkgs.llvmPackages_14.clang-unwrapped ];
buildPhase = '' buildPhase = ''
export XARGO_RUST_SRC="${rust}/lib/rustlib/src/rust/library" export XARGO_RUST_SRC="${rust}/lib/rustlib/src/rust/library"
export CARGO_HOME=$(mktemp -d cargo-home.XXX) export CARGO_HOME=$(mktemp -d cargo-home.XXX)
@ -169,7 +169,7 @@
pkgs.openocd pkgs.gdb pkgs.openocd pkgs.gdb
pkgs.openssh pkgs.rsync pkgs.openssh pkgs.rsync
pkgs.llvmPackages_13.clang-unwrapped pkgs.llvmPackages_14.clang-unwrapped
(pkgs.python3.withPackages(ps: [ ps.pyftdi ])) (pkgs.python3.withPackages(ps: [ ps.pyftdi ]))
]; ];
}; };

View File

@ -1,13 +1,12 @@
use alloc::{boxed::Box, vec::Vec};
use core::{ use core::{
cell::{RefCell, UnsafeCell}, cell::UnsafeCell,
future::Future, future::Future,
mem::MaybeUninit, mem::MaybeUninit,
pin::Pin, pin::Pin,
sync::atomic::{AtomicBool, Ordering}, sync::atomic::{AtomicBool, Ordering},
task::{Context, Poll, RawWaker, RawWakerVTable, Waker}, task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
}; };
use alloc::{boxed::Box, vec::Vec};
//use futures::future::FutureExt;
use pin_utils::pin_mut; use pin_utils::pin_mut;
// NOTE `*const ()` is &AtomicBool // NOTE `*const ()` is &AtomicBool
@ -39,35 +38,32 @@ fn wrap_waker(ready: &AtomicBool) -> Waker {
/// This is a singleton /// This is a singleton
pub struct Executor { pub struct Executor {
// Entered block_on() already? // Entered block_on() already?
in_block_on: RefCell<bool>, in_block_on: bool,
/// Tasks reside on the heap, so that we just queue pointers. They /// Tasks reside on the heap, so that we just queue pointers. They
/// must also be pinned in memory because our RawWaker is a pointer /// must also be pinned in memory because our RawWaker is a pointer
/// to their `ready` field. /// to their `ready` field.
tasks: RefCell<Vec<Pin<Box<Task>>>>, tasks: Vec<Pin<Box<Task>>>,
} }
impl Executor { impl Executor {
/// Creates a new instance of the executor /// Creates a new instance of the executor
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
in_block_on: RefCell::new(false), in_block_on: false,
tasks: RefCell::new(Vec::new()), tasks: Vec::new(),
} }
} }
pub fn block_on<T>(&self, f: impl Future<Output = T>) -> T { pub fn block_on<T>(&mut self, f: impl Future<Output = T>) -> T {
// we want to avoid reentering `block_on` because then all the code // we want to avoid reentering `block_on` because then all the code
// below has to become more complex. It's also likely that the // below has to become more complex. It's also likely that the
// application will only call `block_on` once on an infinite task // application will only call `block_on` once on an infinite task
// (`Future<Output = !>`) // (`Future<Output = !>`)
{ if self.in_block_on {
let mut in_block_on = self.in_block_on.borrow_mut();
if *in_block_on {
panic!("nested `block_on`"); panic!("nested `block_on`");
} }
*in_block_on = true; self.in_block_on = true;
}
pin_mut!(f); pin_mut!(f);
let ready = AtomicBool::new(true); let ready = AtomicBool::new(true);
@ -77,17 +73,14 @@ impl Executor {
// advance the main task // advance the main task
if ready.load(Ordering::Relaxed) { if ready.load(Ordering::Relaxed) {
ready.store(false, Ordering::Relaxed); ready.store(false, Ordering::Relaxed);
// println!("run block_on");
let mut cx = Context::from_waker(&waker); let mut cx = Context::from_waker(&waker);
if let Poll::Ready(val) = f.as_mut().poll(&mut cx) { if let Poll::Ready(val) = f.as_mut().poll(&mut cx) {
break val; break val;
} }
// println!("ran block_on");
} }
// advance all tasks // advance all tasks
core::mem::swap(&mut *self.tasks.borrow_mut(), &mut backup); core::mem::swap(&mut self.tasks, &mut backup);
for mut task in backup.drain(..) { for mut task in backup.drain(..) {
// NOTE we don't need a CAS operation here because `wake` invocations that come from // NOTE we don't need a CAS operation here because `wake` invocations that come from
// interrupt handlers (the only source of 'race conditions' (!= data races)) are // interrupt handlers (the only source of 'race conditions' (!= data races)) are
@ -106,20 +99,16 @@ impl Executor {
} }
} }
// Requeue // Requeue
self.tasks.borrow_mut().push(task); self.tasks.push(task);
} }
// // try to sleep; this will be a no-op if any of the previous tasks generated a SEV or an
// // interrupt ran (regardless of whether it generated a wake-up or not)
// asm::wfe();
}; };
self.in_block_on.replace(false); self.in_block_on = false;
val val
} }
pub fn spawn(&self, f: impl Future + 'static) { pub fn spawn(&mut self, f: impl Future<Output = ()> + 'static) {
let task = Box::pin(Task::new(f)); let task = Box::pin(Task::new(f));
self.tasks.borrow_mut().push(task); self.tasks.push(task);
} }
} }
@ -129,10 +118,10 @@ pub struct Task {
} }
impl Task { impl Task {
fn new(f: impl Future + 'static) -> Self { fn new(f: impl Future<Output = ()> + 'static) -> Self {
Task { Task {
ready: AtomicBool::new(true), ready: AtomicBool::new(true),
f: Box::pin(async { f.await; }), f: Box::pin(f),
} }
} }
} }
@ -140,18 +129,17 @@ impl Task {
/// Returns a handle to the executor singleton /// Returns a handle to the executor singleton
/// ///
/// This lazily initializes the executor and allocator when first called /// This lazily initializes the executor and allocator when first called
pub(crate) fn current() -> &'static Executor { pub(crate) fn current() -> &'static mut Executor {
static INIT: AtomicBool = AtomicBool::new(false); static INIT: AtomicBool = AtomicBool::new(false);
static mut EXECUTOR: UnsafeCell<MaybeUninit<Executor>> = UnsafeCell::new(MaybeUninit::uninit()); static mut EXECUTOR: UnsafeCell<MaybeUninit<Executor>> = UnsafeCell::new(MaybeUninit::uninit());
if INIT.load(Ordering::Relaxed) { if INIT.load(Ordering::Relaxed) {
unsafe { &*(EXECUTOR.get() as *const Executor) } unsafe { EXECUTOR.get_mut().assume_init_mut() }
} else { } else {
unsafe { unsafe {
let executorp = EXECUTOR.get() as *mut Executor; let executor = EXECUTOR.get_mut().write(Executor::new());
executorp.write(Executor::new());
INIT.store(true, Ordering::Relaxed); INIT.store(true, Ordering::Relaxed);
&*executorp executor
} }
} }
} }

View File

@ -17,7 +17,7 @@ pub fn block_on<T>(f: impl Future<Output = T>) -> T {
/// Spawns a task onto the executor /// Spawns a task onto the executor
/// ///
/// The spawned task will not make any progress until `block_on` is called. /// The spawned task will not make any progress until `block_on` is called.
pub fn spawn(f: impl Future + 'static) { pub fn spawn(f: impl Future<Output = ()> + 'static) {
executor::current().spawn(f) executor::current().spawn(f)
} }

View File

@ -1,10 +1,6 @@
#![no_std] #![no_std]
#![feature(never_type)] #![feature(never_type)]
#![feature(global_asm)]
#![feature(asm)]
#![allow(incomplete_features)]
#![feature(inline_const)] #![feature(inline_const)]
#![feature(const_fn_trait_bound)]
extern crate alloc; extern crate alloc;

View File

@ -177,10 +177,7 @@ macro_rules! sync_channel {
{ {
use core::sync::atomic::{AtomicUsize, AtomicPtr}; use core::sync::atomic::{AtomicUsize, AtomicPtr};
use $crate::sync_channel::{Sender, Receiver}; use $crate::sync_channel::{Sender, Receiver};
const fn new_atomic() -> AtomicPtr<$t> { static LIST: [AtomicPtr<$t>; $cap + 1] = [const { AtomicPtr::new(core::ptr::null_mut()) }; $cap + 1];
AtomicPtr::new(core::ptr::null_mut())
}
static LIST: [AtomicPtr<$t>; $cap + 1] = [const { new_atomic() }; $cap + 1];
static WRITE: AtomicUsize = AtomicUsize::new(0); static WRITE: AtomicUsize = AtomicUsize::new(0);
static READ: AtomicUsize = AtomicUsize::new(0); static READ: AtomicUsize = AtomicUsize::new(0);
(Sender::new(&LIST, &WRITE, &READ), Receiver::new(&LIST, &WRITE, &READ)) (Sender::new(&LIST, &WRITE, &READ), Receiver::new(&LIST, &WRITE, &READ))

View File

@ -20,7 +20,7 @@ default = ["panic_handler", "dummy_irq_handler", "dummy_fiq_handler"]
[dependencies] [dependencies]
r0 = "1" r0 = "1"
compiler_builtins = "=0.1.49" compiler_builtins = "=0.1.70"
linked_list_allocator = { version = "0.8", default-features = false, features = ["const_mut_refs"] } linked_list_allocator = { version = "0.8", default-features = false, features = ["const_mut_refs"] }
libregister = { path = "../libregister" } libregister = { path = "../libregister" }
libcortex_a9 = { path = "../libcortex_a9" } libcortex_a9 = { path = "../libcortex_a9" }

View File

@ -66,6 +66,7 @@ unsafe extern "C" fn boot_core0() -> ! {
unsafe extern "C" fn boot_core1() -> ! { unsafe extern "C" fn boot_core1() -> ! {
l1_cache_init(); l1_cache_init();
enable_fpu();
let mpcore = mpcore::RegisterBlock::mpcore(); let mpcore = mpcore::RegisterBlock::mpcore();
mpcore.scu_invalidate.invalidate_core1(); mpcore.scu_invalidate.invalidate_core1();

View File

@ -3,8 +3,6 @@
#![feature(alloc_error_handler)] #![feature(alloc_error_handler)]
#![feature(panic_info_message)] #![feature(panic_info_message)]
#![feature(naked_functions)] #![feature(naked_functions)]
#![feature(global_asm)]
#![feature(asm)]
pub extern crate alloc; pub extern crate alloc;
pub extern crate compiler_builtins; pub extern crate compiler_builtins;