Skip to content

Commit 6f3aa81

Browse files
committed
use ReadBuffer, WriteBuffer to force immovable buffers; fix example
1 parent 5d9fc22 commit 6f3aa81

File tree

3 files changed

+207
-89
lines changed

3 files changed

+207
-89
lines changed

examples/dma.rs

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

55
mod utilities;
66

7+
use core::mem::MaybeUninit;
8+
79
use cortex_m_rt::entry;
810
use cortex_m_semihosting::debug;
911
use stm32h5xx_hal::{
@@ -12,6 +14,114 @@ use stm32h5xx_hal::{
1214
prelude::*,
1315
};
1416

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+
15125
#[entry]
16126
fn main() -> ! {
17127
utilities::logger::init();
@@ -27,85 +137,72 @@ fn main() -> ! {
27137

28138
let channels = dp.GPDMA1.channels(ccdr.peripheral.GPDMA1);
29139

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];
140+
let (source_buf, dest_buf) = u8_to_u8_sequential();
141+
let source_copy = unsafe { &*(source_buf.as_ptr() as *const [u8; 40]) };
142+
let dest_copy = unsafe { &*(dest_buf.as_ptr() as *const [u8; 40]) };
34143

35144
let channel = channels.0;
36145
let config = DmaConfig::new();
37-
let transfer = DmaTransfer::memory_to_memory(config, &channel, &src, dest);
146+
let transfer =
147+
DmaTransfer::memory_to_memory(config, &channel, source_buf, dest_buf);
38148
transfer.start().unwrap();
39149
transfer.wait_for_transfer_complete().unwrap();
40-
assert_eq!(src, *dest, "u8 to u8 transfer failed");
150+
assert_eq!(source_copy, dest_copy);
41151

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];
152+
let (source_buf, dest_buf) = u32_to_u32_transform();
153+
let dest_copy = unsafe { &*(dest_buf.as_ptr() as *const [u32; 10]) };
46154
let config = DmaConfig::new().with_data_transform(
47155
DataTransform::builder()
48156
.swap_destination_half_words()
49157
.swap_destination_half_word_byte_order(),
50158
);
51159

52-
let transfer = DmaTransfer::memory_to_memory(config, &channel, &src, dest);
160+
let transfer =
161+
DmaTransfer::memory_to_memory(config, &channel, source_buf, dest_buf);
53162

54163
transfer.start().unwrap();
55164
transfer.wait_for_transfer_complete().unwrap();
56-
assert_eq!(
57-
[0x78563412; 10], *dest,
58-
"u32 to u32 with data transform failed"
59-
);
165+
let expected = [0x78563412; 10];
166+
assert_eq!(expected, *dest_copy);
60167

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];
168+
let (source_buf, dest_buf) = u32_to_u16_truncate();
169+
let dest_copy = unsafe { &*(dest_buf.as_ptr() as *const [u16; 20]) };
65170
let config = DmaConfig::new().with_data_transform(
66171
DataTransform::builder().left_align_right_truncate(),
67172
);
68-
let transfer = DmaTransfer::memory_to_memory(config, &channel, &src, dest);
173+
let transfer =
174+
DmaTransfer::memory_to_memory(config, &channel, source_buf, dest_buf);
69175

70176
transfer.start().unwrap();
71177
transfer.wait_for_transfer_complete().unwrap();
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");
178+
let expected = [0x1234; 10];
179+
assert_eq!(expected, (*dest_copy)[0..10]);
78180

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];
181+
let (source_buf, dest_buf) = u32_to_u8_unpack();
182+
let dest_copy = unsafe { &*(dest_buf.as_ptr() as *const [u8; 40]) };
83183
let config =
84184
DmaConfig::new().with_data_transform(DataTransform::builder().unpack());
85-
let transfer = DmaTransfer::memory_to_memory(config, &channel, &src, dest);
185+
let transfer =
186+
DmaTransfer::memory_to_memory(config, &channel, source_buf, dest_buf);
86187

87188
transfer.start().unwrap();
88189
transfer.wait_for_transfer_complete().unwrap();
89190
let expected = [0x78, 0x56, 0x34, 0x12];
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-
}
191+
assert_eq!(expected, (*dest_copy)[0..4]);
192+
assert_eq!(expected, (*dest_copy)[36..40]);
193+
194+
let (source_buf, dest_buf) = u8_to_u32_pack();
195+
let dest_copy = unsafe { &*(dest_buf.as_ptr() as *const [u32; 10]) };
100196
let config =
101197
DmaConfig::new().with_data_transform(DataTransform::builder().pack());
102-
let transfer = DmaTransfer::memory_to_memory(config, &channel, &src, dest);
198+
let transfer =
199+
DmaTransfer::memory_to_memory(config, &channel, source_buf, dest_buf);
103200

104201
transfer.start().unwrap();
105202
transfer.wait_for_transfer_complete().unwrap();
106-
assert_eq!([0x12345678; 10], (*dest), "u8 to u32 with pack failed");
107-
108-
log::info!("All tests passed!");
203+
let expected = [0x12345678; 10];
204+
assert_eq!(expected, (*dest_copy));
205+
assert_eq!(expected, (*dest_copy));
109206

110207
loop {
111208
debug::exit(debug::EXIT_SUCCESS)

src/gpdma.rs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -278,22 +278,22 @@ impl<'a, CH: DmaChannel> DmaTransfer<'a, CH> {
278278
/// Create a new memory-to-memory transfer with the channel, source and destination buffers
279279
/// provided.
280280
pub fn memory_to_memory<S, D>(
281-
config: DmaConfig<MemoryToMemory, S, D>,
281+
config: DmaConfig<MemoryToMemory, S::Word, D::Word>,
282282
channel: &'a CH,
283-
source: &'a [S],
284-
destination: &'a mut [D],
283+
source: S,
284+
mut destination: D,
285285
) -> Self
286286
where
287-
S: Word,
288-
D: Word,
287+
S: ReadBuffer<Word: Word>,
288+
D: WriteBuffer<Word: Word>,
289289
{
290290
let src_width = core::mem::size_of::<S>();
291291
let dest_width = core::mem::size_of::<D>();
292292

293-
let src_ptr = source.as_ptr();
294-
let src_size = core::mem::size_of_val(source);
295-
let dest_ptr = destination.as_mut_ptr();
296-
let dest_size = core::mem::size_of_val(destination);
293+
let (src_ptr, src_words) = unsafe { source.read_buffer() };
294+
let src_size = core::mem::size_of::<S::Word>() * src_words;
295+
let (dest_ptr, dest_words) = unsafe { destination.write_buffer() };
296+
let dest_size = core::mem::size_of::<D::Word>() * dest_words;
297297

298298
// Size must be aligned with destination width if source width is greater than destination
299299
// width and packing mode is used, therefore the maximum size must be dictated by
@@ -312,28 +312,28 @@ impl<'a, CH: DmaChannel> DmaTransfer<'a, CH> {
312312

313313
// We also need to ensure that the destination
314314

315-
Self::new::<S, D, MemoryToMemory>(
315+
Self::new::<S::Word, D::Word, MemoryToMemory>(
316316
channel, config, src_ptr, dest_ptr, size,
317317
)
318318
}
319319

320320
/// Create a new memory-to-peripheral transfer with the channel, source buffer and destination
321321
/// peripheral provided.
322322
pub fn memory_to_peripheral<S, D>(
323-
config: DmaConfig<MemoryToPeripheral, S, D::Word>,
323+
config: DmaConfig<MemoryToPeripheral, S::Word, D::Word>,
324324
channel: &'a CH,
325-
source: &'a [S],
325+
source: S,
326326
mut destination: D,
327327
) -> Self
328328
where
329-
S: Word,
329+
S: ReadBuffer<Word: Word>,
330330
D: WriteBuffer<Word: Word>,
331331
{
332-
let src_ptr = source.as_ptr();
333-
let src_size = core::mem::size_of_val(source);
332+
let (src_ptr, src_words) = unsafe { source.read_buffer() };
333+
let src_size = core::mem::size_of::<S::Word>() * src_words;
334334
let (dest_ptr, _) = unsafe { destination.write_buffer() };
335335

336-
Self::new::<S, D::Word, MemoryToPeripheral>(
336+
Self::new::<S::Word, D::Word, MemoryToPeripheral>(
337337
channel, config, src_ptr, dest_ptr, src_size,
338338
)
339339
.apply_hardware_request_config(config)
@@ -342,21 +342,21 @@ impl<'a, CH: DmaChannel> DmaTransfer<'a, CH> {
342342
/// Create a new peripheral-to-memory transfer with the channel, source peripheral and
343343
/// destination buffer provided.
344344
pub fn peripheral_to_memory<S, D>(
345-
config: DmaConfig<PeripheralToMemory, S::Word, D>,
345+
config: DmaConfig<PeripheralToMemory, S::Word, D::Word>,
346346
channel: &'a CH,
347347
source: S,
348-
destination: &'a mut [D],
348+
mut destination: D,
349349
) -> Self
350350
where
351351
S: ReadBuffer<Word: Word>,
352-
D: Word,
352+
D: WriteBuffer<Word: Word>,
353353
{
354354
let (src_ptr, _) = unsafe { source.read_buffer() };
355355

356-
let dest_ptr = destination.as_mut_ptr();
357-
let dest_size = core::mem::size_of_val(destination);
356+
let (dest_ptr, dest_words) = unsafe { destination.write_buffer() };
357+
let dest_size = core::mem::size_of::<D::Word>() * dest_words;
358358

359-
Self::new::<S::Word, D, PeripheralToMemory>(
359+
Self::new::<S::Word, D::Word, PeripheralToMemory>(
360360
channel, config, src_ptr, dest_ptr, dest_size,
361361
)
362362
.apply_hardware_request_config(config)

0 commit comments

Comments
 (0)