# HG changeset patch # User Matt Johnston # Date 1370273353 -28800 # Node ID 0a6cbbb8c2b7b1521c8262ab0844010004c83810 # Parent e23c1b6f6080fc9b3a1d2ef3ea9062b3189903f1 mostly there diff -r e23c1b6f6080 -r 0a6cbbb8c2b7 Makefile --- a/Makefile Mon Jun 03 19:17:36 2013 +0800 +++ b/Makefile Mon Jun 03 23:29:13 2013 +0800 @@ -25,7 +25,7 @@ SOURCE_1WIRE = onewire.c simple_ds18b20.c crc8.c SOURCE_CRYPTO = hmac-sha1.c sha1-asm.S SOURCE = main.c -SOURCE += (SOURCE_CRYPTO) +SOURCE += $(SOURCE_CRYPTO) LIBS = -lm # default but 2mhz @@ -58,7 +58,7 @@ AVRDUDE = avrdude $(PROGRAMMER) #COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -g -std=c99 -mcall-prologues -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--relax -fwhole-program -Wl,-u,vfprintf -lprintf_flt -lm -COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -g -std=c99 -Wl,-u,vfprintf -lprintf_flt -lm +COMPILE = /usr/local/CrossPack-AVR/bin/avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -g -std=c99 -Wl,-u,vfprintf -lprintf_flt -lm # symbolic targets: all: main.hex diff -r e23c1b6f6080 -r 0a6cbbb8c2b7 main.c --- a/main.c Mon Jun 03 19:17:36 2013 +0800 +++ b/main.c Mon Jun 03 23:29:13 2013 +0800 @@ -13,6 +13,8 @@ #include #include +#include "hmac-sha1.h" + //#include "simple_ds18b20.h" //#include "onewire.h" @@ -23,45 +25,28 @@ // to be a multiple. #define TICK 1 -// we have 1024 prescaler, 32768 crystal. -#define SLEEP_COMPARE (32*TICK-1) - +#define SLEEP_COMPARE (2000000/64) // == 31250 exactly +#define NKEYS 6 #define KEYLEN 20 -#define VALUE_NOSENSOR 0x07D0 // 125 degrees -#define VALUE_BROKEN 0x07D1 // 125.0625 - -#define OVERSHOOT_MAX_DIV 1800.0 // 30 mins -#define WORT_INVALID_TIME 900 // 15 mins -// fridge min/max are only used if the wort sensor is invalid -#define FRIDGE_AIR_MIN_RANGE 40 // 4º -#define FRIDGE_AIR_MAX_RANGE 40 // 4º - #define BAUD 19200 #define UBRR ((F_CPU)/8/(BAUD)-1) +// XXX +#define PORT_PI_BOOT PORTD +#define DDR_PI_BOOT DDRD +#define PIN_PI_BOOT PD7 + +// XXX +#define PORT_PI_RESET PORTD +#define DDR_PI_RESET DDRD +#define PIN_PI_RESET PD6 + + #define PORT_LED PORTC #define DDR_LED DDRC #define PIN_LED PC4 -#define PORT_SHDN PORTD -#define DDR_SHDN DDRD -#define PIN_SHDN PD7 - -#define PORT_FRIDGE PORTD -#define DDR_FRIDGE DDRD -#define PIN_FRIDGE PD6 - -// total amount of 16bit values available for measurements. -// adjust emperically, be sure to allow enough stack space too -#define TOTAL_MEASUREMENTS 800 - -// each sensor slot uses 8 bytes -#define MAX_SENSORS 6 - -// fixed at 8, have a shorter name -#define ID_LEN OW_ROMCODE_SIZE - // #define HAVE_UART_ECHO // stores a value of clock_epoch combined with the remainder of TCNT2, @@ -75,13 +60,12 @@ // eeprom-settable parameters, default values defined here. // all timeouts should be a multiple of TICK -static uint32_t watchdog_long_limit = 60*60*24; +static uint32_t watchdog_long_limit = (60L*60*24); static uint32_t watchdog_short_limit = 0; static uint32_t newboot_limit = 60*10; // avr proves itself -static uint8_t avr_keys[NKEYS][KEYLEN] = {0}; - +static uint8_t avr_keys[NKEYS][KEYLEN] = {{0}}; // ---- Atomic guards required accessing these variables // clock_epoch in seconds @@ -89,14 +73,18 @@ // watchdog counts up static uint32_t watchdog_long_count; static uint32_t watchdog_short_count; -// newboot counts down - it's a one-shot +// newboot counts down static uint32_t newboot_count; +// oneshot counts down +static uint32_t oneshot_count; + // ---- End atomic guards required // boolean flags static uint8_t watchdog_long_hit; static uint8_t watchdog_short_hit; static uint8_t newboot_hit; +static uint8_t oneshot_hit; static uint8_t readpos; static char readbuf[50]; @@ -106,6 +94,7 @@ static void long_delay(int ms); static void blink(); static uint16_t adc_vcc(); +static void set_pi_boot_normal(uint8_t normal); static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE); @@ -123,13 +112,11 @@ uint32_t watchdog_short_limit; uint32_t newboot_limit; - uint8_t avr_key[NKEYS][KEYLEN]; + uint8_t avr_keys[NKEYS][KEYLEN]; uint16_t magic; }; -static void deep_sleep(); - // Very first setup static void setup_chip() @@ -147,7 +134,6 @@ // Set clock to 2mhz CLKPR = _BV(CLKPCE); - // divide by 4 CLKPR = _BV(CLKPS1); // enable pullups @@ -188,20 +174,20 @@ static void setup_tick_counter() { + // set up counter1 + // set up counter2. // COM21 COM20 Set OC2 on Compare Match (p116) // WGM21 Clear counter on compare //TCCR2A = _BV(COM2A1) | _BV(COM2A0) | _BV(WGM21); // toggle on match - TCCR2A = _BV(COM2A0); - // CS22 CS21 CS20 clk/1024 - TCCR2B = _BV(CS22) | _BV(CS21) | _BV(CS20); - // set async mode - ASSR |= _BV(AS2); - TCNT2 = 0; - OCR2A = SLEEP_COMPARE; + TCCR1A = _BV(COM1A0); + // systemclock/1024 + TCCR1B = _BV(CS12) | _BV(CS10); + TCNT1 = 0; + OCR1A = SLEEP_COMPARE; // interrupt - TIMSK2 = _BV(OCIE2A); + TIMSK1 = _BV(OCIE1A); } static void @@ -219,7 +205,6 @@ UCSR0B = _BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0); //8N1 UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); - uart_enabled = 1; } static void @@ -227,7 +212,6 @@ { // Turn off interrupts and disable tx/rx UCSR0B = 0; - uart_enabled = 0; // Power reduction register PRR |= _BV(PRUSART0); @@ -236,10 +220,6 @@ int uart_putchar(char c, FILE *stream) { - if (!uart_enabled) - { - return EOF; - } // XXX could perhaps sleep in the loop for power. if (c == '\n') { @@ -248,18 +228,10 @@ } loop_until_bit_is_set(UCSR0A, UDRE0); UDR0 = c; - if (stream == crc_stdout) - { - crc_out = _crc_ccitt_update(crc_out, c); - } if (c == '\r') { loop_until_bit_is_set(UCSR0A, UDRE0); UDR0 = '\n'; - if (stream == crc_stdout) - { - crc_out = _crc_ccitt_update(crc_out, '\n'); - } } return (unsigned char)c; } @@ -274,26 +246,39 @@ while(1); // wait for watchdog to reset processor } +static void +cmd_newboot() +{ + set_pi_boot_normal(1); + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + newboot_count = newboot_limit; + } + printf_P(PSTR("newboot for %d secs"), newboot_limit); +} + static void cmd_get_params() { - uint32_t cur_watchdog_long, cur_watchdog_short, cur_newboot; + uint32_t cur_watchdog_long, cur_watchdog_short, cur_newboot, cur_oneshot; ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { - cur_watchdog_long = watchdot_long_count; - cur_watchdog_short = watchdot_short_count; - cur_newboot = newboot_limit_count; + cur_watchdog_long = watchdog_long_count; + cur_watchdog_short = watchdog_short_count; + cur_newboot = newboot_count; + cur_oneshot = oneshot_count; } - printf_P(PSTR("limit (count) : watchdog_long %lu (%lu) watchdog_short %lu (%lu) newboot %lu (%lu)\n"), + printf_P(PSTR("limit (count) : watchdog_long %lu (%lu) watchdog_short %lu (%lu) newboot %lu (%lu) oneshot (%lu)\n"), watchdog_long_limit, - watchdog_long_count, + cur_watchdog_long, watchdog_short_limit, - watchdog_short_count, + cur_watchdog_short, newboot_limit, - newboot_count); + cur_newboot, + cur_oneshot); } static void @@ -346,20 +331,110 @@ return 0; } +static void +printhex_nibble(const unsigned char b, FILE *stream) +{ + unsigned char c = b & 0x0f; + if ( c > 9 ) { + c += 'A'-10; + } + else { + c += '0'; + } + fputc(c, stream); +} + +void +printhex_byte(const unsigned char b, FILE *stream) +{ + printhex_nibble( b >> 4, stream); + printhex_nibble( b, stream); +} + +void +printhex(uint8_t *id, uint8_t n, FILE *stream) +{ + for (uint8_t i = 0; i < n; i++) + { + if (i > 0) + { + fputc(' ', stream); + } + printhex_byte(id[i], stream); + } +} + +static int8_t +parse_key(const char *params, uint8_t *key_index, uint8_t bytes[KEYLEN]) +{ + // "N HEXKEY" + if (strlen(params) != KEYLEN*2+2) { + printf_P(PSTR("Wrong length key\n")); + return -1; + } + + if (params[1] != ' ') + { + printf_P(PSTR("Missing space\n")); + return -1; + } + + *key_index = from_hex(params[0]); + if (*key_index >= NKEYS) + { + printf_P(PSTR("Bad key index %d, max %d\n"), *key_index, NKEYS); + return -1; + } + + for (int i = 0, p = 0; i < KEYLEN; i++, p += 2) + { + bytes[i] = (from_hex(params[p+2]) << 4) | from_hex(params[p+3]); + } + return 0; +} + static void cmd_set_avr_key(const char *params) { - // "N HEXKEY" - if (strlen(params)) != KEYLEN*2+2) { - printf_P(PSTR("Wrong length key\n")); + uint8_t new_key[KEYLEN]; + uint8_t key_index; + if (parse_key(params, &key_index, new_key) != 0) + { return; } + memcpy(avr_keys[key_index], new_key, sizeof(new_key)); + eeprom_write(avr_keys, avr_keys); +} + +static void +cmd_hmac(const char *params) +{ + uint8_t data[KEYLEN]; + uint8_t key_index; + if (parse_key(params, &key_index, data) != 0) + { + printf_P(PSTR("FAIL: Bad input\n")); + } - uint8_t new_key[KEYLEN]; - for (int i = 0, p = 0; i < KEYLEN; i++, p += 2) + hmac_sha1_ctx_t ctx; + hmac_sha1_init(&ctx, avr_keys[key_index], KEYLEN); + hmac_sha1_lastBlock(&ctx, data, KEYLEN); + hmac_sha1_final(data, &ctx); + + printf_P(PSTR("HMAC: ")); + printhex(data, KEYLEN, stdout); + fputc('\n', stdout); +} + +static void +cmd_oneshot_reboot(const char *params) +{ + uint32_t new_delay = strtoul(params, NULL, 10); + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { - new_key[i] = (fromhex(params[p]) << 4) | fromhex(params[p+1]); + oneshot_count = new_delay; } + printf_P(PSTR("oneshot delay %lu\n"), new_delay); } static void @@ -371,63 +446,23 @@ { eeprom_read(watchdog_long_limit, watchdog_long_limit); eeprom_read(watchdog_short_limit, watchdog_short_limit); - eeprom_read(netboot_limit); - eeprom_read(avr_key); + eeprom_read(newboot_limit, newboot_limit); } + + eeprom_read(avr_keys, avr_keys); } -// returns true if eeprom was written -static bool -set_initial_eeprom() +static void +cmd_vcc() { - uint16_t magic; - eeprom_read(magic, magic); - if (magic == EXPECT_MAGIC) - { - return false; - } - - ATOMIC_BLOCK(ATOMIC_RESTORESTATE) - { - eeprom_write(measure_wake, measure_wake); - eeprom_write(comms_wake, comms_wake); - eeprom_write(wake_secs, wake_secs); - eeprom_write(fridge_setpoint, fridge_setpoint); - eeprom_write(fridge_difference, fridge_difference); - eeprom_write(fridge_delay, fridge_delay); - eeprom_write(overshoot_delay, overshoot_delay); - eeprom_write(overshoot_factor, overshoot_factor); - magic = EXPECT_MAGIC; - eeprom_write(magic, magic); - } - - return true; + uint16_t vcc = adc_vcc(); + printf_P("vcc: %u mV\n", vcc); } static void read_handler() { - if (strcmp_P(readbuf, PSTR("fetch")) == 0) - { - cmd_fetch(); - } - else if (strcmp_P(readbuf, PSTR("clear")) == 0) - { - cmd_clear(); - } - else if (strcmp_P(readbuf, PSTR("btoff")) == 0) - { - cmd_btoff(); - } - else if (strcmp_P(readbuf, PSTR("measure")) == 0) - { - cmd_measure(); - } - else if (strcmp_P(readbuf, PSTR("sensors")) == 0) - { - cmd_sensors(); - } - else if (strcmp_P(readbuf, PSTR("get_params")) == 0) + if (strcmp_P(readbuf, PSTR("get_params")) == 0) { cmd_get_params(); } @@ -435,29 +470,21 @@ { cmd_set_params(&readbuf[11]); } - else if (strcmp_P(readbuf, PSTR("awake")) == 0) - { - cmd_awake(); - } - else if (strncmp_P(readbuf, PSTR("fridge_setpoint "), 16) == 0) + else if (strncmp_P(readbuf, PSTR("set_key "), 8) == 0) { - cmd_set_fridge_setpoint(&readbuf[16]); + cmd_set_avr_key(&readbuf[8]); } - else if (strncmp_P(readbuf, PSTR("fridge_diff "), 12) == 0) + else if (strncmp_P(readbuf, PSTR("oneshot "), 8) == 0) { - cmd_set_fridge_difference(&readbuf[12]); + cmd_oneshot_reboot(&readbuf[8]); } - else if (strncmp_P(readbuf, PSTR("fridge_delay "), 13) == 0) - { - cmd_set_fridge_delay(&readbuf[13]); - } - else if (strncmp_P(readbuf, PSTR("overshoot_delay "), 16) == 0) + else if (strncmp_P(readbuf, PSTR("hmac "), 5) == 0) { - cmd_set_overshoot_delay(&readbuf[16]); + cmd_hmac(&readbuf[5]); } - else if (strncmp_P(readbuf, PSTR("overshoot_factor "), 17) == 0) + else if (strcmp_P(readbuf, PSTR("vcc")) == 0) { - cmd_set_overshoot_factor(&readbuf[17]); + cmd_vcc(); } else if (strcmp_P(readbuf, PSTR("reset")) == 0) { @@ -471,7 +498,6 @@ ISR(INT0_vect) { - button_pressed = 1; blink(); _delay_ms(100); blink(); @@ -504,15 +530,15 @@ } } -ISR(TIMER2_COMPA_vect) +ISR(TIMER1_COMPA_vect) { - TCNT2 = 0; + TCNT1 = 0; clock_epoch += TICK; // watchdogs count up, continuous if (watchdog_long_limit > 0) { - watchdog_count += TICK; + watchdog_long_count += TICK; if (watchdog_long_count >= watchdog_long_limit) { watchdog_long_count = 0; @@ -521,7 +547,7 @@ } if (watchdog_short_limit > 0) { - watchdog_count += TICK; + watchdog_short_count += TICK; if (watchdog_short_count >= watchdog_short_limit) { watchdog_short_count = 0; @@ -529,27 +555,28 @@ } } - // newboot counts down, oneshot. + // newboot counts down if (newboot_count > 0) { - newboot_count--; - if (newboot_count == 0) + newboot_count-=TICK; + if (newboot_count <= 0) { newboot_hit = 1; + newboot_count = 0; } } -} + if (oneshot_count > 0) + { + oneshot_count-=TICK; + if (oneshot_count <= 0) + { + oneshot_hit = 1; + oneshot_count = 0; + } + } -static void -deep_sleep() -{ - // p119 of manual - OCR2A = SLEEP_COMPARE; - loop_until_bit_is_clear(ASSR, OCR2AUB); - set_sleep_mode(SLEEP_MODE_PWR_SAVE); - sleep_mode(); } static void @@ -596,6 +623,53 @@ } static void +reboot_pi() +{ + // pull it low for 30ms + PORT_PI_RESET &= ~_BV(PIN_PI_RESET); + DDR_PI_RESET |= _BV(PIN_PI_RESET); + _delay_ms(30); + DDR_PI_RESET &= ~_BV(PIN_PI_RESET); +} + +static void +set_pi_boot_normal(uint8_t normal) +{ + PORT_PI_BOOT &= ~_BV(PIN_PI_BOOT); + if (normal) + { + // tristate + DDR_PI_BOOT &= ~_BV(PIN_PI_BOOT); + } + else + { + // pull it low + DDR_PI_RESET |= _BV(PIN_PI_BOOT); + + } +} + +static void +check_flags() +{ + if (watchdog_long_hit + || watchdog_short_hit + || oneshot_hit) + { + reboot_pi(); + } + + if (newboot_hit) { + set_pi_boot_normal(0); + } + + watchdog_long_hit = 0; + watchdog_short_hit = 0; + newboot_hit = 0; + oneshot_hit = 0; +} + +static void do_comms() { // avoid receiving rubbish, perhaps @@ -606,6 +680,9 @@ while (1) { wdt_reset(); + + check_flags(); + if (have_cmd) { have_cmd = 0; @@ -653,6 +730,8 @@ printf(PSTR("Started.\n")); + set_pi_boot_normal(0); + load_params(); setup_tick_counter();