From e97afa71ce7bf3d78e257de1aab329135e98c721 Mon Sep 17 00:00:00 2001 From: Jorge Aparicio Date: Mon, 20 Nov 2017 05:11:25 +0100 Subject: [PATCH] peripherals as scoped singletons --- Cargo.toml | 9 +++++---- examples/generics.rs | 12 +++++++++++- examples/one-task.rs | 34 +++++++++++++++++++++------------- examples/zero-tasks.rs | 5 +++-- macros/src/check.rs | 18 ++++++++++++++---- macros/src/trans.rs | 18 +++++++++++++----- src/lib.rs | 2 +- 7 files changed, 68 insertions(+), 30 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5675d76749..37db8565e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,13 +10,13 @@ keywords = ["arm", "cortex-m"] license = "MIT OR Apache-2.0" name = "cortex-m-rtfm" repository = "https://github.com/japaric/cortex-m-rtfm" -version = "0.2.2" +version = "0.3.0" [dependencies] -cortex-m = "0.3.1" +cortex-m = { git = "https://github.com/japaric/cortex-m" } untagged-option = "0.1.1" rtfm-core = "0.1.0" -cortex-m-rtfm-macros = "0.2.1" +cortex-m-rtfm-macros = { path = "macros" } [target.'cfg(target_arch = "x86_64")'.dev-dependencies] compiletest_rs = "0.3.3" @@ -27,7 +27,8 @@ version = "0.3.3" [dev-dependencies.stm32f103xx] features = ["rt"] -version = "0.7.5" +git = "https://github.com/japaric/stm32f103xx" +# version = "0.8.0" [profile.release] lto = true diff --git a/examples/generics.rs b/examples/generics.rs index 57c9b8ebc6..afcafa0a40 100644 --- a/examples/generics.rs +++ b/examples/generics.rs @@ -12,6 +12,11 @@ use stm32f103xx::{SPI1, GPIOA}; app! { device: stm32f103xx, + resources: { + static GPIOA: GPIOA; + static SPI1: SPI1; + }, + tasks: { EXTI0: { path: exti0, @@ -27,7 +32,12 @@ app! { }, } -fn init(_p: init::Peripherals) {} +fn init(p: init::Peripherals) -> init::LateResourceValues { + init::LateResourceValues { + GPIOA: p.device.GPIOA, + SPI1: p.device.SPI1, + } +} fn idle() -> ! { loop { diff --git a/examples/one-task.rs b/examples/one-task.rs index e58d9fcd90..38f0135467 100644 --- a/examples/one-task.rs +++ b/examples/one-task.rs @@ -7,8 +7,9 @@ extern crate cortex_m; extern crate cortex_m_rtfm as rtfm; extern crate stm32f103xx; -use cortex_m::peripheral::SystClkSource; +use cortex_m::peripheral::syst::SystClkSource; use rtfm::{app, Threshold}; +use stm32f103xx::GPIOC; app! { device: stm32f103xx, @@ -35,9 +36,8 @@ app! { // These are the resources this task has access to. // - // A resource can be a peripheral like `GPIOC` or a static variable - // like `ON` - resources: [GPIOC, ON], + // The resources listed here must also appear in `app.resources` + resources: [ON], }, } } @@ -47,19 +47,20 @@ fn init(p: init::Peripherals, r: init::Resources) { r.ON; // power on GPIOC - p.RCC.apb2enr.modify(|_, w| w.iopcen().enabled()); + p.device.RCC.apb2enr.modify(|_, w| w.iopcen().enabled()); // configure PC13 as output - p.GPIOC.bsrr.write(|w| w.bs13().set()); - p.GPIOC + p.device.GPIOC.bsrr.write(|w| w.bs13().set()); + p.device + .GPIOC .crh .modify(|_, w| w.mode13().output().cnf13().push()); // configure the system timer to generate one interrupt every second - p.SYST.set_clock_source(SystClkSource::Core); - p.SYST.set_reload(8_000_000); // 1s - p.SYST.enable_interrupt(); - p.SYST.enable_counter(); + p.core.SYST.set_clock_source(SystClkSource::Core); + p.core.SYST.set_reload(8_000_000); // 1s + p.core.SYST.enable_interrupt(); + p.core.SYST.enable_counter(); } fn idle() -> ! { @@ -74,15 +75,22 @@ fn idle() -> ! { // // `r` is the set of resources this task has access to. `SYS_TICK::Resources` // has one field per resource declared in `app!`. +#[allow(unsafe_code)] fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) { // toggle state **r.ON = !**r.ON; if **r.ON { // set the pin PC13 high - r.GPIOC.bsrr.write(|w| w.bs13().set()); + // NOTE(unsafe) atomic write to a stateless register + unsafe { + (*GPIOC::ptr()).bsrr.write(|w| w.bs13().set()); + } } else { // set the pin PC13 low - r.GPIOC.bsrr.write(|w| w.br13().reset()); + // NOTE(unsafe) atomic write to a stateless register + unsafe { + (*GPIOC::ptr()).bsrr.write(|w| w.br13().reset()); + } } } diff --git a/examples/zero-tasks.rs b/examples/zero-tasks.rs index 9176103d43..58e6afc76c 100644 --- a/examples/zero-tasks.rs +++ b/examples/zero-tasks.rs @@ -25,8 +25,9 @@ app! { // this function. fn init(p: init::Peripherals) { // This function has access to all the peripherals of the device - p.GPIOA; - p.RCC; + p.core.SYST; + p.device.GPIOA; + p.device.RCC; // .. } diff --git a/macros/src/check.rs b/macros/src/check.rs index 3cd112acfd..63cac1fa5e 100644 --- a/macros/src/check.rs +++ b/macros/src/check.rs @@ -63,16 +63,15 @@ pub fn app(app: check::App) -> Result { tasks: app.tasks .into_iter() .map(|(k, v)| { - let v = ::check::task(k.as_ref(), v) - .chain_err(|| format!("checking task `{}`", k))?; + let v = + ::check::task(k.as_ref(), v).chain_err(|| format!("checking task `{}`", k))?; Ok((k, v)) }) .collect::>()?, }; - ::check::resources(&app) - .chain_err(|| "checking `resources`")?; + ::check::resources(&app).chain_err(|| "checking `resources`")?; Ok(app) } @@ -93,6 +92,17 @@ fn resources(app: &App) -> Result<()> { bail!("resource `{}` is unused", resource); } + for (name, task) in &app.tasks { + for resource in &task.resources { + ensure!( + app.resources.contains_key(&resource), + "task {} contains an undeclared resource with name {}", + name, + resource + ); + } + } + Ok(()) } diff --git a/macros/src/trans.rs b/macros/src/trans.rs index 96ff770b64..b97ff4086a 100644 --- a/macros/src/trans.rs +++ b/macros/src/trans.rs @@ -161,8 +161,13 @@ fn init(app: &App, main: &mut Vec, root: &mut Vec) { let device = &app.device; let krate = krate(); - let mut tys = vec![quote!(#device::Peripherals)]; - let mut exprs = vec![quote!(#device::Peripherals::all())]; + let mut tys = vec![quote!(init::Peripherals)]; + let mut exprs = vec![quote!{ + init::Peripherals { + core: ::#device::CorePeripherals::steal(), + device: ::#device::Peripherals::steal(), + } + }]; let mut ret = None; let mut mod_items = vec![]; @@ -255,7 +260,10 @@ fn init(app: &App, main: &mut Vec, root: &mut Vec) { root.push(quote! { #[allow(unsafe_code)] mod init { - pub use ::#device::Peripherals; + pub struct Peripherals { + pub core: ::#device::CorePeripherals, + pub device: ::#device::Peripherals, + } #(#mod_items)* } @@ -268,7 +276,7 @@ fn init(app: &App, main: &mut Vec, root: &mut Vec) { Kind::Exception(ref e) => { if exceptions.is_empty() { exceptions.push(quote! { - let scb = &*#device::SCB.get(); + let scb = &*#device::SCB::ptr(); }); } @@ -284,7 +292,7 @@ fn init(app: &App, main: &mut Vec, root: &mut Vec) { // Interrupt. These can be enabled / disabled through the NVIC if interrupts.is_empty() { interrupts.push(quote! { - let nvic = &*#device::NVIC.get(); + let nvic = &*#device::NVIC::ptr(); }); } diff --git a/src/lib.rs b/src/lib.rs index 4ab8ec58d9..f5481bc401 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -160,6 +160,6 @@ where I: Nr, { // NOTE(safe) atomic write - let nvic = unsafe { &*cortex_m::peripheral::NVIC.get() }; + let nvic = unsafe { &*cortex_m::peripheral::NVIC::ptr() }; nvic.set_pending(interrupt); }