aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/dma
diff options
context:
space:
mode:
authorAlexandros Liarokapis <[email protected]>2024-10-01 17:59:04 +0300
committerAlexandros Liarokapis <[email protected]>2024-10-15 12:29:12 +0300
commitf0d2ebdc7ead41307155b083790b8450ca2b7eac (patch)
tree3f976a73e34f81818126476b2dc896c750000a6b /embassy-stm32/src/dma
parentc991ddb76662cc7da5e847f33c1a446f17822887 (diff)
stm32: fix ringbugger overrun errors due to bad dma wrap-around behavior
Diffstat (limited to 'embassy-stm32/src/dma')
-rw-r--r--embassy-stm32/src/dma/dma_bdma.rs30
-rw-r--r--embassy-stm32/src/dma/ringbuffer/mod.rs67
-rw-r--r--embassy-stm32/src/dma/ringbuffer/tests/mod.rs83
3 files changed, 65 insertions, 115 deletions
diff --git a/embassy-stm32/src/dma/dma_bdma.rs b/embassy-stm32/src/dma/dma_bdma.rs
index 59ad4d988..3f047a9a4 100644
--- a/embassy-stm32/src/dma/dma_bdma.rs
+++ b/embassy-stm32/src/dma/dma_bdma.rs
@@ -6,7 +6,7 @@ use core::task::{Context, Poll, Waker};
6use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; 6use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
7use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8 8
9use super::ringbuffer::{DmaCtrl, OverrunError, ReadableDmaRingBuffer, WritableDmaRingBuffer}; 9use super::ringbuffer::{DmaCtrl, Error, ReadableDmaRingBuffer, WritableDmaRingBuffer};
10use super::word::{Word, WordSize}; 10use super::word::{Word, WordSize};
11use super::{AnyChannel, Channel, Dir, Request, STATE}; 11use super::{AnyChannel, Channel, Dir, Request, STATE};
12use crate::interrupt::typelevel::Interrupt; 12use crate::interrupt::typelevel::Interrupt;
@@ -299,7 +299,6 @@ impl AnyChannel {
299 } else { 299 } else {
300 return; 300 return;
301 } 301 }
302
303 state.waker.wake(); 302 state.waker.wake();
304 } 303 }
305 #[cfg(bdma)] 304 #[cfg(bdma)]
@@ -828,7 +827,8 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> {
828 /// 827 ///
829 /// You must call this after creating it for it to work. 828 /// You must call this after creating it for it to work.
830 pub fn start(&mut self) { 829 pub fn start(&mut self) {
831 self.channel.start() 830 self.channel.start();
831 self.clear();
832 } 832 }
833 833
834 /// Clear all data in the ring buffer. 834 /// Clear all data in the ring buffer.
@@ -840,15 +840,15 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> {
840 /// Return a tuple of the length read and the length remaining in the buffer 840 /// Return a tuple of the length read and the length remaining in the buffer
841 /// If not all of the elements were read, then there will be some elements in the buffer remaining 841 /// If not all of the elements were read, then there will be some elements in the buffer remaining
842 /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read 842 /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
843 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller. 843 /// Error is returned if the portion to be read was overwritten by the DMA controller.
844 pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { 844 pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), Error> {
845 self.ringbuf.read(&mut DmaCtrlImpl(self.channel.reborrow()), buf) 845 self.ringbuf.read(&mut DmaCtrlImpl(self.channel.reborrow()), buf)
846 } 846 }
847 847
848 /// Read an exact number of elements from the ringbuffer. 848 /// Read an exact number of elements from the ringbuffer.
849 /// 849 ///
850 /// Returns the remaining number of elements available for immediate reading. 850 /// Returns the remaining number of elements available for immediate reading.
851 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller. 851 /// Error is returned if the portion to be read was overwritten by the DMA controller.
852 /// 852 ///
853 /// Async/Wake Behavior: 853 /// Async/Wake Behavior:
854 /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point, 854 /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point,
@@ -856,12 +856,17 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> {
856 /// ring buffer was created with a buffer of size 'N': 856 /// ring buffer was created with a buffer of size 'N':
857 /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source. 857 /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source.
858 /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning. 858 /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning.
859 pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result<usize, OverrunError> { 859 pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result<usize, Error> {
860 self.ringbuf 860 self.ringbuf
861 .read_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) 861 .read_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer)
862 .await 862 .await
863 } 863 }
864 864
865 /// The current length of the ringbuffer
866 pub fn len(&mut self) -> Result<usize, Error> {
867 Ok(self.ringbuf.len(&mut DmaCtrlImpl(self.channel.reborrow()))?)
868 }
869
865 /// The capacity of the ringbuffer 870 /// The capacity of the ringbuffer
866 pub const fn capacity(&self) -> usize { 871 pub const fn capacity(&self) -> usize {
867 self.ringbuf.cap() 872 self.ringbuf.cap()
@@ -986,23 +991,28 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> {
986 /// Write elements directly to the raw buffer. 991 /// Write elements directly to the raw buffer.
987 /// This can be used to fill the buffer before starting the DMA transfer. 992 /// This can be used to fill the buffer before starting the DMA transfer.
988 #[allow(dead_code)] 993 #[allow(dead_code)]
989 pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> { 994 pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), Error> {
990 self.ringbuf.write_immediate(buf) 995 self.ringbuf.write_immediate(buf)
991 } 996 }
992 997
993 /// Write elements from the ring buffer 998 /// Write elements from the ring buffer
994 /// Return a tuple of the length written and the length remaining in the buffer 999 /// Return a tuple of the length written and the length remaining in the buffer
995 pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> { 1000 pub fn write(&mut self, buf: &[W]) -> Result<(usize, usize), Error> {
996 self.ringbuf.write(&mut DmaCtrlImpl(self.channel.reborrow()), buf) 1001 self.ringbuf.write(&mut DmaCtrlImpl(self.channel.reborrow()), buf)
997 } 1002 }
998 1003
999 /// Write an exact number of elements to the ringbuffer. 1004 /// Write an exact number of elements to the ringbuffer.
1000 pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, OverrunError> { 1005 pub async fn write_exact(&mut self, buffer: &[W]) -> Result<usize, Error> {
1001 self.ringbuf 1006 self.ringbuf
1002 .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer) 1007 .write_exact(&mut DmaCtrlImpl(self.channel.reborrow()), buffer)
1003 .await 1008 .await
1004 } 1009 }
1005 1010
1011 /// The current length of the ringbuffer
1012 pub fn len(&mut self) -> Result<usize, Error> {
1013 Ok(self.ringbuf.len(&mut DmaCtrlImpl(self.channel.reborrow()))?)
1014 }
1015
1006 /// The capacity of the ringbuffer 1016 /// The capacity of the ringbuffer
1007 pub const fn capacity(&self) -> usize { 1017 pub const fn capacity(&self) -> usize {
1008 self.ringbuf.cap() 1018 self.ringbuf.cap()
diff --git a/embassy-stm32/src/dma/ringbuffer/mod.rs b/embassy-stm32/src/dma/ringbuffer/mod.rs
index eb64ad016..a257faa5b 100644
--- a/embassy-stm32/src/dma/ringbuffer/mod.rs
+++ b/embassy-stm32/src/dma/ringbuffer/mod.rs
@@ -19,9 +19,13 @@ pub trait DmaCtrl {
19 19
20#[derive(Debug, PartialEq)] 20#[derive(Debug, PartialEq)]
21#[cfg_attr(feature = "defmt", derive(defmt::Format))] 21#[cfg_attr(feature = "defmt", derive(defmt::Format))]
22pub struct OverrunError; 22pub enum Error {
23 Overrun,
24 DmaUnsynced,
25}
23 26
24#[derive(Debug, Clone, Copy, Default)] 27#[derive(Debug, Clone, Copy, Default)]
28#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25struct DmaIndex { 29struct DmaIndex {
26 complete_count: usize, 30 complete_count: usize,
27 pos: usize, 31 pos: usize,
@@ -38,15 +42,19 @@ impl DmaIndex {
38 } 42 }
39 43
40 fn dma_sync(&mut self, cap: usize, dma: &mut impl DmaCtrl) { 44 fn dma_sync(&mut self, cap: usize, dma: &mut impl DmaCtrl) {
41 let first_pos = cap - dma.get_remaining_transfers(); 45 // Important!
42 self.complete_count += dma.reset_complete_count(); 46 // The ordering of the first two lines matters!
43 self.pos = cap - dma.get_remaining_transfers(); 47 // If changed, the code will detect a wrong +capacity
44 48 // jump at wrap-around.
45 // If the latter call to get_remaining_transfers() returned a smaller value than the first, the dma 49 let count_diff = dma.reset_complete_count();
46 // has wrapped around between calls and we must check if the complete count also incremented. 50 let pos = cap - dma.get_remaining_transfers();
47 if self.pos < first_pos { 51 self.pos = if pos < self.pos && count_diff == 0 {
48 self.complete_count += dma.reset_complete_count(); 52 cap - 1
49 } 53 } else {
54 pos
55 };
56
57 self.complete_count += count_diff;
50 } 58 }
51 59
52 fn advance(&mut self, cap: usize, steps: usize) { 60 fn advance(&mut self, cap: usize, steps: usize) {
@@ -96,14 +104,18 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
96 } 104 }
97 105
98 /// Get the available readable dma samples. 106 /// Get the available readable dma samples.
99 pub fn len(&mut self, dma: &mut impl DmaCtrl) -> Result<usize, OverrunError> { 107 pub fn len(&mut self, dma: &mut impl DmaCtrl) -> Result<usize, Error> {
100 self.write_index.dma_sync(self.cap(), dma); 108 self.write_index.dma_sync(self.cap(), dma);
101 DmaIndex::normalize(&mut self.write_index, &mut self.read_index); 109 DmaIndex::normalize(&mut self.write_index, &mut self.read_index);
102 110
103 let diff = self.write_index.diff(self.cap(), &self.read_index); 111 let diff = self.write_index.diff(self.cap(), &self.read_index);
104 112
105 if diff < 0 || diff > self.cap() as isize { 113 if diff < 0 {
106 Err(OverrunError) 114 return Err(Error::DmaUnsynced);
115 }
116
117 if diff > self.cap() as isize {
118 Err(Error::Overrun)
107 } else { 119 } else {
108 Ok(diff as usize) 120 Ok(diff as usize)
109 } 121 }
@@ -113,9 +125,9 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
113 /// Return a tuple of the length read and the length remaining in the buffer 125 /// Return a tuple of the length read and the length remaining in the buffer
114 /// If not all of the elements were read, then there will be some elements in the buffer remaining 126 /// If not all of the elements were read, then there will be some elements in the buffer remaining
115 /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read 127 /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
116 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller, 128 /// Error is returned if the portion to be read was overwritten by the DMA controller,
117 /// in which case the rinbuffer will automatically reset itself. 129 /// in which case the rinbuffer will automatically reset itself.
118 pub fn read(&mut self, dma: &mut impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { 130 pub fn read(&mut self, dma: &mut impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), Error> {
119 self.read_raw(dma, buf).inspect_err(|_e| { 131 self.read_raw(dma, buf).inspect_err(|_e| {
120 self.reset(dma); 132 self.reset(dma);
121 }) 133 })
@@ -124,7 +136,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
124 /// Read an exact number of elements from the ringbuffer. 136 /// Read an exact number of elements from the ringbuffer.
125 /// 137 ///
126 /// Returns the remaining number of elements available for immediate reading. 138 /// Returns the remaining number of elements available for immediate reading.
127 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller. 139 /// Error is returned if the portion to be read was overwritten by the DMA controller.
128 /// 140 ///
129 /// Async/Wake Behavior: 141 /// Async/Wake Behavior:
130 /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point, 142 /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point,
@@ -132,7 +144,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
132 /// ring buffer was created with a buffer of size 'N': 144 /// ring buffer was created with a buffer of size 'N':
133 /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source. 145 /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source.
134 /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning. 146 /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning.
135 pub async fn read_exact(&mut self, dma: &mut impl DmaCtrl, buffer: &mut [W]) -> Result<usize, OverrunError> { 147 pub async fn read_exact(&mut self, dma: &mut impl DmaCtrl, buffer: &mut [W]) -> Result<usize, Error> {
136 let mut read_data = 0; 148 let mut read_data = 0;
137 let buffer_len = buffer.len(); 149 let buffer_len = buffer.len();
138 150
@@ -154,7 +166,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
154 .await 166 .await
155 } 167 }
156 168
157 fn read_raw(&mut self, dma: &mut impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { 169 fn read_raw(&mut self, dma: &mut impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), Error> {
158 let readable = self.len(dma)?.min(buf.len()); 170 let readable = self.len(dma)?.min(buf.len());
159 for i in 0..readable { 171 for i in 0..readable {
160 buf[i] = self.read_buf(i); 172 buf[i] = self.read_buf(i);
@@ -205,14 +217,17 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
205 } 217 }
206 218
207 /// Get the remaining writable dma samples. 219 /// Get the remaining writable dma samples.
208 pub fn len(&mut self, dma: &mut impl DmaCtrl) -> Result<usize, OverrunError> { 220 pub fn len(&mut self, dma: &mut impl DmaCtrl) -> Result<usize, Error> {
209 self.read_index.dma_sync(self.cap(), dma); 221 self.read_index.dma_sync(self.cap(), dma);
210 DmaIndex::normalize(&mut self.read_index, &mut self.write_index); 222 DmaIndex::normalize(&mut self.read_index, &mut self.write_index);
211 223
212 let diff = self.write_index.diff(self.cap(), &self.read_index); 224 let diff = self.write_index.diff(self.cap(), &self.read_index);
213 225
214 if diff < 0 || diff > self.cap() as isize { 226 if diff > self.cap() as isize {
215 Err(OverrunError) 227 return Err(Error::DmaUnsynced);
228 }
229 if diff < 0 {
230 Err(Error::Overrun)
216 } else { 231 } else {
217 Ok(self.cap().saturating_sub(diff as usize)) 232 Ok(self.cap().saturating_sub(diff as usize))
218 } 233 }
@@ -225,17 +240,17 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
225 240
226 /// Append data to the ring buffer. 241 /// Append data to the ring buffer.
227 /// Returns a tuple of the data written and the remaining write capacity in the buffer. 242 /// Returns a tuple of the data written and the remaining write capacity in the buffer.
228 /// OverrunError is returned if the portion to be written was previously read by the DMA controller. 243 /// Error is returned if the portion to be written was previously read by the DMA controller.
229 /// In this case, the ringbuffer will automatically reset itself, giving a full buffer worth of 244 /// In this case, the ringbuffer will automatically reset itself, giving a full buffer worth of
230 /// leeway between the write index and the DMA. 245 /// leeway between the write index and the DMA.
231 pub fn write(&mut self, dma: &mut impl DmaCtrl, buf: &[W]) -> Result<(usize, usize), OverrunError> { 246 pub fn write(&mut self, dma: &mut impl DmaCtrl, buf: &[W]) -> Result<(usize, usize), Error> {
232 self.write_raw(dma, buf).inspect_err(|_e| { 247 self.write_raw(dma, buf).inspect_err(|_e| {
233 self.reset(dma); 248 self.reset(dma);
234 }) 249 })
235 } 250 }
236 251
237 /// Write elements directly to the buffer. 252 /// Write elements directly to the buffer.
238 pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), OverrunError> { 253 pub fn write_immediate(&mut self, buf: &[W]) -> Result<(usize, usize), Error> {
239 for (i, data) in buf.iter().enumerate() { 254 for (i, data) in buf.iter().enumerate() {
240 self.write_buf(i, *data) 255 self.write_buf(i, *data)
241 } 256 }
@@ -244,7 +259,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
244 } 259 }
245 260
246 /// Write an exact number of elements to the ringbuffer. 261 /// Write an exact number of elements to the ringbuffer.
247 pub async fn write_exact(&mut self, dma: &mut impl DmaCtrl, buffer: &[W]) -> Result<usize, OverrunError> { 262 pub async fn write_exact(&mut self, dma: &mut impl DmaCtrl, buffer: &[W]) -> Result<usize, Error> {
248 let mut written_data = 0; 263 let mut written_data = 0;
249 let buffer_len = buffer.len(); 264 let buffer_len = buffer.len();
250 265
@@ -266,7 +281,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
266 .await 281 .await
267 } 282 }
268 283
269 pub fn write_raw(&mut self, dma: &mut impl DmaCtrl, buf: &[W]) -> Result<(usize, usize), OverrunError> { 284 fn write_raw(&mut self, dma: &mut impl DmaCtrl, buf: &[W]) -> Result<(usize, usize), Error> {
270 let writable = self.len(dma)?.min(buf.len()); 285 let writable = self.len(dma)?.min(buf.len());
271 for i in 0..writable { 286 for i in 0..writable {
272 self.write_buf(i, buf[i]); 287 self.write_buf(i, buf[i]);
diff --git a/embassy-stm32/src/dma/ringbuffer/tests/mod.rs b/embassy-stm32/src/dma/ringbuffer/tests/mod.rs
index 1800eae69..6fabedb83 100644
--- a/embassy-stm32/src/dma/ringbuffer/tests/mod.rs
+++ b/embassy-stm32/src/dma/ringbuffer/tests/mod.rs
@@ -2,13 +2,14 @@ use std::{cell, vec};
2 2
3use super::*; 3use super::*;
4 4
5#[allow(dead_code)] 5#[allow(unused)]
6#[derive(PartialEq, Debug)] 6#[derive(PartialEq, Debug)]
7enum TestCircularTransferRequest { 7enum TestCircularTransferRequest {
8 ResetCompleteCount(usize), 8 ResetCompleteCount(usize),
9 PositionRequest(usize), 9 PositionRequest(usize),
10} 10}
11 11
12#[allow(unused)]
12struct TestCircularTransfer { 13struct TestCircularTransfer {
13 len: usize, 14 len: usize,
14 requests: cell::RefCell<vec::Vec<TestCircularTransferRequest>>, 15 requests: cell::RefCell<vec::Vec<TestCircularTransferRequest>>,
@@ -39,6 +40,7 @@ impl DmaCtrl for TestCircularTransfer {
39} 40}
40 41
41impl TestCircularTransfer { 42impl TestCircularTransfer {
43 #[allow(unused)]
42 pub fn new(len: usize) -> Self { 44 pub fn new(len: usize) -> Self {
43 Self { 45 Self {
44 requests: cell::RefCell::new(vec![]), 46 requests: cell::RefCell::new(vec![]),
@@ -46,6 +48,7 @@ impl TestCircularTransfer {
46 } 48 }
47 } 49 }
48 50
51 #[allow(unused)]
49 pub fn setup(&self, mut requests: vec::Vec<TestCircularTransferRequest>) { 52 pub fn setup(&self, mut requests: vec::Vec<TestCircularTransferRequest>) {
50 requests.reverse(); 53 requests.reverse();
51 self.requests.replace(requests); 54 self.requests.replace(requests);
@@ -55,84 +58,6 @@ impl TestCircularTransfer {
55const CAP: usize = 16; 58const CAP: usize = 16;
56 59
57#[test] 60#[test]
58fn dma_index_dma_sync_syncs_position_to_last_read_if_sync_takes_place_on_same_dma_cycle() {
59 let mut dma = TestCircularTransfer::new(CAP);
60 dma.setup(vec![
61 TestCircularTransferRequest::PositionRequest(4),
62 TestCircularTransferRequest::ResetCompleteCount(0),
63 TestCircularTransferRequest::PositionRequest(7),
64 ]);
65 let mut index = DmaIndex::default();
66 index.dma_sync(CAP, &mut dma);
67 assert_eq!(index.complete_count, 0);
68 assert_eq!(index.pos, 7);
69}
70
71#[test]
72fn dma_index_dma_sync_updates_complete_count_properly_if_sync_takes_place_on_same_dma_cycle() {
73 let mut dma = TestCircularTransfer::new(CAP);
74 dma.setup(vec![
75 TestCircularTransferRequest::PositionRequest(4),
76 TestCircularTransferRequest::ResetCompleteCount(2),
77 TestCircularTransferRequest::PositionRequest(7),
78 ]);
79 let mut index = DmaIndex::default();
80 index.complete_count = 1;
81 index.dma_sync(CAP, &mut dma);
82 assert_eq!(index.complete_count, 3);
83 assert_eq!(index.pos, 7);
84}
85
86#[test]
87fn dma_index_dma_sync_syncs_to_last_position_if_reads_occur_on_different_dma_cycles() {
88 let mut dma = TestCircularTransfer::new(CAP);
89 dma.setup(vec![
90 TestCircularTransferRequest::PositionRequest(10),
91 TestCircularTransferRequest::ResetCompleteCount(1),
92 TestCircularTransferRequest::PositionRequest(5),
93 TestCircularTransferRequest::ResetCompleteCount(0),
94 ]);
95 let mut index = DmaIndex::default();
96 index.dma_sync(CAP, &mut dma);
97 assert_eq!(index.complete_count, 1);
98 assert_eq!(index.pos, 5);
99}
100
101#[test]
102fn dma_index_dma_sync_detects_new_cycle_if_later_position_is_less_than_first_and_first_complete_count_occurs_on_first_cycle(
103) {
104 let mut dma = TestCircularTransfer::new(CAP);
105 dma.setup(vec![
106 TestCircularTransferRequest::PositionRequest(10),
107 TestCircularTransferRequest::ResetCompleteCount(1),
108 TestCircularTransferRequest::PositionRequest(5),
109 TestCircularTransferRequest::ResetCompleteCount(1),
110 ]);
111 let mut index = DmaIndex::default();
112 index.complete_count = 1;
113 index.dma_sync(CAP, &mut dma);
114 assert_eq!(index.complete_count, 3);
115 assert_eq!(index.pos, 5);
116}
117
118#[test]
119fn dma_index_dma_sync_detects_new_cycle_if_later_position_is_less_than_first_and_first_complete_count_occurs_on_later_cycle(
120) {
121 let mut dma = TestCircularTransfer::new(CAP);
122 dma.setup(vec![
123 TestCircularTransferRequest::PositionRequest(10),
124 TestCircularTransferRequest::ResetCompleteCount(2),
125 TestCircularTransferRequest::PositionRequest(5),
126 TestCircularTransferRequest::ResetCompleteCount(0),
127 ]);
128 let mut index = DmaIndex::default();
129 index.complete_count = 1;
130 index.dma_sync(CAP, &mut dma);
131 assert_eq!(index.complete_count, 3);
132 assert_eq!(index.pos, 5);
133}
134
135#[test]
136fn dma_index_as_index_returns_index_mod_cap_by_default() { 61fn dma_index_as_index_returns_index_mod_cap_by_default() {
137 let index = DmaIndex::default(); 62 let index = DmaIndex::default();
138 assert_eq!(index.as_index(CAP, 0), 0); 63 assert_eq!(index.as_index(CAP, 0), 0);