Skip to content

Commit c65d457

Browse files
committed
Fixes, simpler dma example
- Use stack allocated buffers for dma example, - fix wait_for_transfer_complete/wait_for_half_transfer_complete - remove clock sync delays
1 parent f5cb2a7 commit c65d457

File tree

2 files changed

+53
-140
lines changed

2 files changed

+53
-140
lines changed

examples/dma.rs

Lines changed: 45 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
mod utilities;
66

7-
use core::mem::MaybeUninit;
8-
97
use cortex_m_rt::entry;
108
use cortex_m_semihosting::debug;
119
use stm32h5xx_hal::{
@@ -14,114 +12,6 @@ use stm32h5xx_hal::{
1412
prelude::*,
1513
};
1614

17-
static mut SOURCE_BYTES: MaybeUninit<[u8; 40]> = MaybeUninit::uninit();
18-
static mut DEST_BYTES: MaybeUninit<[u8; 40]> = MaybeUninit::zeroed();
19-
static mut DEST_HALF_WORDS: MaybeUninit<[u16; 20]> = MaybeUninit::uninit();
20-
static mut SOURCE_WORDS: MaybeUninit<[u32; 10]> = MaybeUninit::uninit();
21-
static mut DEST_WORDS: MaybeUninit<[u32; 10]> = MaybeUninit::uninit();
22-
23-
fn u8_to_u8_sequential() -> (&'static [u8; 40], &'static mut [u8; 40]) {
24-
let buf: &mut [MaybeUninit<u8>; 40] = unsafe {
25-
&mut *(core::ptr::addr_of_mut!(SOURCE_BYTES)
26-
as *mut [MaybeUninit<u8>; 40])
27-
};
28-
29-
for (i, value) in buf.iter_mut().enumerate() {
30-
unsafe {
31-
value.as_mut_ptr().write(i as u8);
32-
}
33-
}
34-
#[allow(static_mut_refs)] // TODO: Fix this
35-
let src = unsafe { SOURCE_BYTES.assume_init_ref() };
36-
37-
let dest =
38-
unsafe { (*core::ptr::addr_of_mut!(DEST_BYTES)).assume_init_mut() };
39-
40-
dest.fill(0);
41-
42-
(src, dest)
43-
}
44-
45-
fn u32_to_u32_transform() -> (&'static [u32; 10], &'static mut [u32; 10]) {
46-
let buf: &mut [MaybeUninit<u32>; 10] = unsafe {
47-
&mut *(core::ptr::addr_of_mut!(SOURCE_WORDS)
48-
as *mut [MaybeUninit<u32>; 10])
49-
};
50-
51-
buf.fill(MaybeUninit::new(0x12345678));
52-
53-
#[allow(static_mut_refs)] // TODO: Fix this
54-
let src = unsafe { SOURCE_WORDS.assume_init_ref() };
55-
56-
let dest =
57-
unsafe { (*core::ptr::addr_of_mut!(DEST_WORDS)).assume_init_mut() };
58-
59-
dest.fill(0);
60-
(src, dest)
61-
}
62-
63-
fn u32_to_u16_truncate() -> (&'static [u32; 10], &'static mut [u16; 20]) {
64-
let buf: &mut [MaybeUninit<u32>; 10] = unsafe {
65-
&mut *(core::ptr::addr_of_mut!(SOURCE_WORDS)
66-
as *mut [MaybeUninit<u32>; 10])
67-
};
68-
69-
buf.fill(MaybeUninit::new(0x12345678));
70-
71-
#[allow(static_mut_refs)] // TODO: Fix this
72-
let src = unsafe { SOURCE_WORDS.assume_init_ref() };
73-
74-
let dest = unsafe {
75-
(*core::ptr::addr_of_mut!(DEST_HALF_WORDS)).assume_init_mut()
76-
};
77-
78-
dest.fill(0);
79-
(src, dest)
80-
}
81-
82-
fn u32_to_u8_unpack() -> (&'static [u32; 10], &'static mut [u8; 40]) {
83-
let buf: &mut [MaybeUninit<u32>; 10] = unsafe {
84-
&mut *(core::ptr::addr_of_mut!(SOURCE_WORDS)
85-
as *mut [MaybeUninit<u32>; 10])
86-
};
87-
88-
buf.fill(MaybeUninit::new(0x12345678));
89-
90-
#[allow(static_mut_refs)] // TODO: Fix this
91-
let src = unsafe { SOURCE_WORDS.assume_init_ref() };
92-
93-
let dest =
94-
unsafe { (*core::ptr::addr_of_mut!(DEST_BYTES)).assume_init_mut() };
95-
96-
dest.fill(0);
97-
(src, dest)
98-
}
99-
100-
fn u8_to_u32_pack() -> (&'static [u8; 40], &'static mut [u32; 10]) {
101-
let buf: &mut [MaybeUninit<u8>; 40] = unsafe {
102-
&mut *(core::ptr::addr_of_mut!(SOURCE_BYTES)
103-
as *mut [MaybeUninit<u8>; 40])
104-
};
105-
106-
for chunk in buf.chunks_mut(4) {
107-
unsafe {
108-
chunk[0].as_mut_ptr().write(0x78);
109-
chunk[1].as_mut_ptr().write(0x56);
110-
chunk[2].as_mut_ptr().write(0x34);
111-
chunk[3].as_mut_ptr().write(0x12);
112-
}
113-
}
114-
115-
#[allow(static_mut_refs)] // TODO: Fix this
116-
let src = unsafe { SOURCE_BYTES.assume_init_ref() };
117-
118-
let dest =
119-
unsafe { (*core::ptr::addr_of_mut!(DEST_WORDS)).assume_init_mut() };
120-
121-
dest.fill(0);
122-
(src, dest)
123-
}
124-
12515
#[entry]
12616
fn main() -> ! {
12717
utilities::logger::init();
@@ -137,66 +27,85 @@ fn main() -> ! {
13727

13828
let channels = dp.GPDMA1.channels(ccdr.peripheral.GPDMA1);
13929

140-
let (source_buf, dest_buf) = u8_to_u8_sequential();
30+
// u8 to u8
31+
log::info!("u8 to u8 transfer");
32+
let src: [u8; 40] = core::array::from_fn(|i| i as u8);
33+
let dest = &mut [0u8; 40];
14134

14235
let channel = channels.0;
14336
let config = DmaConfig::new();
144-
let transfer =
145-
DmaTransfer::memory_to_memory(config, &channel, source_buf, dest_buf);
37+
let transfer = DmaTransfer::memory_to_memory(config, &channel, &src, dest);
14638
transfer.start().unwrap();
14739
transfer.wait_for_transfer_complete().unwrap();
148-
assert_eq!(source_buf, dest_buf);
40+
assert_eq!(src, *dest, "u8 to u8 transfer failed");
14941

150-
let (source_buf, dest_buf) = u32_to_u32_transform();
42+
// u32 to u32 with data transform
43+
log::info!("u32 to u32 with data transform");
44+
let src = [0x12345678u32; 10];
45+
let dest = &mut [0u32; 10];
15146
let config = DmaConfig::new().with_data_transform(
15247
DataTransform::builder()
15348
.swap_destination_half_words()
15449
.swap_destination_half_word_byte_order(),
15550
);
15651

157-
let transfer =
158-
DmaTransfer::memory_to_memory(config, &channel, source_buf, dest_buf);
52+
let transfer = DmaTransfer::memory_to_memory(config, &channel, &src, dest);
15953

16054
transfer.start().unwrap();
16155
transfer.wait_for_transfer_complete().unwrap();
162-
let expected = [0x78563412; 10];
163-
assert_eq!(expected, *dest_buf);
56+
assert_eq!(
57+
[0x78563412; 10], *dest,
58+
"u32 to u32 with data transform failed"
59+
);
16460

165-
let (source_buf, dest_buf) = u32_to_u16_truncate();
61+
// u32 to u16 with truncate
62+
log::info!("u32 to u16 with truncate");
63+
let src = [0x12345678u32; 10];
64+
let dest = &mut [0u16; 20];
16665
let config = DmaConfig::new().with_data_transform(
16766
DataTransform::builder().left_align_right_truncate(),
16867
);
169-
let transfer =
170-
DmaTransfer::memory_to_memory(config, &channel, source_buf, dest_buf);
68+
let transfer = DmaTransfer::memory_to_memory(config, &channel, &src, dest);
17169

17270
transfer.start().unwrap();
17371
transfer.wait_for_transfer_complete().unwrap();
174-
let expected = [0x1234; 10];
175-
assert_eq!(expected, (*dest_buf)[0..10]);
72+
assert_eq!(
73+
[0x1234; 10],
74+
(*dest)[0..10],
75+
"u32 to u16 with truncate failed"
76+
);
77+
assert_eq!([0; 10], (*dest)[10..20], "u32 to u16 with truncate failed");
17678

177-
let (source_buf, dest_buf) = u32_to_u8_unpack();
79+
// u32 to u8 with unpack
80+
log::info!("u32 to u8 with unpack");
81+
let src = [0x12345678u32; 10];
82+
let dest = &mut [0u8; 40];
17883
let config =
17984
DmaConfig::new().with_data_transform(DataTransform::builder().unpack());
180-
let transfer =
181-
DmaTransfer::memory_to_memory(config, &channel, source_buf, dest_buf);
85+
let transfer = DmaTransfer::memory_to_memory(config, &channel, &src, dest);
18286

18387
transfer.start().unwrap();
18488
transfer.wait_for_transfer_complete().unwrap();
18589
let expected = [0x78, 0x56, 0x34, 0x12];
186-
assert_eq!(expected, (*dest_buf)[0..4]);
187-
assert_eq!(expected, (*dest_buf)[36..40]);
188-
189-
let (source_buf, dest_buf) = u8_to_u32_pack();
90+
assert_eq!(expected, (*dest)[0..4], "u32 to u8 unpack failed");
91+
assert_eq!(expected, (*dest)[36..40], "u32 to u8 unpack failed");
92+
93+
// u8 to u32 with pack
94+
log::info!("u8 to u32 with pack");
95+
let mut src = [0u8; 40];
96+
let dest = &mut [0u32; 10];
97+
for chunk in src.chunks_mut(4) {
98+
chunk.copy_from_slice(&[0x78, 0x56, 0x34, 0x12]);
99+
}
190100
let config =
191101
DmaConfig::new().with_data_transform(DataTransform::builder().pack());
192-
let transfer =
193-
DmaTransfer::memory_to_memory(config, &channel, source_buf, dest_buf);
102+
let transfer = DmaTransfer::memory_to_memory(config, &channel, &src, dest);
194103

195104
transfer.start().unwrap();
196105
transfer.wait_for_transfer_complete().unwrap();
197-
let expected = [0x12345678; 10];
198-
assert_eq!(expected, (*dest_buf));
199-
assert_eq!(expected, (*dest_buf));
106+
assert_eq!([0x12345678; 10], (*dest), "u8 to u32 with pack failed");
107+
108+
log::info!("All tests passed!");
200109

201110
loop {
202111
debug::exit(debug::EXIT_SUCCESS)

src/gpdma/ch.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,6 @@ where
213213
.tof()
214214
.clear()
215215
});
216-
217-
interrupt_clear_clock_sync_delay!(self.sr());
218216
}
219217

220218
#[inline(always)]
@@ -235,8 +233,6 @@ where
235233
TransferEvent::TransferComplete => w.tcf().clear(),
236234
TransferEvent::HalfTransferComplete => w.htf().clear(),
237235
});
238-
239-
interrupt_clear_clock_sync_delay!(self.sr());
240236
}
241237
Ok(triggered)
242238
}
@@ -633,13 +629,21 @@ where
633629

634630
/// Blocks waiting for a transfer to complete. Reports any errors that occur during a transfer.
635631
fn wait_for_transfer_complete(&self) -> Result<(), Error> {
632+
if !self.is_running() {
633+
return Ok(());
634+
}
635+
636636
while !self.check_transfer_complete()? {}
637637
Ok(())
638638
}
639639

640640
/// Blocks waiting for a half transfer event to trigger. Reports any errors that occur during a
641641
/// transfer.
642642
fn wait_for_half_transfer_complete(&self) -> Result<(), Error> {
643+
if !self.is_running() {
644+
return Ok(());
645+
}
646+
643647
while !self.check_half_transfer_complete()? {}
644648
Ok(())
645649
}

0 commit comments

Comments
 (0)