Exemple #1
0
/**
 * Test nvm_eeprom_load_byte_to_buffer(), nvm_eeprom_flush_buffer() and
 * nvm_eeprom_atomic_write_page()
 *
 * Test procedure:
 * - Erase the TEST_ATOMIC_WRITE_PAGE page.
 * - Load byte and then flush the buffer at one location.
 * - Load two more bytes at a different location.
 * - Write the page.
 * - Verify that only two bytes are written and the rest of the page is erased.
 *
 * \return STATUS_OK if test succeeded, otherwise ERR_BAD_DATA
 */
static status_code_t test_atomic_write(void)
{
	nvm_eeprom_erase_page(TEST_ATOMIC_WRITE_PAGE);

	/* Load a dummy byte and then flush the buffer to remove the byte from
	 * the buffer. The byte should not be written to the EEPROM.
	 */
	nvm_eeprom_load_byte_to_buffer(0, 55);
	nvm_eeprom_flush_buffer();

	/* Load some additional bytes */
	set_buffer(buffer, EEPROM_ERASED);
	buffer[1] = 0xaa;
	buffer[2] = 0x19;
	nvm_eeprom_load_byte_to_buffer(1, buffer[1]);
	nvm_eeprom_load_byte_to_buffer(2, buffer[2]);
	/* Erase and then write page */
	nvm_eeprom_atomic_write_page(TEST_ATOMIC_WRITE_PAGE);

	if (is_eeprom_page_equal_to_buffer(TEST_ATOMIC_WRITE_PAGE, buffer)) {
		return STATUS_OK;
	}

	return ERR_BAD_DATA;
}
/**
 * \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;
}
/**
 * \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;
}
Exemple #4
0
/**
 * \brief Test EEPROM atomic write
 *
 * This test erases test page \ref TEST_ATOMIC_WRITE_PAGE, then writes the first
 * byte in the page buffer before flushing it -- this byte should then not be
 * written to the EEPROM -- and writing different values to the two successive
 * bytes. An atomic write is then executed before the write of the latter two
 * bytes is verified.
 *
 * \param test Current test case.
 */
static void run_eeprom_atomic_write_test(const struct test_case *test)
{
	uint8_t buffer[EEPROM_PAGE_SIZE];
	bool    success;

	nvm_eeprom_erase_page(TEST_ATOMIC_WRITE_PAGE);

	/* Load a dummy byte and then flush the buffer to remove the byte from
	 * the buffer. The byte should not be written to the EEPROM.
	 */
	nvm_eeprom_load_byte_to_buffer(0, 55);
	nvm_eeprom_flush_buffer();

	/* Load some additional bytes */
	set_buffer(buffer, EEPROM_ERASED);
	buffer[1] = 0xaa;
	buffer[2] = 0x19;
	nvm_eeprom_load_byte_to_buffer(1, buffer[1]);
	nvm_eeprom_load_byte_to_buffer(2, buffer[2]);
	/* Erase and then write page */
	nvm_eeprom_atomic_write_page(TEST_ATOMIC_WRITE_PAGE);

	success = is_eeprom_page_equal_to_buffer(TEST_ATOMIC_WRITE_PAGE, buffer);
	test_assert_true(test, success,
			"Page buffer flush, byte load or atomic write failed");
}
/**
 * \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);
	}
}