#ifndef F_CPU #define F_CPU 1000000UL /* 1 Mhz-Takt; hier richtigen Wert eintragen */ #endif #include "../misc/iofixes.h" #include "../firmware/spminterface.h" #include "usbasploader.h" // activate updaters full set of features #ifndef CONFIG_UPDATER_REDUCEWRITES #define CONFIG_UPDATER_REDUCEWRITES #endif #ifndef CONFIG_UPDATER_CLEANMEMCLEAR #define CONFIG_UPDATER_CLEANMEMCLEAR #endif #include #include #include #include #include #include #define updater_pagefillcode ((1<> 1); } #endif void temp_do_spm(const uint32_t flash_byteaddress, const uint8_t spmcrval, const uint16_t dataword) { __do_spm_Ex(flash_byteaddress, spmcrval, dataword, TEMP_SPM_ADDRESS >> 1); } // some important consistency checks //// //check if "NEW_BOOTLOADER_ADDRESS" is page-aligned #if (NEW_BOOTLOADER_ADDRESS % SPM_PAGESIZE != 0) #error "NEW_BOOTLOADER_ADDRESS" is not aligned to pages! #endif //check, if NEW_SPM_ADDRESS is an even address #if ((NEW_SPM_ADDRESS % 2) != 0) #error NEW_SPM_ADDRESS must be an even address, since it contains executable code! #endif //check, if TEMP_SPM somehow overlaps with old SPM #if (((TEMP_SPM_ADDRESS + TEMP_SPM_BLKSIZE + SPM_PAGESIZE) >= funcaddr___bootloader__do_spm) && (TEMP_SPM_ADDRESS <= (funcaddr___bootloader__do_spm + TEMP_SPM_BLKSIZE + SPM_PAGESIZE))) #error TEMP_SPM_ADDRESS overlaps "funcaddr___bootloader__do_spm"! #endif //check, if TEMP_SPM somehow overlaps with new SPM #if (((TEMP_SPM_ADDRESS + TEMP_SPM_BLKSIZE + SPM_PAGESIZE) >= NEW_SPM_ADDRESS) && (TEMP_SPM_ADDRESS <= (NEW_SPM_ADDRESS + TEMP_SPM_BLKSIZE + SPM_PAGESIZE))) #error TEMP_SPM_ADDRESS overlaps "NEW_SPM_ADDRESS"! #endif //check, if TEMP_SPM_ADDRESS is an even address #if ((TEMP_SPM_ADDRESS % 2) != 0) #error TEMP_SPM_ADDRESS must be an even address, since it contains executable code! #endif //check, if TEMP_SPM_ADDRESS fits into flash #if ((TEMP_SPM_PAGEADR + TEMP_SPM_BLKSIZE) > (FLASHEND+1)) #error TEMP_SPM_ADDRESS exceeds flashend! #endif //check if size too low #if (SIZEOF_new_firmware <= (TEMP_SPM_BLKSIZE + (NEW_SPM_ADDRESS - NEW_BOOTLOADER_ADDRESS))) #error empty firmware! #endif //check if size too high #if (SIZEOF_new_firmware > ((FLASHEND+1)-NEW_BOOTLOADER_ADDRESS)) #error firmware too big! firmware does not fit into flash memory! #endif // main code //// /* * in this case a near address */ typedef uint32_t mypgm_addr_t; typedef void (*mypgm_spminterface)(const uint32_t flash_byteaddress, const uint8_t spmcrval, const uint16_t dataword); #if FLASHEND > 65535 # define FULLCORRECTFLASHADDRESS(addr) (((mypgm_addr_t)(addr)) | (((mypgm_addr_t)FLASHADDRESS) & ((mypgm_addr_t)0xffff0000))) # define mymemcpy_PF mymemcpy_PF_far void *mymemcpy_PF_far (void *dest, mypgm_addr_t src, size_t n) { uint8_t *pagedata = (void*)dest; mypgm_addr_t pageaddr = src; size_t i; for (i=0;i> 1; uint16_t *pagedata = (void*)buffer; mypgm_addr_t pageaddr = byteaddress - (byteaddress % SPM_PAGESIZE); size_t i; for (i=0;i> 1; uint16_t *pagedata = (void*)buffer; mypgm_addr_t pageaddr_bakup = byteaddress - (byteaddress % SPM_PAGESIZE); mypgm_addr_t pageaddr = pageaddr_bakup; uint8_t changed=0, needs_erase=0; uint16_t deeword; size_t i; // just check, if page needs a rewrite or an erase... for (i=0;i 65535) deeword=pgm_read_word_far(pageaddr); #else deeword=pgm_read_word(pageaddr); #endif if (deeword != pagedata[i]) changed=1; /* * deeword = x * buffer = y * * 1 ? 1 ==> 1 * 1 ? 0 ==> 1 * 0 ? 1 ==> 0 * 0 ? 0 ==> 1 * * ==> /(/x * y) ==> x + /y */ deeword |= ~pagedata[i]; if ((~deeword) != 0) needs_erase=1; pageaddr+=2; } if (changed) { if (needs_erase) { //do a page-erase, ATTANTION: flash only can be erased a limited number of times ! spmfunc(pageaddr_bakup, updater_pageerasecode, 0); } // from now on, the page is assumed empty !! (hopefully our code is located somewhere else!) // now, fill the tempoary buffer // ATTANTION: see comment on "do_spm" ! pageaddr = pageaddr_bakup; for (i=0;i> 1; uint16_t *pagedata = (void*)buffer; mypgm_addr_t pageaddr_bakup = byteaddress - (byteaddress % SPM_PAGESIZE); mypgm_addr_t pageaddr = pageaddr_bakup; size_t i; //do a page-erase, ATTANTION: flash only can be erased a limited number of times ! spmfunc(pageaddr_bakup, updater_pageerasecode, 0); // from now on, the page is assumed empty !! (hopefully our code is located somewhere else!) // now, fill the tempoary buffer // ATTANTION: see comment on "do_spm" ! pageaddr = pageaddr_bakup; for (i=0;i 65535) crcval = update_crc_32(crcval, pgm_read_byte_far(FULLCORRECTFLASHADDRESS(&new_firmware[i]))); #else crcval = update_crc_32(crcval, pgm_read_byte(FULLCORRECTFLASHADDRESS(&new_firmware[i]))); #endif } crcval ^= D_32; // allow to change the firmware if (crcval == ((uint32_t)UPDATECRC32)) { #endif // check if firmware would change... buffer[0]=0; for (i=0;i 65535) a=pgm_read_word_far(FULLCORRECTFLASHADDRESS(&new_firmware[i])); b=pgm_read_word_far(NEW_BOOTLOADER_ADDRESS+i); #else a=pgm_read_word(FULLCORRECTFLASHADDRESS(&new_firmware[i])); b=pgm_read_word(NEW_BOOTLOADER_ADDRESS+i); #endif if (a!=b) { buffer[0]=1; break; } } // need to change the firmware... if (buffer[0]) { // A // copy the current "bootloader__do_spm" to tempoary position via std. "bootloader__do_spm" for (i=0;isizeof(buffer))?sizeof(buffer):(SIZEOF_new_firmware-i)); mypgm_WRITEpage(NEW_BOOTLOADER_ADDRESS+i, buffer, sizeof(buffer), temp_do_spm); if ((NEW_BOOTLOADER_ADDRESS+i) > (NEW_SPM_ADDRESS+TEMP_SPM_BLKSIZE)) break; } // C // continue writeing the new_firmware after "NEW_SPM_ADDRESS+TEMP_SPM_BLKSIZE" this time use the "new_do_spm" for (;isizeof(buffer))?sizeof(buffer):(SIZEOF_new_firmware-i)); mypgm_WRITEpage(NEW_BOOTLOADER_ADDRESS+i, buffer, sizeof(buffer), new_do_spm); } } #if defined(UPDATECRC32) } #endif return 0; }