X-Git-Url: http://git.linex4red.de/pub/USBaspLoader.git/blobdiff_plain/fa0b51823454caae26a476ec1e156a73377b4546..5b0272d9af73a164da192d796fc33ec736b93f0a:/updater/updater.c diff --git a/updater/updater.c b/updater/updater.c new file mode 100644 index 0000000..6b9cde3 --- /dev/null +++ b/updater/updater.c @@ -0,0 +1,317 @@ +#ifndef F_CPU + #define F_CPU 1000000UL /* 1 Mhz-Takt; hier richtigen Wert eintragen */ +#endif + +// 1) Test the "changed" - feature by debugging a LED-PIN to high (PB0?) +// 2) Test the "needs_erase" - feature by debugging a LED-PIN to high (PB1?) +// #define mypgmdebug 1 + +#include "../firmware/spminterface.h" +#include "firmware.h" + +#include +#include +#include + +#include + +#include + +#include +#include + + + +// helpful definitions and makros //// + +#ifndef NEW_BOOTLOADER_ADDRESS + #error "where should the new bootloader be positioned?" +#endif + + + +#if (NEW_BOOTLOADER_ADDRESS != (funcaddr___bootloader__do_spm-(funcaddr___bootloader__do_spm % SPM_PAGESIZE))) + #warning the new bootloader seems to be located elsewhere, than the current one! +#endif + +#ifndef NEW_SPM_ADDRESS + #warning I do not know where new "bootloader__do_spm" is located - assuming "NEW_BOOTLOADER_ADDRESS+(funcaddr___bootloader__do_spm % SPM_PAGESIZE)" + #define NEW_SPM_ADDRESS (NEW_BOOTLOADER_ADDRESS+(funcaddr___bootloader__do_spm % SPM_PAGESIZE)) +#endif + +// TEMP_SPM supports up to 4 pages for "bootloader__do_spm"... +#define TEMP_SPM_NUMPAGE 4 +#define TEMP_SPM_BLKSIZE (TEMP_SPM_NUMPAGE*SPM_PAGESIZE) +#ifndef TEMP_SPM_PAGEADR + #warning "TEMP_SPM_PAGEADR" is not defined explicitly - will choose END OF FLASH ! + #define TEMP_SPM_PAGEADR ((FLASHEND+1) - TEMP_SPM_BLKSIZE) +#endif +#define TEMP_SPM_ADDRESS ((TEMP_SPM_PAGEADR) + (funcaddr___bootloader__do_spm % SPM_PAGESIZE)) + + +#if (NEW_SPM_ADDRESS == funcaddr___bootloader__do_spm) + #define new_do_spm do_spm +#else +void new_do_spm(const uint32_t flash_byteaddress, const uint8_t spmcrval, const uint16_t dataword) { + __do_spm_Ex(flash_byteaddress, spmcrval, dataword, NEW_SPM_ADDRESS >> 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 0 +size_t mypgm_readpage(const mypgm_addr_t byteaddress,const void* buffer, const size_t bufferbytesize) { + size_t result = (bufferbytesize < SPM_PAGESIZE)?bufferbytesize:SPM_PAGESIZE; + size_t pagesize = result >> 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 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) { +#ifdef mypgmdebug + DDRB |= (1<sizeof(buffer))?sizeof(buffer):(SIZEOF_new_firmware-i)); + + mypgm_WRITEpage(NEW_BOOTLOADER_ADDRESS+i, buffer, sizeof(buffer), temp_do_spm); + + #ifdef mypgmdebug + PORTD ^= (1< (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); + + #ifdef mypgmdebug + PORTD ^= (1<