Auto generate SPI v2 clock enable
Adds RccPeripheral trait for peripherals implementing clock enable and reset for a given peripheral. Add macro table generting implementations of RccPeripheral for peripherals with clock set, currently restricted to SPI.
This commit is contained in:
		| @@ -51,3 +51,5 @@ crate::pac::peripheral_pins!( | |||||||
|         } |         } | ||||||
|     }; |     }; | ||||||
| ); | ); | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,3 +1,6 @@ | |||||||
|  | #![macro_use] | ||||||
|  |  | ||||||
|  | use crate::peripherals; | ||||||
| use crate::time::Hertz; | use crate::time::Hertz; | ||||||
| use core::mem::MaybeUninit; | use core::mem::MaybeUninit; | ||||||
|  |  | ||||||
| @@ -44,3 +47,38 @@ cfg_if::cfg_if! { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | pub(crate) mod sealed { | ||||||
|  |     pub trait RccPeripheral { | ||||||
|  |         fn reset(); | ||||||
|  |         fn enable(); | ||||||
|  |         fn disable(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub trait RccPeripheral: sealed::RccPeripheral + 'static {} | ||||||
|  |  | ||||||
|  | crate::pac::peripheral_rcc!( | ||||||
|  |     ($inst:ident, $enable:ident, $reset:ident, $perien:ident, $perirst:ident) => { | ||||||
|  |         impl sealed::RccPeripheral for peripherals::$inst { | ||||||
|  |             fn enable() { | ||||||
|  |                 unsafe { | ||||||
|  |                     crate::pac::RCC.$enable().modify(|w| w.$perien(true)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             fn disable() { | ||||||
|  |                 unsafe { | ||||||
|  |                     crate::pac::RCC.$enable().modify(|w| w.$perien(false)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             fn reset() { | ||||||
|  |                 unsafe { | ||||||
|  |                     crate::pac::RCC.$reset().modify(|w| w.$perirst(true)); | ||||||
|  |                     crate::pac::RCC.$reset().modify(|w| w.$perirst(false)); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         impl RccPeripheral for peripherals::$inst {} | ||||||
|  |     }; | ||||||
|  | ); | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ use crate::gpio::{AnyPin, Pin}; | |||||||
| use crate::pac::gpio::vals::{Afr, Moder}; | use crate::pac::gpio::vals::{Afr, Moder}; | ||||||
| use crate::pac::gpio::Gpio; | use crate::pac::gpio::Gpio; | ||||||
| use crate::pac::spi; | use crate::pac::spi; | ||||||
|  | use crate::rcc::RccPeripheral; | ||||||
| use crate::spi::{ByteOrder, Config, Error, Instance, MisoPin, MosiPin, SckPin, WordSize}; | use crate::spi::{ByteOrder, Config, Error, Instance, MisoPin, MosiPin, SckPin, WordSize}; | ||||||
| use crate::time::Hertz; | use crate::time::Hertz; | ||||||
| use core::marker::PhantomData; | use core::marker::PhantomData; | ||||||
| @@ -28,14 +29,14 @@ impl WordSize { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| pub struct Spi<'d, T: Instance> { | pub struct Spi<'d, T: Instance + RccPeripheral> { | ||||||
|     sck: AnyPin, |     sck: AnyPin, | ||||||
|     mosi: AnyPin, |     mosi: AnyPin, | ||||||
|     miso: AnyPin, |     miso: AnyPin, | ||||||
|     phantom: PhantomData<&'d mut T>, |     phantom: PhantomData<&'d mut T>, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<'d, T: Instance> Spi<'d, T> { | impl<'d, T: Instance + RccPeripheral> Spi<'d, T> { | ||||||
|     pub fn new<F>( |     pub fn new<F>( | ||||||
|         pclk: Hertz, |         pclk: Hertz, | ||||||
|         _peri: impl Unborrow<Target = T> + 'd, |         _peri: impl Unborrow<Target = T> + 'd, | ||||||
| @@ -63,6 +64,8 @@ impl<'d, T: Instance> Spi<'d, T> { | |||||||
|         let br = Self::compute_baud_rate(pclk, freq.into()); |         let br = Self::compute_baud_rate(pclk, freq.into()); | ||||||
|  |  | ||||||
|         unsafe { |         unsafe { | ||||||
|  |             T::enable(); | ||||||
|  |             T::reset(); | ||||||
|             T::regs().cr2().modify(|w| { |             T::regs().cr2().modify(|w| { | ||||||
|                 w.set_ssoe(false); |                 w.set_ssoe(false); | ||||||
|             }); |             }); | ||||||
| @@ -140,7 +143,7 @@ impl<'d, T: Instance> Spi<'d, T> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<'d, T: Instance> Drop for Spi<'d, T> { | impl<'d, T: Instance + RccPeripheral> Drop for Spi<'d, T> { | ||||||
|     fn drop(&mut self) { |     fn drop(&mut self) { | ||||||
|         unsafe { |         unsafe { | ||||||
|             Self::unconfigure_pin(self.sck.block(), self.sck.pin() as _); |             Self::unconfigure_pin(self.sck.block(), self.sck.pin() as _); | ||||||
| @@ -198,7 +201,7 @@ fn read_word<W: Word>(regs: &'static crate::pac::spi::Spi) -> Result<W, Error> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T> { | impl<'d, T: Instance + RccPeripheral> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T> { | ||||||
|     type Error = Error; |     type Error = Error; | ||||||
|  |  | ||||||
|     fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { |     fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { | ||||||
| @@ -214,7 +217,7 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u8> for Spi<'d, T> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T> { | impl<'d, T: Instance + RccPeripheral> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T> { | ||||||
|     type Error = Error; |     type Error = Error; | ||||||
|  |  | ||||||
|     fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { |     fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { | ||||||
| @@ -230,7 +233,7 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u8> for Spi<'d, T> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T> { | impl<'d, T: Instance + RccPeripheral> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T> { | ||||||
|     type Error = Error; |     type Error = Error; | ||||||
|  |  | ||||||
|     fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> { |     fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> { | ||||||
| @@ -246,7 +249,7 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Write<u16> for Spi<'d, T> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl<'d, T: Instance> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T> { | impl<'d, T: Instance + RccPeripheral> embedded_hal::blocking::spi::Transfer<u16> for Spi<'d, T> { | ||||||
|     type Error = Error; |     type Error = Error; | ||||||
|  |  | ||||||
|     fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> { |     fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> { | ||||||
|   | |||||||
| @@ -136,6 +136,7 @@ fn main() { | |||||||
|     let mut interrupt_table: Vec<Vec<String>> = Vec::new(); |     let mut interrupt_table: Vec<Vec<String>> = Vec::new(); | ||||||
|     let mut peripherals_table: Vec<Vec<String>> = Vec::new(); |     let mut peripherals_table: Vec<Vec<String>> = Vec::new(); | ||||||
|     let mut peripheral_pins_table: Vec<Vec<String>> = Vec::new(); |     let mut peripheral_pins_table: Vec<Vec<String>> = Vec::new(); | ||||||
|  |     let mut peripheral_rcc_table: Vec<Vec<String>> = Vec::new(); | ||||||
|  |  | ||||||
|     let dma_base = chip |     let dma_base = chip | ||||||
|         .peripherals |         .peripherals | ||||||
| @@ -216,6 +217,19 @@ fn main() { | |||||||
|                     }; |                     }; | ||||||
|                     assert_eq!(p.address, dma_base + dma_stride * dma_num); |                     assert_eq!(p.address, dma_base + dma_stride * dma_num); | ||||||
|                 } |                 } | ||||||
|  |                 "spi" => { | ||||||
|  |                     if let Some(clock) = &p.clock { | ||||||
|  |                         let reg = clock.to_ascii_lowercase(); | ||||||
|  |                         let field = name.to_ascii_lowercase(); | ||||||
|  |                         peripheral_rcc_table.push(vec![ | ||||||
|  |                             name.clone(), | ||||||
|  |                             format!("{}enr", reg), | ||||||
|  |                             format!("{}rstr", reg), | ||||||
|  |                             format!("set_{}en", field), | ||||||
|  |                             format!("set_{}rst", field), | ||||||
|  |                         ]); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|                 _ => {} |                 _ => {} | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -255,6 +269,7 @@ fn main() { | |||||||
|     make_table(&mut extra, "peripherals", &peripherals_table); |     make_table(&mut extra, "peripherals", &peripherals_table); | ||||||
|     make_table(&mut extra, "peripheral_versions", &peripheral_version_table); |     make_table(&mut extra, "peripheral_versions", &peripheral_version_table); | ||||||
|     make_table(&mut extra, "peripheral_pins", &peripheral_pins_table); |     make_table(&mut extra, "peripheral_pins", &peripheral_pins_table); | ||||||
|  |     make_table(&mut extra, "peripheral_rcc", &peripheral_rcc_table); | ||||||
|  |  | ||||||
|     for (module, version) in peripheral_versions { |     for (module, version) in peripheral_versions { | ||||||
|         println!("loading {} {}", module, version); |         println!("loading {} {}", module, version); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user