comparison main.c @ 20:bc48a1d17edf

near done
author Matt Johnston <matt@ucc.asn.au>
date Sun, 16 Jun 2013 13:04:09 +0800
parents 021e6e0006f4
children 83a0663c082f
comparison
equal deleted inserted replaced
18:021e6e0006f4 20:bc48a1d17edf
17 #include "aes.h" 17 #include "aes.h"
18 18
19 //#include "simple_ds18b20.h" 19 //#include "simple_ds18b20.h"
20 //#include "onewire.h" 20 //#include "onewire.h"
21 21
22 LOCKBITS = (LB_MODE_3 & BLB0_MODE_4 & BLB1_MODE_4); 22 // not set via bootloader
23 //LOCKBITS = (LB_MODE_3 & BLB0_MODE_4 & BLB1_MODE_4);
23 24
24 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) 25 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
25 #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) 26 #define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
26 27
27 // TICK should be 8 or less (8 untested). all timers need 28 // TICK should be 8 or less (8 untested). all timers need
32 #define NKEYS 10 33 #define NKEYS 10
33 #define HMACLEN 20 34 #define HMACLEN 20
34 #define AESLEN 16 35 #define AESLEN 16
35 #define KEYLEN HMACLEN 36 #define KEYLEN HMACLEN
36 37
37 #define BAUD 19200 38 #define BAUD 38400
38 #define UBRR ((F_CPU)/8/(BAUD)-1) 39 #define UBRR ((F_CPU)/(16*(BAUD))-1)
39 40
40 #define PORT_PI_BOOT PORTD 41 #define PORT_PI_BOOT PORTD
41 #define DDR_PI_BOOT DDRD 42 #define DDR_PI_BOOT DDRD
42 #define PIN_PI_BOOT PD5 43 #define PIN_PI_BOOT PD5
43 44
55 // for 1/32 second accuracy 56 // for 1/32 second accuracy
56 struct epoch_ticks 57 struct epoch_ticks
57 { 58 {
58 uint32_t ticks; 59 uint32_t ticks;
59 // remainder 60 // remainder
60 uint8_t rem; 61 uint16_t rem;
61 }; 62 };
62 63
63 #define WATCHDOG_LONG_MIN (60L*40) // 40 mins 64 #define WATCHDOG_LONG_MIN (60L*40) // 40 mins
64 #define WATCHDOG_LONG_MAX (60L*60*72) // 72 hours 65 #define WATCHDOG_LONG_MAX (60L*60*72) // 72 hours
65 #define WATCHDOG_LONG_DEFAULT (60L*60*6) // 6 hours 66 #define WATCHDOG_LONG_DEFAULT (60L*60*6) // 6 hours
107 // working firmware should boot. set back to 0 for each 'alive' 108 // working firmware should boot. set back to 0 for each 'alive'
108 // command 109 // command
109 static uint8_t long_reboot_mode = 0; 110 static uint8_t long_reboot_mode = 0;
110 111
111 static uint8_t readpos; 112 static uint8_t readpos;
112 static char readbuf[50]; 113 static char readbuf[150];
113 static uint8_t have_cmd; 114 static uint8_t have_cmd;
114 115
115 int uart_putchar(char c, FILE *stream); 116 int uart_putchar(char c, FILE *stream);
116 static void long_delay(int ms); 117 static void long_delay(int ms);
117 static void blink(); 118 static void blink();
118 static uint16_t adc_vcc(); 119 static uint16_t adc_vcc();
119 static uint16_t adc_5v(uint16_t vcc); 120 static uint16_t adc_5v(uint16_t vcc);
121 static uint16_t adc_temp();
120 static void set_pi_boot_normal(uint8_t normal); 122 static void set_pi_boot_normal(uint8_t normal);
121 123
122 124
123 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, 125 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL,
124 _FDEV_SETUP_WRITE); 126 _FDEV_SETUP_WRITE);
144 // Very first setup 146 // Very first setup
145 static void 147 static void
146 setup_chip() 148 setup_chip()
147 { 149 {
148 cli(); 150 cli();
149
150 // stop watchdog timer (might have been used to cause a reset)
151 wdt_reset();
152 MCUSR &= ~_BV(WDRF);
153 WDTCSR |= _BV(WDCE) | _BV(WDE);
154 WDTCSR = 0;
155 151
156 // set to 8 seconds, in case sha1 is slow etc. 152 // set to 8 seconds, in case sha1 is slow etc.
157 wdt_enable(WDTO_8S); 153 wdt_enable(WDTO_8S);
158 154
159 // Set scaler to /1, -> clock to 8mhz 155 // Set scaler to /1, -> clock to 8mhz
209 TCCR1A = _BV(COM1A0); 205 TCCR1A = _BV(COM1A0);
210 #ifdef SIM_DEBUG 206 #ifdef SIM_DEBUG
211 // systemclock/8 207 // systemclock/8
212 TCCR1B = _BV(CS11); 208 TCCR1B = _BV(CS11);
213 #else 209 #else
214 // systemclock/64 210 // systemclock/256
215 TCCR1B = _BV(CS11) | _BV(CS10); 211 TCCR1B = _BV(CS12);
216 #endif 212 #endif
217 TCNT1 = 0; 213 TCNT1 = 0;
218 OCR1A = SLEEP_COMPARE; 214 OCR1A = SLEEP_COMPARE;
219 // interrupt 215 // interrupt
220 TIMSK1 = _BV(OCIE1A); 216 TIMSK1 = _BV(OCIE1A);
263 UDR0 = '\n'; 259 UDR0 = '\n';
264 } 260 }
265 return (unsigned char)c; 261 return (unsigned char)c;
266 } 262 }
267 263
268 static void 264 static void cmd_reset() __attribute__ ((noreturn));
269 cmd_reset() 265 static void
266 cmd_reset()
270 { 267 {
271 printf_P(PSTR("reset\n")); 268 printf_P(PSTR("reset\n"));
272 _delay_ms(100); 269 _delay_ms(100);
273 cli(); // disable interrupts 270 cli(); // disable interrupts
274 wdt_enable(WDTO_15MS); // enable watchdog 271 wdt_enable(WDTO_15MS); // enable watchdog
281 set_pi_boot_normal(1); 278 set_pi_boot_normal(1);
282 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 279 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
283 { 280 {
284 newboot_count = newboot_limit; 281 newboot_count = newboot_limit;
285 } 282 }
286 printf_P(PSTR("newboot for %d secs"), newboot_limit); 283 printf_P(PSTR("newboot for %d secs\n"), newboot_limit);
287 } 284 }
288 285
289 static void 286 static void
290 cmd_oldboot() 287 cmd_oldboot()
291 { 288 {
297 printf_P(PSTR("back to old boot\n")); 294 printf_P(PSTR("back to old boot\n"));
298 } 295 }
299 296
300 297
301 static void 298 static void
302 cmd_get_params() 299 cmd_status()
303 { 300 {
304 uint32_t cur_watchdog_long, cur_watchdog_short, cur_newboot, cur_oneshot; 301 uint32_t cur_watchdog_long, cur_watchdog_short, cur_newboot, cur_oneshot;
302 struct epoch_ticks t;
303
304 get_epoch_ticks(&t);
305
305 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) 306 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
306 { 307 {
307 cur_watchdog_long = watchdog_long_count; 308 cur_watchdog_long = watchdog_long_count;
308 cur_watchdog_short = watchdog_short_count; 309 cur_watchdog_short = watchdog_short_count;
309 cur_newboot = newboot_count; 310 cur_newboot = newboot_count;
310 cur_oneshot = oneshot_count; 311 cur_oneshot = oneshot_count;
311 } 312 }
312 313
313 printf_P(PSTR("limit (count) : watchdog_long %lu (%lu) watchdog_short %lu (%lu) newboot %lu (%lu) oneshot (%lu)\n"), 314 printf_P(PSTR("limit (current)\n"
314 watchdog_long_limit, 315 "watchdog_long %lu (%lu) watchdog newboot mode %d\n"
315 cur_watchdog_long, 316 "watchdog_short %lu (%lu)\n"
316 watchdog_short_limit, 317 "newboot %lu (%lu)\n"
317 cur_watchdog_short, 318 "oneshot (%lu)\n"
318 newboot_limit, 319 "uptime %lu rem %u\n"
319 cur_newboot, 320 ),
320 cur_oneshot); 321 watchdog_long_limit, cur_watchdog_long, long_reboot_mode,
322 watchdog_short_limit, cur_watchdog_short,
323 newboot_limit, cur_newboot,
324 cur_oneshot,
325 t.ticks, t.rem);
321 } 326 }
322 327
323 static void 328 static void
324 cmd_set_params(const char *params) 329 cmd_set_params(const char *params)
325 { 330 {
401 parse_key(const char *params, uint8_t *key_index, uint8_t *bytes, 406 parse_key(const char *params, uint8_t *key_index, uint8_t *bytes,
402 uint8_t bytes_len) 407 uint8_t bytes_len)
403 { 408 {
404 // "N HEXKEY" 409 // "N HEXKEY"
405 if (strlen(params) != bytes_len*2 + 2) { 410 if (strlen(params) != bytes_len*2 + 2) {
406 printf_P(PSTR("Wrong length key\n")); 411 printf_P(PSTR("Wrong length key. wanted %d, got %d, '%s'\n"),
412 bytes_len*2+2, strlen(params), params);
407 return -1; 413 return -1;
408 } 414 }
409 415
410 if (params[1] != ' ') 416 if (params[1] != ' ')
411 { 417 {
438 } 444 }
439 memcpy(avr_keys[key_index], new_key, sizeof(new_key)); 445 memcpy(avr_keys[key_index], new_key, sizeof(new_key));
440 #ifndef SIM_DEBUG 446 #ifndef SIM_DEBUG
441 eeprom_write(avr_keys, avr_keys); 447 eeprom_write(avr_keys, avr_keys);
442 #endif 448 #endif
449 printf_P(PSTR("Set key %d: "), key_index);
450 printhex(new_key, sizeof(new_key), stdout);
451 putchar('\n');
443 } 452 }
444 453
445 static void 454 static void
446 cmd_hmac(const char *params) 455 cmd_hmac(const char *params)
447 { 456 {
459 #endif 468 #endif
460 469
461 hmac_sha1(outdata, avr_keys[key_index], KEYLEN*8, indata, sizeof(indata)*8); 470 hmac_sha1(outdata, avr_keys[key_index], KEYLEN*8, indata, sizeof(indata)*8);
462 printf_P(PSTR("HMAC: ")); 471 printf_P(PSTR("HMAC: "));
463 printhex(outdata, HMACLEN, stdout); 472 printhex(outdata, HMACLEN, stdout);
464 fputc('\n', stdout); 473 putchar('\n');
465 } 474 }
466 475
467 static void 476 static void
468 cmd_decrypt(const char *params) 477 cmd_decrypt(const char *params)
469 { 478 {
494 aesInit(avr_keys[key_index], tmpbuf); 503 aesInit(avr_keys[key_index], tmpbuf);
495 aesDecrypt(&indata[HMACLEN], NULL); 504 aesDecrypt(&indata[HMACLEN], NULL);
496 505
497 printf_P(PSTR("DECRYPTED: ")); 506 printf_P(PSTR("DECRYPTED: "));
498 printhex(output, AESLEN, stdout); 507 printhex(output, AESLEN, stdout);
499 fputc('\n', stdout); 508 putchar('\n');
500 } 509 }
501 510
502 static void 511 static void
503 cmd_oneshot_reboot(const char *params) 512 cmd_oneshot_reboot(const char *params)
504 { 513 {
566 uint16_t vcc = adc_vcc(); 575 uint16_t vcc = adc_vcc();
567 uint16_t v5 = adc_5v(vcc); 576 uint16_t v5 = adc_5v(vcc);
568 printf_P(PSTR("vcc: %u mV\n5v: %u mV\n"), vcc, v5); 577 printf_P(PSTR("vcc: %u mV\n5v: %u mV\n"), vcc, v5);
569 } 578 }
570 579
580 void(*bootloader)() __attribute__ ((noreturn)) = (void*)0x7e00;
581
582 #if 0
583 #ifndef PROG_PASSWORD
584 #define PROG_PASSWORD "Y2vvjxO5"
585 #endif
586
587 static void
588 cmd_prog(const char* arg)
589 {
590 if (strcmp(arg, PROG_PASSWORD) != 0)
591 {
592 printf_P(PSTR("Bad prog password\n"));
593 return;
594 }
595
596 // disable wdt
597 wdt_disable();
598
599 // disable interrupts
600 TIMSK0 = 0;
601 TIMSK1 = 0;
602 TIMSK2 = 0;
603 EIMSK = 0;
604 PCMSK0 = 0;
605 PCMSK1 = 0;
606 PCMSK2 = 0;
607 ACSR &= ~_BV(ACIE);
608 ADCSRA &= ~_BV(ADIE);
609 UCSR0B &= ~_BV(RXCIE0);
610 UCSR0B &= _BV(TXCIE0);
611 // doesn't do TWI, other uart, probably others
612
613 _delay_ms(20);
614
615 bootloader();
616 }
617 #endif
618
571 static void 619 static void
572 read_handler() 620 read_handler()
573 { 621 {
574 #define LOCAL_PSTR(x) const static char x ## _str[] PROGMEM = #x; 622 #define LOCAL_PSTR(x) const static char x ## _str[] PROGMEM = #x;
575 #define LOCAL_HELP(x, d) const static char x ## _help[] PROGMEM = d; 623 #define LOCAL_HELP(x, d) const static char x ## _help[] PROGMEM = d;
576 624
577 LOCAL_PSTR(get_params);
578 LOCAL_PSTR(set_params); 625 LOCAL_PSTR(set_params);
579 LOCAL_PSTR(set_key); 626 LOCAL_PSTR(set_key);
580 LOCAL_PSTR(oneshot); 627 LOCAL_PSTR(oneshot);
581 LOCAL_PSTR(hmac); 628 LOCAL_PSTR(hmac);
582 LOCAL_PSTR(decrypt); 629 LOCAL_PSTR(decrypt);
583 LOCAL_PSTR(alive); 630 LOCAL_PSTR(alive);
584 LOCAL_PSTR(vcc); 631 LOCAL_PSTR(vcc);
585 LOCAL_PSTR(reset); 632 LOCAL_PSTR(reset);
586 LOCAL_PSTR(newboot); 633 LOCAL_PSTR(newboot);
587 LOCAL_PSTR(oldboot); 634 LOCAL_PSTR(oldboot);
635 LOCAL_PSTR(status);
588 LOCAL_HELP(set_params, "<long_limit> <short_limit> <newboot_limit>"); 636 LOCAL_HELP(set_params, "<long_limit> <short_limit> <newboot_limit>");
589 LOCAL_HELP(set_key, "20_byte_hex>"); 637 LOCAL_HELP(set_key, "20_byte_hex>");
590 LOCAL_HELP(oneshot, "<timeout>"); 638 LOCAL_HELP(oneshot, "<timeout>");
591 LOCAL_HELP(hmac, "<key_index> <20_byte_hex_data>"); 639 LOCAL_HELP(hmac, "<key_index> <20_byte_hex_data>");
592 LOCAL_HELP(decrypt, "<key_index> <20_byte_hmac|16_byte_aes_block>"); 640 LOCAL_HELP(decrypt, "<key_index> <20_byte_hmac|16_byte_aes_block>");
594 static const struct handler { 642 static const struct handler {
595 PGM_P name; 643 PGM_P name;
596 void(*cmd)(const char *param); 644 void(*cmd)(const char *param);
597 // existence of arg_help indicates if the cmd takes a parameter. 645 // existence of arg_help indicates if the cmd takes a parameter.
598 PGM_P arg_help; 646 PGM_P arg_help;
599 } handlers[11] PROGMEM = 647 } handlers[] PROGMEM =
600 { 648 {
601 {get_params_str, cmd_get_params, NULL}, 649 {alive_str, cmd_alive, NULL},
650 {newboot_str, cmd_newboot, NULL},
651 {oldboot_str, cmd_oldboot, NULL},
652 {oneshot_str, cmd_oneshot_reboot, oneshot_help},
653 {status_str, cmd_status, NULL},
654 {hmac_str, cmd_hmac, hmac_help},
655 {decrypt_str, cmd_decrypt, decrypt_help},
602 {set_params_str, cmd_set_params, set_params_help}, 656 {set_params_str, cmd_set_params, set_params_help},
603 {set_key_str, cmd_set_avr_key, set_key_help}, 657 {set_key_str, cmd_set_avr_key, set_key_help},
604 {oneshot_str, cmd_oneshot_reboot, oneshot_help},
605 {hmac_str, cmd_hmac, hmac_help},
606 {decrypt_str, cmd_decrypt, decrypt_help},
607 {alive_str, cmd_alive, NULL},
608 {vcc_str, cmd_vcc, NULL}, 658 {vcc_str, cmd_vcc, NULL},
609 {reset_str, cmd_reset, NULL}, 659 {reset_str, cmd_reset, NULL},
610 {newboot_str, cmd_newboot, NULL},
611 {oldboot_str, cmd_oldboot, NULL},
612 }; 660 };
613 661
614 if (readbuf[0] == '\0') 662 if (readbuf[0] == '\0')
615 { 663 {
616 return; 664 return;
971 { 1019 {
972 //uart_on(); 1020 //uart_on();
973 printf_P(PSTR("Bad interrupt\n")); 1021 printf_P(PSTR("Bad interrupt\n"));
974 } 1022 }
975 1023
1024 // disable watchdog on boot
1025 void wdt_init(void) __attribute__((naked)) __attribute__((section(".init3")));
1026 void wdt_init(void)
1027 {
1028 MCUSR = 0;
1029 wdt_disable();
1030 }
1031
976 int main(void) 1032 int main(void)
977 { 1033 {
978 _Static_assert(F_CPU % 256 == 0, "clock prescaler remainder 0"); 1034 _Static_assert(F_CPU % 256 == 0, "clock prescaler remainder 0");
979 _Static_assert(NEWBOOT_MAX < WATCHDOG_LONG_MIN, "newboot max shorter than watchdog min"); 1035 _Static_assert(NEWBOOT_MAX < WATCHDOG_LONG_MIN, "newboot max shorter than watchdog min");
1036 _Static_assert((F_CPU)%(16*(BAUD)) == 0, "baud rate good multiple");
980 1037
981 setup_chip(); 1038 setup_chip();
982 blink(); 1039 blink();
983 1040
984 stdout = &mystdout; 1041 stdout = &mystdout;
985 uart_on(); 1042 uart_on();
986 1043
987 printf_P(PSTR("Pi Watchdog\nMatt Johnston [email protected]")); 1044 long_delay(500);
1045 printf_P(PSTR("Pi Watchdog\nMatt Johnston [email protected]\n"));
988 1046
989 set_pi_boot_normal(0); 1047 set_pi_boot_normal(0);
990 1048
991 load_params(); 1049 load_params();
992 1050