Mercurial > pihelp
comparison main.c @ 27:ce5097eacf2f
try at adc_random()
use interrupts and noise reduction for other sleep
115200, faster crystal
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 26 Jun 2013 23:12:37 +0800 |
parents | 292cd17de2a4 |
children | 5d6a841eef82 |
comparison
equal
deleted
inserted
replaced
26:292cd17de2a4 | 27:ce5097eacf2f |
---|---|
39 #define NKEYS 10 | 39 #define NKEYS 10 |
40 #define HMACLEN 20 | 40 #define HMACLEN 20 |
41 #define AESLEN 16 | 41 #define AESLEN 16 |
42 #define KEYLEN HMACLEN | 42 #define KEYLEN HMACLEN |
43 | 43 |
44 #define BAUD 38400 | 44 #define BAUD 115200 |
45 #define UBRR ((F_CPU)/(16*(BAUD))-1) | 45 #define UBRR ((F_CPU)/(16*(BAUD))-1) |
46 | 46 |
47 #define PORT_PI_BOOT PORTD | 47 #define PORT_PI_BOOT PORTD |
48 #define DDR_PI_BOOT DDRD | 48 #define DDR_PI_BOOT DDRD |
49 #define PIN_PI_BOOT PD5 | 49 #define PIN_PI_BOOT PD5 |
98 static uint32_t newboot_count; | 98 static uint32_t newboot_count; |
99 // oneshot counts down | 99 // oneshot counts down |
100 static uint32_t oneshot_count; | 100 static uint32_t oneshot_count; |
101 // countdown after the warning. | 101 // countdown after the warning. |
102 static uint8_t reboot_count; | 102 static uint8_t reboot_count; |
103 // set by adc completion interrupt | |
104 static uint8_t adc_done; | |
103 | 105 |
104 // ---- End atomic guards required | 106 // ---- End atomic guards required |
105 | 107 |
106 // boolean flags | 108 // boolean flags |
107 static uint8_t watchdog_long_hit; | 109 static uint8_t watchdog_long_hit; |
559 if (memcmp(output, indata, HMACLEN) != 0) { | 561 if (memcmp(output, indata, HMACLEN) != 0) { |
560 printf_P(PSTR("FAIL: hmac mismatch\n")); | 562 printf_P(PSTR("FAIL: hmac mismatch\n")); |
561 } | 563 } |
562 | 564 |
563 uint8_t tmpbuf[256]; | 565 uint8_t tmpbuf[256]; |
564 //aesInit(avr_keys[key_index], tmpbuf); | 566 aesInit(avr_keys[key_index], tmpbuf); |
565 //aesDecrypt(&indata[HMACLEN], NULL); | 567 aesDecrypt(&indata[HMACLEN], NULL); |
566 | 568 |
567 printf_P(PSTR("DECRYPTED: ")); | 569 printf_P(PSTR("DECRYPTED: ")); |
568 printhex(output, AESLEN, stdout); | 570 printhex(output, AESLEN, stdout); |
569 putchar('\n'); | 571 putchar('\n'); |
570 } | 572 } |
633 static void | 635 static void |
634 cmd_vcc() | 636 cmd_vcc() |
635 { | 637 { |
636 uint16_t vcc = adc_vcc(); | 638 uint16_t vcc = adc_vcc(); |
637 uint16_t v5 = adc_5v(vcc); | 639 uint16_t v5 = adc_5v(vcc); |
638 uint16_t r = adc_random(); | |
639 uint16_t temp = adc_temp(); | 640 uint16_t temp = adc_temp(); |
640 // roughly? | 641 // roughly? |
641 uint16_t temp_deg = temp - 290; | 642 uint16_t temp_deg = temp - 290; |
642 printf_P(PSTR("vcc: %u mV\n" | 643 printf_P(PSTR("vcc: %u mV\n" |
643 "5v: %u mV\n" | 644 "5v: %u mV\n" |
644 "temp: %u mV (%dºC)\n" | 645 "temp: %u mV (%dºC)\n" |
645 "random: %u\n" | |
646 ), | 646 ), |
647 vcc, v5, temp, temp_deg, r); | 647 vcc, v5, temp, temp_deg); |
648 } | 648 } |
649 | 649 |
650 void(*bootloader)() __attribute__ ((noreturn)) = (void*)0x7e00; | 650 |
651 | 651 void(*bootloader)() __attribute__ ((noreturn)) = (void*)0x7800; |
652 #if 0 | 652 |
653 #ifndef PROG_PASSWORD | 653 #ifndef PROG_PASSWORD |
654 #define PROG_PASSWORD "Y2vvjxO5" | 654 #define PROG_PASSWORD "Y2vvjxO5" |
655 #endif | 655 #endif |
656 | 656 |
657 static void | 657 static void |
682 | 682 |
683 _delay_ms(20); | 683 _delay_ms(20); |
684 | 684 |
685 bootloader(); | 685 bootloader(); |
686 } | 686 } |
687 #endif | 687 |
688 | |
689 static void | |
690 adc_sleep() | |
691 { | |
692 set_sleep_mode(SLEEP_MODE_IDLE); | |
693 sleep_mode(); | |
694 } | |
695 | |
696 #define BITSET(v, n) (((v) >> (n)) & 1) | |
697 | |
698 static inline uint8_t | |
699 popcnt(uint8_t v) | |
700 { | |
701 return BITSET(v, 0) | |
702 + BITSET(v, 1) | |
703 + BITSET(v, 2) | |
704 + BITSET(v, 3) | |
705 + BITSET(v, 4) | |
706 + BITSET(v, 5) | |
707 + BITSET(v, 6) | |
708 + BITSET(v, 7); | |
709 } | |
710 | |
711 static uint8_t | |
712 adc_bit() | |
713 { | |
714 ADCSRA |= _BV(ADSC); | |
715 loop_until_bit_is_clear(ADCSRA, ADSC); | |
716 uint8_t low = ADCL; | |
717 uint8_t high = ADCH; | |
718 return (popcnt(low)&1) ^ (popcnt(high)&1); | |
719 } | |
720 | |
721 static void | |
722 adc_random(uint8_t admux, | |
723 uint8_t *out, uint16_t num, uint32_t *tries) | |
724 { | |
725 uint8_t ret = 0; | |
726 uint8_t count = 0; | |
727 | |
728 PRR &= ~_BV(PRADC); | |
729 // /16 prescaler for 691mhz, no interrupt | |
730 ADCSRA = _BV(ADEN) | _BV(ADPS2); | |
731 | |
732 *tries = 0; | |
733 for (int i = 0; i < num; i++) | |
734 { | |
735 while (count <= 7) | |
736 { | |
737 (*tries)++; | |
738 | |
739 // Von Neumann extractor | |
740 uint8_t one = adc_bit(); | |
741 uint8_t two = adc_bit(); | |
742 if (one == two) | |
743 { | |
744 continue; | |
745 } | |
746 ret |= one << count; | |
747 count++; | |
748 } | |
749 out[i] = ret; | |
750 } | |
751 ADCSRA = 0; | |
752 PRR |= _BV(PRADC); | |
753 } | |
754 | |
755 ISR(ADC_vect) | |
756 { | |
757 adc_done = 1; | |
758 } | |
759 | |
760 static void | |
761 adc_generic(uint8_t admux, uint8_t *ret_num, uint16_t *ret_sum) | |
762 { | |
763 PRR &= ~_BV(PRADC); | |
764 | |
765 // /64 prescaler, interrupt | |
766 ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADIE); | |
767 | |
768 // set to measure 1.1 reference | |
769 ADMUX = admux; | |
770 | |
771 // delay after setting reference etc, allow settling | |
772 long_delay(300); | |
773 // average a number of samples | |
774 uint16_t sum = 0; | |
775 uint8_t num = 0; | |
776 for (uint8_t n = 0; n < 20; n++) | |
777 { | |
778 while (1) | |
779 { | |
780 adc_done = 0; | |
781 ADCSRA |= _BV(ADSC); | |
782 adc_sleep(); | |
783 | |
784 uint8_t done; | |
785 ATOMIC_BLOCK(ATOMIC_RESTORESTATE) | |
786 { | |
787 done = adc_done; | |
788 } | |
789 if (done) | |
790 { | |
791 break; | |
792 } | |
793 } | |
794 | |
795 uint8_t low_11 = ADCL; | |
796 uint8_t high_11 = ADCH; | |
797 uint16_t val = low_11 + (high_11 << 8); | |
798 | |
799 if (n >= 4) | |
800 { | |
801 sum += val; | |
802 num++; | |
803 } | |
804 } | |
805 ADCSRA = 0; | |
806 PRR |= _BV(PRADC); | |
807 | |
808 *ret_num = num; | |
809 *ret_sum = sum; | |
810 } | |
811 | |
812 static uint16_t | |
813 adc_vcc() | |
814 { | |
815 const uint8_t mux = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); | |
816 uint16_t sum; | |
817 uint8_t num; | |
818 | |
819 adc_generic(mux, &num, &sum); | |
820 | |
821 //float res_volts = 1.1 * 1024 * num / sum; | |
822 //return 1000 * res_volts; | |
823 return ((uint32_t)1100*1024*num) / sum; | |
824 } | |
825 | |
826 #define SCALER_5V 2 | |
827 | |
828 static uint16_t | |
829 adc_5v(uint16_t vcc) | |
830 { | |
831 // set to measure ADC4 against AVCC | |
832 const uint8_t mux = _BV(REFS0) | _BV(MUX2); | |
833 uint16_t sum; | |
834 uint8_t num; | |
835 | |
836 adc_generic(mux, &num, &sum); | |
837 | |
838 return ((uint32_t)vcc*sum*SCALER_5V/(num*1024)); | |
839 } | |
840 | |
841 static uint16_t | |
842 adc_temp() | |
843 { | |
844 // set to measure temperature against 1.1v reference. | |
845 const uint8_t mux = _BV(REFS0) | _BV(REFS1) | _BV(MUX3); | |
846 uint16_t sum; | |
847 uint8_t num; | |
848 | |
849 adc_generic(mux, &num, &sum); | |
850 | |
851 // return the voltage | |
852 | |
853 return ((uint32_t)1100*sum) / (num*1024); | |
854 } | |
855 | |
856 static void | |
857 cmd_random(const char* params) | |
858 { | |
859 uint8_t admux; | |
860 uint16_t num; | |
861 uint8_t buf[100]; | |
862 | |
863 int ret = sscanf_P(params, PSTR("%hhu %u"), | |
864 &admux, &num); | |
865 if (!ret) | |
866 { | |
867 printf_P(PSTR("Bad arguments\n")); | |
868 return; | |
869 } | |
870 uint32_t tries = 0; | |
871 printf_P(PSTR("output: ")); | |
872 for (int i = 0; i < num; i+= sizeof(buf)) | |
873 { | |
874 uint32_t t; | |
875 uint16_t nr = MIN(num-i, sizeof(buf)); | |
876 adc_random(admux, buf, nr, &t); | |
877 printhex(buf, nr, stdout); | |
878 tries += t; | |
879 } | |
880 putchar('\n'); | |
881 printf_P(PSTR("%ld tries\n"), tries); | |
882 } | |
883 | |
884 | |
688 | 885 |
689 static void | 886 static void |
690 read_handler() | 887 read_handler() |
691 { | 888 { |
692 #define LOCAL_PSTR(x) const static char x ## _str[] PROGMEM = #x; | 889 #define LOCAL_PSTR(x) const static char x ## _str[] PROGMEM = #x; |
701 LOCAL_PSTR(vcc); | 898 LOCAL_PSTR(vcc); |
702 LOCAL_PSTR(reset); | 899 LOCAL_PSTR(reset); |
703 LOCAL_PSTR(newboot); | 900 LOCAL_PSTR(newboot); |
704 LOCAL_PSTR(oldboot); | 901 LOCAL_PSTR(oldboot); |
705 LOCAL_PSTR(status); | 902 LOCAL_PSTR(status); |
903 LOCAL_PSTR(random); | |
904 LOCAL_PSTR(prog); | |
706 LOCAL_HELP(set_params, "<long_limit> <short_limit> <newboot_limit>"); | 905 LOCAL_HELP(set_params, "<long_limit> <short_limit> <newboot_limit>"); |
707 LOCAL_HELP(set_key, "20_byte_hex>"); | 906 LOCAL_HELP(set_key, "20_byte_hex>"); |
708 LOCAL_HELP(oneshot, "<timeout>"); | 907 LOCAL_HELP(oneshot, "<timeout>"); |
908 LOCAL_HELP(prog, "<password>"); | |
909 LOCAL_HELP(random, "<admux> <nbytes>"); | |
709 LOCAL_HELP(hmac, "<key_index> <20_byte_hex_data>"); | 910 LOCAL_HELP(hmac, "<key_index> <20_byte_hex_data>"); |
710 LOCAL_HELP(decrypt, "<key_index> <20_byte_hmac|16_byte_aes_block>"); | 911 LOCAL_HELP(decrypt, "<key_index> <20_byte_hmac|16_byte_aes_block>"); |
711 | 912 |
712 static const struct handler { | 913 static const struct handler { |
713 PGM_P name; | 914 PGM_P name; |
723 {status_str, cmd_status, NULL}, | 924 {status_str, cmd_status, NULL}, |
724 {hmac_str, cmd_hmac, hmac_help}, | 925 {hmac_str, cmd_hmac, hmac_help}, |
725 {decrypt_str, cmd_decrypt, decrypt_help}, | 926 {decrypt_str, cmd_decrypt, decrypt_help}, |
726 {set_params_str, cmd_set_params, set_params_help}, | 927 {set_params_str, cmd_set_params, set_params_help}, |
727 {set_key_str, cmd_set_avr_key, set_key_help}, | 928 {set_key_str, cmd_set_avr_key, set_key_help}, |
929 {random_str, cmd_random, random_help}, | |
728 {vcc_str, cmd_vcc, NULL}, | 930 {vcc_str, cmd_vcc, NULL}, |
729 {reset_str, cmd_reset, NULL}, | 931 {reset_str, cmd_reset, NULL}, |
932 {prog_str, cmd_prog, prog_help}, | |
730 }; | 933 }; |
731 | 934 |
732 if (readbuf[0] == '\0') | 935 if (readbuf[0] == '\0') |
733 { | 936 { |
734 return; | 937 return; |
880 set_sleep_mode(SLEEP_MODE_IDLE); | 1083 set_sleep_mode(SLEEP_MODE_IDLE); |
881 sleep_mode(); | 1084 sleep_mode(); |
882 } | 1085 } |
883 | 1086 |
884 static void | 1087 static void |
885 adc_generic(uint8_t admux, uint8_t *ret_num, uint16_t *ret_sum) | |
886 { | |
887 PRR &= ~_BV(PRADC); | |
888 | |
889 // /16 prescaler | |
890 ADCSRA = _BV(ADEN) | _BV(ADPS2); | |
891 | |
892 // set to measure 1.1 reference | |
893 ADMUX = admux; | |
894 | |
895 // delay after setting reference etc, allow settling | |
896 long_delay(300); | |
897 // average a number of samples | |
898 uint16_t sum = 0; | |
899 uint8_t num = 0; | |
900 for (uint8_t n = 0; n < 20; n++) | |
901 { | |
902 ADCSRA |= _BV(ADSC); | |
903 loop_until_bit_is_clear(ADCSRA, ADSC); | |
904 | |
905 uint8_t low_11 = ADCL; | |
906 uint8_t high_11 = ADCH; | |
907 uint16_t val = low_11 + (high_11 << 8); | |
908 | |
909 if (n >= 4) | |
910 { | |
911 sum += val; | |
912 num++; | |
913 } | |
914 } | |
915 ADCSRA = 0; | |
916 PRR |= _BV(PRADC); | |
917 | |
918 *ret_num = num; | |
919 *ret_sum = sum; | |
920 } | |
921 | |
922 static uint16_t | |
923 adc_vcc() | |
924 { | |
925 const uint8_t mux = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); | |
926 uint16_t sum; | |
927 uint8_t num; | |
928 | |
929 adc_generic(mux, &num, &sum); | |
930 | |
931 //float res_volts = 1.1 * 1024 * num / sum; | |
932 //return 1000 * res_volts; | |
933 return ((uint32_t)1100*1024*num) / sum; | |
934 } | |
935 | |
936 #define SCALER_5V 2 | |
937 | |
938 static uint16_t | |
939 adc_5v(uint16_t vcc) | |
940 { | |
941 // set to measure ADC4 against AVCC | |
942 const uint8_t mux = _BV(REFS0) | _BV(MUX2); | |
943 uint16_t sum; | |
944 uint8_t num; | |
945 | |
946 adc_generic(mux, &num, &sum); | |
947 | |
948 return ((uint32_t)vcc*sum*SCALER_5V/(num*1024)); | |
949 } | |
950 | |
951 static uint16_t | |
952 adc_temp() | |
953 { | |
954 // set to measure temperature against 1.1v reference. | |
955 const uint8_t mux = _BV(REFS0) | _BV(REFS1) | _BV(MUX3); | |
956 uint16_t sum; | |
957 uint8_t num; | |
958 | |
959 adc_generic(mux, &num, &sum); | |
960 | |
961 // return the voltage | |
962 | |
963 return ((uint32_t)1100*sum) / (num*1024); | |
964 } | |
965 | |
966 static void | |
967 reboot_pi() | 1088 reboot_pi() |
968 { | 1089 { |
969 printf_P(PSTR("Real reboot now\n")); | 1090 printf_P(PSTR("Real reboot now\n")); |
970 // pull it low for 200ms | 1091 // pull it low for 200ms |
971 PORT_PI_RESET &= ~_BV(PIN_PI_RESET); | 1092 PORT_PI_RESET &= ~_BV(PIN_PI_RESET); |
972 DDR_PI_RESET |= _BV(PIN_PI_RESET); | 1093 DDR_PI_RESET |= _BV(PIN_PI_RESET); |
973 _delay_ms(200); | 1094 _delay_ms(200); |
974 | 1095 |
975 PORT_PI_WARNING &= ~_BV(PIN_PI_WARNING); | 1096 PORT_PI_WARNING &= ~_BV(PIN_PI_WARNING); |
976 DDR_PI_RESET &= ~_BV(PIN_PI_RESET); | 1097 DDR_PI_RESET &= ~_BV(PIN_PI_RESET); |
977 | |
978 hmac_file("stuff"); | |
979 } | 1098 } |
980 | 1099 |
981 static void | 1100 static void |
982 wait_reboot_pi() | 1101 wait_reboot_pi() |
983 { | 1102 { |