/*!
 * \brief Erase and program a page in the flash ROM.
 *
 * \param page The page number to program, 0..479.
 * \param data Pointer to the new page contents.
 * \param len  Number of bytes to program. If this is less than 256, 
 *             then the remaining bytes will be filled with 0xFF.
 */
static void FlashPage(u_short page, void *data, u_short len)
{
    u_short i;
    u_short *wp = data;

    if (len > 256)
        len = 256;

    if (page >= 256) {
        if (page >= 496)
            return;
        RAMPZ = 1;
    } else
        RAMPZ = 0;
    page <<= 8;

    SpmCommand(page, (1 << PGERS) | (1 << SPMEN));
    SpmCommand(0, (1 << RWWSRE) | (1 << SPMEN));

    for (i = 0; i < len; i += 2, wp++)
        SpmBufferFill(i, *wp);
    for (; i < 256; i += 2)
        SpmBufferFill(i, 0xFFFF);

    SpmCommand(page, (1 << PGWRT) | (1 << SPMEN));
    SpmCommand(0, (1 << RWWSRE) | (1 << SPMEN));
}
Пример #2
0
void flash_write( uint32_t address, uint8_t *data, uint16_t len )
{
	uint16_t page;
	uint16_t offset;
	uint16_t i;
	uint32_t page_address;
	HAS_CRITICAL_SECTION;
	
	//if( address < ((uint32_t)(&__text_end)) || address > FLASHMEM_SIZE) {
	//	led_red_toggle();
		// Disallow writing to kernel or bootloader
	//	return;
	//}
	ENTER_CRITICAL_SECTION();
	//! making sure that EEPROM is not busy
	eeprom_busy_wait ();
	
	//
	// For each different page
	//
	while( len > 0 ) {
		page   = (uint16_t)(address >> 8);
		offset = (uint16_t)(address & 0x000000ff);
		//
		// Load data from the page into temperary buffer
		//
		page_address = address & 0xffffff00;
		
		for( i = 0; i < offset; i+=2 ) {
			uint16_t w = pgm_read_word_far( page_address + i );
			SpmBufferFill( i, w );
		}
		//
		// Modify the content
		//
		for( ; len > 0 && i < 256L; i+=2 ) {
			uint16_t w = *data++;
			w += (*data++) << 8;
			len -= 2;
			SpmBufferFill( i, w ); 
		} 
	
		//
		// load the rest of the page
		//	
		for( ; i < 256L; i+=2 ) {
			uint16_t w = pgm_read_word_far( page_address + i );
			SpmBufferFill( i, w );	
		}
	
		//
		// Write it back
		//
		if( page >= 256L ) {
			RAMPZ = 1;
		} else {
			RAMPZ = 0;
		}
		
		//
		// Prepare the page address
		//
		page <<= 8;
		
		SpmCommand(page, (1 << PGERS) | (1 << SPMEN));
		SpmCommand(page, (1 << PGWRT) | (1 << SPMEN)); 
		SpmCommand(0, (1 << RWWSRE) | (1 << SPMEN));
		
		address += (256L - offset);
	}
	RAMPZ = 0;
	LEAVE_CRITICAL_SECTION();
}