Contiki 2.5
cfs-coffee-arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * Coffee architecture-dependent functionality for the STM32W108-based mb851
36  * platform.
37  * \author
38  * Salvatore Pitrulli <salvopitru@users.sourceforge.net>
39  */
40 
41 
42 #include "cfs-coffee-arch.h"
43 
44 #define DEBUG 1
45 #if DEBUG
46 #include <stdio.h>
47 #define PRINTF(...) printf(__VA_ARGS__)
48 #else
49 #define PRINTF(...)
50 #endif
51 
52 #define TESTCOFFEE 1
53 #define DEBUG_CFS 1
54 #if TESTCOFFEE
55 #if DEBUG_CFS
56 #include <stdio.h>
57 #define PRINTF_CFS(...) printf(__VA_ARGS__)
58 #else
59 #define PRINTF_CFS(...)
60 #endif
61 
62 #include "cfs/cfs.h"
63 #include "cfs/cfs-coffee.h"
64 #include "lib/crc16.h"
65 #include "lib/random.h"
66 #include <stdio.h>
67 
68 #define FAIL(x) PRINTF("FAILED\n");error = (x); goto end;
69 
70 #define FILE_SIZE 512
71 
72 int
73 coffee_file_test(void)
74 {
75  int error;
76  int wfd, rfd, afd;
77  unsigned char buf[256], buf2[11];
78  int r, i, j, total_read;
79  unsigned offset;
80 
81  cfs_remove("T1");
82  cfs_remove("T2");
83  cfs_remove("T3");
84  cfs_remove("T4");
85  cfs_remove("T5");
86 
87  wfd = rfd = afd = -1;
88 
89  for(r = 0; r < sizeof(buf); r++) {
90  buf[r] = r;
91  }
92 
93  PRINTF("TEST 1\n");
94 
95  /* Test 1: Open for writing. */
96  wfd = cfs_open("T1", CFS_WRITE);
97  if(wfd < 0) {
98  FAIL(-1);
99  }
100 
101  PRINTF("PASSED\n");
102  PRINTF("TEST ");
103  PRINTF("2\n");
104 
105  /* Test 2: Write buffer. */
106  r = cfs_write(wfd, buf, sizeof(buf));
107  if(r < 0) {
108  FAIL(-2);
109  } else if(r < sizeof(buf)) {
110  FAIL(-3);
111  }
112 
113  PRINTF("PASSED\n");
114  PRINTF("TEST ");
115  PRINTF("3\n");
116 
117  /* Test 3: Deny reading. */
118  r = cfs_read(wfd, buf, sizeof(buf));
119  if(r >= 0) {
120  FAIL(-4);
121  }
122 
123  PRINTF("PASSED\n");
124  PRINTF("TEST ");
125  PRINTF("4\n");
126 
127  /* Test 4: Open for reading. */
128  rfd = cfs_open("T1", CFS_READ);
129  if(rfd < 0) {
130  FAIL(-5);
131  }
132 
133  PRINTF("PASSED\n");
134  PRINTF("TEST ");
135  PRINTF("5\n");
136 
137  /* Test 5: Write to read-only file. */
138  r = cfs_write(rfd, buf, sizeof(buf));
139  if(r >= 0) {
140  FAIL(-6);
141  }
142 
143  PRINTF("PASSED\n");
144  PRINTF("TEST ");
145  PRINTF("7\n");
146 
147  /* Test 7: Read the buffer written in Test 2. */
148  memset(buf, 0, sizeof(buf));
149  r = cfs_read(rfd, buf, sizeof(buf));
150  if(r < 0) {
151  FAIL(-8);
152  } else if(r < sizeof(buf)) {
153  PRINTF_CFS("r=%d\n", r);
154  FAIL(-9);
155  }
156 
157  PRINTF("PASSED\n");
158  PRINTF("TEST ");
159  PRINTF("8\n");
160 
161  /* Test 8: Verify that the buffer is correct. */
162  for(r = 0; r < sizeof(buf); r++) {
163  if(buf[r] != r) {
164  PRINTF_CFS("r=%d. buf[r]=%d\n", r, buf[r]);
165  FAIL(-10);
166  }
167  }
168 
169  PRINTF("PASSED\n");
170  PRINTF("TEST ");
171  PRINTF("9\n");
172 
173  /* Test 9: Seek to beginning. */
174  if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) {
175  FAIL(-11);
176  }
177 
178  PRINTF("PASSED\n");
179  PRINTF("TEST ");
180  PRINTF("10\n");
181 
182  /* Test 10: Write to the log. */
183  r = cfs_write(wfd, buf, sizeof(buf));
184  if(r < 0) {
185  FAIL(-12);
186  } else if(r < sizeof(buf)) {
187  FAIL(-13);
188  }
189 
190  PRINTF("PASSED\n");
191  PRINTF("TEST ");
192  PRINTF("11\n");
193 
194  /* Test 11: Read the data from the log. */
195  cfs_seek(rfd, 0, CFS_SEEK_SET);
196  memset(buf, 0, sizeof(buf));
197  r = cfs_read(rfd, buf, sizeof(buf));
198  if(r < 0) {
199  FAIL(-14);
200  } else if(r < sizeof(buf)) {
201  FAIL(-15);
202  }
203 
204  PRINTF("PASSED\n");
205  PRINTF("TEST ");
206  PRINTF("12\n");
207 
208  /* Test 12: Verify that the data is correct. */
209  for(r = 0; r < sizeof(buf); r++) {
210  if(buf[r] != r) {
211  FAIL(-16);
212  }
213  }
214 
215  PRINTF("PASSED\n");
216  PRINTF("TEST ");
217  PRINTF("13\n");
218 
219  /* Test 13: Write a reversed buffer to the file. */
220  for(r = 0; r < sizeof(buf); r++) {
221  buf[r] = sizeof(buf) - r - 1;
222  }
223  if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) {
224  FAIL(-17);
225  }
226  r = cfs_write(wfd, buf, sizeof(buf));
227  if(r < 0) {
228  FAIL(-18);
229  } else if(r < sizeof(buf)) {
230  FAIL(-19);
231  }
232  if(cfs_seek(rfd, 0, CFS_SEEK_SET) != 0) {
233  FAIL(-20);
234  }
235 
236  PRINTF("PASSED\n");
237  PRINTF("TEST ");
238  PRINTF("14\n");
239 
240  /* Test 14: Read the reversed buffer. */
241  cfs_seek(rfd, 0, CFS_SEEK_SET);
242  memset(buf, 0, sizeof(buf));
243  r = cfs_read(rfd, buf, sizeof(buf));
244  if(r < 0) {
245  FAIL(-21);
246  } else if(r < sizeof(buf)) {
247  PRINTF_CFS("r = %d\n", r);
248  FAIL(-22);
249  }
250 
251  PRINTF("PASSED\n");
252  PRINTF("TEST ");
253  PRINTF("15\n");
254 
255  /* Test 15: Verify that the data is correct. */
256  for(r = 0; r < sizeof(buf); r++) {
257  if(buf[r] != sizeof(buf) - r - 1) {
258  FAIL(-23);
259  }
260  }
261 
262  cfs_close(rfd);
263  cfs_close(wfd);
264 
265  if(cfs_coffee_reserve("T2", FILE_SIZE) < 0) {
266  FAIL(-24);
267  }
268 
269  PRINTF("PASSED\n");
270  PRINTF("TEST ");
271  PRINTF("16\n");
272 
273  /* Test 16: Test multiple writes at random offset. */
274  for(r = 0; r < 100; r++) {
275  wfd = cfs_open("T2", CFS_WRITE | CFS_READ);
276  if(wfd < 0) {
277  FAIL(-25);
278  }
279 
280  offset = random_rand() % FILE_SIZE;
281 
282  for(r = 0; r < sizeof(buf); r++) {
283  buf[r] = r;
284  }
285 
286  if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) {
287  FAIL(-26);
288  }
289 
290  if(cfs_write(wfd, buf, sizeof(buf)) != sizeof(buf)) {
291  FAIL(-27);
292  }
293 
294  if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) {
295  FAIL(-28);
296  }
297 
298  memset(buf, 0, sizeof(buf));
299  if(cfs_read(wfd, buf, sizeof(buf)) != sizeof(buf)) {
300  FAIL(-29);
301  }
302 
303  for(i = 0; i < sizeof(buf); i++) {
304  if(buf[i] != i) {
305  PRINTF_CFS("buf[%d] != %d\n", i, buf[i]);
306  FAIL(-30);
307  }
308  }
309  }
310  PRINTF("PASSED\n");
311  PRINTF("TEST ");
312  PRINTF("17\n");
313  /* Test 17: Append data to the same file many times. */
314 #define APPEND_BYTES 3000
315 #define BULK_SIZE 10
316  for (i = 0; i < APPEND_BYTES; i += BULK_SIZE) {
317  afd = cfs_open("T3", CFS_WRITE | CFS_APPEND);
318  if (afd < 0) {
319  FAIL(-31);
320  }
321  for (j = 0; j < BULK_SIZE; j++) {
322  buf[j] = 1 + ((i + j) & 0x7f);
323  }
324  if ((r = cfs_write(afd, buf, BULK_SIZE)) != BULK_SIZE) {
325  PRINTF_CFS("Count:%d, r=%d\n", i, r);
326  FAIL(-32);
327  }
328  cfs_close(afd);
329  }
330 
331  PRINTF("PASSED\n");
332  PRINTF("TEST ");
333  PRINTF("18\n");
334 
335  /* Test 18: Read back the data written in Test 17 and verify that it
336  is correct. */
337  afd = cfs_open("T3", CFS_READ);
338  if(afd < 0) {
339  FAIL(-33);
340  }
341  total_read = 0;
342  while((r = cfs_read(afd, buf2, sizeof(buf2))) > 0) {
343  for(j = 0; j < r; j++) {
344  if(buf2[j] != 1 + ((total_read + j) & 0x7f)) {
345  FAIL(-34);
346  }
347  }
348  total_read += r;
349  }
350  if(r < 0) {
351  PRINTF_CFS("FAIL:-35 r=%d\n",r);
352  FAIL(-35);
353  }
354  if(total_read != APPEND_BYTES) {
355  PRINTF_CFS("FAIL:-35 total_read=%d\n",total_read);
356  FAIL(-35);
357  }
358  cfs_close(afd);
359 
360  PRINTF("PASSED\n");
361  PRINTF("TEST ");
362  PRINTF("19\n");
363 
364 /***************T4********************/
365 /* file T4 and T5 writing forces to use garbage collector in greedy mode
366  * this test is designed for 10kb of file system
367  * */
368 #define APPEND_BYTES_1 2000
369 #define BULK_SIZE_1 10
370  for (i = 0; i < APPEND_BYTES_1; i += BULK_SIZE_1) {
371  afd = cfs_open("T4", CFS_WRITE | CFS_APPEND);
372  if (afd < 0) {
373  FAIL(-36);
374  }
375  for (j = 0; j < BULK_SIZE_1; j++) {
376  buf[j] = 1 + ((i + j) & 0x7f);
377  }
378 
379  if ((r = cfs_write(afd, buf, BULK_SIZE_1)) != BULK_SIZE_1) {
380  PRINTF_CFS("Count:%d, r=%d\n", i, r);
381  FAIL(-37);
382  }
383  cfs_close(afd);
384  }
385 
386  afd = cfs_open("T4", CFS_READ);
387  if(afd < 0) {
388  FAIL(-38);
389  }
390  total_read = 0;
391  while((r = cfs_read(afd, buf2, sizeof(buf2))) > 0) {
392  for(j = 0; j < r; j++) {
393  if(buf2[j] != 1 + ((total_read + j) & 0x7f)) {
394  PRINTF_CFS("FAIL:-39, total_read=%d r=%d\n",total_read,r);
395  FAIL(-39);
396  }
397  }
398  total_read += r;
399  }
400  if(r < 0) {
401  PRINTF_CFS("FAIL:-40 r=%d\n",r);
402  FAIL(-40);
403  }
404  if(total_read != APPEND_BYTES_1) {
405  PRINTF_CFS("FAIL:-41 total_read=%d\n",total_read);
406  FAIL(-41);
407  }
408  cfs_close(afd);
409  /***************T5********************/
410  PRINTF("PASSED\n");
411  PRINTF("TEST ");
412  PRINTF("20\n");
413 #define APPEND_BYTES_2 1000
414 #define BULK_SIZE_2 10
415  for (i = 0; i < APPEND_BYTES_2; i += BULK_SIZE_2) {
416  afd = cfs_open("T5", CFS_WRITE | CFS_APPEND);
417  if (afd < 0) {
418  FAIL(-42);
419  }
420  for (j = 0; j < BULK_SIZE_2; j++) {
421  buf[j] = 1 + ((i + j) & 0x7f);
422  }
423 
424  if ((r = cfs_write(afd, buf, BULK_SIZE_2)) != BULK_SIZE_2) {
425  PRINTF_CFS("Count:%d, r=%d\n", i, r);
426  FAIL(-43);
427  }
428 
429  cfs_close(afd);
430  }
431 
432  afd = cfs_open("T5", CFS_READ);
433  if(afd < 0) {
434  FAIL(-44);
435  }
436  total_read = 0;
437  while((r = cfs_read(afd, buf2, sizeof(buf2))) > 0) {
438  for(j = 0; j < r; j++) {
439  if(buf2[j] != 1 + ((total_read + j) & 0x7f)) {
440  PRINTF_CFS("FAIL:-45, total_read=%d r=%d\n",total_read,r);
441  FAIL(-45);
442  }
443  }
444  total_read += r;
445  }
446  if(r < 0) {
447  PRINTF_CFS("FAIL:-46 r=%d\n",r);
448  FAIL(-46);
449  }
450  if(total_read != APPEND_BYTES_2) {
451  PRINTF_CFS("FAIL:-47 total_read=%d\n",total_read);
452  FAIL(-47);
453  }
454  cfs_close(afd);
455 
456  PRINTF("PASSED\n");
457 
458  error = 0;
459 end:
460  cfs_close(wfd); cfs_close(rfd); cfs_close(afd);
461  return error;
462 }
463 #endif /* TESTCOFFEE */
464 
465 void stm32w_flash_read(int32u address, void * data, int32u length)
466 {
467  int8u * pdata = (int8u *)address;
468  ENERGEST_ON(ENERGEST_TYPE_FLASH_READ);
469  memcpy(data, pdata, length);
470  ENERGEST_OFF(ENERGEST_TYPE_FLASH_READ);
471 }
472 
473 void stm32w_flash_erase(int8u sector)
474 {
475  //halInternalFlashErase(MFB_PAGE_ERASE, COFFEE_START + (sector) * COFFEE_SECTOR_SIZE);
476 
477  int16u data = 0;
478  int32u addr = COFFEE_START + (sector) * COFFEE_SECTOR_SIZE;
479  int32u end = addr + COFFEE_SECTOR_SIZE;
480 
481  /* This prevents from accidental write to CIB. */
482  if (!(addr >= MFB_BOTTOM && end <= MFB_TOP + 1)) {
483  return;
484  }
485 
486  for(; addr < end; addr += 2){
487  halInternalFlashWrite(addr, &data, 1);
488  }
489 }
490 
491 // Allocates a buffer of FLASH_PAGE_SIZE bytes statically (rather than on the stack).
492 #ifndef STATIC_FLASH_BUFFER
493 #define STATIC_FLASH_BUFFER 1
494 #endif
495 
496 void stm32w_flash_write(int32u address, const void * data, int32u length)
497 {
498  const int32u end = address + length;
499  int32u i;
500  int32u next_page, curr_page;
501  int16u offset;
502 
503 #if STATIC_FLASH_BUFFER
504  static int8u buf[FLASH_PAGE_SIZE];
505 #else
506  int8u buf[FLASH_PAGE_SIZE];
507 #endif
508 
509  for(i = address; i < end;) {
510  next_page = (i | (FLASH_PAGE_SIZE-1)) + 1;
511  curr_page = i & ~(FLASH_PAGE_SIZE-1);
512  offset = i-curr_page;
513  if(next_page > end) {
514  next_page = end;
515  }
516 
517  // Read a page from flash and put it into a mirror buffer.
518  stm32w_flash_read(curr_page, buf, FLASH_PAGE_SIZE);
519  // Update flash mirror data with new data.
520  memcpy(buf + offset, data, next_page - i);
521  // Erase flash page.
522  ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE);
523  halInternalFlashErase(MFB_PAGE_ERASE, i);
524  // Write modified data form mirror buffer into the flash.
525  halInternalFlashWrite(curr_page, (int16u *)buf, FLASH_PAGE_SIZE/2);
526  ENERGEST_OFF(ENERGEST_TYPE_FLASH_WRITE);
527 
528  data = (u8_t *)data + next_page - i;
529  i = next_page;
530  }
531 
532 }
533