Skip to content

Commit 5c587f3

Browse files
committed
Hold onto source/destination; Remove UB from example
1 parent 9bbaca7 commit 5c587f3

File tree

3 files changed

+172
-96
lines changed

3 files changed

+172
-96
lines changed

examples/dma.rs

Lines changed: 86 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,52 @@ mod utilities;
77
use cortex_m::singleton;
88
use cortex_m_rt::entry;
99
use cortex_m_semihosting::debug;
10+
use embedded_dma::{ReadBuffer, WriteBuffer};
1011
use stm32h5xx_hal::{
11-
gpdma::{config::transform::*, DmaConfig, DmaTransfer},
12+
gpdma::{config::transform::*, DmaConfig, DmaTransfer, Word},
1213
pac,
1314
prelude::*,
1415
};
1516

17+
// Buffer is used to manage a reference to a static buffer returned by the cortex_m::singleton!
18+
// macro and which can be with the DmaTransfer API (which requires passing ReadBuffer and
19+
// WriteBuffer implementations by value) and then used to access the buffer after the transfer has
20+
// completed.
21+
struct Buffer<T: Word + 'static, const N: usize> {
22+
data: &'static mut [T; N],
23+
}
24+
25+
impl<T, const N: usize> Buffer<T, N>
26+
where
27+
T: Word + 'static,
28+
{
29+
fn new(data: &'static mut [T; N]) -> Self {
30+
Self { data }
31+
}
32+
}
33+
34+
unsafe impl<T, const N: usize> ReadBuffer for &Buffer<T, N>
35+
where
36+
T: Word + 'static,
37+
{
38+
type Word = T;
39+
40+
unsafe fn read_buffer(&self) -> (*const Self::Word, usize) {
41+
(self.data.as_ptr(), N)
42+
}
43+
}
44+
45+
unsafe impl<T, const N: usize> WriteBuffer for &mut Buffer<T, N>
46+
where
47+
T: Word + 'static,
48+
{
49+
type Word = T;
50+
51+
unsafe fn write_buffer(&mut self) -> (*mut Self::Word, usize) {
52+
(self.data.as_mut_ptr(), N)
53+
}
54+
}
55+
1656
#[entry]
1757
fn main() -> ! {
1858
utilities::logger::init();
@@ -31,90 +71,109 @@ fn main() -> ! {
3171
log::info!("u8 to u8");
3272
let src =
3373
singleton!(: [u8; 40] = core::array::from_fn(|i| i as u8)).unwrap();
74+
75+
let src_buffer = Buffer::new(src);
3476
let dest = singleton!(: [u8; 40] = [0u8; 40]).unwrap();
35-
let source_copy = unsafe { &*(src.as_ptr() as *const [u8; 40]) };
36-
let dest_copy = unsafe { &*(dest.as_ptr() as *const [u8; 40]) };
77+
let mut dest_buffer = Buffer::new(dest);
3778

3879
let mut channel = channels.0;
3980
let config = DmaConfig::new();
40-
let mut transfer =
41-
DmaTransfer::memory_to_memory(config, &mut channel, src, dest);
81+
let mut transfer = DmaTransfer::memory_to_memory(
82+
config,
83+
&mut channel,
84+
&src_buffer,
85+
&mut dest_buffer,
86+
);
4287
transfer.start().unwrap();
4388
transfer.wait_for_transfer_complete().unwrap();
44-
assert_eq!(source_copy, dest_copy);
89+
assert_eq!(src_buffer.data, dest_buffer.data);
4590

4691
log::info!("u32 to u32 with data transform");
4792
let src = singleton!(: [u32; 10] = [0x12345678u32; 10]).unwrap();
4893
let dest = singleton!(: [u32; 10] = [0u32; 10]).unwrap();
49-
50-
let dest_copy = unsafe { &*(dest.as_ptr() as *const [u32; 10]) };
94+
let mut dest_buffer = Buffer::new(dest);
5195

5296
let config = DmaConfig::new().with_data_transform(
5397
DataTransform::builder()
5498
.swap_destination_half_words()
5599
.swap_destination_half_word_byte_order(),
56100
);
57101

58-
let mut transfer =
59-
DmaTransfer::memory_to_memory(config, &mut channel, src, dest);
102+
let mut transfer = DmaTransfer::memory_to_memory(
103+
config,
104+
&mut channel,
105+
src,
106+
&mut dest_buffer,
107+
);
60108

61109
transfer.start().unwrap();
62110
transfer.wait_for_transfer_complete().unwrap();
63111
let expected = [0x78563412; 10];
64-
assert_eq!(expected, *dest_copy);
112+
assert_eq!(expected, *dest_buffer.data);
65113

66114
log::info!("u32 to u16 with truncate");
67115
let src = singleton!(: [u32; 10] = [0x12345678u32; 10]).unwrap();
68116
let dest = singleton!(: [u16; 20] = [0u16; 20]).unwrap();
69-
let dest_copy = unsafe { &*(dest.as_ptr() as *const [u16; 20]) };
117+
let mut dest_buffer = Buffer::new(dest);
118+
70119
let config = DmaConfig::new().with_data_transform(
71120
DataTransform::builder().left_align_right_truncate(),
72121
);
73-
let mut transfer =
74-
DmaTransfer::memory_to_memory(config, &mut channel, src, dest);
122+
let mut transfer = DmaTransfer::memory_to_memory(
123+
config,
124+
&mut channel,
125+
src,
126+
&mut dest_buffer,
127+
);
75128

76129
transfer.start().unwrap();
77130
transfer.wait_for_transfer_complete().unwrap();
78131
let expected = [0x1234; 10];
79-
assert_eq!(expected, (*dest_copy)[0..10]);
132+
assert_eq!(expected, (*dest_buffer.data)[0..10]);
80133

81134
log::info!("u32 to u8 with unpack");
82135
let src = singleton!(: [u32; 10] = [0x12345678u32; 10]).unwrap();
83136
let dest = singleton!(: [u8; 40] = [0u8; 40]).unwrap();
84-
85-
let dest_copy = unsafe { &*(dest.as_ptr() as *const [u8; 40]) };
137+
let mut dest_buffer = Buffer::new(dest);
86138

87139
let config =
88140
DmaConfig::new().with_data_transform(DataTransform::builder().unpack());
89-
let mut transfer =
90-
DmaTransfer::memory_to_memory(config, &mut channel, src, dest);
141+
let mut transfer = DmaTransfer::memory_to_memory(
142+
config,
143+
&mut channel,
144+
src,
145+
&mut dest_buffer,
146+
);
91147

92148
transfer.start().unwrap();
93149
transfer.wait_for_transfer_complete().unwrap();
94150
let expected = [0x78, 0x56, 0x34, 0x12];
95-
assert_eq!(expected, (*dest_copy)[0..4]);
96-
assert_eq!(expected, (*dest_copy)[36..40]);
151+
assert_eq!(expected, (*dest_buffer.data)[0..4]);
152+
assert_eq!(expected, (*dest_buffer.data)[36..40]);
97153

98154
log::info!("u8 to u32 with pack");
99155
let src = singleton!(: [u8; 40] = [0u8; 40]).unwrap();
100156
let dest = singleton!(: [u32; 10] = [0u32; 10]).unwrap();
157+
let mut dest_buffer = Buffer::new(dest);
101158

102159
for chunk in src.chunks_mut(4) {
103160
chunk.copy_from_slice(&[0x78, 0x56, 0x34, 0x12]);
104161
}
105162

106-
let dest_copy = unsafe { &*(dest.as_ptr() as *const [u32; 10]) };
107-
108163
let config =
109164
DmaConfig::new().with_data_transform(DataTransform::builder().pack());
110-
let mut transfer =
111-
DmaTransfer::memory_to_memory(config, &mut channel, src, dest);
165+
let mut transfer = DmaTransfer::memory_to_memory(
166+
config,
167+
&mut channel,
168+
src,
169+
&mut dest_buffer,
170+
);
112171

113172
transfer.start().unwrap();
114173
transfer.wait_for_transfer_complete().unwrap();
115174
let expected = [0x12345678; 10];
116-
assert_eq!(expected, (*dest_copy));
117-
assert_eq!(expected, (*dest_copy));
175+
assert_eq!(expected, (*dest_buffer.data));
176+
assert_eq!(expected, (*dest_buffer.data));
118177

119178
log::info!("All tests passed!");
120179
loop {

0 commit comments

Comments
 (0)