X-Git-Url: http://git.linex4red.de/pub/USBaspLoader.git/blobdiff_plain/13894a8b1ba8938b9b5c5d0177f10a4e90b3ef9d..a93ee833f02abfd9cbd22cc14be1cbe630f9103e:/firmware/main.c diff --git a/firmware/main.c b/firmware/main.c index 968cf61..c80ab7d 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -1,13 +1,17 @@ /* Name: main.c * Project: USBaspLoader * Author: Christian Starkjohann + * Author: Stephan Baerwolf * Creation Date: 2007-12-08 + * Modification Date: 2012-11-10 * Tabsize: 4 * Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH * License: GNU GPL v2 (see License.txt) * This Revision: $Id: main.c 786 2010-05-30 20:41:40Z cs $ */ +#include "spminterface.h" /* must be included as first! */ + #include #include #include @@ -15,13 +19,38 @@ #include #include #include + + +#if 0 +/* + * 29.09.2012 / 30.09.2012 + * + * Since cpufunc.h is not needed in this context and + * since it is not available in all toolchains, this include + * becomes deactivated by github issue-report. + * (In case of trouble it remains in sourcecode for reactivation.) + * + * The autor would like to thank Lena-M for reporting this + * issue (https://github.com/baerwolf/USBaspLoader/issues/1). + */ +#include +#endif + +#include + #include + + static void leaveBootloader() __attribute__((__noreturn__)); #include "bootloaderconfig.h" #include "usbdrv/usbdrv.c" +#ifndef BOOTLOADER_ADDRESS + #error need to know the bootloaders flash address! +#endif + /* ------------------------------------------------------------------------ */ /* Request constants used by USBasp */ @@ -35,6 +64,15 @@ static void leaveBootloader() __attribute__((__noreturn__)); #define USBASP_FUNC_WRITEEEPROM 8 #define USBASP_FUNC_SETLONGADDRESS 9 +// additional USBasp Commands +#define USBASP_FUNC_SETISPSCK 10 +#define USBASP_FUNC_TPI_CONNECT 11 +#define USBASP_FUNC_TPI_DISCONNECT 12 +#define USBASP_FUNC_TPI_RAWREAD 13 +#define USBASP_FUNC_TPI_RAWWRITE 14 +#define USBASP_FUNC_TPI_READBLOCK 15 +#define USBASP_FUNC_TPI_WRITEBLOCK 16 +#define USBASP_FUNC_GETCAPABILITIES 127 /* ------------------------------------------------------------------------ */ #ifndef ulong @@ -44,16 +82,6 @@ static void leaveBootloader() __attribute__((__noreturn__)); # define uint unsigned int #endif -/* defaults if not in config file: */ -#ifndef HAVE_EEPROM_PAGED_ACCESS -# define HAVE_EEPROM_PAGED_ACCESS 0 -#endif -#ifndef HAVE_EEPROM_BYTE_ACCESS -# define HAVE_EEPROM_BYTE_ACCESS 0 -#endif -#ifndef BOOTLOADER_CAN_EXIT -# define BOOTLOADER_CAN_EXIT 0 -#endif /* allow compatibility with avrusbboot's bootloaderconfig.h: */ #ifdef BOOTLOADER_INIT @@ -85,29 +113,63 @@ typedef union longConverter{ uchar b[sizeof(addr_t)]; }longConverter_t; -static uchar requestBootLoaderExit; -static longConverter_t currentAddress; /* in bytes */ -static uchar bytesRemaining; -static uchar isLastPage; + +#if BOOTLOADER_CAN_EXIT +static volatile unsigned char stayinloader = 0xfe; +#endif + +static longConverter_t currentAddress; /* in bytes */ +static uchar bytesRemaining; +static uchar isLastPage; #if HAVE_EEPROM_PAGED_ACCESS -static uchar currentRequest; +static uchar currentRequest; #else -static const uchar currentRequest = 0; +static const uchar currentRequest = 0; #endif static const uchar signatureBytes[4] = { #ifdef SIGNATURE_BYTES SIGNATURE_BYTES -#elif defined (__AVR_ATmega8__) || defined (__AVR_ATmega8HVA__) +#elif defined (__AVR_ATmega8__) || defined (__AVR_ATmega8A__) || defined (__AVR_ATmega8HVA__) 0x1e, 0x93, 0x07, 0 -#elif defined (__AVR_ATmega48__) || defined (__AVR_ATmega48P__) +#elif defined (__AVR_ATmega32__) + 0x1e, 0x95, 0x02, 0 +#elif defined (__AVR_ATmega48__) || defined (__AVR_ATmega48A__) || defined (__AVR_ATmega48P__) + #error ATmega48 does not support bootloaders! 0x1e, 0x92, 0x05, 0 -#elif defined (__AVR_ATmega88__) || defined (__AVR_ATmega88P__) +#elif defined (__AVR_ATmega48PA__) + #error ATmega48 does not support bootloaders! + 0x1e, 0x92, 0x0A, 0 +#elif defined (__AVR_ATmega88__) || defined (__AVR_ATmega88A__) || defined (__AVR_ATmega88P__) 0x1e, 0x93, 0x0a, 0 -#elif defined (__AVR_ATmega168__) || defined (__AVR_ATmega168P__) +#elif defined (__AVR_ATmega88PA__) + 0x1e, 0x93, 0x0F, 0 +#elif defined (__AVR_ATmega164A__) + 0x1e, 0x94, 0x0f, 0 +#elif defined (__AVR_ATmega164P__) + 0x1e, 0x94, 0x0a, 0 +#elif defined (__AVR_ATmega168__) || defined (__AVR_ATmega168A__) || defined (__AVR_ATmega168P__) 0x1e, 0x94, 0x06, 0 +#elif defined (__AVR_ATmega168PA__) + 0x1e, 0x94, 0x0B, 0 +#elif defined (__AVR_ATmega324A__) + 0x1e, 0x95, 0x15, 0 +#elif defined (__AVR_ATmega324P__) + 0x1e, 0x95, 0x08, 0 +#elif defined (__AVR_ATmega328__) + 0x1e, 0x95, 0x14, 0 #elif defined (__AVR_ATmega328P__) 0x1e, 0x95, 0x0f, 0 +#elif defined (__AVR_ATmega644__) || defined (__AVR_ATmega644A__) + 0x1e, 0x96, 0x09, 0 +#elif defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) + 0x1e, 0x96, 0x0a, 0 +#elif defined (__AVR_ATmega128__) + 0x1e, 0x97, 0x02, 0 +#elif defined (__AVR_ATmega1284__) + 0x1e, 0x97, 0x06, 0 +#elif defined (__AVR_ATmega1284P__) + 0x1e, 0x97, 0x05, 0 #else # error "Device signature is not known, please edit main.c!" #endif @@ -120,12 +182,14 @@ static void (*nullVector)(void) __attribute__((__noreturn__)); static void leaveBootloader() { DBG1(0x01, 0, 0); - bootLoaderExit(); cli(); + usbDeviceDisconnect(); + bootLoaderExit(); USB_INTR_ENABLE = 0; USB_INTR_CFG = 0; /* also reset config bits */ GICR = (1 << IVCE); /* enable change of interrupt vectors */ GICR = (0 << IVSEL); /* move interrupts to application flash section */ + /* We must go through a global function pointer variable instead of writing * ((void (*)(void))0)(); * because the compiler optimizes a constant 0 to "rcall 0" which is not @@ -151,6 +215,36 @@ static uchar replyBuffer[4]; if(rq->wValue.bytes[0] == 0x30){ /* read signature */ rval = rq->wIndex.bytes[0] & 3; rval = signatureBytes[rval]; +#if HAVE_READ_LOCK_FUSE +#if defined (__AVR_ATmega8__) || defined (__AVR_ATmega8A__) || defined (__AVR_ATmega32__) + }else if(rq->wValue.bytes[0] == 0x58 && rq->wValue.bytes[1] == 0x00){ /* read lock bits */ + rval = boot_lock_fuse_bits_get(GET_LOCK_BITS); + }else if(rq->wValue.bytes[0] == 0x50 && rq->wValue.bytes[1] == 0x00){ /* read lfuse bits */ + rval = boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS); + }else if(rq->wValue.bytes[0] == 0x58 && rq->wValue.bytes[1] == 0x08){ /* read hfuse bits */ + rval = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS); + +#elif defined (__AVR_ATmega48__) || defined (__AVR_ATmega48A__) || defined (__AVR_ATmega48P__) || defined (__AVR_ATmega48PA__) || \ + defined (__AVR_ATmega88__) || defined (__AVR_ATmega88A__) || defined (__AVR_ATmega88P__) || defined (__AVR_ATmega88PA__) || \ + defined (__AVR_ATmega164A__) || defined (__AVR_ATmega164P__) || \ + defined (__AVR_ATmega168__) || defined (__AVR_ATmega168A__) || defined (__AVR_ATmega168P__) || defined (__AVR_ATmega168PA__) || \ + defined (__AVR_ATmega324A__) || defined (__AVR_ATmega324P__) || \ + defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__) || \ + defined (__AVR_ATmega644__) || defined (__AVR_ATmega644A__) || defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644PA__) || \ + defined (__AVR_ATmega128__) || \ + defined (__AVR_ATmega1284__) || defined (__AVR_ATmega1284P__) + }else if(rq->wValue.bytes[0] == 0x58 && rq->wValue.bytes[1] == 0x00){ /* read lock bits */ + rval = boot_lock_fuse_bits_get(GET_LOCK_BITS); + }else if(rq->wValue.bytes[0] == 0x50 && rq->wValue.bytes[1] == 0x00){ /* read lfuse bits */ + rval = boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS); + }else if(rq->wValue.bytes[0] == 0x58 && rq->wValue.bytes[1] == 0x08){ /* read hfuse bits */ + rval = boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS); + }else if(rq->wValue.bytes[0] == 0x50 && rq->wValue.bytes[1] == 0x08){ /* read efuse bits */ + rval = boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS ); +#else + #warning "HAVE_READ_LOCK_FUSE is activated but MCU unknown -> will not support this feature" +#endif +#endif #if HAVE_EEPROM_BYTE_ACCESS }else if(rq->wValue.bytes[0] == 0xa0){ /* read EEPROM byte */ rval = eeprom_read_byte((void *)address.word); @@ -176,7 +270,7 @@ static uchar replyBuffer[4]; } replyBuffer[3] = rval; len = 4; - }else if(rq->bRequest == USBASP_FUNC_ENABLEPROG){ + }else if((rq->bRequest == USBASP_FUNC_ENABLEPROG) || (rq->bRequest == USBASP_FUNC_SETISPSCK)){ /* replyBuffer[0] = 0; is never touched and thus always 0 which means success */ len = 1; }else if(rq->bRequest >= USBASP_FUNC_READFLASH && rq->bRequest <= USBASP_FUNC_SETLONGADDRESS){ @@ -194,12 +288,17 @@ static uchar replyBuffer[4]; #endif len = 0xff; /* hand over to usbFunctionRead() / usbFunctionWrite() */ } -#if BOOTLOADER_CAN_EXIT + }else if(rq->bRequest == USBASP_FUNC_DISCONNECT){ - requestBootLoaderExit = 1; /* allow proper shutdown/close of connection */ + +#if BOOTLOADER_CAN_EXIT + stayinloader &= (0xfe); #endif }else{ - /* ignore: USBASP_FUNC_CONNECT */ + /* ignore: others, but could be USBASP_FUNC_CONNECT */ +#if BOOTLOADER_CAN_EXIT + stayinloader |= (0x01); +#endif } return len; } @@ -221,16 +320,10 @@ uchar isLast; }else{ uchar i; for(i = 0; i < len;){ -#if !HAVE_CHIP_ERASE - if((currentAddress.w[0] & (SPM_PAGESIZE - 1)) == 0){ /* if page start: erase */ - DBG1(0x33, 0, 0); -# ifndef NO_FLASH_WRITE - cli(); - boot_page_erase(CURRENT_ADDRESS); /* erase page */ - sei(); - boot_spm_busy_wait(); /* wait until page is erased */ -# endif - } +#if HAVE_BLB11_SOFTW_LOCKBIT + if (CURRENT_ADDRESS >= (addr_t)(BOOTLOADER_ADDRESS)) { + return 1; + } #endif i += 2; DBG1(0x32, 0, 0); @@ -241,6 +334,15 @@ uchar isLast; data += 2; /* write page when we cross page boundary or we have the last partial page */ if((currentAddress.w[0] & (SPM_PAGESIZE - 1)) == 0 || (isLast && i >= len && isLastPage)){ +#if !HAVE_CHIP_ERASE + DBG1(0x33, 0, 0); +# ifndef NO_FLASH_WRITE + cli(); + boot_page_erase(CURRENT_ADDRESS - 2); /* erase page */ + sei(); + boot_spm_busy_wait(); /* wait until page is erased */ +# endif +#endif DBG1(0x34, 0, 0); #ifndef NO_FLASH_WRITE cli(); @@ -287,7 +389,6 @@ uchar i = 0; /* enforce USB re-enumerate: */ usbDeviceDisconnect(); /* do this while interrupts are disabled */ while(--i){ /* fake USB disconnect for > 250 ms */ - wdt_reset(); _delay_ms(1); } usbDeviceConnect(); @@ -297,7 +398,6 @@ uchar i = 0; int __attribute__((noreturn)) main(void) { /* initialize */ - wdt_disable(); /* main app may have enabled watchdog */ bootLoaderInit(); odDebugInit(); DBG1(0x00, 0, 0); @@ -306,19 +406,29 @@ int __attribute__((noreturn)) main(void) GICR = (1 << IVSEL); /* move interrupts to boot flash section */ #endif if(bootLoaderCondition()){ - uchar i = 0, j = 0; +#if NEED_WATCHDOG + wdt_disable(); /* main app may have enabled watchdog */ +#endif initForUsbConnectivity(); do{ usbPoll(); #if BOOTLOADER_CAN_EXIT - if(requestBootLoaderExit){ - if(--i == 0){ - if(--j == 0) - break; - } - } + if (stayinloader >= 0x10) { + if (!bootLoaderCondition()) { + stayinloader-=0x10; + } + } else { + if (bootLoaderCondition()) { + if (stayinloader > 1) stayinloader-=2; + } + } +#endif + +#if BOOTLOADER_CAN_EXIT + }while (stayinloader); /* main event loop, if BOOTLOADER_CAN_EXIT*/ +#else + }while (1); /* main event loop */ #endif - }while(bootLoaderCondition()); /* main event loop */ } leaveBootloader(); }