aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-06-30 00:18:44 +0200
committerDario Nieuwenhuis <[email protected]>2025-07-04 00:23:22 +0200
commit84cc949df649c9b3625a65c2cc14e09155deeede (patch)
tree5db9214aa93aea446355eb500860ecc089559f66
parent00b2567fbf6b264a77dbe63ca2424939957f3128 (diff)
stm32/dma: fix packing/unpacking not working.
-rw-r--r--embassy-stm32/src/cryp/mod.rs13
-rw-r--r--embassy-stm32/src/dma/dma_bdma.rs63
-rw-r--r--embassy-stm32/src/dma/gpdma.rs12
-rw-r--r--embassy-stm32/src/dma/util.rs6
-rw-r--r--embassy-stm32/src/spi/mod.rs2
-rw-r--r--examples/stm32f7/src/bin/cryp.rs4
-rw-r--r--tests/stm32/src/bin/cryp.rs2
7 files changed, 57 insertions, 45 deletions
diff --git a/embassy-stm32/src/cryp/mod.rs b/embassy-stm32/src/cryp/mod.rs
index fba3c0fd7..35d9f8cce 100644
--- a/embassy-stm32/src/cryp/mod.rs
+++ b/embassy-stm32/src/cryp/mod.rs
@@ -2,7 +2,6 @@
2#[cfg(any(cryp_v2, cryp_v3, cryp_v4))] 2#[cfg(any(cryp_v2, cryp_v3, cryp_v4))]
3use core::cmp::min; 3use core::cmp::min;
4use core::marker::PhantomData; 4use core::marker::PhantomData;
5use core::ptr;
6 5
7use embassy_hal_internal::{Peri, PeripheralType}; 6use embassy_hal_internal::{Peri, PeripheralType};
8use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
@@ -1814,14 +1813,12 @@ impl<'d, T: Instance> Cryp<'d, T, Async> {
1814 assert_eq!(blocks.len() % block_size, 0); 1813 assert_eq!(blocks.len() % block_size, 0);
1815 // Configure DMA to transfer input to crypto core. 1814 // Configure DMA to transfer input to crypto core.
1816 let dst_ptr: *mut u32 = T::regs().din().as_ptr(); 1815 let dst_ptr: *mut u32 = T::regs().din().as_ptr();
1817 let num_words = blocks.len() / 4;
1818 let src_ptr: *const [u8] = ptr::slice_from_raw_parts(blocks.as_ptr().cast(), num_words);
1819 let options = TransferOptions { 1816 let options = TransferOptions {
1820 #[cfg(not(gpdma))] 1817 #[cfg(not(gpdma))]
1821 priority: crate::dma::Priority::High, 1818 priority: crate::dma::Priority::High,
1822 ..Default::default() 1819 ..Default::default()
1823 }; 1820 };
1824 let dma_transfer = unsafe { dma.write_raw(src_ptr, dst_ptr, options) }; 1821 let dma_transfer = unsafe { dma.write_raw(blocks, dst_ptr, options) };
1825 T::regs().dmacr().modify(|w| w.set_dien(true)); 1822 T::regs().dmacr().modify(|w| w.set_dien(true));
1826 // Wait for the transfer to complete. 1823 // Wait for the transfer to complete.
1827 dma_transfer.await; 1824 dma_transfer.await;
@@ -1836,14 +1833,12 @@ impl<'d, T: Instance> Cryp<'d, T, Async> {
1836 assert_eq!((blocks.len() * 4) % block_size, 0); 1833 assert_eq!((blocks.len() * 4) % block_size, 0);
1837 // Configure DMA to transfer input to crypto core. 1834 // Configure DMA to transfer input to crypto core.
1838 let dst_ptr: *mut u32 = T::regs().din().as_ptr(); 1835 let dst_ptr: *mut u32 = T::regs().din().as_ptr();
1839 let num_words = blocks.len();
1840 let src_ptr: *const [u32] = ptr::slice_from_raw_parts(blocks.as_ptr().cast(), num_words);
1841 let options = TransferOptions { 1836 let options = TransferOptions {
1842 #[cfg(not(gpdma))] 1837 #[cfg(not(gpdma))]
1843 priority: crate::dma::Priority::High, 1838 priority: crate::dma::Priority::High,
1844 ..Default::default() 1839 ..Default::default()
1845 }; 1840 };
1846 let dma_transfer = unsafe { dma.write_raw(src_ptr, dst_ptr, options) }; 1841 let dma_transfer = unsafe { dma.write_raw(blocks, dst_ptr, options) };
1847 T::regs().dmacr().modify(|w| w.set_dien(true)); 1842 T::regs().dmacr().modify(|w| w.set_dien(true));
1848 // Wait for the transfer to complete. 1843 // Wait for the transfer to complete.
1849 dma_transfer.await; 1844 dma_transfer.await;
@@ -1857,14 +1852,12 @@ impl<'d, T: Instance> Cryp<'d, T, Async> {
1857 assert_eq!(blocks.len() % block_size, 0); 1852 assert_eq!(blocks.len() % block_size, 0);
1858 // Configure DMA to get output from crypto core. 1853 // Configure DMA to get output from crypto core.
1859 let src_ptr = T::regs().dout().as_ptr(); 1854 let src_ptr = T::regs().dout().as_ptr();
1860 let num_words = blocks.len() / 4;
1861 let dst_ptr = ptr::slice_from_raw_parts_mut(blocks.as_mut_ptr().cast(), num_words);
1862 let options = TransferOptions { 1855 let options = TransferOptions {
1863 #[cfg(not(gpdma))] 1856 #[cfg(not(gpdma))]
1864 priority: crate::dma::Priority::VeryHigh, 1857 priority: crate::dma::Priority::VeryHigh,
1865 ..Default::default() 1858 ..Default::default()
1866 }; 1859 };
1867 let dma_transfer = unsafe { dma.read_raw(src_ptr, dst_ptr, options) }; 1860 let dma_transfer = unsafe { dma.read_raw(src_ptr, blocks, options) };
1868 T::regs().dmacr().modify(|w| w.set_doen(true)); 1861 T::regs().dmacr().modify(|w| w.set_doen(true));
1869 // Wait for the transfer to complete. 1862 // Wait for the transfer to complete.
1870 dma_transfer.await; 1863 dma_transfer.await;
diff --git a/embassy-stm32/src/dma/dma_bdma.rs b/embassy-stm32/src/dma/dma_bdma.rs
index caf135989..464823bfc 100644
--- a/embassy-stm32/src/dma/dma_bdma.rs
+++ b/embassy-stm32/src/dma/dma_bdma.rs
@@ -341,7 +341,7 @@ impl AnyChannel {
341 mem_len: usize, 341 mem_len: usize,
342 incr_mem: bool, 342 incr_mem: bool,
343 mem_size: WordSize, 343 mem_size: WordSize,
344 peripheral_size: WordSize, 344 peri_size: WordSize,
345 options: TransferOptions, 345 options: TransferOptions,
346 ) { 346 ) {
347 // "Preceding reads and writes cannot be moved past subsequent writes." 347 // "Preceding reads and writes cannot be moved past subsequent writes."
@@ -357,8 +357,6 @@ impl AnyChannel {
357 #[cfg(dmamux)] 357 #[cfg(dmamux)]
358 super::dmamux::configure_dmamux(&info.dmamux, _request); 358 super::dmamux::configure_dmamux(&info.dmamux, _request);
359 359
360 assert!(mem_len > 0 && mem_len <= 0xFFFF);
361
362 match self.info().dma { 360 match self.info().dma {
363 #[cfg(dma)] 361 #[cfg(dma)]
364 DmaInfo::Dma(r) => { 362 DmaInfo::Dma(r) => {
@@ -368,14 +366,39 @@ impl AnyChannel {
368 state.complete_count.store(0, Ordering::Release); 366 state.complete_count.store(0, Ordering::Release);
369 self.clear_irqs(); 367 self.clear_irqs();
370 368
369 // NDTR is the number of transfers in the *peripheral* word size.
370 // ex: if mem_size=1, peri_size=4 and ndtr=3 it'll do 12 mem transfers, 3 peri transfers.
371 let ndtr = match (mem_size, peri_size) {
372 (WordSize::FourBytes, WordSize::OneByte) => mem_len * 4,
373 (WordSize::FourBytes, WordSize::TwoBytes) | (WordSize::TwoBytes, WordSize::OneByte) => mem_len * 2,
374 (WordSize::FourBytes, WordSize::FourBytes)
375 | (WordSize::TwoBytes, WordSize::TwoBytes)
376 | (WordSize::OneByte, WordSize::OneByte) => mem_len,
377 (WordSize::TwoBytes, WordSize::FourBytes) | (WordSize::OneByte, WordSize::TwoBytes) => {
378 assert!(mem_len % 2 == 0);
379 mem_len / 2
380 }
381 (WordSize::OneByte, WordSize::FourBytes) => {
382 assert!(mem_len % 4 == 0);
383 mem_len / 4
384 }
385 };
386
387 assert!(ndtr > 0 && ndtr <= 0xFFFF);
388
371 ch.par().write_value(peri_addr as u32); 389 ch.par().write_value(peri_addr as u32);
372 ch.m0ar().write_value(mem_addr as u32); 390 ch.m0ar().write_value(mem_addr as u32);
373 ch.ndtr().write_value(pac::dma::regs::Ndtr(mem_len as _)); 391 ch.ndtr().write_value(pac::dma::regs::Ndtr(ndtr as _));
374 ch.fcr().write(|w| { 392 ch.fcr().write(|w| {
375 if let Some(fth) = options.fifo_threshold { 393 if let Some(fth) = options.fifo_threshold {
376 // FIFO mode 394 // FIFO mode
377 w.set_dmdis(pac::dma::vals::Dmdis::DISABLED); 395 w.set_dmdis(pac::dma::vals::Dmdis::DISABLED);
378 w.set_fth(fth.into()); 396 w.set_fth(fth.into());
397 } else if mem_size != peri_size {
398 // force FIFO mode if msize != psize
399 // packing/unpacking doesn't work in direct mode.
400 w.set_dmdis(pac::dma::vals::Dmdis::DISABLED);
401 w.set_fth(FifoThreshold::Half.into());
379 } else { 402 } else {
380 // Direct mode 403 // Direct mode
381 w.set_dmdis(pac::dma::vals::Dmdis::ENABLED); 404 w.set_dmdis(pac::dma::vals::Dmdis::ENABLED);
@@ -384,7 +407,7 @@ impl AnyChannel {
384 ch.cr().write(|w| { 407 ch.cr().write(|w| {
385 w.set_dir(dir.into()); 408 w.set_dir(dir.into());
386 w.set_msize(mem_size.into()); 409 w.set_msize(mem_size.into());
387 w.set_psize(peripheral_size.into()); 410 w.set_psize(peri_size.into());
388 w.set_pl(options.priority.into()); 411 w.set_pl(options.priority.into());
389 w.set_minc(incr_mem); 412 w.set_minc(incr_mem);
390 w.set_pinc(false); 413 w.set_pinc(false);
@@ -404,6 +427,8 @@ impl AnyChannel {
404 } 427 }
405 #[cfg(bdma)] 428 #[cfg(bdma)]
406 DmaInfo::Bdma(r) => { 429 DmaInfo::Bdma(r) => {
430 assert!(mem_len > 0 && mem_len <= 0xFFFF);
431
407 #[cfg(bdma_v2)] 432 #[cfg(bdma_v2)]
408 critical_section::with(|_| r.cselr().modify(|w| w.set_cs(info.num, _request))); 433 critical_section::with(|_| r.cselr().modify(|w| w.set_cs(info.num, _request)));
409 434
@@ -417,7 +442,7 @@ impl AnyChannel {
417 ch.mar().write_value(mem_addr as u32); 442 ch.mar().write_value(mem_addr as u32);
418 ch.ndtr().write(|w| w.set_ndt(mem_len as u16)); 443 ch.ndtr().write(|w| w.set_ndt(mem_len as u16));
419 ch.cr().write(|w| { 444 ch.cr().write(|w| {
420 w.set_psize(peripheral_size.into()); 445 w.set_psize(peri_size.into());
421 w.set_msize(mem_size.into()); 446 w.set_msize(mem_size.into());
422 w.set_minc(incr_mem); 447 w.set_minc(incr_mem);
423 w.set_dir(dir.into()); 448 w.set_dir(dir.into());
@@ -587,11 +612,11 @@ impl<'a> Transfer<'a> {
587 } 612 }
588 613
589 /// Create a new read DMA transfer (peripheral to memory), using raw pointers. 614 /// Create a new read DMA transfer (peripheral to memory), using raw pointers.
590 pub unsafe fn new_read_raw<W: Word>( 615 pub unsafe fn new_read_raw<MW: Word, PW: Word>(
591 channel: Peri<'a, impl Channel>, 616 channel: Peri<'a, impl Channel>,
592 request: Request, 617 request: Request,
593 peri_addr: *mut W, 618 peri_addr: *mut PW,
594 buf: *mut [W], 619 buf: *mut [MW],
595 options: TransferOptions, 620 options: TransferOptions,
596 ) -> Self { 621 ) -> Self {
597 Self::new_inner( 622 Self::new_inner(
@@ -599,11 +624,11 @@ impl<'a> Transfer<'a> {
599 request, 624 request,
600 Dir::PeripheralToMemory, 625 Dir::PeripheralToMemory,
601 peri_addr as *const u32, 626 peri_addr as *const u32,
602 buf as *mut W as *mut u32, 627 buf as *mut MW as *mut u32,
603 buf.len(), 628 buf.len(),
604 true, 629 true,
605 W::size(), 630 MW::size(),
606 W::size(), 631 PW::size(),
607 options, 632 options,
608 ) 633 )
609 } 634 }
@@ -672,22 +697,14 @@ impl<'a> Transfer<'a> {
672 mem_addr: *mut u32, 697 mem_addr: *mut u32,
673 mem_len: usize, 698 mem_len: usize,
674 incr_mem: bool, 699 incr_mem: bool,
675 data_size: WordSize, 700 mem_size: WordSize,
676 peripheral_size: WordSize, 701 peri_size: WordSize,
677 options: TransferOptions, 702 options: TransferOptions,
678 ) -> Self { 703 ) -> Self {
679 assert!(mem_len > 0 && mem_len <= 0xFFFF); 704 assert!(mem_len > 0 && mem_len <= 0xFFFF);
680 705
681 channel.configure( 706 channel.configure(
682 _request, 707 _request, dir, peri_addr, mem_addr, mem_len, incr_mem, mem_size, peri_size, options,
683 dir,
684 peri_addr,
685 mem_addr,
686 mem_len,
687 incr_mem,
688 data_size,
689 peripheral_size,
690 options,
691 ); 708 );
692 channel.start(); 709 channel.start();
693 Self { channel } 710 Self { channel }
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs
index ade70fb55..151e4ab9f 100644
--- a/embassy-stm32/src/dma/gpdma.rs
+++ b/embassy-stm32/src/dma/gpdma.rs
@@ -125,11 +125,11 @@ impl<'a> Transfer<'a> {
125 } 125 }
126 126
127 /// Create a new read DMA transfer (peripheral to memory), using raw pointers. 127 /// Create a new read DMA transfer (peripheral to memory), using raw pointers.
128 pub unsafe fn new_read_raw<W: Word>( 128 pub unsafe fn new_read_raw<MW: Word, PW: Word>(
129 channel: Peri<'a, impl Channel>, 129 channel: Peri<'a, impl Channel>,
130 request: Request, 130 request: Request,
131 peri_addr: *mut W, 131 peri_addr: *mut PW,
132 buf: *mut [W], 132 buf: *mut [MW],
133 options: TransferOptions, 133 options: TransferOptions,
134 ) -> Self { 134 ) -> Self {
135 Self::new_inner( 135 Self::new_inner(
@@ -137,11 +137,11 @@ impl<'a> Transfer<'a> {
137 request, 137 request,
138 Dir::PeripheralToMemory, 138 Dir::PeripheralToMemory,
139 peri_addr as *const u32, 139 peri_addr as *const u32,
140 buf as *mut W as *mut u32, 140 buf as *mut MW as *mut u32,
141 buf.len(), 141 buf.len(),
142 true, 142 true,
143 W::size(), 143 PW::size(),
144 W::size(), 144 MW::size(),
145 options, 145 options,
146 ) 146 )
147 } 147 }
diff --git a/embassy-stm32/src/dma/util.rs b/embassy-stm32/src/dma/util.rs
index 8bf89e2fe..3245887c1 100644
--- a/embassy-stm32/src/dma/util.rs
+++ b/embassy-stm32/src/dma/util.rs
@@ -20,10 +20,10 @@ impl<'d> ChannelAndRequest<'d> {
20 Transfer::new_read(self.channel.reborrow(), self.request, peri_addr, buf, options) 20 Transfer::new_read(self.channel.reborrow(), self.request, peri_addr, buf, options)
21 } 21 }
22 22
23 pub unsafe fn read_raw<'a, W: Word>( 23 pub unsafe fn read_raw<'a, MW: Word, PW: Word>(
24 &'a mut self, 24 &'a mut self,
25 peri_addr: *mut W, 25 peri_addr: *mut PW,
26 buf: *mut [W], 26 buf: *mut [MW],
27 options: TransferOptions, 27 options: TransferOptions,
28 ) -> Transfer<'a> { 28 ) -> Transfer<'a> {
29 Transfer::new_read_raw(self.channel.reborrow(), self.request, peri_addr, buf, options) 29 Transfer::new_read_raw(self.channel.reborrow(), self.request, peri_addr, buf, options)
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index 9e2ba093a..c8d83f07e 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -843,7 +843,7 @@ impl<'d> Spi<'d, Async> {
843 843
844 set_rxdmaen(self.info.regs, true); 844 set_rxdmaen(self.info.regs, true);
845 845
846 let rx_src = self.info.regs.rx_ptr(); 846 let rx_src = self.info.regs.rx_ptr::<W>();
847 let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) }; 847 let rx_f = unsafe { self.rx_dma.as_mut().unwrap().read_raw(rx_src, read, Default::default()) };
848 848
849 let tx_dst: *mut W = self.info.regs.tx_ptr(); 849 let tx_dst: *mut W = self.info.regs.tx_ptr();
diff --git a/examples/stm32f7/src/bin/cryp.rs b/examples/stm32f7/src/bin/cryp.rs
index 235853cb9..a31e9b4f2 100644
--- a/examples/stm32f7/src/bin/cryp.rs
+++ b/examples/stm32f7/src/bin/cryp.rs
@@ -68,7 +68,9 @@ async fn main(_spawner: Spawner) -> ! {
68 ); 68 );
69 69
70 // Decrypt in software using AES-GCM 128-bit 70 // Decrypt in software using AES-GCM 128-bit
71 let _ = cipher.decrypt_in_place(&iv.into(), aad.into(), &mut payload_vec); 71 cipher
72 .decrypt_in_place(&iv.into(), aad.into(), &mut payload_vec)
73 .unwrap();
72 74
73 let sw_end_time = Instant::now(); 75 let sw_end_time = Instant::now();
74 let sw_execution_time = sw_end_time - sw_start_time; 76 let sw_execution_time = sw_end_time - sw_start_time;
diff --git a/tests/stm32/src/bin/cryp.rs b/tests/stm32/src/bin/cryp.rs
index 028775ac8..f54c99cc3 100644
--- a/tests/stm32/src/bin/cryp.rs
+++ b/tests/stm32/src/bin/cryp.rs
@@ -72,7 +72,7 @@ async fn main(_spawner: Spawner) {
72 defmt::assert!(encrypt_tag == payload_vec[ciphertext.len()..ciphertext.len() + encrypt_tag.len()]); 72 defmt::assert!(encrypt_tag == payload_vec[ciphertext.len()..ciphertext.len() + encrypt_tag.len()]);
73 73
74 // Decrypt in software using AES-GCM 128-bit 74 // Decrypt in software using AES-GCM 128-bit
75 let _ = cipher.decrypt_in_place(&iv.into(), &aad, &mut payload_vec); 75 cipher.decrypt_in_place(&iv.into(), &aad, &mut payload_vec).unwrap();
76 76
77 info!("Test OK"); 77 info!("Test OK");
78 cortex_m::asm::bkpt(); 78 cortex_m::asm::bkpt();