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"
|
resolver = "2"
|
||||||
members = [
|
members = [
|
||||||
"rp2040-hal",
|
"rp2040-hal",
|
||||||
|
"rp2040-hal-macros",
|
||||||
"boards/adafruit-feather-rp2040",
|
"boards/adafruit-feather-rp2040",
|
||||||
"boards/adafruit-itsy-bitsy-rp2040",
|
"boards/adafruit-itsy-bitsy-rp2040",
|
||||||
"boards/adafruit-kb2040",
|
"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]
|
[dependencies]
|
||||||
cortex-m = "0.7.2"
|
cortex-m = "0.7.2"
|
||||||
|
cortex-m-rt = ">=0.6.15,<0.8"
|
||||||
embedded-hal = { version = "0.2.5", features = ["unproven"] }
|
embedded-hal = { version = "0.2.5", features = ["unproven"] }
|
||||||
eh1_0_alpha = { version = "=1.0.0-alpha.7", package="embedded-hal", optional=true }
|
eh1_0_alpha = { version = "=1.0.0-alpha.7", package="embedded-hal", optional=true }
|
||||||
embedded-time = "0.12.0"
|
embedded-time = "0.12.0"
|
||||||
|
@ -19,6 +20,7 @@ nb = "1.0"
|
||||||
rp2040-pac = "0.3.0"
|
rp2040-pac = "0.3.0"
|
||||||
paste = "1.0"
|
paste = "1.0"
|
||||||
pio = "0.2.0"
|
pio = "0.2.0"
|
||||||
|
rp2040-hal-macros = { version = "0.1.0", path = "../rp2040-hal-macros" }
|
||||||
usb-device = "0.2.8"
|
usb-device = "0.2.8"
|
||||||
vcell = "0.1"
|
vcell = "0.1"
|
||||||
void = { version = "1.0.2", default-features = false }
|
void = { version = "1.0.2", default-features = false }
|
||||||
|
|
|
@ -49,6 +49,15 @@ pub mod xosc;
|
||||||
pub use adc::Adc;
|
pub use adc::Adc;
|
||||||
pub use clocks::Clock;
|
pub use clocks::Clock;
|
||||||
pub use i2c::I2C;
|
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 sio::Sio;
|
||||||
pub use spi::Spi;
|
pub use spi::Spi;
|
||||||
pub use timer::Timer;
|
pub use timer::Timer;
|
||||||
|
|
Loading…
Reference in a new issue