From 99a45ff28ed524abb62ff0d8f6dbfaa519d52c50 Mon Sep 17 00:00:00 2001 From: Per Lindgren Date: Tue, 24 Sep 2019 02:01:25 +0200 Subject: [PATCH] wip (problem with Pin) --- examples/generator.rs | 70 +++++++++++ gen.rs | 172 +++++++++++++++++++++++++++ macros/src/codegen.rs | 3 +- macros/src/codegen/hardware_tasks.rs | 111 +++++++++++++---- macros/src/codegen/post_init.rs | 25 ++++ macros/src/codegen/util.rs | 14 +++ macros/src/lib.rs | 3 +- src/lib.rs | 3 +- 8 files changed, 373 insertions(+), 28 deletions(-) create mode 100644 examples/generator.rs create mode 100644 gen.rs diff --git a/examples/generator.rs b/examples/generator.rs new file mode 100644 index 0000000000..bc51bc9c94 --- /dev/null +++ b/examples/generator.rs @@ -0,0 +1,70 @@ +//! examples/idle.rs +#![feature(generator_trait)] +#![feature(generators)] +#![feature(never_type)] +#![feature(type_alias_impl_trait)] +#![no_main] +#![no_std] + +use core::ops::Generator; +// use core::mem::MaybeUninit; + +// // #[task(binds = EXTI0, resources = [x])] +// // fn bar(cx: bar::Context) { +// // let x = cx.resources.x; +// // } + +// // expansion +// type Foo = impl Generator; + +// static mut X: MaybeUninit = MaybeUninit::uninit(); + +// fn main() { +// // init(); +// unsafe { +// X.as_mut_ptr().write(foo()); +// } +// // idle(); +// } + +// #![deny(unsafe_code)] + +use cortex_m_semihosting::{debug, hprintln}; +use lm3s6965::Interrupt; +use panic_semihosting as _; + +#[rtfm::app(device = lm3s6965)] +const APP: () = { + #[init] + fn init(_: init::Context) { + hprintln!("init").unwrap(); + rtfm::pend(Interrupt::GPIOA); + } + + #[idle] + fn idle(_: idle::Context) -> ! { + static mut X: u32 = 0; + + // Safe access to local `static mut` variable + let _x: &'static mut u32 = X; + + hprintln!("idle").unwrap(); + + debug::exit(debug::EXIT_SUCCESS); + + loop {} + } + + // #[task(binds = GPIOA, resources = [x])] + // in user code the return type will be `impl Generator<..>` + #[task(binds = GPIOA)] + fn foo1(ctx: foo1::Context) -> impl Generator { + move || loop { + // x.lock(|_| {}); + hprintln!("foo1_1").unwrap(); + yield; + hprintln!("foo1_2").unwrap(); + yield; + } + } +}; diff --git a/gen.rs b/gen.rs new file mode 100644 index 0000000000..0c6be84d2d --- /dev/null +++ b/gen.rs @@ -0,0 +1,172 @@ +#![feature(prelude_import)] +//! examples/idle.rs +#![feature(generator_trait)] +#![feature(generators)] +#![feature(never_type)] +#![feature(type_alias_impl_trait)] +#![no_main] +#![no_std] +#[prelude_import] +use core::prelude::v1::*; +#[macro_use] +extern crate core; +#[macro_use] +extern crate compiler_builtins; + +use core::ops::Generator; +// use core::mem::MaybeUninit; + +// // #[task(binds = EXTI0, resources = [x])] +// // fn bar(cx: bar::Context) { +// // let x = cx.resources.x; +// // } + +// // expansion +// type Foo = impl Generator; + +// static mut X: MaybeUninit = MaybeUninit::uninit(); + +// fn main() { +// // init(); +// unsafe { +// X.as_mut_ptr().write(foo()); +// } +// // idle(); +// } + +// #![deny(unsafe_code)] + +use cortex_m_semihosting::{debug, hprintln}; +use lm3s6965::Interrupt; +use panic_semihosting as _; + +#[allow(non_snake_case)] +fn init(_: init::Context) { + + + + // Safe access to local `static mut` variable + + + + + // #[task(binds = GPIOA, resources = [x])] + // in user code the return type will be `impl Generator<..>` + // x.lock(|_| {}); + ::cortex_m_semihosting::export::hstdout_str("init\n").unwrap(); + rtfm::pend(Interrupt::GPIOA); +} +#[allow(non_snake_case)] +fn idle(idle::Locals { X, .. }: idle::Locals, _: idle::Context) -> ! { + use rtfm::Mutex as _; + let _x: &'static mut u32 = X; + ::cortex_m_semihosting::export::hstdout_str("idle\n").unwrap(); + debug::exit(debug::EXIT_SUCCESS); + loop { } +} +type Generatorfoo1= impl : Generator; +static mut GENERATOR_FOO1: core::mem::MaybeUninit = + core::mem::MaybeUninit::uninit(); +#[allow(non_snake_case)] +fn foo1(ctx: foo1::Context) -> Generatorfoo1 { + use rtfm::Mutex as _; + move || + loop { + ::cortex_m_semihosting::export::hstdout_str("foo1_1\n").unwrap(); + yield; + ::cortex_m_semihosting::export::hstdout_str("foo1_2\n").unwrap(); + yield; + } +} +#[allow(non_snake_case)] +#[doc = "Initialization function"] +pub mod init { + #[doc = r" Execution context"] + pub struct Context { + #[doc = r" Core (Cortex-M) peripherals"] + pub core: rtfm::export::Peripherals, + } + impl Context<> { + #[inline(always)] + pub unsafe fn new(core: rtfm::export::Peripherals) -> Self { + Context{core,} + } + } +} +#[allow(non_snake_case)] +#[doc(hidden)] +pub struct idleLocals { + X: &'static mut u32, +} +impl idleLocals<> { + #[inline(always)] + unsafe fn new() -> Self { + static mut X: u32 = 0; + idleLocals{X: &mut X,} + } +} +#[allow(non_snake_case)] +#[doc = "Idle loop"] +pub mod idle { + #[doc(inline)] + pub use super::idleLocals as Locals; + #[doc = r" Execution context"] + pub struct Context { + } + impl Context<> { + #[inline(always)] + pub unsafe fn new(priority: &rtfm::export::Priority) -> Self { + Context{} + } + } +} +#[allow(non_snake_case)] +#[doc = "Hardware task"] +pub mod foo1 { + #[doc = r" Execution context"] + pub struct Context { + } + impl Context<> { + #[inline(always)] + pub unsafe fn new(priority: &rtfm::export::Priority) -> Self { + Context{} + } + } +} +#[doc = r" Implementation details"] +const APP: () = + { + #[doc = + r" Always include the device crate which contains the vector table"] + use lm3s6965 as _; + #[allow(non_snake_case)] + #[no_mangle] + unsafe fn GPIOA() { + const PRIORITY: u8 = 1u8; + rtfm::export::run(PRIORITY, + || + { + ::cortex_m_semihosting::export::hstdout_str("here\n").unwrap(); + core::pin::Pin::new(GENERATOR_FOO1.as_mut_ptr()).resume(); + }); + } + #[no_mangle] + unsafe extern "C" fn main() -> ! { + rtfm::export::interrupt::disable(); + let mut core: rtfm::export::Peripherals = + core::mem::transmute(()); + let _ = [(); ((1 << lm3s6965::NVIC_PRIO_BITS) - 1u8 as usize)]; + core.NVIC.set_priority(lm3s6965::Interrupt::GPIOA, + rtfm::export::logical2hw(1u8, + lm3s6965::NVIC_PRIO_BITS)); + rtfm::export::NVIC::unmask(lm3s6965::Interrupt::GPIOA); + let late = init(init::Context::new(core.into())); + const PRIORITY: u8 = 1u8; + unsafe { + GENERATOR_FOO1.as_mut_ptr().write(foo1(foo1::Context::new(&rtfm::export::Priority::new(PRIORITY)))); + }; + rtfm::export::interrupt::enable(); + idle(idle::Locals::new(), + idle::Context::new(&rtfm::export::Priority::new(0))) + } + }; diff --git a/macros/src/codegen.rs b/macros/src/codegen.rs index 0213848157..6007484975 100644 --- a/macros/src/codegen.rs +++ b/macros/src/codegen.rs @@ -39,7 +39,8 @@ pub fn app(app: &App, analysis: &Analysis, extra: &Extra) -> TokenStream2 { let (const_app_init, root_init, user_init, call_init) = init::codegen(core, app, analysis, extra); - let (const_app_post_init, post_init_stmts) = post_init::codegen(core, analysis, extra); + let (const_app_post_init, post_init_stmts) = + post_init::codegen(core, &app, analysis, extra); let (const_app_idle, root_idle, user_idle, call_idle) = idle::codegen(core, app, analysis, extra); diff --git a/macros/src/codegen/hardware_tasks.rs b/macros/src/codegen/hardware_tasks.rs index a9c2a2bdc7..e62330718c 100644 --- a/macros/src/codegen/hardware_tasks.rs +++ b/macros/src/codegen/hardware_tasks.rs @@ -29,6 +29,9 @@ pub fn codegen( let mut user_tasks = vec![]; for (name, task) in &app.hardware_tasks { + // per: debug + // println!("// -- name -- {:?}", name); + // println!("// -- task -- {:?}", task); let core = task.args.core; let cfg_core = util::cfg_core(core, app.args.cores); @@ -57,24 +60,47 @@ pub fn codegen( let priority = task.args.priority; let section = util::link_section("text", core); - const_app.push(quote!( - #[allow(non_snake_case)] - #[no_mangle] - #section - #cfg_core - unsafe fn #symbol() { - const PRIORITY: u8 = #priority; + if task.is_generator { + let gen_static = util::gen_static_ident(&name); + let gen_type = util::gen_type_ident(&name); + const_app.push(quote!( + #[allow(non_snake_case)] + #[no_mangle] + #section + #cfg_core + unsafe fn #symbol() { + const PRIORITY: u8 = #priority; - #let_instant + #let_instant - rtfm::export::run(PRIORITY, || { - crate::#name( - #locals_new - #name::Context::new(&rtfm::export::Priority::new(PRIORITY) #instant) - ) - }); - } - )); + rtfm::export::run(PRIORITY, || { + hprintln!("here").unwrap(); + // core::pin::Pin::new(crate::#gen_static.assume_init()).resume(); + // let stat = &mut core::mem::transmute::<_,#gen_type>(crate::#gen_static); + core::pin::Pin::new(#gen_static.as_mut_ptr()).resume(); + }); + } + )); + } else { + const_app.push(quote!( + #[allow(non_snake_case)] + #[no_mangle] + #section + #cfg_core + unsafe fn #symbol() { + const PRIORITY: u8 = #priority; + + #let_instant + + rtfm::export::run(PRIORITY, || { + crate::#name( + #locals_new + #name::Context::new(&rtfm::export::Priority::new(PRIORITY) #instant) + ) + }); + } + )); + } let mut needs_lt = false; @@ -116,16 +142,51 @@ pub fn codegen( let section = util::link_section("text", core); // XXX shouldn't this have a cfg_core? let locals_pat = locals_pat.iter(); - user_tasks.push(quote!( - #(#attrs)* - #[allow(non_snake_case)] - #section - fn #name(#(#locals_pat,)* #context: #name::Context) { - use rtfm::Mutex as _; - #(#stmts)* - } - )); + if task.is_generator { + // exapmle expansion + // type GeneratorFoo = impl Generator; + // static mut GENERATOR_FOO: MaybeUninit = MaybeUninit::uninit(); + // #[allow(non_snake_case)] + // fn foo(ctx: foo::Context) -> GeneratorFoo { + // use rtfm::Mutex as _; + // move || loop { yield } + // } + + let gen_type = util::gen_type_ident(&name); + let gen_static = util::gen_static_ident(&name); + + user_tasks.push(quote!( + type #gen_type = impl Generator; + )); + + user_tasks.push(quote!( + static mut #gen_static : core::mem::MaybeUninit<#gen_type> = core::mem::MaybeUninit::uninit(); + )); + + user_tasks.push(quote!( + #(#attrs)* + #[allow(non_snake_case)] + #section + fn #name(#(#locals_pat,)* #context: #name::Context) -> #gen_type { + use rtfm::Mutex as _; + + #(#stmts)* + } + )); + } else { + // generate ordinary task + user_tasks.push(quote!( + #(#attrs)* + #[allow(non_snake_case)] + #section + fn #name(#(#locals_pat,)* #context: #name::Context) { + use rtfm::Mutex as _; + + #(#stmts)* + } + )); + } } (const_app, root, user_tasks) diff --git a/macros/src/codegen/post_init.rs b/macros/src/codegen/post_init.rs index 19773e45bd..e3e3b20e01 100644 --- a/macros/src/codegen/post_init.rs +++ b/macros/src/codegen/post_init.rs @@ -1,11 +1,13 @@ use proc_macro2::TokenStream as TokenStream2; use quote::quote; +use rtfm_syntax::ast::App; use crate::{analyze::Analysis, check::Extra, codegen::util}; /// Generates code that runs after `#[init]` returns pub fn codegen( core: u8, + app: &App, analysis: &Analysis, extra: &Extra, ) -> (Vec, Vec) { @@ -148,6 +150,29 @@ pub fn codegen( } } + // initialize generators + for (name, task) in &app.hardware_tasks { + if task.is_generator { + // example expansion + // const PRIORITY: u8 = 1; + // unsafe { + // GeneratorFoo.as_mut_ptr().write(foo(foo::Context::new(PRIORITY))); + // } + let gen_static = util::gen_static_ident(&name); + let priority = task.args.priority; + + stmts.push(quote!( + const PRIORITY: u8 = #priority; + + unsafe { + #gen_static.as_mut_ptr().write( + #name(#name::Context::new(&rtfm::export::Priority::new(PRIORITY))) + ); + }; + )); + } + } + // enable the interrupts -- this completes the `init`-ialization phase stmts.push(quote!(rtfm::export::interrupt::enable();)); diff --git a/macros/src/codegen/util.rs b/macros/src/codegen/util.rs index 207272dc90..13f839bea1 100644 --- a/macros/src/codegen/util.rs +++ b/macros/src/codegen/util.rs @@ -323,3 +323,17 @@ pub fn suffixed(name: &str, core: u8) -> Ident { pub fn tq_ident(core: Core) -> Ident { Ident::new(&format!("TQ{}", core), Span::call_site()) } + +/// Generates the generator type +/// TODO: Should be CamelCase +pub fn gen_type_ident(name: &Ident) -> Ident { + Ident::new(&format!("Generator{}", name), Span::call_site()) +} + +/// Generates the generator type +pub fn gen_static_ident(name: &Ident) -> Ident { + Ident::new( + &format!("GENERATOR_{}", name).to_uppercase(), + Span::call_site(), + ) +} diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 54282e1ec8..0610928c03 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -1,4 +1,5 @@ -#![deny(warnings)] +// Per : remove comment +// #![deny(warnings)] extern crate proc_macro; diff --git a/src/lib.rs b/src/lib.rs index 959c9b7bc6..2b9e9659a1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,8 @@ #![deny(missing_docs)] #![deny(rust_2018_compatibility)] #![deny(rust_2018_idioms)] -#![deny(warnings)] +// Per : remove comment +// #![deny(warnings)] #![no_std] use core::ops::Sub;