2 * Copyright (c) 2009, Swedish Institute of Computer Science
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
29 * This file is part of the Contiki operating system.
35 * Checkpoint library implementation for the Tmote Sky platform.
37 * Fredrik Osterlind <fros@sics.se>
41 #include "lib/checkpoint.h"
43 #include "sys/rtimer.h"
46 #include "cfs/cfs-coffee.h"
48 #include "dev/watchdog.h"
56 #define PRINTF(...) printf(__VA_ARGS__)
61 #define COMMAND_ROLLBACK 1
62 #define COMMAND_CHECKPOINT 2
65 #define DATA_AS_HEX 0 /* If false, store binary data */
67 #define INCLUDE_RAM 1 /* Less then 10240 bytes */
68 #define INCLUDE_TIMERS 1 /* 16 bytes */
69 #define INCLUDE_LEDS 1 /* 1 bytes */
72 #define RAM_START 0x1100
73 #define RAM_END 0x3900
75 #define STOP_TIMERS() TACTL &= ~(MC1); TBCTL &= ~(MC1); watchdog_stop();
76 #define START_TIMERS() watchdog_start(); TACTL |= MC1; TBCTL |= MC1;
78 static struct mt_thread checkpoint_thread
;
79 static uint8_t preset_cmd
;
87 /*---------------------------------------------------------------------------*/
89 write_byte(int fd
, uint8_t c
)
93 sprintf(hex
, "%02x", c
);
94 if(cfs_write(fd
, hex
, 2) != 2) {
97 #else /* DATA_AS_HEX */
98 if(cfs_write(fd
, &c
, 1) != 1) {
101 #endif /* DATA_AS_HEX */
102 }/*---------------------------------------------------------------------------*/
105 write_array(int fd
, unsigned char *mem
, uint16_t len
)
109 for(i
= 0; i
< len
; i
++) {
110 write_byte(fd
, mem
[i
]);
112 #else /* DATA_AS_HEX */
113 cfs_write(fd
, mem
, len
);
114 #endif /* DATA_AS_HEX */
117 /*---------------------------------------------------------------------------*/
119 write_word(int fd
, uint16_t w
)
123 write_byte(fd
, tmp
.u8
[0]);
124 write_byte(fd
, tmp
.u8
[1]);
126 /*---------------------------------------------------------------------------*/
133 cfs_read(fd
, hex
, 2);
135 if(hex
[0] >= 'A' && hex
[0] <= 'F') {
136 hex
[0] = (hex
[0] - 'A' + 0xa);
137 } else if(hex
[0] >= 'a' && hex
[0] <= 'f') {
138 hex
[0] = (hex
[0] - 'a' + 0xa);
140 hex
[0] = (hex
[0] - '0');
142 if(hex
[1] >= 'A' && hex
[1] <= 'F') {
143 hex
[1] = (hex
[1] - 'A' + 0xa);
144 } else if(hex
[1] >= 'a' && hex
[1] <= 'f') {
145 hex
[1] = (hex
[1] - 'a' + 0xa);
147 hex
[1] = (hex
[1] - '0');
149 return (uint8_t)((hex
[0]<<4)&0xf0) | (hex
[1]&0x0f);
150 #else /* DATA_AS_HEX */
154 #endif /* DATA_AS_HEX */
156 /*---------------------------------------------------------------------------*/
161 tmp
.u8
[0] = read_byte(fd
);
162 tmp
.u8
[1] = read_byte(fd
);
165 /*---------------------------------------------------------------------------*/
167 thread_checkpoint(int fd
)
172 unsigned char *thread_mem_start
= (unsigned char *)&checkpoint_thread
.thread
.stack
;
173 unsigned char *thread_mem_end
= thread_mem_start
+ sizeof(checkpoint_thread
.thread
.stack
) - 1;
174 unsigned char *coffee_mem_start
= cfs_coffee_get_protected_mem(&size
);
175 unsigned char *coffee_mem_end
= coffee_mem_start
+ size
- 1;
176 #endif /* INCLUDE_RAM */
178 /*printf("protected thread memory: %u, size=%u\n", (uint16_t) thread_mem_start, sizeof(checkpoint_thread.thread.stack));*/
179 /*printf("protected coffee memory: %u, size=%u\n", (uint16_t) coffee_mem_start, size);*/
183 for(addr
= (unsigned char *)RAM_START
;
184 addr
< (unsigned char *)RAM_END
;
187 if((addr
>= thread_mem_start
&& addr
<= thread_mem_end
)) {
188 /* Writing dummy memory */
189 /*write_byte(fd, 1);*/
193 if((addr
>= coffee_mem_start
&& addr
<= coffee_mem_end
)) {
194 /* Writing dummy memory */
195 /*write_byte(fd, 2);*/
199 /* TODO Use write_array() */
200 write_byte(fd
, *addr
);
202 if(((int)addr
% 512) == 0) {
207 #endif /* INCLUDE_RAM */
211 write_word(fd
, TACTL
);
212 write_word(fd
, TACCTL1
);
213 write_word(fd
, TACCR1
);
216 write_word(fd
, TBCTL
);
217 write_word(fd
, TBCCTL1
);
218 write_word(fd
, TBCCR1
);
220 #endif /* INCLUDE_TIMERS */
224 write_byte(fd
, leds_arch_get());
225 #endif /* INCLUDE_LEDS */
231 write_byte(fd
, -1); /* Coffee padding byte */
233 /*---------------------------------------------------------------------------*/
235 thread_rollback(int fd
)
240 unsigned char *thread_mem_start
= (unsigned char *)&checkpoint_thread
.thread
.stack
;
241 unsigned char *thread_mem_end
= thread_mem_start
+ sizeof(checkpoint_thread
.thread
.stack
) - 1;
242 unsigned char *coffee_mem_start
= cfs_coffee_get_protected_mem(&size
);
243 unsigned char *coffee_mem_end
= coffee_mem_start
+ size
- 1;
244 #endif /* INCLUDE_RAM */
246 /*printf("protected thread memory: %u, size=%u\n", (uint16_t) thread_mem_start, sizeof(checkpoint_thread.thread.stack));*/
247 /*printf("protected coffee memory: %u, size=%u\n", (uint16_t) coffee_mem_start, size);*/
251 for(addr
= (unsigned char *)RAM_START
;
252 addr
< (unsigned char *)RAM_END
;
254 if((addr
>= thread_mem_start
&& addr
<= thread_mem_end
)) {
255 /* Ignoring incoming memory */
260 if((addr
>= coffee_mem_start
&& addr
<= coffee_mem_end
)) {
261 /* Ignoring incoming memory */
266 *addr
= read_byte(fd
);
268 if(((int)addr
% 512) == 0) {
273 #endif /* INCLUDE_RAM */
277 TACTL
= read_word(fd
);
278 TACCTL1
= read_word(fd
);
279 TACCR1
= read_word(fd
);
282 TBCTL
= read_word(fd
);
283 TBCCTL1
= read_word(fd
);
284 TBCCR1
= read_word(fd
);
286 #endif /* INCLUDE_TIMERS */
290 leds_arch_set(read_byte(fd
));
291 #endif /* INCLUDE_LEDS */
297 read_byte(fd
); /* Coffee padding byte */
299 /*---------------------------------------------------------------------------*/
301 thread_loop(void *data
)
307 /* Store command and file descriptor on stack */
312 if(cmd
== COMMAND_ROLLBACK
) {
313 PRINTF("Rolling back");
316 } else if(cmd
== COMMAND_CHECKPOINT
) {
317 PRINTF("Checkpointing");
318 thread_checkpoint(fd
);
320 } else if(cmd
== COMMAND_TBR
) {
321 PRINTF("Writing TBR");
325 printf("Error: unknown command: %u\n", cmd
);
328 /* Return to main Contiki thread */
332 /*---------------------------------------------------------------------------*/
334 checkpoint_arch_size()
338 /*---------------------------------------------------------------------------*/
340 checkpoint_arch_checkpoint(int fd
)
344 preset_cmd
= COMMAND_CHECKPOINT
;
346 mt_exec(&checkpoint_thread
);
350 /*---------------------------------------------------------------------------*/
352 checkpoint_arch_rollback(int fd
)
356 preset_cmd
= COMMAND_ROLLBACK
;
358 mt_exec(&checkpoint_thread
);
362 /*---------------------------------------------------------------------------*/
364 checkpoint_arch_init(void)
367 mt_start(&checkpoint_thread
, thread_loop
, NULL
);
369 /*mt_stop(&checkpoint_thread);*/
372 /*---------------------------------------------------------------------------*/