/* Name: main.c
* Project: AVR bootloader HID
* Author: Christian Starkjohann
* Creation Date: 2007-03-19
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt)
* This Revision: $Id: main.c 378 2007-07-07 20:47:21Z cs $
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <avr/boot.h>
#include <string.h>
static void leaveBootloader() __attribute__((noreturn));
#include "bootloaderconfig.h"
#include "usbdrv.c"
static char reportId = -1;
static unsigned long currentAddress; /* in bytes */
static uchar offset; /* data already processed in current transfer */
#if BOOTLOADER_CAN_EXIT
static uchar exitMainloop;
#endif
PROGMEM char usbHidReportDescriptor[33] = {
0x06, 0x00, 0xff, // USAGE_PAGE (Generic Desktop)
0x09, 0x01, // USAGE (Vendor Usage 1)
0xa1, 0x01, // COLLECTION (Application)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x75, 0x08, // REPORT_SIZE (8)
0x85, 0x01, // REPORT_ID (1)
0x95, 0x06, // REPORT_COUNT (6)
0x09, 0x21, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
0x85, 0x02, // REPORT_ID (2)
0x95, 0x83, // REPORT_COUNT (131)
0x09, 0x22, // USAGE (Undefined)
0xb2, 0x02, 0x01, // FEATURE (Data,Var,Abs,Buf)
0xc0 // END_COLLECTION
};
/* allow compatibility with avrusbboot's bootloaderconfig.h: */
#ifdef BOOTLOADER_INIT
# define bootLoaderInit() BOOTLOADER_INIT
#endif
#ifdef BOOTLOADER_CONDITION
# define bootLoaderCondition() BOOTLOADER_CONDITION
#endif
static void leaveBootloader() {
cli();
boot_rww_enable();
GICR = (1 << IVCE); /* enable change of interrupt vectors */
GICR = (0 << IVSEL); /* move interrupts to application flash section */
asm volatile("rjmp __vectors-0x1800");
}
uchar usbFunctionSetup(uchar data[8]) {
usbRequest_t *rq = (void *)data;
static uchar replyBuffer[7] = {
1, /* report ID */
SPM_PAGESIZE & 0xff,
SPM_PAGESIZE >> 8,
((long)FLASHEND + 1) & 0xff,
(((long)FLASHEND + 1) >> 8) & 0xff,
(((long)FLASHEND + 1) >> 16) & 0xff,
(((long)FLASHEND + 1) >> 24) & 0xff
};
if(rq->bRequest == USBRQ_HID_SET_REPORT){
reportId = rq->wValue.bytes[0]; /* store report ID */
offset = 0;
return 0xff;
}else if(rq->bRequest == USBRQ_HID_GET_REPORT){
usbMsgPtr = replyBuffer;
return 7;
}
return 0;
}
uchar usbFunctionWrite(uchar *data, uchar len)
{
union {
unsigned long l;
unsigned short s[2];
uchar c[4];
} address;
#if BOOTLOADER_CAN_EXIT
if(reportId == 1){ /* leave boot loader */
exitMainloop = 1;
return 1;
}else
#endif
if(reportId == 2){ /* write page */
if(offset == 0){
data++;
DBG1(0x30, data, 4);
address.c[0] = *data++;
address.c[1] = *data++;
address.c[2] = *data++;
address.c[3] = 0;
len -= 4;
}else{
DBG1(0x31, (void *)¤tAddress, 4);
address.l = currentAddress;
}
offset += len;
len >>= 1;
do{
DBG1(0x32, 0, 0);
if((address.s[0] & (SPM_PAGESIZE - 1)) == 0){ /* if page start: erase */
DBG1(0x33, 0, 0);
#ifndef TEST_MODE
cli();
boot_page_erase(address.l); /* erase page */
sei();
boot_spm_busy_wait(); /* wait until page is erased */
#endif
}
cli();
boot_page_fill(address.l, *(short *)data);
sei();
address.l += 2;
data += 2;
/* write page when we cross page boundary */
if((address.s[0] & (SPM_PAGESIZE - 1)) == 0){
DBG1(0x34, 0, 0);
#ifndef TEST_MODE
cli();
boot_page_write(address.l - 2);
sei();
boot_spm_busy_wait();
#endif
}
}while(--len != 0);
currentAddress = address.l;
DBG1(0x35, (void *)¤tAddress, 4);
if(offset < 128){
return 0;
}else{
reportId = -1;
return 1;
}
}
return 1;
}
int __attribute__((noreturn)) main(void)
{
uchar i, j = 0;
/* initialize hardware */
bootLoaderInit();
odDebugInit();
DBG1(0x00, 0, 0);
/* jump to application if jumper is set */
if(bootLoaderCondition()){
#ifndef TEST_MODE
GICR = (1 << IVCE); /* enable change of interrupt vectors */
GICR = (1 << IVSEL); /* move interrupts to boot flash section */
#endif
#ifdef USB_CFG_PULLUP_IOPORTNAME
while(--j){ /* USB Reset by device only required on Watchdog Reset */
i = 0;
while(--i); /* delay >10ms for USB reset */
}
usbDeviceConnect();
#else
USBDDR = (1 << USB_CFG_DMINUS_BIT) | (1 << USB_CFG_DPLUS_BIT); /* issue RESET */
while(--j){ /* USB Reset by device only required on Watchdog Reset */
i = 0;
while(--i); /* delay >10ms for USB reset */
}
USBDDR = 0;
#endif
usbInit();
sei();
while(bootLoaderCondition()){ /* main event loop */
usbPoll();
#if BOOTLOADER_CAN_EXIT
if(exitMainloop){
i = 0;
while(--i)
usbPoll(); /* try to send the response */
break;
}
#endif
}
}
leaveBootloader();
}
Vorgefundene Kodierung: ASCII (7 bit) | 2
|