1#![doc = crate::before_snippet!()]
24use crate::{pac::trace::RegisterBlock, peripherals::TRACE0, system::PeripheralGuard};
38
39#[derive(Debug, Clone, Copy)]
41pub enum Error {
42 NotStarted,
44}
45
46#[derive(Debug, Clone, Copy)]
48pub struct TraceResult {
49 pub valid_start_index: usize,
51 pub valid_length: usize,
53}
54
55pub struct Trace<'d> {
57 peripheral: TRACE0<'d>,
58 buffer: Option<&'d mut [u8]>,
59 _guard: PeripheralGuard,
60}
61
62impl<'d> Trace<'d> {
63 pub fn new(peripheral: TRACE0<'d>) -> Self {
65 let guard = PeripheralGuard::new(peripheral.peripheral());
66
67 Self {
68 peripheral,
69 buffer: None,
70 _guard: guard,
71 }
72 }
73
74 pub fn start_trace(&mut self, buffer: &'d mut [u8]) {
76 let reg_block = self.peripheral.register_block();
77
78 reg_block
79 .mem_start_addr()
80 .modify(|_, w| unsafe { w.mem_start_addr().bits(buffer.as_ptr() as *const _ as u32) });
81 reg_block.mem_end_addr().modify(|_, w| unsafe {
82 w.mem_end_addr()
83 .bits((buffer.as_ptr() as *const _ as u32) + (buffer.len() as u32))
84 });
85 reg_block
86 .mem_addr_update()
87 .write(|w| w.mem_current_addr_update().set_bit());
88
89 reg_block
91 .intr_ena()
92 .modify(|_, w| w.mem_full_intr_ena().set_bit());
93
94 reg_block
96 .trigger()
97 .write(|w| w.mem_loop().set_bit().restart_ena().set_bit());
98
99 reg_block.intr_clr().write(|w| {
100 w.fifo_overflow_intr_clr()
101 .set_bit()
102 .mem_full_intr_clr()
103 .set_bit()
104 });
105
106 self.buffer.replace(buffer);
107 reg_block.trigger().write(|w| w.on().set_bit());
108 }
109
110 pub fn stop_trace(&mut self) -> Result<TraceResult, Error> {
115 let reg_block = self.peripheral.register_block();
116
117 reg_block
118 .trigger()
119 .write(|w| w.off().set_bit().restart_ena().clear_bit());
120
121 if self.buffer.is_none() {
122 return Err(Error::NotStarted);
123 }
124
125 let buffer = self.buffer.take().unwrap();
126
127 while !reg_block.fifo_status().read().fifo_empty().bit_is_set() {}
128
129 let overflow = reg_block.intr_raw().read().mem_full_intr_raw().bit();
130 let idx = if overflow {
131 reg_block
132 .mem_current_addr()
133 .read()
134 .mem_current_addr()
135 .bits()
136 - &buffer as *const _ as u32
137 } else {
138 0
139 };
140
141 let len = if overflow {
142 buffer.len()
143 } else {
144 reg_block
145 .mem_current_addr()
146 .read()
147 .mem_current_addr()
148 .bits() as usize
149 - buffer.as_ptr() as *const _ as usize
150 - 14 };
152
153 let mut valid = false;
154 let mut fourteen_zeroes = false;
155 let mut zeroes = 0;
156 let start_index = if !valid {
157 let mut i = 0;
158 loop {
159 let b = unsafe {
160 buffer
161 .as_ptr()
162 .add((i + idx as usize) % buffer.len())
163 .read_volatile()
164 };
165
166 if !valid {
167 if b == 0 {
168 zeroes += 1;
169 } else {
170 zeroes = 0;
171 }
172
173 if zeroes >= 14 {
174 fourteen_zeroes = true;
175 }
176
177 if fourteen_zeroes && b != 0 {
178 valid = true;
179 }
180 }
181
182 if valid {
183 break i;
184 }
185
186 i += 1;
187 }
188 } else {
189 0
190 };
191
192 Ok(TraceResult {
193 valid_start_index: start_index,
194 valid_length: len,
195 })
196 }
197}
198
199#[doc(hidden)]
201pub trait Instance: crate::private::Sealed {
202 fn register_block(&self) -> &RegisterBlock;
204
205 fn peripheral(&self) -> crate::system::Peripheral;
207}
208
209impl Instance for TRACE0<'_> {
210 fn register_block(&self) -> &RegisterBlock {
211 self.register_block()
212 }
213
214 fn peripheral(&self) -> crate::system::Peripheral {
215 crate::system::Peripheral::Trace0
216 }
217}