00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <avr/io.h>
00012 #include <avr/interrupt.h>
00013 #include <avr/pgmspace.h>
00014 #include <avr/wdt.h>
00015 #include <avr/boot.h>
00016 #include <avr/eeprom.h>
00017 #include <util/delay.h>
00018 #include <string.h>
00019
00020 static void leaveBootloader() __attribute__((__noreturn__));
00021
00022 #include "bootloaderconfig.h"
00023 #include "usbdrv/usbdrv.c"
00024
00025
00026
00027
00028 #define USBASP_FUNC_CONNECT 1
00029 #define USBASP_FUNC_DISCONNECT 2
00030 #define USBASP_FUNC_TRANSMIT 3
00031 #define USBASP_FUNC_READFLASH 4
00032 #define USBASP_FUNC_ENABLEPROG 5
00033 #define USBASP_FUNC_WRITEFLASH 6
00034 #define USBASP_FUNC_READEEPROM 7
00035 #define USBASP_FUNC_WRITEEEPROM 8
00036 #define USBASP_FUNC_SETLONGADDRESS 9
00037
00038
00039
00040 #ifndef ulong
00041 # define ulong unsigned long
00042 #endif
00043 #ifndef uint
00044 # define uint unsigned int
00045 #endif
00046
00047
00048 #ifndef HAVE_EEPROM_PAGED_ACCESS
00049 # define HAVE_EEPROM_PAGED_ACCESS 0
00050 #endif
00051 #ifndef HAVE_EEPROM_BYTE_ACCESS
00052 # define HAVE_EEPROM_BYTE_ACCESS 0
00053 #endif
00054 #ifndef BOOTLOADER_CAN_EXIT
00055 # define BOOTLOADER_CAN_EXIT 0
00056 #endif
00057
00058
00059 #ifdef BOOTLOADER_INIT
00060 # define bootLoaderInit() BOOTLOADER_INIT
00061 # define bootLoaderExit()
00062 #endif
00063 #ifdef BOOTLOADER_CONDITION
00064 # define bootLoaderCondition() BOOTLOADER_CONDITION
00065 #endif
00066
00067
00068 #ifndef GICR
00069 # define GICR MCUCR
00070 #endif
00071
00072
00073
00074 typedef union longConverter{
00075 ulong l;
00076 uint w[2];
00077 uchar b[4];
00078 }longConverter_t;
00079
00080 static uchar requestBootLoaderExit;
00081 static longConverter_t currentAddress;
00082 static uchar bytesRemaining;
00083 static uchar isLastPage;
00084 #if HAVE_EEPROM_PAGED_ACCESS
00085 static uchar currentRequest;
00086 #else
00087 static const uchar currentRequest = 0;
00088 #endif
00089
00090 static const uchar signatureBytes[4] = {
00091 #ifdef SIGNATURE_BYTES
00092 SIGNATURE_BYTES
00093 #elif defined (__AVR_ATmega8__) || defined (__AVR_ATmega8HVA__)
00094 0x1e, 0x93, 0x07, 0
00095 #elif defined (__AVR_ATmega48__) || defined (__AVR_ATmega48P__)
00096 0x1e, 0x92, 0x05, 0
00097 #elif defined (__AVR_ATmega88__) || defined (__AVR_ATmega88P__)
00098 0x1e, 0x93, 0x0a, 0
00099 #elif defined (__AVR_ATmega168__) || defined (__AVR_ATmega168P__)
00100 0x1e, 0x94, 0x06, 0
00101 #elif defined (__AVR_ATmega328P__)
00102 0x1e, 0x95, 0x0f, 0
00103 #elif defined (__AVR_ATmega32__)
00104 0x1e, 0x95, 0x02, 0
00105 #else
00106 # error "Device signature is not known, please edit main.c!"
00107 #endif
00108 };
00109
00110 #if (FLASHEND) > 0xffff
00111 # define CURRENT_ADDRESS currentAddress.l
00112 #else
00113 # define CURRENT_ADDRESS currentAddress.w[0]
00114 #endif
00115
00116
00117
00118 static void (*nullVector)(void) __attribute__((__noreturn__));
00119
00120 static void leaveBootloader()
00121 {
00122 DBG1(0x01, 0, 0);
00123 bootLoaderExit();
00124 cli();
00125 GICR = (1 << IVCE);
00126 GICR = (0 << IVSEL);
00127
00128
00129
00130
00131
00132 nullVector();
00133 }
00134
00135
00136
00137 uchar usbFunctionSetup(uchar data[8])
00138 {
00139 usbRequest_t *rq = (void *)data;
00140 uchar len = 0;
00141 static uchar replyBuffer[4];
00142
00143 usbMsgPtr = replyBuffer;
00144 if(rq->bRequest == USBASP_FUNC_TRANSMIT){
00145 uchar rval = 0;
00146 usbWord_t address;
00147 address.bytes[1] = rq->wValue.bytes[1];
00148 address.bytes[0] = rq->wIndex.bytes[0];
00149 if(rq->wValue.bytes[0] == 0x30){
00150 rval = rq->wIndex.bytes[0] & 3;
00151 rval = signatureBytes[rval];
00152 #if HAVE_EEPROM_BYTE_ACCESS
00153 }else if(rq->wValue.bytes[0] == 0xa0){
00154 rval = eeprom_read_byte((void *)address.word);
00155 }else if(rq->wValue.bytes[0] == 0xc0){
00156 eeprom_write_byte((void *)address.word, rq->wIndex.bytes[1]);
00157 #endif
00158 }else{
00159
00160 }
00161 replyBuffer[3] = rval;
00162 len = 4;
00163 }else if(rq->bRequest == USBASP_FUNC_ENABLEPROG){
00164
00165 len = 1;
00166 }else if(rq->bRequest >= USBASP_FUNC_READFLASH && rq->bRequest <= USBASP_FUNC_SETLONGADDRESS){
00167 currentAddress.w[0] = rq->wValue.word;
00168 if(rq->bRequest == USBASP_FUNC_SETLONGADDRESS){
00169 #if (FLASHEND) > 0xffff
00170 currentAddress.w[1] = rq->wIndex.word;
00171 #endif
00172 }else{
00173 bytesRemaining = rq->wLength.bytes[0];
00174
00175 isLastPage = rq->wIndex.bytes[1] & 0x02;
00176 #if HAVE_EEPROM_PAGED_ACCESS
00177 currentRequest = rq->bRequest;
00178 #endif
00179 len = 0xff;
00180 }
00181 #if BOOTLOADER_CAN_EXIT
00182 }else if(rq->bRequest == USBASP_FUNC_DISCONNECT){
00183 requestBootLoaderExit = 1;
00184 #endif
00185 }else{
00186
00187 }
00188 return len;
00189 }
00190
00191 uchar usbFunctionWrite(uchar *data, uchar len)
00192 {
00193 uchar isLastWrite;
00194
00195 DBG1(0x31, (void *)¤tAddress.l, 4);
00196 if(len > bytesRemaining)
00197 len = bytesRemaining;
00198 bytesRemaining -= len;
00199 isLastWrite = bytesRemaining == 0;
00200 if(currentRequest >= USBASP_FUNC_READEEPROM){
00201 eeprom_write_block(data, (void *)currentAddress.w[0], len);
00202 currentAddress.w[0] += len;
00203 }else{
00204 char i = len;
00205 while(i > 0){
00206 i -= 2;
00207 if((currentAddress.w[0] & (SPM_PAGESIZE - 1)) == 0){
00208 DBG1(0x33, 0, 0);
00209 #ifndef NO_FLASH_WRITE
00210 cli();
00211 boot_page_erase(CURRENT_ADDRESS);
00212 sei();
00213 boot_spm_busy_wait();
00214 #endif
00215 }
00216 DBG1(0x32, 0, 0);
00217 cli();
00218 boot_page_fill(CURRENT_ADDRESS, *(short *)data);
00219 sei();
00220 CURRENT_ADDRESS += 2;
00221 data += 2;
00222
00223 if((currentAddress.w[0] & (SPM_PAGESIZE - 1)) == 0 || (i <= 0 && isLastWrite && isLastPage)){
00224 DBG1(0x34, 0, 0);
00225 #ifndef NO_FLASH_WRITE
00226 cli();
00227 boot_page_write(CURRENT_ADDRESS - 2);
00228 sei();
00229 boot_spm_busy_wait();
00230 cli();
00231 boot_rww_enable();
00232 sei();
00233 #endif
00234 }
00235 }
00236 DBG1(0x35, (void *)¤tAddress.l, 4);
00237 }
00238 return isLastWrite;
00239 }
00240
00241 uchar usbFunctionRead(uchar *data, uchar len)
00242 {
00243 if(len > bytesRemaining)
00244 len = bytesRemaining;
00245 bytesRemaining -= len;
00246 if(currentRequest >= USBASP_FUNC_READEEPROM){
00247 eeprom_read_block(data, (void *)currentAddress.w[0], len);
00248 }else{
00249 memcpy_P(data, (PGM_VOID_P)CURRENT_ADDRESS, len);
00250 }
00251 CURRENT_ADDRESS += len;
00252 return len;
00253 }
00254
00255
00256
00257 static void initForUsbConnectivity(void)
00258 {
00259 uchar i = 0;
00260
00261 usbInit();
00262
00263 usbDeviceDisconnect();
00264 while(--i){
00265 wdt_reset();
00266 _delay_ms(1);
00267 }
00268 usbDeviceConnect();
00269 sei();
00270 }
00271
00272 int main(void)
00273 {
00274
00275 bootLoaderInit();
00276 odDebugInit();
00277 DBG1(0x00, 0, 0);
00278 #ifndef NO_FLASH_WRITE
00279 GICR = (1 << IVCE);
00280 GICR = (1 << IVSEL);
00281 #endif
00282 if(bootLoaderCondition()){
00283 uint i = 0;
00284 initForUsbConnectivity();
00285 do{
00286 usbPoll();
00287 #if BOOTLOADER_CAN_EXIT
00288 if(requestBootLoaderExit){
00289 if(--i == 0)
00290 break;
00291 }
00292 #endif
00293 }while(bootLoaderCondition());
00294 }
00295 leaveBootloader();
00296 return 0;
00297 }
00298
00299