1use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
26use capsules_extra::log;
27use core::cell::Cell;
28use core::ptr::addr_of_mut;
29use kernel::debug_verbose;
30use kernel::hil::flash;
31use kernel::hil::log::{LogRead, LogReadClient, LogWrite, LogWriteClient};
32use kernel::hil::time::{Alarm, AlarmClient, ConvertTicks};
33use kernel::static_init;
34use kernel::storage_volume;
35use kernel::utilities::cells::{NumericCellExt, TakeCell};
36use kernel::ErrorCode;
37use nrf52840::{
38 nvmc::{NrfPage, Nvmc},
39 rtc::Rtc,
40};
41
42storage_volume!(LINEAR_TEST_LOG, 8);
44
45pub unsafe fn run(mux_alarm: &'static MuxAlarm<'static, Rtc>, flash_controller: &'static Nvmc) {
46 flash_controller.configure_writeable();
48 flash_controller.configure_eraseable();
49 let pagebuffer = static_init!(NrfPage, NrfPage::default());
50
51 let log = static_init!(
53 Log,
54 log::Log::new(&LINEAR_TEST_LOG, flash_controller, pagebuffer, false)
55 );
56 flash::HasClient::set_client(flash_controller, log);
57 kernel::deferred_call::DeferredCallClient::register(log);
58
59 let alarm = static_init!(
60 VirtualMuxAlarm<'static, Rtc>,
61 VirtualMuxAlarm::new(mux_alarm)
62 );
63 alarm.setup();
64
65 let test = static_init!(
67 LogTest<VirtualMuxAlarm<'static, Rtc>>,
68 LogTest::new(log, &mut *addr_of_mut!(BUFFER), alarm, &TEST_OPS)
69 );
70 log.set_read_client(test);
71 log.set_append_client(test);
72 test.alarm.set_alarm_client(test);
73
74 test.run();
75}
76
77static TEST_OPS: [TestOp; 9] = [
78 TestOp::Read,
79 TestOp::Write(64),
81 TestOp::Write(2400),
82 TestOp::Write(2432),
84 TestOp::Write(2448),
86 TestOp::Write(72),
88 TestOp::Read,
90 TestOp::Sync,
91 TestOp::Write(2464),
93];
94
95static mut BUFFER: [u8; 2480] = [0; 2480];
97const WAIT_MS: u32 = 100;
99
100#[derive(Clone, Copy, PartialEq, Debug)]
102enum TestOp {
103 Read,
104 Write(usize),
105 Sync,
106}
107
108type Log = log::Log<'static, Nvmc>;
109
110struct LogTest<A: 'static + Alarm<'static>> {
111 log: &'static Log,
112 buffer: TakeCell<'static, [u8]>,
113 alarm: &'static A,
114 ops: &'static [TestOp],
115 op_index: Cell<usize>,
116}
117
118impl<A: 'static + Alarm<'static>> LogTest<A> {
119 fn new(
120 log: &'static Log,
121 buffer: &'static mut [u8],
122 alarm: &'static A,
123 ops: &'static [TestOp],
124 ) -> LogTest<A> {
125 debug_verbose!(
126 "Log recovered from flash (Start and end entry IDs: {:?} to {:?})",
127 log.log_start(),
128 log.log_end()
129 );
130
131 LogTest {
132 log,
133 buffer: TakeCell::new(buffer),
134 alarm,
135 ops,
136 op_index: Cell::new(0),
137 }
138 }
139
140 fn run(&self) {
141 if self.op_index.get() == self.ops.len() {
142 debug_verbose!("Success!")
143 } else {
144 debug_verbose!(
145 "Executing operation {} of {} - {:?}.",
146 self.op_index.get() + 1,
147 self.ops.len(),
148 self.ops[self.op_index.get()]
149 );
150 match self.ops[self.op_index.get()] {
151 TestOp::Read => self.read(),
152 TestOp::Write(length) => self.write(length),
153 TestOp::Sync => self.sync(),
154 }
155 }
156 }
157
158 fn read(&self) {
159 match self.buffer.take() {
160 Some(buffer) => {
161 for e in buffer.iter_mut() {
163 *e = 0;
164 }
165
166 match self.log.read(buffer, buffer.len()) {
167 Ok(()) => debug_verbose!("Dispatched asynchronous read operation."),
168 Err((return_code, buffer)) => {
169 self.buffer.replace(buffer);
170 match return_code {
171 ErrorCode::FAIL => {
172 debug_verbose!(
174 "READ DONE: READ OFFSET: {:?} / WRITE OFFSET: {:?}",
175 self.log.next_read_entry_id(),
176 self.log.log_end()
177 );
178 self.op_index.increment();
179 self.run();
180 }
181 ErrorCode::BUSY => {
182 debug_verbose!("Flash busy, waiting before reattempting read");
183 self.wait();
184 }
185 _ => panic!("READ FAILED: {:?}", return_code),
186 }
187 }
188 }
189 }
190 None => panic!("NO BUFFER"),
191 }
192 }
193
194 fn write(&self, len: usize) {
195 self.buffer
196 .take()
197 .map(move |buffer| {
198 let expect_write_fail = self.log.log_end() + len > LINEAR_TEST_LOG.len();
199
200 for i in 0..buffer.len() {
202 buffer[i] = if i < len {
203 len as u8
204 } else {
205 0
206 };
207 }
208
209 if let Err((error, original_buffer)) = self.log.append(buffer, len) {
210 self.buffer.replace(original_buffer);
211
212 match error {
213 ErrorCode::FAIL =>
214 if expect_write_fail {
215 debug_verbose!(
216 "Write failed on {} byte write, as expected",
217 len
218 );
219 self.op_index.increment();
220 self.run();
221 } else {
222 panic!(
223 "Write failed unexpectedly on {} byte write (read entry ID: {:?}, append entry ID: {:?})",
224 len,
225 self.log.next_read_entry_id(),
226 self.log.log_end()
227 );
228 }
229 ErrorCode::BUSY => self.wait(),
230 _ => panic!("WRITE FAILED: {:?}", error),
231 }
232 } else if expect_write_fail {
233 panic!(
234 "Write succeeded unexpectedly on {} byte write (read entry ID: {:?}, append entry ID: {:?})",
235 len,
236 self.log.next_read_entry_id(),
237 self.log.log_end()
238 );
239 }
240 })
241 .unwrap();
242 }
243
244 fn sync(&self) {
245 match self.log.sync() {
246 Ok(()) => (),
247 error => panic!("Sync failed: {:?}", error),
248 }
249 }
250
251 fn wait(&self) {
252 let delay = self.alarm.ticks_from_ms(WAIT_MS);
253 let now = self.alarm.now();
254 self.alarm.set_alarm(now, delay);
255 }
256}
257
258impl<A: Alarm<'static>> LogReadClient for LogTest<A> {
259 fn read_done(&self, buffer: &'static mut [u8], length: usize, error: Result<(), ErrorCode>) {
260 match error {
261 Ok(()) => {
262 assert!(length > 0);
264 for i in 0..length {
265 if buffer[i] != length as u8 {
266 panic!(
267 "Read incorrect value {} at index {}, expected {}",
268 buffer[i], i, length
269 );
270 }
271 }
272
273 debug_verbose!("Successful read of size {}", length);
274 self.buffer.replace(buffer);
275 self.wait();
276 }
277 _ => {
278 panic!("Read failed unexpectedly!");
279 }
280 }
281 }
282
283 fn seek_done(&self, _error: Result<(), ErrorCode>) {
284 unreachable!();
285 }
286}
287
288impl<A: Alarm<'static>> LogWriteClient for LogTest<A> {
289 fn append_done(
290 &self,
291 buffer: &'static mut [u8],
292 length: usize,
293 records_lost: bool,
294 error: Result<(), ErrorCode>,
295 ) {
296 assert!(!records_lost);
297 match error {
298 Ok(()) => {
299 debug_verbose!("Write succeeded on {} byte write, as expected", length);
300
301 self.buffer.replace(buffer);
302 self.op_index.increment();
303 self.wait();
304 }
305 error => panic!("WRITE FAILED IN CALLBACK: {:?}", error),
306 }
307 }
308
309 fn sync_done(&self, error: Result<(), ErrorCode>) {
310 if error == Ok(()) {
311 debug_verbose!(
312 "SYNC DONE: READ OFFSET: {:?} / WRITE OFFSET: {:?}",
313 self.log.next_read_entry_id(),
314 self.log.log_end()
315 );
316 } else {
317 panic!("Sync failed: {:?}", error);
318 }
319
320 self.op_index.increment();
321 self.run();
322 }
323
324 fn erase_done(&self, _error: Result<(), ErrorCode>) {
325 unreachable!();
326 }
327}
328
329impl<A: Alarm<'static>> AlarmClient for LogTest<A> {
330 fn alarm(&self) {
331 self.run();
332 }
333}