Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2010, 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 * 00037 * \author 00038 * Fredrik Osterlind <fros@sics.se> 00039 */ 00040 00041 #include "contiki.h" 00042 00043 #include "lib/crc16.h" 00044 #include "lib/checkpoint.h" 00045 00046 #include "sys/rtimer.h" 00047 #include "sys/mt.h" 00048 #include "sys/energest.h" 00049 #include "sys/compower.h" 00050 #include "dev/leds.h" 00051 #include "dev/watchdog.h" 00052 #include "dev/serial-line.h" 00053 #include "dev/uart1.h" 00054 #include "dev/cc2420.h" 00055 #include "dev/button-sensor.h" 00056 #include "cfs/cfs.h" 00057 #include "cfs/cfs-coffee.h" 00058 #include <stdio.h> 00059 00060 #define DEBUG 0 00061 #if DEBUG 00062 #define PRINTF(...) printf(__VA_ARGS__) 00063 #else 00064 #define PRINTF(...) 00065 #endif 00066 00067 #ifndef CHECKPOINT_ROLLBACK_BUTTON 00068 #define CHECKPOINT_ROLLBACK_BUTTON 1 /* rollback "cp_wdt" on button click */ 00069 #endif /* CHECKPOINT_ROLLBACK_BUTTON */ 00070 00071 #if CHECKPOINT_ROLLBACK_BUTTON 00072 PROCESS(checkpoint_button_process, "Rollback on button"); 00073 #endif /* CHECKPOINT_ROLLBACK_BUTTON */ 00074 00075 #define WITH_SERIAL_COMMANDS 0 /* checkpoint via serial port */ 00076 #if WITH_SERIAL_COMMANDS 00077 #if UART1_CONF_TX_WITH_INTERRUPT 00078 #error TX_WITH_INTERRUPTS must be 0 00079 #endif /* UART1_CONF_TX_WITH_INTERRUPT */ 00080 #define PRINTF_COMMAND(...) printf(__VA_ARGS__) 00081 #else /* WITH_SERIAL_COMMANDS */ 00082 #define PRINTF_COMMAND(...) 00083 #endif /* WITH_SERIAL_COMMANDS */ 00084 00085 #define COMMAND_ROLLBACK 1 00086 #define COMMAND_CHECKPOINT 2 00087 #define COMMAND_METRICS 3 00088 00089 #define INCLUDE_RAM 1 /* Less then 10240 bytes */ 00090 #define INCLUDE_TIMERS 1 /* 16 bytes */ 00091 #define INCLUDE_LEDS 1 /* 1 bytes */ 00092 /* ... */ 00093 00094 /* 10kb memory */ 00095 #define RAM_START 0x1100 00096 #define RAM_END 0x3900 00097 00098 #define PAUSE_TIME() \ 00099 TACTL &= ~(MC1); \ 00100 TBCTL &= ~(MC1); \ 00101 watchdog_stop(); 00102 #define RESUME_TIME() \ 00103 TACTL |= MC1; \ 00104 TBCTL |= MC1; \ 00105 TACCR1 = clock_fine_max(); \ 00106 watchdog_start(); 00107 #define PAUSE_TIME_INT() \ 00108 dint(); \ 00109 PAUSE_TIME(); 00110 #define RESUME_TIME_INT() \ 00111 RESUME_TIME(); \ 00112 eint(); 00113 00114 static struct mt_thread checkpoint_thread; 00115 static uint8_t preset_cmd; 00116 static int preset_fd; 00117 00118 /* bookkeeping */ 00119 #if WITH_SERIAL_COMMANDS 00120 static int nr_pongs=0; 00121 #endif /* WITH_SERIAL_COMMANDS */ 00122 static int nr_checkpoints=0, nr_rollbacks=0, nr_metrics=0; 00123 00124 /*---------------------------------------------------------------------------*/ 00125 typedef union { 00126 unsigned char u8[2]; 00127 unsigned short u16; 00128 } word_union_t; 00129 /*---------------------------------------------------------------------------*/ 00130 static int 00131 write_byte(int fd, uint8_t c) 00132 { 00133 return cfs_write(fd, &c, 1); 00134 } 00135 /*---------------------------------------------------------------------------*/ 00136 static void 00137 write_word(int fd, uint16_t w) 00138 { 00139 word_union_t tmp; 00140 tmp.u16 = w; 00141 write_byte(fd, tmp.u8[0]); 00142 write_byte(fd, tmp.u8[1]); 00143 } 00144 /*---------------------------------------------------------------------------*/ 00145 static uint8_t 00146 read_byte(int fd) 00147 { 00148 uint8_t c; 00149 cfs_read(fd, &c, 1); 00150 return c; 00151 } 00152 /*---------------------------------------------------------------------------*/ 00153 static uint16_t 00154 read_word(int fd) 00155 { 00156 word_union_t tmp; 00157 tmp.u8[0] = read_byte(fd); 00158 tmp.u8[1] = read_byte(fd); 00159 return tmp.u16; 00160 } 00161 /*---------------------------------------------------------------------------*/ 00162 static void 00163 thread_checkpoint(int fd) 00164 { 00165 #if INCLUDE_RAM 00166 unsigned char *addr; 00167 uint16_t size = 0; 00168 unsigned char *thread_mem_start = (unsigned char *)&checkpoint_thread.thread.stack; 00169 unsigned char *thread_mem_end = thread_mem_start + sizeof(checkpoint_thread.thread.stack) - 1; 00170 unsigned char *coffee_mem_start = cfs_coffee_get_protected_mem(&size); 00171 unsigned char *coffee_mem_end = coffee_mem_start + size - 1; 00172 #endif /* INCLUDE_RAM */ 00173 00174 /*PRINTF("protected thread memory: %u, size=%u\n", (uint16_t) thread_mem_start, sizeof(checkpoint_thread.thread.stack));*/ 00175 /*PRINTF("protected coffee memory: %u, size=%u\n", (uint16_t) coffee_mem_start, size);*/ 00176 00177 /* RAM */ 00178 #if INCLUDE_RAM 00179 for(addr = (unsigned char *)RAM_START; 00180 addr < (unsigned char *)RAM_END; 00181 addr++) { 00182 00183 if((addr >= thread_mem_start && addr <= thread_mem_end)) { 00184 /* Skip */ 00185 continue; 00186 } 00187 00188 if((addr >= coffee_mem_start && addr <= coffee_mem_end)) { 00189 /* Skip */ 00190 continue; 00191 } 00192 00193 /* TODO Use write_array() */ 00194 write_byte(fd, *addr); 00195 00196 /*if(((int)addr % 512) == 0) { 00197 PRINTF("."); 00198 }*/ 00199 } 00200 00201 #endif /* INCLUDE_RAM */ 00202 00203 /* Timers */ 00204 #if INCLUDE_TIMERS 00205 write_word(fd, TACTL); 00206 write_word(fd, TACCTL1); 00207 write_word(fd, TACCR1); 00208 write_word(fd, TAR); 00209 00210 write_word(fd, TBCTL); 00211 write_word(fd, TBCCTL1); 00212 write_word(fd, TBCCR1); 00213 write_word(fd, TBR); 00214 #endif /* INCLUDE_TIMERS */ 00215 00216 /* LEDs */ 00217 #if INCLUDE_LEDS 00218 write_byte(fd, leds_arch_get()); 00219 #endif /* INCLUDE_LEDS */ 00220 00221 /* Radio */ 00222 /* ADC */ 00223 /* ... */ 00224 00225 write_byte(fd, -1); /* Coffee padding byte */ 00226 } 00227 /*---------------------------------------------------------------------------*/ 00228 static void 00229 thread_rollback(int fd) 00230 { 00231 #if INCLUDE_RAM 00232 unsigned char *addr; 00233 uint16_t size = 0; 00234 unsigned char *thread_mem_start = (unsigned char *)&checkpoint_thread.thread.stack; 00235 unsigned char *thread_mem_end = thread_mem_start + sizeof(checkpoint_thread.thread.stack) - 1; 00236 unsigned char *coffee_mem_start = cfs_coffee_get_protected_mem(&size); 00237 unsigned char *coffee_mem_end = coffee_mem_start + size - 1; 00238 #endif /* INCLUDE_RAM */ 00239 00240 /*PRINTF("protected thread memory: %u, size=%u\n", (uint16_t) thread_mem_start, sizeof(checkpoint_thread.thread.stack));*/ 00241 /*PRINTF("protected coffee memory: %u, size=%u\n", (uint16_t) coffee_mem_start, size);*/ 00242 00243 /* RAM */ 00244 #if INCLUDE_RAM 00245 for(addr = (unsigned char *)RAM_START; 00246 addr < (unsigned char *)RAM_END; 00247 addr++) { 00248 if((addr >= thread_mem_start && addr <= thread_mem_end)) { 00249 /* Skip */ 00250 continue; 00251 } 00252 00253 if((addr >= coffee_mem_start && addr <= coffee_mem_end)) { 00254 /* Skip */ 00255 continue; 00256 } 00257 00258 *addr = read_byte(fd); 00259 } 00260 #endif /* INCLUDE_RAM */ 00261 00262 /* Timers */ 00263 #if INCLUDE_TIMERS 00264 TACTL = read_word(fd); 00265 TACCTL1 = read_word(fd); 00266 TACCR1 = read_word(fd); 00267 TAR = read_word(fd); 00268 00269 TBCTL = read_word(fd); 00270 TBCCTL1 = read_word(fd); 00271 TBCCR1 = read_word(fd); 00272 TBR = read_word(fd); 00273 #endif /* INCLUDE_TIMERS */ 00274 00275 /* LEDs */ 00276 #if INCLUDE_LEDS 00277 leds_arch_set(read_byte(fd)); 00278 #endif /* INCLUDE_LEDS */ 00279 00280 /* Radio */ 00281 /* ADC */ 00282 /* ... */ 00283 00284 read_byte(fd); /* Coffee padding byte */ 00285 } 00286 /*---------------------------------------------------------------------------*/ 00287 #if WITH_SERIAL_COMMANDS 00288 static uint32_t 00289 thread_metric_tx(void) 00290 { 00291 energest_flush(); 00292 return energest_type_time(ENERGEST_TYPE_TRANSMIT); 00293 } 00294 /*---------------------------------------------------------------------------*/ 00295 static uint32_t 00296 thread_metric_rx(void) 00297 { 00298 energest_flush(); 00299 return energest_type_time(ENERGEST_TYPE_LISTEN); 00300 } 00301 #endif /* WITH_SERIAL_COMMANDS */ 00302 /*---------------------------------------------------------------------------*/ 00303 static void 00304 thread_metrics(void) 00305 { 00306 PRINTF_COMMAND("METRICS:START\n"); 00307 PRINTF_COMMAND("M:RTIMER_NOW:%u\n", RTIMER_NOW()); /* TODO extract */ 00308 PRINTF_COMMAND("M:ENERGY_TX:%lu\n", thread_metric_tx()); 00309 PRINTF_COMMAND("M:ENERGY_RX:%lu\n", thread_metric_rx()); 00310 PRINTF_COMMAND("M:RTIMER_NOW2:%u\n", RTIMER_NOW()); 00311 nr_metrics++; 00312 PRINTF_COMMAND("METRICS:DONE %u\n", nr_metrics); 00313 } 00314 /*---------------------------------------------------------------------------*/ 00315 static void 00316 checkpoint_thread_loop(void *data) 00317 { 00318 uint8_t cmd; 00319 int fd; 00320 00321 while(1) { 00322 /* Store command and file descriptor on stack */ 00323 cmd = preset_cmd; 00324 fd = preset_fd; 00325 00326 /* Handle command */ 00327 if(cmd == COMMAND_ROLLBACK) { 00328 PRINTF_COMMAND("RB:START\n"); 00329 thread_rollback(fd); 00330 nr_rollbacks++; 00331 PRINTF_COMMAND("RB:DONE %u\n", nr_rollbacks); 00332 /* TODO Synch before leaving this thread. */ 00333 } else if(cmd == COMMAND_CHECKPOINT) { 00334 PRINTF_COMMAND("CP:START\n"); 00335 thread_checkpoint(fd); 00336 thread_metrics(); 00337 nr_checkpoints++; 00338 PRINTF_COMMAND("CP:DONE %u\n", nr_checkpoints); 00339 } else if(cmd == COMMAND_METRICS) { 00340 thread_metrics(); 00341 } else { 00342 printf("ERROR: Unknown thread command: %u\n", cmd); 00343 } 00344 00345 /* Return to Contiki */ 00346 mt_yield(); 00347 } 00348 } 00349 /*---------------------------------------------------------------------------*/ 00350 int 00351 checkpoint_arch_size() 00352 { 00353 return 10258; 00354 } 00355 /*---------------------------------------------------------------------------*/ 00356 void 00357 checkpoint_arch_checkpoint(int fd) 00358 { 00359 PAUSE_TIME_INT(); 00360 00361 preset_cmd = COMMAND_CHECKPOINT; 00362 preset_fd = fd; 00363 mt_exec(&checkpoint_thread); 00364 00365 RESUME_TIME_INT(); 00366 } 00367 /*---------------------------------------------------------------------------*/ 00368 void 00369 checkpoint_arch_rollback(int fd) 00370 { 00371 PAUSE_TIME_INT(); 00372 00373 preset_cmd = COMMAND_ROLLBACK; 00374 preset_fd = fd; 00375 mt_exec(&checkpoint_thread); 00376 00377 RESUME_TIME_INT(); 00378 } 00379 /*---------------------------------------------------------------------------*/ 00380 static uint8_t inited = 0; 00381 void 00382 checkpoint_arch_init(void) 00383 { 00384 if(inited) { 00385 return; 00386 } 00387 00388 mt_init(); 00389 mt_start(&checkpoint_thread, checkpoint_thread_loop, NULL); 00390 inited = 1; 00391 00392 #if CHECKPOINT_ROLLBACK_BUTTON 00393 process_start(&checkpoint_button_process, NULL); 00394 #endif /* CHECKPOINT_ROLLBACK_BUTTON */ 00395 00396 /*mt_stop(&checkpoint_thread);*/ 00397 /*mt_remove();*/ 00398 } 00399 /*---------------------------------------------------------------------------*/ 00400 struct power_log { 00401 uint32_t transmit; 00402 uint32_t listen; 00403 }; 00404 /*---------------------------------------------------------------------------*/ 00405 #if WITH_SERIAL_COMMANDS 00406 static void 00407 serial_interrupt_checkpoint() 00408 { 00409 int fd = 0; 00410 PAUSE_TIME(); 00411 00412 if(SPI_IS_ENABLED()) { 00413 /* SPI is busy, abort */ 00414 PRINTF_COMMAND("CP:SPIBUSY\n"); 00415 RESUME_TIME(); 00416 return; 00417 } 00418 00419 /* Open file */ 00420 cfs_remove("cp"); 00421 cfs_coffee_reserve("cp", checkpoint_arch_size()); 00422 fd = cfs_open("cp", CFS_WRITE); 00423 00424 if(fd < 0) { 00425 printf("ERROR: No file access (cp)\n"); 00426 RESUME_TIME(); 00427 return; 00428 } 00429 00430 /* Checkpoint */ 00431 preset_cmd = COMMAND_CHECKPOINT; 00432 preset_fd = fd; 00433 mt_exec(&checkpoint_thread); 00434 00435 /* Close file */ 00436 cfs_close(fd); 00437 00438 RESUME_TIME(); 00439 } 00440 /*---------------------------------------------------------------------------*/ 00441 static void 00442 serial_interrupt_rollback() 00443 { 00444 int fd = 0; 00445 PAUSE_TIME(); 00446 00447 if(SPI_IS_ENABLED()) { 00448 /* SPI is busy, abort */ 00449 PRINTF_COMMAND("RB:SPIBUSY\n"); 00450 RESUME_TIME(); 00451 return; 00452 } 00453 00454 /* Open file */ 00455 fd = cfs_open("cp", CFS_READ); 00456 00457 if(fd < 0) { 00458 printf("ERROR: No file access (rb)\n"); 00459 RESUME_TIME(); 00460 return; 00461 } 00462 00463 /* Rollback */ 00464 preset_cmd = COMMAND_ROLLBACK; 00465 preset_fd = fd; 00466 mt_exec(&checkpoint_thread); 00467 00468 /* Close file */ 00469 cfs_close(fd); 00470 00471 RESUME_TIME(); 00472 } 00473 /*---------------------------------------------------------------------------*/ 00474 static void 00475 serial_interrupt_metrics() 00476 { 00477 PAUSE_TIME(); 00478 00479 preset_cmd = COMMAND_METRICS; 00480 preset_fd = -1; 00481 mt_exec(&checkpoint_thread); 00482 00483 RESUME_TIME(); 00484 } 00485 /*---------------------------------------------------------------------------*/ 00486 static const unsigned char command_checkpoint[] = { 'c', 'p', '\n' }; 00487 static const unsigned char command_rollback[] = { 'r', 'b', '\n' }; 00488 static const unsigned char command_metrics[] = { 'm', 't', '\n' }; 00489 static volatile int command_checkpoint_state = 0; 00490 static volatile int command_rollback_state = 0; 00491 static volatile int command_metrics_state = 0; 00492 /*---------------------------------------------------------------------------*/ 00493 static int 00494 serial_input_byte_intercept(unsigned char c) 00495 { 00496 /* Detect checkpoint request */ 00497 if(command_checkpoint[command_checkpoint_state] == c) { 00498 command_checkpoint_state++; 00499 00500 if(command_checkpoint_state == sizeof(command_checkpoint)) { 00501 serial_interrupt_checkpoint(); 00502 command_checkpoint_state = 0; 00503 } 00504 } else { 00505 command_checkpoint_state = 0; 00506 } 00507 00508 /* Detect rollback request */ 00509 if(command_rollback[command_rollback_state] == c) { 00510 command_rollback_state++; 00511 00512 if(command_rollback_state == sizeof(command_rollback)) { 00513 serial_interrupt_rollback(); 00514 command_rollback_state = 0; 00515 } 00516 } else { 00517 command_rollback_state = 0; 00518 } 00519 00520 /* Detect metrics request */ 00521 if(command_metrics[command_metrics_state] == c) { 00522 command_metrics_state++; 00523 00524 if(command_metrics_state == sizeof(command_metrics)) { 00525 serial_interrupt_metrics(); 00526 command_metrics_state = 0; 00527 } 00528 } else { 00529 command_metrics_state = 0; 00530 } 00531 00532 /* Forward to serial line input byte */ 00533 return serial_line_input_byte(c); 00534 } 00535 /*---------------------------------------------------------------------------*/ 00536 static void 00537 handle_get_command(void) 00538 { 00539 int fd = 0; 00540 fd = cfs_open("cp", CFS_READ); 00541 if(fd < 0) { 00542 printf("ERROR: No file access (get)\n"); 00543 } else { 00544 PRINTF_COMMAND("GET:START\n"); 00545 char data[8]; 00546 int offset=0, size=0, read=8; 00547 unsigned short crc = 0; 00548 cfs_seek(fd, offset, CFS_SEEK_SET); 00549 00550 while (read == 8) { 00551 int i; 00552 00553 /*if(offset != cfs_seek(fd, offset, CFS_SEEK_SET)) { 00554 printf("bad seek, breaking\n"); 00555 break; 00556 }*/ 00557 read = cfs_read(fd, data, 8); 00558 size += read; 00559 00560 printf("%04i: ", offset); /*REMOVE*/ 00561 for (i=0; i < read; i++) { 00562 crc = crc16_add((uint8_t) data[i], crc); 00563 printf("%02x", (uint8_t) (0xff&data[i])); 00564 } 00565 printf("\n"); 00566 00567 offset += 8; 00568 } 00569 00570 PRINTF_COMMAND("GET:DONE CRC=%u\n", crc); 00571 cfs_close(fd); 00572 } 00573 } 00574 /*---------------------------------------------------------------------------*/ 00575 static int 00576 hex_decode_char(char c) 00577 { 00578 if(c >= 'A' && c <= 'F') { 00579 return c - 'A' + 10; 00580 } else if(c >= 'a' && c <= 'f') { 00581 return c - 'a' + 10; 00582 } else if(c >= '0' && c <= '9') { 00583 return c - '0'; 00584 } else { 00585 printf("WARN: bad hex: %c\n", c); 00586 return 0; 00587 } 00588 } 00589 /*---------------------------------------------------------------------------*/ 00590 PROCESS(checkpoint_serial_process, "Checkpoint via serial commands"); 00591 PROCESS_THREAD(checkpoint_serial_process, ev, data) 00592 { 00593 static int set_fd = -1; 00594 static int set_count = -1; 00595 00596 PROCESS_BEGIN(); 00597 00598 /* Note: 'cp', 'rb', and 'mt' commands are intercepted */ 00599 PROCESS_PAUSE(); 00600 uart1_set_input(serial_input_byte_intercept); 00601 00602 /* Format Coffee? */ 00603 PRINTF("Formatting Coffee\n"); 00604 cfs_coffee_format(); 00605 PRINTF("Formatting Coffee... done!\n"); 00606 00607 while(1) { 00608 PROCESS_WAIT_EVENT_UNTIL(ev == serial_line_event_message && data != NULL); 00609 00610 if(strcmp("set", data) == 0) { 00611 /* TODO Handle set command */ 00612 /* Open file */ 00613 cfs_remove("cp"); 00614 cfs_coffee_reserve("cp", checkpoint_arch_size()); 00615 set_fd = cfs_open("cp", CFS_WRITE); 00616 set_count = 0; 00617 if(set_fd < 0) { 00618 printf("SET:FSBUSY\n"); 00619 } else { 00620 printf("SET:LINE\n"); 00621 } 00622 } else if(set_fd >= 0 && strcmp("set:done", data) == 0) { 00623 cfs_close(set_fd); 00624 set_fd = -1; 00625 if(set_count == 9862) { 00626 printf("SET:DONE\n"); 00627 } else { 00628 printf("SET:WRONGSIZE\n"); 00629 } 00630 } else if(set_fd >= 0) { 00631 /* We are ready for another line */ 00632 printf("SET:LINE\n"); 00633 /* Set command: parse hex data */ 00634 int len = strlen((char*)data); 00635 if(len > 16 || (len%2)!=0) { 00636 printf("WARN: bad set data: %s\n", (char*)data); 00637 } else { 00638 int i; 00639 for (i=0; i < len; i+=2) { 00640 uint8_t b = 00641 (hex_decode_char(((char*)data)[i]) << 4) + 00642 (hex_decode_char(((char*)data)[i+1])); 00643 00644 PRINTF("Parsing set command: writing to CFS: %02x\n", b); 00645 write_byte(set_fd, b); /* TODO Check return value */ 00646 set_count++; 00647 } 00648 } 00649 } else if(strcmp("", data) == 0 || 00650 strcmp("cp", data) == 0 || 00651 strcmp("rb", data) == 0 || 00652 strcmp("mt", data) == 0) { 00653 /* ignore commands: handled by interrupt */ 00654 } else if(strcmp("ping", data) == 0) { 00655 nr_pongs++; 00656 printf("pong %u\n", nr_pongs); 00657 } else if(strcmp("get", data) == 0) { 00658 handle_get_command(); 00659 } else { 00660 printf("WARN: Unknown command: '%s'\n", (char*)data); 00661 } 00662 } 00663 00664 PROCESS_END(); 00665 } 00666 #endif /* WITH_SERIAL_COMMANDS */ 00667 /*---------------------------------------------------------------------------*/ 00668 #if CHECKPOINT_ROLLBACK_BUTTON 00669 PROCESS_THREAD(checkpoint_button_process, ev, data) 00670 { 00671 PROCESS_BEGIN(); 00672 00673 button_sensor.configure(SENSORS_ACTIVE, 1); 00674 00675 while(1) { 00676 PROCESS_WAIT_EVENT(); 00677 00678 if(ev == sensors_event && data == &button_sensor) { 00679 int fd = 0; 00680 00681 /* Rollback from Coffee file "cp_wdt" */ 00682 fd = cfs_open("cp_wdt", CFS_READ); 00683 if(fd >= 0) { 00684 checkpoint_rollback(fd); 00685 cfs_close(fd); 00686 } 00687 } 00688 } 00689 00690 PROCESS_END(); 00691 } 00692 #endif /* CHECKPOINT_ROLLBACK_BUTTON */