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