static bool hex_load(const char *file, long firmsize, uint8_t *image) { FILE *f; char s[0x80]; f = fopen(file, "r"); if(f == NULL){ return false; } fseek(f, 0, SEEK_SET); struct record *t = ihex_new(); bool ret = true; while(fgets(s, 0x80, f) != NULL){ if(ihex_load(s, t) == false){ ret = false; break; } ihex_write(t, firmsize, image); } ihex_destory(t); return ret; }
/*--- MAIN -------------------------------------------------------------------*/ int main(void) { char temp_char; uint16_t loop = 1; uint8_t bootFlag = TRUE; cli(); /* the following code moves the interrupt vector pointer to the bootloader section. The problem is the compiler doesn't understand where to put the IV table. */ GICR = _BV(IVCE); GICR |= _BV(IVSEL); //move interruptvectors to the Boot sector /* The slow baud rate is required because of the intel hex parsing overhead. If I could figure out how to enable interrupts in the BLS (compiler issue) then a higher speed could be used by switching to an interrupt based UART ISR. The code could also be optimized. */ SerCom0Init(BAUD_2400); // NOTE, the baud rates are constants defined in // sercom.h. You need to adjust those constants // to fit your MCU speed // poll USART receive complete flag 64k times to catch the 'i' reliably // test if flash is empty (i.e. flash content is 0xff) if(pgm_read_byte_near(0x0000) != 0xFF) { bootFlag = FALSE; } do { if(bit_is_set( UCSRA, RXC)) if( UDR == 'i') { bootFlag = TRUE; PutString0("Boot V "); PutChar0(VER_HIGH_BYTE); PutChar0(VER_LOW_BYTE); PutString0("\r\n"); } } while(loop++); /* this main loop is the user 'menu'. */ while(bootFlag) { if( Hit0() ) // more necessary for UART code running interrupts { temp_char=GetChar0(); switch(temp_char) { case 'u': // download new program { /* erase the main flash excepting BLS */ buf_address = 0; while ( APP_END > buf_address ) { boot_page_erase(buf_address); // Perform page erase boot_spm_busy_wait(); // Wait until the memory is erased. buf_address += SPM_PAGESIZE; } buf_address = 0; /* load new program */ PutString0("READY"); if(( temp_char = ihex_load())) { PutString0("ERR "); PutInt0(temp_char); } else {( PutString0("OK") ); bootFlag = FALSE ; // Exit to run } } break; case 'x': //Exit upgrade { GICR = _BV(IVCE); GICR &= ~_BV(IVSEL); //move interruptvectors to the Application sector jump_to_app(); // Jump to application sector // wdt_enable(WDTO_15MS); // Enable Watchdog Timer to give reset } break; default: { PutString0("u - Upload or x - Execute\r\n"); } } // end switch } // end if( Hit0() ) } // end while(1) // Start to application GICR = _BV(IVCE); GICR &= ~_BV(IVSEL); //move interruptvectors to the Application sector jump_to_app(); // Jump to application sector return 0; }
/*--- MAIN -------------------------------------------------------------------*/ int main(void) { uint8_t temp_char,tmp; uint8_t bootFlag = TRUE; cli(); /* the following code moves the interrupt vector pointer to the bootloader section. The problem is the compiler doesn't understand where to put the IV table. */ GICR = _BV(IVCE); GICR = _BV(IVSEL); //move interruptvectors to the Boot sector ** WRITE 0 TO IVCE use = not | // Initial 7 Segments on E_io // Set direction of two switch to Input DDRB = 0xFF; // Output DDRC = 0x18; // P3, P4 for Control 7 segments Digits // Enable pull up resistor PORTC |= 0x24; /* The slow baud rate is required because of the intel hex parsing overhead. If I could figure out how to enable interrupts in the BLS (compiler issue) then a higher speed could be used by switching to an interrupt based UART ISR. The code could also be optimized. */ uart_init( UART_INTERRUPT,UART_8_N_1,UART_38400); // poll USART receive complete flag 64k times to catch the 'i' reliably // test if flash is empty (i.e. flash content is 0xff) if(pgm_read_byte_near(0x0000) != 0xFF) { bootFlag = FALSE; } // Enter boot mode by press b // while (!(tmp = uart_read())); // if (tmp == 'b') // bootFlag = TRUE; // Check SW for enter boot mode either press both SW at the same time tmp = PINC & (0x24); // PB0, PB3 port if (!tmp) // Press SW tmp = 0 bootFlag = TRUE; uart_write_str (VERSION); // Display b characters E_OUT_PORTA = 0x7C; // b E_OUT_PB1(0); E_OUT_PB2(1); /* this main loop is the user 'menu'. */ while(bootFlag) { if( (tmp = uart_read()) ) { switch(tmp) { case 'u': // download new program { /* erase the main flash excepting BLS */ buf_address = 0; while ( APP_END > buf_address ) { boot_page_erase(buf_address); // Perform page erase boot_spm_busy_wait(); // Wait until the memory is erased. buf_address += SPM_PAGESIZE; } buf_address = 0; /* load new program */ uart_write_str("READY \n"); if(( temp_char = ihex_load())) { uart_write_str("ERR "); uart_write_char(temp_char + '0' ); uart_write_char('\n'); } else { bootFlag = FALSE ; // Exit to run } } break; case 'x': //Exit upgrade { GICR = _BV(IVCE); GICR &= ~(_BV(IVSEL) | _BV(IVCE)); //move interruptvectors to the Application sector Write 0 to IVCE jump_to_app(); // Jump to application sector // wdt_enable(WDTO_15MS); // Enable Watchdog Timer to give reset } break; default: { uart_write_str(" u - Upload or x - Execute \n"); } } // end switch } } // end while(1) // Start to application GICR = _BV(IVCE); GICR &= ~(_BV(IVSEL) | _BV(IVCE)); //move interruptvectors to the Application sector Write 0 to IVCE jump_to_app(); // Jump to application sector return 0; }