checkpoint-arch.c

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

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