aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-03-25 21:31:14 +0000
committerGitHub <[email protected]>2025-03-25 21:31:14 +0000
commit4f250f399513319220853bfa0e13b9a588de8000 (patch)
treea24154b18817b34cbb80b3b253fe3b7a1bc7cb6f
parent17cce79807ff978270b96ba081a4ee2ed5604dcd (diff)
parenta592acb8068011787453944963b384fd43a52e65 (diff)
Merge pull request #4005 from embassy-rs/no-nodma
stm32: remove DMA generic params, remove NoDma.
-rw-r--r--embassy-stm32/build.rs17
-rw-r--r--embassy-stm32/src/cryp/mod.rs877
-rw-r--r--embassy-stm32/src/dac/mod.rs400
-rw-r--r--embassy-stm32/src/dma/mod.rs11
-rw-r--r--embassy-stm32/src/dma/util.rs6
-rw-r--r--embassy-stm32/src/hash/mod.rs286
-rw-r--r--embassy-stm32/src/macros.rs12
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs104
-rw-r--r--embassy-stm32/src/spi/mod.rs2
-rw-r--r--examples/stm32f4/src/bin/dac.rs3
-rw-r--r--examples/stm32h7/src/bin/dac.rs3
-rw-r--r--examples/stm32h7/src/bin/dac_dma.rs7
-rw-r--r--examples/stm32l4/src/bin/dac.rs3
-rw-r--r--examples/stm32l4/src/bin/dac_dma.rs7
-rw-r--r--examples/stm32u0/src/bin/dac.rs3
-rw-r--r--tests/stm32/src/bin/dac.rs3
-rw-r--r--tests/stm32/src/bin/dac_l1.rs3
-rw-r--r--tests/stm32/src/bin/hash.rs3
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;
7use embassy_hal_internal::{into_ref, PeripheralRef}; 7use embassy_hal_internal::{into_ref, PeripheralRef};
8use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9 9
10use crate::dma::{NoDma, Transfer, TransferOptions}; 10use crate::dma::{ChannelAndRequest, TransferOptions};
11use crate::interrupt::typelevel::Interrupt; 11use crate::interrupt::typelevel::Interrupt;
12use crate::mode::{Async, Blocking, Mode};
12use crate::{interrupt, pac, peripherals, rcc, Peripheral}; 13use crate::{interrupt, pac, peripherals, rcc, Peripheral};
13 14
14const DES_BLOCK_SIZE: usize = 8; // 64 bits 15const 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
1010pub struct Cryp<'d, T: Instance, DmaIn = NoDma, DmaOut = NoDma> { 990pub 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
1016impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> { 997impl<'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
1019impl<'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
1461impl<'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
4use core::marker::PhantomData; 4use core::marker::PhantomData;
5 5
6use embassy_hal_internal::{into_ref, PeripheralRef}; 6use embassy_hal_internal::into_ref;
7 7
8use crate::dma::NoDma; 8use crate::dma::ChannelAndRequest;
9use 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))]
10use crate::pac::dac; 11use crate::pac::dac;
11use crate::rcc::{self, RccPeripheral}; 12use 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.
103pub struct DacChannel<'d, T: Instance, const N: u8, DMA = NoDma> { 104pub 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.
110pub type DacCh1<'d, T, DMA = NoDma> = DacChannel<'d, T, 1, DMA>; 111pub type DacCh1<'d, T, M> = DacChannel<'d, T, Ch1, M>;
111/// DAC channel 2 type alias. 112/// DAC channel 2 type alias.
112pub type DacCh2<'d, T, DMA = NoDma> = DacChannel<'d, T, 2, DMA>; 113pub type DacCh2<'d, T, M> = DacChannel<'d, T, Ch2, M>;
113
114impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> {
115 const IDX: usize = (N - 1) as usize;
116 114
115impl<'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
198impl<'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
234impl<'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
282macro_rules! impl_dma_methods { 363impl<'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
354impl_dma_methods!(1, DacDma1);
355impl_dma_methods!(2, DacDma2);
356
357impl<'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/// ```
373pub struct Dac<'d, T: Instance, DMACh1 = NoDma, DMACh2 = NoDma> { 379pub 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
378impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { 384impl<'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 } 446impl<'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
496impl<'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)]
516pub trait Instance: SealedInstance + RccPeripheral + 'static {} 575pub trait Instance: SealedInstance + RccPeripheral + 'static {}
517dma_trait!(DacDma1, Instance);
518dma_trait!(DacDma2, Instance);
519 576
520/// Marks a pin that can be used with the DAC 577/// Channel 1 marker type.
521pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {} 578pub enum Ch1 {}
579/// Channel 2 marker type.
580pub enum Ch2 {}
581
582trait SealedChannel {
583 const IDX: usize;
584}
585/// DAC channel trait.
586#[allow(private_bounds)]
587pub trait Channel: SealedChannel {}
588
589impl SealedChannel for Ch1 {
590 const IDX: usize = 0;
591}
592impl SealedChannel for Ch2 {
593 const IDX: usize = 1;
594}
595impl Channel for Ch1 {}
596impl Channel for Ch2 {}
597
598dma_trait!(Dma, Instance, Channel);
599pin_trait!(DacPin, Instance, Channel);
522 600
523foreach_peripheral!( 601foreach_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
535macro_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 {}
108const CHANNEL_COUNT: usize = crate::_generated::DMA_CHANNELS.len(); 108const CHANNEL_COUNT: usize = crate::_generated::DMA_CHANNELS.len();
109static STATE: [ChannelState; CHANNEL_COUNT] = [ChannelState::NEW; CHANNEL_COUNT]; 109static 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.
118pub struct NoDma;
119
120impl_peripheral!(NoDma);
121
122// safety: must be called only once at startup 111// safety: must be called only once at startup
123pub(crate) unsafe fn init( 112pub(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};
12use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
13use stm32_metapac::hash::regs::*; 13use stm32_metapac::hash::regs::*;
14 14
15use crate::dma::NoDma;
16#[cfg(hash_v2)] 15#[cfg(hash_v2)]
17use crate::dma::Transfer; 16use crate::dma::ChannelAndRequest;
18use crate::interrupt::typelevel::Interrupt; 17use crate::interrupt::typelevel::Interrupt;
18#[cfg(hash_v2)]
19use crate::mode::Async;
20use crate::mode::{Blocking, Mode};
19use crate::peripherals::HASH; 21use crate::peripherals::HASH;
20use crate::{interrupt, pac, peripherals, rcc, Peripheral}; 22use crate::{interrupt, pac, peripherals, rcc, Peripheral};
21 23
@@ -116,24 +118,26 @@ pub struct Context<'c> {
116type HmacKey<'k> = Option<&'k [u8]>; 118type HmacKey<'k> = Option<&'k [u8]>;
117 119
118/// HASH driver. 120/// HASH driver.
119pub struct Hash<'d, T: Instance, D = NoDma> { 121pub 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
125impl<'d, T: Instance, D> Hash<'d, T, D> { 128impl<'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
150impl<'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)]
396impl<'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
570trait SealedInstance { 580trait 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)]
89macro_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
88macro_rules! new_dma { 100macro_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};
12use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
13use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; 13use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR};
14 14
15use crate::dma::NoDma; 15#[cfg(sdmmc_v1)]
16use crate::dma::ChannelAndRequest;
16#[cfg(gpio_v2)] 17#[cfg(gpio_v2)]
17use crate::gpio::Pull; 18use crate::gpio::Pull;
18use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; 19use 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
304pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> { 305pub 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
334const DATA_AF: AfType = CMD_AF; 335const DATA_AF: AfType = CMD_AF;
335 336
336#[cfg(sdmmc_v1)] 337#[cfg(sdmmc_v1)]
337impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { 338impl<'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)]
408impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { 409impl<'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
476impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { 475impl<'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
1350impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> { 1363impl<'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)]
1485dma_trait!(SdmmcDma, Instance); 1498dma_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)]
1492pub trait SdmmcDma<T: Instance> {}
1493#[cfg(sdmmc_v2)]
1494impl<T: Instance> SdmmcDma<T> for NoDma {}
1495
1496foreach_peripheral!( 1500foreach_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
1515impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> block_device_driver::BlockDevice<512> for Sdmmc<'d, T, Dma> { 1519impl<'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 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::dac::{DacCh1, Value}; 6use embassy_stm32::dac::{DacCh1, Value};
7use embassy_stm32::dma::NoDma;
8use {defmt_rtt as _, panic_probe as _}; 7use {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 @@
4use cortex_m_rt::entry; 4use cortex_m_rt::entry;
5use defmt::*; 5use defmt::*;
6use embassy_stm32::dac::{DacCh1, Value}; 6use embassy_stm32::dac::{DacCh1, Value};
7use embassy_stm32::dma::NoDma;
8use embassy_stm32::Config; 7use embassy_stm32::Config;
9use {defmt_rtt as _, panic_probe as _}; 8use {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 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; 6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray};
7use embassy_stm32::mode::Async;
7use embassy_stm32::pac::timer::vals::Mms; 8use embassy_stm32::pac::timer::vals::Mms;
8use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; 9use embassy_stm32::peripherals::{DAC1, TIM6, TIM7};
9use embassy_stm32::rcc::frequency; 10use embassy_stm32::rcc::frequency;
10use embassy_stm32::time::Hertz; 11use embassy_stm32::time::Hertz;
11use embassy_stm32::timer::low_level::Timer; 12use 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]
59async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { 60async 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]
102async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { 103async 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
4use defmt::*; 4use defmt::*;
5use embassy_stm32::dac::{DacCh1, Value}; 5use embassy_stm32::dac::{DacCh1, Value};
6use embassy_stm32::dma::NoDma;
7use {defmt_rtt as _, panic_probe as _}; 6use {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 @@
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; 6use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray};
7use embassy_stm32::mode::Async;
7use embassy_stm32::pac::timer::vals::Mms; 8use embassy_stm32::pac::timer::vals::Mms;
8use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; 9use embassy_stm32::peripherals::{DAC1, TIM6, TIM7};
9use embassy_stm32::rcc::frequency; 10use embassy_stm32::rcc::frequency;
10use embassy_stm32::time::Hertz; 11use embassy_stm32::time::Hertz;
11use embassy_stm32::timer::low_level::Timer; 12use 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]
30async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { 31async 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]
73async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { 74async 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
4use defmt::*; 4use defmt::*;
5use embassy_stm32::dac::{DacCh1, Value}; 5use embassy_stm32::dac::{DacCh1, Value};
6use embassy_stm32::dma::NoDma;
7use {defmt_rtt as _, panic_probe as _}; 6use {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;
12use embassy_executor::Spawner; 12use embassy_executor::Spawner;
13use embassy_stm32::adc::Adc; 13use embassy_stm32::adc::Adc;
14use embassy_stm32::dac::{DacCh1, Value}; 14use embassy_stm32::dac::{DacCh1, Value};
15use embassy_stm32::dma::NoDma;
16use embassy_time::Timer; 15use embassy_time::Timer;
17use micromath::F32Ext; 16use micromath::F32Ext;
18use {defmt_rtt as _, panic_probe as _}; 17use {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;
12use embassy_executor::Spawner; 12use embassy_executor::Spawner;
13use embassy_stm32::adc::Adc; 13use embassy_stm32::adc::Adc;
14use embassy_stm32::dac::{DacCh1, Value}; 14use embassy_stm32::dac::{DacCh1, Value};
15use embassy_stm32::dma::NoDma;
16use embassy_stm32::{bind_interrupts, peripherals}; 15use embassy_stm32::{bind_interrupts, peripherals};
17use embassy_time::Timer; 16use embassy_time::Timer;
18use micromath::F32Ext; 17use 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 @@
6mod common; 6mod common;
7use common::*; 7use common::*;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::dma::NoDma;
10use embassy_stm32::hash::*; 9use embassy_stm32::hash::*;
11use embassy_stm32::{bind_interrupts, hash, peripherals}; 10use embassy_stm32::{bind_interrupts, hash, peripherals};
12use hmac::{Hmac, Mac}; 11use hmac::{Hmac, Mac};
@@ -36,7 +35,7 @@ bind_interrupts!(struct Irqs {
36#[embassy_executor::main] 35#[embassy_executor::main]
37async fn main(_spawner: Spawner) { 36async 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";