diff options
| author | Jenna Fox <a@creativepony.com> | 2012-09-23 17:44:36 +1000 | 
|---|---|---|
| committer | Jenna Fox <a@creativepony.com> | 2012-09-23 17:44:36 +1000 | 
| commit | e64ecae69a30e8d0b178e4280da2e80063f20a60 (patch) | |
| tree | 9d6a1f06766548f1f321752f01082ca2571888e5 | |
| parent | 7f2300dbccc2ca61369bb401e4e1f00a85212999 (diff) | |
| download | micronucleus-e64ecae69a30e8d0b178e4280da2e80063f20a60.tar.gz micronucleus-e64ecae69a30e8d0b178e4280da2e80063f20a60.tar.bz2 micronucleus-e64ecae69a30e8d0b178e4280da2e80063f20a60.zip | |
nice cleaned up usbFunctionWrite
| -rw-r--r-- | firmware/main.c | 466 | 
1 files changed, 238 insertions, 228 deletions
| diff --git a/firmware/main.c b/firmware/main.c index f5a57ce..cdc0841 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -62,11 +62,21 @@ typedef union longConverter{  } longConverter_t;  // outstanding events for the mainloop to deal with -static uchar events = 0; +static uchar events = 0; // bitmap of events to run  #define EVENT_PAGE_NEEDS_ERASE 1  #define EVENT_WRITE_PAGE 2  #define EVENT_EXIT_BOOTLOADER 4 +#define fireEvent(event) events |= (event) +#define isEvent(event)   (events & (event)) +#define clearEvents()    events = 0 + +// state for uploading process +static uchar state = 0; +#define STATE_UNDEFINED 0 +#define STATE_NEW_PAGE 1 +#define STATE_CONTINUING_PAGE 2 +  //static uchar            flashPageLoaded = 0;  //#if HAVE_CHIP_ERASE  //static uchar            eraseRequested = 0; @@ -86,6 +96,7 @@ static uint16_t         vectorTemp[2];  static longConverter_t  currentAddress; /* in bytes */  static uchar            bytesRemaining;  static uchar            isLastPage; +  //#if HAVE_EEPROM_PAGED_ACCESS  //static uchar            currentRequest;  //#else @@ -110,9 +121,6 @@ static const uchar      currentRequest = 0;  // #endif  // }; -#define fireEvent(event) events |= (event) -#define isEvent(event)   (events & (event)) -#define clearEvents()    events = 0  /* ------------------------------------------------------------------------ */ @@ -176,32 +184,30 @@ static void fillFlashWithVectors(void)      // fill all or remainder of page starting at currentAddress with 0xFFs, unless we're      //   at a special address that needs a vector replaced -    for (i = currentAddress % SPM_PAGESIZE; i < SPM_PAGESIZE; i += 2) -    { +    for (i = currentAddress % SPM_PAGESIZE; i < SPM_PAGESIZE; i += 2) {          writeWordToPageBuffer(0xFFFF);      }      writeFlashPage();  } -#	if HAVE_CHIP_ERASE -static void eraseApplication(void) -{ -    // erase all pages starting from end of application section down to page 1 (leaving page 0) -    currentAddress = BOOTLOADER_ADDRESS - SPM_PAGESIZE; -    while(currentAddress != 0x0000) -    { -        boot_page_erase(currentAddress); -        boot_spm_busy_wait(); - -        currentAddress -= SPM_PAGESIZE; -    } - -    // erase and load page 0 with vectors -    fillFlashWithVectors(); -} -#	endif -#endif +// #	if HAVE_CHIP_ERASE +// static void eraseApplication(void) +// { +//     // erase all pages starting from end of application section down to page 1 (leaving page 0) +//     currentAddress = BOOTLOADER_ADDRESS - SPM_PAGESIZE; +//     while(currentAddress != 0x0000) +//     { +//         boot_page_erase(currentAddress); +//         boot_spm_busy_wait(); +//  +//         currentAddress -= SPM_PAGESIZE; +//     } +//  +//     // erase and load page 0 with vectors +//     fillFlashWithVectors(); +// } +// #	endif  static inline __attribute__((noreturn)) void leaveBootloader(void) { @@ -231,217 +237,221 @@ static inline __attribute__((noreturn)) void leaveBootloader(void) {  /* ------------------------------------------------------------------------ */ -uchar   usbFunctionSetup(uchar data[8]) -{ -usbRequest_t    *rq = (void *)data; -uchar           len = 0; -static uchar    replyBuffer[4]; - -#ifdef APPCHECKSUM -    connectedToPc = 1; -#endif - -    usbMsgPtr = replyBuffer; -    if(rq->bRequest == USBASP_FUNC_TRANSMIT){   /* emulate parts of ISP protocol */ -        uchar rval = 0; -        usbWord_t address; -        address.bytes[1] = rq->wValue.bytes[1]; -        address.bytes[0] = rq->wIndex.bytes[0]; -        if(rq->wValue.bytes[0] == 0x30){        /* read signature */ -            rval = rq->wIndex.bytes[0] & 3; -            rval = signatureBytes[rval]; -#if HAVE_EEPROM_BYTE_ACCESS -        }else if(rq->wValue.bytes[0] == 0xa0){  /* read EEPROM byte */ -            rval = eeprom_read_byte((void *)address.word); -        }else if(rq->wValue.bytes[0] == 0xc0){  /* write EEPROM byte */ -            eeprom_write_byte((void *)address.word, rq->wIndex.bytes[1]); -#endif -#if HAVE_CHIP_ERASE -        }else if(rq->wValue.bytes[0] == 0xac && rq->wValue.bytes[1] == 0x80){  /* chip erase */ -#	ifdef TINY85MODE -            eraseRequested = 1; -#	else -            addr_t addr; -            for(addr = 0; addr < FLASHEND + 1 - 2048; addr += SPM_PAGESIZE) { -                /* wait and erase page */ -                //DBG1(0x33, 0, 0); -#   	ifndef NO_FLASH_WRITE -                boot_spm_busy_wait(); -                cli(); -                boot_page_erase(addr); -                sei(); -#   	endif -            } -#	endif -#endif -        }else{ -            /* ignore all others, return default value == 0 */ -        } -        replyBuffer[3] = rval; -        len = 4; -    }else if(rq->bRequest == USBASP_FUNC_ENABLEPROG){ -        /* 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){ -        currentAddress.w[0] = rq->wValue.word; -        if(rq->bRequest == USBASP_FUNC_SETLONGADDRESS){ -#if (FLASHEND) > 0xffff -            currentAddress.w[1] = rq->wIndex.word; -#endif -        }else{ -            bytesRemaining = rq->wLength.bytes[0]; -            /* if(rq->bRequest == USBASP_FUNC_WRITEFLASH) only evaluated during writeFlash anyway */ -            isLastPage = rq->wIndex.bytes[1] & 0x02; -#if HAVE_EEPROM_PAGED_ACCESS -            currentRequest = rq->bRequest; -#endif -            len = 0xff; /* hand over to usbFunctionRead() / usbFunctionWrite() */ -        } +uchar usbFunctionSetup(uchar data[8]) { +   usbRequest_t *rq = (void *)data; +   static uchar replyBuffer[7] = { // TODO: Adjust this buffer size when trimming off those two useless bytes +      1, // report ID +      SPM_PAGESIZE & 0xff, +      SPM_PAGESIZE >> 8, // also completely useless on tiny85's - they'll never have more than 64 byte pagesize +      ((uint)PROGMEM_SIZE) & 0xff, +      (((uint)PROGMEM_SIZE) >> 8) & 0xff, +      0, +      0 // TODO: remove these last ones that don't do anything for these small chips ? +   }; + +   if (rq->bRequest == USBRQ_HID_SET_REPORT) { +      if (rq->wValue.bytes[0] == 2) { +         //offset = 0; +         state = STATE_NEW_PAGE; +         return USB_NO_MSG; +      }  #if BOOTLOADER_CAN_EXIT -    }else if(rq->bRequest == USBASP_FUNC_DISCONNECT){ -        requestBootLoaderExit = 1;      /* allow proper shutdown/close of connection */ +      else { +         fireEvent(EVENT_EXIT_BOOTLOADER); +      }  #endif -    }else{ -        /* ignore: USBASP_FUNC_CONNECT */ -    } -    return len; +   } else if (rq->bRequest == USBRQ_HID_GET_REPORT) { +      usbMsgPtr = replyBuffer; +      return 7; // TODO: Adjust this to match replyBuffer's size after trimming two useless bytes +   } +   return 0;  } - -uchar usbFunctionWrite(uchar *data, uchar len) -{ -    uchar   isLast; - -    //DBG1(0x31, (void *)¤tAddress.l, 4); -    if(len > bytesRemaining) -        len = bytesRemaining; -    bytesRemaining -= len; -    isLast = bytesRemaining == 0; -#if HAVE_EEPROM_PAGED_ACCESS -    if(currentRequest >= USBASP_FUNC_READEEPROM){ -        uchar i; -        for(i = 0; i < len; i++){ -            eeprom_write_byte((void *)(currentAddress.w[0]++), *data++); -        } -    }else { -#endif -        uchar i; -        for(i = 0; i < len;){ -#ifdef TINY85MODE -#if 1 -            if(currentAddress == RESET_VECTOR_OFFSET * 2) -            { -                vectorTemp[0] = *(short *)data; -            } -            if(currentAddress == USBPLUS_VECTOR_OFFSET * 2) -            { -                vectorTemp[1] = *(short *)data; -            } -#else -            if(currentAddress == RESET_VECTOR_OFFSET * 2 || currentAddress == USBPLUS_VECTOR_OFFSET * 2) -            { -                vectorTemp[currentAddress ? 1:0] = *(short *)data; -            } -#endif -#else -#	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(currentAddress);   /* erase page */ -                sei(); -                boot_spm_busy_wait();               /* wait until page is erased */ -#   	endif -#	endif -#endif - -            i += 2; -            //DBG1(0x32, 0, 0); -#ifdef TINY85MODE -            if(currentAddress >= BOOTLOADER_ADDRESS - 6) -            { -                // stop writing data to flash if the application is too big, and clear any leftover data in the page buffer -                __boot_page_fill_clear(); -                return isLast; -            } - -            writeWordToPageBuffer(*(short *)data); -#else -			cli(); -            boot_page_fill(currentAddress, *(short *)data); -            sei(); -            currentAddress += 2; -#endif -            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)){ -                //DBG1(0x34, 0, 0); -#ifdef TINY85MODE -                flashPageLoaded = 1; -#else -#	ifndef NO_FLASH_WRITE -                cli(); -                boot_page_write(currentAddress - 2); -                sei(); -                boot_spm_busy_wait(); -                cli(); -                boot_rww_enable(); -                sei(); -#	endif -#endif -            } -        } -        //DBG1(0x35, (void *)¤tAddress.l, 4); -#if HAVE_EEPROM_PAGED_ACCESS +//  +// uchar usbFunctionSetup(uchar data[8]) { +//     usbRequest_t    *rq = (void *)data; +//     uchar           len = 0; +//     static uchar    replyBuffer[4]; +//      +//  +//     usbMsgPtr = replyBuffer; +//     if (rq->bRequest == USBASP_FUNC_TRANSMIT) {   /* emulate parts of ISP protocol */ +//         uchar rval = 0; +//         usbWord_t address; +//         address.bytes[1] = rq->wValue.bytes[1]; +//         address.bytes[0] = rq->wIndex.bytes[0]; +//         if(rq->wValue.bytes[0] == 0x30){        /* read signature */ +//             rval = rq->wIndex.bytes[0] & 3; +//             rval = signatureBytes[rval]; +// #if HAVE_EEPROM_BYTE_ACCESS +//         }else if(rq->wValue.bytes[0] == 0xa0){  /* read EEPROM byte */ +//             rval = eeprom_read_byte((void *)address.word); +//         }else if(rq->wValue.bytes[0] == 0xc0){  /* write EEPROM byte */ +//             eeprom_write_byte((void *)address.word, rq->wIndex.bytes[1]); +// #endif +// #if HAVE_CHIP_ERASE +//         }else if(rq->wValue.bytes[0] == 0xac && rq->wValue.bytes[1] == 0x80){  /* chip erase */ +// #	ifdef TINY85MODE +//             eraseRequested = 1; +// #	else +//             addr_t addr; +//             for(addr = 0; addr < FLASHEND + 1 - 2048; addr += SPM_PAGESIZE) { +//                 /* wait and erase page */ +//                 //DBG1(0x33, 0, 0); +// #   	ifndef NO_FLASH_WRITE +//                 boot_spm_busy_wait(); +//                 cli(); +//                 boot_page_erase(addr); +//                 sei(); +// #   	endif +//             } +// #	endif +// #endif +//         }else{ +//             /* ignore all others, return default value == 0 */ +//         } +//         replyBuffer[3] = rval; +//         len = 4; +//     }else if(rq->bRequest == USBASP_FUNC_ENABLEPROG){ +//         /* 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){ +//         currentAddress.w[0] = rq->wValue.word; +//         if(rq->bRequest == USBASP_FUNC_SETLONGADDRESS){ +// #if (FLASHEND) > 0xffff +//             currentAddress.w[1] = rq->wIndex.word; +// #endif +//         }else{ +//             bytesRemaining = rq->wLength.bytes[0]; +//             /* if(rq->bRequest == USBASP_FUNC_WRITEFLASH) only evaluated during writeFlash anyway */ +//             isLastPage = rq->wIndex.bytes[1] & 0x02; +// #if HAVE_EEPROM_PAGED_ACCESS +//             currentRequest = rq->bRequest; +// #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 */ +// #endif +//     }else{ +//         /* ignore: USBASP_FUNC_CONNECT */ +//     } +//     return len; +// } + +// uchar usbFunctionWrite(uchar *data, uchar len) +// { +//     uchar   isLast; +//      +//     //DBG1(0x31, (void *)¤tAddress.l, 4); +//     if(len > bytesRemaining) +//         len = bytesRemaining; +//     bytesRemaining -= len; +//     isLast = bytesRemaining == 0; +// #if HAVE_EEPROM_PAGED_ACCESS +//     if(currentRequest >= USBASP_FUNC_READEEPROM){ +//         uchar i; +//         for(i = 0; i < len; i++){ +//             eeprom_write_byte((void *)(currentAddress.w[0]++), *data++); +//         } +//     }else { +// #endif +//         uchar i; +//         for(i = 0; i < len;){ +// //#ifdef TINY85MODE +// //#if 1 +//             if(currentAddress == RESET_VECTOR_OFFSET * 2) +//             { +//                 vectorTemp[0] = *(short *)data; +//             } +//             if(currentAddress == USBPLUS_VECTOR_OFFSET * 2) +//             { +//                 vectorTemp[1] = *(short *)data; +//             } +// // #else +// //             if(currentAddress == RESET_VECTOR_OFFSET * 2 || currentAddress == USBPLUS_VECTOR_OFFSET * 2) +// //             { +// //                 vectorTemp[currentAddress ? 1:0] = *(short *)data; +// //             } +// // #endif +//  +//             i += 2; +//             //DBG1(0x32, 0, 0); +// #ifdef TINY85MODE +//             if(currentAddress >= BOOTLOADER_ADDRESS - 6) +//             { +//                 // stop writing data to flash if the application is too big, and clear any leftover data in the page buffer +//                 __boot_page_fill_clear(); +//                 return isLast; +//             } +//  +//             writeWordToPageBuffer(*(short *)data); +// #else +// 			cli(); +//             boot_page_fill(currentAddress, *(short *)data); +//             sei(); +//             currentAddress += 2; +// #endif +//             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)){ +//                 //DBG1(0x34, 0, 0); +// #ifdef TINY85MODE +//                 flashPageLoaded = 1; +// #else +// #	ifndef NO_FLASH_WRITE +//                 cli(); +//                 boot_page_write(currentAddress - 2); +//                 sei(); +//                 boot_spm_busy_wait(); +//                 cli(); +//                 boot_rww_enable(); +//                 sei(); +// #	endif +// #endif +//             } +//         } +//  +//     return isLast; +// } + +// read in a page over usb, and write it in to the flash write buffer +uchar usbFunctionWrite(uchar *data, uchar length) { +    union { +        addr_t  l; +        uint    s[sizeof(addr_t)/2]; +        uchar   c[sizeof(addr_t)]; +    } address; +     +    // if we are the first functionWrite for this page, update our write address +    if (state == STATE_NEW_PAGE) { +        address.l = currentAddress; +         +        //DBG1(0x30, data, 3); +        address.c[0] = data[1]; +        address.c[1] = data[2]; +        data += 4; +        length -= 4; +         +        currentAddress = address.l; +         +        state = STATE_CONTINUING_PAGE;      } -#endif +     +    do { +        writeWordToPageBuffer(*(uint16_t *) data); +        currentAddress += 2; // advance progmem address +        data += 2; // advance data pointer +        length -= 2; +    } while(length); +     +     +    isLast = !(currentAddress % SPM_PAGESIZE == 0); // if we have now reached another page boundary, we're done +    if (isLast) fireEvent(EVENT_PAGE_WRITE); +          return isLast;  } -uchar usbFunctionRead(uchar *data, uchar len) -{ -    uchar   i; - -    if(len > bytesRemaining) -        len = bytesRemaining; -    bytesRemaining -= len; -    for(i = 0; i < len; i++){ -#if HAVE_EEPROM_PAGED_ACCESS -        if(currentRequest >= USBASP_FUNC_READEEPROM){ -            *data = eeprom_read_byte((void *)currentAddress.w[0]); -        }else{ -#endif -            *data = pgm_read_byte((void *)currentAddress); - -            // read back original vectors -#ifdef TINY85MODE -#if 1 -            if(currentAddress == RESET_VECTOR_OFFSET * 2) -                *data = vectorTemp[0]; -            if(currentAddress == (RESET_VECTOR_OFFSET * 2) + 1) -                *data = vectorTemp[0]/256; -            if(currentAddress == (USBPLUS_VECTOR_OFFSET * 2)) -                *data = vectorTemp[1]; -            if(currentAddress == (USBPLUS_VECTOR_OFFSET * 2) + 1) -                *data = vectorTemp[1]/256; -#else -            if(currentAddress == RESET_VECTOR_OFFSET * 2 || currentAddress == USBPLUS_VECTOR_OFFSET * 2) -            { -                *(short *)data = vectorTemp[currentAddress ? 1:0]; -                data++; -                currentAddress++; -            } -#endif -#endif -#if HAVE_EEPROM_PAGED_ACCESS -        } -#endif -        data++; -        currentAddress++; -    } -    return len; -} -  /* ------------------------------------------------------------------------ */  #ifdef TINY85MODE | 
