mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2024-12-23 20:51:31 +11:00
Add an rp2040 specific #[entry] macro. (#300)
* Add an rp2040 specific #[entry] macro. This macro extends the one from cortex-m-rt by code to unlock all spinlocks on boot. * Idiomatic pointer arithmetic Apply suggestion by @9names, improving address calculations. (This doesn't change the generated code at opt levels 2 or "z".) Co-authored-by: 9names <60134748+9names@users.noreply.github.com>
This commit is contained in:
parent
7aefb8680d
commit
f8de8755cc
|
@ -2,6 +2,7 @@
|
|||
resolver = "2"
|
||||
members = [
|
||||
"rp2040-hal",
|
||||
"rp2040-hal-macros",
|
||||
"boards/adafruit-feather-rp2040",
|
||||
"boards/adafruit-itsy-bitsy-rp2040",
|
||||
"boards/adafruit-kb2040",
|
||||
|
|
20
rp2040-hal-macros/Cargo.toml
Normal file
20
rp2040-hal-macros/Cargo.toml
Normal file
|
@ -0,0 +1,20 @@
|
|||
[package]
|
||||
description = "Macros used by rp2040-hal"
|
||||
license = "MIT OR Apache-2.0"
|
||||
name = "rp2040-hal-macros"
|
||||
readme = "README.md"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
cortex-m-rt = "0.7.0"
|
||||
|
||||
[dependencies.syn]
|
||||
features = ["extra-traits", "full"]
|
||||
version = "1.0"
|
||||
|
27
rp2040-hal-macros/README.md
Normal file
27
rp2040-hal-macros/README.md
Normal file
|
@ -0,0 +1,27 @@
|
|||
# `rp2040-hal-macros`
|
||||
|
||||
Macros used by rp2040-hal.
|
||||
|
||||
## Entry macro
|
||||
|
||||
Extension of the `cortex-m-rt` `#[entry]` with rp2040 specific initialization code.
|
||||
|
||||
Currently, it just unlocks all spinlocks before calling the entry function.
|
||||
|
||||
# License
|
||||
|
||||
Licensed under either of
|
||||
|
||||
- Apache License, Version 2.0 (`APACHE2.0` or
|
||||
http://www.apache.org/licenses/LICENSE-2.0)
|
||||
|
||||
- MIT license (`MIT` or http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
## Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
|
||||
dual licensed as above, without any additional terms or conditions.
|
||||
|
59
rp2040-hal-macros/src/lib.rs
Normal file
59
rp2040-hal-macros/src/lib.rs
Normal file
|
@ -0,0 +1,59 @@
|
|||
extern crate proc_macro;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use proc_macro2::Span;
|
||||
use quote::quote;
|
||||
use syn::{parse, parse_macro_input, Item, ItemFn, Stmt};
|
||||
|
||||
#[proc_macro_attribute]
|
||||
pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let mut f = parse_macro_input!(input as ItemFn);
|
||||
|
||||
if !args.is_empty() {
|
||||
return parse::Error::new(Span::call_site(), "This attribute accepts no arguments")
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
|
||||
let clear_locks: TokenStream = quote!(unsafe {
|
||||
const SIO_BASE: u32 = 0xd0000000;
|
||||
const SPINLOCK0_PTR: *mut u32 = (SIO_BASE + 0x100) as *mut u32;
|
||||
const SPINLOCK_COUNT: usize = 32;
|
||||
for i in 0..SPINLOCK_COUNT {
|
||||
SPINLOCK0_PTR.wrapping_add(i).write_volatile(1);
|
||||
}
|
||||
})
|
||||
.into();
|
||||
let clear_locks = parse_macro_input!(clear_locks as Stmt);
|
||||
|
||||
// statics must stay first so cortex_m_rt::entry still finds them
|
||||
let stmts = insert_after_static(f.block.stmts, clear_locks);
|
||||
f.block.stmts = stmts;
|
||||
|
||||
quote!(
|
||||
#[::cortex_m_rt::entry]
|
||||
#f
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Insert new statements after initial block of statics
|
||||
fn insert_after_static(stmts: impl IntoIterator<Item = Stmt>, insert: Stmt) -> Vec<Stmt> {
|
||||
let mut istmts = stmts.into_iter();
|
||||
let mut stmts = vec![];
|
||||
for stmt in istmts.by_ref() {
|
||||
match stmt {
|
||||
Stmt::Item(Item::Static(var)) => {
|
||||
stmts.push(Stmt::Item(Item::Static(var)));
|
||||
}
|
||||
_ => {
|
||||
stmts.push(insert);
|
||||
stmts.push(stmt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
stmts.extend(istmts);
|
||||
|
||||
stmts
|
||||
}
|
|
@ -11,6 +11,7 @@ license = "MIT OR Apache-2.0"
|
|||
|
||||
[dependencies]
|
||||
cortex-m = "0.7.2"
|
||||
cortex-m-rt = ">=0.6.15,<0.8"
|
||||
embedded-hal = { version = "0.2.5", features = ["unproven"] }
|
||||
eh1_0_alpha = { version = "=1.0.0-alpha.7", package="embedded-hal", optional=true }
|
||||
embedded-time = "0.12.0"
|
||||
|
@ -19,6 +20,7 @@ nb = "1.0"
|
|||
rp2040-pac = "0.3.0"
|
||||
paste = "1.0"
|
||||
pio = "0.2.0"
|
||||
rp2040-hal-macros = { version = "0.1.0", path = "../rp2040-hal-macros" }
|
||||
usb-device = "0.2.8"
|
||||
vcell = "0.1"
|
||||
void = { version = "1.0.2", default-features = false }
|
||||
|
|
|
@ -49,6 +49,15 @@ pub mod xosc;
|
|||
pub use adc::Adc;
|
||||
pub use clocks::Clock;
|
||||
pub use i2c::I2C;
|
||||
/// Attribute to declare the entry point of the program
|
||||
///
|
||||
/// This is based on and can be used like the [entry attribute from
|
||||
/// cortex-m-rt](https://docs.rs/cortex-m-rt/latest/cortex_m_rt/attr.entry.html).
|
||||
///
|
||||
/// It extends that macro with code to unlock all spinlocks at the beginning
|
||||
/// of `main`. As spinlocks are not automatically unlocked on software resets,
|
||||
/// this can prevent unexpected deadlocks when running from a debugger.
|
||||
pub use rp2040_hal_macros::entry;
|
||||
pub use sio::Sio;
|
||||
pub use spi::Spi;
|
||||
pub use timer::Timer;
|
||||
|
|
Loading…
Reference in a new issue