Skip to content
Snippets Groups Projects
Commit e97afa71 authored by Jorge Aparicio's avatar Jorge Aparicio
Browse files

peripherals as scoped singletons

parent e620b1e5
No related branches found
No related tags found
No related merge requests found
...@@ -10,13 +10,13 @@ keywords = ["arm", "cortex-m"] ...@@ -10,13 +10,13 @@ keywords = ["arm", "cortex-m"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
name = "cortex-m-rtfm" name = "cortex-m-rtfm"
repository = "https://github.com/japaric/cortex-m-rtfm" repository = "https://github.com/japaric/cortex-m-rtfm"
version = "0.2.2" version = "0.3.0"
[dependencies] [dependencies]
cortex-m = "0.3.1" cortex-m = { git = "https://github.com/japaric/cortex-m" }
untagged-option = "0.1.1" untagged-option = "0.1.1"
rtfm-core = "0.1.0" 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] [target.'cfg(target_arch = "x86_64")'.dev-dependencies]
compiletest_rs = "0.3.3" compiletest_rs = "0.3.3"
...@@ -27,7 +27,8 @@ version = "0.3.3" ...@@ -27,7 +27,8 @@ version = "0.3.3"
[dev-dependencies.stm32f103xx] [dev-dependencies.stm32f103xx]
features = ["rt"] features = ["rt"]
version = "0.7.5" git = "https://github.com/japaric/stm32f103xx"
# version = "0.8.0"
[profile.release] [profile.release]
lto = true lto = true
...@@ -12,6 +12,11 @@ use stm32f103xx::{SPI1, GPIOA}; ...@@ -12,6 +12,11 @@ use stm32f103xx::{SPI1, GPIOA};
app! { app! {
device: stm32f103xx, device: stm32f103xx,
resources: {
static GPIOA: GPIOA;
static SPI1: SPI1;
},
tasks: { tasks: {
EXTI0: { EXTI0: {
path: exti0, path: exti0,
...@@ -27,7 +32,12 @@ app! { ...@@ -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() -> ! { fn idle() -> ! {
loop { loop {
......
...@@ -7,8 +7,9 @@ extern crate cortex_m; ...@@ -7,8 +7,9 @@ extern crate cortex_m;
extern crate cortex_m_rtfm as rtfm; extern crate cortex_m_rtfm as rtfm;
extern crate stm32f103xx; extern crate stm32f103xx;
use cortex_m::peripheral::SystClkSource; use cortex_m::peripheral::syst::SystClkSource;
use rtfm::{app, Threshold}; use rtfm::{app, Threshold};
use stm32f103xx::GPIOC;
app! { app! {
device: stm32f103xx, device: stm32f103xx,
...@@ -35,9 +36,8 @@ app! { ...@@ -35,9 +36,8 @@ app! {
// These are the resources this task has access to. // These are the resources this task has access to.
// //
// A resource can be a peripheral like `GPIOC` or a static variable // The resources listed here must also appear in `app.resources`
// like `ON` resources: [ON],
resources: [GPIOC, ON],
}, },
} }
} }
...@@ -47,19 +47,20 @@ fn init(p: init::Peripherals, r: init::Resources) { ...@@ -47,19 +47,20 @@ fn init(p: init::Peripherals, r: init::Resources) {
r.ON; r.ON;
// power on GPIOC // power on GPIOC
p.RCC.apb2enr.modify(|_, w| w.iopcen().enabled()); p.device.RCC.apb2enr.modify(|_, w| w.iopcen().enabled());
// configure PC13 as output // configure PC13 as output
p.GPIOC.bsrr.write(|w| w.bs13().set()); p.device.GPIOC.bsrr.write(|w| w.bs13().set());
p.GPIOC p.device
.GPIOC
.crh .crh
.modify(|_, w| w.mode13().output().cnf13().push()); .modify(|_, w| w.mode13().output().cnf13().push());
// configure the system timer to generate one interrupt every second // configure the system timer to generate one interrupt every second
p.SYST.set_clock_source(SystClkSource::Core); p.core.SYST.set_clock_source(SystClkSource::Core);
p.SYST.set_reload(8_000_000); // 1s p.core.SYST.set_reload(8_000_000); // 1s
p.SYST.enable_interrupt(); p.core.SYST.enable_interrupt();
p.SYST.enable_counter(); p.core.SYST.enable_counter();
} }
fn idle() -> ! { fn idle() -> ! {
...@@ -74,15 +75,22 @@ fn idle() -> ! { ...@@ -74,15 +75,22 @@ fn idle() -> ! {
// //
// `r` is the set of resources this task has access to. `SYS_TICK::Resources` // `r` is the set of resources this task has access to. `SYS_TICK::Resources`
// has one field per resource declared in `app!`. // has one field per resource declared in `app!`.
#[allow(unsafe_code)]
fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) { fn sys_tick(_t: &mut Threshold, r: SYS_TICK::Resources) {
// toggle state // toggle state
**r.ON = !**r.ON; **r.ON = !**r.ON;
if **r.ON { if **r.ON {
// set the pin PC13 high // 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 { } else {
// set the pin PC13 low // 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());
}
} }
} }
...@@ -25,8 +25,9 @@ app! { ...@@ -25,8 +25,9 @@ app! {
// this function. // this function.
fn init(p: init::Peripherals) { fn init(p: init::Peripherals) {
// This function has access to all the peripherals of the device // This function has access to all the peripherals of the device
p.GPIOA; p.core.SYST;
p.RCC; p.device.GPIOA;
p.device.RCC;
// .. // ..
} }
......
...@@ -63,16 +63,15 @@ pub fn app(app: check::App) -> Result<App> { ...@@ -63,16 +63,15 @@ pub fn app(app: check::App) -> Result<App> {
tasks: app.tasks tasks: app.tasks
.into_iter() .into_iter()
.map(|(k, v)| { .map(|(k, v)| {
let v = ::check::task(k.as_ref(), v) let v =
.chain_err(|| format!("checking task `{}`", k))?; ::check::task(k.as_ref(), v).chain_err(|| format!("checking task `{}`", k))?;
Ok((k, v)) Ok((k, v))
}) })
.collect::<Result<_>>()?, .collect::<Result<_>>()?,
}; };
::check::resources(&app) ::check::resources(&app).chain_err(|| "checking `resources`")?;
.chain_err(|| "checking `resources`")?;
Ok(app) Ok(app)
} }
...@@ -93,6 +92,17 @@ fn resources(app: &App) -> Result<()> { ...@@ -93,6 +92,17 @@ fn resources(app: &App) -> Result<()> {
bail!("resource `{}` is unused", resource); 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(()) Ok(())
} }
......
...@@ -161,8 +161,13 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) { ...@@ -161,8 +161,13 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
let device = &app.device; let device = &app.device;
let krate = krate(); let krate = krate();
let mut tys = vec![quote!(#device::Peripherals)]; let mut tys = vec![quote!(init::Peripherals)];
let mut exprs = vec![quote!(#device::Peripherals::all())]; let mut exprs = vec![quote!{
init::Peripherals {
core: ::#device::CorePeripherals::steal(),
device: ::#device::Peripherals::steal(),
}
}];
let mut ret = None; let mut ret = None;
let mut mod_items = vec![]; let mut mod_items = vec![];
...@@ -255,7 +260,10 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) { ...@@ -255,7 +260,10 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
root.push(quote! { root.push(quote! {
#[allow(unsafe_code)] #[allow(unsafe_code)]
mod init { mod init {
pub use ::#device::Peripherals; pub struct Peripherals {
pub core: ::#device::CorePeripherals,
pub device: ::#device::Peripherals,
}
#(#mod_items)* #(#mod_items)*
} }
...@@ -268,7 +276,7 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) { ...@@ -268,7 +276,7 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
Kind::Exception(ref e) => { Kind::Exception(ref e) => {
if exceptions.is_empty() { if exceptions.is_empty() {
exceptions.push(quote! { exceptions.push(quote! {
let scb = &*#device::SCB.get(); let scb = &*#device::SCB::ptr();
}); });
} }
...@@ -284,7 +292,7 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) { ...@@ -284,7 +292,7 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
// Interrupt. These can be enabled / disabled through the NVIC // Interrupt. These can be enabled / disabled through the NVIC
if interrupts.is_empty() { if interrupts.is_empty() {
interrupts.push(quote! { interrupts.push(quote! {
let nvic = &*#device::NVIC.get(); let nvic = &*#device::NVIC::ptr();
}); });
} }
......
...@@ -160,6 +160,6 @@ where ...@@ -160,6 +160,6 @@ where
I: Nr, I: Nr,
{ {
// NOTE(safe) atomic write // NOTE(safe) atomic write
let nvic = unsafe { &*cortex_m::peripheral::NVIC.get() }; let nvic = unsafe { &*cortex_m::peripheral::NVIC::ptr() };
nvic.set_pending(interrupt); nvic.set_pending(interrupt);
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment