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