Mercurial > pihelp
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 |