Contiki 2.6

checkpoint-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  *  Checkpoint library implementation for the Tmote Sky platform.
00036  * \author
00037  *  Fredrik Osterlind <fros@sics.se>
00038  */
00039 
00040 #include "contiki.h"
00041 #include "lib/checkpoint.h"
00042 
00043 #include "sys/rtimer.h"
00044 #include "sys/mt.h"
00045 #include "cfs/cfs.h"
00046 #include "cfs/cfs-coffee.h"
00047 #include "dev/leds.h"
00048 #include "dev/watchdog.h"
00049 
00050 #include <stdio.h>
00051 
00052 #define DEBUG 0
00053 #if DEBUG
00054 #define PRINTF(...) printf(__VA_ARGS__)
00055 #else
00056 #define PRINTF(...)
00057 #endif
00058 
00059 #define COMMAND_ROLLBACK 1
00060 #define COMMAND_CHECKPOINT 2
00061 #define COMMAND_TBR 3
00062 
00063 #define DATA_AS_HEX 0 /* If false, store binary data */
00064 
00065 #define INCLUDE_RAM 1 /* Less then 10240 bytes */
00066 #define INCLUDE_TIMERS 1 /* 16 bytes */
00067 #define INCLUDE_LEDS 1 /* 1 bytes */
00068 
00069 /* 10kb memory */
00070 #define RAM_START 0x1100
00071 #define RAM_END 0x3900
00072 
00073 #define STOP_TIMERS() TACTL &= ~(MC1); TBCTL &= ~(MC1); watchdog_stop();
00074 #define START_TIMERS() watchdog_start(); TACTL |= MC1; TBCTL |= MC1;
00075 
00076 static struct mt_thread checkpoint_thread;
00077 static uint8_t preset_cmd;
00078 static int preset_fd;
00079 
00080 typedef union {
00081   unsigned char u8[2];
00082   unsigned short u16;
00083 } word_union_t;
00084 
00085 /*---------------------------------------------------------------------------*/
00086 static void
00087 write_byte(int fd, uint8_t c)
00088 {
00089 #if DATA_AS_HEX
00090   uint8_t hex[2];
00091   sprintf(hex, "%02x", c);
00092   if(cfs_write(fd, hex, 2) != 2) {
00093     printf("err #1\n");
00094   }
00095 #else /* DATA_AS_HEX */
00096   if(cfs_write(fd, &c, 1) != 1) {
00097     printf("err #2\n");
00098   }
00099 #endif /* DATA_AS_HEX */
00100 }/*---------------------------------------------------------------------------*/
00101 #if 0
00102 static void
00103 write_array(int fd, unsigned char *mem, uint16_t len)
00104 {
00105 #if DATA_AS_HEX
00106   int i;
00107   for(i = 0; i < len; i++) {
00108     write_byte(fd, mem[i]);
00109   }
00110 #else /* DATA_AS_HEX */
00111   cfs_write(fd, mem, len);
00112 #endif /* DATA_AS_HEX */
00113 }
00114 #endif /* 0 */
00115 /*---------------------------------------------------------------------------*/
00116 static void
00117 write_word(int fd, uint16_t w)
00118 {
00119   word_union_t tmp;
00120   tmp.u16 = w;
00121   write_byte(fd, tmp.u8[0]);
00122   write_byte(fd, tmp.u8[1]);
00123 }
00124 /*---------------------------------------------------------------------------*/
00125 static uint8_t
00126 read_byte(int fd)
00127 {
00128 #if DATA_AS_HEX
00129   uint8_t hex[2];
00130 
00131   cfs_read(fd, hex, 2);
00132 
00133   if(hex[0] >= 'A' && hex[0] <= 'F') {
00134     hex[0] = (hex[0] - 'A' + 0xa);
00135   } else if(hex[0] >= 'a' && hex[0] <= 'f') {
00136     hex[0] = (hex[0] - 'a' + 0xa);
00137   } else {
00138     hex[0] = (hex[0] - '0');
00139   }
00140   if(hex[1] >= 'A' && hex[1] <= 'F') {
00141     hex[1] = (hex[1] - 'A' + 0xa);
00142   } else if(hex[1] >= 'a' && hex[1] <= 'f') {
00143     hex[1] = (hex[1] - 'a' + 0xa);
00144   } else {
00145     hex[1] = (hex[1] - '0');
00146   }
00147   return (uint8_t)((hex[0]<<4)&0xf0) | (hex[1]&0x0f);
00148 #else /* DATA_AS_HEX */
00149   uint8_t c;
00150   cfs_read(fd, &c, 1);
00151   return c;
00152 #endif /* DATA_AS_HEX */
00153 }
00154 /*---------------------------------------------------------------------------*/
00155 static uint16_t
00156 read_word(int fd)
00157 {
00158   word_union_t tmp;
00159   tmp.u8[0] = read_byte(fd);
00160   tmp.u8[1] = read_byte(fd);
00161   return tmp.u16;
00162 }
00163 /*---------------------------------------------------------------------------*/
00164 static void
00165 thread_checkpoint(int fd)
00166 {
00167 #if INCLUDE_RAM
00168   unsigned char *addr;
00169   uint16_t size = 0;
00170   unsigned char *thread_mem_start = (unsigned char *)&checkpoint_thread.thread.stack;
00171   unsigned char *thread_mem_end = thread_mem_start + sizeof(checkpoint_thread.thread.stack) - 1;
00172   unsigned char *coffee_mem_start = cfs_coffee_get_protected_mem(&size);
00173   unsigned char *coffee_mem_end = coffee_mem_start + size - 1;
00174 #endif /* INCLUDE_RAM */
00175 
00176   /*printf("protected thread memory: %u, size=%u\n", (uint16_t) thread_mem_start, sizeof(checkpoint_thread.thread.stack));*/
00177   /*printf("protected coffee memory: %u, size=%u\n", (uint16_t) coffee_mem_start, size);*/
00178 
00179   /* RAM */
00180 #if INCLUDE_RAM
00181   for(addr = (unsigned char *)RAM_START;
00182       addr < (unsigned char *)RAM_END;
00183       addr++) {
00184 
00185     if((addr >= thread_mem_start && addr <= thread_mem_end)) {
00186       /* Writing dummy memory */
00187       /*write_byte(fd, 1);*/
00188       continue;
00189     }
00190 
00191     if((addr >= coffee_mem_start && addr <= coffee_mem_end)) {
00192       /* Writing dummy memory */
00193       /*write_byte(fd, 2);*/
00194       continue;
00195     }
00196 
00197     /* TODO Use write_array() */
00198     write_byte(fd, *addr);
00199 
00200     if(((int)addr % 512) == 0) {
00201       PRINTF(".");
00202     }
00203   }
00204 
00205 #endif /* INCLUDE_RAM */
00206 
00207   /* Timers */
00208 #if INCLUDE_TIMERS
00209 /*  write_word(fd, TACTL);
00210   write_word(fd, TACCTL1);
00211   write_word(fd, TACCR1);
00212   write_word(fd, TAR);
00213 
00214   write_word(fd, TBCTL);
00215   write_word(fd, TBCCTL1);
00216   write_word(fd, TBCCR1);
00217   write_word(fd, TBR);*/
00218 #endif /* INCLUDE_TIMERS */
00219 
00220   /* LEDs */
00221 #if INCLUDE_LEDS
00222   write_byte(fd, leds_arch_get());
00223 #endif /* INCLUDE_LEDS */
00224 
00225   /* Radio */
00226   /* ADC */
00227   /* ... */
00228 
00229   write_byte(fd, -1); /* Coffee padding byte */
00230 }
00231 /*---------------------------------------------------------------------------*/
00232 static void
00233 thread_rollback(int fd)
00234 {
00235 #if INCLUDE_RAM
00236   unsigned char *addr;
00237   uint16_t size = 0;
00238   unsigned char *thread_mem_start = (unsigned char *)&checkpoint_thread.thread.stack;
00239   unsigned char *thread_mem_end = thread_mem_start + sizeof(checkpoint_thread.thread.stack) - 1;
00240   unsigned char *coffee_mem_start = cfs_coffee_get_protected_mem(&size);
00241   unsigned char *coffee_mem_end = coffee_mem_start + size - 1;
00242 #endif /* INCLUDE_RAM */
00243 
00244   /*printf("protected thread memory: %u, size=%u\n", (uint16_t) thread_mem_start, sizeof(checkpoint_thread.thread.stack));*/
00245   /*printf("protected coffee memory: %u, size=%u\n", (uint16_t) coffee_mem_start, size);*/
00246 
00247   /* RAM */
00248 #if INCLUDE_RAM
00249   for(addr = (unsigned char *)RAM_START;
00250       addr < (unsigned char *)RAM_END;
00251       addr++) {
00252     if((addr >= thread_mem_start && addr <= thread_mem_end)) {
00253       /* Ignoring incoming memory */
00254       /*read_byte(fd);*/
00255       continue;
00256     }
00257 
00258     if((addr >= coffee_mem_start && addr <= coffee_mem_end)) {
00259       /* Ignoring incoming memory */
00260       /*read_byte(fd);*/
00261       continue;
00262     }
00263 
00264     *addr = read_byte(fd);
00265 
00266     if(((int)addr % 512) == 0) {
00267       PRINTF(".");
00268     }
00269   }
00270 
00271 #endif /* INCLUDE_RAM */
00272 
00273   /* Timers */
00274 #if INCLUDE_TIMERS
00275 /*  TACTL = read_word(fd);
00276   TACCTL1 = read_word(fd);
00277   TACCR1 = read_word(fd);
00278   TAR = read_word(fd);
00279 
00280   TBCTL = read_word(fd);
00281   TBCCTL1 = read_word(fd);
00282   TBCCR1 = read_word(fd);
00283   TBR = read_word(fd);*/
00284 #endif /* INCLUDE_TIMERS */
00285 
00286   /* LEDs */
00287 #if INCLUDE_LEDS
00288   leds_arch_set(read_byte(fd));
00289 #endif /* INCLUDE_LEDS */
00290 
00291   /* Radio */
00292   /* ADC */
00293   /* ... */
00294 
00295   read_byte(fd); /* Coffee padding byte */
00296 }
00297 /*---------------------------------------------------------------------------*/
00298 static void
00299 thread_loop(void *data)
00300 {
00301   uint8_t cmd;
00302   int fd;
00303 
00304   while(1) {
00305     /* Store command and file descriptor on stack */
00306     cmd = preset_cmd;
00307     fd = preset_fd;
00308 
00309     /* Handle command */
00310     if(cmd == COMMAND_ROLLBACK) {
00311       PRINTF("Rolling back");
00312       thread_rollback(fd);
00313       PRINTF(" done!\n");
00314     } else if(cmd == COMMAND_CHECKPOINT) {
00315       PRINTF("Checkpointing");
00316       thread_checkpoint(fd);
00317       PRINTF(" done!\n");
00318     } else if(cmd == COMMAND_TBR) {
00319       PRINTF("Writing TBR");
00320      // write_word(fd, TBR);
00321       PRINTF(" done!\n");
00322     } else {
00323       printf("Error: unknown command: %u\n", cmd);
00324     }
00325 
00326     /* Return to main Contiki thread */
00327     mt_yield();
00328   }
00329 }
00330 /*---------------------------------------------------------------------------*/
00331 int
00332 checkpoint_arch_size()
00333 {
00334   return 10258;
00335 }
00336 /*---------------------------------------------------------------------------*/
00337 void
00338 checkpoint_arch_checkpoint(int fd)
00339 {
00340 //  STOP_TIMERS();
00341 
00342   preset_cmd = COMMAND_CHECKPOINT;
00343   preset_fd = fd;
00344   mt_exec(&checkpoint_thread);
00345 
00346 //  START_TIMERS();
00347 }
00348 /*---------------------------------------------------------------------------*/
00349 void
00350 checkpoint_arch_rollback(int fd)
00351 {
00352   //STOP_TIMERS();
00353 
00354   preset_cmd = COMMAND_ROLLBACK;
00355   preset_fd = fd;
00356   mt_exec(&checkpoint_thread);
00357 
00358   //START_TIMERS();
00359 }
00360 /*---------------------------------------------------------------------------*/
00361 void
00362 checkpoint_arch_init(void)
00363 {
00364   mt_init();
00365   mt_start(&checkpoint_thread, thread_loop, NULL);
00366 
00367   /*mt_stop(&checkpoint_thread);*/
00368   /*mt_remove();*/
00369 }
00370 /*---------------------------------------------------------------------------*/