Ejemplo n.º 1
0
/**
 * \brief Fill temporary EEPROM page buffer with value.
 *
 * This fills the the EEPROM page buffers with a given value.
 * If memory mapped EEPROM is enabled, this function will not work.
 *
 * \note Only the lower part of the address is used to address the buffer.
 *       Therefore, no address parameter is needed. In the end, the data
 *       is written to the EEPROM page given by the address parameter to the
 *       EEPROM write page operation.
 *
 * \param  value Value to copy to the page buffer.
 */
void nvm_eeprom_fill_buffer_with_value(uint8_t value)
{
	uint8_t old_cmd;
	old_cmd = NVM.CMD;

	nvm_eeprom_flush_buffer();
	// Wait until NVM is ready
	nvm_wait_until_ready();

	NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc;

	/*  Set address to zero, as only the lower bits matters. ADDR0 is
	 *  maintained inside the loop below.
	 */
	NVM.ADDR2 = 0x00;
	NVM.ADDR1 = 0x00;

	// Load multible bytes into page buffer
	uint8_t i;
	for (i = 0; i < EEPROM_PAGE_SIZE; ++i) {
		NVM.ADDR0 = i;
		NVM.DATA0 = value;
	}
	NVM.CMD = old_cmd;
}
Ejemplo n.º 2
0
/**
 * \brief Write one byte to EEPROM using IO mapping.
 *
 * This function writes one byte to EEPROM using IO-mapped access.
 * This function will cancel all ongoing EEPROM page buffer loading
 * operations, if any.
 *
 * \param  address    EEPROM address (max EEPROM_SIZE)
 * \param  value      Byte value to write to EEPROM.
 */
void nvm_eeprom_write_byte(eeprom_addr_t address, uint8_t value)
{
	uint8_t old_cmd;

	Assert(address <= EEPROM_SIZE);
	/*  Flush buffer to make sure no unintentional data is written and load
	 *  the "Page Load" command into the command register.
	 */
	old_cmd = NVM.CMD;
	nvm_eeprom_flush_buffer();
	// Wait until NVM is ready
	nvm_wait_until_ready();
	nvm_eeprom_load_byte_to_buffer(address, value);

	// Set address to write to
	NVM.ADDR2 = 0x00;
	NVM.ADDR1 = (address >> 8) & 0xFF;
	NVM.ADDR0 = address & 0xFF;

	/*  Issue EEPROM Atomic Write (Erase&Write) command. Load command, write
	 *  the protection signature and execute command.
	 */
	NVM.CMD = NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc;
	nvm_exec();
	NVM.CMD = old_cmd;
}
Ejemplo n.º 3
0
/**
 * \brief Read buffer within the eeprom
 *
 * \param address   the address to where to read
 * \param buf       pointer to the data
 * \param len       the number of bytes to read
 */
void nvm_eeprom_read_buffer(eeprom_addr_t address, void *buf, uint16_t len)
{
	nvm_wait_until_ready();
	eeprom_enable_mapping();
	memcpy( buf,(void*)(address+MAPPED_EEPROM_START), len );
	eeprom_disable_mapping();
}
Ejemplo n.º 4
0
void debug_string(uint8_t level,const char * const sz,const uint8_t isPGM)
{
	if(level>g_log_verbosity) return;

	const char * p = sz;

	if(isPGM) {
		nvm_wait_until_ready();
		while(1) {
			const uint8_t c = nvm_flash_read_byte( p++ );
			if(c==0) break;
//			while (udi_cdc_is_tx_ready()) {}
//			udi_cdc_putc(c);
			while (usart_data_register_is_empty(USART_DEBUG) == false) {}
			usart_put(USART_DEBUG, c);
		}
		
	} else {
		while(*p) {
			while (usart_data_register_is_empty(USART_DEBUG) == false) {}
			usart_put(USART_DEBUG, *p++);
			//while (udi_cdc_is_tx_ready()) {}
			//udi_cdc_putc(*p++);

		}
	}
}
Ejemplo n.º 5
0
/**
 * \brief Erase bytes from all EEPROM pages.
 *
 * This function erases bytes from all EEPROM pages, so that every location
 * written to in the page buffer reads 0xFF.
 */
void nvm_eeprom_erase_bytes_in_all_pages(void)
{
	// Wait until NVM is ready
	nvm_wait_until_ready();

	// Issue EEPROM Erase All command
	nvm_issue_command(NVM_CMD_ERASE_EEPROM_gc);
}
Ejemplo n.º 6
0
/**
 * \brief Load single byte into temporary page buffer.
 *
 * This function loads one byte into the temporary EEPROM page buffers.
 * If memory mapped EEPROM is enabled, this function will not work.
 * Make sure that the buffer is flushed before starting to load bytes.
 * Also, if multiple bytes are loaded into the same location, they will
 * be ANDed together, thus 0x55 and 0xAA will result in 0x00 in the buffer.
 *
 * \note Only one page buffer exist, thus only one page can be loaded with
 *       data and programmed into one page. If data needs to be written to
 *       different pages, the loading and writing needs to be repeated.
 *
 * \param  byte_addr EEPROM Byte address, between 0 and EEPROM_PAGE_SIZE.
 * \param  value     Byte value to write to buffer.
 */
void nvm_eeprom_load_byte_to_buffer(uint8_t byte_addr, uint8_t value)
{
	// Wait until NVM is ready
	nvm_wait_until_ready();

	eeprom_enable_mapping();
	*(uint8_t*)(byte_addr + MAPPED_EEPROM_START) = value;
	eeprom_disable_mapping();
}
Ejemplo n.º 7
0
/** \brief Read a buffer from non-volatile RAM
 *
 * This routine reads \c count Bytes from the NVRAM source pointed
 * to by \c src to the destination buffer pointed to by \c dst.
 *
 * \param   src     the read source in the NVRAM address space
 * \param   dst     the destination buffer in program data memory space
 * \param   count   the number of Bytes to read
 *
 * \return  Nothing.
 */
void nvram_read(nvram_addr_t src, void *dst, size_t count)
{
#if XMEGA
	nvm_wait_until_ready();
	nvm_user_sig_read_buffer((flash_addr_t)(src + SENSOR_NVM_OFFSET), dst,
			count);
#elif UC3
	memcpy(dst, (void *)(src + SENSOR_NVM_BASE + SENSOR_NVM_OFFSET), count);
#endif
}
Ejemplo n.º 8
0
/**
 * \brief Flush temporary EEPROM page buffer.
 *
 * This function flushes the EEPROM page buffers. This function will cancel
 * any ongoing EEPROM page buffer loading operations, if any.
 * This function also works for memory mapped EEPROM access.
 *
 * \note An EEPROM write operations will automatically flush the buffer for you.
 * \note The function does not preserve the value of the NVM.CMD register
 */
void nvm_eeprom_flush_buffer(void)
{
	// Wait until NVM is ready
	nvm_wait_until_ready();

	// Flush EEPROM page buffer if necessary
	if ((NVM.STATUS & NVM_EELOAD_bm) != 0) {
		NVM.CMD = NVM_CMD_ERASE_EEPROM_BUFFER_gc;
		nvm_exec();
	}
}
Ejemplo n.º 9
0
/**
 * \brief Fill temporary EEPROM page buffer with value.
 *
 * This fills the the EEPROM page buffers with a given value.
 * If memory mapped EEPROM is enabled, this function will not work.
 *
 * \note Only the lower part of the address is used to address the buffer.
 *       Therefore, no address parameter is needed. In the end, the data
 *       is written to the EEPROM page given by the address parameter to the
 *       EEPROM write page operation.
 *
 * \param  value Value to copy to the page buffer.
 */
void nvm_eeprom_fill_buffer_with_value(uint8_t value)
{
	nvm_eeprom_flush_buffer();
	// Wait until NVM is ready
	nvm_wait_until_ready();
	// Load multiple bytes into page buffer
	uint8_t i;
	for (i = 0; i < EEPROM_PAGE_SIZE; ++i) {
		nvm_eeprom_load_byte_to_buffer(i, value);
	}
}
Ejemplo n.º 10
0
/**
 * \brief Load entire page into temporary EEPROM page buffer.
 *
 * This function loads an entire EEPROM page from an SRAM buffer to
 * the EEPROM page buffers. If memory mapped EEPROM is enabled, this
 * function will not work. Make sure that the buffer is flushed before
 * starting to load bytes.
 *
 * \note Only the lower part of the address is used to address the buffer.
 *       Therefore, no address parameter is needed. In the end, the data
 *       is written to the EEPROM page given by the address parameter to the
 *       EEPROM write page operation.
 *
 * \param  values   Pointer to SRAM buffer containing an entire page.
 */
void nvm_eeprom_load_page_to_buffer(const uint8_t *values)
{
	// Wait until NVM is ready
	nvm_wait_until_ready();

	// Load multiple bytes into page buffer
	uint8_t i;
	for (i = 0; i < EEPROM_PAGE_SIZE; ++i) {
		nvm_eeprom_load_byte_to_buffer(i, *values);
		++values;
	}
}
Ejemplo n.º 11
0
/**
 * \brief Read one byte from EEPROM using mapped access.
 *
 * This function reads one byte from EEPROM using mapped access.
 *
 * \param  addr       EEPROM address, between 0 and EEPROM_SIZE
 *
 *  \return  Byte value read from EEPROM.
 */
uint8_t nvm_eeprom_read_byte(eeprom_addr_t addr)
{
	uint8_t data;
	Assert(addr <= EEPROM_SIZE);

	/* Wait until NVM is ready */
	nvm_wait_until_ready();
	eeprom_enable_mapping();
	data = *(uint8_t*)(addr + MAPPED_EEPROM_START),
	eeprom_disable_mapping();
	return data;
}
Ejemplo n.º 12
0
/**
 * \brief Read a fuse byte.
 *
 * This function reads and returns the value of a given fuse byte.
 *
 * \param fuse Fuse byte to read.
 *
 * \return  Byte value of fuse.
 */
uint8_t nvm_fuses_read(enum fuse_byte_t fuse)
{
	// Wait until NVM is ready
	nvm_wait_until_ready();

	// Set address
	NVM.ADDR0 = fuse;

	// Issue READ_FUSES command
	nvm_issue_command(NVM_CMD_READ_FUSES_gc);

	return NVM.DATA0;
}
Ejemplo n.º 13
0
/**
 * \brief Read buffer within the application section
 *
 * \param address	the address to where to read
 * \param buf		pointer to the data
 * \param len		the number of bytes to read
 */
void nvm_flash_read_buffer(flash_addr_t address, void *buf, uint16_t len)
{
#if (FLASH_SIZE>0x10000)
	uint32_t opt_address = address;
#else
	uint16_t opt_address = (uint16_t)address;
#endif
	nvm_wait_until_ready();
	while ( len ) {
		*(uint8_t*)buf = nvm_flash_read_byte(opt_address);
		buf=(uint8_t*)buf+1;
		opt_address++;
		len--;
	}
}
Ejemplo n.º 14
0
/** \brief Write a buffer to non-volatile RAM
 *
 * This routine writes \c count Bytes to the NVRAM destination pointed
 * to by \c dst from the source buffer pointed to by \c src.
 *
 * \param   dst     the write destination in the NVRAM address space
 * \param   src     the source buffer in program data memory space
 * \param   count   the number of Bytes to write
 *
 * \return  Nothing.
 */
void nvram_write(nvram_addr_t dst, const void *src, size_t count)
{
#if XMEGA
	nvm_wait_until_ready();
	nvm_user_sig_write_buffer((flash_addr_t)(dst + SENSOR_NVM_OFFSET),
			src, count, true);
	/* check for blank, erase if needed */
#elif UC3
	const bool erase_page = true;
	volatile void *const flash_addr
		= (volatile void *)(dst + SENSOR_NVM_BASE + SENSOR_NVM_OFFSET);

	sysclk_enable_pbb_module(SYSCLK_FLASH_REGS);
	(void)flash_memcpy(flash_addr, src, count, erase_page);
	sysclk_disable_pbb_module(SYSCLK_FLASH_REGS);
#endif
}
Ejemplo n.º 15
0
/**
 * \brief Read one byte from EEPROM using IO mapping.
 *
 * This function reads one byte from EEPROM using IO-mapped access.
 * If memory mapped EEPROM is enabled, this function will not work.
 *
 * \param  addr       EEPROM address, between 0 and EEPROM_SIZE
 *
 *  \return  Byte value read from EEPROM.
 */
uint8_t nvm_eeprom_read_byte(eeprom_addr_t addr)
{
	Assert(addr <= EEPROM_SIZE);

	/* Wait until NVM is ready */
	nvm_wait_until_ready();

	/* Set address to read from */
	NVM.ADDR2 = 0x00;
	NVM.ADDR1 = (addr >> 8) & 0xFF;
	NVM.ADDR0 = addr & 0xFF;

	/* Issue EEPROM Read command */
	nvm_issue_command(NVM_CMD_READ_EEPROM_gc);

	return NVM.DATA0;
}
Ejemplo n.º 16
0
/**
 * \brief Erase bytes from EEPROM page.
 *
 * This function erases bytes from one EEPROM page, so that every location
 * written to in the page buffer reads 0xFF.
 *
 * \param page_addr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGE_SIZE
 */
void nvm_eeprom_erase_bytes_in_page(uint8_t page_addr)
{
	// Wait until NVM is ready
	nvm_wait_until_ready();

	// Calculate page address
	uint16_t address = (uint16_t)(page_addr * EEPROM_PAGE_SIZE);

	Assert(address <= EEPROM_SIZE);

	// Set address
	NVM.ADDR2 = 0x00;
	NVM.ADDR1 = (address >> 8) & 0xFF;
	NVM.ADDR0 = address & 0xFF;

	// Issue EEPROM Erase command
	nvm_issue_command(NVM_CMD_ERASE_EEPROM_PAGE_gc);
}
Ejemplo n.º 17
0
/**
 * \brief Load single byte into temporary page buffer.
 *
 * This function loads one byte into the temporary EEPROM page buffers.
 * If memory mapped EEPROM is enabled, this function will not work.
 * Make sure that the buffer is flushed before starting to load bytes.
 * Also, if multiple bytes are loaded into the same location, they will
 * be ANDed together, thus 0x55 and 0xAA will result in 0x00 in the buffer.
 *
 * \note Only one page buffer exist, thus only one page can be loaded with
 *       data and programmed into one page. If data needs to be written to
 *       different pages, the loading and writing needs to be repeated.
 *
 * \param  byte_addr EEPROM Byte address, between 0 and EEPROM_PAGE_SIZE.
 * \param  value     Byte value to write to buffer.
 */
void nvm_eeprom_load_byte_to_buffer(uint8_t byte_addr, uint8_t value)
{
	uint8_t old_cmd;
	old_cmd = NVM.CMD;

	// Wait until NVM is ready
	nvm_wait_until_ready();

	NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc;

	// Set address
	NVM.ADDR2 = 0x00;
	NVM.ADDR1 = 0x00;
	NVM.ADDR0 = byte_addr & 0xFF;

	// Set data, which triggers loading of EEPROM page buffer
	NVM.DATA0 = value;

	NVM.CMD = old_cmd;
}
Ejemplo n.º 18
0
int main(void)
{
   ADDR_T address = 0;
   unsigned int temp_int=0;
   unsigned char val;
   
   /* Initialization */    
   void (*funcptr)( void ) = 0x0000; // Set up function pointer to RESET vector.
   
   PMIC_SetVectorLocationToBoot();
   
   
   eeprom_disable_mapping();
   
   PROGPORT |= (1<<PROG_NO); // Enable pull-up on PROG_NO line on PROGPORT.
   
   /* Branch to bootloader or application code? */
   if( /*!(PROGPIN & (1<<PROG_NO))*/1 ) // If PROGPIN is pulled low, enter programmingmode.
   {
      initbootuart(); // Initialize UART.

      /* Main loop */
      for(;;)
      {
	 
	 val = recchar(); // Wait for command character.
	 
	 // Check autoincrement status.
	 if(val=='a')
	 {
	    sendchar('Y'); // Yes, we do autoincrement.
	 }
	 
	 // Set address (2 bytes).
	 else if(val == 'A')
	 { // NOTE: Flash addresses are given in words, not bytes.                                            
	    address = recchar();
	    address <<=  8;
	    address |= recchar(); // Read address high and low byte.
	    sendchar('\r'); // Send OK back.
	 }

	 // Set extended address (3 bytes).
	 else if(val == 'H')
	 { // NOTE: Flash addresses are given in words, not bytes.                                            
	    address = (uint32_t)recchar() << 16;
	    address |= (uint16_t)recchar() << 8;
	    address |= recchar();
	    sendchar('\r'); // Send OK back.
	 }

	 // Chip erase.
	 else if(val=='e')
	 {
	    for(address = 0; address < APP_END; address += PAGESIZE)
	    { // NOTE: Here we use address as a byte-address, not word-address, for convenience.
	       nvm_wait_until_ready();
#ifdef __ICCAVR__
#pragma diag_suppress=Pe1053 // Suppress warning for conversion from long-type address to flash ptr.
#endif
	       EraseApplicationPage( address );
#ifdef __ICCAVR__
#pragma diag_default=Pe1053 // Back to default.
#endif
	    }
	    nvm_eeprom_erase_all();
	    sendchar('\r'); // Send OK back.
	 }
	 
#ifndef REMOVE_BLOCK_SUPPORT

	 // Check block load support.
	 else if(val=='b')
	 {
	    sendchar('Y'); // Report block load supported.
	    sendchar((BLOCKSIZE>>8) & 0xFF); // MSB first.
	    sendchar(BLOCKSIZE&0xFF); // Report BLOCKSIZE (bytes).
	 }
	 
	 // Start block load.
	 else if(val=='B')
Ejemplo n.º 19
0
/**
 * \brief Erase and write specific parts of application flash section
 *
 * \param address        the address to where to write
 * \param buf            pointer to the data
 * \param len            the number of bytes to write
 * \param b_blank_check  if True then the page flash is checked before write
 *                       to run or not the erase page command.
 *
 * Set b_blank_check to false if all application flash is erased before.
 */
void nvm_flash_erase_and_write_buffer(flash_addr_t address, const void *buf,
	uint16_t len, bool b_blank_check)
{
	uint16_t w_value;
	uint16_t page_pos;
	bool b_flag_erase;
#if (FLASH_SIZE>0x10000)
	uint32_t page_address;
	uint32_t opt_address = address;
#else
	uint16_t page_address;
	uint16_t opt_address = (uint16_t)address;
#endif

	// Compute the start of the page to be modified
	page_address = opt_address-(opt_address%FLASH_PAGE_SIZE);

	// For each page
	while ( len ) {
		b_flag_erase = false;

		nvm_wait_until_ready();
		for (page_pos=0; page_pos<FLASH_PAGE_SIZE; page_pos+=2 ) {
			if (b_blank_check) {
				// Read flash to know if the erase command is mandatory
				w_value = nvm_flash_read_word(page_address);
				if (w_value!=0xFFFF) {
					b_flag_erase = true; // The page is not empty
				}
			}else{
				w_value = 0xFFFF;
			}

			// Update flash buffer
			if (len) {
				if (opt_address == page_address) {
					// The MSB of flash word must be changed
					// because the address is even
					len--;
					opt_address++;
					LSB(w_value)=*(uint8_t*)buf;
					buf=(uint8_t*)buf+1;
				}
			}
			if (len) {
				if (opt_address == (page_address+1)) {
					// The LSB of flash word must be changed
					// because the user buffer is not empty
					len--;
					opt_address++;
					MSB(w_value)=*(uint8_t*)buf;
					buf=(uint8_t*)buf+1;
				}
			}
			// Load flash buffer
			nvm_flash_load_word_to_buffer(page_address,w_value);
			page_address+=2;
		}

		// Write flash buffer
		if (b_flag_erase) {
			nvm_flash_atomic_write_app_page(page_address-FLASH_PAGE_SIZE);
		}else{
			nvm_flash_split_write_app_page(page_address-FLASH_PAGE_SIZE);
		}
	}
}