Mercurial > pihelp
changeset 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 | 320c8cc7df5a |
files | Makefile main.c |
diffstat | 2 files changed, 213 insertions(+), 94 deletions(-) [+] |
line wrap: on
line diff
--- a/Makefile Wed Jun 26 22:00:08 2013 +0800 +++ b/Makefile Wed Jun 26 23:12:37 2013 +0800 @@ -19,7 +19,7 @@ DEVICE = atmega328p PROGDEVICE = atmega328p -CLOCK = 4915200L +CLOCK = 11059200 PROGRAMMER = #-c stk500v2 -P avrdoper PROGRAMMER = -c stk500 -P ~/dev/stk500 -p $(PROGDEVICE) -B 2 SOURCE_1WIRE = onewire.c simple_ds18b20.c crc8.c
--- a/main.c Wed Jun 26 22:00:08 2013 +0800 +++ b/main.c Wed Jun 26 23:12:37 2013 +0800 @@ -41,7 +41,7 @@ #define AESLEN 16 #define KEYLEN HMACLEN -#define BAUD 38400 +#define BAUD 115200 #define UBRR ((F_CPU)/(16*(BAUD))-1) #define PORT_PI_BOOT PORTD @@ -100,6 +100,8 @@ static uint32_t oneshot_count; // countdown after the warning. static uint8_t reboot_count; +// set by adc completion interrupt +static uint8_t adc_done; // ---- End atomic guards required @@ -561,8 +563,8 @@ } uint8_t tmpbuf[256]; - //aesInit(avr_keys[key_index], tmpbuf); - //aesDecrypt(&indata[HMACLEN], NULL); + aesInit(avr_keys[key_index], tmpbuf); + aesDecrypt(&indata[HMACLEN], NULL); printf_P(PSTR("DECRYPTED: ")); printhex(output, AESLEN, stdout); @@ -635,21 +637,19 @@ { uint16_t vcc = adc_vcc(); uint16_t v5 = adc_5v(vcc); - uint16_t r = adc_random(); uint16_t temp = adc_temp(); // roughly? uint16_t temp_deg = temp - 290; printf_P(PSTR("vcc: %u mV\n" "5v: %u mV\n" "temp: %u mV (%dÂșC)\n" - "random: %u\n" ), - vcc, v5, temp, temp_deg, r); + vcc, v5, temp, temp_deg); } -void(*bootloader)() __attribute__ ((noreturn)) = (void*)0x7e00; -#if 0 +void(*bootloader)() __attribute__ ((noreturn)) = (void*)0x7800; + #ifndef PROG_PASSWORD #define PROG_PASSWORD "Y2vvjxO5" #endif @@ -684,7 +684,204 @@ bootloader(); } -#endif + + +static void +adc_sleep() +{ + set_sleep_mode(SLEEP_MODE_IDLE); + sleep_mode(); +} + +#define BITSET(v, n) (((v) >> (n)) & 1) + +static inline uint8_t +popcnt(uint8_t v) +{ + return BITSET(v, 0) + + BITSET(v, 1) + + BITSET(v, 2) + + BITSET(v, 3) + + BITSET(v, 4) + + BITSET(v, 5) + + BITSET(v, 6) + + BITSET(v, 7); +} + +static uint8_t +adc_bit() +{ + ADCSRA |= _BV(ADSC); + loop_until_bit_is_clear(ADCSRA, ADSC); + uint8_t low = ADCL; + uint8_t high = ADCH; + return (popcnt(low)&1) ^ (popcnt(high)&1); +} + +static void +adc_random(uint8_t admux, + uint8_t *out, uint16_t num, uint32_t *tries) +{ + uint8_t ret = 0; + uint8_t count = 0; + + PRR &= ~_BV(PRADC); + // /16 prescaler for 691mhz, no interrupt + ADCSRA = _BV(ADEN) | _BV(ADPS2); + + *tries = 0; + for (int i = 0; i < num; i++) + { + while (count <= 7) + { + (*tries)++; + + // Von Neumann extractor + uint8_t one = adc_bit(); + uint8_t two = adc_bit(); + if (one == two) + { + continue; + } + ret |= one << count; + count++; + } + out[i] = ret; + } + ADCSRA = 0; + PRR |= _BV(PRADC); +} + +ISR(ADC_vect) +{ + adc_done = 1; +} + +static void +adc_generic(uint8_t admux, uint8_t *ret_num, uint16_t *ret_sum) +{ + PRR &= ~_BV(PRADC); + + // /64 prescaler, interrupt + ADCSRA = _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADIE); + + // set to measure 1.1 reference + ADMUX = admux; + + // delay after setting reference etc, allow settling + long_delay(300); + // average a number of samples + uint16_t sum = 0; + uint8_t num = 0; + for (uint8_t n = 0; n < 20; n++) + { + while (1) + { + adc_done = 0; + ADCSRA |= _BV(ADSC); + adc_sleep(); + + uint8_t done; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + done = adc_done; + } + if (done) + { + break; + } + } + + uint8_t low_11 = ADCL; + uint8_t high_11 = ADCH; + uint16_t val = low_11 + (high_11 << 8); + + if (n >= 4) + { + sum += val; + num++; + } + } + ADCSRA = 0; + PRR |= _BV(PRADC); + + *ret_num = num; + *ret_sum = sum; +} + +static uint16_t +adc_vcc() +{ + const uint8_t mux = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); + uint16_t sum; + uint8_t num; + + adc_generic(mux, &num, &sum); + + //float res_volts = 1.1 * 1024 * num / sum; + //return 1000 * res_volts; + return ((uint32_t)1100*1024*num) / sum; +} + +#define SCALER_5V 2 + +static uint16_t +adc_5v(uint16_t vcc) +{ + // set to measure ADC4 against AVCC + const uint8_t mux = _BV(REFS0) | _BV(MUX2); + uint16_t sum; + uint8_t num; + + adc_generic(mux, &num, &sum); + + return ((uint32_t)vcc*sum*SCALER_5V/(num*1024)); +} + +static uint16_t +adc_temp() +{ + // set to measure temperature against 1.1v reference. + const uint8_t mux = _BV(REFS0) | _BV(REFS1) | _BV(MUX3); + uint16_t sum; + uint8_t num; + + adc_generic(mux, &num, &sum); + + // return the voltage + + return ((uint32_t)1100*sum) / (num*1024); +} + +static void +cmd_random(const char* params) +{ + uint8_t admux; + uint16_t num; + uint8_t buf[100]; + + int ret = sscanf_P(params, PSTR("%hhu %u"), + &admux, &num); + if (!ret) + { + printf_P(PSTR("Bad arguments\n")); + return; + } + uint32_t tries = 0; + printf_P(PSTR("output: ")); + for (int i = 0; i < num; i+= sizeof(buf)) + { + uint32_t t; + uint16_t nr = MIN(num-i, sizeof(buf)); + adc_random(admux, buf, nr, &t); + printhex(buf, nr, stdout); + tries += t; + } + putchar('\n'); + printf_P(PSTR("%ld tries\n"), tries); +} + + static void read_handler() @@ -703,9 +900,13 @@ LOCAL_PSTR(newboot); LOCAL_PSTR(oldboot); LOCAL_PSTR(status); + LOCAL_PSTR(random); + LOCAL_PSTR(prog); LOCAL_HELP(set_params, "<long_limit> <short_limit> <newboot_limit>"); LOCAL_HELP(set_key, "20_byte_hex>"); LOCAL_HELP(oneshot, "<timeout>"); + LOCAL_HELP(prog, "<password>"); + LOCAL_HELP(random, "<admux> <nbytes>"); LOCAL_HELP(hmac, "<key_index> <20_byte_hex_data>"); LOCAL_HELP(decrypt, "<key_index> <20_byte_hmac|16_byte_aes_block>"); @@ -725,8 +926,10 @@ {decrypt_str, cmd_decrypt, decrypt_help}, {set_params_str, cmd_set_params, set_params_help}, {set_key_str, cmd_set_avr_key, set_key_help}, + {random_str, cmd_random, random_help}, {vcc_str, cmd_vcc, NULL}, {reset_str, cmd_reset, NULL}, + {prog_str, cmd_prog, prog_help}, }; if (readbuf[0] == '\0') @@ -882,88 +1085,6 @@ } static void -adc_generic(uint8_t admux, uint8_t *ret_num, uint16_t *ret_sum) -{ - PRR &= ~_BV(PRADC); - - // /16 prescaler - ADCSRA = _BV(ADEN) | _BV(ADPS2); - - // set to measure 1.1 reference - ADMUX = admux; - - // delay after setting reference etc, allow settling - long_delay(300); - // average a number of samples - uint16_t sum = 0; - uint8_t num = 0; - for (uint8_t n = 0; n < 20; n++) - { - ADCSRA |= _BV(ADSC); - loop_until_bit_is_clear(ADCSRA, ADSC); - - uint8_t low_11 = ADCL; - uint8_t high_11 = ADCH; - uint16_t val = low_11 + (high_11 << 8); - - if (n >= 4) - { - sum += val; - num++; - }