stm32_eth/dma/rx/
descriptor.rs1use crate::dma::{
2 desc::Descriptor,
3 ring::{RingDescriptor, RingEntry},
4};
5
6use crate::dma::PacketId;
7
8#[cfg(feature = "ptp")]
9use crate::ptp::Timestamp;
10
11#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13#[derive(Debug, PartialEq)]
14pub(crate) enum RxDescriptorError {
15 Truncated,
17 DmaError,
19}
20
21#[allow(unused)]
24const RXDESC_0_TIMESTAMP_VALID: u32 = 1 << 7;
25const RXDESC_0_OWN: u32 = 1 << 31;
27const RXDESC_0_FS: u32 = 1 << 9;
29const RXDESC_0_LS: u32 = 1 << 8;
31const RXDESC_0_ES: u32 = 1 << 15;
33const RXDESC_0_FL_MASK: u32 = 0x3FFF;
35const RXDESC_0_FL_SHIFT: usize = 16;
36
37const RXDESC_1_RBS_SHIFT: usize = 0;
38const RXDESC_1_RBS_MASK: u32 = 0x0fff << RXDESC_1_RBS_SHIFT;
39const RXDESC_1_RCH: u32 = 1 << 14;
41const RXDESC_1_RER: u32 = 1 << 15;
43
44#[repr(C)]
45pub struct RxDescriptor {
47 desc: Descriptor,
48 buffer1: Option<u32>,
49 next_descriptor: Option<u32>,
50 packet_id: Option<PacketId>,
51 #[cfg(feature = "ptp")]
52 cached_timestamp: Option<Timestamp>,
53}
54
55impl Default for RxDescriptor {
56 fn default() -> Self {
57 Self::new()
58 }
59}
60
61impl RxDescriptor {
62 pub const fn new() -> Self {
64 Self {
65 desc: Descriptor::new(),
66 buffer1: None,
67 next_descriptor: None,
68 packet_id: None,
69 #[cfg(feature = "ptp")]
70 cached_timestamp: None,
71 }
72 }
73
74 fn is_owned(&self) -> bool {
76 (self.desc.read(0) & RXDESC_0_OWN) == RXDESC_0_OWN
77 }
78
79 pub fn set_owned(&mut self) {
83 self.write_buffer1();
84 self.write_buffer2();
85
86 #[cfg(feature = "fence")]
88 core::sync::atomic::fence(core::sync::atomic::Ordering::Release);
89 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::Release);
90
91 unsafe {
92 self.desc.write(0, RXDESC_0_OWN);
93 }
94
95 #[cfg(feature = "fence")]
98 core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst);
99 }
100
101 fn has_error(&self) -> bool {
102 (self.desc.read(0) & RXDESC_0_ES) == RXDESC_0_ES
103 }
104
105 fn is_first(&self) -> bool {
107 (self.desc.read(0) & RXDESC_0_FS) == RXDESC_0_FS
108 }
109
110 fn is_last(&self) -> bool {
112 (self.desc.read(0) & RXDESC_0_LS) == RXDESC_0_LS
113 }
114
115 #[cfg(feature = "ptp")]
117 pub fn timestamp(&self) -> Option<Timestamp> {
118 #[cfg(not(feature = "stm32f1xx-hal"))]
119 let is_valid = { self.desc.read(0) & RXDESC_0_TIMESTAMP_VALID == RXDESC_0_TIMESTAMP_VALID };
120
121 #[cfg(feature = "stm32f1xx-hal")]
122 let is_valid = true;
125
126 let timestamp = Timestamp::from_descriptor(&self.desc);
127
128 if is_valid && self.is_last() {
129 timestamp
130 } else {
131 None
132 }
133 }
134
135 fn write_buffer1(&mut self) {
142 let buffer_addr = self
143 .buffer1
144 .expect("Writing buffer1 of an RX descriptor, but `buffer_address` is None");
145
146 unsafe {
147 self.desc.write(2, buffer_addr);
148 }
149 }
150
151 fn set_buffer1(&mut self, buffer: *const u8, len: usize) {
152 self.buffer1 = Some(buffer as u32);
153 self.write_buffer1();
154 unsafe {
155 self.desc.modify(1, |w| {
156 (w & !RXDESC_1_RBS_MASK) | ((len as u32) << RXDESC_1_RBS_SHIFT)
157 });
158 }
159 }
160
161 fn write_buffer2(&mut self) {
168 let addr = self
169 .next_descriptor
170 .expect("Writing buffer2 of an RX descriptor, but `next_descriptor` is None");
171
172 unsafe {
173 self.desc.write(3, addr);
174 }
175 }
176
177 fn set_buffer2(&mut self, buffer: *const u8) {
179 self.next_descriptor = Some(buffer as u32);
180 self.write_buffer2();
181 }
182
183 fn set_end_of_ring(&mut self) {
184 unsafe {
185 self.desc.modify(1, |w| w | RXDESC_1_RER);
186 }
187 }
188
189 fn get_frame_len(&self) -> usize {
190 ((self.desc.read(0) >> RXDESC_0_FL_SHIFT) & RXDESC_0_FL_MASK) as usize
191 }
192}
193
194pub type RxRingEntry = RingEntry<RxDescriptor>;
196
197impl RingDescriptor for RxDescriptor {
198 fn setup(&mut self, buffer: *const u8, len: usize, next: Option<&Self>) {
199 unsafe {
201 self.desc.write(1, RXDESC_1_RCH);
202 }
203 self.set_buffer1(buffer, len);
204 match next {
205 Some(next) => self.set_buffer2(&next.desc as *const Descriptor as *const u8),
206 None => {
207 #[allow(clippy::zero_ptr)]
208 self.set_buffer2(0 as *const u8);
209 self.set_end_of_ring();
210 }
211 };
212 self.set_owned();
213 }
214}
215
216impl RxRingEntry {
217 pub const RX_INIT: Self = Self::new();
219
220 pub(super) fn is_available(&self) -> bool {
221 !self.desc().is_owned()
222 }
223
224 pub(super) fn recv(&mut self, packet_id: Option<PacketId>) -> Result<usize, RxDescriptorError> {
226 if self.desc().has_error() {
227 self.desc_mut().set_owned();
228 Err(RxDescriptorError::DmaError)
229 } else if self.desc().is_first() && self.desc().is_last() {
230 let frame_len = self.desc().get_frame_len();
231
232 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::Acquire);
234
235 #[cfg(feature = "ptp")]
236 {
237 self.desc_mut().cached_timestamp = self.desc().timestamp();
239 }
240
241 self.desc_mut().packet_id = packet_id;
243
244 Ok(frame_len)
245 } else {
246 self.desc_mut().set_owned();
247 Err(RxDescriptorError::Truncated)
248 }
249 }
250}
251
252#[cfg(feature = "ptp")]
253impl RxRingEntry {
254 pub fn has_packet_id(&self, id: &PacketId) -> bool {
255 Some(id) == self.desc().packet_id.as_ref()
256 }
257
258 pub fn read_timestamp(&self) -> Option<Timestamp> {
259 self.desc().cached_timestamp.clone()
260 }
261}