static void
flash_page(uint32_t page, uint8_t *buf)
{
    uint16_t i;
    uint8_t sreg;

#ifdef TFTP_DEBUG_DO_NOT_FLASH
    return;
#endif

#if FLASHEND > UINT16_MAX
    if (memcmp_PF(buf, (uint_farptr_t)page, SPM_PAGESIZE) == 0)
#else
    if (memcmp_P(buf, (PGM_VOID_P)page, SPM_PAGESIZE) == 0)
#endif
	return;					/* no changes */

    /* Disable interrupts. */
    sreg = SREG;
    cli();

    eeprom_busy_wait();

    boot_page_erase(page);
    boot_spm_busy_wait();

    for(i = 0; i < SPM_PAGESIZE; i += 2) {
	/* Set up little-endian word. */
	uint16_t w = *buf++;
	w += (*buf++) << 8;

	boot_page_fill (page + i, w);
    }

    boot_page_write (page);
    boot_spm_busy_wait();

    /* Reenable RWW-section again. */
    boot_rww_enable ();

    /* Re-enable interrupts (if they were ever enabled). */
    SREG = sreg;
}
Beispiel #2
0
/* This function stores the CRC value and the length in the
   last two words of the program flash. It does a 
   read/modify/write type operation on the whole last page. */
void
store_crc(uint16_t crc, uint16_t length)
{    
    uint16_t n, i=0;
    
    /* Run through the page and store the information that is already there
       in the temporary buffer. */
    for(n=PGM_LAST_PAGE_START; n<(PGM_LAST_PAGE_START + PGM_PAGE_SIZE-4); n+=2) {
        i = pgm_read_word_near(n);
        boot_page_fill(n, i);
    }
    /* Add the length and crc to the buffer and write it out. */
    boot_page_fill(PGM_LENGTH, length);
    boot_page_fill(PGM_CRC, crc);
    boot_page_erase(PGM_LAST_PAGE_START);
    boot_spm_busy_wait(); 	
    boot_page_write(PGM_LAST_PAGE_START);
    boot_spm_busy_wait(); 
}
Beispiel #3
0
static void
flash_page(uint32_t page, uint8_t *buf)
{
    uint16_t i;
    uint8_t sreg;

#ifdef TFTP_DEBUG_DO_NOT_FLASH
    return;
#endif

    for(i = 0; i < SPM_PAGESIZE; i ++)
	if(buf[i] != pgm_read_byte_near(page + i))
	    goto commit_changes;
    return;					/* no changes */

 commit_changes:
    /* Disable interrupts. */
    sreg = SREG;
    cli();
    
    eeprom_busy_wait();

    boot_page_erase(page);
    boot_spm_busy_wait();

    for(i = 0; i < SPM_PAGESIZE; i += 2) {
	/* Set up little-endian word. */
	uint16_t w = *buf++;
	w += (*buf++) << 8;
        
	boot_page_fill (page + i, w);
    }

    boot_page_write (page);
    boot_spm_busy_wait();

    /* Reenable RWW-section again. */
    boot_rww_enable ();

    /* Re-enable interrupts (if they were ever enabled). */
    SREG = sreg;
}
Beispiel #4
0
void boot_v_erase_page( uint16_t pagenumber ){
	
	uint32_t addr = ( uint32_t )pagenumber * ( uint32_t )PAGE_SIZE; 
	
	// erase page:
	boot_page_erase(addr);

	boot_spm_busy_wait();
	
	boot_rww_enable();
}
void write_page(uint16_t address, uint16_t words[SPM_PAGESIZE / 2]) {
  // fill buffer
  uint16_t iter = 0;
  while (iter < SPM_PAGESIZE / 2) {
    boot_page_fill(address + (iter * 2), words[iter]);
    iter++;
  }
  
  boot_page_write(address);
  boot_spm_busy_wait(); // Wait until the memory is written.
}
Beispiel #6
0
void BootloaderAPI_WritePage(const uint32_t Address)
{
	if (! IsPageAddressValid(Address))
		return;

	ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
	{
		boot_page_write_safe(Address);
		boot_spm_busy_wait();
		boot_rww_enable();
	}
}
Beispiel #7
0
static inline void eraseFlash(void)
{
	// erase only main section (bootloader protection)
	uint32_t addr = 0;
	while (APP_END > addr)
	{
		boot_page_erase(addr);		// Perform page erase
		boot_spm_busy_wait();		// Wait until the memory is erased.
		addr += SPM_PAGESIZE;
	}
	boot_rww_enable();
}
void change_password(const char *password) {
	uint8_t temp;
	uint8_t i = 0;

	temp = SREG;
	cli();

	// Ref: http://www.nongnu.org/avr-libc/user-manual/group__avr__boot.html
	boot_page_erase(FLASH_MEMORY_PAGE_ADDRESS);
    boot_spm_busy_wait();      // Wait until the memory is erased.

	// Add the magic at the beginning
	boot_page_fill(FLASH_MEMORY_PAGE_ADDRESS + i, PASSWORD_MAGIC);
	i+=PASSWORD_MAGIC_LENGTH;

    for(; i<(PASSWORD_MAGIC_LENGTH+MAX_PASSWORD_LENGTH+1); i+=2) {
        // Set up little-endian word.

        uint16_t w = *password++;
        w += (*password++) << 8;
    
        boot_page_fill(FLASH_MEMORY_PAGE_ADDRESS + i, w);

		// Quit if last written word contain the null character
		if(*(password-1) == '\0' || *(password-2) == '\0') {
			break;
		}
    }

    boot_page_write(FLASH_MEMORY_PAGE_ADDRESS);     // Store buffer in flash page.
    boot_spm_busy_wait();       // Wait until the memory is written.

	// Reenable RWW-section again. We need this if we want to jump back
    // to the application after bootloading.
	boot_rww_enable ();

	// Set back the global interrupt bit to its original state
	SREG |= temp & (1<<SREG_I);
}
Beispiel #9
0
int flash_write_block(uint8_t *block_addr, uint8_t *data)
{
#if (FLASHEND) > 0xFFFF /* we need long addressing */
	unsigned long a = (unsigned long)(block_addr);
#else
	unsigned int a = (unsigned int)(block_addr);
#endif
	int i;

	if ((a & (BLOCK_SIZE - 1)) != 0) /* Not block size aligned */
		return -1;

	if (a >= BL_ADDR) /* Allowing to write only in the application section */
		return -1;

	cli(); // Disable interruptions

	/* Erase the (flash) block */
	boot_page_erase(a);
	boot_spm_busy_wait(); /* Wait until page is erased */

	/* Start filling the block's buffer word-wise */
	for (i = 0; i < BLOCK_SIZE; i += 2)
	{
		boot_page_fill(a + i, *(uint16_t *)(data + i));
	}

	/* Write the block's buffer into the flash */
	boot_page_write(a);
	boot_spm_busy_wait(); /* Wait until page is written */

	boot_rww_enable(); /* Re-enable RWW-section again */
	/* The above is needed to access the flash written */

	sei(); // Enable interrupts

	return 0;
}
Beispiel #10
0
void flash_write(const uint8_t *buf, uint16_t size)
{
	static uint8_t last;
	const uint8_t *p;

	for (p = buf; p != buf+size; p++) {
		if (!(payload & (SPM_PAGESIZE-1))) {
			boot_page_erase(payload);
			boot_spm_busy_wait();
		}

		if (payload & 1)
			boot_page_fill(payload, last | (*p << 8));
		else
			last = *p;
		payload++;

		if (!(payload & (SPM_PAGESIZE-1))) {
			boot_page_write(payload-SPM_PAGESIZE);
			boot_spm_busy_wait();
		}
	}
}
Beispiel #11
0
// Vymazání celé aplikaèní pamìti
void ChipErase(void)
{
	uint16_t	address = 0x0000, konec = 0x0000;
	konec = END_APP_ADDRESS_BYTES;
	// Maže od adresy 0x0000 po koneènou adresu Bootloaderu
	while (address < konec)
	{
		// Vymaže pøíslušnou adresu
		
		boot_page_erase(address);
		boot_spm_busy_wait();
		address += SPM_PAGESIZE;
	}
}
void
boot_program_page (uint32_t page)
{
  uint16_t i;
  uint8_t sreg;

  // Disable interrupts.
  sreg = SREG;
  cli();

  eeprom_busy_wait ();

  boot_page_erase (page);
  boot_spm_busy_wait ();      // Wait until the memory is erased.
  uint8_t wbufaddr = 0;

  for (i=0; i<SPM_PAGESIZE; i+=2)
  {
    // Set up little-endian word.
    uint16_t w = buf[wbufaddr++];
    w += buf[wbufaddr++] << 8;

    boot_page_fill (page + i, w);
  }

  boot_page_write (page);     // Store buffer in flash page.
  boot_spm_busy_wait();       // Wait until the memory is written.

  // Reenable RWW-section again. We need this if we want to jump back
  // to the application after bootloading.

  boot_rww_enable ();

  // Re-enable interrupts (if they were ever enabled).

  SREG = sreg;
}
Beispiel #13
0
static void eraseApplication(void)
{
    // erase all pages starting from end of application section down to page 1 (leaving page 0)
    CURRENT_ADDRESS = BOOTLOADER_ADDRESS - SPM_PAGESIZE;
    while(CURRENT_ADDRESS != 0x0000)
    {
        boot_page_erase(CURRENT_ADDRESS);
        boot_spm_busy_wait();

        CURRENT_ADDRESS -= SPM_PAGESIZE;
    }

    // erase and load page 0 with vectors
    fillFlashWithVectors();
}
Beispiel #14
0
// Zápis po pages do pamìti Flash
void WriteFlashPages(uint16_t address, uint8_t *Buffer)
{
	uint16_t i;
	uint16_t Data=0;
	for (i = 0; i < SPM_PAGESIZE; i += 2)
	{
		Data = *Buffer++;
		Data |= *Buffer++ << 8;
		// Plní Page buffer (256 velikost u 644p)
		boot_page_fill (address + i, Data);
	}

	boot_page_write (address);     //Naplní buffer
	boot_spm_busy_wait();       // Èeká dokud se neuvolní
}
Beispiel #15
0
/*
 Erase the flash page(s) corresponding to the coffee sector.
 This is done by calling the write routine with a null buffer and any address
 within each page of the sector (we choose the first byte).
 */
BOOTLOADER_SECTION
void avr_flash_erase(coffee_page_t sector) {
	coffee_page_t i;

#if FLASH_COMPLEMENT_DATA
	uint32_t addr32;
	volatile uint8_t sreg;

	// Disable interrupts.
	sreg = SREG;
	cli();

	for (i = 0; i < COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE; i++) {
		for (addr32 = COFFEE_START + (((sector + i) * COFFEE_PAGE_SIZE)
				& ~(COFFEE_PAGE_SIZE - 1)); addr32 < (COFFEE_START + (((sector
				+ i + 1) * COFFEE_PAGE_SIZE) & ~(COFFEE_PAGE_SIZE - 1))); addr32
				+= SPM_PAGESIZE) {
			boot_page_erase(addr32);
			boot_spm_busy_wait();

		}
	}
	//RE-enable interrupts
	boot_rww_enable();
	SREG = sreg;
#else
	for (i=0;i<COFFEE_SECTOR_SIZE/COFFEE_PAGE_SIZE;i++) {
		avr_flash_write((sector+i)*COFFEE_PAGE_SIZE,0,0);
	}
#endif

#if 0
#if TESTCOFFEE
/* Defining TESTCOFFEE is a convenient way of testing a new configuration.
 * It is triggered by an erase of the last sector.
 * Note this routine will be reentered during the test!                     */

  if ((sector+i)==COFFEE_PAGES-1) {
    int j=(int)(COFFEE_START>>1),k=(int)((COFFEE_START>>1)+(COFFEE_SIZE>>1)),l=(int)(COFFEE_SIZE/1024UL);
    printf_P(PSTR("\nTesting coffee filesystem [0x%08x -> 0x%08x (%uKb)] ..."),j,k,l);
    int r= coffee_file_test();
    if (r<0) {
      printf_P(PSTR("\nFailed with return %d! :-(\n"),r);
    } else {
      printf_P(PSTR("Passed! :-)\n"));
    }
  }
Beispiel #16
0
void ws_flash_read_byte(uint32_t addr, uint8_t *buf)
{
  uint8_t sreg;

  sreg = SREG;
  cli();
  eeprom_busy_wait();
  _WAIT_FOR_SPM();
  eeprom_busy_wait();
  boot_spm_busy_wait();
  _ENABLE_RWW_SECTION();
  *buf = pgm_read_byte_far(addr);

  boot_rww_enable();
  SREG = sreg;
  return;
}
Beispiel #17
0
// erase any existing application and write in jumps for usb interrupt and reset to bootloader
//  - Because flash can be erased once and programmed several times, we can write the bootloader
//  - vectors in now, and write in the application stuff around them later.
//  - if vectors weren't written back in immidately, usb would fail.
static inline void eraseApplication(void) {
    // erase all pages until bootloader, in reverse order (so our vectors stay in place for as long as possible)
    // while the vectors don't matter for usb comms as interrupts are disabled during erase, it's important
    // to minimise the chance of leaving the device in a state where the bootloader wont run, if there's power failure
    // during upload
    currentAddress = BOOTLOADER_ADDRESS;
    cli();
    while (currentAddress) {
        currentAddress -= SPM_PAGESIZE;
        
        boot_page_erase(currentAddress);
        boot_spm_busy_wait();
    }
    
    fillFlashWithVectors();
    sei();
}
Beispiel #18
0
static inline uint16_t writeFlashPage(uint16_t address, pagebuf_t size)
{
  uint16_t pagestart = address;
  uint16_t data, sreg;
  uint8_t *tmp = gBuffer;

  do {
    // Safeguard
    if(address >= BOOTLOADER_ADDRESS)
      return address;

    data = *tmp++;
    data |= *tmp++ << 8;

    if(address == RESET_VECTOR_OFFSET * 2)
      vectorTemp[0] = (short)data;
    else if(address == PCINT0_VECTOR_OFFSET * 2)
      vectorTemp[1] = (short)data;
    else if(address == TIM0_COMPA_VECTOR_OFFSET * 2)
      vectorTemp[2] = (short)data;
    else if(address == TIM0_COMPB_VECTOR_OFFSET * 2)
      vectorTemp[3] = (short)data;
    else
    {
      sreg = SREG;
      cli();
      boot_page_fill(address, data);
      SREG = sreg;
    }

    address += 2;
    size -= 2;
  } while (size);

  sreg = SREG;
  cli();
  boot_page_write(pagestart);
  boot_spm_busy_wait();
  SREG = sreg;

  if(pagestart == 0)
    updateTinyTable();

  return address;
}
Beispiel #19
0
uchar usbFunctionWrite(uchar *data, uchar len)
{
    if (len > bytes_remaining)
        len = bytes_remaining;
    bytes_remaining -= len;

    if (request == USBASP_FUNC_WRITEEEPROM) {
        for (uint8_t i = 0; i < len; i++)
            eeprom_write_byte((uint8_t *)flash_address.word++, *data++);
    } else {
        /* data is handled wordwise, adjust len */
        len /= 2;
        len -= 1;
        for (uint8_t i = 0; i <= len; i++) {
            uint16_t *w = (uint16_t *)data;
            cli();
            boot_page_fill(flash_address.word, *w);
            sei();

            usbWord_t next_address;
            next_address.word = flash_address.word;
            next_address.word += 2;
            data += 2;

            /* write page if page boundary is crossed or this is the last page */
            if ( next_address.bytes[0] % SPM_PAGESIZE == 0 ||
                    (bytes_remaining == 0 && i == len) ) {
                cli();
                boot_page_write(flash_address.word);
                sei();
                boot_spm_busy_wait();
                cli();
                boot_rww_enable();
                sei();
            }

            flash_address.word = next_address.word;
        }
    }

    /* flash led on activity */
    PORTC ^= _BV(PC4);

    return (bytes_remaining == 0);
}
Beispiel #20
0
static inline void eraseApplication()
{
  uint16_t address = BOOTLOADER_ADDRESS;
  uint8_t sreg;

  sreg = SREG;
  cli();

  while(address)
  {
    address -= SPM_PAGESIZE;
    boot_page_erase(address);
    boot_spm_busy_wait();
  }

  fixVectors();
  SREG = sreg;
}
Beispiel #21
0
/**
 * Flushes a partially written page of data to physical FLASH, if a page
 * boundary has been crossed.
 *
 * \note If a page flush occurs the global HEX parser state is updated.
 */
static void FlushPageIfRequired(void)
{
	/* Abort if no data has been buffered for writing to the current page */
	if (!PageDirty)
	  return;

	/* Flush the FLASH page to physical memory if we are crossing a page boundary */
	uint32_t NewPageStartAddress = (HEXParser.CurrAddress & ~(SPM_PAGESIZE - 1));
	if (HEXParser.PageStartAddress != NewPageStartAddress)
	{
		boot_page_write(HEXParser.PageStartAddress);
		boot_spm_busy_wait();

		HEXParser.PageStartAddress = NewPageStartAddress;

		PageDirty = false;
	}
}
Beispiel #22
0
void erase_flash_page(uint32_t flashPage)
{
	 uint8_t sreg;
	 
	
	sreg = SREG;
	
	cli();
	eeprom_busy_wait ();
        boot_page_erase (flashPage);
        boot_spm_busy_wait ();      // Wait until the memory is erased.
	
	
        boot_rww_enable ();

	
	
	
	SREG = sreg;
}
Beispiel #23
0
static void updateTinyTable()
{
  uint8_t sreg;

  sreg = SREG;
  cli();

  boot_page_fill(BOOTLOADER_ADDRESS - TINY_RESET_VECTOR_OFFSET, 
                 vectorTemp[0] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS) / 2 + 4 + RESET_VECTOR_OFFSET);
  boot_page_fill(BOOTLOADER_ADDRESS - TINY_PCINT0_VECTOR_OFFSET, 
                 vectorTemp[1] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS) / 2 + 3 + PCINT0_VECTOR_OFFSET);
  boot_page_fill(BOOTLOADER_ADDRESS - TINY_TIM0_COMPA_VECTOR_OFFSET, 
                 vectorTemp[2] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS) / 2 + 2 + TIM0_COMPA_VECTOR_OFFSET);
  boot_page_fill(BOOTLOADER_ADDRESS - TINY_TIM0_COMPB_VECTOR_OFFSET, 
                 vectorTemp[3] + ((FLASHEND + 1) - BOOTLOADER_ADDRESS) / 2 + 1 + TIM0_COMPB_VECTOR_OFFSET);

  boot_page_write(BOOTLOADER_ADDRESS - SPM_PAGESIZE + 1);
  boot_spm_busy_wait();

  SREG = sreg;
}
Beispiel #24
0
BOOTLOADER_SECTION void flash_write_page(const u16_t page, const u8_t* data)
{
    u16_t i;

    // Calculate 32-bit address from specified page
    u32_t adr = ((u32_t)page) * FLASH_PAGE_SIZE;

    // Save status of global interrupts
    u8_t sreg = SREG;

    // Disable interrupts
    cli();

    // Clear the page first
    flash_clear_page(page);

    // Fill write data with 16-bit data
    for(i=0; i<FLASH_PAGE_SIZE; i+=2)
    {
        // Fetch little endian word of data
        u16_t word;
        word  = *data++;
        word += (*data++) << 8;

        boot_page_fill(adr+i, word);
    }

    // Commit data to flash page
    boot_page_write(adr);   

    // Wait until SPM command has finished
    boot_spm_busy_wait();

    // Re-enable RWW-section
    boot_rww_enable();

    // Restore status of global interrupts
    SREG = sreg;
}
Beispiel #25
0
/* _____GLOBAL FUNCTIONS_____________________________________________________ */
BOOTLOADER_SECTION void flash_clear_page(const u16_t page)
{
    // Calculate 32-bit address from specified page
    u32_t adr = ((u32_t)page) * SPM_PAGESIZE;

    // Save status of global interrupts
    u8_t sreg = SREG;

    // Disable interrupts
    cli();

    boot_page_erase(adr);

    // Wait until SPM command has finished
    boot_spm_busy_wait();

    // Re-enable RWW-section
    boot_rww_enable();

    // Restore status of global interrupts
    SREG = sreg;
}
Beispiel #26
0
// write a page to flash.  This will NOT pre-erase the page!
void boot_v_write_page( uint16_t pagenumber, uint8_t *data ){

	uint32_t addr = ( uint32_t )pagenumber * ( uint32_t )PAGE_SIZE; 

	// fill page buffer:
	
	for(uint32_t i = addr; i < addr + PAGE_SIZE; i += 2){
		
		uint8_t lsb = *data++;
		uint8_t msb = *data++;
		uint16_t data = (msb << 8) + lsb;
		
		boot_page_fill(i, data);
	}
	
	
	boot_page_write(addr);
	
	boot_spm_busy_wait();
	
	boot_rww_enable();
}
Beispiel #27
0
void ws_flash_read_page(uint32_t addr, uint8_t *buf)
{
  uint8_t sreg;
  uint32_t i;

  sreg = SREG;
  cli();
  eeprom_busy_wait();

  for (i=0;i<PAGESIZE;i++)
  {
    _WAIT_FOR_SPM();
    eeprom_busy_wait();
    boot_spm_busy_wait();
    _ENABLE_RWW_SECTION();
    buf[i] = pgm_read_byte_far(addr+i);
  }

  boot_rww_enable();
  SREG = sreg;
  return;
}
Beispiel #28
0
static inline uint16_t writeFlashPage(uint16_t waddr, uint8_t size)
{
	uint32_t pagestart = (uint32_t)waddr<<1;
	uint32_t baddr = pagestart;
	uint16_t data;
	uint8_t *tmp = gBuffer;

	do
	{
		data = *tmp++;
		data |= *tmp++ << 8;
		boot_page_fill(baddr, data);	// call asm routine.

		baddr += 2;			// Select next word in memory
		size -= 2;			// Reduce number of bytes to write by two
	}
	while (size);				// Loop until all bytes written

	boot_page_write(pagestart);
	boot_spm_busy_wait();
	boot_rww_enable();		// Re-enable the RWW section

	return baddr>>1;
}
Beispiel #29
0
usbMsgLen_t usbFunctionSetup(uchar data[8])
{
    usbRequest_t *req = (void *)data;
    uint8_t len = 0;
    static uint8_t buf[4];

    /* set global data pointer to local buffer */
    usbMsgPtr = buf;

    /* on enableprog just return one zero, which means success */
    if (req->bRequest == USBASP_FUNC_ENABLEPROG) {
        buf[0] = 0;
        len = 1;
        timeout = 255;
    } else if (req->bRequest == USBASP_FUNC_CONNECT) {
        /* turn on led */
        PORTD |= _BV(PD5);
    } else if (req->bRequest == USBASP_FUNC_DISCONNECT) {
        /* turn off led */
        PORTD &= ~_BV(PD6);
        request_exit = 1;
    /* catch query for the devicecode, chip erase and eeprom byte requests */
    } else if (req->bRequest == USBASP_FUNC_TRANSMIT) {

        /* reset buffer with zeroes */
        memset(buf, '\0', sizeof(buf));

        /* read the address for eeprom operations */
        usbWord_t address;
        address.bytes[0] = data[4]; /* low byte is data[4] */
        address.bytes[1] = data[3]; /* high byte is data[3] */

        /* if this is a request to read the device signature, answer with the
         * appropiate signature byte */
        if (data[2] == ISP_READ_SIGNATURE) {
            /* the complete isp data is reported back to avrdude, but we just need byte 4
             * bits 0 and 1 of byte 3 determine the signature byte address */
            buf[3] = signature[data[4] & 0x03];

#ifdef ENABLE_CATCH_EEPROM_ISP
        /* catch eeprom read */
        } else if (data[2] == ISP_READ_EEPROM) {

            buf[3] = eeprom_read_byte((uint8_t *)address.word);

        /* catch eeprom write */
        } else if (data[2] == ISP_WRITE_EEPROM) {

            /* address is in data[4], data[3], and databyte is in data[5] */
            eeprom_write_byte((uint8_t *)address.word, data[5]);
#endif

        /* catch a chip erase */
        } else if (data[2] == ISP_CHIP_ERASE1 && data[3] == ISP_CHIP_ERASE2) {
            for (flash_address.word = 0;
                 flash_address.word < BOOT_SECTION_START;
                 flash_address.word += SPM_PAGESIZE) {

                /* wait and erase page */
                boot_spm_busy_wait();
                cli();
                boot_page_erase(flash_address.word);
                sei();
            }
        }

        /* in case no data has been filled in by the if's above, just return zeroes */
        len = 4;

#ifdef ENABLE_ECHO_FUNC
    /* implement a simple echo function, for testing the usb connectivity */
    } else if (req->bRequest == FUNC_ECHO) {
        buf[0] = req->wValue.bytes[0];
        buf[1] = req->wValue.bytes[1];
        len = 2;
#endif
    } else if (req->bRequest >= USBASP_FUNC_READFLASH) {
        /* && req->bRequest <= USBASP_FUNC_SETLONGADDRESS */

        putc('R');
        putc(req->bRequest);

        /* extract address and length */
        flash_address.word = req->wValue.word;
        bytes_remaining = req->wLength.bytes[0];
        request = req->bRequest;
        /* hand control over to usbFunctionRead()/usbFunctionWrite() */
        len = 0xff;
    }

    return len;
}
Beispiel #30
0
void BootloaderAPI_WritePage(const uint32_t Address)
{
	boot_page_write_safe(Address);
	boot_spm_busy_wait();
	boot_rww_enable();
}