51 #include "dev/watchdog.h"
53 #include "dev/uart1.h"
55 #include "dev/button-sensor.h"
62 #define PRINTF(...) printf(__VA_ARGS__)
67 #ifndef CHECKPOINT_ROLLBACK_BUTTON
68 #define CHECKPOINT_ROLLBACK_BUTTON 1
71 #if CHECKPOINT_ROLLBACK_BUTTON
72 PROCESS(checkpoint_button_process,
"Rollback on button");
75 #define WITH_SERIAL_COMMANDS 0
76 #if WITH_SERIAL_COMMANDS
77 #if UART1_CONF_TX_WITH_INTERRUPT
78 #error TX_WITH_INTERRUPTS must be 0
80 #define PRINTF_COMMAND(...) printf(__VA_ARGS__)
82 #define PRINTF_COMMAND(...)
85 #define COMMAND_ROLLBACK 1
86 #define COMMAND_CHECKPOINT 2
87 #define COMMAND_METRICS 3
90 #define INCLUDE_TIMERS 1
91 #define INCLUDE_LEDS 1
95 #define RAM_START 0x1100
96 #define RAM_END 0x3900
98 #define PAUSE_TIME() \
102 #define RESUME_TIME() \
105 TACCR1 = clock_fine_max(); \
107 #define PAUSE_TIME_INT() \
110 #define RESUME_TIME_INT() \
114 static struct mt_thread checkpoint_thread;
115 static uint8_t preset_cmd;
116 static int preset_fd;
119 #if WITH_SERIAL_COMMANDS
120 static int nr_pongs=0;
122 static int nr_checkpoints=0, nr_rollbacks=0, nr_metrics=0;
131 write_byte(
int fd, uint8_t c)
133 return cfs_write(fd, &c, 1);
137 write_word(
int fd, uint16_t w)
141 write_byte(fd, tmp.u8[0]);
142 write_byte(fd, tmp.u8[1]);
157 tmp.u8[0] = read_byte(fd);
158 tmp.u8[1] = read_byte(fd);
163 thread_checkpoint(
int fd)
168 unsigned char *thread_mem_start = (
unsigned char *)&checkpoint_thread.thread.stack;
169 unsigned char *thread_mem_end = thread_mem_start +
sizeof(checkpoint_thread.thread.stack) - 1;
171 unsigned char *coffee_mem_end = coffee_mem_start + size - 1;
179 for(addr = (
unsigned char *)RAM_START;
180 addr < (
unsigned char *)RAM_END;
183 if((addr >= thread_mem_start && addr <= thread_mem_end)) {
188 if((addr >= coffee_mem_start && addr <= coffee_mem_end)) {
194 write_byte(fd, *addr);
205 write_word(fd, TACTL);
206 write_word(fd, TACCTL1);
207 write_word(fd, TACCR1);
210 write_word(fd, TBCTL);
211 write_word(fd, TBCCTL1);
212 write_word(fd, TBCCR1);
218 write_byte(fd, leds_arch_get());
229 thread_rollback(
int fd)
234 unsigned char *thread_mem_start = (
unsigned char *)&checkpoint_thread.thread.stack;
235 unsigned char *thread_mem_end = thread_mem_start +
sizeof(checkpoint_thread.thread.stack) - 1;
237 unsigned char *coffee_mem_end = coffee_mem_start + size - 1;
245 for(addr = (
unsigned char *)RAM_START;
246 addr < (
unsigned char *)RAM_END;
248 if((addr >= thread_mem_start && addr <= thread_mem_end)) {
253 if((addr >= coffee_mem_start && addr <= coffee_mem_end)) {
258 *addr = read_byte(fd);
264 TACTL = read_word(fd);
265 TACCTL1 = read_word(fd);
266 TACCR1 = read_word(fd);
269 TBCTL = read_word(fd);
270 TBCCTL1 = read_word(fd);
271 TBCCR1 = read_word(fd);
277 leds_arch_set(read_byte(fd));
287 #if WITH_SERIAL_COMMANDS
289 thread_metric_tx(
void)
292 return energest_type_time(ENERGEST_TYPE_TRANSMIT);
296 thread_metric_rx(
void)
299 return energest_type_time(ENERGEST_TYPE_LISTEN);
306 PRINTF_COMMAND(
"METRICS:START\n");
307 PRINTF_COMMAND(
"M:RTIMER_NOW:%u\n",
RTIMER_NOW());
308 PRINTF_COMMAND(
"M:ENERGY_TX:%lu\n", thread_metric_tx());
309 PRINTF_COMMAND(
"M:ENERGY_RX:%lu\n", thread_metric_rx());
310 PRINTF_COMMAND(
"M:RTIMER_NOW2:%u\n",
RTIMER_NOW());
312 PRINTF_COMMAND(
"METRICS:DONE %u\n", nr_metrics);
316 checkpoint_thread_loop(
void *data)
327 if(cmd == COMMAND_ROLLBACK) {
328 PRINTF_COMMAND(
"RB:START\n");
331 PRINTF_COMMAND(
"RB:DONE %u\n", nr_rollbacks);
333 }
else if(cmd == COMMAND_CHECKPOINT) {
334 PRINTF_COMMAND(
"CP:START\n");
335 thread_checkpoint(fd);
338 PRINTF_COMMAND(
"CP:DONE %u\n", nr_checkpoints);
339 }
else if(cmd == COMMAND_METRICS) {
342 printf(
"ERROR: Unknown thread command: %u\n", cmd);
351 checkpoint_arch_size()
357 checkpoint_arch_checkpoint(
int fd)
361 preset_cmd = COMMAND_CHECKPOINT;
369 checkpoint_arch_rollback(
int fd)
373 preset_cmd = COMMAND_ROLLBACK;
380 static uint8_t inited = 0;
382 checkpoint_arch_init(
void)
389 mt_start(&checkpoint_thread, checkpoint_thread_loop,
NULL);
392 #if CHECKPOINT_ROLLBACK_BUTTON
405 #if WITH_SERIAL_COMMANDS
407 serial_interrupt_checkpoint()
412 if(SPI_IS_ENABLED()) {
414 PRINTF_COMMAND(
"CP:SPIBUSY\n");
425 printf(
"ERROR: No file access (cp)\n");
431 preset_cmd = COMMAND_CHECKPOINT;
442 serial_interrupt_rollback()
447 if(SPI_IS_ENABLED()) {
449 PRINTF_COMMAND(
"RB:SPIBUSY\n");
458 printf(
"ERROR: No file access (rb)\n");
464 preset_cmd = COMMAND_ROLLBACK;
475 serial_interrupt_metrics()
479 preset_cmd = COMMAND_METRICS;
486 static const unsigned char command_checkpoint[] = {
'c',
'p',
'\n' };
487 static const unsigned char command_rollback[] = {
'r',
'b',
'\n' };
488 static const unsigned char command_metrics[] = {
'm',
't',
'\n' };
489 static volatile int command_checkpoint_state = 0;
490 static volatile int command_rollback_state = 0;
491 static volatile int command_metrics_state = 0;
494 serial_input_byte_intercept(
unsigned char c)
497 if(command_checkpoint[command_checkpoint_state] == c) {
498 command_checkpoint_state++;
500 if(command_checkpoint_state ==
sizeof(command_checkpoint)) {
501 serial_interrupt_checkpoint();
502 command_checkpoint_state = 0;
505 command_checkpoint_state = 0;
509 if(command_rollback[command_rollback_state] == c) {
510 command_rollback_state++;
512 if(command_rollback_state ==
sizeof(command_rollback)) {
513 serial_interrupt_rollback();
514 command_rollback_state = 0;
517 command_rollback_state = 0;
521 if(command_metrics[command_metrics_state] == c) {
522 command_metrics_state++;
524 if(command_metrics_state ==
sizeof(command_metrics)) {
525 serial_interrupt_metrics();
526 command_metrics_state = 0;
529 command_metrics_state = 0;
533 return serial_line_input_byte(c);
537 handle_get_command(
void)
542 printf(
"ERROR: No file access (get)\n");
544 PRINTF_COMMAND(
"GET:START\n");
546 int offset=0, size=0, read=8;
547 unsigned short crc = 0;
557 read = cfs_read(fd, data, 8);
560 printf(
"%04i: ", offset);
561 for (i=0; i < read; i++) {
563 printf(
"%02x", (uint8_t) (0xff&data[i]));
570 PRINTF_COMMAND(
"GET:DONE CRC=%u\n", crc);
576 hex_decode_char(
char c)
578 if(c >=
'A' && c <=
'F') {
580 }
else if(c >=
'a' && c <=
'f') {
582 }
else if(c >=
'0' && c <=
'9') {
585 printf(
"WARN: bad hex: %c\n", c);
590 PROCESS(checkpoint_serial_process,
"Checkpoint via serial commands");
593 static int set_fd = -1;
594 static int set_count = -1;
600 uart1_set_input(serial_input_byte_intercept);
603 PRINTF(
"Formatting Coffee\n");
605 PRINTF(
"Formatting Coffee... done!\n");
610 if(strcmp(
"set", data) == 0) {
618 printf(
"SET:FSBUSY\n");
620 printf(
"SET:LINE\n");
622 }
else if(set_fd >= 0 && strcmp(
"set:done", data) == 0) {
625 if(set_count == 9862) {
626 printf(
"SET:DONE\n");
628 printf(
"SET:WRONGSIZE\n");
630 }
else if(set_fd >= 0) {
632 printf(
"SET:LINE\n");
634 int len = strlen((
char*)data);
635 if(len > 16 || (len%2)!=0) {
636 printf(
"WARN: bad set data: %s\n", (
char*)data);
639 for (i=0; i < len; i+=2) {
641 (hex_decode_char(((
char*)data)[i]) << 4) +
642 (hex_decode_char(((
char*)data)[i+1]));
644 PRINTF(
"Parsing set command: writing to CFS: %02x\n", b);
645 write_byte(set_fd, b);
649 }
else if(strcmp(
"", data) == 0 ||
650 strcmp(
"cp", data) == 0 ||
651 strcmp(
"rb", data) == 0 ||
652 strcmp(
"mt", data) == 0) {
654 }
else if(strcmp(
"ping", data) == 0) {
656 printf(
"pong %u\n", nr_pongs);
657 }
else if(strcmp(
"get", data) == 0) {
658 handle_get_command();
660 printf(
"WARN: Unknown command: '%s'\n", (
char*)data);
668 #if CHECKPOINT_ROLLBACK_BUTTON
673 button_sensor.configure(SENSORS_ACTIVE, 1);
678 if(ev == sensors_event && data == &button_sensor) {
684 checkpoint_rollback(fd);