ruuvi.drivers.c  ${PROJECT_VERSION}
Drivers for external sensors and peripherals on embedded systems.
ruuvi_interface_flash_test.c
Go to the documentation of this file.
2 #if RUUVI_RUN_TESTS
3 #include "ruuvi_driver_error.h"
4 #include "ruuvi_driver_test.h"
8 #include <stdbool.h>
9 #include <string.h>
22 #define F_BIG_RECORD_SIZE 0x900U
23 #define F_TEST_PAGE 0x0002U
24 #define F_TEST_RECORD 0x0001U
25 static const char __attribute__ ( (aligned (4))) f_data1[] = "Flash test data 1";
26 static const char __attribute__ ( (aligned (4))) f_data2[] = "Flash test data 2";
27 static uint32_t boot_count = 0;
28 
38 static bool ri_flash_init_test (const rd_test_print_fp printfp)
39 {
40  rd_status_t err_code = RD_SUCCESS;
41  bool status = false;
42  printfp ("\"init\":");
43  err_code = ri_flash_init();
44 
45  if (RD_SUCCESS != err_code)
46  {
47  status = true;
50  }
51  else
52  {
53  err_code = ri_flash_init();
54 
55  if (RD_ERROR_INVALID_STATE != err_code)
56  {
57  status = true;
58  }
59  }
60 
61  err_code |= ri_flash_record_get (APP_FLASH_LOG_FILE, APP_FLASH_LOG_BOOT_COUNTER_RECORD,
62  sizeof (uint32_t), &boot_count);
63 
64  if (status)
65  {
66  printfp ("\"fail\",\r\n");
67  }
68  else
69  {
70  printfp ("\"pass\",\r\n");
71  }
72 
73  return status;
74 }
75 
88 static bool ri_flash_uninit_test (const rd_test_print_fp printfp)
89 {
90  rd_status_t err_code = RD_SUCCESS;
91  bool status = false;
92  printfp ("\"uninit\":");
93  err_code = ri_flash_uninit();
94 
95  if (RD_SUCCESS != err_code)
96  {
97  status = true;
98  }
99  else
100  {
101  err_code = ri_flash_init();
102  err_code |= ri_flash_uninit();
103  err_code = ri_flash_init();
104 
105  if (RD_SUCCESS != err_code)
106  {
107  status = true;
108  }
109  }
110 
111  if (status)
112  {
113  printfp ("\"fail\",\r\n");
114  }
115  else
116  {
117  printfp ("\"pass\",\r\n");
118  }
119 
120  return status;
121 }
122 
129 static bool ri_flash_store_test (const rd_test_print_fp printfp)
130 {
131  rd_status_t err_code = RD_SUCCESS;
132  bool status = false;
133  printfp ("\"store\":");
134  err_code = ri_flash_uninit();
135  err_code = ri_flash_record_set (F_TEST_PAGE, F_TEST_RECORD, sizeof (f_data1), f_data1);
136 
137  if (RD_SUCCESS == err_code)
138  {
139  status = true;
140  }
141  else
142  {
143  err_code = ri_flash_init();
144  err_code |= ri_flash_record_set (F_TEST_PAGE, F_TEST_RECORD, sizeof (f_data1), f_data1);
145  err_code |= ri_flash_record_set (F_TEST_PAGE, F_TEST_RECORD, sizeof (f_data2), f_data2);
146 
147  if (RD_SUCCESS != err_code)
148  {
149  status = true;
150  }
151  else
152  {
153  err_code |= ri_flash_record_set (F_TEST_PAGE, F_TEST_RECORD, UINT16_MAX, f_data2);
154 
155  if (RD_ERROR_DATA_SIZE != err_code)
156  {
157  status = true;
158  }
159  }
160  }
161 
162  if (status)
163  {
164  printfp ("\"fail\",\r\n");
165  }
166  else
167  {
168  printfp ("\"pass\",\r\n");
169  }
170 
171  return status;
172 }
173 
180 static bool ri_flash_load_test (const rd_test_print_fp printfp)
181 {
182  rd_status_t err_code = RD_SUCCESS;
183  bool status = false;
184  // Ensure we can align into 4-byte boundary.
185  char load_buffer[sizeof (f_data2) + 4] = {0};
186  printfp ("\"load\":");
187  err_code = ri_flash_uninit();
188  err_code |= ri_flash_record_get (F_TEST_PAGE, F_TEST_RECORD, sizeof (f_data1),
189  load_buffer);
190 
191  if (RD_SUCCESS == err_code)
192  {
193  status = true;
194  }
195  else
196  {
197  err_code = ri_flash_init();
198  err_code |= ri_flash_record_get (F_TEST_PAGE, F_TEST_RECORD, sizeof (load_buffer),
199  load_buffer);
200 
201  if (RD_SUCCESS != err_code
202  || strcmp (f_data2, load_buffer))
203  {
204  status = true;
205  }
206  }
207 
208  if (status)
209  {
210  printfp ("\"fail\",\r\n");
211  }
212  else
213  {
214  printfp ("\"pass\",\r\n");
215  }
216 
217  return status;
218 }
219 
226 static bool ri_flash_delete_test (const rd_test_print_fp printfp)
227 {
228  rd_status_t err_code = RD_SUCCESS;
229  bool status = false;
230  // Ensure we can align into 4-byte boundary.
231  char load_buffer[sizeof (f_data2) + 4] = {0};
232  printfp ("\"free\":");
233  err_code = ri_flash_uninit();
234  err_code |= ri_flash_record_delete (F_TEST_PAGE, F_TEST_RECORD);
235 
236  if (RD_SUCCESS == err_code)
237  {
238  status = true;
239  }
240  else
241  {
242  err_code = ri_flash_init();
243  err_code |= ri_flash_record_delete (F_TEST_PAGE, F_TEST_RECORD);
244 
245  if (RD_SUCCESS != err_code)
246  {
247  status = true;
248  }
249  else
250  {
251  err_code |= ri_flash_record_get (F_TEST_PAGE, F_TEST_RECORD, sizeof (load_buffer),
252  load_buffer);
253 
254  if (RD_ERROR_NOT_FOUND != err_code)
255  {
256  status = true;
257  }
258  }
259  }
260 
261  if (status)
262  {
263  printfp ("\"fail\",\r\n");
264  }
265  else
266  {
267  printfp ("\"pass\",\r\n");
268  }
269 
270  (void) ri_flash_uninit();
271  return status;
272 }
273 
283 static bool ri_flash_gc_size_busy_test (const rd_test_print_fp printfp)
284 {
285  rd_status_t err_code = RD_SUCCESS;
286  bool status = false;
287  printfp ("\"gc\":");
288  err_code = ri_flash_uninit();
289  err_code |= ri_flash_gc_run();
290 
291  if (RD_SUCCESS == err_code)
292  {
293  status = true;
294  }
295  else
296  {
297  err_code = ri_flash_init();
298  size_t size;
299 
300  // Test that checking free size works
301  do
302  {
303  while (ri_flash_is_busy()) {};
304 
305  err_code = ri_flash_record_set (F_TEST_PAGE, F_TEST_RECORD, sizeof (f_data1), f_data1);
306 
307  err_code |= ri_flash_free_size_get (&size);
308  } while ( ( (F_BIG_RECORD_SIZE < size) && (RD_SUCCESS == err_code))
309 
310  || (RD_ERROR_BUSY == err_code));
311 
312  // Test that garbage collection works
313  err_code = ri_flash_gc_run();
314 
315  while (ri_flash_is_busy()) {};
316 
317  err_code |= ri_flash_free_size_get (&size);
318 
319  if ( (RD_SUCCESS != err_code) || (F_BIG_RECORD_SIZE > size))
320  {
321  status = true;
322  }
323  }
324 
325  if (status)
326  {
327  printfp ("\"fail\"\r\n");
328  }
329  else
330  {
331  printfp ("\"pass\"\r\n");
332  }
333 
334  err_code |= ri_flash_record_set (APP_FLASH_LOG_FILE, APP_FLASH_LOG_BOOT_COUNTER_RECORD,
335  sizeof (uint32_t), &boot_count);
336  err_code = ri_flash_uninit();
337  return status;
338 }
339 
347 {
348  bool status = false;
349  printfp ("\"flash\":{\r\n");
350  status |= ri_flash_init_test (printfp);
351  status |= ri_flash_uninit_test (printfp);
352  status |= ri_flash_store_test (printfp);
353  status |= ri_flash_load_test (printfp);
354  status |= ri_flash_delete_test (printfp);
355  status |= ri_flash_gc_size_busy_test (printfp);
356  printfp ("},\r\n");
357  return status;
358 }
359 
360 /* @} */
361 #endif
uint32_t rd_status_t
bitfield for representing errors
#define RD_SUCCESS
Internal Error.
#define RD_ERROR_DATA_SIZE
Invalid Data size.
#define RD_ERROR_NOT_FOUND
Not found.
#define RD_ERROR_INVALID_STATE
Invalid state, operation disallowed in this state.
#define RD_ERROR_BUSY
Busy.
rd_status_t ri_flash_gc_run(void)
Run garbage collection.
bool ri_flash_run_integration_test(const rd_test_print_fp printfp)
Run all flash tests.
bool ri_flash_is_busy()
Check if flash is busy.
rd_status_t ri_flash_uninit(void)
Unintialize flash. After uninitialization only initialization can be used.
void ri_flash_purge(void)
Purge flash.
rd_status_t ri_flash_record_set(const uint32_t page_id, const uint32_t record_id, const size_t data_size, const void *const data)
Set data to record in page.
rd_status_t ri_flash_init(void)
rd_status_t ri_flash_record_delete(const uint32_t file_id, const uint32_t record_id)
Mark a record for deletion.
rd_status_t ri_flash_free_size_get(size_t *size)
Get total size of free flash.
rd_status_t ri_flash_record_get(const uint32_t page_id, const uint32_t record_id, const size_t data_size, void *const data)
Get data from record in page.
void(* rd_test_print_fp)(const char *const msg)
function pointer to print test information
Header to enable and disable module compilation.
Ruuvi error codes and error check function.
Functions for testing drivers.
Interface functions to persistent flash storage.
void ri_power_reset(void)
Reset IC.