Pass config directly to chip specific configure function

This removes the need to duplicate the configuration for each individual
chip, but will instead pass on the configuration specified in the config
attribute.

Update nrf, stm32, rp macros with passing the config to a per-chip
configure function which assumes the appropriate configuration to be
passed to it.

To demonstrate this feature, the stm32l0xx clock setup and RTC is added which exposes
clock configuration different from stm32f4xx (and has a different set of timers and HAL APIs).
This commit is contained in:
Ulf Lilleengen
2021-04-20 16:33:47 +02:00
parent 0d02e64f62
commit 9586365b07
15 changed files with 546 additions and 142 deletions

View File

@ -1,60 +1,15 @@
use crate::path::ModulePrefix;
use darling::FromMeta;
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use syn::spanned::Spanned;
use quote::quote;
#[derive(Debug, FromMeta)]
pub enum HfclkSource {
Internal,
ExternalXtal,
}
impl Default for HfclkSource {
fn default() -> Self {
Self::Internal
}
}
#[derive(Debug, FromMeta)]
pub enum LfclkSource {
InternalRC,
Synthesized,
ExternalXtal,
ExternalLowSwing,
ExternalFullSwing,
}
impl Default for LfclkSource {
fn default() -> Self {
Self::InternalRC
}
}
#[derive(Debug, FromMeta, Default)]
pub struct Args {
#[darling(default)]
pub embassy_prefix: ModulePrefix,
#[darling(default)]
pub hfclk_source: HfclkSource,
#[darling(default)]
pub lfclk_source: LfclkSource,
}
pub fn generate(args: &Args) -> TokenStream {
let hfclk_source = format_ident!("{}", format!("{:?}", args.hfclk_source));
let lfclk_source = format_ident!("{}", format!("{:?}", args.lfclk_source));
let embassy_path = args.embassy_prefix.append("embassy").path();
let embassy_nrf_path = args.embassy_prefix.append("embassy_nrf").path();
pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream {
let embassy_path = embassy_prefix.append("embassy").path();
let embassy_nrf_path = embassy_prefix.append("embassy_nrf").path();
quote!(
use #embassy_nrf_path::{interrupt, peripherals, rtc};
let mut config = #embassy_nrf_path::system::Config::default();
config.hfclk_source = #embassy_nrf_path::system::HfclkSource::#hfclk_source;
config.lfclk_source = #embassy_nrf_path::system::LfclkSource::#lfclk_source;
unsafe { #embassy_nrf_path::system::configure(config) };
unsafe { #embassy_nrf_path::system::configure(#config) };
let mut rtc = rtc::RTC::new(unsafe { <peripherals::RTC1 as #embassy_path::util::Steal>::steal() }, interrupt::take!(RTC1));
let rtc = unsafe { make_static(&mut rtc) };

View File

@ -1,20 +1,12 @@
use crate::path::ModulePrefix;
use darling::FromMeta;
use proc_macro2::TokenStream;
use quote::quote;
#[derive(Debug, FromMeta, Default)]
pub struct Args {
#[darling(default)]
pub embassy_prefix: ModulePrefix,
}
pub fn generate(args: &Args) -> TokenStream {
let embassy_rp_path = args.embassy_prefix.append("embassy_rp").path();
pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream {
let embassy_rp_path = embassy_prefix.append("embassy_rp").path();
quote!(
use #embassy_rp_path::{interrupt, peripherals};
let mut config = #embassy_rp_path::system::Config::default();
unsafe { #embassy_rp_path::system::configure(config) };
unsafe { #embassy_rp_path::system::configure(#config) };
)
}

View File

@ -1,57 +1,19 @@
use crate::path::ModulePrefix;
use darling::FromMeta;
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use syn::spanned::Spanned;
use quote::quote;
#[derive(Debug, FromMeta, Default)]
pub struct Args {
#[darling(default)]
pub embassy_prefix: ModulePrefix,
#[darling(default)]
pub use_hse: Option<u32>,
#[darling(default)]
pub sysclk: Option<u32>,
#[darling(default)]
pub pclk1: Option<u32>,
#[darling(default)]
pub require_pll48clk: bool,
}
pub fn generate(args: &Args) -> TokenStream {
let embassy_path = args.embassy_prefix.append("embassy").path();
let embassy_stm32_path = args.embassy_prefix.append("embassy_stm32").path();
let mut clock_cfg_args = quote! {};
if args.use_hse.is_some() {
let mhz = args.use_hse.unwrap();
clock_cfg_args = quote! { #clock_cfg_args.use_hse(#mhz.mhz()) };
}
if args.sysclk.is_some() {
let mhz = args.sysclk.unwrap();
clock_cfg_args = quote! { #clock_cfg_args.sysclk(#mhz.mhz()) };
}
if args.pclk1.is_some() {
let mhz = args.pclk1.unwrap();
clock_cfg_args = quote! { #clock_cfg_args.pclk1(#mhz.mhz()) };
}
if args.require_pll48clk {
clock_cfg_args = quote! { #clock_cfg_args.require_pll48clk() };
}
pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream {
let embassy_path = embassy_prefix.append("embassy").path();
let embassy_stm32_path = embassy_prefix.append("embassy_stm32").path();
quote!(
use #embassy_stm32_path::{rtc, interrupt, Peripherals, pac, hal::rcc::RccExt, hal::time::U32Ext};
let dp = pac::Peripherals::take().unwrap();
let rcc = dp.RCC.constrain();
let clocks = rcc.cfgr#clock_cfg_args.freeze();
unsafe { #embassy_stm32_path::system::configure(#config) };
unsafe { Peripherals::set_peripherals(clocks) };
let (dp, clocks) = Peripherals::take().unwrap();
let mut rtc = rtc::RTC::new(dp.TIM3, interrupt::take!(TIM3), clocks);
let mut rtc = rtc::RTC::new(dp.TIM2, interrupt::take!(TIM2), clocks);
let rtc = unsafe { make_static(&mut rtc) };
rtc.start();
let mut alarm = rtc.alarm1();
@ -60,5 +22,7 @@ pub fn generate(args: &Args) -> TokenStream {
let alarm = unsafe { make_static(&mut alarm) };
executor.set_alarm(alarm);
unsafe { Peripherals::set_peripherals(clocks) };
)
}

View File

@ -212,13 +212,13 @@ mod chip;
#[path = "chip/rp.rs"]
mod chip;
#[cfg(feature = "std")]
mod chip {
#[derive(Debug, darling::FromMeta, Default)]
pub struct Args {
#[darling(default)]
pub embassy_prefix: crate::path::ModulePrefix,
}
#[derive(Debug, FromMeta)]
struct MainArgs {
#[darling(default)]
embassy_prefix: ModulePrefix,
#[darling(default)]
config: Option<syn::LitStr>,
}
#[cfg(any(feature = "nrf", feature = "stm32", feature = "rp"))]
@ -227,7 +227,7 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
let macro_args = syn::parse_macro_input!(args as syn::AttributeArgs);
let task_fn = syn::parse_macro_input!(item as syn::ItemFn);
let macro_args = match chip::Args::from_list(&macro_args) {
let macro_args = match MainArgs::from_list(&macro_args) {
Ok(v) => v,
Err(e) => {
return TokenStream::from(e.write_errors());
@ -270,10 +270,21 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
return TokenStream::new();
}
let embassy_prefix_lit = macro_args.embassy_prefix.literal();
let embassy_path = macro_args.embassy_prefix.append("embassy").path();
let task_fn_body = task_fn.block.clone();
let chip_setup = chip::generate(&macro_args);
let embassy_prefix = macro_args.embassy_prefix;
let embassy_prefix_lit = embassy_prefix.literal();
let embassy_path = embassy_prefix.append("embassy").path();
let task_fn_body = task_fn.block;
let config = macro_args
.config
.map(|s| s.parse::<syn::Expr>().unwrap())
.unwrap_or_else(|| {
syn::Expr::Verbatim(quote! {
Default::default()
})
});
let chip_setup = chip::generate(&embassy_prefix, config);
let result = quote! {
#[#embassy_path::task(embassy_prefix = #embassy_prefix_lit)]
@ -288,6 +299,7 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
}
let mut executor = #embassy_path::executor::Executor::new();
let executor = unsafe { make_static(&mut executor) };
#chip_setup
@ -307,7 +319,7 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
let macro_args = syn::parse_macro_input!(args as syn::AttributeArgs);
let task_fn = syn::parse_macro_input!(item as syn::ItemFn);
let macro_args = match chip::Args::from_list(&macro_args) {
let macro_args = match MainArgs::from_list(&macro_args) {
Ok(v) => v,
Err(e) => {
return TokenStream::from(e.write_errors());