Skip to content

Commit 100bf1b

Browse files
committed
Add free method, don't consume self in abort/wait_for_transfer_complete
1 parent 5b0d9be commit 100bf1b

File tree

2 files changed

+55
-105
lines changed

2 files changed

+55
-105
lines changed

examples/dma.rs

Lines changed: 26 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -7,52 +7,12 @@ 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};
1110
use stm32h5xx_hal::{
12-
gpdma::{config::transform::*, DmaConfig, DmaTransfer, Word},
11+
gpdma::{config::transform::*, DmaConfig, DmaTransfer},
1312
pac,
1413
prelude::*,
1514
};
1615

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-
5616
#[entry]
5717
fn main() -> ! {
5818
utilities::logger::init();
@@ -72,108 +32,90 @@ fn main() -> ! {
7232
let src =
7333
singleton!(: [u8; 40] = core::array::from_fn(|i| i as u8)).unwrap();
7434

75-
let src_buffer = Buffer::new(src);
7635
let dest = singleton!(: [u8; 40] = [0u8; 40]).unwrap();
77-
let mut dest_buffer = Buffer::new(dest);
7836

7937
let mut channel = channels.0;
8038
let config = DmaConfig::new();
81-
let mut transfer = DmaTransfer::memory_to_memory(
82-
config,
83-
&mut channel,
84-
&src_buffer,
85-
&mut dest_buffer,
86-
);
39+
let mut transfer =
40+
DmaTransfer::memory_to_memory(config, &mut channel, src, dest);
8741
transfer.start().unwrap();
8842
transfer.wait_for_transfer_complete().unwrap();
89-
assert_eq!(src_buffer.data, dest_buffer.data);
43+
let (src, dest) = transfer.free();
44+
assert_eq!(src, dest);
9045

9146
log::info!("u32 to u32 with data transform");
9247
let src = singleton!(: [u32; 10] = [0x12345678u32; 10]).unwrap();
9348
let dest = singleton!(: [u32; 10] = [0u32; 10]).unwrap();
94-
let mut dest_buffer = Buffer::new(dest);
9549

9650
let config = DmaConfig::new().with_data_transform(
9751
DataTransform::builder()
9852
.swap_destination_half_words()
9953
.swap_destination_half_word_byte_order(),
10054
);
10155

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

10959
transfer.start().unwrap();
11060
transfer.wait_for_transfer_complete().unwrap();
61+
let (_, dest) = transfer.free();
62+
11163
let expected = [0x78563412; 10];
112-
assert_eq!(expected, *dest_buffer.data);
64+
assert_eq!(expected, *dest);
11365

11466
log::info!("u32 to u16 with truncate");
11567
let src = singleton!(: [u32; 10] = [0x12345678u32; 10]).unwrap();
11668
let dest = singleton!(: [u16; 20] = [0u16; 20]).unwrap();
117-
let mut dest_buffer = Buffer::new(dest);
11869

11970
let config = DmaConfig::new().with_data_transform(
12071
DataTransform::builder().left_align_right_truncate(),
12172
);
122-
let mut transfer = DmaTransfer::memory_to_memory(
123-
config,
124-
&mut channel,
125-
src,
126-
&mut dest_buffer,
127-
);
73+
let mut transfer =
74+
DmaTransfer::memory_to_memory(config, &mut channel, src, dest);
12875

12976
transfer.start().unwrap();
13077
transfer.wait_for_transfer_complete().unwrap();
78+
let (_, dest) = transfer.free();
79+
13180
let expected = [0x1234; 10];
132-
assert_eq!(expected, (*dest_buffer.data)[0..10]);
81+
assert_eq!(expected, (*dest)[0..10]);
13382

13483
log::info!("u32 to u8 with unpack");
13584
let src = singleton!(: [u32; 10] = [0x12345678u32; 10]).unwrap();
13685
let dest = singleton!(: [u8; 40] = [0u8; 40]).unwrap();
137-
let mut dest_buffer = Buffer::new(dest);
13886

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

14892
transfer.start().unwrap();
14993
transfer.wait_for_transfer_complete().unwrap();
94+
let (_, dest) = transfer.free();
15095
let expected = [0x78, 0x56, 0x34, 0x12];
151-
assert_eq!(expected, (*dest_buffer.data)[0..4]);
152-
assert_eq!(expected, (*dest_buffer.data)[36..40]);
96+
assert_eq!(expected, (*dest)[0..4]);
97+
assert_eq!(expected, (*dest)[36..40]);
15398

15499
log::info!("u8 to u32 with pack");
155100
let src = singleton!(: [u8; 40] = [0u8; 40]).unwrap();
156101
let dest = singleton!(: [u32; 10] = [0u32; 10]).unwrap();
157-
let mut dest_buffer = Buffer::new(dest);
158102

159103
for chunk in src.chunks_mut(4) {
160104
chunk.copy_from_slice(&[0x78, 0x56, 0x34, 0x12]);
161105
}
162106

163107
let config =
164108
DmaConfig::new().with_data_transform(DataTransform::builder().pack());
165-
let mut transfer = DmaTransfer::memory_to_memory(
166-
config,
167-
&mut channel,
168-
src,
169-
&mut dest_buffer,
170-
);
109+
let mut transfer =
110+
DmaTransfer::memory_to_memory(config, &mut channel, src, dest);
171111

172112
transfer.start().unwrap();
173113
transfer.wait_for_transfer_complete().unwrap();
114+
let (_, dest) = transfer.free();
115+
174116
let expected = [0x12345678; 10];
175-
assert_eq!(expected, (*dest_buffer.data));
176-
assert_eq!(expected, (*dest_buffer.data));
117+
assert_eq!(expected, *dest);
118+
assert_eq!(expected, *dest);
177119

178120
log::info!("All tests passed!");
179121
loop {

src/gpdma.rs

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ use crate::{
8282
};
8383
use core::{
8484
marker::PhantomData,
85+
mem,
8586
ops::Deref,
8687
sync::atomic::{fence, Ordering},
8788
};
@@ -252,12 +253,8 @@ where
252253
D: WriteBuffer<Word: Word>,
253254
{
254255
channel: &'a mut CH,
255-
256-
// Hold onto source and destination for the lifetime of the transfer to ensure that any
257-
// user implementations of ReadBuffer and WriteBuffer that are themselves references are held
258-
// for the duration of the transfer and so prevent access to the underlying data.
259-
_source: S,
260-
_destination: D,
256+
source: S,
257+
destination: D,
261258
}
262259

263260
impl<'a, CH, S, D> DmaTransfer<'a, CH, S, D>
@@ -289,8 +286,8 @@ where
289286

290287
Self {
291288
channel,
292-
_source: source,
293-
_destination: destination,
289+
source,
290+
destination,
294291
}
295292
}
296293

@@ -501,13 +498,12 @@ where
501498

502499
/// Blocks waiting for a transfer to complete. Returns an error if one occurred during the
503500
/// transfer.
504-
pub fn wait_for_transfer_complete(self) -> Result<(), Error> {
501+
pub fn wait_for_transfer_complete(&mut self) -> Result<(), Error> {
505502
let result = self.channel.wait_for_transfer_complete();
506503
// Preserve the instruction and bus sequence of the preceding operation and
507504
// the subsequent buffer access.
508505
fence(Ordering::SeqCst);
509506

510-
core::mem::forget(self); // Prevents self from being dropped and attempting to abort
511507
result
512508
}
513509

@@ -529,8 +525,28 @@ where
529525
}
530526

531527
/// Abort a transaction and wait for it to suspend the transfer before resetting the channel
532-
pub fn abort(self) {
533-
// Allow Drop implementation to handle transfer abortion
528+
pub fn abort(&mut self) {
529+
if self.is_running() {
530+
self.channel.abort();
531+
}
532+
533+
self.disable_interrupts();
534+
535+
// Preserve the instruction and bus sequence of the preceding operation and
536+
// the subsequent buffer access.
537+
fence(Ordering::SeqCst);
538+
}
539+
540+
pub fn free(mut self) -> (S, D) {
541+
self.abort();
542+
let (src, dest) = unsafe {
543+
(
544+
core::ptr::read(&self.source),
545+
core::ptr::read(&self.destination),
546+
)
547+
};
548+
mem::forget(self);
549+
(src, dest)
534550
}
535551
}
536552

@@ -541,14 +557,6 @@ where
541557
D: WriteBuffer<Word: Word>,
542558
{
543559
fn drop(&mut self) {
544-
if self.is_running() {
545-
self.channel.abort();
546-
}
547-
548-
self.disable_interrupts();
549-
550-
// Preserve the instruction and bus sequence of the preceding operation and
551-
// the subsequent buffer access.
552-
fence(Ordering::SeqCst);
560+
self.abort();
553561
}
554562
}

0 commit comments

Comments
 (0)