Exemple #1
0
void __attribute__ ((section (".bootlup"))) __attribute__((noreturn)) bootlup()
{
	const uint32_t addr_to = (uint32_t)BOOTLOADER_ADDRESS*2; /* byte address of bootloader */
	const uint8_t nbpages=3072/SPM_PAGESIZE; /* maximum of 3k bootloader at the moment */
#if SPM_PAGESIZE > 255
	uint16_t i;
#else
	uint8_t i;
#endif
	for(uint8_t page=0;page<nbpages;page++)
	{
		boot_page_erase(addr_to+page*SPM_PAGESIZE);
		boot_spm_busy_wait ();      // Wait until the memory is erased

		for (i=0; i<SPM_PAGESIZE; i+=2)
		{
			uint16_t w = pgm_read_word(page*SPM_PAGESIZE+i);
			boot_page_fill (addr_to+page*SPM_PAGESIZE+i, w);
		}

		boot_page_write (addr_to+page*SPM_PAGESIZE); // Store buffer in flash page
		boot_spm_busy_wait ();// Wait until the memory is erased
	}

	boot_rww_enable ();

	jump_to_bootloader();
}
bool BootloaderAPI_EraseFillWritePage(const address_size_t address, const uint16_t* words)
{
    // Do not write out of bounds
    if ((address & (SPM_PAGESIZE - 1)) || (address > (FLASHEND - SPM_PAGESIZE)))
    {
        return true;
    }

    // Erase the given FLASH page, ready to be programmed
    boot_page_erase(address);
    boot_spm_busy_wait();

    // Write each of the FLASH page's bytes in sequence
    uint8_t PageWord;
    for (PageWord = 0; PageWord < (SPM_PAGESIZE / 2); PageWord++)
    {
        // Write the next data word to the FLASH page
        boot_page_fill(address + ((uint16_t)PageWord << 1), *words);
        words++;
    }

    // Write the filled FLASH page to memory
    boot_page_write(address);
    boot_spm_busy_wait();

    // Re-enable RWW section
    boot_rww_enable();

    // No error occured
    return false;
}
void main()
{
	DDRB|=(1<<1);
	unsigned int k=0;
	while(k<sizeof(bootloader))
	{
	    unsigned t=0;
	    for(t=0;t<SPM_PAGESIZE;t++)
	    	tpage[t]=pgm_read_byte(&bootloader[k+t]);
	    //erase
		eeprom_busy_wait();
		boot_page_erase(BOOTLOADER_ADDRESS+k); /* erase page */
		boot_spm_busy_wait(); /* wait until page is erased */
		//load
	    for(t=0;t<SPM_PAGESIZE;t+=2)
			boot_page_fill(BOOTLOADER_ADDRESS+k+t,*(unsigned int *)&tpage[t]);
		//program
		cli();
		//boot_page_write(BOOTLOADER_ADDRESS+k);
		sei();
		boot_spm_busy_wait();
		boot_rww_enable(); /* wait until page is erased */
		k+=SPM_PAGESIZE;
		blink(2);
	}
	while(1);
}
Exemple #4
0
void
boot_program_page (uint32_t page, uint8_t *buf)
{
  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.

  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);     // 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;
}
/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
 *  the device from the USB host before passing along unhandled control requests to the library for processing
 *  internally.
 */
void EVENT_USB_Device_ControlRequest(void)
{
	/* Ignore any requests that aren't directed to the HID interface */
	if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
	    (REQTYPE_CLASS | REQREC_INTERFACE))
	{
		return;
	}

	/* Process HID specific control requests */
	switch (USB_ControlRequest.bRequest)
	{
		case HID_REQ_SetReport:
			Endpoint_ClearSETUP();
			
			/* Wait until the command has been sent by the host */
			while (!(Endpoint_IsOUTReceived()));
		
			/* Read in the write destination address */
			uint16_t PageAddress = Endpoint_Read_16_LE();
			
			/* Check if the command is a program page command, or a start application command */
			if (PageAddress == COMMAND_STARTAPPLICATION)
			{
				RunBootloader = false;
			}
			else
			{
				/* Erase the given FLASH page, ready to be programmed */
				boot_page_erase(PageAddress);
				boot_spm_busy_wait();
				
				/* Write each of the FLASH page's bytes in sequence */
				for (uint8_t PageWord = 0; PageWord < (SPM_PAGESIZE / 2); PageWord++)				
				{
					/* Check if endpoint is empty - if so clear it and wait until ready for next packet */
					if (!(Endpoint_BytesInEndpoint()))
					{
						Endpoint_ClearOUT();
						while (!(Endpoint_IsOUTReceived()));
					}

					/* Write the next data word to the FLASH page */
					boot_page_fill(PageAddress + ((uint16_t)PageWord << 1), Endpoint_Read_16_LE());
				}

				/* Write the filled FLASH page to memory */
				boot_page_write(PageAddress);
				boot_spm_busy_wait();

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

			Endpoint_ClearOUT();

			Endpoint_ClearStatusStage();
			break;
	}
}
void program_flash (uint16_t address, uint16_t length)
{
    uint16_t ii, ww;
    uint8_t temp;

    // wait until eventually running write cycles of internal eeprom are
    // finished.
    eeprom_busy_wait ();

    do {
        // erase flash page and wait until the memory is erased.
        boot_page_erase (address);
        boot_spm_busy_wait ();

        // only copy full 16bit words to flash memory
        if (length % 2) length--;

        for (ii=0; ii<SPM_PAGESIZE; ii+=2) {
            // read a word and convert to litte endian
            eep_read(MOD_eExtEEPAddr_AppStart + address + ii, 1, &temp);
            ww = temp;
            eep_read(MOD_eExtEEPAddr_AppStart + address + ii + 1, 1, &temp);
            ww |= temp << 8;
            boot_page_fill (address + ii, ww);

            length -= 2;
            if (length == 0) break;
        }
        // store buffer in flash page and wait until the memory is written.
        boot_page_write (address);
        boot_spm_busy_wait();
        // one flash page has been written
        address += SPM_PAGESIZE;
    } while (length > 0);
}
static void boot_program_page(uint16_t page, uint8_t* buf)
{
    uint16_t i, w;

    // Check we are not overwriting this particular routine
    if ((page >= (FLASHEND - SPM_PAGESIZE + 1)) || ((page & SPM_PAGE_SIZE_BYTES_BM) != 0))
    {
        return;
    }

    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
    {
        // Erase page, wait for memories to be ready
        boot_page_erase(page);
        boot_spm_busy_wait();

        // Fill the bootloader temporary page buffer
        for (i = 0; i < SPM_PAGESIZE; i+=2)
        {
            // Set up little-endian word.
            w = (*buf++) & 0x00FF;
            w |= (((uint16_t)(*buf++)) << 8) & 0xFF00;
            boot_page_fill(page + i, w);
        }

        // Store buffer in flash page, wait until the memory is written, re-enable RWW section
        boot_page_write(page);
        boot_spm_busy_wait();
        boot_rww_enable();
    }
}
Exemple #8
0
void flash_flush_buffer() {
	uint8_t sreg;
	uint16_t word;
	uint8_t i;
	uint16_t* buf = (uint16_t*)flash_pagebuf; // Access buffer on a word basis.
	
	if (!flash_buffer_dirty) return; // Nothing to flush.
	
	// Copy the sram buffer to the temporary page buffer.
	for (i = 0; i < SPM_PAGESIZE/2; i++) {
		word = buf[i];
		boot_page_fill(i*2, word); // Absolute addressing is not neccessary.
	}
	
	// Disable interrupts.
	sreg = SREG;
	cli();
	
	eeprom_busy_wait(); // Make sure any eeprom access has finished.
	
	boot_page_erase(flash_prev_addr);
	boot_spm_busy_wait();  // Wait until the memory is erased.
	
	boot_page_write(flash_prev_addr); // Store buffer in flash page.
	boot_spm_busy_wait();  // Wait until the memory is written.

	flash_buffer_dirty = 0;

	// Reenable RWW-section again so we can return to BIOS after flashing.
	boot_rww_enable ();
	
	// Re-enable interrupts (if they were ever enabled).
	SREG = sreg;
}
void write_flash_page()
{
	uint16_t i = 0;

	eeprom_busy_wait ();

	boot_page_erase (address);
	boot_spm_busy_wait ();      // Wait until the memory is erased.
	
	for (i=0; i<SPM_PAGESIZE; i+=2)
	{
		// Set up little-endian word.
		uint16_t w = *((uint16_t*)(pagebuffer + i));
		
		boot_page_fill (address + i, w);
	}

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

	// Normally, we should re-enable the RWW-section here
	// in order to call the application at bootloader exit.
	// 
	//boot_rww_enable ();	
	// 
	// However, as we are going to exit the bootloader via
	// Watchdog - Reset, we can skip this, saving another
	// 8 bytes :)

}
Exemple #10
0
//------------------------------------------------------------------------------
void rnaInputStream( unsigned char *data, unsigned char dataLen )
{
	for( unsigned char i=0; i<dataLen; i++ )
	{
		packet[packetPos++] = data[i];
	}

	if ( packetPos >= packetExpectedLength )
	{
		if ( packet[0] == RNATypeCodePage )
		{
			struct PacketCodePage *page = (struct PacketCodePage *)(packet + 1);

			unsigned char pos = 0;
			for( unsigned char c=0; c<64; c += 2 )
			{
				boot_page_fill( c, page->code[pos++] );
			}

			boot_page_erase( page->page );
			boot_spm_busy_wait();
			boot_page_write( page->page );
			boot_spm_busy_wait();
		}
		else if ( packet[0] == RNATypeEnterApp )
		{
			jumpToApp = 1;
		}
	}
}
uchar   usbFunctionSetup(uchar data[8])
{
    uchar len = 0;
    
    if (data[1] == USBBOOT_FUNC_LEAVE_BOOT) {
      leaveBootLoader();
    } else if (data[1] == USBBOOT_FUNC_WRITE_PAGE) {

      state = STATE_WRITE_PAGE;

      page_address = (data[3] << 8) | data[2]; /* page address */
      page_offset = 0;

      eeprom_busy_wait();
      cli();
      boot_page_erase(page_address); /* erase page */
      sei();
      boot_spm_busy_wait(); /* wait until page is erased */

      len = 0xff; /* multiple out */

    } else if (data[1] == USBBOOT_FUNC_GET_PAGESIZE) {

      replyBuffer[0] = SPM_PAGESIZE >> 8;
      replyBuffer[1] = SPM_PAGESIZE & 0xff;
      len = 2;

    } else return usbAppFunctionSetup(data,&usbMsgPtr);
Exemple #12
0
static void fixVectors()
{
  uint16_t rjmp;
  uint8_t i;
  uint8_t sreg;
  uint8_t vectors[4] = {
    RESET_VECTOR_OFFSET*2,
    PCINT0_VECTOR_OFFSET*2,
    TIM0_COMPA_VECTOR_OFFSET*2,
    TIM0_COMPB_VECTOR_OFFSET*2,
  };

  rjmp = pgm_read_word(BOOTLOADER_ADDRESS) + BOOTLOADER_ADDRESS / 2;
  if(rjmp != pgm_read_word(0))
  {
    sreg = SREG;
    cli();

    for( i = 0; i < 4; i++)
    {
      rjmp = pgm_read_word(BOOTLOADER_ADDRESS + vectors[i]) + BOOTLOADER_ADDRESS / 2;
      boot_page_fill(vectors[i], rjmp);
    }

    eeprom_busy_wait();

    boot_page_erase(0x00);
    boot_spm_busy_wait();
    boot_page_write(0x00);
    boot_spm_busy_wait();

    SREG = sreg;
  }
}
// ----------------------------------------------------------------------
// Handle an OUT packet.
// ----------------------------------------------------------------------
uchar	usbFunctionWrite ( uchar* data, uchar len )
{
	uchar	i, isLast;

	if(len > remaining) {
		len = remaining;
	}
	remaining -= len;
	isLast = remaining == 0;

	usb_maybe_finalizing = 0;

	if (cmd0 == USBTINY_EEPROM_WRITE)
	{
		#ifdef ENABLE_EEPROM_WRITING
		for	( i = 0; i < len; i++ ) {
			eeprom_write_byte((void *)(cur_addr.u16[0]++), *data++);
		}
		#endif
	}
	else if (cmd0 == USBTINY_FLASH_WRITE)
	{
		#ifdef ENABLE_FLASH_WRITING
		for ( i = 0; i < len; )
		{
			if (CUR_ADDR < SPM_PAGESIZE)
			{
				fake_page_used = 1;
				fake_page[CUR_ADDR] = *((uint16_t*)data);
				CUR_ADDR += 2;
				data += 2;
				i += 2;
			}
			else
			{
				#ifndef ENABLE_CHIP_ERASE
				if ((cur_addr.u16[0] & (SPM_PAGESIZE - 1)) == 0 && CUR_ADDR < BOOTLOADER_ADDRESS) {
					// page start, erase
					boot_page_erase(CUR_ADDR);
					//boot_spm_busy_wait(); // wait not required since CPU is halted
				}
				#endif

				write_word(*((uint16_t*)data));
				data += 2;
				i += 2;

				#ifndef ENABLE_WRITE_WHEN_TOLD
				if ((cur_addr.u16[0] & (SPM_PAGESIZE - 1)) == 0) {
					// end of page
					finalize_flash_if_dirty();
				}
				#endif
			}
		}
		#endif
	}

	return isLast;
}
// ----------------------------------------------------------------------
// finishes a write operation if already started
// ----------------------------------------------------------------------
static void finalize_flash_if_dirty()
{
	if (dirty != 0 && CUR_ADDR <= BOOTLOADER_ADDRESS)
	{
		cli();
		#ifdef ENABLE_FLASH_WRITING
		if (CUR_ADDR >= BOOTLOADER_ADDRESS - SPM_PAGESIZE + 2) {
			// this is the last page before the bootloader
			// the very last 4 bytes will contain these 2 RJMP instructions
			// these two instructions are from the user app, but re-targeted
			boot_page_fill(BOOTLOADER_ADDRESS - 2, 0xCFFF & (((fake_page[0] & 0x0FFF) - (BOOTLOADER_ADDRESS / 2) + 1) | 0xC000)); // jump to start
			boot_page_fill(BOOTLOADER_ADDRESS - 4, 0xCFFF & (((fake_page[4] & 0x0FFF) - (BOOTLOADER_ADDRESS / 2) + 4) | 0xC000)); // USB interrupt
			sei();
			last_page_used = 1;
		}

		boot_page_write(CUR_ADDR - 2);
		//boot_spm_busy_wait(); // wait not required since CPU is halted

		#if !defined(ENABLE_CHIP_ERASE) && defined(ENABLE_WRITE_WHEN_TOLD)
		if (erase_next != 0 && (cur_addr.u16[0] & (SPM_PAGESIZE - 1)) == 0) {
			boot_page_erase(CUR_ADDR);
			//boot_spm_busy_wait(); // wait not required since CPU is halted
		}
		#endif
		#endif
		sei();
	}
	dirty = 0;
}
Exemple #15
0
//------------------------------------------------------------------------------
void commitPage( unsigned int page )
{
    boot_page_erase( page );
    boot_spm_busy_wait();
    boot_page_write( page );
    boot_spm_busy_wait();
}
Exemple #16
0
void flash_copy_data(uint16_t src, uint16_t dst, uint16_t len) {
	uint16_t data;

	cli(); // From this point we're on our own
	
	len = (len | (SPM_PAGESIZE - 1)) + 3; // Round len up to a whole page + 2
	
	while (len -= 2) {
		if (dst >= (uint16_t)&__flash_code_start) break;

		wdt_reset();

		data = pgm_read_word(src); // Read source word
		boot_page_fill(dst, data); // Write word to destination
		
		if ((dst + 2) % SPM_PAGESIZE == 0) { // If we just wrote the last word of a page
			boot_page_erase(dst);
			boot_spm_busy_wait(); // Wait until the memory is erased.
			boot_page_write(dst); // Store buffer in flash page.
			boot_spm_busy_wait(); // Wait until the memory is written.
			boot_rww_enable();
		}
		 
		src += 2;
		dst += 2;		
	}

	while (1); // Nothing more we can do, hopefully there is a watchdog active
}
Exemple #17
0
/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
 *  control requests that are not handled internally by the USB library (including the HID commands, which are
 *  all issued via the control endpoint), so that they can be handled appropriately for the application.
 */
void EVENT_USB_UnhandledControlPacket(void)
{
	/* Handle HID Class specific requests */
	switch (USB_ControlRequest.bRequest)
	{
		case REQ_SetReport:
			if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
			{
				Endpoint_ClearSETUP();
				
				/* Wait until the command (report) has been sent by the host */
				while (!(Endpoint_IsOUTReceived()));

				/* Read in the write destination address */
				uint16_t PageAddress = Endpoint_Read_Word_LE();
				
				/* Check if the command is a program page command, or a start application command */
				if (PageAddress == TEENSY_STARTAPPLICATION)
				{
					RunBootloader = false;
				}
				else
				{
					/* Erase the given FLASH page, ready to be programmed */
					boot_page_erase(PageAddress);
					boot_spm_busy_wait();
					
					/* Write each of the FLASH page's bytes in sequence */
					for (uint8_t PageByte = 0; PageByte < 128; PageByte += 2)
					{
						/* Check if endpoint is empty - if so clear it and wait until ready for next packet */
						if (!(Endpoint_BytesInEndpoint()))
						{
							Endpoint_ClearOUT();
							while (!(Endpoint_IsOUTReceived()));
						}

						/* Write the next data word to the FLASH page */
						boot_page_fill(PageAddress + PageByte, Endpoint_Read_Word_LE());
					}

					/* Write the filled FLASH page to memory */
					boot_page_write(PageAddress);
					boot_spm_busy_wait();

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

				Endpoint_ClearOUT();

				/* Acknowledge status stage */
				while (!(Endpoint_IsINReady()));
				Endpoint_ClearIN();
			}
			
			break;
	}
}
Exemple #18
0
// Handle setup request
extern	byte_t	usb_setup ( byte_t data[8] )
{
    byte_t len = 0;

    // Load the application
    if (data[1] == USBTINYBL_FUNC_APP_INIT) 
    {
        init_application();
    }
    // Write a page
    else if (data[1] == USBTINYBL_FUNC_WRITE) 
    {

        status = STATUS_WRITE;

        page_address = (data[3] << 8) | data[2]; // Set the page address
        // ignore a page write over the bootloader section
        if (page_address >= BOOTLOADER_ADDRESS)
        {
            status = STATUS_IDLE;
            return 0xff;
        }
        page_counter = 0;

        eeprom_busy_wait();
        cli();
        boot_page_erase(page_address);          // Erase the page
        sei();
        boot_spm_busy_wait();                   // Wait until page is erased

        len = 0xff;                             // Request the data though usb_out
    }
    // Read a page
    else if (data[1] == USBTINYBL_FUNC_READ) 
    {

        status = STATUS_READ;

        page_address = (data[3] << 8) | data[2]; // Set the page address
        page_counter = 0;
        boot_rww_enable();
        len = 0xff;                             // Request the data though usb_out
    }
    else if (data[1] == USBTINYBL_FUNC_GET_VER)
    {
        data[0] = VERSION_MAJOR;
        data[1] = VERSION_MINOR;
        len = 2;
    }
    // Load page size
    else if (data[1] == USBTINYBL_FUNC_GET_PAGE) 
    {

      data[0] = SPM_PAGESIZE >> 8;
      data[1] = SPM_PAGESIZE & 0xff;
      len = 2;
    }
Exemple #19
0
static void erase_flash( void )
{
	unsigned addr = BOOTLOADER_ADDRESS;
	do {
        addr -= SPM_PAGESIZE;
        boot_page_erase( addr );
        wdt_reset();
	}
	while ( addr );
}
Exemple #20
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();
}
Exemple #21
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();
}
Exemple #22
0
static void write_page(uint16_t addr)
{
	uint8_t sreg;
	sreg = SREG;
	cli();
	eeprom_busy_wait();
	boot_page_erase(addr);
	boot_spm_busy_wait();
	boot_page_write(addr);
	boot_spm_busy_wait();
	SREG = sreg;
}
Exemple #23
0
static void writeFlashPage(void)
{
    if(needToErase)
    {
        boot_page_erase(CURRENT_ADDRESS - 2);
        boot_spm_busy_wait();
    }

    boot_page_write(CURRENT_ADDRESS - 2);
    boot_spm_busy_wait(); // Wait until the memory is written.

    needToErase = 0;
}
Exemple #24
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;
	}
}
Exemple #25
0
uchar usbFunctionWrite(uchar *data, uchar len)
{
    if (bytesRemaining == 0)
        return 1;
    if (len > bytesRemaining)
        len = bytesRemaining;

    if (cmd == WRITE_EEPROM_BLOCK) {
        /* We write only 2 bytes at a time since eeprom_write_block takes a long time. 
         * If we write more data that it will cause V-USB to timeout */
        eeprom_write_block((const void*)data, (void *)address, 2); 
        eeprom_busy_wait();
        return 1; /* Done with data */
    }
    else if (cmd == WRITE_FLASH_BLOCK) {
        do {
            /* if we're at the start of a page, erase the page */
            if (startPage){
                pageAddress = address;
                cli();
                boot_page_erase(pageAddress);
                sei();
                boot_spm_busy_wait();
                startPage = 0;
            }

            /* Fill the page buffer */
            cli();
            boot_page_fill(address, *(short *)data);
            sei();

            /* We wrote 2 bytes */
            address += 2;
            data += 2;
            len -= 2;
            bytesRemaining -= 2;

            /* 0 bytes remaining, so we must be at the end of a page */
            if (bytesRemaining == 0) {
                cli();
                boot_page_write(pageAddress);
                sei();
                boot_spm_busy_wait();
                return 1; /* Tell the driver that we're done with the data */
            }

        } while(len);
    }
    return 1;
}
Exemple #26
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();
}
static inline void flashPage( u16 p_page ) {
  u16 i;
  u16 data;

  boot_page_erase( p_page );
  boot_spm_busy_wait();
  
  for( i = 0; i < SPM_PAGESIZE; i += 2 ) {
    data = s_flashBuffer[i/2];
    boot_page_fill( p_page+i, data );
  }
  
  boot_page_write( p_page );
  boot_spm_busy_wait();	
}
Exemple #28
0
/**
 * Private avr flush funtion.
 *
 * Write current buffered page in flash memory (if modified).
 * This function erase flash memory page before writing.
 *
 * This function is only use internally in this module.
 */
static void flash_avr_flush(Flash *fd)
{
	if (fd->page_dirty)
	{

		LOG_INFO("Flushing page %d\n", fd->curr_page);

		// Wait while the SPM instruction is busy.
		boot_spm_busy_wait();

		LOG_INFO("Filling temparary page buffer...");

		// Fill the temporary buffer of the AVR
		for (page_addr_t page_addr = 0; page_addr < SPM_PAGESIZE; page_addr += 2)
		{
			uint16_t word = ((uint16_t)fd->page_buf[page_addr + 1] << 8) | fd->page_buf[page_addr];

			ATOMIC(boot_page_fill(page_addr, word));
		}
		LOG_INFO("Done.\n");

		wdt_reset();

		LOG_INFO("Erasing page, addr %u...", fd->curr_page * SPM_PAGESIZE);

		/* Page erase */
		ATOMIC(boot_page_erase(fd->curr_page * SPM_PAGESIZE));

		/* Wait until the memory is erased. */
		boot_spm_busy_wait();

		LOG_INFO("Done.\n");
		LOG_INFO("Writing page, addr %u...", fd->curr_page * SPM_PAGESIZE);

		/* Store buffer in flash page. */
		ATOMIC(boot_page_write(fd->curr_page * SPM_PAGESIZE));
		boot_spm_busy_wait();  // Wait while the SPM instruction is busy.

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

		fd->page_dirty = false;
		LOG_INFO("Done.\n");
	}
}
Exemple #29
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"));
    }
  }
Exemple #30
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();
}