diff options
| author | Dario Nieuwenhuis <[email protected]> | 2025-03-25 21:31:14 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-03-25 21:31:14 +0000 |
| commit | 4f250f399513319220853bfa0e13b9a588de8000 (patch) | |
| tree | a24154b18817b34cbb80b3b253fe3b7a1bc7cb6f | |
| parent | 17cce79807ff978270b96ba081a4ee2ed5604dcd (diff) | |
| parent | a592acb8068011787453944963b384fd43a52e65 (diff) | |
Merge pull request #4005 from embassy-rs/no-nodma
stm32: remove DMA generic params, remove NoDma.
| -rw-r--r-- | embassy-stm32/build.rs | 17 | ||||
| -rw-r--r-- | embassy-stm32/src/cryp/mod.rs | 877 | ||||
| -rw-r--r-- | embassy-stm32/src/dac/mod.rs | 400 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/mod.rs | 11 | ||||
| -rw-r--r-- | embassy-stm32/src/dma/util.rs | 6 | ||||
| -rw-r--r-- | embassy-stm32/src/hash/mod.rs | 286 | ||||
| -rw-r--r-- | embassy-stm32/src/macros.rs | 12 | ||||
| -rw-r--r-- | embassy-stm32/src/sdmmc/mod.rs | 104 | ||||
| -rw-r--r-- | embassy-stm32/src/spi/mod.rs | 2 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/dac.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/dac.rs | 3 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/dac_dma.rs | 7 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/dac.rs | 3 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/dac_dma.rs | 7 | ||||
| -rw-r--r-- | examples/stm32u0/src/bin/dac.rs | 3 | ||||
| -rw-r--r-- | tests/stm32/src/bin/dac.rs | 3 | ||||
| -rw-r--r-- | tests/stm32/src/bin/dac_l1.rs | 3 | ||||
| -rw-r--r-- | tests/stm32/src/bin/hash.rs | 3 |
18 files changed, 908 insertions, 842 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index eb0437bc2..8ca79eadf 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -1151,6 +1151,8 @@ fn main() { | |||
| 1151 | (("tsc", "G8_IO2"), quote!(crate::tsc::G8IO2Pin)), | 1151 | (("tsc", "G8_IO2"), quote!(crate::tsc::G8IO2Pin)), |
| 1152 | (("tsc", "G8_IO3"), quote!(crate::tsc::G8IO3Pin)), | 1152 | (("tsc", "G8_IO3"), quote!(crate::tsc::G8IO3Pin)), |
| 1153 | (("tsc", "G8_IO4"), quote!(crate::tsc::G8IO4Pin)), | 1153 | (("tsc", "G8_IO4"), quote!(crate::tsc::G8IO4Pin)), |
| 1154 | (("dac", "OUT1"), quote!(crate::dac::DacPin<Ch1>)), | ||
| 1155 | (("dac", "OUT2"), quote!(crate::dac::DacPin<Ch2>)), | ||
| 1154 | ].into(); | 1156 | ].into(); |
| 1155 | 1157 | ||
| 1156 | for p in METADATA.peripherals { | 1158 | for p in METADATA.peripherals { |
| @@ -1250,17 +1252,6 @@ fn main() { | |||
| 1250 | } | 1252 | } |
| 1251 | } | 1253 | } |
| 1252 | 1254 | ||
| 1253 | // DAC is special | ||
| 1254 | if regs.kind == "dac" { | ||
| 1255 | let peri = format_ident!("{}", p.name); | ||
| 1256 | let pin_name = format_ident!("{}", pin.pin); | ||
| 1257 | let ch: u8 = pin.signal.strip_prefix("OUT").unwrap().parse().unwrap(); | ||
| 1258 | |||
| 1259 | g.extend(quote! { | ||
| 1260 | impl_dac_pin!( #peri, #pin_name, #ch); | ||
| 1261 | }) | ||
| 1262 | } | ||
| 1263 | |||
| 1264 | if regs.kind == "spdifrx" { | 1255 | if regs.kind == "spdifrx" { |
| 1265 | let peri = format_ident!("{}", p.name); | 1256 | let peri = format_ident!("{}", p.name); |
| 1266 | let pin_name = format_ident!("{}", pin.pin); | 1257 | let pin_name = format_ident!("{}", pin.pin); |
| @@ -1304,8 +1295,8 @@ fn main() { | |||
| 1304 | (("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)), | 1295 | (("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)), |
| 1305 | (("octospi", "OCTOSPI1"), quote!(crate::ospi::OctoDma)), | 1296 | (("octospi", "OCTOSPI1"), quote!(crate::ospi::OctoDma)), |
| 1306 | (("hspi", "HSPI1"), quote!(crate::hspi::HspiDma)), | 1297 | (("hspi", "HSPI1"), quote!(crate::hspi::HspiDma)), |
| 1307 | (("dac", "CH1"), quote!(crate::dac::DacDma1)), | 1298 | (("dac", "CH1"), quote!(crate::dac::Dma<Ch1>)), |
| 1308 | (("dac", "CH2"), quote!(crate::dac::DacDma2)), | 1299 | (("dac", "CH2"), quote!(crate::dac::Dma<Ch2>)), |
| 1309 | (("timer", "UP"), quote!(crate::timer::UpDma)), | 1300 | (("timer", "UP"), quote!(crate::timer::UpDma)), |
| 1310 | (("hash", "IN"), quote!(crate::hash::Dma)), | 1301 | (("hash", "IN"), quote!(crate::hash::Dma)), |
| 1311 | (("cryp", "IN"), quote!(crate::cryp::DmaIn)), | 1302 | (("cryp", "IN"), quote!(crate::cryp::DmaIn)), |
diff --git a/embassy-stm32/src/cryp/mod.rs b/embassy-stm32/src/cryp/mod.rs index 6afe68a39..54d2c30e5 100644 --- a/embassy-stm32/src/cryp/mod.rs +++ b/embassy-stm32/src/cryp/mod.rs | |||
| @@ -7,8 +7,9 @@ use core::ptr; | |||
| 7 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 7 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 8 | use embassy_sync::waitqueue::AtomicWaker; | 8 | use embassy_sync::waitqueue::AtomicWaker; |
| 9 | 9 | ||
| 10 | use crate::dma::{NoDma, Transfer, TransferOptions}; | 10 | use crate::dma::{ChannelAndRequest, TransferOptions}; |
| 11 | use crate::interrupt::typelevel::Interrupt; | 11 | use crate::interrupt::typelevel::Interrupt; |
| 12 | use crate::mode::{Async, Blocking, Mode}; | ||
| 12 | use crate::{interrupt, pac, peripherals, rcc, Peripheral}; | 13 | use crate::{interrupt, pac, peripherals, rcc, Peripheral}; |
| 13 | 14 | ||
| 14 | const DES_BLOCK_SIZE: usize = 8; // 64 bits | 15 | const DES_BLOCK_SIZE: usize = 8; // 64 bits |
| @@ -57,15 +58,10 @@ pub trait Cipher<'c> { | |||
| 57 | fn prepare_key(&self, _p: pac::cryp::Cryp) {} | 58 | fn prepare_key(&self, _p: pac::cryp::Cryp) {} |
| 58 | 59 | ||
| 59 | /// Performs any cipher-specific initialization. | 60 | /// Performs any cipher-specific initialization. |
| 60 | fn init_phase_blocking<T: Instance, DmaIn, DmaOut>(&self, _p: pac::cryp::Cryp, _cryp: &Cryp<T, DmaIn, DmaOut>) {} | 61 | fn init_phase_blocking<T: Instance, M: Mode>(&self, _p: pac::cryp::Cryp, _cryp: &Cryp<T, M>) {} |
| 61 | 62 | ||
| 62 | /// Performs any cipher-specific initialization. | 63 | /// Performs any cipher-specific initialization. |
| 63 | async fn init_phase<T: Instance, DmaIn, DmaOut>(&self, _p: pac::cryp::Cryp, _cryp: &mut Cryp<'_, T, DmaIn, DmaOut>) | 64 | async fn init_phase<T: Instance>(&self, _p: pac::cryp::Cryp, _cryp: &mut Cryp<'_, T, Async>) {} |
| 64 | where | ||
| 65 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 66 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 67 | { | ||
| 68 | } | ||
| 69 | 65 | ||
| 70 | /// Called prior to processing the last data block for cipher-specific operations. | 66 | /// Called prior to processing the last data block for cipher-specific operations. |
| 71 | fn pre_final(&self, _p: pac::cryp::Cryp, _dir: Direction, _padding_len: usize) -> [u32; 4] { | 67 | fn pre_final(&self, _p: pac::cryp::Cryp, _dir: Direction, _padding_len: usize) -> [u32; 4] { |
| @@ -73,10 +69,10 @@ pub trait Cipher<'c> { | |||
| 73 | } | 69 | } |
| 74 | 70 | ||
| 75 | /// Called after processing the last data block for cipher-specific operations. | 71 | /// Called after processing the last data block for cipher-specific operations. |
| 76 | fn post_final_blocking<T: Instance, DmaIn, DmaOut>( | 72 | fn post_final_blocking<T: Instance, M: Mode>( |
| 77 | &self, | 73 | &self, |
| 78 | _p: pac::cryp::Cryp, | 74 | _p: pac::cryp::Cryp, |
| 79 | _cryp: &Cryp<T, DmaIn, DmaOut>, | 75 | _cryp: &Cryp<T, M>, |
| 80 | _dir: Direction, | 76 | _dir: Direction, |
| 81 | _int_data: &mut [u8; AES_BLOCK_SIZE], | 77 | _int_data: &mut [u8; AES_BLOCK_SIZE], |
| 82 | _temp1: [u32; 4], | 78 | _temp1: [u32; 4], |
| @@ -85,18 +81,15 @@ pub trait Cipher<'c> { | |||
| 85 | } | 81 | } |
| 86 | 82 | ||
| 87 | /// Called after processing the last data block for cipher-specific operations. | 83 | /// Called after processing the last data block for cipher-specific operations. |
| 88 | async fn post_final<T: Instance, DmaIn, DmaOut>( | 84 | async fn post_final<T: Instance>( |
| 89 | &self, | 85 | &self, |
| 90 | _p: pac::cryp::Cryp, | 86 | _p: pac::cryp::Cryp, |
| 91 | _cryp: &mut Cryp<'_, T, DmaIn, DmaOut>, | 87 | _cryp: &mut Cryp<'_, T, Async>, |
| 92 | _dir: Direction, | 88 | _dir: Direction, |
| 93 | _int_data: &mut [u8; AES_BLOCK_SIZE], | 89 | _int_data: &mut [u8; AES_BLOCK_SIZE], |
| 94 | _temp1: [u32; 4], | 90 | _temp1: [u32; 4], |
| 95 | _padding_mask: [u8; 16], | 91 | _padding_mask: [u8; 16], |
| 96 | ) where | 92 | ) { |
| 97 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 98 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 99 | { | ||
| 100 | } | 93 | } |
| 101 | 94 | ||
| 102 | /// Returns the AAD header block as required by the cipher. | 95 | /// Returns the AAD header block as required by the cipher. |
| @@ -474,13 +467,13 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGcm<'c, KEY_SIZE> { | |||
| 474 | p.cr().modify(|w| w.set_algomode3(true)); | 467 | p.cr().modify(|w| w.set_algomode3(true)); |
| 475 | } | 468 | } |
| 476 | 469 | ||
| 477 | fn init_phase_blocking<T: Instance, DmaIn, DmaOut>(&self, p: pac::cryp::Cryp, _cryp: &Cryp<T, DmaIn, DmaOut>) { | 470 | fn init_phase_blocking<T: Instance, M: Mode>(&self, p: pac::cryp::Cryp, _cryp: &Cryp<T, M>) { |
| 478 | p.cr().modify(|w| w.set_gcm_ccmph(0)); | 471 | p.cr().modify(|w| w.set_gcm_ccmph(0)); |
| 479 | p.cr().modify(|w| w.set_crypen(true)); | 472 | p.cr().modify(|w| w.set_crypen(true)); |
| 480 | while p.cr().read().crypen() {} | 473 | while p.cr().read().crypen() {} |
| 481 | } | 474 | } |
| 482 | 475 | ||
| 483 | async fn init_phase<T: Instance, DmaIn, DmaOut>(&self, p: pac::cryp::Cryp, _cryp: &mut Cryp<'_, T, DmaIn, DmaOut>) { | 476 | async fn init_phase<T: Instance>(&self, p: pac::cryp::Cryp, _cryp: &mut Cryp<'_, T, Async>) { |
| 484 | p.cr().modify(|w| w.set_gcm_ccmph(0)); | 477 | p.cr().modify(|w| w.set_gcm_ccmph(0)); |
| 485 | p.cr().modify(|w| w.set_crypen(true)); | 478 | p.cr().modify(|w| w.set_crypen(true)); |
| 486 | while p.cr().read().crypen() {} | 479 | while p.cr().read().crypen() {} |
| @@ -508,10 +501,10 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGcm<'c, KEY_SIZE> { | |||
| 508 | } | 501 | } |
| 509 | 502 | ||
| 510 | #[cfg(cryp_v2)] | 503 | #[cfg(cryp_v2)] |
| 511 | fn post_final_blocking<T: Instance, DmaIn, DmaOut>( | 504 | fn post_final_blocking<T: Instance, M: Mode>( |
| 512 | &self, | 505 | &self, |
| 513 | p: pac::cryp::Cryp, | 506 | p: pac::cryp::Cryp, |
| 514 | cryp: &Cryp<T, DmaIn, DmaOut>, | 507 | cryp: &Cryp<T, M>, |
| 515 | dir: Direction, | 508 | dir: Direction, |
| 516 | int_data: &mut [u8; AES_BLOCK_SIZE], | 509 | int_data: &mut [u8; AES_BLOCK_SIZE], |
| 517 | _temp1: [u32; 4], | 510 | _temp1: [u32; 4], |
| @@ -534,18 +527,15 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGcm<'c, KEY_SIZE> { | |||
| 534 | } | 527 | } |
| 535 | 528 | ||
| 536 | #[cfg(cryp_v2)] | 529 | #[cfg(cryp_v2)] |
| 537 | async fn post_final<T: Instance, DmaIn, DmaOut>( | 530 | async fn post_final<T: Instance>( |
| 538 | &self, | 531 | &self, |
| 539 | p: pac::cryp::Cryp, | 532 | p: pac::cryp::Cryp, |
| 540 | cryp: &mut Cryp<'_, T, DmaIn, DmaOut>, | 533 | cryp: &mut Cryp<'_, T, Async>, |
| 541 | dir: Direction, | 534 | dir: Direction, |
| 542 | int_data: &mut [u8; AES_BLOCK_SIZE], | 535 | int_data: &mut [u8; AES_BLOCK_SIZE], |
| 543 | _temp1: [u32; 4], | 536 | _temp1: [u32; 4], |
| 544 | padding_mask: [u8; AES_BLOCK_SIZE], | 537 | padding_mask: [u8; AES_BLOCK_SIZE], |
| 545 | ) where | 538 | ) { |
| 546 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 547 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 548 | { | ||
| 549 | if dir == Direction::Encrypt { | 539 | if dir == Direction::Encrypt { |
| 550 | // Handle special GCM partial block process. | 540 | // Handle special GCM partial block process. |
| 551 | p.cr().modify(|w| w.set_crypen(false)); | 541 | p.cr().modify(|w| w.set_crypen(false)); |
| @@ -559,8 +549,8 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGcm<'c, KEY_SIZE> { | |||
| 559 | 549 | ||
| 560 | let mut out_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; | 550 | let mut out_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; |
| 561 | 551 | ||
| 562 | let read = Cryp::<T, DmaIn, DmaOut>::read_bytes(&mut cryp.outdma, Self::BLOCK_SIZE, &mut out_data); | 552 | let read = Cryp::<T, Async>::read_bytes(cryp.outdma.as_mut().unwrap(), Self::BLOCK_SIZE, &mut out_data); |
| 563 | let write = Cryp::<T, DmaIn, DmaOut>::write_bytes(&mut cryp.indma, Self::BLOCK_SIZE, int_data); | 553 | let write = Cryp::<T, Async>::write_bytes(cryp.indma.as_mut().unwrap(), Self::BLOCK_SIZE, int_data); |
| 564 | 554 | ||
| 565 | embassy_futures::join::join(read, write).await; | 555 | embassy_futures::join::join(read, write).await; |
| 566 | 556 | ||
| @@ -615,13 +605,13 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGmac<'c, KEY_SIZE> { | |||
| 615 | p.cr().modify(|w| w.set_algomode3(true)); | 605 | p.cr().modify(|w| w.set_algomode3(true)); |
| 616 | } | 606 | } |
| 617 | 607 | ||
| 618 | fn init_phase_blocking<T: Instance, DmaIn, DmaOut>(&self, p: pac::cryp::Cryp, _cryp: &Cryp<T, DmaIn, DmaOut>) { | 608 | fn init_phase_blocking<T: Instance, M: Mode>(&self, p: pac::cryp::Cryp, _cryp: &Cryp<T, M>) { |
| 619 | p.cr().modify(|w| w.set_gcm_ccmph(0)); | 609 | p.cr().modify(|w| w.set_gcm_ccmph(0)); |
| 620 | p.cr().modify(|w| w.set_crypen(true)); | 610 | p.cr().modify(|w| w.set_crypen(true)); |
| 621 | while p.cr().read().crypen() {} | 611 | while p.cr().read().crypen() {} |
| 622 | } | 612 | } |
| 623 | 613 | ||
| 624 | async fn init_phase<T: Instance, DmaIn, DmaOut>(&self, p: pac::cryp::Cryp, _cryp: &mut Cryp<'_, T, DmaIn, DmaOut>) { | 614 | async fn init_phase<T: Instance>(&self, p: pac::cryp::Cryp, _cryp: &mut Cryp<'_, T, Async>) { |
| 625 | p.cr().modify(|w| w.set_gcm_ccmph(0)); | 615 | p.cr().modify(|w| w.set_gcm_ccmph(0)); |
| 626 | p.cr().modify(|w| w.set_crypen(true)); | 616 | p.cr().modify(|w| w.set_crypen(true)); |
| 627 | while p.cr().read().crypen() {} | 617 | while p.cr().read().crypen() {} |
| @@ -649,10 +639,10 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGmac<'c, KEY_SIZE> { | |||
| 649 | } | 639 | } |
| 650 | 640 | ||
| 651 | #[cfg(cryp_v2)] | 641 | #[cfg(cryp_v2)] |
| 652 | fn post_final_blocking<T: Instance, DmaIn, DmaOut>( | 642 | fn post_final_blocking<T: Instance, M: Mode>( |
| 653 | &self, | 643 | &self, |
| 654 | p: pac::cryp::Cryp, | 644 | p: pac::cryp::Cryp, |
| 655 | cryp: &Cryp<T, DmaIn, DmaOut>, | 645 | cryp: &Cryp<T, M>, |
| 656 | dir: Direction, | 646 | dir: Direction, |
| 657 | int_data: &mut [u8; AES_BLOCK_SIZE], | 647 | int_data: &mut [u8; AES_BLOCK_SIZE], |
| 658 | _temp1: [u32; 4], | 648 | _temp1: [u32; 4], |
| @@ -675,18 +665,15 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGmac<'c, KEY_SIZE> { | |||
| 675 | } | 665 | } |
| 676 | 666 | ||
| 677 | #[cfg(cryp_v2)] | 667 | #[cfg(cryp_v2)] |
| 678 | async fn post_final<T: Instance, DmaIn, DmaOut>( | 668 | async fn post_final<T: Instance>( |
| 679 | &self, | 669 | &self, |
| 680 | p: pac::cryp::Cryp, | 670 | p: pac::cryp::Cryp, |
| 681 | cryp: &mut Cryp<'_, T, DmaIn, DmaOut>, | 671 | cryp: &mut Cryp<'_, T, Async>, |
| 682 | dir: Direction, | 672 | dir: Direction, |
| 683 | int_data: &mut [u8; AES_BLOCK_SIZE], | 673 | int_data: &mut [u8; AES_BLOCK_SIZE], |
| 684 | _temp1: [u32; 4], | 674 | _temp1: [u32; 4], |
| 685 | padding_mask: [u8; AES_BLOCK_SIZE], | 675 | padding_mask: [u8; AES_BLOCK_SIZE], |
| 686 | ) where | 676 | ) { |
| 687 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 688 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 689 | { | ||
| 690 | if dir == Direction::Encrypt { | 677 | if dir == Direction::Encrypt { |
| 691 | // Handle special GCM partial block process. | 678 | // Handle special GCM partial block process. |
| 692 | p.cr().modify(|w| w.set_crypen(false)); | 679 | p.cr().modify(|w| w.set_crypen(false)); |
| @@ -700,8 +687,8 @@ impl<'c, const KEY_SIZE: usize> Cipher<'c> for AesGmac<'c, KEY_SIZE> { | |||
| 700 | 687 | ||
| 701 | let mut out_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; | 688 | let mut out_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; |
| 702 | 689 | ||
| 703 | let read = Cryp::<T, DmaIn, DmaOut>::read_bytes(&mut cryp.outdma, Self::BLOCK_SIZE, &mut out_data); | 690 | let read = Cryp::<T, Async>::read_bytes(cryp.outdma.as_mut().unwrap(), Self::BLOCK_SIZE, &mut out_data); |
| 704 | let write = Cryp::<T, DmaIn, DmaOut>::write_bytes(&mut cryp.indma, Self::BLOCK_SIZE, int_data); | 691 | let write = Cryp::<T, Async>::write_bytes(cryp.indma.as_mut().unwrap(), Self::BLOCK_SIZE, int_data); |
| 705 | 692 | ||
| 706 | embassy_futures::join::join(read, write).await; | 693 | embassy_futures::join::join(read, write).await; |
| 707 | } | 694 | } |
| @@ -812,7 +799,7 @@ impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> Cip | |||
| 812 | p.cr().modify(|w| w.set_algomode3(true)); | 799 | p.cr().modify(|w| w.set_algomode3(true)); |
| 813 | } | 800 | } |
| 814 | 801 | ||
| 815 | fn init_phase_blocking<T: Instance, DmaIn, DmaOut>(&self, p: pac::cryp::Cryp, cryp: &Cryp<T, DmaIn, DmaOut>) { | 802 | fn init_phase_blocking<T: Instance, M: Mode>(&self, p: pac::cryp::Cryp, cryp: &Cryp<T, M>) { |
| 816 | p.cr().modify(|w| w.set_gcm_ccmph(0)); | 803 | p.cr().modify(|w| w.set_gcm_ccmph(0)); |
| 817 | 804 | ||
| 818 | cryp.write_bytes_blocking(Self::BLOCK_SIZE, &self.block0); | 805 | cryp.write_bytes_blocking(Self::BLOCK_SIZE, &self.block0); |
| @@ -821,14 +808,10 @@ impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> Cip | |||
| 821 | while p.cr().read().crypen() {} | 808 | while p.cr().read().crypen() {} |
| 822 | } | 809 | } |
| 823 | 810 | ||
| 824 | async fn init_phase<T: Instance, DmaIn, DmaOut>(&self, p: pac::cryp::Cryp, cryp: &mut Cryp<'_, T, DmaIn, DmaOut>) | 811 | async fn init_phase<T: Instance>(&self, p: pac::cryp::Cryp, cryp: &mut Cryp<'_, T, Async>) { |
| 825 | where | ||
| 826 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 827 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 828 | { | ||
| 829 | p.cr().modify(|w| w.set_gcm_ccmph(0)); | 812 | p.cr().modify(|w| w.set_gcm_ccmph(0)); |
| 830 | 813 | ||
| 831 | Cryp::<T, DmaIn, DmaOut>::write_bytes(&mut cryp.indma, Self::BLOCK_SIZE, &self.block0).await; | 814 | Cryp::<T, Async>::write_bytes(cryp.indma.as_mut().unwrap(), Self::BLOCK_SIZE, &self.block0).await; |
| 832 | 815 | ||
| 833 | p.cr().modify(|w| w.set_crypen(true)); | 816 | p.cr().modify(|w| w.set_crypen(true)); |
| 834 | while p.cr().read().crypen() {} | 817 | while p.cr().read().crypen() {} |
| @@ -865,10 +848,10 @@ impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> Cip | |||
| 865 | } | 848 | } |
| 866 | 849 | ||
| 867 | #[cfg(cryp_v2)] | 850 | #[cfg(cryp_v2)] |
| 868 | fn post_final_blocking<T: Instance, DmaIn, DmaOut>( | 851 | fn post_final_blocking<T: Instance, M: Mode>( |
| 869 | &self, | 852 | &self, |
| 870 | p: pac::cryp::Cryp, | 853 | p: pac::cryp::Cryp, |
| 871 | cryp: &Cryp<T, DmaIn, DmaOut>, | 854 | cryp: &Cryp<T, M>, |
| 872 | dir: Direction, | 855 | dir: Direction, |
| 873 | int_data: &mut [u8; AES_BLOCK_SIZE], | 856 | int_data: &mut [u8; AES_BLOCK_SIZE], |
| 874 | temp1: [u32; 4], | 857 | temp1: [u32; 4], |
| @@ -902,18 +885,15 @@ impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> Cip | |||
| 902 | } | 885 | } |
| 903 | 886 | ||
| 904 | #[cfg(cryp_v2)] | 887 | #[cfg(cryp_v2)] |
| 905 | async fn post_final<T: Instance, DmaIn, DmaOut>( | 888 | async fn post_final<T: Instance>( |
| 906 | &self, | 889 | &self, |
| 907 | p: pac::cryp::Cryp, | 890 | p: pac::cryp::Cryp, |
| 908 | cryp: &mut Cryp<'_, T, DmaIn, DmaOut>, | 891 | cryp: &mut Cryp<'_, T, Async>, |
| 909 | dir: Direction, | 892 | dir: Direction, |
| 910 | int_data: &mut [u8; AES_BLOCK_SIZE], | 893 | int_data: &mut [u8; AES_BLOCK_SIZE], |
| 911 | temp1: [u32; 4], | 894 | temp1: [u32; 4], |
| 912 | padding_mask: [u8; 16], | 895 | padding_mask: [u8; 16], |
| 913 | ) where | 896 | ) { |
| 914 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 915 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 916 | { | ||
| 917 | if dir == Direction::Decrypt { | 897 | if dir == Direction::Decrypt { |
| 918 | //Handle special CCM partial block process. | 898 | //Handle special CCM partial block process. |
| 919 | let mut temp2 = [0; 4]; | 899 | let mut temp2 = [0; 4]; |
| @@ -937,7 +917,7 @@ impl<'c, const KEY_SIZE: usize, const TAG_SIZE: usize, const IV_SIZE: usize> Cip | |||
| 937 | in_data[i] = int_word; | 917 | in_data[i] = int_word; |
| 938 | in_data[i] = in_data[i] ^ temp1[i] ^ temp2[i]; | 918 | in_data[i] = in_data[i] ^ temp1[i] ^ temp2[i]; |
| 939 | } | 919 | } |
| 940 | Cryp::<T, DmaIn, DmaOut>::write_words(&mut cryp.indma, Self::BLOCK_SIZE, &in_data).await; | 920 | Cryp::<T, Async>::write_words(cryp.indma.as_mut().unwrap(), Self::BLOCK_SIZE, &in_data).await; |
| 941 | } | 921 | } |
| 942 | } | 922 | } |
| 943 | } | 923 | } |
| @@ -1007,26 +987,26 @@ pub enum Direction { | |||
| 1007 | } | 987 | } |
| 1008 | 988 | ||
| 1009 | /// Crypto Accelerator Driver | 989 | /// Crypto Accelerator Driver |
| 1010 | pub struct Cryp<'d, T: Instance, DmaIn = NoDma, DmaOut = NoDma> { | 990 | pub struct Cryp<'d, T: Instance, M: Mode> { |
| 1011 | _peripheral: PeripheralRef<'d, T>, | 991 | _peripheral: PeripheralRef<'d, T>, |
| 1012 | indma: PeripheralRef<'d, DmaIn>, | 992 | _phantom: PhantomData<M>, |
| 1013 | outdma: PeripheralRef<'d, DmaOut>, | 993 | indma: Option<ChannelAndRequest<'d>>, |
| 994 | outdma: Option<ChannelAndRequest<'d>>, | ||
| 1014 | } | 995 | } |
| 1015 | 996 | ||
| 1016 | impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> { | 997 | impl<'d, T: Instance> Cryp<'d, T, Blocking> { |
| 1017 | /// Create a new CRYP driver. | 998 | /// Create a new CRYP driver in blocking mode. |
| 1018 | pub fn new( | 999 | pub fn new_blocking( |
| 1019 | peri: impl Peripheral<P = T> + 'd, | 1000 | peri: impl Peripheral<P = T> + 'd, |
| 1020 | indma: impl Peripheral<P = DmaIn> + 'd, | ||
| 1021 | outdma: impl Peripheral<P = DmaOut> + 'd, | ||
| 1022 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 1001 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 1023 | ) -> Self { | 1002 | ) -> Self { |
| 1024 | rcc::enable_and_reset::<T>(); | 1003 | rcc::enable_and_reset::<T>(); |
| 1025 | into_ref!(peri, indma, outdma); | 1004 | into_ref!(peri); |
| 1026 | let instance = Self { | 1005 | let instance = Self { |
| 1027 | _peripheral: peri, | 1006 | _peripheral: peri, |
| 1028 | indma: indma, | 1007 | _phantom: PhantomData, |
| 1029 | outdma: outdma, | 1008 | indma: None, |
| 1009 | outdma: None, | ||
| 1030 | }; | 1010 | }; |
| 1031 | 1011 | ||
| 1032 | T::Interrupt::unpend(); | 1012 | T::Interrupt::unpend(); |
| @@ -1034,7 +1014,9 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> { | |||
| 1034 | 1014 | ||
| 1035 | instance | 1015 | instance |
| 1036 | } | 1016 | } |
| 1017 | } | ||
| 1037 | 1018 | ||
| 1019 | impl<'d, T: Instance, M: Mode> Cryp<'d, T, M> { | ||
| 1038 | /// Start a new encrypt or decrypt operation for the given cipher. | 1020 | /// Start a new encrypt or decrypt operation for the given cipher. |
| 1039 | pub fn start_blocking<'c, C: Cipher<'c> + CipherSized + IVSized>( | 1021 | pub fn start_blocking<'c, C: Cipher<'c> + CipherSized + IVSized>( |
| 1040 | &self, | 1022 | &self, |
| @@ -1114,89 +1096,6 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> { | |||
| 1114 | ctx | 1096 | ctx |
| 1115 | } | 1097 | } |
| 1116 | 1098 | ||
| 1117 | /// Start a new encrypt or decrypt operation for the given cipher. | ||
| 1118 | pub async fn start<'c, C: Cipher<'c> + CipherSized + IVSized>( | ||
| 1119 | &mut self, | ||
| 1120 | cipher: &'c C, | ||
| 1121 | dir: Direction, | ||
| 1122 | ) -> Context<'c, C> | ||
| 1123 | where | ||
| 1124 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 1125 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 1126 | { | ||
| 1127 | let mut ctx: Context<'c, C> = Context { | ||
| 1128 | dir, | ||
| 1129 | last_block_processed: false, | ||
| 1130 | cr: 0, | ||
| 1131 | iv: [0; 4], | ||
| 1132 | csgcmccm: [0; 8], | ||
| 1133 | csgcm: [0; 8], | ||
| 1134 | aad_complete: false, | ||
| 1135 | header_len: 0, | ||
| 1136 | payload_len: 0, | ||
| 1137 | cipher: cipher, | ||
| 1138 | phantom_data: PhantomData, | ||
| 1139 | header_processed: false, | ||
| 1140 | aad_buffer: [0; 16], | ||
| 1141 | aad_buffer_len: 0, | ||
| 1142 | }; | ||
| 1143 | |||
| 1144 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1145 | |||
| 1146 | let key = ctx.cipher.key(); | ||
| 1147 | |||
| 1148 | if key.len() == (128 / 8) { | ||
| 1149 | T::regs().cr().modify(|w| w.set_keysize(0)); | ||
| 1150 | } else if key.len() == (192 / 8) { | ||
| 1151 | T::regs().cr().modify(|w| w.set_keysize(1)); | ||
| 1152 | } else if key.len() == (256 / 8) { | ||
| 1153 | T::regs().cr().modify(|w| w.set_keysize(2)); | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | self.load_key(key); | ||
| 1157 | |||
| 1158 | // Set data type to 8-bit. This will match software implementations. | ||
| 1159 | T::regs().cr().modify(|w| w.set_datatype(2)); | ||
| 1160 | |||
| 1161 | ctx.cipher.prepare_key(T::regs()); | ||
| 1162 | |||
| 1163 | ctx.cipher.set_algomode(T::regs()); | ||
| 1164 | |||
| 1165 | // Set encrypt/decrypt | ||
| 1166 | if dir == Direction::Encrypt { | ||
| 1167 | T::regs().cr().modify(|w| w.set_algodir(false)); | ||
| 1168 | } else { | ||
| 1169 | T::regs().cr().modify(|w| w.set_algodir(true)); | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | // Load the IV into the registers. | ||
| 1173 | let iv = ctx.cipher.iv(); | ||
| 1174 | let mut full_iv: [u8; 16] = [0; 16]; | ||
| 1175 | full_iv[0..iv.len()].copy_from_slice(iv); | ||
| 1176 | let mut iv_idx = 0; | ||
| 1177 | let mut iv_word: [u8; 4] = [0; 4]; | ||
| 1178 | iv_word.copy_from_slice(&full_iv[iv_idx..iv_idx + 4]); | ||
| 1179 | iv_idx += 4; | ||
| 1180 | T::regs().init(0).ivlr().write_value(u32::from_be_bytes(iv_word)); | ||
| 1181 | iv_word.copy_from_slice(&full_iv[iv_idx..iv_idx + 4]); | ||
| 1182 | iv_idx += 4; | ||
| 1183 | T::regs().init(0).ivrr().write_value(u32::from_be_bytes(iv_word)); | ||
| 1184 | iv_word.copy_from_slice(&full_iv[iv_idx..iv_idx + 4]); | ||
| 1185 | iv_idx += 4; | ||
| 1186 | T::regs().init(1).ivlr().write_value(u32::from_be_bytes(iv_word)); | ||
| 1187 | iv_word.copy_from_slice(&full_iv[iv_idx..iv_idx + 4]); | ||
| 1188 | T::regs().init(1).ivrr().write_value(u32::from_be_bytes(iv_word)); | ||
| 1189 | |||
| 1190 | // Flush in/out FIFOs | ||
| 1191 | T::regs().cr().modify(|w| w.fflush()); | ||
| 1192 | |||
| 1193 | ctx.cipher.init_phase(T::regs(), self).await; | ||
| 1194 | |||
| 1195 | self.store_context(&mut ctx); | ||
| 1196 | |||
| 1197 | ctx | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] | 1099 | #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] |
| 1201 | /// Controls the header phase of cipher processing. | 1100 | /// Controls the header phase of cipher processing. |
| 1202 | /// This function is only valid for authenticated ciphers including GCM, CCM, and GMAC. | 1101 | /// This function is only valid for authenticated ciphers including GCM, CCM, and GMAC. |
| @@ -1294,101 +1193,6 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> { | |||
| 1294 | self.store_context(ctx); | 1193 | self.store_context(ctx); |
| 1295 | } | 1194 | } |
| 1296 | 1195 | ||
| 1297 | #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] | ||
| 1298 | /// Controls the header phase of cipher processing. | ||
| 1299 | /// This function is only valid for authenticated ciphers including GCM, CCM, and GMAC. | ||
| 1300 | /// All additional associated data (AAD) must be supplied to this function prior to starting the payload phase with `payload`. | ||
| 1301 | /// The AAD must be supplied in multiples of the block size (128-bits for AES, 64-bits for DES), except when supplying the last block. | ||
| 1302 | /// When supplying the last block of AAD, `last_aad_block` must be `true`. | ||
| 1303 | pub async fn aad<'c, const TAG_SIZE: usize, C: Cipher<'c> + CipherSized + IVSized + CipherAuthenticated<TAG_SIZE>>( | ||
| 1304 | &mut self, | ||
| 1305 | ctx: &mut Context<'c, C>, | ||
| 1306 | aad: &[u8], | ||
| 1307 | last_aad_block: bool, | ||
| 1308 | ) where | ||
| 1309 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 1310 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 1311 | { | ||
| 1312 | self.load_context(ctx); | ||
| 1313 | |||
| 1314 | // Perform checks for correctness. | ||
| 1315 | if ctx.aad_complete { | ||
| 1316 | panic!("Cannot update AAD after starting payload!") | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | ctx.header_len += aad.len() as u64; | ||
| 1320 | |||
| 1321 | // Header phase | ||
| 1322 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1323 | T::regs().cr().modify(|w| w.set_gcm_ccmph(1)); | ||
| 1324 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 1325 | |||
| 1326 | // First write the header B1 block if not yet written. | ||
| 1327 | if !ctx.header_processed { | ||
| 1328 | ctx.header_processed = true; | ||
| 1329 | let header = ctx.cipher.get_header_block(); | ||
| 1330 | ctx.aad_buffer[0..header.len()].copy_from_slice(header); | ||
| 1331 | ctx.aad_buffer_len += header.len(); | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | // Fill the header block to make a full block. | ||
| 1335 | let len_to_copy = min(aad.len(), C::BLOCK_SIZE - ctx.aad_buffer_len); | ||
| 1336 | ctx.aad_buffer[ctx.aad_buffer_len..ctx.aad_buffer_len + len_to_copy].copy_from_slice(&aad[..len_to_copy]); | ||
| 1337 | ctx.aad_buffer_len += len_to_copy; | ||
| 1338 | ctx.aad_buffer[ctx.aad_buffer_len..].fill(0); | ||
| 1339 | let mut aad_len_remaining = aad.len() - len_to_copy; | ||
| 1340 | |||
| 1341 | if ctx.aad_buffer_len < C::BLOCK_SIZE { | ||
| 1342 | // The buffer isn't full and this is the last buffer, so process it as is (already padded). | ||
| 1343 | if last_aad_block { | ||
| 1344 | Self::write_bytes(&mut self.indma, C::BLOCK_SIZE, &ctx.aad_buffer).await; | ||
| 1345 | assert_eq!(T::regs().sr().read().ifem(), true); | ||
| 1346 | |||
| 1347 | // Switch to payload phase. | ||
| 1348 | ctx.aad_complete = true; | ||
| 1349 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1350 | T::regs().cr().modify(|w| w.set_gcm_ccmph(2)); | ||
| 1351 | T::regs().cr().modify(|w| w.fflush()); | ||
| 1352 | } else { | ||
| 1353 | // Just return because we don't yet have a full block to process. | ||
| 1354 | return; | ||
| 1355 | } | ||
| 1356 | } else { | ||
| 1357 | // Load the full block from the buffer. | ||
| 1358 | Self::write_bytes(&mut self.indma, C::BLOCK_SIZE, &ctx.aad_buffer).await; | ||
| 1359 | assert_eq!(T::regs().sr().read().ifem(), true); | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | // Handle a partial block that is passed in. | ||
| 1363 | ctx.aad_buffer_len = 0; | ||
| 1364 | let leftovers = aad_len_remaining % C::BLOCK_SIZE; | ||
| 1365 | ctx.aad_buffer[..leftovers].copy_from_slice(&aad[aad.len() - leftovers..aad.len()]); | ||
| 1366 | ctx.aad_buffer_len += leftovers; | ||
| 1367 | ctx.aad_buffer[ctx.aad_buffer_len..].fill(0); | ||
| 1368 | aad_len_remaining -= leftovers; | ||
| 1369 | assert_eq!(aad_len_remaining % C::BLOCK_SIZE, 0); | ||
| 1370 | |||
| 1371 | // Load full data blocks into core. | ||
| 1372 | let num_full_blocks = aad_len_remaining / C::BLOCK_SIZE; | ||
| 1373 | let start_index = len_to_copy; | ||
| 1374 | let end_index = start_index + (C::BLOCK_SIZE * num_full_blocks); | ||
| 1375 | Self::write_bytes(&mut self.indma, C::BLOCK_SIZE, &aad[start_index..end_index]).await; | ||
| 1376 | |||
| 1377 | if last_aad_block { | ||
| 1378 | if leftovers > 0 { | ||
| 1379 | Self::write_bytes(&mut self.indma, C::BLOCK_SIZE, &ctx.aad_buffer).await; | ||
| 1380 | assert_eq!(T::regs().sr().read().ifem(), true); | ||
| 1381 | } | ||
| 1382 | // Switch to payload phase. | ||
| 1383 | ctx.aad_complete = true; | ||
| 1384 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1385 | T::regs().cr().modify(|w| w.set_gcm_ccmph(2)); | ||
| 1386 | T::regs().cr().modify(|w| w.fflush()); | ||
| 1387 | } | ||
| 1388 | |||
| 1389 | self.store_context(ctx); | ||
| 1390 | } | ||
| 1391 | |||
| 1392 | /// Performs encryption/decryption on the provided context. | 1196 | /// Performs encryption/decryption on the provided context. |
| 1393 | /// The context determines algorithm, mode, and state of the crypto accelerator. | 1197 | /// The context determines algorithm, mode, and state of the crypto accelerator. |
| 1394 | /// When the last piece of data is supplied, `last_block` should be `true`. | 1198 | /// When the last piece of data is supplied, `last_block` should be `true`. |
| @@ -1478,105 +1282,6 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> { | |||
| 1478 | self.store_context(ctx); | 1282 | self.store_context(ctx); |
| 1479 | } | 1283 | } |
| 1480 | 1284 | ||
| 1481 | /// Performs encryption/decryption on the provided context. | ||
| 1482 | /// The context determines algorithm, mode, and state of the crypto accelerator. | ||
| 1483 | /// When the last piece of data is supplied, `last_block` should be `true`. | ||
| 1484 | /// This function panics under various mismatches of parameters. | ||
| 1485 | /// Output buffer must be at least as long as the input buffer. | ||
| 1486 | /// Data must be a multiple of block size (128-bits for AES, 64-bits for DES) for CBC and ECB modes. | ||
| 1487 | /// Padding or ciphertext stealing must be managed by the application for these modes. | ||
| 1488 | /// Data must also be a multiple of block size unless `last_block` is `true`. | ||
| 1489 | pub async fn payload<'c, C: Cipher<'c> + CipherSized + IVSized>( | ||
| 1490 | &mut self, | ||
| 1491 | ctx: &mut Context<'c, C>, | ||
| 1492 | input: &[u8], | ||
| 1493 | output: &mut [u8], | ||
| 1494 | last_block: bool, | ||
| 1495 | ) where | ||
| 1496 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 1497 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 1498 | { | ||
| 1499 | self.load_context(ctx); | ||
| 1500 | |||
| 1501 | let last_block_remainder = input.len() % C::BLOCK_SIZE; | ||
| 1502 | |||
| 1503 | // Perform checks for correctness. | ||
| 1504 | if !ctx.aad_complete && ctx.header_len > 0 { | ||
| 1505 | panic!("Additional associated data must be processed first!"); | ||
| 1506 | } else if !ctx.aad_complete { | ||
| 1507 | #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] | ||
| 1508 | { | ||
| 1509 | ctx.aad_complete = true; | ||
| 1510 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1511 | T::regs().cr().modify(|w| w.set_gcm_ccmph(2)); | ||
| 1512 | T::regs().cr().modify(|w| w.fflush()); | ||
| 1513 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 1514 | } | ||
| 1515 | } | ||
| 1516 | if ctx.last_block_processed { | ||
| 1517 | panic!("The last block has already been processed!"); | ||
| 1518 | } | ||
| 1519 | if input.len() > output.len() { | ||
| 1520 | panic!("Output buffer length must match input length."); | ||
| 1521 | } | ||
| 1522 | if !last_block { | ||
| 1523 | if last_block_remainder != 0 { | ||
| 1524 | panic!("Input length must be a multiple of {} bytes.", C::BLOCK_SIZE); | ||
| 1525 | } | ||
| 1526 | } | ||
| 1527 | if C::REQUIRES_PADDING { | ||
| 1528 | if last_block_remainder != 0 { | ||
| 1529 | panic!("Input must be a multiple of {} bytes in ECB and CBC modes. Consider padding or ciphertext stealing.", C::BLOCK_SIZE); | ||
| 1530 | } | ||
| 1531 | } | ||
| 1532 | if last_block { | ||
| 1533 | ctx.last_block_processed = true; | ||
| 1534 | } | ||
| 1535 | |||
| 1536 | // Load data into core, block by block. | ||
| 1537 | let num_full_blocks = input.len() / C::BLOCK_SIZE; | ||
| 1538 | for block in 0..num_full_blocks { | ||
| 1539 | let index = block * C::BLOCK_SIZE; | ||
| 1540 | // Read block out | ||
| 1541 | let read = Self::read_bytes( | ||
| 1542 | &mut self.outdma, | ||
| 1543 | C::BLOCK_SIZE, | ||
| 1544 | &mut output[index..index + C::BLOCK_SIZE], | ||
| 1545 | ); | ||
| 1546 | // Write block in | ||
| 1547 | let write = Self::write_bytes(&mut self.indma, C::BLOCK_SIZE, &input[index..index + C::BLOCK_SIZE]); | ||
| 1548 | embassy_futures::join::join(read, write).await; | ||
| 1549 | } | ||
| 1550 | |||
| 1551 | // Handle the final block, which is incomplete. | ||
| 1552 | if last_block_remainder > 0 { | ||
| 1553 | let padding_len = C::BLOCK_SIZE - last_block_remainder; | ||
| 1554 | let temp1 = ctx.cipher.pre_final(T::regs(), ctx.dir, padding_len); | ||
| 1555 | |||
| 1556 | let mut intermediate_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; | ||
| 1557 | let mut last_block: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; | ||
| 1558 | last_block[..last_block_remainder].copy_from_slice(&input[input.len() - last_block_remainder..input.len()]); | ||
| 1559 | let read = Self::read_bytes(&mut self.outdma, C::BLOCK_SIZE, &mut intermediate_data); | ||
| 1560 | let write = Self::write_bytes(&mut self.indma, C::BLOCK_SIZE, &last_block); | ||
| 1561 | embassy_futures::join::join(read, write).await; | ||
| 1562 | |||
| 1563 | // Handle the last block depending on mode. | ||
| 1564 | let output_len = output.len(); | ||
| 1565 | output[output_len - last_block_remainder..output_len] | ||
| 1566 | .copy_from_slice(&intermediate_data[0..last_block_remainder]); | ||
| 1567 | |||
| 1568 | let mut mask: [u8; 16] = [0; 16]; | ||
| 1569 | mask[..last_block_remainder].fill(0xFF); | ||
| 1570 | ctx.cipher | ||
| 1571 | .post_final(T::regs(), self, ctx.dir, &mut intermediate_data, temp1, mask) | ||
| 1572 | .await; | ||
| 1573 | } | ||
| 1574 | |||
| 1575 | ctx.payload_len += input.len() as u64; | ||
| 1576 | |||
| 1577 | self.store_context(ctx); | ||
| 1578 | } | ||
| 1579 | |||
| 1580 | #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] | 1285 | #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] |
| 1581 | /// Generates an authentication tag for authenticated ciphers including GCM, CCM, and GMAC. | 1286 | /// Generates an authentication tag for authenticated ciphers including GCM, CCM, and GMAC. |
| 1582 | /// Called after the all data has been encrypted/decrypted by `payload`. | 1287 | /// Called after the all data has been encrypted/decrypted by `payload`. |
| @@ -1623,57 +1328,6 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> { | |||
| 1623 | tag | 1328 | tag |
| 1624 | } | 1329 | } |
| 1625 | 1330 | ||
| 1626 | #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] | ||
| 1627 | // Generates an authentication tag for authenticated ciphers including GCM, CCM, and GMAC. | ||
| 1628 | /// Called after the all data has been encrypted/decrypted by `payload`. | ||
| 1629 | pub async fn finish< | ||
| 1630 | 'c, | ||
| 1631 | const TAG_SIZE: usize, | ||
| 1632 | C: Cipher<'c> + CipherSized + IVSized + CipherAuthenticated<TAG_SIZE>, | ||
| 1633 | >( | ||
| 1634 | &mut self, | ||
| 1635 | mut ctx: Context<'c, C>, | ||
| 1636 | ) -> [u8; TAG_SIZE] | ||
| 1637 | where | ||
| 1638 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 1639 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 1640 | { | ||
| 1641 | self.load_context(&mut ctx); | ||
| 1642 | |||
| 1643 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1644 | T::regs().cr().modify(|w| w.set_gcm_ccmph(3)); | ||
| 1645 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 1646 | |||
| 1647 | let headerlen1: u32 = ((ctx.header_len * 8) >> 32) as u32; | ||
| 1648 | let headerlen2: u32 = (ctx.header_len * 8) as u32; | ||
| 1649 | let payloadlen1: u32 = ((ctx.payload_len * 8) >> 32) as u32; | ||
| 1650 | let payloadlen2: u32 = (ctx.payload_len * 8) as u32; | ||
| 1651 | |||
| 1652 | #[cfg(cryp_v2)] | ||
| 1653 | let footer: [u32; 4] = [ | ||
| 1654 | headerlen1.swap_bytes(), | ||
| 1655 | headerlen2.swap_bytes(), | ||
| 1656 | payloadlen1.swap_bytes(), | ||
| 1657 | payloadlen2.swap_bytes(), | ||
| 1658 | ]; | ||
| 1659 | #[cfg(any(cryp_v3, cryp_v4))] | ||
| 1660 | let footer: [u32; 4] = [headerlen1, headerlen2, payloadlen1, payloadlen2]; | ||
| 1661 | |||
| 1662 | let write = Self::write_words(&mut self.indma, C::BLOCK_SIZE, &footer); | ||
| 1663 | |||
| 1664 | let mut full_tag: [u8; 16] = [0; 16]; | ||
| 1665 | let read = Self::read_bytes(&mut self.outdma, C::BLOCK_SIZE, &mut full_tag); | ||
| 1666 | |||
| 1667 | embassy_futures::join::join(read, write).await; | ||
| 1668 | |||
| 1669 | let mut tag: [u8; TAG_SIZE] = [0; TAG_SIZE]; | ||
| 1670 | tag.copy_from_slice(&full_tag[0..TAG_SIZE]); | ||
| 1671 | |||
| 1672 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1673 | |||
| 1674 | tag | ||
| 1675 | } | ||
| 1676 | |||
| 1677 | fn load_key(&self, key: &[u8]) { | 1331 | fn load_key(&self, key: &[u8]) { |
| 1678 | // Load the key into the registers. | 1332 | // Load the key into the registers. |
| 1679 | let mut keyidx = 0; | 1333 | let mut keyidx = 0; |
| @@ -1774,17 +1428,393 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> { | |||
| 1774 | } | 1428 | } |
| 1775 | } | 1429 | } |
| 1776 | 1430 | ||
| 1777 | async fn write_bytes(dma: &mut PeripheralRef<'_, DmaIn>, block_size: usize, blocks: &[u8]) | 1431 | #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] |
| 1778 | where | 1432 | fn write_words_blocking(&self, block_size: usize, blocks: &[u32]) { |
| 1779 | DmaIn: crate::cryp::DmaIn<T>, | 1433 | assert_eq!((blocks.len() * 4) % block_size, 0); |
| 1780 | { | 1434 | let mut byte_counter: usize = 0; |
| 1435 | for word in blocks { | ||
| 1436 | T::regs().din().write_value(*word); | ||
| 1437 | byte_counter += 4; | ||
| 1438 | if byte_counter % block_size == 0 { | ||
| 1439 | // Block until input FIFO is empty. | ||
| 1440 | while !T::regs().sr().read().ifem() {} | ||
| 1441 | } | ||
| 1442 | } | ||
| 1443 | } | ||
| 1444 | |||
| 1445 | fn read_bytes_blocking(&self, block_size: usize, blocks: &mut [u8]) { | ||
| 1446 | // Block until there is output to read. | ||
| 1447 | while !T::regs().sr().read().ofne() {} | ||
| 1448 | // Ensure input is a multiple of block size. | ||
| 1449 | assert_eq!(blocks.len() % block_size, 0); | ||
| 1450 | // Read block out | ||
| 1451 | let mut index = 0; | ||
| 1452 | let end_index = blocks.len(); | ||
| 1453 | while index < end_index { | ||
| 1454 | let out_word: u32 = T::regs().dout().read(); | ||
| 1455 | blocks[index..index + 4].copy_from_slice(u32::to_ne_bytes(out_word).as_slice()); | ||
| 1456 | index += 4; | ||
| 1457 | } | ||
| 1458 | } | ||
| 1459 | } | ||
| 1460 | |||
| 1461 | impl<'d, T: Instance> Cryp<'d, T, Async> { | ||
| 1462 | /// Create a new CRYP driver. | ||
| 1463 | pub fn new( | ||
| 1464 | peri: impl Peripheral<P = T> + 'd, | ||
| 1465 | indma: impl Peripheral<P = impl DmaIn<T>> + 'd, | ||
| 1466 | outdma: impl Peripheral<P = impl DmaOut<T>> + 'd, | ||
| 1467 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||
| 1468 | ) -> Self { | ||
| 1469 | rcc::enable_and_reset::<T>(); | ||
| 1470 | into_ref!(peri, indma, outdma); | ||
| 1471 | let instance = Self { | ||
| 1472 | _peripheral: peri, | ||
| 1473 | _phantom: PhantomData, | ||
| 1474 | indma: new_dma!(indma), | ||
| 1475 | outdma: new_dma!(outdma), | ||
| 1476 | }; | ||
| 1477 | |||
| 1478 | T::Interrupt::unpend(); | ||
| 1479 | unsafe { T::Interrupt::enable() }; | ||
| 1480 | |||
| 1481 | instance | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | /// Start a new encrypt or decrypt operation for the given cipher. | ||
| 1485 | pub async fn start<'c, C: Cipher<'c> + CipherSized + IVSized>( | ||
| 1486 | &mut self, | ||
| 1487 | cipher: &'c C, | ||
| 1488 | dir: Direction, | ||
| 1489 | ) -> Context<'c, C> { | ||
| 1490 | let mut ctx: Context<'c, C> = Context { | ||
| 1491 | dir, | ||
| 1492 | last_block_processed: false, | ||
| 1493 | cr: 0, | ||
| 1494 | iv: [0; 4], | ||
| 1495 | csgcmccm: [0; 8], | ||
| 1496 | csgcm: [0; 8], | ||
| 1497 | aad_complete: false, | ||
| 1498 | header_len: 0, | ||
| 1499 | payload_len: 0, | ||
| 1500 | cipher: cipher, | ||
| 1501 | phantom_data: PhantomData, | ||
| 1502 | header_processed: false, | ||
| 1503 | aad_buffer: [0; 16], | ||
| 1504 | aad_buffer_len: 0, | ||
| 1505 | }; | ||
| 1506 | |||
| 1507 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1508 | |||
| 1509 | let key = ctx.cipher.key(); | ||
| 1510 | |||
| 1511 | if key.len() == (128 / 8) { | ||
| 1512 | T::regs().cr().modify(|w| w.set_keysize(0)); | ||
| 1513 | } else if key.len() == (192 / 8) { | ||
| 1514 | T::regs().cr().modify(|w| w.set_keysize(1)); | ||
| 1515 | } else if key.len() == (256 / 8) { | ||
| 1516 | T::regs().cr().modify(|w| w.set_keysize(2)); | ||
| 1517 | } | ||
| 1518 | |||
| 1519 | self.load_key(key); | ||
| 1520 | |||
| 1521 | // Set data type to 8-bit. This will match software implementations. | ||
| 1522 | T::regs().cr().modify(|w| w.set_datatype(2)); | ||
| 1523 | |||
| 1524 | ctx.cipher.prepare_key(T::regs()); | ||
| 1525 | |||
| 1526 | ctx.cipher.set_algomode(T::regs()); | ||
| 1527 | |||
| 1528 | // Set encrypt/decrypt | ||
| 1529 | if dir == Direction::Encrypt { | ||
| 1530 | T::regs().cr().modify(|w| w.set_algodir(false)); | ||
| 1531 | } else { | ||
| 1532 | T::regs().cr().modify(|w| w.set_algodir(true)); | ||
| 1533 | } | ||
| 1534 | |||
| 1535 | // Load the IV into the registers. | ||
| 1536 | let iv = ctx.cipher.iv(); | ||
| 1537 | let mut full_iv: [u8; 16] = [0; 16]; | ||
| 1538 | full_iv[0..iv.len()].copy_from_slice(iv); | ||
| 1539 | let mut iv_idx = 0; | ||
| 1540 | let mut iv_word: [u8; 4] = [0; 4]; | ||
| 1541 | iv_word.copy_from_slice(&full_iv[iv_idx..iv_idx + 4]); | ||
| 1542 | iv_idx += 4; | ||
| 1543 | T::regs().init(0).ivlr().write_value(u32::from_be_bytes(iv_word)); | ||
| 1544 | iv_word.copy_from_slice(&full_iv[iv_idx..iv_idx + 4]); | ||
| 1545 | iv_idx += 4; | ||
| 1546 | T::regs().init(0).ivrr().write_value(u32::from_be_bytes(iv_word)); | ||
| 1547 | iv_word.copy_from_slice(&full_iv[iv_idx..iv_idx + 4]); | ||
| 1548 | iv_idx += 4; | ||
| 1549 | T::regs().init(1).ivlr().write_value(u32::from_be_bytes(iv_word)); | ||
| 1550 | iv_word.copy_from_slice(&full_iv[iv_idx..iv_idx + 4]); | ||
| 1551 | T::regs().init(1).ivrr().write_value(u32::from_be_bytes(iv_word)); | ||
| 1552 | |||
| 1553 | // Flush in/out FIFOs | ||
| 1554 | T::regs().cr().modify(|w| w.fflush()); | ||
| 1555 | |||
| 1556 | ctx.cipher.init_phase(T::regs(), self).await; | ||
| 1557 | |||
| 1558 | self.store_context(&mut ctx); | ||
| 1559 | |||
| 1560 | ctx | ||
| 1561 | } | ||
| 1562 | |||
| 1563 | #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] | ||
| 1564 | /// Controls the header phase of cipher processing. | ||
| 1565 | /// This function is only valid for authenticated ciphers including GCM, CCM, and GMAC. | ||
| 1566 | /// All additional associated data (AAD) must be supplied to this function prior to starting the payload phase with `payload`. | ||
| 1567 | /// The AAD must be supplied in multiples of the block size (128-bits for AES, 64-bits for DES), except when supplying the last block. | ||
| 1568 | /// When supplying the last block of AAD, `last_aad_block` must be `true`. | ||
| 1569 | pub async fn aad< | ||
| 1570 | 'c, | ||
| 1571 | const TAG_SIZE: usize, | ||
| 1572 | C: Cipher<'c> + CipherSized + IVSized + CipherAuthenticated<TAG_SIZE>, | ||
| 1573 | >( | ||
| 1574 | &mut self, | ||
| 1575 | ctx: &mut Context<'c, C>, | ||
| 1576 | aad: &[u8], | ||
| 1577 | last_aad_block: bool, | ||
| 1578 | ) { | ||
| 1579 | self.load_context(ctx); | ||
| 1580 | |||
| 1581 | // Perform checks for correctness. | ||
| 1582 | if ctx.aad_complete { | ||
| 1583 | panic!("Cannot update AAD after starting payload!") | ||
| 1584 | } | ||
| 1585 | |||
| 1586 | ctx.header_len += aad.len() as u64; | ||
| 1587 | |||
| 1588 | // Header phase | ||
| 1589 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1590 | T::regs().cr().modify(|w| w.set_gcm_ccmph(1)); | ||
| 1591 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 1592 | |||
| 1593 | // First write the header B1 block if not yet written. | ||
| 1594 | if !ctx.header_processed { | ||
| 1595 | ctx.header_processed = true; | ||
| 1596 | let header = ctx.cipher.get_header_block(); | ||
| 1597 | ctx.aad_buffer[0..header.len()].copy_from_slice(header); | ||
| 1598 | ctx.aad_buffer_len += header.len(); | ||
| 1599 | } | ||
| 1600 | |||
| 1601 | // Fill the header block to make a full block. | ||
| 1602 | let len_to_copy = min(aad.len(), C::BLOCK_SIZE - ctx.aad_buffer_len); | ||
| 1603 | ctx.aad_buffer[ctx.aad_buffer_len..ctx.aad_buffer_len + len_to_copy].copy_from_slice(&aad[..len_to_copy]); | ||
| 1604 | ctx.aad_buffer_len += len_to_copy; | ||
| 1605 | ctx.aad_buffer[ctx.aad_buffer_len..].fill(0); | ||
| 1606 | let mut aad_len_remaining = aad.len() - len_to_copy; | ||
| 1607 | |||
| 1608 | if ctx.aad_buffer_len < C::BLOCK_SIZE { | ||
| 1609 | // The buffer isn't full and this is the last buffer, so process it as is (already padded). | ||
| 1610 | if last_aad_block { | ||
| 1611 | Self::write_bytes(self.indma.as_mut().unwrap(), C::BLOCK_SIZE, &ctx.aad_buffer).await; | ||
| 1612 | assert_eq!(T::regs().sr().read().ifem(), true); | ||
| 1613 | |||
| 1614 | // Switch to payload phase. | ||
| 1615 | ctx.aad_complete = true; | ||
| 1616 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1617 | T::regs().cr().modify(|w| w.set_gcm_ccmph(2)); | ||
| 1618 | T::regs().cr().modify(|w| w.fflush()); | ||
| 1619 | } else { | ||
| 1620 | // Just return because we don't yet have a full block to process. | ||
| 1621 | return; | ||
| 1622 | } | ||
| 1623 | } else { | ||
| 1624 | // Load the full block from the buffer. | ||
| 1625 | Self::write_bytes(self.indma.as_mut().unwrap(), C::BLOCK_SIZE, &ctx.aad_buffer).await; | ||
| 1626 | assert_eq!(T::regs().sr().read().ifem(), true); | ||
| 1627 | } | ||
| 1628 | |||
| 1629 | // Handle a partial block that is passed in. | ||
| 1630 | ctx.aad_buffer_len = 0; | ||
| 1631 | let leftovers = aad_len_remaining % C::BLOCK_SIZE; | ||
| 1632 | ctx.aad_buffer[..leftovers].copy_from_slice(&aad[aad.len() - leftovers..aad.len()]); | ||
| 1633 | ctx.aad_buffer_len += leftovers; | ||
| 1634 | ctx.aad_buffer[ctx.aad_buffer_len..].fill(0); | ||
| 1635 | aad_len_remaining -= leftovers; | ||
| 1636 | assert_eq!(aad_len_remaining % C::BLOCK_SIZE, 0); | ||
| 1637 | |||
| 1638 | // Load full data blocks into core. | ||
| 1639 | let num_full_blocks = aad_len_remaining / C::BLOCK_SIZE; | ||
| 1640 | let start_index = len_to_copy; | ||
| 1641 | let end_index = start_index + (C::BLOCK_SIZE * num_full_blocks); | ||
| 1642 | Self::write_bytes( | ||
| 1643 | self.indma.as_mut().unwrap(), | ||
| 1644 | C::BLOCK_SIZE, | ||
| 1645 | &aad[start_index..end_index], | ||
| 1646 | ) | ||
| 1647 | .await; | ||
| 1648 | |||
| 1649 | if last_aad_block { | ||
| 1650 | if leftovers > 0 { | ||
| 1651 | Self::write_bytes(self.indma.as_mut().unwrap(), C::BLOCK_SIZE, &ctx.aad_buffer).await; | ||
| 1652 | assert_eq!(T::regs().sr().read().ifem(), true); | ||
| 1653 | } | ||
| 1654 | // Switch to payload phase. | ||
| 1655 | ctx.aad_complete = true; | ||
| 1656 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1657 | T::regs().cr().modify(|w| w.set_gcm_ccmph(2)); | ||
| 1658 | T::regs().cr().modify(|w| w.fflush()); | ||
| 1659 | } | ||
| 1660 | |||
| 1661 | self.store_context(ctx); | ||
| 1662 | } | ||
| 1663 | |||
| 1664 | /// Performs encryption/decryption on the provided context. | ||
| 1665 | /// The context determines algorithm, mode, and state of the crypto accelerator. | ||
| 1666 | /// When the last piece of data is supplied, `last_block` should be `true`. | ||
| 1667 | /// This function panics under various mismatches of parameters. | ||
| 1668 | /// Output buffer must be at least as long as the input buffer. | ||
| 1669 | /// Data must be a multiple of block size (128-bits for AES, 64-bits for DES) for CBC and ECB modes. | ||
| 1670 | /// Padding or ciphertext stealing must be managed by the application for these modes. | ||
| 1671 | /// Data must also be a multiple of block size unless `last_block` is `true`. | ||
| 1672 | pub async fn payload<'c, C: Cipher<'c> + CipherSized + IVSized>( | ||
| 1673 | &mut self, | ||
| 1674 | ctx: &mut Context<'c, C>, | ||
| 1675 | input: &[u8], | ||
| 1676 | output: &mut [u8], | ||
| 1677 | last_block: bool, | ||
| 1678 | ) { | ||
| 1679 | self.load_context(ctx); | ||
| 1680 | |||
| 1681 | let last_block_remainder = input.len() % C::BLOCK_SIZE; | ||
| 1682 | |||
| 1683 | // Perform checks for correctness. | ||
| 1684 | if !ctx.aad_complete && ctx.header_len > 0 { | ||
| 1685 | panic!("Additional associated data must be processed first!"); | ||
| 1686 | } else if !ctx.aad_complete { | ||
| 1687 | #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] | ||
| 1688 | { | ||
| 1689 | ctx.aad_complete = true; | ||
| 1690 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1691 | T::regs().cr().modify(|w| w.set_gcm_ccmph(2)); | ||
| 1692 | T::regs().cr().modify(|w| w.fflush()); | ||
| 1693 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 1694 | } | ||
| 1695 | } | ||
| 1696 | if ctx.last_block_processed { | ||
| 1697 | panic!("The last block has already been processed!"); | ||
| 1698 | } | ||
| 1699 | if input.len() > output.len() { | ||
| 1700 | panic!("Output buffer length must match input length."); | ||
| 1701 | } | ||
| 1702 | if !last_block { | ||
| 1703 | if last_block_remainder != 0 { | ||
| 1704 | panic!("Input length must be a multiple of {} bytes.", C::BLOCK_SIZE); | ||
| 1705 | } | ||
| 1706 | } | ||
| 1707 | if C::REQUIRES_PADDING { | ||
| 1708 | if last_block_remainder != 0 { | ||
| 1709 | panic!("Input must be a multiple of {} bytes in ECB and CBC modes. Consider padding or ciphertext stealing.", C::BLOCK_SIZE); | ||
| 1710 | } | ||
| 1711 | } | ||
| 1712 | if last_block { | ||
| 1713 | ctx.last_block_processed = true; | ||
| 1714 | } | ||
| 1715 | |||
| 1716 | // Load data into core, block by block. | ||
| 1717 | let num_full_blocks = input.len() / C::BLOCK_SIZE; | ||
| 1718 | for block in 0..num_full_blocks { | ||
| 1719 | let index = block * C::BLOCK_SIZE; | ||
| 1720 | // Read block out | ||
| 1721 | let read = Self::read_bytes( | ||
| 1722 | self.outdma.as_mut().unwrap(), | ||
| 1723 | C::BLOCK_SIZE, | ||
| 1724 | &mut output[index..index + C::BLOCK_SIZE], | ||
| 1725 | ); | ||
| 1726 | // Write block in | ||
| 1727 | let write = Self::write_bytes( | ||
| 1728 | self.indma.as_mut().unwrap(), | ||
| 1729 | C::BLOCK_SIZE, | ||
| 1730 | &input[index..index + C::BLOCK_SIZE], | ||
| 1731 | ); | ||
| 1732 | embassy_futures::join::join(read, write).await; | ||
| 1733 | } | ||
| 1734 | |||
| 1735 | // Handle the final block, which is incomplete. | ||
| 1736 | if last_block_remainder > 0 { | ||
| 1737 | let padding_len = C::BLOCK_SIZE - last_block_remainder; | ||
| 1738 | let temp1 = ctx.cipher.pre_final(T::regs(), ctx.dir, padding_len); | ||
| 1739 | |||
| 1740 | let mut intermediate_data: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; | ||
| 1741 | let mut last_block: [u8; AES_BLOCK_SIZE] = [0; AES_BLOCK_SIZE]; | ||
| 1742 | last_block[..last_block_remainder].copy_from_slice(&input[input.len() - last_block_remainder..input.len()]); | ||
| 1743 | let read = Self::read_bytes(self.outdma.as_mut().unwrap(), C::BLOCK_SIZE, &mut intermediate_data); | ||
| 1744 | let write = Self::write_bytes(self.indma.as_mut().unwrap(), C::BLOCK_SIZE, &last_block); | ||
| 1745 | embassy_futures::join::join(read, write).await; | ||
| 1746 | |||
| 1747 | // Handle the last block depending on mode. | ||
| 1748 | let output_len = output.len(); | ||
| 1749 | output[output_len - last_block_remainder..output_len] | ||
| 1750 | .copy_from_slice(&intermediate_data[0..last_block_remainder]); | ||
| 1751 | |||
| 1752 | let mut mask: [u8; 16] = [0; 16]; | ||
| 1753 | mask[..last_block_remainder].fill(0xFF); | ||
| 1754 | ctx.cipher | ||
| 1755 | .post_final(T::regs(), self, ctx.dir, &mut intermediate_data, temp1, mask) | ||
| 1756 | .await; | ||
| 1757 | } | ||
| 1758 | |||
| 1759 | ctx.payload_len += input.len() as u64; | ||
| 1760 | |||
| 1761 | self.store_context(ctx); | ||
| 1762 | } | ||
| 1763 | |||
| 1764 | #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] | ||
| 1765 | // Generates an authentication tag for authenticated ciphers including GCM, CCM, and GMAC. | ||
| 1766 | /// Called after the all data has been encrypted/decrypted by `payload`. | ||
| 1767 | pub async fn finish< | ||
| 1768 | 'c, | ||
| 1769 | const TAG_SIZE: usize, | ||
| 1770 | C: Cipher<'c> + CipherSized + IVSized + CipherAuthenticated<TAG_SIZE>, | ||
| 1771 | >( | ||
| 1772 | &mut self, | ||
| 1773 | mut ctx: Context<'c, C>, | ||
| 1774 | ) -> [u8; TAG_SIZE] { | ||
| 1775 | self.load_context(&mut ctx); | ||
| 1776 | |||
| 1777 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1778 | T::regs().cr().modify(|w| w.set_gcm_ccmph(3)); | ||
| 1779 | T::regs().cr().modify(|w| w.set_crypen(true)); | ||
| 1780 | |||
| 1781 | let headerlen1: u32 = ((ctx.header_len * 8) >> 32) as u32; | ||
| 1782 | let headerlen2: u32 = (ctx.header_len * 8) as u32; | ||
| 1783 | let payloadlen1: u32 = ((ctx.payload_len * 8) >> 32) as u32; | ||
| 1784 | let payloadlen2: u32 = (ctx.payload_len * 8) as u32; | ||
| 1785 | |||
| 1786 | #[cfg(cryp_v2)] | ||
| 1787 | let footer: [u32; 4] = [ | ||
| 1788 | headerlen1.swap_bytes(), | ||
| 1789 | headerlen2.swap_bytes(), | ||
| 1790 | payloadlen1.swap_bytes(), | ||
| 1791 | payloadlen2.swap_bytes(), | ||
| 1792 | ]; | ||
| 1793 | #[cfg(any(cryp_v3, cryp_v4))] | ||
| 1794 | let footer: [u32; 4] = [headerlen1, headerlen2, payloadlen1, payloadlen2]; | ||
| 1795 | |||
| 1796 | let write = Self::write_words(self.indma.as_mut().unwrap(), C::BLOCK_SIZE, &footer); | ||
| 1797 | |||
| 1798 | let mut full_tag: [u8; 16] = [0; 16]; | ||
| 1799 | let read = Self::read_bytes(self.outdma.as_mut().unwrap(), C::BLOCK_SIZE, &mut full_tag); | ||
| 1800 | |||
| 1801 | embassy_futures::join::join(read, write).await; | ||
| 1802 | |||
| 1803 | let mut tag: [u8; TAG_SIZE] = [0; TAG_SIZE]; | ||
| 1804 | tag.copy_from_slice(&full_tag[0..TAG_SIZE]); | ||
| 1805 | |||
| 1806 | T::regs().cr().modify(|w| w.set_crypen(false)); | ||
| 1807 | |||
| 1808 | tag | ||
| 1809 | } | ||
| 1810 | |||
| 1811 | async fn write_bytes(dma: &mut ChannelAndRequest<'d>, block_size: usize, blocks: &[u8]) { | ||
| 1781 | if blocks.len() == 0 { | 1812 | if blocks.len() == 0 { |
| 1782 | return; | 1813 | return; |
| 1783 | } | 1814 | } |
| 1784 | // Ensure input is a multiple of block size. | 1815 | // Ensure input is a multiple of block size. |
| 1785 | assert_eq!(blocks.len() % block_size, 0); | 1816 | assert_eq!(blocks.len() % block_size, 0); |
| 1786 | // Configure DMA to transfer input to crypto core. | 1817 | // Configure DMA to transfer input to crypto core. |
| 1787 | let dma_request = dma.request(); | ||
| 1788 | let dst_ptr: *mut u32 = T::regs().din().as_ptr(); | 1818 | let dst_ptr: *mut u32 = T::regs().din().as_ptr(); |
| 1789 | let num_words = blocks.len() / 4; | 1819 | let num_words = blocks.len() / 4; |
| 1790 | let src_ptr: *const [u8] = ptr::slice_from_raw_parts(blocks.as_ptr().cast(), num_words); | 1820 | let src_ptr: *const [u8] = ptr::slice_from_raw_parts(blocks.as_ptr().cast(), num_words); |
| @@ -1793,38 +1823,20 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> { | |||
| 1793 | priority: crate::dma::Priority::High, | 1823 | priority: crate::dma::Priority::High, |
| 1794 | ..Default::default() | 1824 | ..Default::default() |
| 1795 | }; | 1825 | }; |
| 1796 | let dma_transfer = unsafe { Transfer::new_write_raw(dma, dma_request, src_ptr, dst_ptr, options) }; | 1826 | let dma_transfer = unsafe { dma.write_raw(src_ptr, dst_ptr, options) }; |
| 1797 | T::regs().dmacr().modify(|w| w.set_dien(true)); | 1827 | T::regs().dmacr().modify(|w| w.set_dien(true)); |
| 1798 | // Wait for the transfer to complete. | 1828 | // Wait for the transfer to complete. |
| 1799 | dma_transfer.await; | 1829 | dma_transfer.await; |
| 1800 | } | 1830 | } |
| 1801 | 1831 | ||
| 1802 | #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] | 1832 | #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] |
| 1803 | fn write_words_blocking(&self, block_size: usize, blocks: &[u32]) { | 1833 | async fn write_words(dma: &mut ChannelAndRequest<'d>, block_size: usize, blocks: &[u32]) { |
| 1804 | assert_eq!((blocks.len() * 4) % block_size, 0); | ||
| 1805 | let mut byte_counter: usize = 0; | ||
| 1806 | for word in blocks { | ||
| 1807 | T::regs().din().write_value(*word); | ||
| 1808 | byte_counter += 4; | ||
| 1809 | if byte_counter % block_size == 0 { | ||
| 1810 | // Block until input FIFO is empty. | ||
| 1811 | while !T::regs().sr().read().ifem() {} | ||
| 1812 | } | ||
| 1813 | } | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | #[cfg(any(cryp_v2, cryp_v3, cryp_v4))] | ||
| 1817 | async fn write_words(dma: &mut PeripheralRef<'_, DmaIn>, block_size: usize, blocks: &[u32]) | ||
| 1818 | where | ||
| 1819 | DmaIn: crate::cryp::DmaIn<T>, | ||
| 1820 | { | ||
| 1821 | if blocks.len() == 0 { | 1834 | if blocks.len() == 0 { |
| 1822 | return; | 1835 | return; |
| 1823 | } | 1836 | } |
| 1824 | // Ensure input is a multiple of block size. | 1837 | // Ensure input is a multiple of block size. |
| 1825 | assert_eq!((blocks.len() * 4) % block_size, 0); | 1838 | assert_eq!((blocks.len() * 4) % block_size, 0); |
| 1826 | // Configure DMA to transfer input to crypto core. | 1839 | // Configure DMA to transfer input to crypto core. |
| 1827 | let dma_request = dma.request(); | ||
| 1828 | let dst_ptr: *mut u32 = T::regs().din().as_ptr(); | 1840 | let dst_ptr: *mut u32 = T::regs().din().as_ptr(); |
| 1829 | let num_words = blocks.len(); | 1841 | let num_words = blocks.len(); |
| 1830 | let src_ptr: *const [u32] = ptr::slice_from_raw_parts(blocks.as_ptr().cast(), num_words); | 1842 | let src_ptr: *const [u32] = ptr::slice_from_raw_parts(blocks.as_ptr().cast(), num_words); |
| @@ -1833,38 +1845,19 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> { | |||
| 1833 | priority: crate::dma::Priority::High, | 1845 | priority: crate::dma::Priority::High, |
| 1834 | ..Default::default() | 1846 | ..Default::default() |
| 1835 | }; | 1847 | }; |
| 1836 | let dma_transfer = unsafe { Transfer::new_write_raw(dma, dma_request, src_ptr, dst_ptr, options) }; | 1848 | let dma_transfer = unsafe { dma.write_raw(src_ptr, dst_ptr, options) }; |
| 1837 | T::regs().dmacr().modify(|w| w.set_dien(true)); | 1849 | T::regs().dmacr().modify(|w| w.set_dien(true)); |
| 1838 | // Wait for the transfer to complete. | 1850 | // Wait for the transfer to complete. |
| 1839 | dma_transfer.await; | 1851 | dma_transfer.await; |
| 1840 | } | 1852 | } |
| 1841 | 1853 | ||
| 1842 | fn read_bytes_blocking(&self, block_size: usize, blocks: &mut [u8]) { | 1854 | async fn read_bytes(dma: &mut ChannelAndRequest<'d>, block_size: usize, blocks: &mut [u8]) { |
| 1843 | // Block until there is output to read. | ||
| 1844 | while !T::regs().sr().read().ofne() {} | ||
| 1845 | // Ensure input is a multiple of block size. | ||
| 1846 | assert_eq!(blocks.len() % block_size, 0); | ||
| 1847 | // Read block out | ||
| 1848 | let mut index = 0; | ||
| 1849 | let end_index = blocks.len(); | ||
| 1850 | while index < end_index { | ||
| 1851 | let out_word: u32 = T::regs().dout().read(); | ||
| 1852 | blocks[index..index + 4].copy_from_slice(u32::to_ne_bytes(out_word).as_slice()); | ||
| 1853 | index += 4; | ||
| 1854 | } | ||
| 1855 | } | ||
| 1856 | |||
| 1857 | async fn read_bytes(dma: &mut PeripheralRef<'_, DmaOut>, block_size: usize, blocks: &mut [u8]) | ||
| 1858 | where | ||
| 1859 | DmaOut: crate::cryp::DmaOut<T>, | ||
| 1860 | { | ||
| 1861 | if blocks.len() == 0 { | 1855 | if blocks.len() == 0 { |
| 1862 | return; | 1856 | return; |
| 1863 | } | 1857 | } |
| 1864 | // Ensure input is a multiple of block size. | 1858 | // Ensure input is a multiple of block size. |
| 1865 | assert_eq!(blocks.len() % block_size, 0); | 1859 | assert_eq!(blocks.len() % block_size, 0); |
| 1866 | // Configure DMA to get output from crypto core. | 1860 | // Configure DMA to get output from crypto core. |
| 1867 | let dma_request = dma.request(); | ||
| 1868 | let src_ptr = T::regs().dout().as_ptr(); | 1861 | let src_ptr = T::regs().dout().as_ptr(); |
| 1869 | let num_words = blocks.len() / 4; | 1862 | let num_words = blocks.len() / 4; |
| 1870 | let dst_ptr = ptr::slice_from_raw_parts_mut(blocks.as_mut_ptr().cast(), num_words); | 1863 | let dst_ptr = ptr::slice_from_raw_parts_mut(blocks.as_mut_ptr().cast(), num_words); |
| @@ -1873,7 +1866,7 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> { | |||
| 1873 | priority: crate::dma::Priority::VeryHigh, | 1866 | priority: crate::dma::Priority::VeryHigh, |
| 1874 | ..Default::default() | 1867 | ..Default::default() |
| 1875 | }; | 1868 | }; |
| 1876 | let dma_transfer = unsafe { Transfer::new_read_raw(dma, dma_request, src_ptr, dst_ptr, options) }; | 1869 | let dma_transfer = unsafe { dma.read_raw(src_ptr, dst_ptr, options) }; |
| 1877 | T::regs().dmacr().modify(|w| w.set_doen(true)); | 1870 | T::regs().dmacr().modify(|w| w.set_doen(true)); |
| 1878 | // Wait for the transfer to complete. | 1871 | // Wait for the transfer to complete. |
| 1879 | dma_transfer.await; | 1872 | dma_transfer.await; |
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index 8bba5ded0..7a63dc5fc 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs | |||
| @@ -3,9 +3,10 @@ | |||
| 3 | 3 | ||
| 4 | use core::marker::PhantomData; | 4 | use core::marker::PhantomData; |
| 5 | 5 | ||
| 6 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 6 | use embassy_hal_internal::into_ref; |
| 7 | 7 | ||
| 8 | use crate::dma::NoDma; | 8 | use crate::dma::ChannelAndRequest; |
| 9 | use crate::mode::{Async, Blocking, Mode as PeriMode}; | ||
| 9 | #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] | 10 | #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] |
| 10 | use crate::pac::dac; | 11 | use crate::pac::dac; |
| 11 | use crate::rcc::{self, RccPeripheral}; | 12 | use crate::rcc::{self, RccPeripheral}; |
| @@ -100,24 +101,20 @@ pub enum ValueArray<'a> { | |||
| 100 | /// | 101 | /// |
| 101 | /// If you want to use both channels, either together or independently, | 102 | /// If you want to use both channels, either together or independently, |
| 102 | /// create a [`Dac`] first and use it to access each channel. | 103 | /// create a [`Dac`] first and use it to access each channel. |
| 103 | pub struct DacChannel<'d, T: Instance, const N: u8, DMA = NoDma> { | 104 | pub struct DacChannel<'d, T: Instance, C: Channel, M: PeriMode> { |
| 104 | phantom: PhantomData<&'d mut T>, | 105 | phantom: PhantomData<&'d mut (T, C, M)>, |
| 105 | #[allow(unused)] | 106 | #[allow(unused)] |
| 106 | dma: PeripheralRef<'d, DMA>, | 107 | dma: Option<ChannelAndRequest<'d>>, |
| 107 | } | 108 | } |
| 108 | 109 | ||
| 109 | /// DAC channel 1 type alias. | 110 | /// DAC channel 1 type alias. |
| 110 | pub type DacCh1<'d, T, DMA = NoDma> = DacChannel<'d, T, 1, DMA>; | 111 | pub type DacCh1<'d, T, M> = DacChannel<'d, T, Ch1, M>; |
| 111 | /// DAC channel 2 type alias. | 112 | /// DAC channel 2 type alias. |
| 112 | pub type DacCh2<'d, T, DMA = NoDma> = DacChannel<'d, T, 2, DMA>; | 113 | pub type DacCh2<'d, T, M> = DacChannel<'d, T, Ch2, M>; |
| 113 | |||
| 114 | impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | ||
| 115 | const IDX: usize = (N - 1) as usize; | ||
| 116 | 114 | ||
| 115 | impl<'d, T: Instance, C: Channel> DacChannel<'d, T, C, Async> { | ||
| 117 | /// Create a new `DacChannel` instance, consuming the underlying DAC peripheral. | 116 | /// Create a new `DacChannel` instance, consuming the underlying DAC peripheral. |
| 118 | /// | 117 | /// |
| 119 | /// If you're not using DMA, pass [`dma::NoDma`] for the `dma` argument. | ||
| 120 | /// | ||
| 121 | /// The channel is enabled on creation and begin to drive the output pin. | 118 | /// The channel is enabled on creation and begin to drive the output pin. |
| 122 | /// Note that some methods, such as `set_trigger()` and `set_mode()`, will | 119 | /// Note that some methods, such as `set_trigger()` and `set_mode()`, will |
| 123 | /// disable the channel; you must re-enable it with `enable()`. | 120 | /// disable the channel; you must re-enable it with `enable()`. |
| @@ -125,21 +122,18 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||
| 125 | /// By default, triggering is disabled, but it can be enabled using | 122 | /// By default, triggering is disabled, but it can be enabled using |
| 126 | /// [`DacChannel::set_trigger()`]. | 123 | /// [`DacChannel::set_trigger()`]. |
| 127 | pub fn new( | 124 | pub fn new( |
| 128 | _peri: impl Peripheral<P = T> + 'd, | 125 | peri: impl Peripheral<P = T> + 'd, |
| 129 | dma: impl Peripheral<P = DMA> + 'd, | 126 | dma: impl Peripheral<P = impl Dma<T, C>> + 'd, |
| 130 | pin: impl Peripheral<P = impl DacPin<T, N> + crate::gpio::Pin> + 'd, | 127 | pin: impl Peripheral<P = impl DacPin<T, C>> + 'd, |
| 131 | ) -> Self { | 128 | ) -> Self { |
| 132 | into_ref!(dma, pin); | 129 | into_ref!(dma, pin); |
| 133 | pin.set_as_analog(); | 130 | pin.set_as_analog(); |
| 134 | rcc::enable_and_reset::<T>(); | 131 | Self::new_inner( |
| 135 | let mut dac = Self { | 132 | peri, |
| 136 | phantom: PhantomData, | 133 | new_dma!(dma), |
| 137 | dma, | 134 | #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] |
| 138 | }; | 135 | Mode::NormalExternalBuffered, |
| 139 | #[cfg(any(dac_v5, dac_v6, dac_v7))] | 136 | ) |
| 140 | dac.set_hfsel(); | ||
| 141 | dac.enable(); | ||
| 142 | dac | ||
| 143 | } | 137 | } |
| 144 | 138 | ||
| 145 | /// Create a new `DacChannel` instance where the external output pin is not used, | 139 | /// Create a new `DacChannel` instance where the external output pin is not used, |
| @@ -150,13 +144,99 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||
| 150 | /// Note that some methods, such as `set_trigger()` and `set_mode()`, will disable the | 144 | /// Note that some methods, such as `set_trigger()` and `set_mode()`, will disable the |
| 151 | /// channel; you must re-enable it with `enable()`. | 145 | /// channel; you must re-enable it with `enable()`. |
| 152 | /// | 146 | /// |
| 153 | /// If you're not using DMA, pass [`dma::NoDma`] for the `dma` argument. | ||
| 154 | /// | ||
| 155 | /// By default, triggering is disabled, but it can be enabled using | 147 | /// By default, triggering is disabled, but it can be enabled using |
| 156 | /// [`DacChannel::set_trigger()`]. | 148 | /// [`DacChannel::set_trigger()`]. |
| 157 | #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))] | 149 | #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))] |
| 158 | pub fn new_internal(_peri: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = DMA> + 'd) -> Self { | 150 | pub fn new_internal(peri: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = impl Dma<T, C>> + 'd) -> Self { |
| 159 | into_ref!(dma); | 151 | into_ref!(dma); |
| 152 | Self::new_inner(peri, new_dma!(dma), Mode::NormalInternalUnbuffered) | ||
| 153 | } | ||
| 154 | |||
| 155 | /// Write `data` to this channel via DMA. | ||
| 156 | /// | ||
| 157 | /// To prevent delays or glitches when outputing a periodic waveform, the `circular` | ||
| 158 | /// flag can be set. This configures a circular DMA transfer that continually outputs | ||
| 159 | /// `data`. Note that for performance reasons in circular mode the transfer-complete | ||
| 160 | /// interrupt is disabled. | ||
| 161 | #[cfg(not(gpdma))] | ||
| 162 | pub async fn write(&mut self, data: ValueArray<'_>, circular: bool) { | ||
| 163 | // Enable DAC and DMA | ||
| 164 | T::regs().cr().modify(|w| { | ||
| 165 | w.set_en(C::IDX, true); | ||
| 166 | w.set_dmaen(C::IDX, true); | ||
| 167 | }); | ||
| 168 | |||
| 169 | let dma = self.dma.as_mut().unwrap(); | ||
| 170 | |||
| 171 | let tx_options = crate::dma::TransferOptions { | ||
| 172 | circular, | ||
| 173 | half_transfer_ir: false, | ||
| 174 | complete_transfer_ir: !circular, | ||
| 175 | ..Default::default() | ||
| 176 | }; | ||
| 177 | |||
| 178 | // Initiate the correct type of DMA transfer depending on what data is passed | ||
| 179 | let tx_f = match data { | ||
| 180 | ValueArray::Bit8(buf) => unsafe { dma.write(buf, T::regs().dhr8r(C::IDX).as_ptr() as *mut u8, tx_options) }, | ||
| 181 | ValueArray::Bit12Left(buf) => unsafe { | ||
| 182 | dma.write(buf, T::regs().dhr12l(C::IDX).as_ptr() as *mut u16, tx_options) | ||
| 183 | }, | ||
| 184 | ValueArray::Bit12Right(buf) => unsafe { | ||
| 185 | dma.write(buf, T::regs().dhr12r(C::IDX).as_ptr() as *mut u16, tx_options) | ||
| 186 | }, | ||
| 187 | }; | ||
| 188 | |||
| 189 | tx_f.await; | ||
| 190 | |||
| 191 | T::regs().cr().modify(|w| { | ||
| 192 | w.set_en(C::IDX, false); | ||
| 193 | w.set_dmaen(C::IDX, false); | ||
| 194 | }); | ||
| 195 | } | ||
| 196 | } | ||
| 197 | |||
| 198 | impl<'d, T: Instance, C: Channel> DacChannel<'d, T, C, Blocking> { | ||
| 199 | /// Create a new `DacChannel` instance, consuming the underlying DAC peripheral. | ||
| 200 | /// | ||
| 201 | /// The channel is enabled on creation and begin to drive the output pin. | ||
| 202 | /// Note that some methods, such as `set_trigger()` and `set_mode()`, will | ||
| 203 | /// disable the channel; you must re-enable it with `enable()`. | ||
| 204 | /// | ||
| 205 | /// By default, triggering is disabled, but it can be enabled using | ||
| 206 | /// [`DacChannel::set_trigger()`]. | ||
| 207 | pub fn new_blocking(peri: impl Peripheral<P = T> + 'd, pin: impl Peripheral<P = impl DacPin<T, C>> + 'd) -> Self { | ||
| 208 | into_ref!(pin); | ||
| 209 | pin.set_as_analog(); | ||
| 210 | Self::new_inner( | ||
| 211 | peri, | ||
| 212 | None, | ||
| 213 | #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] | ||
| 214 | Mode::NormalExternalBuffered, | ||
| 215 | ) | ||
| 216 | } | ||
| 217 | |||
| 218 | /// Create a new `DacChannel` instance where the external output pin is not used, | ||
| 219 | /// so the DAC can only be used to generate internal signals. | ||
| 220 | /// The GPIO pin is therefore available to be used for other functions. | ||
| 221 | /// | ||
| 222 | /// The channel is set to [`Mode::NormalInternalUnbuffered`] and enabled on creation. | ||
| 223 | /// Note that some methods, such as `set_trigger()` and `set_mode()`, will disable the | ||
| 224 | /// channel; you must re-enable it with `enable()`. | ||
| 225 | /// | ||
| 226 | /// By default, triggering is disabled, but it can be enabled using | ||
| 227 | /// [`DacChannel::set_trigger()`]. | ||
| 228 | #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))] | ||
| 229 | pub fn new_internal_blocking(peri: impl Peripheral<P = T> + 'd) -> Self { | ||
| 230 | Self::new_inner(peri, None, Mode::NormalInternalUnbuffered) | ||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | impl<'d, T: Instance, C: Channel, M: PeriMode> DacChannel<'d, T, C, M> { | ||
| 235 | fn new_inner( | ||
| 236 | _peri: impl Peripheral<P = T> + 'd, | ||
| 237 | dma: Option<ChannelAndRequest<'d>>, | ||
| 238 | #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] mode: Mode, | ||
| 239 | ) -> Self { | ||
| 160 | rcc::enable_and_reset::<T>(); | 240 | rcc::enable_and_reset::<T>(); |
| 161 | let mut dac = Self { | 241 | let mut dac = Self { |
| 162 | phantom: PhantomData, | 242 | phantom: PhantomData, |
| @@ -164,7 +244,8 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||
| 164 | }; | 244 | }; |
| 165 | #[cfg(any(dac_v5, dac_v6, dac_v7))] | 245 | #[cfg(any(dac_v5, dac_v6, dac_v7))] |
| 166 | dac.set_hfsel(); | 246 | dac.set_hfsel(); |
| 167 | dac.set_mode(Mode::NormalInternalUnbuffered); | 247 | #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] |
| 248 | dac.set_mode(mode); | ||
| 168 | dac.enable(); | 249 | dac.enable(); |
| 169 | dac | 250 | dac |
| 170 | } | 251 | } |
| @@ -173,7 +254,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||
| 173 | pub fn set_enable(&mut self, on: bool) { | 254 | pub fn set_enable(&mut self, on: bool) { |
| 174 | critical_section::with(|_| { | 255 | critical_section::with(|_| { |
| 175 | T::regs().cr().modify(|reg| { | 256 | T::regs().cr().modify(|reg| { |
| 176 | reg.set_en(Self::IDX, on); | 257 | reg.set_en(C::IDX, on); |
| 177 | }); | 258 | }); |
| 178 | }); | 259 | }); |
| 179 | } | 260 | } |
| @@ -194,8 +275,8 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||
| 194 | pub fn set_trigger(&mut self, source: TriggerSel) { | 275 | pub fn set_trigger(&mut self, source: TriggerSel) { |
| 195 | critical_section::with(|_| { | 276 | critical_section::with(|_| { |
| 196 | T::regs().cr().modify(|reg| { | 277 | T::regs().cr().modify(|reg| { |
| 197 | reg.set_en(Self::IDX, false); | 278 | reg.set_en(C::IDX, false); |
| 198 | reg.set_tsel(Self::IDX, source as u8); | 279 | reg.set_tsel(C::IDX, source as u8); |
| 199 | }); | 280 | }); |
| 200 | }); | 281 | }); |
| 201 | } | 282 | } |
| @@ -204,7 +285,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||
| 204 | pub fn set_triggering(&mut self, on: bool) { | 285 | pub fn set_triggering(&mut self, on: bool) { |
| 205 | critical_section::with(|_| { | 286 | critical_section::with(|_| { |
| 206 | T::regs().cr().modify(|reg| { | 287 | T::regs().cr().modify(|reg| { |
| 207 | reg.set_ten(Self::IDX, on); | 288 | reg.set_ten(C::IDX, on); |
| 208 | }); | 289 | }); |
| 209 | }); | 290 | }); |
| 210 | } | 291 | } |
| @@ -212,7 +293,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||
| 212 | /// Software trigger this channel. | 293 | /// Software trigger this channel. |
| 213 | pub fn trigger(&mut self) { | 294 | pub fn trigger(&mut self) { |
| 214 | T::regs().swtrigr().write(|reg| { | 295 | T::regs().swtrigr().write(|reg| { |
| 215 | reg.set_swtrig(Self::IDX, true); | 296 | reg.set_swtrig(C::IDX, true); |
| 216 | }); | 297 | }); |
| 217 | } | 298 | } |
| 218 | 299 | ||
| @@ -223,10 +304,10 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||
| 223 | pub fn set_mode(&mut self, mode: Mode) { | 304 | pub fn set_mode(&mut self, mode: Mode) { |
| 224 | critical_section::with(|_| { | 305 | critical_section::with(|_| { |
| 225 | T::regs().cr().modify(|reg| { | 306 | T::regs().cr().modify(|reg| { |
| 226 | reg.set_en(Self::IDX, false); | 307 | reg.set_en(C::IDX, false); |
| 227 | }); | 308 | }); |
| 228 | T::regs().mcr().modify(|reg| { | 309 | T::regs().mcr().modify(|reg| { |
| 229 | reg.set_mode(Self::IDX, mode.mode()); | 310 | reg.set_mode(C::IDX, mode.mode()); |
| 230 | }); | 311 | }); |
| 231 | }); | 312 | }); |
| 232 | } | 313 | } |
| @@ -237,15 +318,15 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||
| 237 | /// it will be output after the next trigger. | 318 | /// it will be output after the next trigger. |
| 238 | pub fn set(&mut self, value: Value) { | 319 | pub fn set(&mut self, value: Value) { |
| 239 | match value { | 320 | match value { |
| 240 | Value::Bit8(v) => T::regs().dhr8r(Self::IDX).write(|reg| reg.set_dhr(v)), | 321 | Value::Bit8(v) => T::regs().dhr8r(C::IDX).write(|reg| reg.set_dhr(v)), |
| 241 | Value::Bit12Left(v) => T::regs().dhr12l(Self::IDX).write(|reg| reg.set_dhr(v)), | 322 | Value::Bit12Left(v) => T::regs().dhr12l(C::IDX).write(|reg| reg.set_dhr(v)), |
| 242 | Value::Bit12Right(v) => T::regs().dhr12r(Self::IDX).write(|reg| reg.set_dhr(v)), | 323 | Value::Bit12Right(v) => T::regs().dhr12r(C::IDX).write(|reg| reg.set_dhr(v)), |
| 243 | } | 324 | } |
| 244 | } | 325 | } |
| 245 | 326 | ||
| 246 | /// Read the current output value of the DAC. | 327 | /// Read the current output value of the DAC. |
| 247 | pub fn read(&self) -> u16 { | 328 | pub fn read(&self) -> u16 { |
| 248 | T::regs().dor(Self::IDX).read().dor() | 329 | T::regs().dor(C::IDX).read().dor() |
| 249 | } | 330 | } |
| 250 | 331 | ||
| 251 | /// Set HFSEL as appropriate for the current peripheral clock frequency. | 332 | /// Set HFSEL as appropriate for the current peripheral clock frequency. |
| @@ -279,82 +360,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { | |||
| 279 | } | 360 | } |
| 280 | } | 361 | } |
| 281 | 362 | ||
| 282 | macro_rules! impl_dma_methods { | 363 | impl<'d, T: Instance, C: Channel, M: PeriMode> Drop for DacChannel<'d, T, C, M> { |
| 283 | ($n:literal, $trait:ident) => { | ||
| 284 | impl<'d, T: Instance, DMA> DacChannel<'d, T, $n, DMA> | ||
| 285 | where | ||
| 286 | DMA: $trait<T>, | ||
| 287 | { | ||
| 288 | /// Write `data` to this channel via DMA. | ||
| 289 | /// | ||
| 290 | /// To prevent delays or glitches when outputing a periodic waveform, the `circular` | ||
| 291 | /// flag can be set. This configures a circular DMA transfer that continually outputs | ||
| 292 | /// `data`. Note that for performance reasons in circular mode the transfer-complete | ||
| 293 | /// interrupt is disabled. | ||
| 294 | #[cfg(not(gpdma))] | ||
| 295 | pub async fn write(&mut self, data: ValueArray<'_>, circular: bool) { | ||
| 296 | // Enable DAC and DMA | ||
| 297 | T::regs().cr().modify(|w| { | ||
| 298 | w.set_en(Self::IDX, true); | ||
| 299 | w.set_dmaen(Self::IDX, true); | ||
| 300 | }); | ||
| 301 | |||
| 302 | let tx_request = self.dma.request(); | ||
| 303 | let dma_channel = &mut self.dma; | ||
| 304 | |||
| 305 | let tx_options = crate::dma::TransferOptions { | ||
| 306 | circular, | ||
| 307 | half_transfer_ir: false, | ||
| 308 | complete_transfer_ir: !circular, | ||
| 309 | ..Default::default() | ||
| 310 | }; | ||
| 311 | |||
| 312 | // Initiate the correct type of DMA transfer depending on what data is passed | ||
| 313 | let tx_f = match data { | ||
| 314 | ValueArray::Bit8(buf) => unsafe { | ||
| 315 | crate::dma::Transfer::new_write( | ||
| 316 | dma_channel, | ||
| 317 | tx_request, | ||
| 318 | buf, | ||
| 319 | T::regs().dhr8r(Self::IDX).as_ptr() as *mut u8, | ||
| 320 | tx_options, | ||
| 321 | ) | ||
| 322 | }, | ||
| 323 | ValueArray::Bit12Left(buf) => unsafe { | ||
| 324 | crate::dma::Transfer::new_write( | ||
| 325 | dma_channel, | ||
| 326 | tx_request, | ||
| 327 | buf, | ||
| 328 | T::regs().dhr12l(Self::IDX).as_ptr() as *mut u16, | ||
| 329 | tx_options, | ||
| 330 | ) | ||
| 331 | }, | ||
| 332 | ValueArray::Bit12Right(buf) => unsafe { | ||
| 333 | crate::dma::Transfer::new_write( | ||
| 334 | dma_channel, | ||
| 335 | tx_request, | ||
| 336 | buf, | ||
| 337 | T::regs().dhr12r(Self::IDX).as_ptr() as *mut u16, | ||
| 338 | tx_options, | ||
| 339 | ) | ||
| 340 | }, | ||
| 341 | }; | ||
| 342 | |||
| 343 | tx_f.await; | ||
| 344 | |||
| 345 | T::regs().cr().modify(|w| { | ||
| 346 | w.set_en(Self::IDX, false); | ||
| 347 | w.set_dmaen(Self::IDX, false); | ||
| 348 | }); | ||
| 349 | } | ||
| 350 | } | ||
| 351 | }; | ||
| 352 | } | ||
| 353 | |||
| 354 | impl_dma_methods!(1, DacDma1); | ||
| 355 | impl_dma_methods!(2, DacDma2); | ||
| 356 | |||
| 357 | impl<'d, T: Instance, const N: u8, DMA> Drop for DacChannel<'d, T, N, DMA> { | ||
| 358 | fn drop(&mut self) { | 364 | fn drop(&mut self) { |
| 359 | rcc::disable::<T>(); | 365 | rcc::disable::<T>(); |
| 360 | } | 366 | } |
| @@ -368,14 +374,14 @@ impl<'d, T: Instance, const N: u8, DMA> Drop for DacChannel<'d, T, N, DMA> { | |||
| 368 | /// | 374 | /// |
| 369 | /// ```ignore | 375 | /// ```ignore |
| 370 | /// // Pins may need to be changed for your specific device. | 376 | /// // Pins may need to be changed for your specific device. |
| 371 | /// let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, NoDma, NoDma, p.PA4, p.PA5).split(); | 377 | /// let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new_blocking(p.DAC1, p.PA4, p.PA5).split(); |
| 372 | /// ``` | 378 | /// ``` |
| 373 | pub struct Dac<'d, T: Instance, DMACh1 = NoDma, DMACh2 = NoDma> { | 379 | pub struct Dac<'d, T: Instance, M: PeriMode> { |
| 374 | ch1: DacChannel<'d, T, 1, DMACh1>, | 380 | ch1: DacChannel<'d, T, Ch1, M>, |
| 375 | ch2: DacChannel<'d, T, 2, DMACh2>, | 381 | ch2: DacChannel<'d, T, Ch2, M>, |
| 376 | } | 382 | } |
| 377 | 383 | ||
| 378 | impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | 384 | impl<'d, T: Instance> Dac<'d, T, Async> { |
| 379 | /// Create a new `Dac` instance, consuming the underlying DAC peripheral. | 385 | /// Create a new `Dac` instance, consuming the underlying DAC peripheral. |
| 380 | /// | 386 | /// |
| 381 | /// This struct allows you to access both channels of the DAC, where available. You can either | 387 | /// This struct allows you to access both channels of the DAC, where available. You can either |
| @@ -389,37 +395,82 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | |||
| 389 | /// By default, triggering is disabled, but it can be enabled using the `set_trigger()` | 395 | /// By default, triggering is disabled, but it can be enabled using the `set_trigger()` |
| 390 | /// method on the underlying channels. | 396 | /// method on the underlying channels. |
| 391 | pub fn new( | 397 | pub fn new( |
| 392 | _peri: impl Peripheral<P = T> + 'd, | 398 | peri: impl Peripheral<P = T> + 'd, |
| 393 | dma_ch1: impl Peripheral<P = DMACh1> + 'd, | 399 | dma_ch1: impl Peripheral<P = impl Dma<T, Ch1>> + 'd, |
| 394 | dma_ch2: impl Peripheral<P = DMACh2> + 'd, | 400 | dma_ch2: impl Peripheral<P = impl Dma<T, Ch2>> + 'd, |
| 395 | pin_ch1: impl Peripheral<P = impl DacPin<T, 1> + crate::gpio::Pin> + 'd, | 401 | pin_ch1: impl Peripheral<P = impl DacPin<T, Ch1> + crate::gpio::Pin> + 'd, |
| 396 | pin_ch2: impl Peripheral<P = impl DacPin<T, 2> + crate::gpio::Pin> + 'd, | 402 | pin_ch2: impl Peripheral<P = impl DacPin<T, Ch2> + crate::gpio::Pin> + 'd, |
| 397 | ) -> Self { | 403 | ) -> Self { |
| 398 | into_ref!(dma_ch1, dma_ch2, pin_ch1, pin_ch2); | 404 | into_ref!(dma_ch1, dma_ch2, pin_ch1, pin_ch2); |
| 399 | pin_ch1.set_as_analog(); | 405 | pin_ch1.set_as_analog(); |
| 400 | pin_ch2.set_as_analog(); | 406 | pin_ch2.set_as_analog(); |
| 407 | Self::new_inner( | ||
| 408 | peri, | ||
| 409 | new_dma!(dma_ch1), | ||
| 410 | new_dma!(dma_ch2), | ||
| 411 | #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] | ||
| 412 | Mode::NormalExternalBuffered, | ||
| 413 | ) | ||
| 414 | } | ||
| 401 | 415 | ||
| 402 | // Enable twice to increment the DAC refcount for each channel. | 416 | /// Create a new `Dac` instance where the external output pins are not used, |
| 403 | rcc::enable_and_reset::<T>(); | 417 | /// so the DAC can only be used to generate internal signals but the GPIO |
| 404 | rcc::enable_and_reset::<T>(); | 418 | /// pins remain available for other functions. |
| 405 | 419 | /// | |
| 406 | let mut ch1 = DacCh1 { | 420 | /// This struct allows you to access both channels of the DAC, where available. You can either |
| 407 | phantom: PhantomData, | 421 | /// call `split()` to obtain separate `DacChannel`s, or use methods on `Dac` to use the two |
| 408 | dma: dma_ch1, | 422 | /// channels together. |
| 409 | }; | 423 | /// |
| 410 | #[cfg(any(dac_v5, dac_v6, dac_v7))] | 424 | /// The channels are set to [`Mode::NormalInternalUnbuffered`] and enabled on creation. |
| 411 | ch1.set_hfsel(); | 425 | /// Note that some methods, such as `set_trigger()` and `set_mode()`, will disable the |
| 412 | ch1.enable(); | 426 | /// channel; you must re-enable them with `enable()`. |
| 413 | 427 | /// | |
| 414 | let mut ch2 = DacCh2 { | 428 | /// By default, triggering is disabled, but it can be enabled using the `set_trigger()` |
| 415 | phantom: PhantomData, | 429 | /// method on the underlying channels. |
| 416 | dma: dma_ch2, | 430 | #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))] |
| 417 | }; | 431 | pub fn new_internal( |
| 418 | #[cfg(any(dac_v5, dac_v6, dac_v7))] | 432 | peri: impl Peripheral<P = T> + 'd, |
| 419 | ch2.set_hfsel(); | 433 | dma_ch1: impl Peripheral<P = impl Dma<T, Ch1>> + 'd, |
| 420 | ch2.enable(); | 434 | dma_ch2: impl Peripheral<P = impl Dma<T, Ch2>> + 'd, |
| 435 | ) -> Self { | ||
| 436 | into_ref!(dma_ch1, dma_ch2); | ||
| 437 | Self::new_inner( | ||
| 438 | peri, | ||
| 439 | new_dma!(dma_ch1), | ||
| 440 | new_dma!(dma_ch2), | ||
| 441 | Mode::NormalInternalUnbuffered, | ||
| 442 | ) | ||
| 443 | } | ||
| 444 | } | ||
| 421 | 445 | ||
| 422 | Self { ch1, ch2 } | 446 | impl<'d, T: Instance> Dac<'d, T, Blocking> { |
| 447 | /// Create a new `Dac` instance, consuming the underlying DAC peripheral. | ||
| 448 | /// | ||
| 449 | /// This struct allows you to access both channels of the DAC, where available. You can either | ||
| 450 | /// call `split()` to obtain separate `DacChannel`s, or use methods on `Dac` to use | ||
| 451 | /// the two channels together. | ||
| 452 | /// | ||
| 453 | /// The channels are enabled on creation and begin to drive their output pins. | ||
| 454 | /// Note that some methods, such as `set_trigger()` and `set_mode()`, will | ||
| 455 | /// disable the channel; you must re-enable them with `enable()`. | ||
| 456 | /// | ||
| 457 | /// By default, triggering is disabled, but it can be enabled using the `set_trigger()` | ||
| 458 | /// method on the underlying channels. | ||
| 459 | pub fn new_blocking( | ||
| 460 | peri: impl Peripheral<P = T> + 'd, | ||
| 461 | pin_ch1: impl Peripheral<P = impl DacPin<T, Ch1> + crate::gpio::Pin> + 'd, | ||
| 462 | pin_ch2: impl Peripheral<P = impl DacPin<T, Ch2> + crate::gpio::Pin> + 'd, | ||
| 463 | ) -> Self { | ||
| 464 | into_ref!(pin_ch1, pin_ch2); | ||
| 465 | pin_ch1.set_as_analog(); | ||
| 466 | pin_ch2.set_as_analog(); | ||
| 467 | Self::new_inner( | ||
| 468 | peri, | ||
| 469 | None, | ||
| 470 | None, | ||
| 471 | #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] | ||
| 472 | Mode::NormalExternalBuffered, | ||
| 473 | ) | ||
| 423 | } | 474 | } |
| 424 | 475 | ||
| 425 | /// Create a new `Dac` instance where the external output pins are not used, | 476 | /// Create a new `Dac` instance where the external output pins are not used, |
| @@ -437,12 +488,18 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | |||
| 437 | /// By default, triggering is disabled, but it can be enabled using the `set_trigger()` | 488 | /// By default, triggering is disabled, but it can be enabled using the `set_trigger()` |
| 438 | /// method on the underlying channels. | 489 | /// method on the underlying channels. |
| 439 | #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))] | 490 | #[cfg(all(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7), not(any(stm32h56x, stm32h57x))))] |
| 440 | pub fn new_internal( | 491 | pub fn new_internal(peri: impl Peripheral<P = T> + 'd) -> Self { |
| 492 | Self::new_inner(peri, None, None, Mode::NormalInternalUnbuffered) | ||
| 493 | } | ||
| 494 | } | ||
| 495 | |||
| 496 | impl<'d, T: Instance, M: PeriMode> Dac<'d, T, M> { | ||
| 497 | fn new_inner( | ||
| 441 | _peri: impl Peripheral<P = T> + 'd, | 498 | _peri: impl Peripheral<P = T> + 'd, |
| 442 | dma_ch1: impl Peripheral<P = DMACh1> + 'd, | 499 | dma_ch1: Option<ChannelAndRequest<'d>>, |
| 443 | dma_ch2: impl Peripheral<P = DMACh2> + 'd, | 500 | dma_ch2: Option<ChannelAndRequest<'d>>, |
| 501 | #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] mode: Mode, | ||
| 444 | ) -> Self { | 502 | ) -> Self { |
| 445 | into_ref!(dma_ch1, dma_ch2); | ||
| 446 | // Enable twice to increment the DAC refcount for each channel. | 503 | // Enable twice to increment the DAC refcount for each channel. |
| 447 | rcc::enable_and_reset::<T>(); | 504 | rcc::enable_and_reset::<T>(); |
| 448 | rcc::enable_and_reset::<T>(); | 505 | rcc::enable_and_reset::<T>(); |
| @@ -453,7 +510,8 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | |||
| 453 | }; | 510 | }; |
| 454 | #[cfg(any(dac_v5, dac_v6, dac_v7))] | 511 | #[cfg(any(dac_v5, dac_v6, dac_v7))] |
| 455 | ch1.set_hfsel(); | 512 | ch1.set_hfsel(); |
| 456 | ch1.set_mode(Mode::NormalInternalUnbuffered); | 513 | #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] |
| 514 | ch1.set_mode(mode); | ||
| 457 | ch1.enable(); | 515 | ch1.enable(); |
| 458 | 516 | ||
| 459 | let mut ch2 = DacCh2 { | 517 | let mut ch2 = DacCh2 { |
| @@ -462,7 +520,8 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | |||
| 462 | }; | 520 | }; |
| 463 | #[cfg(any(dac_v5, dac_v6, dac_v7))] | 521 | #[cfg(any(dac_v5, dac_v6, dac_v7))] |
| 464 | ch2.set_hfsel(); | 522 | ch2.set_hfsel(); |
| 465 | ch2.set_mode(Mode::NormalInternalUnbuffered); | 523 | #[cfg(any(dac_v3, dac_v4, dac_v5, dac_v6, dac_v7))] |
| 524 | ch2.set_mode(mode); | ||
| 466 | ch2.enable(); | 525 | ch2.enable(); |
| 467 | 526 | ||
| 468 | Self { ch1, ch2 } | 527 | Self { ch1, ch2 } |
| @@ -471,17 +530,17 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { | |||
| 471 | /// Split this `Dac` into separate channels. | 530 | /// Split this `Dac` into separate channels. |
| 472 | /// | 531 | /// |
| 473 | /// You can access and move the channels around separately after splitting. | 532 | /// You can access and move the channels around separately after splitting. |
| 474 | pub fn split(self) -> (DacCh1<'d, T, DMACh1>, DacCh2<'d, T, DMACh2>) { | 533 | pub fn split(self) -> (DacCh1<'d, T, M>, DacCh2<'d, T, M>) { |
| 475 | (self.ch1, self.ch2) | 534 | (self.ch1, self.ch2) |
| 476 | } | 535 | } |
| 477 | 536 | ||
| 478 | /// Temporarily access channel 1. | 537 | /// Temporarily access channel 1. |
| 479 | pub fn ch1(&mut self) -> &mut DacCh1<'d, T, DMACh1> { | 538 | pub fn ch1(&mut self) -> &mut DacCh1<'d, T, M> { |
| 480 | &mut self.ch1 | 539 | &mut self.ch1 |
| 481 | } | 540 | } |
| 482 | 541 | ||
| 483 | /// Temporarily access channel 2. | 542 | /// Temporarily access channel 2. |
| 484 | pub fn ch2(&mut self) -> &mut DacCh2<'d, T, DMACh2> { | 543 | pub fn ch2(&mut self) -> &mut DacCh2<'d, T, M> { |
| 485 | &mut self.ch2 | 544 | &mut self.ch2 |
| 486 | } | 545 | } |
| 487 | 546 | ||
| @@ -514,11 +573,30 @@ trait SealedInstance { | |||
| 514 | /// DAC instance. | 573 | /// DAC instance. |
| 515 | #[allow(private_bounds)] | 574 | #[allow(private_bounds)] |
| 516 | pub trait Instance: SealedInstance + RccPeripheral + 'static {} | 575 | pub trait Instance: SealedInstance + RccPeripheral + 'static {} |
| 517 | dma_trait!(DacDma1, Instance); | ||
| 518 | dma_trait!(DacDma2, Instance); | ||
| 519 | 576 | ||
| 520 | /// Marks a pin that can be used with the DAC | 577 | /// Channel 1 marker type. |
| 521 | pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {} | 578 | pub enum Ch1 {} |
| 579 | /// Channel 2 marker type. | ||
| 580 | pub enum Ch2 {} | ||
| 581 | |||
| 582 | trait SealedChannel { | ||
| 583 | const IDX: usize; | ||
| 584 | } | ||
| 585 | /// DAC channel trait. | ||
| 586 | #[allow(private_bounds)] | ||
| 587 | pub trait Channel: SealedChannel {} | ||
| 588 | |||
| 589 | impl SealedChannel for Ch1 { | ||
| 590 | const IDX: usize = 0; | ||
| 591 | } | ||
| 592 | impl SealedChannel for Ch2 { | ||
| 593 | const IDX: usize = 1; | ||
| 594 | } | ||
| 595 | impl Channel for Ch1 {} | ||
| 596 | impl Channel for Ch2 {} | ||
| 597 | |||
| 598 | dma_trait!(Dma, Instance, Channel); | ||
| 599 | pin_trait!(DacPin, Instance, Channel); | ||
| 522 | 600 | ||
| 523 | foreach_peripheral!( | 601 | foreach_peripheral!( |
| 524 | (dac, $inst:ident) => { | 602 | (dac, $inst:ident) => { |
| @@ -531,9 +609,3 @@ foreach_peripheral!( | |||
| 531 | impl crate::dac::Instance for peripherals::$inst {} | 609 | impl crate::dac::Instance for peripherals::$inst {} |
| 532 | }; | 610 | }; |
| 533 | ); | 611 | ); |
| 534 | |||
| 535 | macro_rules! impl_dac_pin { | ||
| 536 | ($inst:ident, $pin:ident, $ch:expr) => { | ||
| 537 | impl crate::dac::DacPin<peripherals::$inst, $ch> for crate::peripherals::$pin {} | ||
| 538 | }; | ||
| 539 | } | ||
diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 66c4aa53c..ac4a0f98e 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs | |||
| @@ -108,17 +108,6 @@ impl Channel for AnyChannel {} | |||
| 108 | const CHANNEL_COUNT: usize = crate::_generated::DMA_CHANNELS.len(); | 108 | const CHANNEL_COUNT: usize = crate::_generated::DMA_CHANNELS.len(); |
| 109 | static STATE: [ChannelState; CHANNEL_COUNT] = [ChannelState::NEW; CHANNEL_COUNT]; | 109 | static STATE: [ChannelState; CHANNEL_COUNT] = [ChannelState::NEW; CHANNEL_COUNT]; |
| 110 | 110 | ||
| 111 | /// "No DMA" placeholder. | ||
| 112 | /// | ||
| 113 | /// You may pass this in place of a real DMA channel when creating a driver | ||
| 114 | /// to indicate it should not use DMA. | ||
| 115 | /// | ||
| 116 | /// This often causes async functionality to not be available on the instance, | ||
| 117 | /// leaving only blocking functionality. | ||
| 118 | pub struct NoDma; | ||
| 119 | |||
| 120 | impl_peripheral!(NoDma); | ||
| 121 | |||
| 122 | // safety: must be called only once at startup | 111 | // safety: must be called only once at startup |
| 123 | pub(crate) unsafe fn init( | 112 | pub(crate) unsafe fn init( |
| 124 | cs: critical_section::CriticalSection, | 113 | cs: critical_section::CriticalSection, |
diff --git a/embassy-stm32/src/dma/util.rs b/embassy-stm32/src/dma/util.rs index 5aaca57c9..5e1158182 100644 --- a/embassy-stm32/src/dma/util.rs +++ b/embassy-stm32/src/dma/util.rs | |||
| @@ -39,10 +39,10 @@ impl<'d> ChannelAndRequest<'d> { | |||
| 39 | Transfer::new_write(&mut self.channel, self.request, buf, peri_addr, options) | 39 | Transfer::new_write(&mut self.channel, self.request, buf, peri_addr, options) |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | pub unsafe fn write_raw<'a, W: Word>( | 42 | pub unsafe fn write_raw<'a, MW: Word, PW: Word>( |
| 43 | &'a mut self, | 43 | &'a mut self, |
| 44 | buf: *const [W], | 44 | buf: *const [MW], |
| 45 | peri_addr: *mut W, | 45 | peri_addr: *mut PW, |
| 46 | options: TransferOptions, | 46 | options: TransferOptions, |
| 47 | ) -> Transfer<'a> { | 47 | ) -> Transfer<'a> { |
| 48 | Transfer::new_write_raw(&mut self.channel, self.request, buf, peri_addr, options) | 48 | Transfer::new_write_raw(&mut self.channel, self.request, buf, peri_addr, options) |
diff --git a/embassy-stm32/src/hash/mod.rs b/embassy-stm32/src/hash/mod.rs index 3c2125498..3951e9d63 100644 --- a/embassy-stm32/src/hash/mod.rs +++ b/embassy-stm32/src/hash/mod.rs | |||
| @@ -12,10 +12,12 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; | |||
| 12 | use embassy_sync::waitqueue::AtomicWaker; | 12 | use embassy_sync::waitqueue::AtomicWaker; |
| 13 | use stm32_metapac::hash::regs::*; | 13 | use stm32_metapac::hash::regs::*; |
| 14 | 14 | ||
| 15 | use crate::dma::NoDma; | ||
| 16 | #[cfg(hash_v2)] | 15 | #[cfg(hash_v2)] |
| 17 | use crate::dma::Transfer; | 16 | use crate::dma::ChannelAndRequest; |
| 18 | use crate::interrupt::typelevel::Interrupt; | 17 | use crate::interrupt::typelevel::Interrupt; |
| 18 | #[cfg(hash_v2)] | ||
| 19 | use crate::mode::Async; | ||
| 20 | use crate::mode::{Blocking, Mode}; | ||
| 19 | use crate::peripherals::HASH; | 21 | use crate::peripherals::HASH; |
| 20 | use crate::{interrupt, pac, peripherals, rcc, Peripheral}; | 22 | use crate::{interrupt, pac, peripherals, rcc, Peripheral}; |
| 21 | 23 | ||
| @@ -116,24 +118,26 @@ pub struct Context<'c> { | |||
| 116 | type HmacKey<'k> = Option<&'k [u8]>; | 118 | type HmacKey<'k> = Option<&'k [u8]>; |
| 117 | 119 | ||
| 118 | /// HASH driver. | 120 | /// HASH driver. |
| 119 | pub struct Hash<'d, T: Instance, D = NoDma> { | 121 | pub struct Hash<'d, T: Instance, M: Mode> { |
| 120 | _peripheral: PeripheralRef<'d, T>, | 122 | _peripheral: PeripheralRef<'d, T>, |
| 121 | #[allow(dead_code)] | 123 | _phantom: PhantomData<M>, |
| 122 | dma: PeripheralRef<'d, D>, | 124 | #[cfg(hash_v2)] |
| 125 | dma: Option<ChannelAndRequest<'d>>, | ||
| 123 | } | 126 | } |
| 124 | 127 | ||
| 125 | impl<'d, T: Instance, D> Hash<'d, T, D> { | 128 | impl<'d, T: Instance> Hash<'d, T, Blocking> { |
| 126 | /// Instantiates, resets, and enables the HASH peripheral. | 129 | /// Instantiates, resets, and enables the HASH peripheral. |
| 127 | pub fn new( | 130 | pub fn new_blocking( |
| 128 | peripheral: impl Peripheral<P = T> + 'd, | 131 | peripheral: impl Peripheral<P = T> + 'd, |
| 129 | dma: impl Peripheral<P = D> + 'd, | ||
| 130 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 132 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 131 | ) -> Self { | 133 | ) -> Self { |
| 132 | rcc::enable_and_reset::<HASH>(); | 134 | rcc::enable_and_reset::<HASH>(); |
| 133 | into_ref!(peripheral, dma); | 135 | into_ref!(peripheral); |
| 134 | let instance = Self { | 136 | let instance = Self { |
| 135 | _peripheral: peripheral, | 137 | _peripheral: peripheral, |
| 136 | dma: dma, | 138 | _phantom: PhantomData, |
| 139 | #[cfg(hash_v2)] | ||
| 140 | dma: None, | ||
| 137 | }; | 141 | }; |
| 138 | 142 | ||
| 139 | T::Interrupt::unpend(); | 143 | T::Interrupt::unpend(); |
| @@ -141,7 +145,9 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { | |||
| 141 | 145 | ||
| 142 | instance | 146 | instance |
| 143 | } | 147 | } |
| 148 | } | ||
| 144 | 149 | ||
| 150 | impl<'d, T: Instance, M: Mode> Hash<'d, T, M> { | ||
| 145 | /// Starts computation of a new hash and returns the saved peripheral state. | 151 | /// Starts computation of a new hash and returns the saved peripheral state. |
| 146 | pub fn start<'c>(&mut self, algorithm: Algorithm, format: DataType, key: HmacKey<'c>) -> Context<'c> { | 152 | pub fn start<'c>(&mut self, algorithm: Algorithm, format: DataType, key: HmacKey<'c>) -> Context<'c> { |
| 147 | // Define a context for this new computation. | 153 | // Define a context for this new computation. |
| @@ -282,14 +288,136 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { | |||
| 282 | self.store_context(ctx); | 288 | self.store_context(ctx); |
| 283 | } | 289 | } |
| 284 | 290 | ||
| 291 | /// Computes a digest for the given context. | ||
| 292 | /// The digest buffer must be large enough to accomodate a digest for the selected algorithm. | ||
| 293 | /// The largest returned digest size is 128 bytes for SHA-512. | ||
| 294 | /// Panics if the supplied digest buffer is too short. | ||
| 295 | pub fn finish_blocking<'c>(&mut self, mut ctx: Context<'c>, digest: &mut [u8]) -> usize { | ||
| 296 | // Restore the peripheral state. | ||
| 297 | self.load_context(&ctx); | ||
| 298 | |||
| 299 | // Hash the leftover bytes, if any. | ||
| 300 | self.accumulate_blocking(&ctx.buffer[0..ctx.buflen]); | ||
| 301 | ctx.buflen = 0; | ||
| 302 | |||
| 303 | //Start the digest calculation. | ||
| 304 | T::regs().str().write(|w| w.set_dcal(true)); | ||
| 305 | |||
| 306 | // Load the HMAC key if provided. | ||
| 307 | if let Some(key) = ctx.key { | ||
| 308 | while !T::regs().sr().read().dinis() {} | ||
| 309 | self.accumulate_blocking(key); | ||
| 310 | T::regs().str().write(|w| w.set_dcal(true)); | ||
| 311 | } | ||
| 312 | |||
| 313 | // Block until digest computation is complete. | ||
| 314 | while !T::regs().sr().read().dcis() {} | ||
| 315 | |||
| 316 | // Return the digest. | ||
| 317 | let digest_words = match ctx.algo { | ||
| 318 | Algorithm::SHA1 => 5, | ||
| 319 | #[cfg(any(hash_v1, hash_v2, hash_v4))] | ||
| 320 | Algorithm::MD5 => 4, | ||
| 321 | Algorithm::SHA224 => 7, | ||
| 322 | Algorithm::SHA256 => 8, | ||
| 323 | #[cfg(hash_v3)] | ||
| 324 | Algorithm::SHA384 => 12, | ||
| 325 | #[cfg(hash_v3)] | ||
| 326 | Algorithm::SHA512_224 => 7, | ||
| 327 | #[cfg(hash_v3)] | ||
| 328 | Algorithm::SHA512_256 => 8, | ||
| 329 | #[cfg(hash_v3)] | ||
| 330 | Algorithm::SHA512 => 16, | ||
| 331 | }; | ||
| 332 | |||
| 333 | let digest_len_bytes = digest_words * 4; | ||
| 334 | // Panics if the supplied digest buffer is too short. | ||
| 335 | if digest.len() < digest_len_bytes { | ||
| 336 | panic!("Digest buffer must be at least {} bytes long.", digest_words * 4); | ||
| 337 | } | ||
| 338 | |||
| 339 | let mut i = 0; | ||
| 340 | while i < digest_words { | ||
| 341 | let word = T::regs().hr(i).read(); | ||
| 342 | digest[(i * 4)..((i * 4) + 4)].copy_from_slice(word.to_be_bytes().as_slice()); | ||
| 343 | i += 1; | ||
| 344 | } | ||
| 345 | digest_len_bytes | ||
| 346 | } | ||
| 347 | |||
| 348 | /// Push data into the hash core. | ||
| 349 | fn accumulate_blocking(&mut self, input: &[u8]) { | ||
| 350 | // Set the number of valid bits. | ||
| 351 | let num_valid_bits: u8 = (8 * (input.len() % 4)) as u8; | ||
| 352 | T::regs().str().modify(|w| w.set_nblw(num_valid_bits)); | ||
| 353 | |||
| 354 | let mut i = 0; | ||
| 355 | while i < input.len() { | ||
| 356 | let mut word: [u8; 4] = [0; 4]; | ||
| 357 | let copy_idx = min(i + 4, input.len()); | ||
| 358 | word[0..copy_idx - i].copy_from_slice(&input[i..copy_idx]); | ||
| 359 | T::regs().din().write_value(u32::from_ne_bytes(word)); | ||
| 360 | i += 4; | ||
| 361 | } | ||
| 362 | } | ||
| 363 | |||
| 364 | /// Save the peripheral state to a context. | ||
| 365 | fn store_context<'c>(&mut self, ctx: &mut Context<'c>) { | ||
| 366 | // Block waiting for data in ready. | ||
| 367 | while !T::regs().sr().read().dinis() {} | ||
| 368 | |||
| 369 | // Store peripheral context. | ||
| 370 | ctx.imr = T::regs().imr().read().0; | ||
| 371 | ctx.str = T::regs().str().read().0; | ||
| 372 | ctx.cr = T::regs().cr().read().0; | ||
| 373 | let mut i = 0; | ||
| 374 | while i < NUM_CONTEXT_REGS { | ||
| 375 | ctx.csr[i] = T::regs().csr(i).read(); | ||
| 376 | i += 1; | ||
| 377 | } | ||
| 378 | } | ||
| 379 | |||
| 380 | /// Restore the peripheral state from a context. | ||
| 381 | fn load_context(&mut self, ctx: &Context) { | ||
| 382 | // Restore the peripheral state from the context. | ||
| 383 | T::regs().imr().write_value(Imr { 0: ctx.imr }); | ||
| 384 | T::regs().str().write_value(Str { 0: ctx.str }); | ||
| 385 | T::regs().cr().write_value(Cr { 0: ctx.cr }); | ||
| 386 | T::regs().cr().modify(|w| w.set_init(true)); | ||
| 387 | let mut i = 0; | ||
| 388 | while i < NUM_CONTEXT_REGS { | ||
| 389 | T::regs().csr(i).write_value(ctx.csr[i]); | ||
| 390 | i += 1; | ||
| 391 | } | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 395 | #[cfg(hash_v2)] | ||
| 396 | impl<'d, T: Instance> Hash<'d, T, Async> { | ||
| 397 | /// Instantiates, resets, and enables the HASH peripheral. | ||
| 398 | pub fn new( | ||
| 399 | peripheral: impl Peripheral<P = T> + 'd, | ||
| 400 | dma: impl Peripheral<P = impl Dma<T>> + 'd, | ||
| 401 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||
| 402 | ) -> Self { | ||
| 403 | rcc::enable_and_reset::<HASH>(); | ||
| 404 | into_ref!(peripheral, dma); | ||
| 405 | let instance = Self { | ||
| 406 | _peripheral: peripheral, | ||
| 407 | _phantom: PhantomData, | ||
| 408 | dma: new_dma!(dma), | ||
| 409 | }; | ||
| 410 | |||
| 411 | T::Interrupt::unpend(); | ||
| 412 | unsafe { T::Interrupt::enable() }; | ||
| 413 | |||
| 414 | instance | ||
| 415 | } | ||
| 416 | |||
| 285 | /// Restores the peripheral state using the given context, | 417 | /// Restores the peripheral state using the given context, |
| 286 | /// then updates the state with the provided data. | 418 | /// then updates the state with the provided data. |
| 287 | /// Peripheral state is saved upon return. | 419 | /// Peripheral state is saved upon return. |
| 288 | #[cfg(hash_v2)] | 420 | pub async fn update(&mut self, ctx: &mut Context<'_>, input: &[u8]) { |
| 289 | pub async fn update<'c>(&mut self, ctx: &mut Context<'c>, input: &[u8]) | ||
| 290 | where | ||
| 291 | D: crate::hash::Dma<T>, | ||
| 292 | { | ||
| 293 | // Restore the peripheral state. | 421 | // Restore the peripheral state. |
| 294 | self.load_context(&ctx); | 422 | self.load_context(&ctx); |
| 295 | 423 | ||
| @@ -353,68 +481,7 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { | |||
| 353 | /// The digest buffer must be large enough to accomodate a digest for the selected algorithm. | 481 | /// The digest buffer must be large enough to accomodate a digest for the selected algorithm. |
| 354 | /// The largest returned digest size is 128 bytes for SHA-512. | 482 | /// The largest returned digest size is 128 bytes for SHA-512. |
| 355 | /// Panics if the supplied digest buffer is too short. | 483 | /// Panics if the supplied digest buffer is too short. |
| 356 | pub fn finish_blocking<'c>(&mut self, mut ctx: Context<'c>, digest: &mut [u8]) -> usize { | 484 | pub async fn finish<'c>(&mut self, mut ctx: Context<'c>, digest: &mut [u8]) -> usize { |
| 357 | // Restore the peripheral state. | ||
| 358 | self.load_context(&ctx); | ||
| 359 | |||
| 360 | // Hash the leftover bytes, if any. | ||
| 361 | self.accumulate_blocking(&ctx.buffer[0..ctx.buflen]); | ||
| 362 | ctx.buflen = 0; | ||
| 363 | |||
| 364 | //Start the digest calculation. | ||
| 365 | T::regs().str().write(|w| w.set_dcal(true)); | ||
| 366 | |||
| 367 | // Load the HMAC key if provided. | ||
| 368 | if let Some(key) = ctx.key { | ||
| 369 | while !T::regs().sr().read().dinis() {} | ||
| 370 | self.accumulate_blocking(key); | ||
| 371 | T::regs().str().write(|w| w.set_dcal(true)); | ||
| 372 | } | ||
| 373 | |||
| 374 | // Block until digest computation is complete. | ||
| 375 | while !T::regs().sr().read().dcis() {} | ||
| 376 | |||
| 377 | // Return the digest. | ||
| 378 | let digest_words = match ctx.algo { | ||
| 379 | Algorithm::SHA1 => 5, | ||
| 380 | #[cfg(any(hash_v1, hash_v2, hash_v4))] | ||
| 381 | Algorithm::MD5 => 4, | ||
| 382 | Algorithm::SHA224 => 7, | ||
| 383 | Algorithm::SHA256 => 8, | ||
| 384 | #[cfg(hash_v3)] | ||
| 385 | Algorithm::SHA384 => 12, | ||
| 386 | #[cfg(hash_v3)] | ||
| 387 | Algorithm::SHA512_224 => 7, | ||
| 388 | #[cfg(hash_v3)] | ||
| 389 | Algorithm::SHA512_256 => 8, | ||
| 390 | #[cfg(hash_v3)] | ||
| 391 | Algorithm::SHA512 => 16, | ||
| 392 | }; | ||
| 393 | |||
| 394 | let digest_len_bytes = digest_words * 4; | ||
| 395 | // Panics if the supplied digest buffer is too short. | ||
| 396 | if digest.len() < digest_len_bytes { | ||
| 397 | panic!("Digest buffer must be at least {} bytes long.", digest_words * 4); | ||
| 398 | } | ||
| 399 | |||
| 400 | let mut i = 0; | ||
| 401 | while i < digest_words { | ||
| 402 | let word = T::regs().hr(i).read(); | ||
| 403 | digest[(i * 4)..((i * 4) + 4)].copy_from_slice(word.to_be_bytes().as_slice()); | ||
| 404 | i += 1; | ||
| 405 | } | ||
| 406 | digest_len_bytes | ||
| 407 | } | ||
| 408 | |||
| 409 | /// Computes a digest for the given context. | ||
| 410 | /// The digest buffer must be large enough to accomodate a digest for the selected algorithm. | ||
| 411 | /// The largest returned digest size is 128 bytes for SHA-512. | ||
| 412 | /// Panics if the supplied digest buffer is too short. | ||
| 413 | #[cfg(hash_v2)] | ||
| 414 | pub async fn finish<'c>(&mut self, mut ctx: Context<'c>, digest: &mut [u8]) -> usize | ||
| 415 | where | ||
| 416 | D: crate::hash::Dma<T>, | ||
| 417 | { | ||
| 418 | // Restore the peripheral state. | 485 | // Restore the peripheral state. |
| 419 | self.load_context(&ctx); | 486 | self.load_context(&ctx); |
| 420 | 487 | ||
| @@ -483,27 +550,7 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { | |||
| 483 | } | 550 | } |
| 484 | 551 | ||
| 485 | /// Push data into the hash core. | 552 | /// Push data into the hash core. |
| 486 | fn accumulate_blocking(&mut self, input: &[u8]) { | 553 | async fn accumulate(&mut self, input: &[u8]) { |
| 487 | // Set the number of valid bits. | ||
| 488 | let num_valid_bits: u8 = (8 * (input.len() % 4)) as u8; | ||
| 489 | T::regs().str().modify(|w| w.set_nblw(num_valid_bits)); | ||
| 490 | |||
| 491 | let mut i = 0; | ||
| 492 | while i < input.len() { | ||
| 493 | let mut word: [u8; 4] = [0; 4]; | ||
| 494 | let copy_idx = min(i + 4, input.len()); | ||
| 495 | word[0..copy_idx - i].copy_from_slice(&input[i..copy_idx]); | ||
| 496 | T::regs().din().write_value(u32::from_ne_bytes(word)); | ||
| 497 | i += 4; | ||
| 498 | } | ||
| 499 | } | ||
| 500 | |||
| 501 | /// Push data into the hash core. | ||
| 502 | #[cfg(hash_v2)] | ||
| 503 | async fn accumulate(&mut self, input: &[u8]) | ||
| 504 | where | ||
| 505 | D: crate::hash::Dma<T>, | ||
| 506 | { | ||
| 507 | // Ignore an input length of 0. | 554 | // Ignore an input length of 0. |
| 508 | if input.len() == 0 { | 555 | if input.len() == 0 { |
| 509 | return; | 556 | return; |
| @@ -514,57 +561,20 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { | |||
| 514 | T::regs().str().modify(|w| w.set_nblw(num_valid_bits)); | 561 | T::regs().str().modify(|w| w.set_nblw(num_valid_bits)); |
| 515 | 562 | ||
| 516 | // Configure DMA to transfer input to hash core. | 563 | // Configure DMA to transfer input to hash core. |
| 517 | let dma_request = self.dma.request(); | ||
| 518 | let dst_ptr: *mut u32 = T::regs().din().as_ptr(); | 564 | let dst_ptr: *mut u32 = T::regs().din().as_ptr(); |
| 519 | let mut num_words = input.len() / 4; | 565 | let mut num_words = input.len() / 4; |
| 520 | if input.len() % 4 > 0 { | 566 | if input.len() % 4 > 0 { |
| 521 | num_words += 1; | 567 | num_words += 1; |
| 522 | } | 568 | } |
| 523 | let src_ptr: *const [u8] = ptr::slice_from_raw_parts(input.as_ptr().cast(), num_words); | 569 | let src_ptr: *const [u8] = ptr::slice_from_raw_parts(input.as_ptr().cast(), num_words); |
| 524 | let dma_transfer = unsafe { | 570 | |
| 525 | Transfer::new_write_raw( | 571 | let dma = self.dma.as_mut().unwrap(); |
| 526 | &mut self.dma, | 572 | let dma_transfer = unsafe { dma.write_raw(src_ptr, dst_ptr as *mut u32, Default::default()) }; |
| 527 | dma_request, | ||
| 528 | src_ptr, | ||
| 529 | dst_ptr as *mut u32, | ||
| 530 | Default::default(), | ||
| 531 | ) | ||
| 532 | }; | ||
| 533 | T::regs().cr().modify(|w| w.set_dmae(true)); | 573 | T::regs().cr().modify(|w| w.set_dmae(true)); |
| 534 | 574 | ||
| 535 | // Wait for the transfer to complete. | 575 | // Wait for the transfer to complete. |
| 536 | dma_transfer.await; | 576 | dma_transfer.await; |
| 537 | } | 577 | } |
| 538 | |||
| 539 | /// Save the peripheral state to a context. | ||
| 540 | fn store_context<'c>(&mut self, ctx: &mut Context<'c>) { | ||
| 541 | // Block waiting for data in ready. | ||
| 542 | while !T::regs().sr().read().dinis() {} | ||
| 543 | |||
| 544 | // Store peripheral context. | ||
| 545 | ctx.imr = T::regs().imr().read().0; | ||
| 546 | ctx.str = T::regs().str().read().0; | ||
| 547 | ctx.cr = T::regs().cr().read().0; | ||
| 548 | let mut i = 0; | ||
| 549 | while i < NUM_CONTEXT_REGS { | ||
| 550 | ctx.csr[i] = T::regs().csr(i).read(); | ||
| 551 | i += 1; | ||
| 552 | } | ||
| 553 | } | ||
| 554 | |||
| 555 | /// Restore the peripheral state from a context. | ||
| 556 | fn load_context(&mut self, ctx: &Context) { | ||
| 557 | // Restore the peripheral state from the context. | ||
| 558 | T::regs().imr().write_value(Imr { 0: ctx.imr }); | ||
| 559 | T::regs().str().write_value(Str { 0: ctx.str }); | ||
| 560 | T::regs().cr().write_value(Cr { 0: ctx.cr }); | ||
| 561 | T::regs().cr().modify(|w| w.set_init(true)); | ||
| 562 | let mut i = 0; | ||
| 563 | while i < NUM_CONTEXT_REGS { | ||
| 564 | T::regs().csr(i).write_value(ctx.csr[i]); | ||
| 565 | i += 1; | ||
| 566 | } | ||
| 567 | } | ||
| 568 | } | 578 | } |
| 569 | 579 | ||
| 570 | trait SealedInstance { | 580 | trait SealedInstance { |
diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs index ae53deb08..000773e2d 100644 --- a/embassy-stm32/src/macros.rs +++ b/embassy-stm32/src/macros.rs | |||
| @@ -85,6 +85,18 @@ macro_rules! dma_trait_impl { | |||
| 85 | }; | 85 | }; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | #[allow(unused)] | ||
| 89 | macro_rules! new_dma_nonopt { | ||
| 90 | ($name:ident) => {{ | ||
| 91 | let dma = $name.into_ref(); | ||
| 92 | let request = dma.request(); | ||
| 93 | crate::dma::ChannelAndRequest { | ||
| 94 | channel: dma.map_into(), | ||
| 95 | request, | ||
| 96 | } | ||
| 97 | }}; | ||
| 98 | } | ||
| 99 | |||
| 88 | macro_rules! new_dma { | 100 | macro_rules! new_dma { |
| 89 | ($name:ident) => {{ | 101 | ($name:ident) => {{ |
| 90 | let dma = $name.into_ref(); | 102 | let dma = $name.into_ref(); |
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 8af2f8381..d8671caf7 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs | |||
| @@ -12,7 +12,8 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; | |||
| 12 | use embassy_sync::waitqueue::AtomicWaker; | 12 | use embassy_sync::waitqueue::AtomicWaker; |
| 13 | use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; | 13 | use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; |
| 14 | 14 | ||
| 15 | use crate::dma::NoDma; | 15 | #[cfg(sdmmc_v1)] |
| 16 | use crate::dma::ChannelAndRequest; | ||
| 16 | #[cfg(gpio_v2)] | 17 | #[cfg(gpio_v2)] |
| 17 | use crate::gpio::Pull; | 18 | use crate::gpio::Pull; |
| 18 | use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; | 19 | use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; |
| @@ -301,10 +302,10 @@ impl Default for Config { | |||
| 301 | } | 302 | } |
| 302 | 303 | ||
| 303 | /// Sdmmc device | 304 | /// Sdmmc device |
| 304 | pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> { | 305 | pub struct Sdmmc<'d, T: Instance> { |
| 305 | _peri: PeripheralRef<'d, T>, | 306 | _peri: PeripheralRef<'d, T>, |
| 306 | #[allow(unused)] | 307 | #[cfg(sdmmc_v1)] |
| 307 | dma: PeripheralRef<'d, Dma>, | 308 | dma: ChannelAndRequest<'d>, |
| 308 | 309 | ||
| 309 | clk: PeripheralRef<'d, AnyPin>, | 310 | clk: PeripheralRef<'d, AnyPin>, |
| 310 | cmd: PeripheralRef<'d, AnyPin>, | 311 | cmd: PeripheralRef<'d, AnyPin>, |
| @@ -334,18 +335,18 @@ const CMD_AF: AfType = AfType::output_pull(OutputType::PushPull, Speed::VeryHigh | |||
| 334 | const DATA_AF: AfType = CMD_AF; | 335 | const DATA_AF: AfType = CMD_AF; |
| 335 | 336 | ||
| 336 | #[cfg(sdmmc_v1)] | 337 | #[cfg(sdmmc_v1)] |
| 337 | impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | 338 | impl<'d, T: Instance> Sdmmc<'d, T> { |
| 338 | /// Create a new SDMMC driver, with 1 data lane. | 339 | /// Create a new SDMMC driver, with 1 data lane. |
| 339 | pub fn new_1bit( | 340 | pub fn new_1bit( |
| 340 | sdmmc: impl Peripheral<P = T> + 'd, | 341 | sdmmc: impl Peripheral<P = T> + 'd, |
| 341 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 342 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 342 | dma: impl Peripheral<P = Dma> + 'd, | 343 | dma: impl Peripheral<P = impl SdmmcDma<T>> + 'd, |
| 343 | clk: impl Peripheral<P = impl CkPin<T>> + 'd, | 344 | clk: impl Peripheral<P = impl CkPin<T>> + 'd, |
| 344 | cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, | 345 | cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, |
| 345 | d0: impl Peripheral<P = impl D0Pin<T>> + 'd, | 346 | d0: impl Peripheral<P = impl D0Pin<T>> + 'd, |
| 346 | config: Config, | 347 | config: Config, |
| 347 | ) -> Self { | 348 | ) -> Self { |
| 348 | into_ref!(clk, cmd, d0); | 349 | into_ref!(dma, clk, cmd, d0); |
| 349 | 350 | ||
| 350 | critical_section::with(|_| { | 351 | critical_section::with(|_| { |
| 351 | clk.set_as_af(clk.af_num(), CLK_AF); | 352 | clk.set_as_af(clk.af_num(), CLK_AF); |
| @@ -355,7 +356,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||
| 355 | 356 | ||
| 356 | Self::new_inner( | 357 | Self::new_inner( |
| 357 | sdmmc, | 358 | sdmmc, |
| 358 | dma, | 359 | new_dma_nonopt!(dma), |
| 359 | clk.map_into(), | 360 | clk.map_into(), |
| 360 | cmd.map_into(), | 361 | cmd.map_into(), |
| 361 | d0.map_into(), | 362 | d0.map_into(), |
| @@ -370,7 +371,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||
| 370 | pub fn new_4bit( | 371 | pub fn new_4bit( |
| 371 | sdmmc: impl Peripheral<P = T> + 'd, | 372 | sdmmc: impl Peripheral<P = T> + 'd, |
| 372 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 373 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 373 | dma: impl Peripheral<P = Dma> + 'd, | 374 | dma: impl Peripheral<P = impl SdmmcDma<T>> + 'd, |
| 374 | clk: impl Peripheral<P = impl CkPin<T>> + 'd, | 375 | clk: impl Peripheral<P = impl CkPin<T>> + 'd, |
| 375 | cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, | 376 | cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, |
| 376 | d0: impl Peripheral<P = impl D0Pin<T>> + 'd, | 377 | d0: impl Peripheral<P = impl D0Pin<T>> + 'd, |
| @@ -392,7 +393,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||
| 392 | 393 | ||
| 393 | Self::new_inner( | 394 | Self::new_inner( |
| 394 | sdmmc, | 395 | sdmmc, |
| 395 | dma, | 396 | new_dma_nonopt!(dma), |
| 396 | clk.map_into(), | 397 | clk.map_into(), |
| 397 | cmd.map_into(), | 398 | cmd.map_into(), |
| 398 | d0.map_into(), | 399 | d0.map_into(), |
| @@ -405,7 +406,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||
| 405 | } | 406 | } |
| 406 | 407 | ||
| 407 | #[cfg(sdmmc_v2)] | 408 | #[cfg(sdmmc_v2)] |
| 408 | impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | 409 | impl<'d, T: Instance> Sdmmc<'d, T> { |
| 409 | /// Create a new SDMMC driver, with 1 data lane. | 410 | /// Create a new SDMMC driver, with 1 data lane. |
| 410 | pub fn new_1bit( | 411 | pub fn new_1bit( |
| 411 | sdmmc: impl Peripheral<P = T> + 'd, | 412 | sdmmc: impl Peripheral<P = T> + 'd, |
| @@ -425,7 +426,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | |||
| 425 | 426 | ||
| 426 | Self::new_inner( | 427 | Self::new_inner( |
| 427 | sdmmc, | 428 | sdmmc, |
| 428 | NoDma.into_ref(), | ||
| 429 | clk.map_into(), | 429 | clk.map_into(), |
| 430 | cmd.map_into(), | 430 | cmd.map_into(), |
| 431 | d0.map_into(), | 431 | d0.map_into(), |
| @@ -461,7 +461,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | |||
| 461 | 461 | ||
| 462 | Self::new_inner( | 462 | Self::new_inner( |
| 463 | sdmmc, | 463 | sdmmc, |
| 464 | NoDma.into_ref(), | ||
| 465 | clk.map_into(), | 464 | clk.map_into(), |
| 466 | cmd.map_into(), | 465 | cmd.map_into(), |
| 467 | d0.map_into(), | 466 | d0.map_into(), |
| @@ -473,10 +472,10 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | |||
| 473 | } | 472 | } |
| 474 | } | 473 | } |
| 475 | 474 | ||
| 476 | impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | 475 | impl<'d, T: Instance> Sdmmc<'d, T> { |
| 477 | fn new_inner( | 476 | fn new_inner( |
| 478 | sdmmc: impl Peripheral<P = T> + 'd, | 477 | sdmmc: impl Peripheral<P = T> + 'd, |
| 479 | dma: impl Peripheral<P = Dma> + 'd, | 478 | #[cfg(sdmmc_v1)] dma: ChannelAndRequest<'d>, |
| 480 | clk: PeripheralRef<'d, AnyPin>, | 479 | clk: PeripheralRef<'d, AnyPin>, |
| 481 | cmd: PeripheralRef<'d, AnyPin>, | 480 | cmd: PeripheralRef<'d, AnyPin>, |
| 482 | d0: PeripheralRef<'d, AnyPin>, | 481 | d0: PeripheralRef<'d, AnyPin>, |
| @@ -485,7 +484,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 485 | d3: Option<PeripheralRef<'d, AnyPin>>, | 484 | d3: Option<PeripheralRef<'d, AnyPin>>, |
| 486 | config: Config, | 485 | config: Config, |
| 487 | ) -> Self { | 486 | ) -> Self { |
| 488 | into_ref!(sdmmc, dma); | 487 | into_ref!(sdmmc); |
| 489 | 488 | ||
| 490 | rcc::enable_and_reset::<T>(); | 489 | rcc::enable_and_reset::<T>(); |
| 491 | 490 | ||
| @@ -514,6 +513,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 514 | 513 | ||
| 515 | Self { | 514 | Self { |
| 516 | _peri: sdmmc, | 515 | _peri: sdmmc, |
| 516 | #[cfg(sdmmc_v1)] | ||
| 517 | dma, | 517 | dma, |
| 518 | 518 | ||
| 519 | clk, | 519 | clk, |
| @@ -567,7 +567,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 567 | #[allow(unused_variables)] | 567 | #[allow(unused_variables)] |
| 568 | fn prepare_datapath_read<'a>( | 568 | fn prepare_datapath_read<'a>( |
| 569 | config: &Config, | 569 | config: &Config, |
| 570 | dma: &'a mut PeripheralRef<'d, Dma>, | 570 | #[cfg(sdmmc_v1)] dma: &'a mut ChannelAndRequest<'d>, |
| 571 | buffer: &'a mut [u32], | 571 | buffer: &'a mut [u32], |
| 572 | length_bytes: u32, | 572 | length_bytes: u32, |
| 573 | block_size: u8, | 573 | block_size: u8, |
| @@ -583,16 +583,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 583 | regs.dlenr().write(|w| w.set_datalength(length_bytes)); | 583 | regs.dlenr().write(|w| w.set_datalength(length_bytes)); |
| 584 | 584 | ||
| 585 | #[cfg(sdmmc_v1)] | 585 | #[cfg(sdmmc_v1)] |
| 586 | let transfer = unsafe { | 586 | let transfer = unsafe { dma.read(regs.fifor().as_ptr() as *mut u32, buffer, DMA_TRANSFER_OPTIONS) }; |
| 587 | let request = dma.request(); | ||
| 588 | Transfer::new_read( | ||
| 589 | dma, | ||
| 590 | request, | ||
| 591 | regs.fifor().as_ptr() as *mut u32, | ||
| 592 | buffer, | ||
| 593 | DMA_TRANSFER_OPTIONS, | ||
| 594 | ) | ||
| 595 | }; | ||
| 596 | #[cfg(sdmmc_v2)] | 587 | #[cfg(sdmmc_v2)] |
| 597 | let transfer = { | 588 | let transfer = { |
| 598 | regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); | 589 | regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); |
| @@ -632,14 +623,8 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 632 | 623 | ||
| 633 | #[cfg(sdmmc_v1)] | 624 | #[cfg(sdmmc_v1)] |
| 634 | let transfer = unsafe { | 625 | let transfer = unsafe { |
| 635 | let request = self.dma.request(); | 626 | self.dma |
| 636 | Transfer::new_write( | 627 | .write(buffer, regs.fifor().as_ptr() as *mut u32, DMA_TRANSFER_OPTIONS) |
| 637 | &mut self.dma, | ||
| 638 | request, | ||
| 639 | buffer, | ||
| 640 | regs.fifor().as_ptr() as *mut u32, | ||
| 641 | DMA_TRANSFER_OPTIONS, | ||
| 642 | ) | ||
| 643 | }; | 628 | }; |
| 644 | #[cfg(sdmmc_v2)] | 629 | #[cfg(sdmmc_v2)] |
| 645 | let transfer = { | 630 | let transfer = { |
| @@ -735,7 +720,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 735 | let regs = T::regs(); | 720 | let regs = T::regs(); |
| 736 | let on_drop = OnDrop::new(|| Self::on_drop()); | 721 | let on_drop = OnDrop::new(|| Self::on_drop()); |
| 737 | 722 | ||
| 738 | let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, status.as_mut(), 64, 6); | 723 | let transfer = Self::prepare_datapath_read( |
| 724 | &self.config, | ||
| 725 | #[cfg(sdmmc_v1)] | ||
| 726 | &mut self.dma, | ||
| 727 | status.as_mut(), | ||
| 728 | 64, | ||
| 729 | 6, | ||
| 730 | ); | ||
| 739 | InterruptHandler::<T>::data_interrupts(true); | 731 | InterruptHandler::<T>::data_interrupts(true); |
| 740 | Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6 | 732 | Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6 |
| 741 | 733 | ||
| @@ -821,7 +813,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 821 | let regs = T::regs(); | 813 | let regs = T::regs(); |
| 822 | let on_drop = OnDrop::new(|| Self::on_drop()); | 814 | let on_drop = OnDrop::new(|| Self::on_drop()); |
| 823 | 815 | ||
| 824 | let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, status.as_mut(), 64, 6); | 816 | let transfer = Self::prepare_datapath_read( |
| 817 | &self.config, | ||
| 818 | #[cfg(sdmmc_v1)] | ||
| 819 | &mut self.dma, | ||
| 820 | status.as_mut(), | ||
| 821 | 64, | ||
| 822 | 6, | ||
| 823 | ); | ||
| 825 | InterruptHandler::<T>::data_interrupts(true); | 824 | InterruptHandler::<T>::data_interrupts(true); |
| 826 | Self::cmd(Cmd::card_status(0), true)?; | 825 | Self::cmd(Cmd::card_status(0), true)?; |
| 827 | 826 | ||
| @@ -924,7 +923,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 924 | let regs = T::regs(); | 923 | let regs = T::regs(); |
| 925 | let on_drop = OnDrop::new(|| Self::on_drop()); | 924 | let on_drop = OnDrop::new(|| Self::on_drop()); |
| 926 | 925 | ||
| 927 | let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, scr, 8, 3); | 926 | let transfer = Self::prepare_datapath_read( |
| 927 | &self.config, | ||
| 928 | #[cfg(sdmmc_v1)] | ||
| 929 | &mut self.dma, | ||
| 930 | scr, | ||
| 931 | 8, | ||
| 932 | 3, | ||
| 933 | ); | ||
| 928 | InterruptHandler::<T>::data_interrupts(true); | 934 | InterruptHandler::<T>::data_interrupts(true); |
| 929 | Self::cmd(Cmd::cmd51(), true)?; | 935 | Self::cmd(Cmd::cmd51(), true)?; |
| 930 | 936 | ||
| @@ -1214,7 +1220,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 1214 | let regs = T::regs(); | 1220 | let regs = T::regs(); |
| 1215 | let on_drop = OnDrop::new(|| Self::on_drop()); | 1221 | let on_drop = OnDrop::new(|| Self::on_drop()); |
| 1216 | 1222 | ||
| 1217 | let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, buffer, 512, 9); | 1223 | let transfer = Self::prepare_datapath_read( |
| 1224 | &self.config, | ||
| 1225 | #[cfg(sdmmc_v1)] | ||
| 1226 | &mut self.dma, | ||
| 1227 | buffer, | ||
| 1228 | 512, | ||
| 1229 | 9, | ||
| 1230 | ); | ||
| 1218 | InterruptHandler::<T>::data_interrupts(true); | 1231 | InterruptHandler::<T>::data_interrupts(true); |
| 1219 | Self::cmd(Cmd::read_single_block(address), true)?; | 1232 | Self::cmd(Cmd::read_single_block(address), true)?; |
| 1220 | 1233 | ||
| @@ -1347,7 +1360,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 1347 | } | 1360 | } |
| 1348 | } | 1361 | } |
| 1349 | 1362 | ||
| 1350 | impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> { | 1363 | impl<'d, T: Instance> Drop for Sdmmc<'d, T> { |
| 1351 | fn drop(&mut self) { | 1364 | fn drop(&mut self) { |
| 1352 | T::Interrupt::disable(); | 1365 | T::Interrupt::disable(); |
| 1353 | Self::on_drop(); | 1366 | Self::on_drop(); |
| @@ -1484,15 +1497,6 @@ pin_trait!(D7Pin, Instance); | |||
| 1484 | #[cfg(sdmmc_v1)] | 1497 | #[cfg(sdmmc_v1)] |
| 1485 | dma_trait!(SdmmcDma, Instance); | 1498 | dma_trait!(SdmmcDma, Instance); |
| 1486 | 1499 | ||
| 1487 | /// DMA instance trait. | ||
| 1488 | /// | ||
| 1489 | /// This is only implemented for `NoDma`, since SDMMCv2 has DMA built-in, instead of | ||
| 1490 | /// using ST's system-wide DMA peripheral. | ||
| 1491 | #[cfg(sdmmc_v2)] | ||
| 1492 | pub trait SdmmcDma<T: Instance> {} | ||
| 1493 | #[cfg(sdmmc_v2)] | ||
| 1494 | impl<T: Instance> SdmmcDma<T> for NoDma {} | ||
| 1495 | |||
| 1496 | foreach_peripheral!( | 1500 | foreach_peripheral!( |
| 1497 | (sdmmc, $inst:ident) => { | 1501 | (sdmmc, $inst:ident) => { |
| 1498 | impl SealedInstance for peripherals::$inst { | 1502 | impl SealedInstance for peripherals::$inst { |
| @@ -1512,7 +1516,7 @@ foreach_peripheral!( | |||
| 1512 | }; | 1516 | }; |
| 1513 | ); | 1517 | ); |
| 1514 | 1518 | ||
| 1515 | impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> block_device_driver::BlockDevice<512> for Sdmmc<'d, T, Dma> { | 1519 | impl<'d, T: Instance> block_device_driver::BlockDevice<512> for Sdmmc<'d, T> { |
| 1516 | type Error = Error; | 1520 | type Error = Error; |
| 1517 | type Align = aligned::A4; | 1521 | type Align = aligned::A4; |
| 1518 | 1522 | ||
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index 44dda6a9e..a43da1b5a 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs | |||
| @@ -839,7 +839,7 @@ impl<'d> Spi<'d, Async> { | |||
| 839 | let rx_src = self.info.regs.rx_ptr(); | 839 | let rx_src = self.info.regs.rx_ptr(); |
| 840 | let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) }; | 840 | let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) }; |
| 841 | 841 | ||
| 842 | let tx_dst = self.info.regs.tx_ptr(); | 842 | let tx_dst: *mut W = self.info.regs.tx_ptr(); |
| 843 | let tx_f = unsafe { | 843 | let tx_f = unsafe { |
| 844 | self.tx_dma | 844 | self.tx_dma |
| 845 | .as_mut() | 845 | .as_mut() |
diff --git a/examples/stm32f4/src/bin/dac.rs b/examples/stm32f4/src/bin/dac.rs index dd2a45718..68fe6cabd 100644 --- a/examples/stm32f4/src/bin/dac.rs +++ b/examples/stm32f4/src/bin/dac.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::dac::{DacCh1, Value}; | 6 | use embassy_stm32::dac::{DacCh1, Value}; |
| 7 | use embassy_stm32::dma::NoDma; | ||
| 8 | use {defmt_rtt as _, panic_probe as _}; | 7 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 8 | ||
| 10 | #[embassy_executor::main] | 9 | #[embassy_executor::main] |
| @@ -12,7 +11,7 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 12 | let p = embassy_stm32::init(Default::default()); | 11 | let p = embassy_stm32::init(Default::default()); |
| 13 | info!("Hello World, dude!"); | 12 | info!("Hello World, dude!"); |
| 14 | 13 | ||
| 15 | let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); | 14 | let mut dac = DacCh1::new_blocking(p.DAC1, p.PA4); |
| 16 | 15 | ||
| 17 | loop { | 16 | loop { |
| 18 | for v in 0..=255 { | 17 | for v in 0..=255 { |
diff --git a/examples/stm32h7/src/bin/dac.rs b/examples/stm32h7/src/bin/dac.rs index a6f969aba..27df80336 100644 --- a/examples/stm32h7/src/bin/dac.rs +++ b/examples/stm32h7/src/bin/dac.rs | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | use cortex_m_rt::entry; | 4 | use cortex_m_rt::entry; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_stm32::dac::{DacCh1, Value}; | 6 | use embassy_stm32::dac::{DacCh1, Value}; |
| 7 | use embassy_stm32::dma::NoDma; | ||
| 8 | use embassy_stm32::Config; | 7 | use embassy_stm32::Config; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 9 | ||
| @@ -44,7 +43,7 @@ fn main() -> ! { | |||
| 44 | } | 43 | } |
| 45 | let p = embassy_stm32::init(config); | 44 | let p = embassy_stm32::init(config); |
| 46 | 45 | ||
| 47 | let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); | 46 | let mut dac = DacCh1::new_blocking(p.DAC1, p.PA4); |
| 48 | 47 | ||
| 49 | loop { | 48 | loop { |
| 50 | for v in 0..=255 { | 49 | for v in 0..=255 { |
diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs index 3a9887e3c..98c9f1e90 100644 --- a/examples/stm32h7/src/bin/dac_dma.rs +++ b/examples/stm32h7/src/bin/dac_dma.rs | |||
| @@ -4,8 +4,9 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; | 6 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; |
| 7 | use embassy_stm32::mode::Async; | ||
| 7 | use embassy_stm32::pac::timer::vals::Mms; | 8 | use embassy_stm32::pac::timer::vals::Mms; |
| 8 | use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; | 9 | use embassy_stm32::peripherals::{DAC1, TIM6, TIM7}; |
| 9 | use embassy_stm32::rcc::frequency; | 10 | use embassy_stm32::rcc::frequency; |
| 10 | use embassy_stm32::time::Hertz; | 11 | use embassy_stm32::time::Hertz; |
| 11 | use embassy_stm32::timer::low_level::Timer; | 12 | use embassy_stm32::timer::low_level::Timer; |
| @@ -56,7 +57,7 @@ async fn main(spawner: Spawner) { | |||
| 56 | } | 57 | } |
| 57 | 58 | ||
| 58 | #[embassy_executor::task] | 59 | #[embassy_executor::task] |
| 59 | async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | 60 | async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, Async>) { |
| 60 | let data: &[u8; 256] = &calculate_array::<256>(); | 61 | let data: &[u8; 256] = &calculate_array::<256>(); |
| 61 | 62 | ||
| 62 | info!("TIM6 frequency is {}", frequency::<TIM6>()); | 63 | info!("TIM6 frequency is {}", frequency::<TIM6>()); |
| @@ -99,7 +100,7 @@ async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | |||
| 99 | } | 100 | } |
| 100 | 101 | ||
| 101 | #[embassy_executor::task] | 102 | #[embassy_executor::task] |
| 102 | async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { | 103 | async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, Async>) { |
| 103 | let data: &[u8; 256] = &calculate_array::<256>(); | 104 | let data: &[u8; 256] = &calculate_array::<256>(); |
| 104 | 105 | ||
| 105 | info!("TIM7 frequency is {}", frequency::<TIM6>()); | 106 | info!("TIM7 frequency is {}", frequency::<TIM6>()); |
diff --git a/examples/stm32l4/src/bin/dac.rs b/examples/stm32l4/src/bin/dac.rs index fdbf1d374..50db0e082 100644 --- a/examples/stm32l4/src/bin/dac.rs +++ b/examples/stm32l4/src/bin/dac.rs | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::dac::{DacCh1, Value}; | 5 | use embassy_stm32::dac::{DacCh1, Value}; |
| 6 | use embassy_stm32::dma::NoDma; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | 6 | use {defmt_rtt as _, panic_probe as _}; |
| 8 | 7 | ||
| 9 | #[cortex_m_rt::entry] | 8 | #[cortex_m_rt::entry] |
| @@ -11,7 +10,7 @@ fn main() -> ! { | |||
| 11 | let p = embassy_stm32::init(Default::default()); | 10 | let p = embassy_stm32::init(Default::default()); |
| 12 | info!("Hello World!"); | 11 | info!("Hello World!"); |
| 13 | 12 | ||
| 14 | let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); | 13 | let mut dac = DacCh1::new_blocking(p.DAC1, p.PA4); |
| 15 | 14 | ||
| 16 | loop { | 15 | loop { |
| 17 | for v in 0..=255 { | 16 | for v in 0..=255 { |
diff --git a/examples/stm32l4/src/bin/dac_dma.rs b/examples/stm32l4/src/bin/dac_dma.rs index d01b016c0..6c9219080 100644 --- a/examples/stm32l4/src/bin/dac_dma.rs +++ b/examples/stm32l4/src/bin/dac_dma.rs | |||
| @@ -4,8 +4,9 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; | 6 | use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; |
| 7 | use embassy_stm32::mode::Async; | ||
| 7 | use embassy_stm32::pac::timer::vals::Mms; | 8 | use embassy_stm32::pac::timer::vals::Mms; |
| 8 | use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; | 9 | use embassy_stm32::peripherals::{DAC1, TIM6, TIM7}; |
| 9 | use embassy_stm32::rcc::frequency; | 10 | use embassy_stm32::rcc::frequency; |
| 10 | use embassy_stm32::time::Hertz; | 11 | use embassy_stm32::time::Hertz; |
| 11 | use embassy_stm32::timer::low_level::Timer; | 12 | use embassy_stm32::timer::low_level::Timer; |
| @@ -27,7 +28,7 @@ async fn main(spawner: Spawner) { | |||
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | #[embassy_executor::task] | 30 | #[embassy_executor::task] |
| 30 | async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | 31 | async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, Async>) { |
| 31 | let data: &[u8; 256] = &calculate_array::<256>(); | 32 | let data: &[u8; 256] = &calculate_array::<256>(); |
| 32 | 33 | ||
| 33 | info!("TIM6 frequency is {}", frequency::<TIM6>()); | 34 | info!("TIM6 frequency is {}", frequency::<TIM6>()); |
| @@ -70,7 +71,7 @@ async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { | |||
| 70 | } | 71 | } |
| 71 | 72 | ||
| 72 | #[embassy_executor::task] | 73 | #[embassy_executor::task] |
| 73 | async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { | 74 | async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, Async>) { |
| 74 | let data: &[u8; 256] = &calculate_array::<256>(); | 75 | let data: &[u8; 256] = &calculate_array::<256>(); |
| 75 | 76 | ||
| 76 | info!("TIM7 frequency is {}", frequency::<TIM7>()); | 77 | info!("TIM7 frequency is {}", frequency::<TIM7>()); |
diff --git a/examples/stm32u0/src/bin/dac.rs b/examples/stm32u0/src/bin/dac.rs index fdbf1d374..50db0e082 100644 --- a/examples/stm32u0/src/bin/dac.rs +++ b/examples/stm32u0/src/bin/dac.rs | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::dac::{DacCh1, Value}; | 5 | use embassy_stm32::dac::{DacCh1, Value}; |
| 6 | use embassy_stm32::dma::NoDma; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | 6 | use {defmt_rtt as _, panic_probe as _}; |
| 8 | 7 | ||
| 9 | #[cortex_m_rt::entry] | 8 | #[cortex_m_rt::entry] |
| @@ -11,7 +10,7 @@ fn main() -> ! { | |||
| 11 | let p = embassy_stm32::init(Default::default()); | 10 | let p = embassy_stm32::init(Default::default()); |
| 12 | info!("Hello World!"); | 11 | info!("Hello World!"); |
| 13 | 12 | ||
| 14 | let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4); | 13 | let mut dac = DacCh1::new_blocking(p.DAC1, p.PA4); |
| 15 | 14 | ||
| 16 | loop { | 15 | loop { |
| 17 | for v in 0..=255 { | 16 | for v in 0..=255 { |
diff --git a/tests/stm32/src/bin/dac.rs b/tests/stm32/src/bin/dac.rs index 88e661525..d34bbb255 100644 --- a/tests/stm32/src/bin/dac.rs +++ b/tests/stm32/src/bin/dac.rs | |||
| @@ -12,7 +12,6 @@ use defmt::assert; | |||
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_stm32::adc::Adc; | 13 | use embassy_stm32::adc::Adc; |
| 14 | use embassy_stm32::dac::{DacCh1, Value}; | 14 | use embassy_stm32::dac::{DacCh1, Value}; |
| 15 | use embassy_stm32::dma::NoDma; | ||
| 16 | use embassy_time::Timer; | 15 | use embassy_time::Timer; |
| 17 | use micromath::F32Ext; | 16 | use micromath::F32Ext; |
| 18 | use {defmt_rtt as _, panic_probe as _}; | 17 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -27,7 +26,7 @@ async fn main(_spawner: Spawner) { | |||
| 27 | let dac_pin = peri!(p, DAC_PIN); | 26 | let dac_pin = peri!(p, DAC_PIN); |
| 28 | let mut adc_pin = unsafe { core::ptr::read(&dac_pin) }; | 27 | let mut adc_pin = unsafe { core::ptr::read(&dac_pin) }; |
| 29 | 28 | ||
| 30 | let mut dac = DacCh1::new(dac, NoDma, dac_pin); | 29 | let mut dac = DacCh1::new_blocking(dac, dac_pin); |
| 31 | let mut adc = Adc::new(adc); | 30 | let mut adc = Adc::new(adc); |
| 32 | 31 | ||
| 33 | #[cfg(feature = "stm32h755zi")] | 32 | #[cfg(feature = "stm32h755zi")] |
diff --git a/tests/stm32/src/bin/dac_l1.rs b/tests/stm32/src/bin/dac_l1.rs index 925db617d..e6400f28e 100644 --- a/tests/stm32/src/bin/dac_l1.rs +++ b/tests/stm32/src/bin/dac_l1.rs | |||
| @@ -12,7 +12,6 @@ use defmt::assert; | |||
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_stm32::adc::Adc; | 13 | use embassy_stm32::adc::Adc; |
| 14 | use embassy_stm32::dac::{DacCh1, Value}; | 14 | use embassy_stm32::dac::{DacCh1, Value}; |
| 15 | use embassy_stm32::dma::NoDma; | ||
| 16 | use embassy_stm32::{bind_interrupts, peripherals}; | 15 | use embassy_stm32::{bind_interrupts, peripherals}; |
| 17 | use embassy_time::Timer; | 16 | use embassy_time::Timer; |
| 18 | use micromath::F32Ext; | 17 | use micromath::F32Ext; |
| @@ -32,7 +31,7 @@ async fn main(_spawner: Spawner) { | |||
| 32 | let dac_pin = peri!(p, DAC_PIN); | 31 | let dac_pin = peri!(p, DAC_PIN); |
| 33 | let mut adc_pin = unsafe { core::ptr::read(&dac_pin) }; | 32 | let mut adc_pin = unsafe { core::ptr::read(&dac_pin) }; |
| 34 | 33 | ||
| 35 | let mut dac = DacCh1::new(dac, NoDma, dac_pin); | 34 | let mut dac = DacCh1::new_blocking(dac, dac_pin); |
| 36 | let mut adc = Adc::new(adc, Irqs); | 35 | let mut adc = Adc::new(adc, Irqs); |
| 37 | 36 | ||
| 38 | #[cfg(feature = "stm32h755zi")] | 37 | #[cfg(feature = "stm32h755zi")] |
diff --git a/tests/stm32/src/bin/hash.rs b/tests/stm32/src/bin/hash.rs index bdb3c9a69..52b84a499 100644 --- a/tests/stm32/src/bin/hash.rs +++ b/tests/stm32/src/bin/hash.rs | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | mod common; | 6 | mod common; |
| 7 | use common::*; | 7 | use common::*; |
| 8 | use embassy_executor::Spawner; | 8 | use embassy_executor::Spawner; |
| 9 | use embassy_stm32::dma::NoDma; | ||
| 10 | use embassy_stm32::hash::*; | 9 | use embassy_stm32::hash::*; |
| 11 | use embassy_stm32::{bind_interrupts, hash, peripherals}; | 10 | use embassy_stm32::{bind_interrupts, hash, peripherals}; |
| 12 | use hmac::{Hmac, Mac}; | 11 | use hmac::{Hmac, Mac}; |
| @@ -36,7 +35,7 @@ bind_interrupts!(struct Irqs { | |||
| 36 | #[embassy_executor::main] | 35 | #[embassy_executor::main] |
| 37 | async fn main(_spawner: Spawner) { | 36 | async fn main(_spawner: Spawner) { |
| 38 | let p: embassy_stm32::Peripherals = init(); | 37 | let p: embassy_stm32::Peripherals = init(); |
| 39 | let mut hw_hasher = Hash::new(p.HASH, NoDma, Irqs); | 38 | let mut hw_hasher = Hash::new_blocking(p.HASH, Irqs); |
| 40 | 39 | ||
| 41 | let test_1: &[u8] = b"as;dfhaslfhas;oifvnasd;nifvnhasd;nifvhndlkfghsd;nvfnahssdfgsdafgsasdfasdfasdfasdfasdfghjklmnbvcalskdjghalskdjgfbaslkdjfgbalskdjgbalskdjbdfhsdfhsfghsfghfgh"; | 40 | let test_1: &[u8] = b"as;dfhaslfhas;oifvnasd;nifvnhasd;nifvhndlkfghsd;nvfnahssdfgsdafgsasdfasdfasdfasdfasdfghjklmnbvcalskdjghalskdjgfbaslkdjfgbalskdjgbalskdjbdfhsdfhsfghsfghfgh"; |
| 42 | let test_2: &[u8] = b"fdhalksdjfhlasdjkfhalskdjfhgal;skdjfgalskdhfjgalskdjfglafgadfgdfgdafgaadsfgfgdfgadrgsyfthxfgjfhklhjkfgukhulkvhlvhukgfhfsrghzdhxyfufynufyuszeradrtydyytserr"; | 41 | let test_2: &[u8] = b"fdhalksdjfhlasdjkfhalskdjfhgal;skdjfgalskdhfjgalskdjfglafgadfgdfgdafgaadsfgfgdfgadrgsyfthxfgjfhklhjkfgukhulkvhlvhukgfhfsrghzdhxyfufynufyuszeradrtydyytserr"; |
