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

Generated on Mon Apr 11 14:23:45 2011 for Contiki 2.5 by  doxygen 1.6.1