summaryrefslogtreecommitdiff
path: root/eeprom_driver.c
diff options
context:
space:
mode:
authorWolfgang Draxinger <Wolfgang.Draxinger@draxit.de>2013-12-22 16:44:10 +0100
committerWolfgang Draxinger <Wolfgang.Draxinger@draxit.de>2013-12-22 16:44:10 +0100
commit217ddb1e32dcb4cde11ecca88418be428895f2dc (patch)
tree8e84c0cecc506f9da54f87d82af95f59d348b3de /eeprom_driver.c
parent3e8ce25f77700dcef050601412435950dc7dfa7b (diff)
downloadvgaedidinjector-217ddb1e32dcb4cde11ecca88418be428895f2dc.tar.gz
vgaedidinjector-217ddb1e32dcb4cde11ecca88418be428895f2dc.tar.bz2
Makefile separator errors fixed
Diffstat (limited to 'eeprom_driver.c')
-rw-r--r--eeprom_driver.c330
1 files changed, 330 insertions, 0 deletions
diff --git a/eeprom_driver.c b/eeprom_driver.c
new file mode 100644
index 0000000..cc849a6
--- /dev/null
+++ b/eeprom_driver.c
@@ -0,0 +1,330 @@
+/* This file has been prepared for Doxygen automatic documentation generation.*/
+/*! \file *********************************************************************
+ *
+ * \brief XMEGA EEPROM driver source file.
+ *
+ * This file contains the function implementations for the XMEGA EEPROM driver.
+ *
+ * The driver is not intended for size and/or speed critical code, since
+ * most functions are just a few lines of code, and the function call
+ * overhead would decrease code performance. The driver is intended for
+ * rapid prototyping and documentation purposes for getting started with
+ * the XMEGA EEPROM module.
+ *
+ * For size and/or speed critical code, it is recommended to copy the
+ * function contents directly into your application instead of making
+ * a function call.
+ *
+ * \par Application note:
+ * AVR1315: Accessing the XMEGA EEPROM
+ *
+ * \par Documentation
+ * For comprehensive code documentation, supported compilers, compiler
+ * settings and supported devices see readme.html
+ *
+ * \author
+ * Atmel Corporation: http://www.atmel.com \n
+ * Support email: avr@atmel.com
+ *
+ * $Revision: 1569 $
+ * $Date: 2008-04-22 13:03:43 +0200 (ti, 22 apr 2008) $ \n
+ *
+ * Copyright (c) 2008, Atmel Corporation All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. The name of ATMEL may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
+ * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#include "eeprom_driver.h"
+
+/*! \brief Write one byte to EEPROM using IO mapping.
+ *
+ * This function writes one byte to EEPROM using IO-mapped access.
+ * If memory mapped EEPROM is enabled, this function will not work.
+ * This functiom will cancel all ongoing EEPROM page buffer loading
+ * operations, if any.
+ *
+ * \param pageAddr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGESIZE
+ * \param byteAddr EEPROM Byte address, between 0 and EEPROM_PAGESIZE.
+ * \param value Byte value to write to EEPROM.
+ */
+void EEPROM_WriteByte( uint8_t pageAddr, uint8_t byteAddr, uint8_t value )
+{
+ /* Flush buffer to make sure no unintetional data is written and load
+ * the "Page Load" command into the command register.
+ */
+ EEPROM_FlushBuffer();
+ NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc;
+
+ /* Calculate address */
+ uint16_t address = (uint16_t)(pageAddr*EEPROM_PAGESIZE)
+ |(byteAddr & (EEPROM_PAGESIZE-1));
+
+ /* Set address to write to. */
+ NVM.ADDR0 = address & 0xFF;
+ NVM.ADDR1 = (address >> 8) & 0x1F;
+ NVM.ADDR2 = 0x00;
+
+ /* Load data to write, which triggers the loading of EEPROM page buffer. */
+ NVM.DATA0 = value;
+
+ /* 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();
+}
+
+
+/*! \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 pageAddr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGESIZE
+ * \param byteAddr EEPROM Byte address, between 0 and EEPROM_PAGESIZE.
+ *
+ * \return Byte value read from EEPROM.
+ */
+uint8_t EEPROM_ReadByte( uint8_t pageAddr, uint8_t byteAddr )
+{
+ /* Wait until NVM is not busy. */
+ EEPROM_WaitForNVM();
+
+ /* Calculate address */
+ uint16_t address = (uint16_t)(pageAddr*EEPROM_PAGESIZE)
+ |(byteAddr & (EEPROM_PAGESIZE-1));
+
+ /* Set address to read from. */
+ NVM.ADDR0 = address & 0xFF;
+ NVM.ADDR1 = (address >> 8) & 0x1F;
+ NVM.ADDR2 = 0x00;
+
+ /* Issue EEPROM Read command. */
+ NVM.CMD = NVM_CMD_READ_EEPROM_gc;
+ NVM_EXEC();
+
+ return NVM.DATA0;
+}
+
+
+/*! \brief Wait for any NVM access to finish, including EEPROM.
+ *
+ * This function is blcoking and waits for any NVM access to finish,
+ * including EEPROM. Use this function before any EEPROM accesses,
+ * if you are not certain that any previous operations are finished yet,
+ * like an EEPROM write.
+ */
+void EEPROM_WaitForNVM( void )
+{
+ do {
+ /* Block execution while waiting for the NVM to be ready. */
+ } while ((NVM.STATUS & NVM_NVMBUSY_bm) == NVM_NVMBUSY_bm);
+}
+
+
+/*! \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 The EEPROM write operations will automatically flush the buffer for you.
+ */
+void EEPROM_FlushBuffer( void )
+{
+ /* Wait until NVM is not busy. */
+ EEPROM_WaitForNVM();
+
+ /* Flush EEPROM page buffer if necessary. */
+ if ((NVM.STATUS & NVM_EELOAD_bm) != 0) {
+ NVM.CMD = NVM_CMD_ERASE_EEPROM_BUFFER_gc;
+ NVM_EXEC();
+ }
+}
+
+
+/*! \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 byteAddr EEPROM Byte address, between 0 and EEPROM_PAGESIZE.
+ * \param value Byte value to write to buffer.
+ */
+void EEPROM_LoadByte( uint8_t byteAddr, uint8_t value )
+{
+ /* Wait until NVM is not busy and prepare NVM command.*/
+ EEPROM_WaitForNVM();
+ NVM.CMD = NVM_CMD_LOAD_EEPROM_BUFFER_gc;
+
+ /* Set address. */
+ NVM.ADDR0 = byteAddr & 0xFF;
+ NVM.ADDR1 = 0x00;
+ NVM.ADDR2 = 0x00;
+
+ /* Set data, which triggers loading of EEPROM page buffer. */
+ NVM.DATA0 = value;
+}
+
+
+/*! \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 EEPROM_LoadPage( const uint8_t * values )
+{
+ /* Wait until NVM is not busy. */
+ EEPROM_WaitForNVM();
+ 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.ADDR1 = 0x00;
+ NVM.ADDR2 = 0x00;
+
+ /* Load multible bytes into page buffer. */
+ for (uint8_t i = 0; i < EEPROM_PAGESIZE; ++i) {
+ NVM.ADDR0 = i;
+ NVM.DATA0 = *values;
+ ++values;
+ }
+}
+
+/*! \brief Write already loaded page into EEPROM.
+ *
+ * This function writes the contents of an already loaded EEPROM page
+ * buffer into EEPROM memory.
+ *
+ * As this is an atomic write, the page in EEPROM will be erased
+ * automatically before writing. Note that only the page buffer locations
+ * that have been loaded will be used when writing to EEPROM. Page buffer
+ * locations that have not been loaded will be left untouched in EEPROM.
+ *
+ * \param pageAddr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGESIZE
+ */
+void EEPROM_AtomicWritePage( uint8_t pageAddr )
+{
+ /* Wait until NVM is not busy. */
+ EEPROM_WaitForNVM();
+
+ /* Calculate page address */
+ uint16_t address = (uint16_t)(pageAddr*EEPROM_PAGESIZE);
+
+ /* Set address. */
+ NVM.ADDR0 = address & 0xFF;
+ NVM.ADDR1 = (address >> 8) & 0x1F;
+ NVM.ADDR2 = 0x00;
+
+ /* Issue EEPROM Atomic Write (Erase&Write) command. */
+ NVM.CMD = NVM_CMD_ERASE_WRITE_EEPROM_PAGE_gc;
+ NVM_EXEC();
+}
+
+
+/*! \brief Erase EEPROM page.
+ *
+ * This function erases one EEPROM page, so that every location reads 0xFF.
+ *
+ * \param pageAddr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGESIZE
+ */
+void EEPROM_ErasePage( uint8_t pageAddr )
+{
+ /* Wait until NVM is not busy. */
+ EEPROM_WaitForNVM();
+
+ /* Calculate page address */
+ uint16_t address = (uint16_t)(pageAddr*EEPROM_PAGESIZE);
+
+ /* Set address. */
+ NVM.ADDR0 = address & 0xFF;
+ NVM.ADDR1 = (address >> 8) & 0x1F;
+ NVM.ADDR2 = 0x00;
+
+ /* Issue EEPROM Erase command. */
+ NVM.CMD = NVM_CMD_ERASE_EEPROM_PAGE_gc;
+ NVM_EXEC();
+}
+
+
+/*! \brief Write (without erasing) EEPROM page.
+ *
+ * This function writes the contents of an already loaded EEPROM page
+ * buffer into EEPROM memory.
+ *
+ * As this is a split write, the page in EEPROM will _not_ be erased
+ * before writing.
+ *
+ * \param pageAddr EEPROM Page address, between 0 and EEPROM_SIZE/EEPROM_PAGESIZE
+ */
+void EEPROM_SplitWritePage( uint8_t pageAddr )
+{
+ /* Wait until NVM is not busy. */
+ EEPROM_WaitForNVM();
+
+ /* Calculate page address */
+ uint16_t address = (uint16_t)(pageAddr*EEPROM_PAGESIZE);
+
+ /* Set address. */
+ NVM.ADDR0 = address & 0xFF;
+ NVM.ADDR1 = (address >> 8) & 0x1F;
+ NVM.ADDR2 = 0x00;
+
+ /* Issue EEPROM Split Write command. */
+ NVM.CMD = NVM_CMD_WRITE_EEPROM_PAGE_gc;
+ NVM_EXEC();
+}
+
+/*! \brief Erase entire EEPROM memory.
+ *
+ * This function erases the entire EEPROM memory block to 0xFF.
+ */
+void EEPROM_EraseAll( void )
+{
+ /* Wait until NVM is not busy. */
+ EEPROM_WaitForNVM();
+
+ /* Issue EEPROM Erase All command. */
+ NVM.CMD = NVM_CMD_ERASE_EEPROM_gc;
+ NVM_EXEC();
+}
+