Esempio n. 1
0
void leaveBootloader() {
      cli();
      boot_rww_enable();
      GICR = (1 << IVCE);  /* enable change of interrupt vectors */
      GICR = (0 << IVSEL); /* move interrupts to application flash section */
      jump_to_app();
}
Esempio n. 2
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();
    }
}
Esempio n. 3
0
/** 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;
	}
}
Esempio n. 4
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;
}
Esempio n. 5
0
void ws_flash_write_page(uint32_t address, uint8_t *buf)
{
  uint32_t i;
  uint8_t sreg;
  uint8_t *buffer;

  buffer = buf;

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

  // Start by erasing the page at given address
  boot_page_erase_safe (address);
  boot_spm_busy_wait ();	// Wait until the memory is erased

  for(i=0; i<PAGESIZE; i+=2){
    uint16_t w = *buffer++;
    w += (*buffer++) << 8;
    boot_page_fill_safe(address+i, w);
  }
  boot_page_write_safe (address);
  boot_spm_busy_wait ();

  while(boot_rww_busy()){ boot_rww_enable_safe();}

  boot_rww_enable();
  SREG = sreg;
}
Esempio n. 6
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
}
Esempio n. 7
0
void leaveBootLoader() {
/*  boot_rww_enable_safe(); */
    boot_spm_busy_wait();
    eeprom_busy_wait();
    boot_rww_enable();
  state=STATE_IDLE;
}
Esempio n. 8
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;
}
Esempio n. 9
0
void write_flash_page(uint8_t* buffer, uint32_t address, uint16_t len)
{
	uint16_t size;
	uint8_t sreg;
	uint8_t *p;
	uint16_t data;
	uint16_t lowByte, highByte;
	address_t tempAddress;
	
	tempAddress = address;
	p = buffer;
	size = len;
	
	sreg = SREG;
	cli();
	eeprom_busy_wait ();
	
	
	while(size) {
		lowByte = *p++;
		highByte = *p++;
		
		data = (highByte << 8) | lowByte;
		boot_page_fill(address, data);	
		address += 2;
		size-=2;
	}
	
	boot_page_write(tempAddress);
	boot_spm_busy_wait();
	boot_rww_enable();
	
	SREG = sreg;
	
}
Esempio n. 10
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();
}
Esempio n. 11
0
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);
}
Esempio n. 12
0
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;
}
Esempio n. 13
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;
	}
}
Esempio n. 14
0
// Start the application in firmware
void init_application() 
{
    cli();
    boot_rww_enable();   // Enable access to the flash memory
    GICR = (1 << IVCE);  // enable change of interrupt vectors
    GICR = (0 << IVSEL); // move interrupts to application flash section 
    init_app();
}
Esempio n. 15
0
void flash_end_write(void)
{
	if (payload & (SPM_PAGESIZE-1)) {
		boot_page_write(payload & ~(SPM_PAGESIZE-1));
		boot_spm_busy_wait();
	}
	boot_rww_enable();
}
Esempio n. 16
0
/** Reads or writes a block of EEPROM or FLASH memory to or from the appropriate CDC data endpoint, depending
 *  on the AVR910 protocol command issued.
 *
 *  \param[in] Command  Single character AVR910 protocol command indicating what memory operation to perform
 */
static void ReadWriteMemoryBlock(const uint8_t Command)
{
	uint16_t BlockSize;
	char     MemoryType;

	bool     HighByte = false;
	uint8_t  LowByte  = 0;

	BlockSize  = (FetchNextCommandByte() << 8);
	BlockSize |=  FetchNextCommandByte();

	MemoryType =  FetchNextCommandByte();

	if ((MemoryType != 'E') && (MemoryType != 'F'))
	{
		/* Send error byte back to the host */
		WriteNextResponseByte('?');

		return;
	}

	/* Disable timer 1 interrupt - can't afford to process nonessential interrupts
	 * while doing SPM tasks */
	TIMSK1 = 0;

	/* Check if command is to read memory */
	if (Command == 'g')
	{		
		/* Re-enable RWW section */
		boot_rww_enable();

		while (BlockSize--)
		{
			if (MemoryType == 'F')
			{
				/* Read the next FLASH byte from the current FLASH page */
				#if (FLASHEND > 0xFFFF)
				WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte));
				#else
				WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte));
				#endif

				/* If both bytes in current word have been read, increment the address counter */
				if (HighByte)
				  CurrAddress += 2;

				HighByte = !HighByte;
			}
			else
			{
				/* Read the next EEPROM byte into the endpoint */
				WriteNextResponseByte(eeprom_read_byte((uint8_t*)(intptr_t)(CurrAddress >> 1)));

				/* Increment the address counter after use */
				CurrAddress += 2;
			}
		}
	}
Esempio n. 17
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;
    }
Esempio n. 18
0
void flash_write_block(uint8_t * buf, uintptr_t adr, uintptr_t len)
{
  volatile uint8_t check;
  check = BOOT_SPM_CHECK_VAL;

  if (config_range(adr, len) || writeallow_range(adr, len)) {
    uintptr_t start = adr;
    uintptr_t end   = adr + len;
    uintptr_t i = ~(SPM_PAGESIZE - 1) & start;
    uintptr_t e = i + SPM_PAGESIZE;
    uintptr_t start_a = start & ~0x1;
    uintptr_t end_a   = end   & ~0x1;
  
    DBG_ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
      eeprom_busy_wait();
      boot_spm_busy_wait();
  
      bool change = 0;
  
      for (; i < start_a; i += 2) boot_page_fill(i, pgm_read_word(i));
      if (start & 0x1) {
        uint16_t dat_old = pgm_read_word(i);
        uint16_t dat = (dat_old & 0x00ff) | (*buf << 8);
        change |= dat != dat_old;
        buf++;
        boot_page_fill(i, dat);
        i += 2;
      }
      for (; i < end_a; i += 2) {
        uint16_t dat_old = pgm_read_word(i);
        uint16_t dat = *buf;
        buf++;
        dat |= *buf << 8;
        buf++;
        change |= dat != dat_old;
        boot_page_fill(i, dat);
      }
      if (end & 0x1) {
        uint16_t dat_old = pgm_read_word(i);
        uint16_t dat = (dat_old & 0xff00) | *buf;
        change |= dat != dat_old;
        buf++;
        boot_page_fill(i, dat);
        i += 2;
      }
      for (; i < e; i += 2) boot_page_fill(i, pgm_read_word(i));
      
      if (change) {
        assert(boot_page_erase_checked(adr, check) == 0);
        boot_spm_busy_wait();
        assert(boot_page_write_checked(adr, check) == 0);
        boot_spm_busy_wait();
      }
      boot_rww_enable();
    }
  }
Esempio n. 19
0
/** Reads or writes a block of EEPROM or FLASH memory to or from the appropriate CDC data endpoint, depending
 *  on the AVR109 protocol command issued.
 *
 *  \param[in] Command  Single character AVR109 protocol command indicating what memory operation to perform
 */
static void ReadWriteMemoryBlock(const uint8_t Command)
{
	uint16_t BlockSize;
	char     MemoryType;

	uint8_t  HighByte = 0;
	uint8_t  LowByte  = 0;

	BlockSize  = (FetchNextCommandByte() << 8);
	BlockSize |=  FetchNextCommandByte();

	MemoryType =  FetchNextCommandByte();

	if ((MemoryType != MEMORY_TYPE_FLASH) && (MemoryType != MEMORY_TYPE_EEPROM))
	{
		/* Send error byte back to the host */
		WriteNextResponseByte('?');

		return;
	}

	/* Check if command is to read a memory block */
	if (Command == AVR109_COMMAND_BlockRead)
	{
		/* Re-enable RWW section */
		boot_rww_enable();

		while (BlockSize--)
		{
			if (MemoryType == MEMORY_TYPE_FLASH)
			{
				/* Read the next FLASH byte from the current FLASH page */
				#if (FLASHEND > 0xFFFF)
				WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte));
				#else
				WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte));
				#endif

				/* If both bytes in current word have been read, increment the address counter */
				if (HighByte)
				  CurrAddress += 2;

				HighByte = !HighByte;
			}
			else
			{
				/* Read the next EEPROM byte into the endpoint */
				WriteNextResponseByte(eeprom_read_byte((uint8_t*)(intptr_t)(CurrAddress >> 1)));

				/* Increment the address counter after use */
				CurrAddress += 2;
			}
		}
	}
Esempio n. 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();
}
Esempio n. 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();
}
Esempio n. 22
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();
	}
}
Esempio n. 23
0
/** Resets all configured hardware required for the bootloader back to their original states. */
void ResetHardware(void)
{
	/* Shut down the USB subsystem */
	USB_ShutDown();
	
	/* Relocate the interrupt vector table back to the application section */
	MCUCR = (1 << IVCE);
	MCUCR = 0;

	/* Re-enable RWW section */
	boot_rww_enable();
}
Esempio n. 24
0
void BOOTLOADER_SECTION bootloader(void)
{
  unsigned long address;
  unsigned short boot_word;
//  unsigned char buffer[8];

  cli();

  // Erase page.
  boot_page_erase((unsigned long)ADDRESS);
  while(boot_rww_busy())
  {
    boot_rww_enable();
  }

  // Write data to buffer a word at a time. Note incrementing address by 2.
  // SPM_PAGESIZE is defined in the microprocessor IO header file.
  for(address = ADDRESS; address < ADDRESS + SPM_PAGESIZE; address += 2)
  {
    boot_word=boot_word_read();
    boot_page_fill(address, boot_word);
  }

  // Write page.
  boot_page_write((unsigned long)ADDRESS);
  while(boot_rww_busy())
  {
    boot_rww_enable();
  }

  sei();

  // Read back the values and display.
  // (The show() function is undefined and is used here as an example only.)
  // for(unsigned long i = ADDRESS; i < ADDRESS + 256; i++)
  // {
  //   show(utoa(pgm_read_byte(i), buffer, 16));
  // }
}
Esempio n. 25
0
static inline void uploadPage() {
  u16 ourCRC = 0xffff;
  u16 page = getWordWithCRC( &ourCRC );
  u16 realCRC = getWord();
  char *response = RESPONSE_ERROR;

  fillBuffer( page );
  if ( realCRC == ourCRC ) {
    flashPage( page * SPM_PAGESIZE );
    boot_rww_enable();				//Re-enable the RWW section
    response = RESPONSE_OK;
  } 
  respond( UPLOAD_PAGE_COMMAND, page, response );
}
Esempio n. 26
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");
	}
}
Esempio n. 27
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"));
    }
  }
Esempio n. 28
0
/**
 * This function writes a complete page to the flash memory.
 *
 * @param[in]   page    Page which shall be written
 * @param[in]   buffer  Pointer to the buffer with the data
 */
extern void vscp_bl_adapter_programPage(uint16_t page, uint8_t *buffer)
{
    uint32_t    addr    = page * VSCP_PLATFORM_FLASH_PAGE_SIZE;
    uint16_t    index   = 0u;
    uint8_t     sreg    = 0;

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

    /* No EEPROM activity allowed */
    eeprom_busy_wait();

    /* Erase flash page */
    boot_page_erase(addr);

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

    for (index = 0u; index < VSCP_PLATFORM_FLASH_PAGE_SIZE; index += 2u)
    {
        /* Set up little-endian word. */
        uint16_t leWord = *buffer;
        ++buffer;
        leWord += (*buffer) << 8u;
        ++buffer;

        boot_page_fill(addr + index, leWord);
    }

    /* Store buffer in flash page. */
    boot_page_write(addr);

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

    /* Re-enable RWW-section again. We need this if we want to jump back
     * to the application after the boot loader.
     */
    boot_rww_enable();

    /* Enable interrupts (if they were ever enabled). */
    SREG = sreg;

    return;
}
Esempio n. 29
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;
}
Esempio n. 30
0
static void leaveBootloader()
{
    statusLedOff();
    cli();
    boot_rww_enable();
    USB_INTR_ENABLE = 0;
    USB_INTR_CFG = 0;       /* also reset config bits */

    GICR = (1 << IVCE);     /* enable change of interrupt vectors */
    GICR = (0 << IVSEL);    /* move interrupts to application flash section */
    /* We must go through a global function pointer variable instead of writing
     *  ((void (*)(void))0)();
     * because the compiler optimizes a constant 0 to "rcall 0" which is not
     * handled correctly by the assembler.
     */
    nullVector();
}