Contiki 2.6
|
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 /*---------------------------------------------------------------------------*/