From 6ee9e012fcfc9a0a901f78885d19ae3c3d10570c Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 27 Mar 2021 17:27:39 -0500 Subject: [PATCH] add embassy::main and implement for stm32f4 --- embassy-macros/Cargo.toml | 4 + embassy-macros/src/lib.rs | 117 ++++++++++ embassy-nrf/Cargo.toml | 1 + embassy-stm32/Cargo.toml | 1 + embassy-stm32/src/lib.rs | 206 ++++++++++++++++++ embassy-stm32f4-examples/Cargo.toml | 1 + embassy-stm32f4-examples/src/bin/rtc_async.rs | 49 +---- embassy/src/executor/mod.rs | 2 +- embassy/src/lib.rs | 1 + 9 files changed, 343 insertions(+), 39 deletions(-) diff --git a/embassy-macros/Cargo.toml b/embassy-macros/Cargo.toml index 1f3e20aa..295a5703 100644 --- a/embassy-macros/Cargo.toml +++ b/embassy-macros/Cargo.toml @@ -11,3 +11,7 @@ darling = "0.10.2" [lib] proc-macro = true + +[features] +stm32 = [] +nrf = [] \ No newline at end of file diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs index 0bc5f003..450edbe4 100644 --- a/embassy-macros/src/lib.rs +++ b/embassy-macros/src/lib.rs @@ -178,3 +178,120 @@ pub fn interrupt_take(item: TokenStream) -> TokenStream { }; result.into() } + +#[derive(Debug, FromMeta)] +struct MainMacroArgs { + #[darling(default)] + use_hse: Option, + #[darling(default)] + sysclk: Option, + #[darling(default)] + pclk1: Option, +} + +#[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(¯o_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::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::util::Forever::new(); + static __embassy_alarm: embassy::util::Forever> = embassy::util::Forever::new(); + static __embassy_executor: embassy::util::Forever = 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() +} diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 026e815f..f26e892d 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -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 } diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 3fae66e9..437cacb2 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -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"]} defmt = { version = "0.2.0", optional = true } log = { version = "0.4.11", optional = true } diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 8a1fe5a3..122761c1 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -73,3 +73,209 @@ pub mod can; feature = "stm32f479", ))] pub mod rtc; + +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, +} diff --git a/embassy-stm32f4-examples/Cargo.toml b/embassy-stm32f4-examples/Cargo.toml index 5bbaecc5..fbdc6d79 100644 --- a/embassy-stm32f4-examples/Cargo.toml +++ b/embassy-stm32f4-examples/Cargo.toml @@ -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" } defmt = "0.2.0" defmt-rtt = "0.2.0" diff --git a/embassy-stm32f4-examples/src/bin/rtc_async.rs b/embassy-stm32f4-examples/src/bin/rtc_async.rs index 41ce2d4f..1927d01b 100644 --- a/embassy-stm32f4-examples/src/bin/rtc_async.rs +++ b/embassy-stm32f4-examples/src/bin/rtc_async.rs @@ -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> = Forever::new(); -static ALARM: Forever> = Forever::new(); -static EXECUTOR: Forever = 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(); } diff --git a/embassy/src/executor/mod.rs b/embassy/src/executor/mod.rs index fedff73e..b2c42190 100644 --- a/embassy/src/executor/mod.rs +++ b/embassy/src/executor/mod.rs @@ -1,4 +1,4 @@ -pub use embassy_macros::task; +pub use embassy_macros::{main, task}; use core::marker::PhantomData; use core::ptr::NonNull; diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs index b6fefc9f..482d5b36 100644 --- a/embassy/src/lib.rs +++ b/embassy/src/lib.rs @@ -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.