aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2021-03-28 17:56:44 -0500
committerGitHub <[email protected]>2021-03-28 17:56:44 -0500
commitf4791b826a1bb1e191af4bac959e88489af428ca (patch)
treec64ffaba100632a8b5777e8d6bb3e5a3cfff777b
parentf6bcd2690d33e95b43de466d5ed6a8f7a64776ee (diff)
parent9e687ade6483c0541aa082c7a1922ba9271d2f46 (diff)
Merge pull request #109 from xoviat/proc-macro
add embassy::main
-rw-r--r--embassy-macros/Cargo.toml4
-rw-r--r--embassy-macros/src/lib.rs117
-rw-r--r--embassy-nrf/Cargo.toml1
-rw-r--r--embassy-stm32/Cargo.toml1
-rw-r--r--embassy-stm32/src/lib.rs206
-rw-r--r--embassy-stm32f4-examples/Cargo.toml1
-rw-r--r--embassy-stm32f4-examples/src/bin/rtc_async.rs49
-rw-r--r--embassy/src/executor/mod.rs2
-rw-r--r--embassy/src/lib.rs1
9 files changed, 343 insertions, 39 deletions
diff --git a/embassy-macros/Cargo.toml b/embassy-macros/Cargo.toml
index 1f3e20aa8..295a57039 100644
--- a/embassy-macros/Cargo.toml
+++ b/embassy-macros/Cargo.toml
@@ -11,3 +11,7 @@ darling = "0.10.2"
11 11
12[lib] 12[lib]
13proc-macro = true 13proc-macro = true
14
15[features]
16stm32 = []
17nrf = [] \ No newline at end of file
diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs
index 0bc5f0035..450edbe43 100644
--- a/embassy-macros/src/lib.rs
+++ b/embassy-macros/src/lib.rs
@@ -178,3 +178,120 @@ pub fn interrupt_take(item: TokenStream) -> TokenStream {
178 }; 178 };
179 result.into() 179 result.into()
180} 180}
181
182#[derive(Debug, FromMeta)]
183struct MainMacroArgs {
184 #[darling(default)]
185 use_hse: Option<u32>,
186 #[darling(default)]
187 sysclk: Option<u32>,
188 #[darling(default)]
189 pclk1: Option<u32>,
190}
191
192#[proc_macro_attribute]
193pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
194 let macro_args = syn::parse_macro_input!(args as syn::AttributeArgs);
195 let mut task_fn = syn::parse_macro_input!(item as syn::ItemFn);
196
197 let macro_args = match MainMacroArgs::from_list(&macro_args) {
198 Ok(v) => v,
199 Err(e) => {
200 return TokenStream::from(e.write_errors());
201 }
202 };
203
204 let mut fail = false;
205 if task_fn.sig.asyncness.is_none() {
206 task_fn
207 .sig
208 .span()
209 .unwrap()
210 .error("task functions must be async")
211 .emit();
212 fail = true;
213 }
214 if !task_fn.sig.generics.params.is_empty() {
215 task_fn
216 .sig
217 .span()
218 .unwrap()
219 .error("main function must not be generic")
220 .emit();
221 fail = true;
222 }
223
224 let mut arg_names: syn::punctuated::Punctuated<syn::Ident, syn::Token![,]> =
225 syn::punctuated::Punctuated::new();
226 let mut args = task_fn.sig.inputs.clone();
227
228 if args.len() != 1 {
229 task_fn
230 .sig
231 .span()
232 .unwrap()
233 .error("main function must have one argument")
234 .emit();
235 fail = true;
236 }
237
238 if fail {
239 return TokenStream::new();
240 }
241
242 let name = task_fn.sig.ident.clone();
243 let task_fn_body = task_fn.block.clone();
244
245 let mut clock_cfg_args = quote! {};
246 if macro_args.use_hse.is_some() {
247 let mhz = macro_args.use_hse.unwrap();
248 clock_cfg_args = quote! { #clock_cfg_args.use_hse(#mhz.mhz()) };
249 }
250
251 if macro_args.sysclk.is_some() {
252 let mhz = macro_args.sysclk.unwrap();
253 clock_cfg_args = quote! { #clock_cfg_args.sysclk(#mhz.mhz()) };
254 }
255
256 if macro_args.pclk1.is_some() {
257 let mhz = macro_args.pclk1.unwrap();
258 clock_cfg_args = quote! { #clock_cfg_args.pclk1(#mhz.mhz()) };
259 }
260
261 let result = quote! {
262 static __embassy_rtc: embassy::util::Forever<embassy_stm32::rtc::RTC<embassy_stm32::pac::TIM3>> = embassy::util::Forever::new();
263 static __embassy_alarm: embassy::util::Forever<embassy_stm32::rtc::Alarm<embassy_stm32::pac::TIM3>> = embassy::util::Forever::new();
264 static __embassy_executor: embassy::util::Forever<embassy::executor::Executor> = embassy::util::Forever::new();
265
266 #[embassy::executor::task]
267 async fn __embassy_main(#args) {
268 #task_fn_body
269 }
270
271 #[cortex_m_rt::entry]
272 fn main() -> ! {
273 use embassy::executor::Executor;
274 use embassy_stm32::{rtc, interrupt, Peripherals, pac, hal::rcc::RccExt, hal::time::U32Ext};
275
276 let dp = pac::Peripherals::take().unwrap();
277 let rcc = dp.RCC.constrain();
278 let clocks = rcc.cfgr#clock_cfg_args.freeze();
279
280 unsafe { Peripherals::set_peripherals(clocks) };
281
282 let rtc = __embassy_rtc.put(rtc::RTC::new(dp.TIM3, interrupt::take!(TIM3), clocks));
283 rtc.start();
284
285 unsafe { embassy::time::set_clock(rtc) };
286
287 let alarm = __embassy_alarm.put(rtc.alarm1());
288 let executor = __embassy_executor.put(Executor::new());
289 executor.set_alarm(alarm);
290
291 executor.run(|spawner| {
292 spawner.spawn(__embassy_main(spawner)).unwrap();
293 })
294 }
295 };
296 result.into()
297}
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml
index 026e815f7..f26e892d3 100644
--- a/embassy-nrf/Cargo.toml
+++ b/embassy-nrf/Cargo.toml
@@ -20,6 +20,7 @@ defmt-error = [ ]
20 20
21[dependencies] 21[dependencies]
22embassy = { version = "0.1.0", path = "../embassy" } 22embassy = { version = "0.1.0", path = "../embassy" }
23embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["nrf"]}
23embassy-extras = {version = "0.1.0", path = "../embassy-extras" } 24embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
24 25
25defmt = { version = "0.2.0", optional = true } 26defmt = { version = "0.2.0", optional = true }
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 66221ed59..28d9e7fe3 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -35,6 +35,7 @@ stm32l0x3 = ["stm32l0xx-hal/stm32l0x3"]
35 35
36[dependencies] 36[dependencies]
37embassy = { version = "0.1.0", path = "../embassy" } 37embassy = { version = "0.1.0", path = "../embassy" }
38embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["stm32"]}
38embassy-extras = {version = "0.1.0", path = "../embassy-extras" } 39embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
39 40
40defmt = { version = "0.2.0", optional = true } 41defmt = { version = "0.2.0", optional = true }
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 5ca7c2d0c..40e6093d5 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -95,3 +95,209 @@ pub mod rtc;
95 feature = "stm32f479", 95 feature = "stm32f479",
96))] 96))]
97unsafe impl embassy_extras::usb::USBInterrupt for interrupt::OTG_FS {} 97unsafe impl embassy_extras::usb::USBInterrupt for interrupt::OTG_FS {}
98
99use core::option::Option;
100use hal::prelude::*;
101use hal::rcc::Clocks;
102
103macro_rules! peripherals {
104 ($($PER:ident,)+) => {
105 #[doc = r"All the peripherals"]
106 #[allow(non_snake_case)]
107 pub struct Peripherals {
108 $(
109 pub $PER: pac::$PER,
110 )+
111 }
112
113 static mut GLOBAL_PERIPHERALS: Option<(Peripherals, Clocks)> = None;
114
115 impl Peripherals {
116 pub fn take() -> Option<(Peripherals, Clocks)> {
117 unsafe { GLOBAL_PERIPHERALS.take() }
118 }
119
120 pub unsafe fn set_peripherals(clocks: Clocks) {
121 let dp = pac::Peripherals::steal();
122 let peripherals = Peripherals {
123 $(
124 $PER: dp.$PER,
125 )+
126 };
127
128 GLOBAL_PERIPHERALS.replace((peripherals, clocks));
129 }
130 }
131 };
132}
133
134#[cfg(feature = "stm32f446")]
135peripherals! {
136 DCMI,
137 FMC,
138 DBGMCU,
139 DMA2,
140 DMA1,
141// RCC,
142 GPIOH,
143 GPIOG,
144 GPIOF,
145 GPIOE,
146 GPIOD,
147 GPIOC,
148 GPIOB,
149 GPIOA,
150 SYSCFG,
151 SPI1,
152 SPI2,
153 SPI3,
154 SPI4,
155 ADC1,
156 ADC2,
157 ADC3,
158 USART6,
159 USART1,
160 USART2,
161 USART3,
162 DAC,
163 I2C3,
164 I2C2,
165 I2C1,
166 IWDG,
167 WWDG,
168 RTC,
169 UART4,
170 UART5,
171 ADC_COMMON,
172 TIM1,
173 TIM2,
174 TIM8,
175// TIM3,
176 TIM4,
177 TIM5,
178 TIM9,
179 TIM12,
180 TIM10,
181 TIM13,
182 TIM14,
183 TIM11,
184 TIM6,
185 TIM7,
186 CRC,
187 OTG_FS_GLOBAL,
188 OTG_FS_HOST,
189 OTG_FS_DEVICE,
190 OTG_FS_PWRCLK,
191 CAN1,
192 CAN2,
193 FLASH,
194 EXTI,
195 OTG_HS_GLOBAL,
196 OTG_HS_HOST,
197 OTG_HS_DEVICE,
198 OTG_HS_PWRCLK,
199 SAI1,
200 SAI2,
201 PWR,
202 QUADSPI,
203 SPDIFRX,
204 SDMMC,
205 HDMI_CEC,
206 FPU,
207 STK,
208 NVIC_STIR,
209 FPU_CPACR,
210 SCB_ACTRL,
211}
212
213#[cfg(feature = "stm32f405")]
214peripherals! {
215 RNG,
216 DCMI,
217 FSMC,
218 DBGMCU,
219 DMA2,
220 DMA1,
221// RCC,
222 GPIOI,
223 GPIOH,
224 GPIOG,
225 GPIOF,
226 GPIOE,
227 GPIOD,
228 GPIOC,
229 GPIOJ,
230 GPIOK,
231 GPIOB,
232 GPIOA,
233 SYSCFG,
234 SPI1,
235 SPI2,
236 SPI3,
237 I2S2EXT,
238 I2S3EXT,
239 SPI4,
240 SPI5,
241 SPI6,
242 SDIO,
243 ADC1,
244 ADC2,
245 ADC3,
246 USART6,
247 USART1,
248 USART2,
249 USART3,
250 DAC,
251 PWR,
252 I2C3,
253 I2C2,
254 I2C1,
255 IWDG,
256 WWDG,
257 RTC,
258 UART4,
259 UART5,
260 UART7,
261 UART8,
262 ADC_COMMON,
263 TIM1,
264 TIM8,
265 TIM2,
266// TIM3,
267 TIM4,
268 TIM5,
269 TIM9,
270 TIM12,
271 TIM10,
272 TIM13,
273 TIM14,
274 TIM11,
275 TIM6,
276 TIM7,
277 ETHERNET_MAC,
278 ETHERNET_MMC,
279 ETHERNET_PTP,
280 ETHERNET_DMA,
281 CRC,
282 OTG_FS_GLOBAL,
283 OTG_FS_HOST,
284 OTG_FS_DEVICE,
285 OTG_FS_PWRCLK,
286 CAN1,
287 CAN2,
288 FLASH,
289 EXTI,
290 OTG_HS_GLOBAL,
291 OTG_HS_HOST,
292 OTG_HS_DEVICE,
293 OTG_HS_PWRCLK,
294 SAI1,
295 LTDC,
296 HASH,
297 CRYP,
298 FPU,
299 STK,
300 NVIC_STIR,
301 FPU_CPACR,
302 SCB_ACTRL,
303}
diff --git a/embassy-stm32f4-examples/Cargo.toml b/embassy-stm32f4-examples/Cargo.toml
index e97bd9beb..c6ef98973 100644
--- a/embassy-stm32f4-examples/Cargo.toml
+++ b/embassy-stm32f4-examples/Cargo.toml
@@ -38,6 +38,7 @@ stm32f479 = ["stm32f4xx-hal/stm32f469", "embassy-stm32f4/stm32f469"]
38embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] } 38embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] }
39embassy-traits = { version = "0.1.0", path = "../embassy-traits", features = ["defmt"] } 39embassy-traits = { version = "0.1.0", path = "../embassy-traits", features = ["defmt"] }
40embassy-stm32f4 = { version = "*", path = "../embassy-stm32f4" } 40embassy-stm32f4 = { version = "*", path = "../embassy-stm32f4" }
41embassy-stm32 = { version = "*", path = "../embassy-stm32" }
41embassy-extras = {version = "0.1.0", path = "../embassy-extras" } 42embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
42 43
43defmt = "0.2.0" 44defmt = "0.2.0"
diff --git a/embassy-stm32f4-examples/src/bin/rtc_async.rs b/embassy-stm32f4-examples/src/bin/rtc_async.rs
index 41ce2d4f1..1927d01bf 100644
--- a/embassy-stm32f4-examples/src/bin/rtc_async.rs
+++ b/embassy-stm32f4-examples/src/bin/rtc_async.rs
@@ -8,19 +8,19 @@
8mod example_common; 8mod example_common;
9use example_common::*; 9use example_common::*;
10 10
11use cortex_m_rt::entry;
12use defmt::panic; 11use defmt::panic;
13use embassy::executor::{task, Executor}; 12use embassy;
13use embassy::executor::Spawner;
14use embassy::task;
14use embassy::time::{Duration, Timer}; 15use embassy::time::{Duration, Timer};
15use embassy::util::Forever; 16use embassy_stm32f4;
16use embassy_stm32f4::{interrupt, pac, rtc}; 17use embassy_stm32f4::hal;
17use stm32f4xx_hal::prelude::*;
18 18
19#[task] 19#[task]
20async fn run1() { 20async fn run1() {
21 loop { 21 loop {
22 info!("BIG INFREQUENT TICK"); 22 info!("BIG INFREQUENT TICK");
23 Timer::after(Duration::from_ticks(32768 * 2)).await; 23 Timer::after(Duration::from_ticks(32768 * 2 as u64)).await;
24 } 24 }
25} 25}
26 26
@@ -28,40 +28,13 @@ async fn run1() {
28async fn run2() { 28async fn run2() {
29 loop { 29 loop {
30 info!("tick"); 30 info!("tick");
31 Timer::after(Duration::from_ticks(13000)).await; 31 Timer::after(Duration::from_ticks(13000 as u64)).await;
32 } 32 }
33} 33}
34 34
35static RTC: Forever<rtc::RTC<pac::TIM2>> = Forever::new(); 35#[embassy::main(use_hse = 16)]
36static ALARM: Forever<rtc::Alarm<pac::TIM2>> = Forever::new(); 36async fn main(spawner: Spawner) {
37static EXECUTOR: Forever<Executor> = Forever::new(); 37 let (dp, clocks) = embassy_stm32::Peripherals::take().unwrap();
38 38
39#[entry] 39 spawner.spawn(run1()).unwrap();
40fn main() -> ! {
41 info!("Hello World!");
42
43 let p = unwrap!(pac::Peripherals::take());
44
45 p.RCC.ahb1enr.modify(|_, w| w.dma1en().enabled());
46 let rcc = p.RCC.constrain();
47 let clocks = rcc.cfgr.freeze();
48
49 p.DBGMCU.cr.modify(|_, w| {
50 w.dbg_sleep().set_bit();
51 w.dbg_standby().set_bit();
52 w.dbg_stop().set_bit()
53 });
54
55 let rtc = RTC.put(rtc::RTC::new(p.TIM2, interrupt::take!(TIM2), clocks));
56 rtc.start();
57
58 unsafe { embassy::time::set_clock(rtc) };
59
60 let alarm = ALARM.put(rtc.alarm1());
61 let executor = EXECUTOR.put(Executor::new());
62 executor.set_alarm(alarm);
63 executor.run(|spawner| {
64 unwrap!(spawner.spawn(run1()));
65 unwrap!(spawner.spawn(run2()));
66 });
67} 40}
diff --git a/embassy/src/executor/mod.rs b/embassy/src/executor/mod.rs
index fedff73e2..b2c42190f 100644
--- a/embassy/src/executor/mod.rs
+++ b/embassy/src/executor/mod.rs
@@ -1,4 +1,4 @@
1pub use embassy_macros::task; 1pub use embassy_macros::{main, task};
2 2
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4use core::ptr::NonNull; 4use core::ptr::NonNull;
diff --git a/embassy/src/lib.rs b/embassy/src/lib.rs
index b6fefc9f7..482d5b367 100644
--- a/embassy/src/lib.rs
+++ b/embassy/src/lib.rs
@@ -18,6 +18,7 @@ pub mod time;
18pub mod util; 18pub mod util;
19 19
20pub use embassy_traits as traits; 20pub use embassy_traits as traits;
21pub use executor::{main, task};
21 22
22#[doc(hidden)] 23#[doc(hidden)]
23/// Implementation details for embassy macros. DO NOT USE. 24/// Implementation details for embassy macros. DO NOT USE.