Contiki 2.5
checkpoint-arch.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009, Swedish Institute of Computer Science
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * Checkpoint library implementation for the Tmote Sky platform.
36  * \author
37  * Fredrik Osterlind <fros@sics.se>
38  */
39 
40 #include "contiki.h"
41 #include "lib/checkpoint.h"
42 
43 #include "sys/rtimer.h"
44 #include "sys/mt.h"
45 #include "cfs/cfs.h"
46 #include "cfs/cfs-coffee.h"
47 #include "dev/leds.h"
48 #include "dev/watchdog.h"
49 #include <stdio.h>
50 
51 #define DEBUG 1
52 #if DEBUG
53 #define PRINTF(...) printf(__VA_ARGS__)
54 #else
55 #define PRINTF(...)
56 #endif
57 
58 #define COMMAND_ROLLBACK 1
59 #define COMMAND_CHECKPOINT 2
60 #define COMMAND_TBR 3
61 
62 #define DATA_AS_HEX 0 /* If false, store binary data */
63 
64 #define INCLUDE_RAM 1 /* Less then 10240 bytes */
65 #define INCLUDE_TIMERS 1 /* 16 bytes */
66 #define INCLUDE_LEDS 1 /* 1 bytes */
67 
68 // 8kB memory
69 #define RAM_START 0x1100
70 #define RAM_END 0x30FF
71 
72 #define STOP_TIMERS() TACTL &= ~(MC1); TBCTL &= ~(MC1); watchdog_stop();
73 #define START_TIMERS() watchdog_start(); TACTL |= MC1; TBCTL |= MC1;
74 
75 static struct mt_thread checkpoint_thread;
76 static uint8_t preset_cmd;
77 static int preset_fd;
78 
79 typedef union {
80  unsigned char u8[2];
81  unsigned short u16;
82 } word_union_t;
83 
84 /*---------------------------------------------------------------------------*/
85 static void
86 write_byte(int fd, uint8_t c)
87 {
88 #if DATA_AS_HEX
89  uint8_t hex[2];
90  sprintf(hex, "%02x", c);
91  if(cfs_write(fd, hex, 2) != 2) {
92  printf("err #1\n");
93  }
94 #else /* DATA_AS_HEX */
95  if(cfs_write(fd, &c, 1) != 1) {
96  printf("err #2\n");
97  }
98 #endif /* DATA_AS_HEX */
99 }/*---------------------------------------------------------------------------*/
100 #if 0
101 static void
102 write_array(int fd, unsigned char *mem, uint16_t len)
103 {
104 #if DATA_AS_HEX
105  int i;
106  for(i = 0; i < len; i++) {
107  write_byte(fd, mem[i]);
108  }
109 #else /* DATA_AS_HEX */
110  cfs_write(fd, mem, len);
111 #endif /* DATA_AS_HEX */
112 }
113 #endif /* 0 */
114 /*---------------------------------------------------------------------------*/
115 static void
116 write_word(int fd, uint16_t w)
117 {
118  word_union_t tmp;
119  tmp.u16 = w;
120  write_byte(fd, tmp.u8[0]);
121  write_byte(fd, tmp.u8[1]);
122 }
123 /*---------------------------------------------------------------------------*/
124 static uint8_t
125 read_byte(int fd)
126 {
127 #if DATA_AS_HEX
128  uint8_t hex[2];
129 
130  cfs_read(fd, hex, 2);
131 
132  if(hex[0] >= 'A' && hex[0] <= 'F') {
133  hex[0] = (hex[0] - 'A' + 0xa);
134  } else if(hex[0] >= 'a' && hex[0] <= 'f') {
135  hex[0] = (hex[0] - 'a' + 0xa);
136  } else {
137  hex[0] = (hex[0] - '0');
138  }
139  if(hex[1] >= 'A' && hex[1] <= 'F') {
140  hex[1] = (hex[1] - 'A' + 0xa);
141  } else if(hex[1] >= 'a' && hex[1] <= 'f') {
142  hex[1] = (hex[1] - 'a' + 0xa);
143  } else {
144  hex[1] = (hex[1] - '0');
145  }
146  return (uint8_t)((hex[0]<<4)&0xf0) | (hex[1]&0x0f);
147 #else /* DATA_AS_HEX */
148  uint8_t c;
149  cfs_read(fd, &c, 1);
150  return c;
151 #endif /* DATA_AS_HEX */
152 }
153 /*---------------------------------------------------------------------------*/
154 static uint16_t
155 read_word(int fd)
156 {
157  word_union_t tmp;
158  tmp.u8[0] = read_byte(fd);
159  tmp.u8[1] = read_byte(fd);
160  return tmp.u16;
161 }
162 /*---------------------------------------------------------------------------*/
163 static void
164 thread_checkpoint(int fd)
165 {
166 #if INCLUDE_RAM
167  unsigned char *addr;
168  uint16_t size = 0;
169  unsigned char *thread_mem_start = (unsigned char *)&checkpoint_thread.thread.stack;
170  unsigned char *thread_mem_end = thread_mem_start + sizeof(checkpoint_thread.thread.stack) - 1;
171  unsigned char *coffee_mem_start = cfs_coffee_get_protected_mem(&size);
172  unsigned char *coffee_mem_end = coffee_mem_start + size - 1;
173 #endif /* INCLUDE_RAM */
174 
175  /*printf("protected thread memory: %u, size=%u\n", (uint16_t) thread_mem_start, sizeof(checkpoint_thread.thread.stack));*/
176  /*printf("protected coffee memory: %u, size=%u\n", (uint16_t) coffee_mem_start, size);*/
177 
178  /* RAM */
179 #if INCLUDE_RAM
180  for(addr = (unsigned char *)RAM_START;
181  addr < (unsigned char *)RAM_END;
182  addr++) {
183 
184  if((addr >= thread_mem_start && addr <= thread_mem_end)) {
185  /* Writing dummy memory */
186  /*write_byte(fd, 1);*/
187  continue;
188  }
189 
190  if((addr >= coffee_mem_start && addr <= coffee_mem_end)) {
191  /* Writing dummy memory */
192  /*write_byte(fd, 2);*/
193  continue;
194  }
195 
196  /* TODO Use write_array() */
197  write_byte(fd, *addr);
198 
199  if(((int)addr % 512) == 0) {
200  PRINTF(".");
201  }
202  }
203 
204 #endif /* INCLUDE_RAM */
205 
206  /* Timers */
207 #if INCLUDE_TIMERS
208  write_word(fd, TACTL);
209  write_word(fd, TACCTL1);
210  write_word(fd, TACCR1);
211  write_word(fd, TAR);
212 
213  write_word(fd, TBCTL);
214  write_word(fd, TBCCTL1);
215  write_word(fd, TBCCR1);
216  write_word(fd, TBR);
217 #endif /* INCLUDE_TIMERS */
218 
219  /* LEDs */
220 #if INCLUDE_LEDS
221  write_byte(fd, leds_arch_get());
222 #endif /* INCLUDE_LEDS */
223 
224  /* Radio */
225  /* ADC */
226  /* ... */
227 
228  write_byte(fd, -1); /* Coffee padding byte */
229 }
230 /*---------------------------------------------------------------------------*/
231 static void
232 thread_rollback(int fd)
233 {
234 #if INCLUDE_RAM
235  unsigned char *addr;
236  uint16_t size = 0;
237  unsigned char *thread_mem_start = (unsigned char *)&checkpoint_thread.thread.stack;
238  unsigned char *thread_mem_end = thread_mem_start + sizeof(checkpoint_thread.thread.stack) - 1;
239  unsigned char *coffee_mem_start = cfs_coffee_get_protected_mem(&size);
240  unsigned char *coffee_mem_end = coffee_mem_start + size - 1;
241 #endif /* INCLUDE_RAM */
242 
243  /*printf("protected thread memory: %u, size=%u\n", (uint16_t) thread_mem_start, sizeof(checkpoint_thread.thread.stack));*/
244  /*printf("protected coffee memory: %u, size=%u\n", (uint16_t) coffee_mem_start, size);*/
245 
246  /* RAM */
247 #if INCLUDE_RAM
248  for(addr = (unsigned char *)RAM_START;
249  addr < (unsigned char *)RAM_END;
250  addr++) {
251  if((addr >= thread_mem_start && addr <= thread_mem_end)) {
252  /* Ignoring incoming memory */
253  /*read_byte(fd);*/
254  continue;
255  }
256 
257  if((addr >= coffee_mem_start && addr <= coffee_mem_end)) {
258  /* Ignoring incoming memory */
259  /*read_byte(fd);*/
260  continue;
261  }
262 
263  *addr = read_byte(fd);
264 
265  if(((int)addr % 512) == 0) {
266  PRINTF(".");
267  }
268  }
269 
270 #endif /* INCLUDE_RAM */
271 
272  /* Timers */
273 #if INCLUDE_TIMERS
274  TACTL = read_word(fd);
275  TACCTL1 = read_word(fd);
276  TACCR1 = read_word(fd);
277  TAR = read_word(fd);
278 
279  TBCTL = read_word(fd);
280  TBCCTL1 = read_word(fd);
281  TBCCR1 = read_word(fd);
282  TBR = read_word(fd);
283 #endif /* INCLUDE_TIMERS */
284 
285  /* LEDs */
286 #if INCLUDE_LEDS
287  leds_arch_set(read_byte(fd));
288 #endif /* INCLUDE_LEDS */
289 
290  /* Radio */
291  /* ADC */
292  /* ... */
293 
294  read_byte(fd); /* Coffee padding byte */
295 }
296 /*---------------------------------------------------------------------------*/
297 static void
298 thread_loop(void *data)
299 {
300  uint8_t cmd;
301  int fd;
302 
303  while(1) {
304  /* Store command and file descriptor on stack */
305  cmd = preset_cmd;
306  fd = preset_fd;
307 
308  /* Handle command */
309  if(cmd == COMMAND_ROLLBACK) {
310  PRINTF("Rolling back");
311  thread_rollback(fd);
312  PRINTF(" done!\n");
313  } else if(cmd == COMMAND_CHECKPOINT) {
314  PRINTF("Checkpointing");
315  thread_checkpoint(fd);
316  PRINTF(" done!\n");
317  } else if(cmd == COMMAND_TBR) {
318  PRINTF("Writing TBR");
319  write_word(fd, TBR);
320  PRINTF(" done!\n");
321  } else {
322  printf("Error: unknown command: %u\n", cmd);
323  }
324 
325  /* Return to main Contiki thread */
326  mt_yield();
327  }
328 }
329 /*---------------------------------------------------------------------------*/
330 int
331 checkpoint_arch_size()
332 {
333  return 10258;
334 }
335 /*---------------------------------------------------------------------------*/
336 void
337 checkpoint_arch_checkpoint(int fd)
338 {
339  STOP_TIMERS();
340 
341  preset_cmd = COMMAND_CHECKPOINT;
342  preset_fd = fd;
343  mt_exec(&checkpoint_thread);
344 
345  START_TIMERS();
346 }
347 /*---------------------------------------------------------------------------*/
348 void
349 checkpoint_arch_rollback(int fd)
350 {
351  STOP_TIMERS();
352 
353  preset_cmd = COMMAND_ROLLBACK;
354  preset_fd = fd;
355  mt_exec(&checkpoint_thread);
356 
357  START_TIMERS();
358 }
359 /*---------------------------------------------------------------------------*/
360 void
361 checkpoint_arch_init(void)
362 {
363  mt_init();
364  mt_start(&checkpoint_thread, thread_loop, NULL);
365 
366  /*mt_stop(&checkpoint_thread);*/
367  /*mt_remove();*/
368 }
369 /*---------------------------------------------------------------------------*/