예제 #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();
}
예제 #2
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;
}
예제 #3
0
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 :)

}
예제 #4
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
}
예제 #5
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;
}
예제 #6
0
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);
}
예제 #7
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();
    }
}
예제 #8
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;
	
}
예제 #9
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;
}
예제 #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;
		}
	}
}
예제 #11
0
// simply write currently stored page in to already erased flash memory
static void writeFlashPage(void) {
    didWriteSomething = 1;
    cli();
    boot_page_write(currentAddress - 2);
    boot_spm_busy_wait(); // Wait until the memory is written.
    sei();
}
예제 #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;
  }
}
// ----------------------------------------------------------------------
// 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;
}
예제 #14
0
//------------------------------------------------------------------------------
void commitPage( unsigned int page )
{
    boot_page_erase( page );
    boot_spm_busy_wait();
    boot_page_write( page );
    boot_spm_busy_wait();
}
예제 #15
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;
	}
}
예제 #16
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;
	}
}
예제 #17
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();
}
예제 #18
0
파일: main.c 프로젝트: gblargg/micronucleus
static void write_flash( void )
{
	if ( currentAddress - 2 < BOOTLOADER_ADDRESS )
	{
		boot_page_write( currentAddress - 2 );
		prevCommand = cmd_written;
	}
}
예제 #19
0
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.
}
예제 #20
0
파일: ows_spm.c 프로젝트: vir/tinyowd
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;
}
예제 #21
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;
}
예제 #22
0
파일: main.c 프로젝트: ejholmes/openfocus
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;
}
예제 #23
0
파일: main.c 프로젝트: Ceitec/F-00011
// 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í
}
예제 #24
0
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();	
}
예제 #25
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");
	}
}
예제 #26
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;
}
예제 #27
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;
}
예제 #28
0
파일: usbload.c 프로젝트: fd0/usbload
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);
}
예제 #29
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;
	}
}
예제 #30
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

#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;
}