1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
extern crate proc_macro; extern crate quote; extern crate syn; use proc_macro::TokenStream; use quote::{format_ident, quote}; use syn::parse_macro_input; #[proc_macro] pub fn fgpio(item: TokenStream) -> TokenStream { let name = parse_macro_input!(item as syn::Ident).to_string(); let name_uc = name.to_uppercase(); let fgpio = format_ident!("fgpio{}", name); let fgpio_uc = format_ident!("FGPIO{}", name_uc); let port = format_ident!("PORT{}", name_uc); let pin_fields = (0..32 as usize).map(|i| { let pxi = format_ident!("p{}{}", name, i); let pxi_uc = format_ident!("P{}{}", name_uc, i); quote! { pub #pxi: #pxi_uc<IN> } }); let pin_init = (0..32 as usize).map(|i| { let pxi = format_ident!("p{}{}", name, i); let pxi_uc = format_ident!("P{}{}", name_uc, i); quote! { #pxi: #pxi_uc::<IN>{_mode: PhantomData} } }); let pin = (0..32 as usize).map(|i| { let pxi_uc = format_ident!("P{}{}", name_uc, i); let pcr = format_ident!("pcr{}", i); quote! { pub struct #pxi_uc<MODE> { _mode: PhantomData<MODE> } impl<MODE> #pxi_uc<MODE> { pub fn enable(&self) { unsafe { &(*#port::ptr()) }.#pcr.write(|w| w.mux()._001()); } pub fn into_input(self) -> #pxi_uc<IN> { self.regblock().pddr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << #i)) }); #pxi_uc{_mode: PhantomData} } pub fn into_output(self) -> #pxi_uc<OUT> { self.regblock().pddr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << #i)) }); #pxi_uc{_mode: PhantomData} } fn regblock(&self) -> &#fgpio::RegisterBlock { unsafe { &(*#fgpio_uc::ptr()) } } fn value(&self) -> u32 { self.regblock().pdir.read().pdi().bits() & (1 << #i) } } impl InputPin for #pxi_uc<IN> { type Error = Void; fn is_high(&self) -> Result<bool, Self::Error> { Ok(self.value() != 0) } fn is_low(&self) -> Result<bool, Self::Error> { Ok(self.value() == 0) } } impl OutputPin for #pxi_uc<OUT> { type Error = Void; fn set_low(&mut self) -> Result<(), Self::Error> { self.regblock().pcor.write(|w| unsafe { w.bits(1<<#i) }); Ok(()) } fn set_high(&mut self) -> Result<(), Self::Error> { self.regblock().psor.write(|w| unsafe { w.bits(1<<#i) }); Ok(()) } } impl #pxi_uc<OUT> { pub fn toggle(&mut self) { self.regblock().ptor.write(|w| unsafe { w.bits(1<<#i) }); } } } }); let result = quote! { pub mod #fgpio { use core::marker::PhantomData; use embedded_hal::digital::v2::{InputPin, OutputPin}; use void::Void; use crate::dev::{#fgpio_uc, #port, #fgpio}; use super::{FgpioExt, IN, OUT}; pub struct Parts { pub #fgpio: #fgpio_uc, #(#pin_fields,)* } impl Parts { pub fn into_fgpio(self) -> #fgpio_uc { self.#fgpio } } impl FgpioExt for #fgpio_uc { type Parts = Parts; fn split(self) -> Parts { Parts { #fgpio: self, #(#pin_init,)* } } } #(#pin)* } }; TokenStream::from(result) }