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