Merge pull request #109 from xoviat/proc-macro

add embassy::main
This commit is contained in:
xoviat 2021-03-28 17:56:44 -05:00 committed by GitHub
commit f4791b826a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 343 additions and 39 deletions

View file

@ -11,3 +11,7 @@ darling = "0.10.2"
[lib]
proc-macro = true
[features]
stm32 = []
nrf = []

View file

@ -178,3 +178,120 @@ pub fn interrupt_take(item: TokenStream) -> TokenStream {
};
result.into()
}
#[derive(Debug, FromMeta)]
struct MainMacroArgs {
#[darling(default)]
use_hse: Option<u32>,
#[darling(default)]
sysclk: Option<u32>,
#[darling(default)]
pclk1: Option<u32>,
}
#[proc_macro_attribute]
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
let macro_args = syn::parse_macro_input!(args as syn::AttributeArgs);
let mut task_fn = syn::parse_macro_input!(item as syn::ItemFn);
let macro_args = match MainMacroArgs::from_list(&macro_args) {
Ok(v) => v,
Err(e) => {
return TokenStream::from(e.write_errors());
}
};
let mut fail = false;
if task_fn.sig.asyncness.is_none() {
task_fn
.sig
.span()
.unwrap()
.error("task functions must be async")
.emit();
fail = true;
}
if !task_fn.sig.generics.params.is_empty() {
task_fn
.sig
.span()
.unwrap()
.error("main function must not be generic")
.emit();
fail = true;
}
let mut arg_names: syn::punctuated::Punctuated<syn::Ident, syn::Token![,]> =
syn::punctuated::Punctuated::new();
let mut args = task_fn.sig.inputs.clone();
if args.len() != 1 {
task_fn
.sig
.span()
.unwrap()
.error("main function must have one argument")
.emit();
fail = true;
}
if fail {
return TokenStream::new();
}
let name = task_fn.sig.ident.clone();
let task_fn_body = task_fn.block.clone();
let mut clock_cfg_args = quote! {};
if macro_args.use_hse.is_some() {
let mhz = macro_args.use_hse.unwrap();
clock_cfg_args = quote! { #clock_cfg_args.use_hse(#mhz.mhz()) };
}
if macro_args.sysclk.is_some() {
let mhz = macro_args.sysclk.unwrap();
clock_cfg_args = quote! { #clock_cfg_args.sysclk(#mhz.mhz()) };
}
if macro_args.pclk1.is_some() {
let mhz = macro_args.pclk1.unwrap();
clock_cfg_args = quote! { #clock_cfg_args.pclk1(#mhz.mhz()) };
}
let result = quote! {
static __embassy_rtc: embassy::util::Forever<embassy_stm32::rtc::RTC<embassy_stm32::pac::TIM3>> = embassy::util::Forever::new();
static __embassy_alarm: embassy::util::Forever<embassy_stm32::rtc::Alarm<embassy_stm32::pac::TIM3>> = embassy::util::Forever::new();
static __embassy_executor: embassy::util::Forever<embassy::executor::Executor> = embassy::util::Forever::new();
#[embassy::executor::task]
async fn __embassy_main(#args) {
#task_fn_body
}
#[cortex_m_rt::entry]
fn main() -> ! {
use embassy::executor::Executor;
use embassy_stm32::{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 { Peripherals::set_peripherals(clocks) };
let rtc = __embassy_rtc.put(rtc::RTC::new(dp.TIM3, interrupt::take!(TIM3), clocks));
rtc.start();
unsafe { embassy::time::set_clock(rtc) };
let alarm = __embassy_alarm.put(rtc.alarm1());
let executor = __embassy_executor.put(Executor::new());
executor.set_alarm(alarm);
executor.run(|spawner| {
spawner.spawn(__embassy_main(spawner)).unwrap();
})
}
};
result.into()
}

View file

@ -20,6 +20,7 @@ defmt-error = [ ]
[dependencies]
embassy = { version = "0.1.0", path = "../embassy" }
embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["nrf"]}
embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
defmt = { version = "0.2.0", optional = true }

View file

@ -35,6 +35,7 @@ stm32l0x3 = ["stm32l0xx-hal/stm32l0x3"]
[dependencies]
embassy = { version = "0.1.0", path = "../embassy" }
embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["stm32"]}
embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
defmt = { version = "0.2.0", optional = true }

View file

@ -95,3 +95,209 @@ pub mod rtc;
feature = "stm32f479",
))]
unsafe impl embassy_extras::usb::USBInterrupt for interrupt::OTG_FS {}
use core::option::Option;
use hal::prelude::*;
use hal::rcc::Clocks;
macro_rules! peripherals {
($($PER:ident,)+) => {
#[doc = r"All the peripherals"]
#[allow(non_snake_case)]
pub struct Peripherals {
$(
pub $PER: pac::$PER,
)+
}
static mut GLOBAL_PERIPHERALS: Option<(Peripherals, Clocks)> = None;
impl Peripherals {
pub fn take() -> Option<(Peripherals, Clocks)> {
unsafe { GLOBAL_PERIPHERALS.take() }
}
pub unsafe fn set_peripherals(clocks: Clocks) {
let dp = pac::Peripherals::steal();
let peripherals = Peripherals {
$(
$PER: dp.$PER,
)+
};
GLOBAL_PERIPHERALS.replace((peripherals, clocks));
}
}
};
}
#[cfg(feature = "stm32f446")]
peripherals! {
DCMI,
FMC,
DBGMCU,
DMA2,
DMA1,
// RCC,
GPIOH,
GPIOG,
GPIOF,
GPIOE,
GPIOD,
GPIOC,
GPIOB,
GPIOA,
SYSCFG,
SPI1,
SPI2,
SPI3,
SPI4,
ADC1,
ADC2,
ADC3,
USART6,
USART1,
USART2,
USART3,
DAC,
I2C3,
I2C2,
I2C1,
IWDG,
WWDG,
RTC,
UART4,
UART5,
ADC_COMMON,
TIM1,
TIM2,
TIM8,
// TIM3,
TIM4,
TIM5,
TIM9,
TIM12,
TIM10,
TIM13,
TIM14,
TIM11,
TIM6,
TIM7,
CRC,
OTG_FS_GLOBAL,
OTG_FS_HOST,
OTG_FS_DEVICE,
OTG_FS_PWRCLK,
CAN1,
CAN2,
FLASH,
EXTI,
OTG_HS_GLOBAL,
OTG_HS_HOST,
OTG_HS_DEVICE,
OTG_HS_PWRCLK,
SAI1,
SAI2,
PWR,
QUADSPI,
SPDIFRX,
SDMMC,
HDMI_CEC,
FPU,
STK,
NVIC_STIR,
FPU_CPACR,
SCB_ACTRL,
}
#[cfg(feature = "stm32f405")]
peripherals! {
RNG,
DCMI,
FSMC,
DBGMCU,
DMA2,
DMA1,
// RCC,
GPIOI,
GPIOH,
GPIOG,
GPIOF,
GPIOE,
GPIOD,
GPIOC,
GPIOJ,
GPIOK,
GPIOB,
GPIOA,
SYSCFG,
SPI1,
SPI2,
SPI3,
I2S2EXT,
I2S3EXT,
SPI4,
SPI5,
SPI6,
SDIO,
ADC1,
ADC2,
ADC3,
USART6,
USART1,
USART2,
USART3,
DAC,
PWR,
I2C3,
I2C2,
I2C1,
IWDG,
WWDG,
RTC,
UART4,
UART5,
UART7,
UART8,
ADC_COMMON,
TIM1,
TIM8,
TIM2,
// TIM3,
TIM4,
TIM5,
TIM9,
TIM12,
TIM10,
TIM13,
TIM14,
TIM11,
TIM6,
TIM7,
ETHERNET_MAC,
ETHERNET_MMC,
ETHERNET_PTP,
ETHERNET_DMA,
CRC,
OTG_FS_GLOBAL,
OTG_FS_HOST,
OTG_FS_DEVICE,
OTG_FS_PWRCLK,
CAN1,
CAN2,
FLASH,
EXTI,
OTG_HS_GLOBAL,
OTG_HS_HOST,
OTG_HS_DEVICE,
OTG_HS_PWRCLK,
SAI1,
LTDC,
HASH,
CRYP,
FPU,
STK,
NVIC_STIR,
FPU_CPACR,
SCB_ACTRL,
}

View file

@ -38,6 +38,7 @@ stm32f479 = ["stm32f4xx-hal/stm32f469", "embassy-stm32f4/stm32f469"]
embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] }
embassy-traits = { version = "0.1.0", path = "../embassy-traits", features = ["defmt"] }
embassy-stm32f4 = { version = "*", path = "../embassy-stm32f4" }
embassy-stm32 = { version = "*", path = "../embassy-stm32" }
embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
defmt = "0.2.0"

View file

@ -8,19 +8,19 @@
mod example_common;
use example_common::*;
use cortex_m_rt::entry;
use defmt::panic;
use embassy::executor::{task, Executor};
use embassy;
use embassy::executor::Spawner;
use embassy::task;
use embassy::time::{Duration, Timer};
use embassy::util::Forever;
use embassy_stm32f4::{interrupt, pac, rtc};
use stm32f4xx_hal::prelude::*;
use embassy_stm32f4;
use embassy_stm32f4::hal;
#[task]
async fn run1() {
loop {
info!("BIG INFREQUENT TICK");
Timer::after(Duration::from_ticks(32768 * 2)).await;
Timer::after(Duration::from_ticks(32768 * 2 as u64)).await;
}
}
@ -28,40 +28,13 @@ async fn run1() {
async fn run2() {
loop {
info!("tick");
Timer::after(Duration::from_ticks(13000)).await;
Timer::after(Duration::from_ticks(13000 as u64)).await;
}
}
static RTC: Forever<rtc::RTC<pac::TIM2>> = Forever::new();
static ALARM: Forever<rtc::Alarm<pac::TIM2>> = Forever::new();
static EXECUTOR: Forever<Executor> = Forever::new();
#[embassy::main(use_hse = 16)]
async fn main(spawner: Spawner) {
let (dp, clocks) = embassy_stm32::Peripherals::take().unwrap();
#[entry]
fn main() -> ! {
info!("Hello World!");
let p = unwrap!(pac::Peripherals::take());
p.RCC.ahb1enr.modify(|_, w| w.dma1en().enabled());
let rcc = p.RCC.constrain();
let clocks = rcc.cfgr.freeze();
p.DBGMCU.cr.modify(|_, w| {
w.dbg_sleep().set_bit();
w.dbg_standby().set_bit();
w.dbg_stop().set_bit()
});
let rtc = RTC.put(rtc::RTC::new(p.TIM2, interrupt::take!(TIM2), clocks));
rtc.start();
unsafe { embassy::time::set_clock(rtc) };
let alarm = ALARM.put(rtc.alarm1());
let executor = EXECUTOR.put(Executor::new());
executor.set_alarm(alarm);
executor.run(|spawner| {
unwrap!(spawner.spawn(run1()));
unwrap!(spawner.spawn(run2()));
});
spawner.spawn(run1()).unwrap();
}

View file

@ -1,4 +1,4 @@
pub use embassy_macros::task;
pub use embassy_macros::{main, task};
use core::marker::PhantomData;
use core::ptr::NonNull;

View file

@ -18,6 +18,7 @@ pub mod time;
pub mod util;
pub use embassy_traits as traits;
pub use executor::{main, task};
#[doc(hidden)]
/// Implementation details for embassy macros. DO NOT USE.