aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexandros Liarokapis <[email protected]>2024-09-24 00:59:34 +0300
committerAlexandros Liarokapis <[email protected]>2024-10-15 12:29:12 +0300
commit9c7b296432af40ac44e5e65a3742c691f1414444 (patch)
tree0eb3ae4375d8719babd73c229ab33cc0af5dea2d
parent82712252166a274c1499c3680b63f86cdfbb8dfb (diff)
overrun at invalid diffs, rename clear to reset, simplify dma_sync method
-rw-r--r--embassy-stm32/src/adc/ringbuffered_v2.rs3
-rw-r--r--embassy-stm32/src/dma/dma_bdma.rs4
-rw-r--r--embassy-stm32/src/dma/ringbuffer/mod.rs55
-rw-r--r--embassy-stm32/src/dma/ringbuffer/tests/mod.rs22
-rw-r--r--embassy-stm32/src/dma/ringbuffer/tests/prop_test/reader.rs10
-rw-r--r--embassy-stm32/src/dma/ringbuffer/tests/prop_test/writer.rs10
6 files changed, 50 insertions, 54 deletions
diff --git a/embassy-stm32/src/adc/ringbuffered_v2.rs b/embassy-stm32/src/adc/ringbuffered_v2.rs
index 3b064044e..9fc233222 100644
--- a/embassy-stm32/src/adc/ringbuffered_v2.rs
+++ b/embassy-stm32/src/adc/ringbuffered_v2.rs
@@ -226,9 +226,8 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> {
226 226
227 /// Turns on ADC if it is not already turned on and starts continuous DMA transfer. 227 /// Turns on ADC if it is not already turned on and starts continuous DMA transfer.
228 pub fn start(&mut self) -> Result<(), OverrunError> { 228 pub fn start(&mut self) -> Result<(), OverrunError> {
229 self.ring_buf.clear();
230
231 self.setup_adc(); 229 self.setup_adc();
230 self.ring_buf.clear();
232 231
233 Ok(()) 232 Ok(())
234 } 233 }
diff --git a/embassy-stm32/src/dma/dma_bdma.rs b/embassy-stm32/src/dma/dma_bdma.rs
index a43137c6e..59ad4d988 100644
--- a/embassy-stm32/src/dma/dma_bdma.rs
+++ b/embassy-stm32/src/dma/dma_bdma.rs
@@ -833,7 +833,7 @@ impl<'a, W: Word> ReadableRingBuffer<'a, W> {
833 833
834 /// Clear all data in the ring buffer. 834 /// Clear all data in the ring buffer.
835 pub fn clear(&mut self) { 835 pub fn clear(&mut self) {
836 self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); 836 self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow()));
837 } 837 }
838 838
839 /// Read elements from the ring buffer 839 /// Read elements from the ring buffer
@@ -980,7 +980,7 @@ impl<'a, W: Word> WritableRingBuffer<'a, W> {
980 980
981 /// Clear all data in the ring buffer. 981 /// Clear all data in the ring buffer.
982 pub fn clear(&mut self) { 982 pub fn clear(&mut self) {
983 self.ringbuf.clear(&mut DmaCtrlImpl(self.channel.reborrow())); 983 self.ringbuf.reset(&mut DmaCtrlImpl(self.channel.reborrow()));
984 } 984 }
985 985
986 /// Write elements directly to the raw buffer. 986 /// Write elements directly to the raw buffer.
diff --git a/embassy-stm32/src/dma/ringbuffer/mod.rs b/embassy-stm32/src/dma/ringbuffer/mod.rs
index 76f7f36ec..eb64ad016 100644
--- a/embassy-stm32/src/dma/ringbuffer/mod.rs
+++ b/embassy-stm32/src/dma/ringbuffer/mod.rs
@@ -23,14 +23,14 @@ pub struct OverrunError;
23 23
24#[derive(Debug, Clone, Copy, Default)] 24#[derive(Debug, Clone, Copy, Default)]
25struct DmaIndex { 25struct DmaIndex {
26 completion_count: usize, 26 complete_count: usize,
27 pos: usize, 27 pos: usize,
28} 28}
29 29
30impl DmaIndex { 30impl DmaIndex {
31 fn reset(&mut self) { 31 fn reset(&mut self) {
32 self.pos = 0; 32 self.pos = 0;
33 self.completion_count = 0; 33 self.complete_count = 0;
34 } 34 }
35 35
36 fn as_index(&self, cap: usize, offset: usize) -> usize { 36 fn as_index(&self, cap: usize, offset: usize) -> usize {
@@ -38,34 +38,31 @@ impl DmaIndex {
38 } 38 }
39 39
40 fn dma_sync(&mut self, cap: usize, dma: &mut impl DmaCtrl) { 40 fn dma_sync(&mut self, cap: usize, dma: &mut impl DmaCtrl) {
41 let fst_pos = cap - dma.get_remaining_transfers(); 41 let first_pos = cap - dma.get_remaining_transfers();
42 let fst_count = dma.reset_complete_count(); 42 self.complete_count += dma.reset_complete_count();
43 let pos = cap - dma.get_remaining_transfers(); 43 self.pos = cap - dma.get_remaining_transfers();
44 44
45 let wrap_count = if pos >= fst_pos { 45 // If the latter call to get_remaining_transfers() returned a smaller value than the first, the dma
46 fst_count 46 // has wrapped around between calls and we must check if the complete count also incremented.
47 } else { 47 if self.pos < first_pos {
48 fst_count + dma.reset_complete_count() 48 self.complete_count += dma.reset_complete_count();
49 }; 49 }
50
51 self.pos = pos;
52 self.completion_count += wrap_count;
53 } 50 }
54 51
55 fn advance(&mut self, cap: usize, steps: usize) { 52 fn advance(&mut self, cap: usize, steps: usize) {
56 let next = self.pos + steps; 53 let next = self.pos + steps;
57 self.completion_count += next / cap; 54 self.complete_count += next / cap;
58 self.pos = next % cap; 55 self.pos = next % cap;
59 } 56 }
60 57
61 fn normalize(lhs: &mut DmaIndex, rhs: &mut DmaIndex) { 58 fn normalize(lhs: &mut DmaIndex, rhs: &mut DmaIndex) {
62 let min_count = lhs.completion_count.min(rhs.completion_count); 59 let min_count = lhs.complete_count.min(rhs.complete_count);
63 lhs.completion_count -= min_count; 60 lhs.complete_count -= min_count;
64 rhs.completion_count -= min_count; 61 rhs.complete_count -= min_count;
65 } 62 }
66 63
67 fn diff(&self, cap: usize, rhs: &DmaIndex) -> isize { 64 fn diff(&self, cap: usize, rhs: &DmaIndex) -> isize {
68 (self.completion_count * cap + self.pos) as isize - (rhs.completion_count * cap + rhs.pos) as isize 65 (self.complete_count * cap + self.pos) as isize - (rhs.complete_count * cap + rhs.pos) as isize
69 } 66 }
70} 67}
71 68
@@ -86,7 +83,7 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
86 } 83 }
87 84
88 /// Reset the ring buffer to its initial state. 85 /// Reset the ring buffer to its initial state.
89 pub fn clear(&mut self, dma: &mut impl DmaCtrl) { 86 pub fn reset(&mut self, dma: &mut impl DmaCtrl) {
90 dma.reset_complete_count(); 87 dma.reset_complete_count();
91 self.write_index.reset(); 88 self.write_index.reset();
92 self.write_index.dma_sync(self.cap(), dma); 89 self.write_index.dma_sync(self.cap(), dma);
@@ -103,12 +100,12 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
103 self.write_index.dma_sync(self.cap(), dma); 100 self.write_index.dma_sync(self.cap(), dma);
104 DmaIndex::normalize(&mut self.write_index, &mut self.read_index); 101 DmaIndex::normalize(&mut self.write_index, &mut self.read_index);
105 102
106 let diff: usize = self.write_index.diff(self.cap(), &self.read_index).try_into().unwrap(); 103 let diff = self.write_index.diff(self.cap(), &self.read_index);
107 104
108 if diff > self.cap() { 105 if diff < 0 || diff > self.cap() as isize {
109 Err(OverrunError) 106 Err(OverrunError)
110 } else { 107 } else {
111 Ok(diff) 108 Ok(diff as usize)
112 } 109 }
113 } 110 }
114 111
@@ -117,10 +114,10 @@ impl<'a, W: Word> ReadableDmaRingBuffer<'a, W> {
117 /// If not all of the elements were read, then there will be some elements in the buffer remaining 114 /// If not all of the elements were read, then there will be some elements in the buffer remaining
118 /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read 115 /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read
119 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller, 116 /// OverrunError is returned if the portion to be read was overwritten by the DMA controller,
120 /// in which case the rinbuffer will automatically clear itself. 117 /// in which case the rinbuffer will automatically reset itself.
121 pub fn read(&mut self, dma: &mut impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { 118 pub fn read(&mut self, dma: &mut impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> {
122 self.read_raw(dma, buf).inspect_err(|_e| { 119 self.read_raw(dma, buf).inspect_err(|_e| {
123 self.clear(dma); 120 self.reset(dma);
124 }) 121 })
125 } 122 }
126 123
@@ -192,14 +189,14 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
192 dma_buf, 189 dma_buf,
193 read_index: Default::default(), 190 read_index: Default::default(),
194 write_index: DmaIndex { 191 write_index: DmaIndex {
195 completion_count: 0, 192 complete_count: 0,
196 pos: len, 193 pos: len,
197 }, 194 },
198 } 195 }
199 } 196 }
200 197
201 /// Reset the ring buffer to its initial state. The buffer after the reset will be full. 198 /// Reset the ring buffer to its initial state. The buffer after the reset will be full.
202 pub fn clear(&mut self, dma: &mut impl DmaCtrl) { 199 pub fn reset(&mut self, dma: &mut impl DmaCtrl) {
203 dma.reset_complete_count(); 200 dma.reset_complete_count();
204 self.read_index.reset(); 201 self.read_index.reset();
205 self.read_index.dma_sync(self.cap(), dma); 202 self.read_index.dma_sync(self.cap(), dma);
@@ -214,7 +211,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
214 211
215 let diff = self.write_index.diff(self.cap(), &self.read_index); 212 let diff = self.write_index.diff(self.cap(), &self.read_index);
216 213
217 if diff < 0 { 214 if diff < 0 || diff > self.cap() as isize {
218 Err(OverrunError) 215 Err(OverrunError)
219 } else { 216 } else {
220 Ok(self.cap().saturating_sub(diff as usize)) 217 Ok(self.cap().saturating_sub(diff as usize))
@@ -233,7 +230,7 @@ impl<'a, W: Word> WritableDmaRingBuffer<'a, W> {
233 /// leeway between the write index and the DMA. 230 /// leeway between the write index and the DMA.
234 pub fn write(&mut self, dma: &mut impl DmaCtrl, buf: &[W]) -> Result<(usize, usize), OverrunError> { 231 pub fn write(&mut self, dma: &mut impl DmaCtrl, buf: &[W]) -> Result<(usize, usize), OverrunError> {
235 self.write_raw(dma, buf).inspect_err(|_e| { 232 self.write_raw(dma, buf).inspect_err(|_e| {
236 self.clear(dma); 233 self.reset(dma);
237 }) 234 })
238 } 235 }
239 236
diff --git a/embassy-stm32/src/dma/ringbuffer/tests/mod.rs b/embassy-stm32/src/dma/ringbuffer/tests/mod.rs
index 9768e1df8..1800eae69 100644
--- a/embassy-stm32/src/dma/ringbuffer/tests/mod.rs
+++ b/embassy-stm32/src/dma/ringbuffer/tests/mod.rs
@@ -64,12 +64,12 @@ fn dma_index_dma_sync_syncs_position_to_last_read_if_sync_takes_place_on_same_dm
64 ]); 64 ]);
65 let mut index = DmaIndex::default(); 65 let mut index = DmaIndex::default();
66 index.dma_sync(CAP, &mut dma); 66 index.dma_sync(CAP, &mut dma);
67 assert_eq!(index.completion_count, 0); 67 assert_eq!(index.complete_count, 0);
68 assert_eq!(index.pos, 7); 68 assert_eq!(index.pos, 7);
69} 69}
70 70
71#[test] 71#[test]
72fn dma_index_dma_sync_updates_completion_count_properly_if_sync_takes_place_on_same_dma_cycle() { 72fn dma_index_dma_sync_updates_complete_count_properly_if_sync_takes_place_on_same_dma_cycle() {
73 let mut dma = TestCircularTransfer::new(CAP); 73 let mut dma = TestCircularTransfer::new(CAP);
74 dma.setup(vec![ 74 dma.setup(vec![
75 TestCircularTransferRequest::PositionRequest(4), 75 TestCircularTransferRequest::PositionRequest(4),
@@ -77,9 +77,9 @@ fn dma_index_dma_sync_updates_completion_count_properly_if_sync_takes_place_on_s
77 TestCircularTransferRequest::PositionRequest(7), 77 TestCircularTransferRequest::PositionRequest(7),
78 ]); 78 ]);
79 let mut index = DmaIndex::default(); 79 let mut index = DmaIndex::default();
80 index.completion_count = 1; 80 index.complete_count = 1;
81 index.dma_sync(CAP, &mut dma); 81 index.dma_sync(CAP, &mut dma);
82 assert_eq!(index.completion_count, 3); 82 assert_eq!(index.complete_count, 3);
83 assert_eq!(index.pos, 7); 83 assert_eq!(index.pos, 7);
84} 84}
85 85
@@ -94,12 +94,12 @@ fn dma_index_dma_sync_syncs_to_last_position_if_reads_occur_on_different_dma_cyc
94 ]); 94 ]);
95 let mut index = DmaIndex::default(); 95 let mut index = DmaIndex::default();
96 index.dma_sync(CAP, &mut dma); 96 index.dma_sync(CAP, &mut dma);
97 assert_eq!(index.completion_count, 1); 97 assert_eq!(index.complete_count, 1);
98 assert_eq!(index.pos, 5); 98 assert_eq!(index.pos, 5);
99} 99}
100 100
101#[test] 101#[test]
102fn dma_index_dma_sync_detects_new_cycle_if_later_position_is_less_than_first_and_first_completion_count_occurs_on_first_cycle( 102fn dma_index_dma_sync_detects_new_cycle_if_later_position_is_less_than_first_and_first_complete_count_occurs_on_first_cycle(
103) { 103) {
104 let mut dma = TestCircularTransfer::new(CAP); 104 let mut dma = TestCircularTransfer::new(CAP);
105 dma.setup(vec![ 105 dma.setup(vec![
@@ -109,14 +109,14 @@ fn dma_index_dma_sync_detects_new_cycle_if_later_position_is_less_than_first_and
109 TestCircularTransferRequest::ResetCompleteCount(1), 109 TestCircularTransferRequest::ResetCompleteCount(1),
110 ]); 110 ]);
111 let mut index = DmaIndex::default(); 111 let mut index = DmaIndex::default();
112 index.completion_count = 1; 112 index.complete_count = 1;
113 index.dma_sync(CAP, &mut dma); 113 index.dma_sync(CAP, &mut dma);
114 assert_eq!(index.completion_count, 3); 114 assert_eq!(index.complete_count, 3);
115 assert_eq!(index.pos, 5); 115 assert_eq!(index.pos, 5);
116} 116}
117 117
118#[test] 118#[test]
119fn dma_index_dma_sync_detects_new_cycle_if_later_position_is_less_than_first_and_first_completion_count_occurs_on_later_cycle( 119fn dma_index_dma_sync_detects_new_cycle_if_later_position_is_less_than_first_and_first_complete_count_occurs_on_later_cycle(
120) { 120) {
121 let mut dma = TestCircularTransfer::new(CAP); 121 let mut dma = TestCircularTransfer::new(CAP);
122 dma.setup(vec![ 122 dma.setup(vec![
@@ -126,9 +126,9 @@ fn dma_index_dma_sync_detects_new_cycle_if_later_position_is_less_than_first_and
126 TestCircularTransferRequest::ResetCompleteCount(0), 126 TestCircularTransferRequest::ResetCompleteCount(0),
127 ]); 127 ]);
128 let mut index = DmaIndex::default(); 128 let mut index = DmaIndex::default();
129 index.completion_count = 1; 129 index.complete_count = 1;
130 index.dma_sync(CAP, &mut dma); 130 index.dma_sync(CAP, &mut dma);
131 assert_eq!(index.completion_count, 3); 131 assert_eq!(index.complete_count, 3);
132 assert_eq!(index.pos, 5); 132 assert_eq!(index.pos, 5);
133} 133}
134 134
diff --git a/embassy-stm32/src/dma/ringbuffer/tests/prop_test/reader.rs b/embassy-stm32/src/dma/ringbuffer/tests/prop_test/reader.rs
index 6e640a813..4f3957a68 100644
--- a/embassy-stm32/src/dma/ringbuffer/tests/prop_test/reader.rs
+++ b/embassy-stm32/src/dma/ringbuffer/tests/prop_test/reader.rs
@@ -5,7 +5,7 @@ use super::*;
5#[derive(Debug, Clone)] 5#[derive(Debug, Clone)]
6enum ReaderTransition { 6enum ReaderTransition {
7 Write(usize), 7 Write(usize),
8 Clear, 8 Reset,
9 ReadUpTo(usize), 9 ReadUpTo(usize),
10} 10}
11 11
@@ -23,14 +23,14 @@ impl ReferenceStateMachine for ReaderSM {
23 prop_oneof![ 23 prop_oneof![
24 (1..50_usize).prop_map(ReaderTransition::Write), 24 (1..50_usize).prop_map(ReaderTransition::Write),
25 (1..50_usize).prop_map(ReaderTransition::ReadUpTo), 25 (1..50_usize).prop_map(ReaderTransition::ReadUpTo),
26 strategy::Just(ReaderTransition::Clear), 26 strategy::Just(ReaderTransition::Reset),
27 ] 27 ]
28 .boxed() 28 .boxed()
29 } 29 }
30 30
31 fn apply(status: Self::State, transition: &Self::Transition) -> Self::State { 31 fn apply(status: Self::State, transition: &Self::Transition) -> Self::State {
32 match (status, transition) { 32 match (status, transition) {
33 (_, ReaderTransition::Clear) => Status::Available(0), 33 (_, ReaderTransition::Reset) => Status::Available(0),
34 (Status::Available(x), ReaderTransition::Write(y)) => { 34 (Status::Available(x), ReaderTransition::Write(y)) => {
35 if x + y > CAP { 35 if x + y > CAP {
36 Status::Failed 36 Status::Failed
@@ -87,8 +87,8 @@ impl StateMachineTest for ReaderTest {
87 ) -> Self::SystemUnderTest { 87 ) -> Self::SystemUnderTest {
88 match transition { 88 match transition {
89 ReaderTransition::Write(x) => sut.producer.advance(x), 89 ReaderTransition::Write(x) => sut.producer.advance(x),
90 ReaderTransition::Clear => { 90 ReaderTransition::Reset => {
91 sut.consumer.clear(&mut sut.producer); 91 sut.consumer.reset(&mut sut.producer);
92 } 92 }
93 ReaderTransition::ReadUpTo(x) => { 93 ReaderTransition::ReadUpTo(x) => {
94 let status = sut.status; 94 let status = sut.status;
diff --git a/embassy-stm32/src/dma/ringbuffer/tests/prop_test/writer.rs b/embassy-stm32/src/dma/ringbuffer/tests/prop_test/writer.rs
index c1b3859b2..15433c0ee 100644
--- a/embassy-stm32/src/dma/ringbuffer/tests/prop_test/writer.rs
+++ b/embassy-stm32/src/dma/ringbuffer/tests/prop_test/writer.rs
@@ -6,7 +6,7 @@ use super::*;
6enum WriterTransition { 6enum WriterTransition {
7 Read(usize), 7 Read(usize),
8 WriteUpTo(usize), 8 WriteUpTo(usize),
9 Clear, 9 Reset,
10} 10}
11 11
12struct WriterSM; 12struct WriterSM;
@@ -23,14 +23,14 @@ impl ReferenceStateMachine for WriterSM {
23 prop_oneof![ 23 prop_oneof![
24 (1..50_usize).prop_map(WriterTransition::Read), 24 (1..50_usize).prop_map(WriterTransition::Read),
25 (1..50_usize).prop_map(WriterTransition::WriteUpTo), 25 (1..50_usize).prop_map(WriterTransition::WriteUpTo),
26 strategy::Just(WriterTransition::Clear), 26 strategy::Just(WriterTransition::Reset),
27 ] 27 ]
28 .boxed() 28 .boxed()
29 } 29 }
30 30
31 fn apply(status: Self::State, transition: &Self::Transition) -> Self::State { 31 fn apply(status: Self::State, transition: &Self::Transition) -> Self::State {
32 match (status, transition) { 32 match (status, transition) {
33 (_, WriterTransition::Clear) => Status::Available(CAP), 33 (_, WriterTransition::Reset) => Status::Available(CAP),
34 (Status::Available(x), WriterTransition::Read(y)) => { 34 (Status::Available(x), WriterTransition::Read(y)) => {
35 if x < *y { 35 if x < *y {
36 Status::Failed 36 Status::Failed
@@ -87,8 +87,8 @@ impl StateMachineTest for WriterTest {
87 ) -> Self::SystemUnderTest { 87 ) -> Self::SystemUnderTest {
88 match transition { 88 match transition {
89 WriterTransition::Read(x) => sut.consumer.advance(x), 89 WriterTransition::Read(x) => sut.consumer.advance(x),
90 WriterTransition::Clear => { 90 WriterTransition::Reset => {
91 sut.producer.clear(&mut sut.consumer); 91 sut.producer.reset(&mut sut.consumer);
92 } 92 }
93 WriterTransition::WriteUpTo(x) => { 93 WriterTransition::WriteUpTo(x) => {
94 let status = sut.status; 94 let status = sut.status;