/* Soil Sensor Bootloader * Main file. * Sensiplicity Systems * * Copyright 2015 * * Department of Botany and Plant Pathology * Center for Genome Research and Biocomputing * Oregon State University * Corvallis, OR 97331 * * This program is not free software; you can not redistribute it and/or * modify it at all. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include "bus.h" #include "light.h" #include "crc.h" #define F_CPU 2000000l #include //TODO #include /* Calling this "function" jumps to the main program. */ void (*start_firmware)(void) = 0x0000; /* Move interrupt vector table to bootloader space. */ void bl_interrupts(void){ MCUCR = _BV(IVCE); MCUCR = _BV(IVSEL); } /* Move interrupt vector to main program space. */ void fw_interrupts(void){ MCUCR = _BV(IVCE); MCUCR = 0; } /* Compute an overall CRC of the whole main firmware flash space. * A CRC is first computed for each set of six flash pages, then an * overall CRC is computed from those. */ uint16_t calc_flash_crc(void){ uint8_t sixpage_buf[192]; /* Due to the AVR's Harvard architecture, each set of six pages * must be loaded from Flash into RAM for the CRC routine of * operate on them. */ uint16_t sixpage_crcs[32]; /* CRCs of each set of six pages. */ for(uint8_t i=0; i<32; i++){ for(uint8_t b=0; b<192; b++){ sixpage_buf[b] = pgm_read_byte_near((i * 192) + b); } if(31 == i){ /* Exclude the last two bytes of the last page, * as they contain the overall CRC. */ sixpage_crcs[i] = calc_crc(sixpage_buf, 190); } else { sixpage_crcs[i] = calc_crc(sixpage_buf, 192); } } return calc_crc((uint8_t *) sixpage_crcs, 64); } int main(void){ //TODO: For maximum robustness, set lock bits to prevent the //bootloader from being modified. /* Set system clock to 16MHz/8 = 2MHz */ CLKPR = _BV(CLKPCE); CLKPR = _BV(CLKPS1) | _BV(CLKPS0); bl_interrupts(); init_bus(); init_led(); set_led(LED_GREEN); uint16_t overall_crc = calc_flash_crc(); uint16_t stored_crc = pgm_read_word_near(6142); if(stored_crc != overall_crc){ ProgrammingMode = 1; set_led(LED_RED); } _delay_ms(500); if(!ProgrammingMode){ /* No request to enter programming mode, start the main firmware. */ cli(); set_led(LED_OFF); fw_interrupts(); start_firmware(); } else { /* Programming in progress. Loop until rebooted by bus module. */ while(1); } return 0; }