add embassy::main and implement for stm32f4
This commit is contained in:
parent
19b959b0f8
commit
6ee9e012fc
@ -11,3 +11,7 @@ darling = "0.10.2"
|
|||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
|
[features]
|
||||||
|
stm32 = []
|
||||||
|
nrf = []
|
@ -178,3 +178,120 @@ pub fn interrupt_take(item: TokenStream) -> TokenStream {
|
|||||||
};
|
};
|
||||||
result.into()
|
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]
|
[dependencies]
|
||||||
embassy = { version = "0.1.0", path = "../embassy" }
|
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" }
|
embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
|
||||||
|
|
||||||
defmt = { version = "0.2.0", optional = true }
|
defmt = { version = "0.2.0", optional = true }
|
||||||
|
@ -35,6 +35,7 @@ stm32l0x3 = ["stm32l0xx-hal/stm32l0x3"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy = { version = "0.1.0", path = "../embassy" }
|
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 }
|
defmt = { version = "0.2.0", optional = true }
|
||||||
log = { version = "0.4.11", optional = true }
|
log = { version = "0.4.11", optional = true }
|
||||||
|
@ -73,3 +73,209 @@ pub mod can;
|
|||||||
feature = "stm32f479",
|
feature = "stm32f479",
|
||||||
))]
|
))]
|
||||||
pub mod rtc;
|
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 = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] }
|
||||||
embassy-traits = { version = "0.1.0", path = "../embassy-traits", features = ["defmt"] }
|
embassy-traits = { version = "0.1.0", path = "../embassy-traits", features = ["defmt"] }
|
||||||
embassy-stm32f4 = { version = "*", path = "../embassy-stm32f4" }
|
embassy-stm32f4 = { version = "*", path = "../embassy-stm32f4" }
|
||||||
|
embassy-stm32 = { version = "*", path = "../embassy-stm32" }
|
||||||
|
|
||||||
defmt = "0.2.0"
|
defmt = "0.2.0"
|
||||||
defmt-rtt = "0.2.0"
|
defmt-rtt = "0.2.0"
|
||||||
|
@ -8,19 +8,19 @@
|
|||||||
mod example_common;
|
mod example_common;
|
||||||
use example_common::*;
|
use example_common::*;
|
||||||
|
|
||||||
use cortex_m_rt::entry;
|
|
||||||
use defmt::panic;
|
use defmt::panic;
|
||||||
use embassy::executor::{task, Executor};
|
use embassy;
|
||||||
|
use embassy::executor::Spawner;
|
||||||
|
use embassy::task;
|
||||||
use embassy::time::{Duration, Timer};
|
use embassy::time::{Duration, Timer};
|
||||||
use embassy::util::Forever;
|
use embassy_stm32f4;
|
||||||
use embassy_stm32f4::{interrupt, pac, rtc};
|
use embassy_stm32f4::hal;
|
||||||
use stm32f4xx_hal::prelude::*;
|
|
||||||
|
|
||||||
#[task]
|
#[task]
|
||||||
async fn run1() {
|
async fn run1() {
|
||||||
loop {
|
loop {
|
||||||
info!("BIG INFREQUENT TICK");
|
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() {
|
async fn run2() {
|
||||||
loop {
|
loop {
|
||||||
info!("tick");
|
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();
|
#[embassy::main(use_hse = 16)]
|
||||||
static ALARM: Forever<rtc::Alarm<pac::TIM2>> = Forever::new();
|
async fn main(spawner: Spawner) {
|
||||||
static EXECUTOR: Forever<Executor> = Forever::new();
|
let (dp, clocks) = embassy_stm32::Peripherals::take().unwrap();
|
||||||
|
|
||||||
#[entry]
|
spawner.spawn(run1()).unwrap();
|
||||||
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()));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
pub use embassy_macros::task;
|
pub use embassy_macros::{main, task};
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::ptr::NonNull;
|
use core::ptr::NonNull;
|
||||||
|
@ -18,6 +18,7 @@ pub mod time;
|
|||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
pub use embassy_traits as traits;
|
pub use embassy_traits as traits;
|
||||||
|
pub use executor::{main, task};
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
/// Implementation details for embassy macros. DO NOT USE.
|
/// Implementation details for embassy macros. DO NOT USE.
|
||||||
|
Loading…
Reference in New Issue
Block a user