* This Revision: $Id: main.c 786 2010-05-30 20:41:40Z cs $
*/
+#include "spminterface.h" /* must be included as first! */
+
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/boot.h>
#include <avr/eeprom.h>
#include <util/delay.h>
+
+#include <avr/cpufunc.h>
+
+#include <avr/boot.h>
+
#include <string.h>
+
+
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 */
#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
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 uchar requestBootLoaderExit;
+#endif
+static volatile unsigned char stayinloader = 0xfe;
+
+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] = {
0x1e, 0x94, 0x06, 0
#elif defined (__AVR_ATmega328P__)
0x1e, 0x95, 0x0f, 0
+#elif defined (__AVR_ATmega1284P__)
+ 0x1e, 0x97, 0x05, 0
#else
# error "Device signature is not known, please edit main.c!"
#endif
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
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__)
+ }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);
+#endif
+#endif
#if HAVE_EEPROM_BYTE_ACCESS
}else if(rq->wValue.bytes[0] == 0xa0){ /* read EEPROM byte */
rval = eeprom_read_byte((void *)address.word);
}
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){
#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 */
+ stayinloader &= (0xfe);
+#if BOOTLOADER_CAN_EXIT
+ requestBootLoaderExit = 1; /* allow proper shutdown/close of connection */
#endif
}else{
- /* ignore: USBASP_FUNC_CONNECT */
+ /* ignore: others, but could be USBASP_FUNC_CONNECT */
+ stayinloader |= (0x01);
}
return len;
}
}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);
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();
/* 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();
int __attribute__((noreturn)) main(void)
{
/* initialize */
- wdt_disable(); /* main app may have enabled watchdog */
bootLoaderInit();
odDebugInit();
DBG1(0x00, 0, 0);
GICR = (1 << IVSEL); /* move interrupts to boot flash section */
#endif
if(bootLoaderCondition()){
+ wdt_disable(); /* main app may have enabled watchdog */
+#if BOOTLOADER_CAN_EXIT
uchar i = 0, j = 0;
+#endif
initForUsbConnectivity();
do{
usbPoll();
}
}
#endif
- }while(bootLoaderCondition()); /* main event loop */
+ if (stayinloader >= 0x10) {
+ if (!bootLoaderCondition()) {
+ stayinloader-=0x10;
+ }
+ } else {
+ if (bootLoaderCondition()) {
+ if (stayinloader > 1) stayinloader-=2;
+ }
+ }
+
+ }while (stayinloader); /* main event loop */
}
leaveBootloader();
}