Contiki 2.6

cfs-coffee-arch.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2009, Swedish Institute of Computer Science
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the Institute nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  *
00029  * This file is part of the Contiki operating system.
00030  *
00031  */
00032 
00033 /**
00034  * \file
00035  *  Coffee architecture-dependent functionality for the STM32W108-based mb851
00036  *  platform.
00037  * \author
00038  *  Salvatore Pitrulli <salvopitru@users.sourceforge.net>
00039  */
00040 
00041 
00042 #include "cfs-coffee-arch.h"
00043 
00044 #define DEBUG 1
00045 #if DEBUG
00046 #include <stdio.h>
00047 #define PRINTF(...) printf(__VA_ARGS__)
00048 #else
00049 #define PRINTF(...)
00050 #endif
00051 
00052 #define TESTCOFFEE 1
00053 #define DEBUG_CFS 1
00054 #if TESTCOFFEE
00055 #if DEBUG_CFS
00056 #include <stdio.h>
00057 #define PRINTF_CFS(...) printf(__VA_ARGS__)
00058 #else
00059 #define PRINTF_CFS(...)
00060 #endif
00061 
00062 #include "cfs/cfs.h"
00063 #include "cfs/cfs-coffee.h"
00064 #include "lib/crc16.h"
00065 #include "lib/random.h"
00066 #include <stdio.h>
00067 
00068 #define FAIL(x) PRINTF("FAILED\n");error = (x); goto end;
00069 
00070 #define FILE_SIZE 512
00071 
00072 int
00073 coffee_file_test(void)
00074 {
00075   int error;
00076   int wfd, rfd, afd;
00077   unsigned char buf[256], buf2[11];
00078   int r, i, j, total_read;
00079   unsigned offset;
00080 
00081   cfs_remove("T1");
00082   cfs_remove("T2");
00083   cfs_remove("T3");
00084   cfs_remove("T4");
00085   cfs_remove("T5");
00086 
00087   wfd = rfd = afd = -1;
00088 
00089   for(r = 0; r < sizeof(buf); r++) {
00090     buf[r] = r;
00091   }
00092   
00093   PRINTF("TEST 1\n");
00094 
00095   /* Test 1: Open for writing. */
00096   wfd = cfs_open("T1", CFS_WRITE);
00097   if(wfd < 0) {
00098     FAIL(-1);
00099   }
00100   
00101   PRINTF("PASSED\n");
00102   PRINTF("TEST ");
00103   PRINTF("2\n");
00104 
00105   /* Test 2: Write buffer. */
00106   r = cfs_write(wfd, buf, sizeof(buf));
00107   if(r < 0) {
00108     FAIL(-2);
00109   } else if(r < sizeof(buf)) {
00110     FAIL(-3);
00111   }
00112   
00113   PRINTF("PASSED\n");
00114   PRINTF("TEST ");
00115   PRINTF("3\n");
00116 
00117   /* Test 3: Deny reading. */
00118   r = cfs_read(wfd, buf, sizeof(buf));
00119   if(r >= 0) {
00120     FAIL(-4);
00121   }
00122   
00123   PRINTF("PASSED\n");
00124   PRINTF("TEST ");
00125   PRINTF("4\n");
00126 
00127   /* Test 4: Open for reading. */
00128   rfd = cfs_open("T1", CFS_READ);
00129   if(rfd < 0) {
00130     FAIL(-5);
00131   }
00132   
00133   PRINTF("PASSED\n");
00134   PRINTF("TEST ");
00135   PRINTF("5\n");
00136 
00137   /* Test 5: Write to read-only file. */
00138   r = cfs_write(rfd, buf, sizeof(buf));
00139   if(r >= 0) {
00140     FAIL(-6);
00141   }
00142   
00143   PRINTF("PASSED\n");
00144   PRINTF("TEST ");
00145   PRINTF("7\n");
00146 
00147   /* Test 7: Read the buffer written in Test 2. */
00148   memset(buf, 0, sizeof(buf));
00149   r = cfs_read(rfd, buf, sizeof(buf));
00150   if(r < 0) {
00151     FAIL(-8);
00152   } else if(r < sizeof(buf)) {
00153     PRINTF_CFS("r=%d\n", r);
00154     FAIL(-9);
00155   }
00156   
00157   PRINTF("PASSED\n");
00158   PRINTF("TEST ");
00159   PRINTF("8\n");
00160 
00161   /* Test 8: Verify that the buffer is correct. */
00162   for(r = 0; r < sizeof(buf); r++) {
00163     if(buf[r] != r) {
00164       PRINTF_CFS("r=%d. buf[r]=%d\n", r, buf[r]);
00165       FAIL(-10);
00166     }
00167   }
00168   
00169   PRINTF("PASSED\n");
00170   PRINTF("TEST ");
00171   PRINTF("9\n");
00172 
00173   /* Test 9: Seek to beginning. */
00174   if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) {
00175     FAIL(-11);
00176   }
00177   
00178   PRINTF("PASSED\n");
00179   PRINTF("TEST ");
00180   PRINTF("10\n");
00181 
00182   /* Test 10: Write to the log. */
00183   r = cfs_write(wfd, buf, sizeof(buf));
00184   if(r < 0) {
00185     FAIL(-12);
00186   } else if(r < sizeof(buf)) {
00187     FAIL(-13);
00188   }
00189   
00190   PRINTF("PASSED\n");
00191   PRINTF("TEST ");
00192   PRINTF("11\n");
00193 
00194   /* Test 11: Read the data from the log. */
00195   cfs_seek(rfd, 0, CFS_SEEK_SET);
00196   memset(buf, 0, sizeof(buf));
00197   r = cfs_read(rfd, buf, sizeof(buf));
00198   if(r < 0) {
00199     FAIL(-14);
00200   } else if(r < sizeof(buf)) {
00201     FAIL(-15);
00202   }
00203   
00204   PRINTF("PASSED\n");
00205   PRINTF("TEST ");
00206   PRINTF("12\n");
00207 
00208   /* Test 12: Verify that the data is correct. */
00209   for(r = 0; r < sizeof(buf); r++) {
00210     if(buf[r] != r) {
00211       FAIL(-16);
00212     }
00213   }
00214   
00215   PRINTF("PASSED\n");
00216   PRINTF("TEST ");
00217   PRINTF("13\n");
00218 
00219   /* Test 13: Write a reversed buffer to the file. */
00220   for(r = 0; r < sizeof(buf); r++) {
00221     buf[r] = sizeof(buf) - r - 1;
00222   }
00223   if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) {
00224     FAIL(-17);
00225   }
00226   r = cfs_write(wfd, buf, sizeof(buf));
00227   if(r < 0) {
00228     FAIL(-18);
00229   } else if(r < sizeof(buf)) {
00230     FAIL(-19);
00231   }
00232   if(cfs_seek(rfd, 0, CFS_SEEK_SET) != 0) {
00233     FAIL(-20);
00234   }
00235   
00236   PRINTF("PASSED\n");
00237   PRINTF("TEST ");
00238   PRINTF("14\n");
00239 
00240   /* Test 14: Read the reversed buffer. */
00241   cfs_seek(rfd, 0, CFS_SEEK_SET);
00242   memset(buf, 0, sizeof(buf));
00243   r = cfs_read(rfd, buf, sizeof(buf));
00244   if(r < 0) {
00245     FAIL(-21);
00246   } else if(r < sizeof(buf)) {
00247     PRINTF_CFS("r = %d\n", r);
00248     FAIL(-22);
00249   }
00250   
00251   PRINTF("PASSED\n");
00252   PRINTF("TEST ");
00253   PRINTF("15\n");
00254 
00255   /* Test 15: Verify that the data is correct. */
00256   for(r = 0; r < sizeof(buf); r++) {
00257     if(buf[r] != sizeof(buf) - r - 1) {
00258       FAIL(-23);
00259     }
00260   }
00261 
00262   cfs_close(rfd);
00263   cfs_close(wfd);
00264 
00265   if(cfs_coffee_reserve("T2", FILE_SIZE) < 0) {
00266     FAIL(-24);
00267   }
00268   
00269   PRINTF("PASSED\n");
00270   PRINTF("TEST ");
00271   PRINTF("16\n");
00272 
00273   /* Test 16: Test multiple writes at random offset. */
00274   for(r = 0; r < 100; r++) {
00275     wfd = cfs_open("T2", CFS_WRITE | CFS_READ);
00276     if(wfd < 0) {
00277       FAIL(-25);
00278     }
00279 
00280     offset = random_rand() % FILE_SIZE;
00281 
00282     for(r = 0; r < sizeof(buf); r++) {
00283       buf[r] = r;
00284     }
00285 
00286     if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) {
00287       FAIL(-26);
00288     }
00289 
00290     if(cfs_write(wfd, buf, sizeof(buf)) != sizeof(buf)) {
00291       FAIL(-27);
00292     }
00293 
00294     if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) {
00295       FAIL(-28);
00296     }
00297 
00298     memset(buf, 0, sizeof(buf));
00299     if(cfs_read(wfd, buf, sizeof(buf)) != sizeof(buf)) {
00300       FAIL(-29);
00301     }
00302 
00303     for(i = 0; i < sizeof(buf); i++) {
00304       if(buf[i] != i) {
00305         PRINTF_CFS("buf[%d] != %d\n", i, buf[i]);
00306         FAIL(-30);
00307       }
00308     }
00309   }
00310   PRINTF("PASSED\n");
00311   PRINTF("TEST ");
00312   PRINTF("17\n");
00313   /* Test 17: Append data to the same file many times. */
00314 #define APPEND_BYTES 3000
00315 #define BULK_SIZE 10
00316   for (i = 0; i < APPEND_BYTES; i += BULK_SIZE) {
00317     afd = cfs_open("T3", CFS_WRITE | CFS_APPEND);
00318     if (afd < 0) {
00319       FAIL(-31);
00320     }
00321     for (j = 0; j < BULK_SIZE; j++) {
00322       buf[j] = 1 + ((i + j) & 0x7f);
00323     }
00324     if ((r = cfs_write(afd, buf, BULK_SIZE)) != BULK_SIZE) {
00325       PRINTF_CFS("Count:%d, r=%d\n", i, r);
00326       FAIL(-32);
00327     }
00328     cfs_close(afd);
00329   }
00330         
00331   PRINTF("PASSED\n");
00332   PRINTF("TEST ");
00333   PRINTF("18\n");
00334 
00335   /* Test 18: Read back the data written in Test 17 and verify that it
00336      is correct. */
00337   afd = cfs_open("T3", CFS_READ);
00338   if(afd < 0) {
00339     FAIL(-33);
00340   }
00341   total_read = 0;
00342   while((r = cfs_read(afd, buf2, sizeof(buf2))) > 0) {
00343     for(j = 0; j < r; j++) {
00344       if(buf2[j] != 1 + ((total_read + j) & 0x7f)) {
00345   FAIL(-34);
00346       }
00347     }
00348     total_read += r;
00349   }
00350   if(r < 0) {
00351           PRINTF_CFS("FAIL:-35 r=%d\n",r);
00352     FAIL(-35);
00353   }
00354   if(total_read != APPEND_BYTES) {
00355           PRINTF_CFS("FAIL:-35 total_read=%d\n",total_read);
00356     FAIL(-35);
00357   }
00358   cfs_close(afd);
00359   
00360   PRINTF("PASSED\n");
00361   PRINTF("TEST ");
00362   PRINTF("19\n");
00363 
00364 /***************T4********************/
00365 /* file T4 and T5 writing forces to use garbage collector in greedy mode
00366  * this test is designed for 10kb of file system
00367  * */
00368 #define APPEND_BYTES_1 2000
00369 #define BULK_SIZE_1 10
00370   for (i = 0; i < APPEND_BYTES_1; i += BULK_SIZE_1) {
00371     afd = cfs_open("T4", CFS_WRITE | CFS_APPEND);
00372     if (afd < 0) {
00373      FAIL(-36);
00374     }
00375     for (j = 0; j < BULK_SIZE_1; j++) {
00376       buf[j] = 1 + ((i + j) & 0x7f);
00377     }
00378 
00379    if ((r = cfs_write(afd, buf, BULK_SIZE_1)) != BULK_SIZE_1) {
00380      PRINTF_CFS("Count:%d, r=%d\n", i, r);
00381      FAIL(-37);
00382    }
00383    cfs_close(afd);
00384    }
00385 
00386   afd = cfs_open("T4", CFS_READ);
00387   if(afd < 0) {
00388     FAIL(-38);
00389   }
00390   total_read = 0;
00391   while((r = cfs_read(afd, buf2, sizeof(buf2))) > 0) {
00392     for(j = 0; j < r; j++) {
00393       if(buf2[j] != 1 + ((total_read + j) & 0x7f)) {
00394           PRINTF_CFS("FAIL:-39, total_read=%d r=%d\n",total_read,r);
00395   FAIL(-39);
00396       }
00397     }
00398     total_read += r;
00399   }
00400   if(r < 0) {
00401           PRINTF_CFS("FAIL:-40 r=%d\n",r);
00402     FAIL(-40);
00403   }
00404   if(total_read != APPEND_BYTES_1) {
00405           PRINTF_CFS("FAIL:-41 total_read=%d\n",total_read);
00406     FAIL(-41);
00407   }
00408   cfs_close(afd);
00409   /***************T5********************/
00410   PRINTF("PASSED\n");
00411   PRINTF("TEST ");
00412   PRINTF("20\n");
00413 #define APPEND_BYTES_2 1000
00414 #define BULK_SIZE_2 10
00415     for (i = 0; i < APPEND_BYTES_2; i += BULK_SIZE_2) {
00416       afd = cfs_open("T5", CFS_WRITE | CFS_APPEND);
00417       if (afd < 0) {
00418         FAIL(-42);
00419       }
00420       for (j = 0; j < BULK_SIZE_2; j++) {
00421         buf[j] = 1 + ((i + j) & 0x7f);
00422       }
00423 
00424       if ((r = cfs_write(afd, buf, BULK_SIZE_2)) != BULK_SIZE_2) {
00425         PRINTF_CFS("Count:%d, r=%d\n", i, r);
00426         FAIL(-43);
00427       }
00428 
00429       cfs_close(afd);
00430     }
00431 
00432     afd = cfs_open("T5", CFS_READ);
00433     if(afd < 0) {
00434       FAIL(-44);
00435     }
00436     total_read = 0;
00437     while((r = cfs_read(afd, buf2, sizeof(buf2))) > 0) {
00438       for(j = 0; j < r; j++) {
00439         if(buf2[j] != 1 + ((total_read + j) & 0x7f)) {
00440           PRINTF_CFS("FAIL:-45, total_read=%d r=%d\n",total_read,r);
00441     FAIL(-45);
00442         }
00443       }
00444       total_read += r;
00445     }
00446     if(r < 0) {
00447           PRINTF_CFS("FAIL:-46 r=%d\n",r);
00448       FAIL(-46);
00449     }
00450     if(total_read != APPEND_BYTES_2) {
00451           PRINTF_CFS("FAIL:-47 total_read=%d\n",total_read);
00452       FAIL(-47);
00453     }
00454     cfs_close(afd);
00455     
00456     PRINTF("PASSED\n");
00457 
00458   error = 0;
00459 end:
00460   cfs_close(wfd); cfs_close(rfd); cfs_close(afd);
00461   return error;
00462 }
00463 #endif /* TESTCOFFEE */
00464 
00465 void stm32w_flash_read(int32u address, void * data, int32u length)
00466 {
00467   int8u * pdata = (int8u *)address;
00468   ENERGEST_ON(ENERGEST_TYPE_FLASH_READ);
00469   memcpy(data, pdata, length);
00470   ENERGEST_OFF(ENERGEST_TYPE_FLASH_READ);
00471 }
00472 
00473 void stm32w_flash_erase(int8u sector)
00474 {
00475   //halInternalFlashErase(MFB_PAGE_ERASE, COFFEE_START + (sector) * COFFEE_SECTOR_SIZE);
00476   
00477   int16u data = 0;
00478   int32u addr = COFFEE_START + (sector) * COFFEE_SECTOR_SIZE;
00479   int32u end = addr + COFFEE_SECTOR_SIZE;
00480   
00481   /* This prevents from accidental write to CIB. */
00482   if (!(addr >= MFB_BOTTOM && end <= MFB_TOP + 1)) {
00483     return;
00484   }
00485   
00486   for(; addr < end; addr += 2){
00487     halInternalFlashWrite(addr, &data, 1);
00488   }
00489 }
00490 
00491 // Allocates a buffer of FLASH_PAGE_SIZE bytes statically (rather than on the stack).
00492 #ifndef STATIC_FLASH_BUFFER
00493 #define STATIC_FLASH_BUFFER 1
00494 #endif
00495 
00496 void stm32w_flash_write(int32u address, const void * data, int32u length)
00497 {
00498   const int32u end = address + length;
00499   int32u i;
00500   int32u next_page, curr_page;
00501   int16u offset;
00502   
00503 #if STATIC_FLASH_BUFFER
00504   static int8u buf[FLASH_PAGE_SIZE];
00505 #else
00506   int8u buf[FLASH_PAGE_SIZE];
00507 #endif
00508   
00509   for(i = address; i < end;) {
00510     next_page = (i | (FLASH_PAGE_SIZE-1)) + 1;
00511     curr_page = i & ~(FLASH_PAGE_SIZE-1);
00512     offset = i-curr_page;
00513     if(next_page > end) {
00514       next_page = end;
00515     }
00516     
00517     // Read a page from flash and put it into a mirror buffer.
00518     stm32w_flash_read(curr_page, buf, FLASH_PAGE_SIZE);
00519     // Update flash mirror data with new data.
00520     memcpy(buf + offset, data, next_page - i);
00521     // Erase flash page.    
00522     ENERGEST_ON(ENERGEST_TYPE_FLASH_WRITE);
00523     halInternalFlashErase(MFB_PAGE_ERASE, i);
00524     // Write modified data form mirror buffer into the flash.   
00525     halInternalFlashWrite(curr_page, (int16u *)buf, FLASH_PAGE_SIZE/2);
00526     ENERGEST_OFF(ENERGEST_TYPE_FLASH_WRITE);
00527     
00528     data = (uint8_t *)data + next_page - i;
00529     i = next_page;
00530   }
00531   
00532 }
00533