add embassy::main and implement for stm32f4
This commit is contained in:
parent
19b959b0f8
commit
6ee9e012fc
9 changed files with 343 additions and 39 deletions
|
@ -11,3 +11,7 @@ darling = "0.10.2"
|
|||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[features]
|
||||
stm32 = []
|
||||
nrf = []
|
|
@ -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(¯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::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()
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
pub use embassy_macros::task;
|
||||
pub use embassy_macros::{main, task};
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use core::ptr::NonNull;
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue