Example #1
0
// read in a page over usb, and write it in to the flash write buffer
static uchar usbFunctionWrite(uchar *data, uchar length) {
    //if (length > writeLength) length = writeLength; // test for missing final page bug
    writeLength -= length;
    
    do {
        // remember vectors or the tinyvector table 
        if (currentAddress == RESET_VECTOR_OFFSET * 2) {
            vectorTemp[0] = *(short *)data;
        }
        
        if (currentAddress == USBPLUS_VECTOR_OFFSET * 2) {
            vectorTemp[1] = *(short *)data;
        }
        
        // make sure we don't write over the bootloader!
        if (currentAddress >= PROGMEM_SIZE) {
            __boot_page_fill_clear();
            break;
        }
        
        writeWordToPageBuffer(*(uint16_t *) data);
        data += 2; // advance data pointer
        length -= 2;
    } while(length);
    
    // TODO: Isn't this always last?
    // if we have now reached another page boundary, we're done
    uchar isLast = (writeLength == 0);
    // definitely need this if! seems usbFunctionWrite gets called again in future usbPoll's in the runloop!
    if (isLast) fireEvent(EVENT_WRITE_PAGE); // ask runloop to write our page
    
    return isLast; // let vusb know we're done with this request
}
Example #2
0
// write a word in to the page buffer, doing interrupt table modifications where they're required
static void writeWordToPageBuffer(uint16_t data) {
    // first two interrupt vectors get replaced with a jump to the bootloader's vector table
    if (currentAddress == (RESET_VECTOR_OFFSET * 2) || currentAddress == (USBPLUS_VECTOR_OFFSET * 2)) {
        data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1;
    }
    
    // at end of page just before bootloader, write in tinyVector table
    // see http://embedded-creations.com/projects/attiny85-usb-bootloader-overview/avr-jtag-programmer/
    // for info on how the tiny vector table works
    if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET) {
        data = vectorTemp[0] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 2 + RESET_VECTOR_OFFSET;
    }
    
    if (currentAddress == BOOTLOADER_ADDRESS - TINYVECTOR_USBPLUS_OFFSET) {
        data = vectorTemp[1] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 1 + USBPLUS_VECTOR_OFFSET;
    }
    
    
    // clear page buffer as a precaution before filling the buffer on the first page
    // in case the bootloader somehow ran after user program and there was something
    // in the page buffer already
    if (currentAddress == 0x0000) __boot_page_fill_clear();
    
    cli();
    boot_page_fill(currentAddress, data);
    sei();
    
	// only need to erase if there is data already in the page that doesn't match what we're programming
	// TODO: what about this: if (pgm_read_word(currentAddress) & data != data) { ??? should work right?
	//if (pgm_read_word(currentAddress) != data && pgm_read_word(currentAddress) != 0xFFFF) {
    //if ((pgm_read_word(currentAddress) & data) != data) {
    //    fireEvent(EVENT_PAGE_NEEDS_ERASE);
    //}
    
    // increment progmem address by one word
    currentAddress += 2;
}
Example #3
0
static void writeWordToPageBuffer(uint16_t data)
{
    // first two interrupt vectors get replaced with a jump to the bootloader vector table
    if(CURRENT_ADDRESS == (RESET_VECTOR_OFFSET * 2) || CURRENT_ADDRESS == (USBPLUS_VECTOR_OFFSET * 2))
        data = 0xC000 + (BOOTLOADER_ADDRESS/2) - 1;

    // write 2's complement of checksum
#ifdef APPCHECKSUM
    if(CURRENT_ADDRESS == BOOTLOADER_ADDRESS - APPCHECKSUM_POSITION)
        data = (uint8_t)(~checksum + 1);
#endif

    if(CURRENT_ADDRESS == BOOTLOADER_ADDRESS - TINYVECTOR_RESET_OFFSET)
        data = vectorTemp[0] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 2 + RESET_VECTOR_OFFSET;

    if(CURRENT_ADDRESS == BOOTLOADER_ADDRESS - TINYVECTOR_USBPLUS_OFFSET)
        data = vectorTemp[1] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS)/2 + 1 + USBPLUS_VECTOR_OFFSET;

#ifdef APPCHECKSUM
    // only calculate checksum when we are writing new data to flash (ignore when writing vectors after bootloader programming)
    checksum += (uint8_t)(data/256) + (uint8_t)(data);
#endif

    // clear page buffer as a precaution before filling the buffer on the first page
    // TODO: maybe clear on the first byte of every page?
    if(CURRENT_ADDRESS == 0x0000)
        __boot_page_fill_clear();

    boot_page_fill(CURRENT_ADDRESS, data);

	// only need to erase if there is data already in the page that doesn't match what we're programming    
	if(pgm_read_word(CURRENT_ADDRESS) != data && pgm_read_word(CURRENT_ADDRESS) != 0xFFFF)
        needToErase = 1;

    CURRENT_ADDRESS += 2;
}
Example #4
0
uchar usbFunctionWrite(uchar *data, uchar len)
{
    uchar   isLast;

    DBG1(0x31, (void *)&currentAddress.l, 4);
    if(len > bytesRemaining)
        len = bytesRemaining;
    bytesRemaining -= len;
    isLast = bytesRemaining == 0;
    if(currentRequest >= USBASP_FUNC_READEEPROM){
        uchar i;
        for(i = 0; i < len; i++){
            eeprom_write_byte((void *)(currentAddress.w[0]++), *data++);
        }
    }else {
        uchar i;
        for(i = 0; i < len;){
#ifdef TINY85MODE
#if 1
            if(CURRENT_ADDRESS == RESET_VECTOR_OFFSET * 2)
            {
                vectorTemp[0] = *(short *)data;
            }
            if(CURRENT_ADDRESS == USBPLUS_VECTOR_OFFSET * 2)
            {
                vectorTemp[1] = *(short *)data;
            }
#else
            if(CURRENT_ADDRESS == RESET_VECTOR_OFFSET * 2 || CURRENT_ADDRESS == USBPLUS_VECTOR_OFFSET * 2)
            {
                vectorTemp[CURRENT_ADDRESS ? 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(CURRENT_ADDRESS);   /* erase page */
                sei();
                boot_spm_busy_wait();               /* wait until page is erased */
#   	endif
#	endif
#endif

            i += 2;
            DBG1(0x32, 0, 0);
#ifdef TINY85MODE
            if(CURRENT_ADDRESS >= 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(CURRENT_ADDRESS, *(short *)data);
            sei();
            CURRENT_ADDRESS += 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(CURRENT_ADDRESS - 2);
                sei();
                boot_spm_busy_wait();
                cli();
                boot_rww_enable();
                sei();
#	endif
#endif
            }
        }
        DBG1(0x35, (void *)&currentAddress.l, 4);
    }
    return isLast;
}

uchar usbFunctionRead(uchar *data, uchar len)
{
    uchar   i;

    if(len > bytesRemaining)
        len = bytesRemaining;
    bytesRemaining -= len;
    for(i = 0; i < len; i++){
        if(currentRequest >= USBASP_FUNC_READEEPROM){
            *data = eeprom_read_byte((void *)currentAddress.w[0]);
        }else{
            *data = pgm_read_byte((void *)CURRENT_ADDRESS);

            // read back original vectors
#ifdef TINY85MODE
#if 1
            if(CURRENT_ADDRESS == RESET_VECTOR_OFFSET * 2)
                *data = vectorTemp[0];
            if(CURRENT_ADDRESS == (RESET_VECTOR_OFFSET * 2) + 1)
                *data = vectorTemp[0]/256;
            if(CURRENT_ADDRESS == (USBPLUS_VECTOR_OFFSET * 2))
                *data = vectorTemp[1];
            if(CURRENT_ADDRESS == (USBPLUS_VECTOR_OFFSET * 2) + 1)
                *data = vectorTemp[1]/256;
#else
            if(CURRENT_ADDRESS == RESET_VECTOR_OFFSET * 2 || CURRENT_ADDRESS == USBPLUS_VECTOR_OFFSET * 2)
            {
                *(short *)data = vectorTemp[CURRENT_ADDRESS ? 1:0];
                data++;
                CURRENT_ADDRESS++;
            }
#endif
#endif
        }
        data++;
        CURRENT_ADDRESS++;
    }
    return len;
}