diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..51aa8ec --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +target = "thumbv7em-none-eabihf" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 73fab07..c84ca7a 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ target/ # MSVC Windows builds of rustc generate these, which store debugging information *.pdb + +.idea diff --git a/Cargo.lock b/Cargo.lock index 265e278..1396a5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,16 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" +[[package]] +name = "cipher" +version = "0.5.0-pre.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b1425e6ce000f05a73096556cabcfb6a10a3ffe3bb4d75416ca8f00819c0b6a" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "cortex-m" version = "0.7.7" @@ -55,6 +65,15 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" +[[package]] +name = "crypto-common" +version = "0.2.0-rc.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0b8ce8218c97789f16356e7896b3714f26c2ee1079b79c0b7ae7064bb9089fa" +dependencies = [ + "hybrid-array", +] + [[package]] name = "embedded-hal" version = "0.2.7" @@ -87,6 +106,24 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +[[package]] +name = "hybrid-array" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2d35805454dc9f8662a98d6d61886ffe26bd465f5960e0e55345c70d5c0d2a9" +dependencies = [ + "typenum", +] + +[[package]] +name = "inout" +version = "0.2.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de49db00f5add6dad75a57946b75de0f26287a6fc95f4f277d48419200422beb" +dependencies = [ + "hybrid-array", +] + [[package]] name = "max78000-pac" version = "0.3.0" @@ -103,6 +140,7 @@ dependencies = [ name = "max7800x-hal" version = "0.5.1" dependencies = [ + "cipher", "cortex-m", "cortex-m-rt", "embedded-hal 1.0.0", @@ -203,6 +241,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + [[package]] name = "unicode-ident" version = "1.0.14" diff --git a/Cargo.toml b/Cargo.toml index f298c34..19dfd5e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ max78000-pac = "0.3.0" paste = "1.0.15" rand = { version = "0.8.5", default-features = false, optional = true } rand_core = { version = "0.6.4", default-features = false, optional = true } +cipher = "0.5.0-pre.7" [features] default = ["rand", "rt"] diff --git a/src/aes.rs b/src/aes.rs new file mode 100644 index 0000000..c9dd907 --- /dev/null +++ b/src/aes.rs @@ -0,0 +1,272 @@ +use crate::aes::CipherType::{Decrypt, Encrypt}; +use crate::gcr::ResetForPeripheral; +use cipher::consts::{U16, U24, U32}; +use cipher::{ + Block, BlockCipherDecBackend, BlockCipherDecClosure, BlockCipherDecrypt, BlockCipherEncBackend, + BlockCipherEncClosure, BlockCipherEncrypt, BlockSizeUser, InOut, KeySizeUser, + ParBlocksSizeUser, +}; +use max78000_pac::aes::ctrl::KeySize; + +/// Address of the AES key registers in memory. +pub const AES_KEYS: usize = 0x4000_7800; + +/// Enum representing the type of cipher operation. +#[repr(u8)] +#[derive(Clone, Copy, Eq, PartialEq)] +pub enum CipherType { + Encrypt = 0b_00, // Encryption mode + Decrypt = 0b_10, // Decryption mode +} + +/// Enum for representing the AES key sizes. +pub enum Key<'a> { + Bits128(&'a [u8; 16]), // 128-bit key + Bits192(&'a [u8; 24]), // 192-bit key + Bits256(&'a [u8; 32]), // 256-bit key +} + +impl<'a> Key<'a> { + /// Returns the size of the key in bytes. + fn size(&self) -> usize { + match self { + Key::Bits128(_) => 16, + Key::Bits192(_) => 24, + Key::Bits256(_) => 32, + } + } + + /// Returns a pointer to the key data. + fn as_ptr(&self) -> *const u8 { + match self { + Key::Bits128(key) => key.as_ptr(), + Key::Bits192(key) => key.as_ptr(), + Key::Bits256(key) => key.as_ptr(), + } + } + + /// Creates a `Key` variant based on the input byte slice length. + pub fn from_bytes(key_bytes: &'a [u8]) -> Result { + match key_bytes.len() { + 16 => Ok(Key::Bits128(key_bytes.try_into().expect("Slice should be 16 bytes"))), + 24 => Ok(Key::Bits192(key_bytes.try_into().expect("Slice should be 24 bytes"))), + 32 => Ok(Key::Bits256(key_bytes.try_into().expect("Slice should be 32 bytes"))), + _ => Err("Invalid key length. Expected 16, 24, or 32 bytes."), + } + } +} + +impl Into for &Key<'_> { + /// Converts a `Key` into the corresponding `KeySize` enum variant. + fn into(self) -> KeySize { + match self { + Key::Bits128(_) => KeySize::Aes128, + Key::Bits192(_) => KeySize::Aes192, + Key::Bits256(_) => KeySize::Aes256, + } + } +} + +/// AES struct for handling encryption and decryption using the AES hardware module. +pub struct AesBackend { + aes: crate::pac::Aes, // Shared mutable access +} + +/// AES-128 Implementation +pub type Aes128Hardware = AesBackend<16>; +impl KeySizeUser for Aes128Hardware { + type KeySize = U16; +} + +/// AES-192 Implementation +pub type Aes192Hardware = AesBackend<24>; +impl KeySizeUser for Aes192Hardware { + type KeySize = U24; +} + +/// AES-256 Implementation +pub type Aes256Hardware = AesBackend<32>; +impl KeySizeUser for Aes256Hardware { + type KeySize = U32; +} + +impl AesBackend +where + Self: KeySizeUser, +{ + /// Creates a new instance with a key. + pub fn new_with_key( + aes: crate::pac::Aes, + reg: &mut crate::gcr::GcrRegisters, + key: cipher::Key, // GenericArray + ) -> Self { + let instance = Self::new_backend(aes, reg); + + instance.set_key( + &Key::from_bytes( + &key.as_slice() + ).expect("Invalid key")); + + instance + } +} + +impl AesBackend { + /// Creates a new AES instance and initializes the hardware module. + fn new_backend(aes: crate::pac::Aes, reg: &mut crate::gcr::GcrRegisters) -> Self { + use crate::gcr::ClockForPeripheral; + + // Reset and enable the AES hardware module. + unsafe { + aes.reset(&mut reg.gcr); + aes.enable_clock(&mut reg.gcr); + } + + // Disable AES interrupt notifications. + aes.inten().write(|reg| reg.done().clear_bit()); + + Self { aes } + } + + /// Checks if the AES hardware module is currently busy. + fn _is_busy(&self) -> bool { + self.aes.status().read().busy().bit_is_set() + } + + /// Configures the AES hardware with the provided key. + pub fn set_key(&self, key: &Key) { + // Wait until the AES module is not busy. + while self._is_busy() {} + + // Disable the AES module to configure the key. + self.aes.ctrl().write(|reg| reg.en().clear_bit()); + + // Flush input and output FIFOs if not empty. + if self.aes.status().read().input_em().bit_is_clear() { + self.aes.ctrl().write(|reg| reg.input_flush().set_bit()); + } + if self.aes.status().read().output_em().bit_is_clear() { + self.aes.ctrl().write(|reg| reg.output_flush().set_bit()); + } + + // Configure the key size. + self.aes + .ctrl() + .write(|reg| reg.key_size().variant(key.into())); + + // Write the key into the AES key registers. + unsafe { + for i in 0..256 { + core::ptr::write_volatile((AES_KEYS + (i * 4)) as *mut u32, 0u32); + } + core::ptr::copy_nonoverlapping(key.as_ptr(), AES_KEYS as *mut u8, key.size()); + } + + // Enable the AES module. + self.aes.ctrl().write(|reg| reg.en().set_bit()); + } + + /// Configures the AES hardware for encryption or decryption. + fn set_cipher_type(&self, cipher_type: CipherType) { + if self.aes.ctrl().read().type_() == cipher_type as u8 { + return; + } + + // Wait until the AES module is not busy. + while self._is_busy() {} + + // Disable the AES module to change the mode. + self.aes.ctrl().write(|reg| reg.en().clear_bit()); + + // Configure the cipher type (encrypt or decrypt). + self.aes.ctrl().modify(|read, write| unsafe { + let mut data = read.bits(); + data |= (cipher_type as u32) << 8 | 1; + write.bits(data) + }); + } + + /// Helper function to write a single 16-byte block to the input FIFO. + /// + /// # Warning: + /// This function assumes the block size is exactly 16 bytes. + fn write_block_to_fifo(&self, block: &[u8; 16]) { + let words = [ + u32::from_be_bytes(block[12..16].try_into().unwrap()), + u32::from_be_bytes(block[8..12].try_into().unwrap()), + u32::from_be_bytes(block[4..8].try_into().unwrap()), + u32::from_be_bytes(block[0..4].try_into().unwrap()), + ]; + + for &word in &words { + self.aes.fifo().write(|reg| unsafe { reg.bits(word) }); + } + } + + /// Reads a single 16-byte block from the output FIFO. + fn read_block_from_fifo(&self) -> [u8; 16] { + while self._is_busy() {} + + let mut data = [0u8; 16]; + for chunk in data.chunks_exact_mut(4).rev() { + let word = self.aes.fifo().read().bits(); + let bytes = word.to_be_bytes(); // Convert the 32-bit word to 4 bytes + chunk.copy_from_slice(&bytes); + } + data + } +} + +impl ParBlocksSizeUser for AesBackend { + type ParBlocksSize = U16; +} + +impl BlockSizeUser for AesBackend { + type BlockSize = U16; // AES block size is 16 bytes (128 bits) +} + +impl BlockCipherEncBackend for AesBackend { + fn encrypt_block(&self, mut block: InOut<'_, '_, Block>) { + // If AES is an in-place transform, read from `get()` + let mut data = [0u8; 16]; + + self.set_cipher_type(Encrypt); + + let input_block = block.get_in(); + data.copy_from_slice(input_block); + self.write_block_to_fifo(&data); + + // Then modify the same buffer with `get_mut()` + let output_block = block.get_out(); + output_block.copy_from_slice(&self.read_block_from_fifo()); + } +} + +impl BlockCipherDecBackend for AesBackend { + fn decrypt_block(&self, mut block: InOut<'_, '_, Block>) { + // If AES is an in-place transform, read from `get()` + let mut data = [0u8; 16]; + + self.set_cipher_type(Decrypt); + + let input_block = block.get_in(); + data.copy_from_slice(input_block); + self.write_block_to_fifo(&data); + + // Then modify the same buffer with `get_mut()` + let output_block = block.get_out(); + output_block.copy_from_slice(&data); + } +} + +impl BlockCipherEncrypt for AesBackend { + fn encrypt_with_backend(&self, f: impl BlockCipherEncClosure) { + f.call(self); + } +} + +impl BlockCipherDecrypt for AesBackend { + fn decrypt_with_backend(&self, f: impl BlockCipherDecClosure) { + f.call(self) + } +} diff --git a/src/flc.rs b/src/flc.rs index bd19e68..a18fd16 100644 --- a/src/flc.rs +++ b/src/flc.rs @@ -2,15 +2,15 @@ use crate::gcr::clocks::{Clock, SystemClock}; /// Base address of the flash memory. -pub const FLASH_BASE: u32 = 0x1000_0000; +pub const FLASH_BASE: u32 = 0x1000_0000; /// Size of the flash memory. -pub const FLASH_SIZE: u32 = 0x0008_0000; +pub const FLASH_SIZE: u32 = 0x0008_0000; /// End address of the flash memory. -pub const FLASH_END: u32 = FLASH_BASE + FLASH_SIZE; +pub const FLASH_END: u32 = FLASH_BASE + FLASH_SIZE; /// Number of flash pages. pub const FLASH_PAGE_COUNT: u32 = 64; /// Size of a flash page. -pub const FLASH_PAGE_SIZE: u32 = 0x2000; +pub const FLASH_PAGE_SIZE: u32 = 0x2000; /// Flash controller errors. #[derive(Debug, PartialEq)] @@ -72,9 +72,9 @@ impl Flc { while self.is_busy() {} // Set FLC divisor let flc_div = self.sys_clk.frequency / 1_000_000; - self.flc.clkdiv().modify(|_, w| unsafe { - w.clkdiv().bits(flc_div as u8) - }); + self.flc + .clkdiv() + .modify(|_, w| unsafe { w.clkdiv().bits(flc_div as u8) }); // Clear stale interrupts if self.flc.intr().read().af().bit_is_set() { self.flc.intr().write(|w| w.af().clear_bit()); @@ -85,10 +85,10 @@ impl Flc { #[inline] pub fn is_busy(&self) -> bool { let ctrl = self.flc.ctrl().read(); - ctrl.pend().is_busy() || - ctrl.pge().bit_is_set() || - ctrl.me().bit_is_set() || - ctrl.wr().bit_is_set() + ctrl.pend().is_busy() + || ctrl.pge().bit_is_set() + || ctrl.me().bit_is_set() + || ctrl.wr().bit_is_set() } /// Check if an address is within the valid flash memory range. @@ -119,9 +119,9 @@ impl Flc { // Convert to physical address let phys_addr = address & (FLASH_SIZE - 1); // Safety: We have validated the address already - self.flc.addr().write(|w| unsafe { - w.addr().bits(phys_addr) - }); + self.flc + .addr() + .write(|w| unsafe { w.addr().bits(phys_addr) }); Ok(()) } @@ -306,9 +306,7 @@ impl Flc { self.check_address(address)?; let addr_32_ptr = address as *const u32; // Safety: We have checked the address already - unsafe { - Ok(core::ptr::read_volatile(addr_32_ptr)) - } + unsafe { Ok(core::ptr::read_volatile(addr_32_ptr)) } } /// Erases a page in flash memory. @@ -327,15 +325,15 @@ impl Flc { // Lock based on page number if page_num < 32 { let write_lock_bit = 1 << page_num; - self.flc.welr0().write(|w| unsafe { - w.bits(write_lock_bit) - }); + self.flc + .welr0() + .write(|w| unsafe { w.bits(write_lock_bit) }); while self.flc.welr0().read().bits() & write_lock_bit == write_lock_bit {} } else { let write_lock_bit = 1 << (page_num - 32); - self.flc.welr1().write(|w| unsafe { - w.bits(write_lock_bit) - }); + self.flc + .welr1() + .write(|w| unsafe { w.bits(write_lock_bit) }); while self.flc.welr1().read().bits() & write_lock_bit == write_lock_bit {} } Ok(()) @@ -349,17 +347,13 @@ impl Flc { // Lock based on page number if page_num < 32 { let read_lock_bit = 1 << page_num; - self.flc.rlr0().write(|w| unsafe { - w.bits(read_lock_bit) - }); + self.flc.rlr0().write(|w| unsafe { w.bits(read_lock_bit) }); while self.flc.rlr0().read().bits() & read_lock_bit == read_lock_bit {} } else { let read_lock_bit = 1 << (page_num - 32); - self.flc.rlr1().write(|w| unsafe { - w.bits(read_lock_bit) - }); + self.flc.rlr1().write(|w| unsafe { w.bits(read_lock_bit) }); while self.flc.rlr1().read().bits() & read_lock_bit == read_lock_bit {} } Ok(()) } -} \ No newline at end of file +} diff --git a/src/gcr/clocks.rs b/src/gcr/clocks.rs index c5d7bd9..899151c 100644 --- a/src/gcr/clocks.rs +++ b/src/gcr/clocks.rs @@ -2,7 +2,7 @@ //! //! This module provides a full [typestate](https://docs.rust-embedded.org/book/static-guarantees/typestate-programming.html) //! API for enabling oscillators, configuring the system clock, and calculating -//! clock frequencies. By using typestates, calculation of clock frequencies +//! clock frequencies. By using typestates, calculation of clock frequencies //! are done entirely at compile time, with no runtime or memory overhead. use core::marker::PhantomData; @@ -137,7 +137,6 @@ impl SystemClockDivider for Div128 { const DIVISOR: u32 = 128; } - /// Oscillators represent the state of a physical oscillator. To use an /// oscillator, it must be enabled. Then, it can be converted into a clock. pub struct Oscillator { @@ -151,7 +150,10 @@ pub struct Clock { _src: PhantomData, pub frequency: u32, } -impl Clone for Clock where SRC: ClockOption { +impl Clone for Clock +where + SRC: ClockOption, +{ fn clone(&self) -> Self { *self } @@ -164,7 +166,10 @@ pub struct OscillatorGuard { _source: PhantomData, } -impl OscillatorGuard where O: OscillatorSource { +impl OscillatorGuard +where + O: OscillatorSource, +{ pub(super) fn new() -> Self { Self { _source: PhantomData, @@ -193,7 +198,10 @@ impl OscillatorGuards { /// Initialization of an [`Oscillator`] requires consumption of a /// corresponding typed OscillatorGuard. -impl Oscillator where O: OscillatorSource { +impl Oscillator +where + O: OscillatorSource, +{ pub fn new(_guard: OscillatorGuard) -> Self { Self { _source: PhantomData, @@ -204,9 +212,10 @@ impl Oscillator where O: OscillatorSource { pub type Ipo = Oscillator; impl Ipo { - pub fn enable(&self, reg: &mut super::GcrRegisters) -> - Oscillator - { + pub fn enable( + &self, + reg: &mut super::GcrRegisters, + ) -> Oscillator { reg.gcr.clkctrl().modify(|_, w| w.ipo_en().set_bit()); while reg.gcr.clkctrl().read().ipo_rdy().bit_is_clear() {} Oscillator { @@ -216,9 +225,7 @@ impl Ipo { } } impl Oscillator { - pub const fn into_clock(self) -> - Clock - { + pub const fn into_clock(self) -> Clock { Clock:: { _src: PhantomData, frequency: InternalPrimaryOscillator::BASE_FREQUENCY, @@ -228,9 +235,10 @@ impl Oscillator { pub type Iso = Oscillator; impl Iso { - pub fn enable(self, reg: &mut super::GcrRegisters) -> - Oscillator - { + pub fn enable( + self, + reg: &mut super::GcrRegisters, + ) -> Oscillator { reg.gcr.clkctrl().modify(|_, w| w.iso_en().set_bit()); while reg.gcr.clkctrl().read().iso_rdy().bit_is_clear() {} Oscillator { @@ -262,9 +270,10 @@ impl Oscillator { pub type Ibro = Oscillator; impl Ibro { - pub fn enable(self, reg: &mut super::GcrRegisters) -> - Oscillator - { + pub fn enable( + self, + reg: &mut super::GcrRegisters, + ) -> Oscillator { // IBRO is always enabled while reg.gcr.clkctrl().read().ibro_rdy().bit_is_clear() {} Oscillator { @@ -284,9 +293,10 @@ impl Oscillator { pub type Ertco = Oscillator; impl Oscillator { - pub fn enable(self, reg: &mut super::GcrRegisters) -> - Oscillator - { + pub fn enable( + self, + reg: &mut super::GcrRegisters, + ) -> Oscillator { reg.gcr.clkctrl().modify(|_, w| w.ertco_en().set_bit()); while reg.gcr.clkctrl().read().ertco_rdy().bit_is_clear() {} todo!("ERTCO requires initialization of the RTC peripheral"); @@ -298,10 +308,7 @@ impl Oscillator { } /// System clock setup configuration (source and divider). -pub struct SystemClockConfig< - S: OscillatorSource, - D: SystemClockDivider, -> { +pub struct SystemClockConfig { _source: PhantomData, _divider: PhantomData, } diff --git a/src/gcr/mod.rs b/src/gcr/mod.rs index fc621e4..2473e67 100644 --- a/src/gcr/mod.rs +++ b/src/gcr/mod.rs @@ -17,10 +17,7 @@ pub struct GcrRegisters { pub struct Gcr { pub reg: GcrRegisters, pub osc_guards: clocks::OscillatorGuards, - pub sys_clk: clocks::SystemClockConfig< - clocks::InternalSecondaryOscillator, - clocks::DivUnknown - >, + pub sys_clk: clocks::SystemClockConfig, } impl Gcr { @@ -101,7 +98,6 @@ macro_rules! generate_reset { }; } - generate_clock!(Adc, Gcr, pclkdis0, adc); generate_clock!(Aes, Gcr, pclkdis1, aes); // CNN? @@ -142,10 +138,10 @@ generate_reset!(Aes, Gcr, rst1, aes); // CPU1 (RISC-V core)? generate_reset!(Crc, Gcr, rst1, crc); generate_reset!(Dma, Gcr, rst0, dma); -generate_reset!(Dvs, Gcr, rst1, dvs); // Note: Dynamic Voltage Scaling Controller does not have its own peripheral clock -generate_reset!(Gpio0, Gcr, rst0, gpio0); // Note: Peripheral resets may not affect the GPIO peripherals -generate_reset!(Gpio1, Gcr, rst0, gpio1); // Note: Peripheral resets may not affect the GPIO peripherals -generate_reset!(Gpio2, Lpgcr, rst, gpio2); // Note: Peripheral resets may not affect the GPIO peripherals +generate_reset!(Dvs, Gcr, rst1, dvs); // Note: Dynamic Voltage Scaling Controller does not have its own peripheral clock +generate_reset!(Gpio0, Gcr, rst0, gpio0); // Note: Peripheral resets may not affect the GPIO peripherals +generate_reset!(Gpio1, Gcr, rst0, gpio1); // Note: Peripheral resets may not affect the GPIO peripherals +generate_reset!(Gpio2, Lpgcr, rst, gpio2); // Note: Peripheral resets may not affect the GPIO peripherals generate_reset!(I2c0, Gcr, rst0, i2c0); generate_reset!(I2c1, Gcr, rst1, i2c1); generate_reset!(I2c2, Gcr, rst1, i2c2); @@ -170,4 +166,4 @@ generate_reset!(Uart1, Gcr, rst0, uart1); generate_reset!(Uart2, Gcr, rst0, uart2); generate_reset!(Uart3, Lpgcr, rst, uart3); generate_reset!(Wdt0, Gcr, rst0, wdt0); -generate_reset!(Wdt1, Lpgcr, rst, wdt1); \ No newline at end of file +generate_reset!(Wdt1, Lpgcr, rst, wdt1); diff --git a/src/gpio.rs b/src/gpio.rs index 239a89a..db139d9 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -272,14 +272,16 @@ impl Pin { #[inline(always)] pub fn set_power_vddio(&mut self) { let gpio = unsafe { &*gpiox_ptr::

() }; - gpio.vssel().modify(|r, w| unsafe { w.bits(r.bits() & !(1 << N)) }); + gpio.vssel() + .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << N)) }); } /// Sets the pin power supply to VDDIOH. #[inline(always)] pub fn set_power_vddioh(&mut self) { let gpio = unsafe { &*gpiox_ptr::

() }; - gpio.vssel().modify(|r, w| unsafe { w.bits(r.bits() | (1 << N)) }); + gpio.vssel() + .modify(|r, w| unsafe { w.bits(r.bits() | (1 << N)) }); } } @@ -419,11 +421,19 @@ macro_rules! gpio { }; } -gpio!(Gpio0, gpio0, gcr, 0, [0, 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]); +gpio!( + Gpio0, + gpio0, + gcr, + 0, + [ + 0, 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 + ] +); gpio!(Gpio1, gpio1, gcr, 1, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); gpio!(Gpio2, gpio2, lpgcr, 2, [0, 1, 2, 3, 4, 5, 6, 7]); - /// Zero runtime cost function to get the address of a GPIO peripheral. #[inline(always)] const fn gpiox_ptr() -> *const crate::pac::gpio0::RegisterBlock { diff --git a/src/lib.rs b/src/lib.rs index 5deb49b..15d47a3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,19 +1,20 @@ //! # Hardware Abstraction Layer for MAX7800x Microcontrollers #![no_std] +/// Entry point for the runtime application. +pub use cortex_m_rt::entry; /// Re-export of the Peripheral Access Crate (PAC) for the MAX78000. pub use max78000_pac as pac; pub use pac::Interrupt; -/// Entry point for the runtime application. -pub use cortex_m_rt::entry; mod private { pub trait Sealed {} } use private::Sealed; +pub mod aes; pub mod flc; pub mod gcr; pub mod gpio; pub mod trng; -pub mod uart; \ No newline at end of file +pub mod uart; diff --git a/src/trng.rs b/src/trng.rs index eff33b0..d8e9858 100644 --- a/src/trng.rs +++ b/src/trng.rs @@ -25,7 +25,9 @@ impl Trng { /// Create a new TRNG peripheral instance. pub fn new(trng: crate::pac::Trng, reg: &mut crate::gcr::GcrRegisters) -> Self { use crate::gcr::ClockForPeripheral; - unsafe { trng.enable_clock(&mut reg.gcr); } + unsafe { + trng.enable_clock(&mut reg.gcr); + } Self { trng } } @@ -82,4 +84,4 @@ impl RngCore for Trng { self.fill_bytes(dest); Ok(()) } -} \ No newline at end of file +} diff --git a/src/uart.rs b/src/uart.rs index 12d7178..112fa75 100644 --- a/src/uart.rs +++ b/src/uart.rs @@ -3,15 +3,11 @@ use core::marker::PhantomData; use core::ops::Deref; use crate::gcr::{ + clocks::{Clock, InternalBaudRateOscillator, PeripheralClock}, ClockForPeripheral, - clocks::{ - Clock, - InternalBaudRateOscillator, - PeripheralClock, - } }; -use crate::gpio::{Pin, Af1}; -use embedded_hal_nb::{serial, nb}; +use crate::gpio::{Af1, Pin}; +use embedded_hal_nb::{nb, serial}; use paste::paste; enum UartClockSource { @@ -143,7 +139,7 @@ pub struct BuiltUartPeripheral { _rx_pin: RX, _tx_pin: TX, _cts_pin: CTS, - _rts_pin: RTS + _rts_pin: RTS, } // TODO @@ -257,11 +253,14 @@ uart! {Uart2, /// # Clock Methods /// You must set the clock source for the UART peripheral after using a /// constructor and before building the peripheral. -impl UartPeripheral { +impl + UartPeripheral +{ /// Set the clock source for the UART peripheral to the PCLK. - pub fn clock_pclk(self, clock: &Clock) -> - UartPeripheral - { + pub fn clock_pclk( + self, + clock: &Clock, + ) -> UartPeripheral { UartPeripheral { _state: PhantomData, _clock: PhantomData, @@ -280,9 +279,10 @@ impl UartPeripheral) -> - UartPeripheral - { + pub fn clock_ibro( + self, + clock: &Clock, + ) -> UartPeripheral { UartPeripheral { _state: PhantomData, _clock: PhantomData, @@ -307,10 +307,10 @@ impl UartPeripheral UartPeripheral where - UART: Deref + UART: Deref, { /// Set the baud rate (bits per second) for the UART peripheral. - /// + /// /// Default: `115200` pub fn baud(mut self, baud: u32) -> Self { self.baud = baud; @@ -318,7 +318,7 @@ where } /// Set the number of data bits for the UART peripheral. - /// + /// /// Default: [`DataBits::Eight`] pub fn data_bits(mut self, data_bits: DataBits) -> Self { self.data_bits = data_bits; @@ -326,7 +326,7 @@ where } /// Set the number of stop bits for the UART peripheral. - /// + /// /// Default: [`StopBits::One`] pub fn stop_bits(mut self, stop_bits: StopBits) -> Self { self.stop_bits = stop_bits; @@ -334,7 +334,7 @@ where } /// Set the parity for the UART peripheral. - /// + /// /// Default: [`ParityBit::None`] pub fn parity(mut self, parity: ParityBit) -> Self { self.parity = parity; @@ -368,8 +368,10 @@ where // } } -impl UartPeripheral -where UART: Deref +impl + UartPeripheral +where + UART: Deref, { /// Apply all settings and configure the UART peripheral. /// This must be called before the UART peripheral can be used. @@ -405,7 +407,9 @@ where UART: Deref }); // Set the baud rate let clkdiv = clk_src_freq / self.baud; - self.uart.clkdiv().write(|w| unsafe { w.clkdiv().bits(clkdiv) }); + self.uart + .clkdiv() + .write(|w| unsafe { w.clkdiv().bits(clkdiv) }); // Wait until baud clock is ready while self.uart.ctrl().read().bclkrdy().bit_is_clear() {} BuiltUartPeripheral { @@ -413,7 +417,7 @@ where UART: Deref _rx_pin: self._rx_pin, _tx_pin: self._tx_pin, _cts_pin: self._cts_pin, - _rts_pin: self._rts_pin + _rts_pin: self._rts_pin, } } } @@ -423,7 +427,7 @@ where UART: Deref /// been built. impl BuiltUartPeripheral where - UART: Deref + UART: Deref, { #[doc(hidden)] #[inline(always)] @@ -500,14 +504,14 @@ where // Embedded HAL non-blocking serial traits impl serial::ErrorType for BuiltUartPeripheral where - UART: Deref + UART: Deref, { type Error = serial::ErrorKind; } impl serial::Read for BuiltUartPeripheral where - UART: Deref + UART: Deref, { fn read(&mut self) -> nb::Result { self._read_byte() @@ -516,7 +520,7 @@ where impl serial::Write for BuiltUartPeripheral where - UART: Deref + UART: Deref, { fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { self._write_byte(byte) @@ -531,14 +535,14 @@ where // Embedded IO traits impl embedded_io::ErrorType for BuiltUartPeripheral where - UART: Deref + UART: Deref, { type Error = core::convert::Infallible; } impl embedded_io::Read for BuiltUartPeripheral where - UART: Deref + UART: Deref, { fn read(&mut self, buf: &mut [u8]) -> Result { let mut count = 0; @@ -565,7 +569,7 @@ where impl embedded_io::ReadReady for BuiltUartPeripheral where - UART: Deref + UART: Deref, { fn read_ready(&mut self) -> Result { Ok(!self._is_rx_empty()) @@ -574,7 +578,7 @@ where impl embedded_io::Write for BuiltUartPeripheral where - UART: Deref + UART: Deref, { fn write(&mut self, buf: &[u8]) -> Result { for byte in buf { @@ -591,9 +595,9 @@ where impl embedded_io::WriteReady for BuiltUartPeripheral where - UART: Deref + UART: Deref, { fn write_ready(&mut self) -> Result { Ok(!self._is_tx_full()) } -} \ No newline at end of file +}