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"]
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
......@@ -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 {
......
......@@ -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());
}
}
}
......@@ -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;
// ..
}
......
......@@ -63,16 +63,15 @@ pub fn app(app: check::App) -> Result<App> {
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::<Result<_>>()?,
};
::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(())
}
......
......@@ -161,8 +161,13 @@ fn init(app: &App, main: &mut Vec<Tokens>, root: &mut Vec<Tokens>) {
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<Tokens>, root: &mut Vec<Tokens>) {
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<Tokens>, root: &mut Vec<Tokens>) {
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<Tokens>, root: &mut Vec<Tokens>) {
// 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();
});
}
......
......@@ -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);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment