1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156 |
- //*****************************************************************************
- //
- // eeprom.c - Driver for programming the on-chip EEPROM.
- //
- // Copyright (c) 2010-2020 Texas Instruments Incorporated. All rights reserved.
- // Software License Agreement
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions
- // are met:
- //
- // Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- //
- // 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.
- //
- // Neither the name of Texas Instruments Incorporated nor the names of
- // its contributors may be used to endorse or promote products derived
- // from this software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "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 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- // OWNER OR CONTRIBUTORS 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.
- //
- // This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library.
- //
- //*****************************************************************************
- #include <stdbool.h>
- #include <stdint.h>
- #include "inc/hw_eeprom.h"
- #include "inc/hw_flash.h"
- #include "inc/hw_ints.h"
- #include "inc/hw_sysctl.h"
- #include "inc/hw_types.h"
- #include "driverlib/debug.h"
- #include "driverlib/flash.h"
- #include "driverlib/interrupt.h"
- #include "driverlib/sysctl.h"
- #include "driverlib/eeprom.h"
- //*****************************************************************************
- //
- //! \addtogroup eeprom_api
- //! @{
- //
- //*****************************************************************************
- //*****************************************************************************
- //
- // Useful macros to extract the number of EEPROM blocks available on the target
- // device and the total EEPROM storage in bytes from the EESIZE register.
- //
- //*****************************************************************************
- #define BLOCKS_FROM_EESIZE(x) (((x) & EEPROM_EESIZE_BLKCNT_M) >> \
- EEPROM_EESIZE_BLKCNT_S)
- #define SIZE_FROM_EESIZE(x) ((((x) & EEPROM_EESIZE_WORDCNT_M) >> \
- EEPROM_EESIZE_WORDCNT_S) * 4)
- //*****************************************************************************
- //
- // Useful macro to extract the offset from a linear address.
- //
- //*****************************************************************************
- #define OFFSET_FROM_ADDR(x) (((x) >> 2) & 0x0F)
- //*****************************************************************************
- //
- // The key value required to initiate a mass erase.
- //
- //*****************************************************************************
- #define EEPROM_MASS_ERASE_KEY ((uint32_t)0xE37B << EEPROM_EEDBGME_KEY_S)
- //*****************************************************************************
- //
- // This function implements a workaround for a bug in Blizzard rev A silicon.
- // It ensures that only the 1KB flash sector containing a given EEPROM address
- // is erased if an erase/copy operation is required as a result of a following
- // EEPROM write.
- //
- //*****************************************************************************
- static void
- _EEPROMSectorMaskSet(uint32_t ui32Address)
- {
- uint32_t ui32Mask;
- //
- // Determine which page contains the passed EEPROM address. The 2KB EEPROM
- // is implemented in 16KB of flash with each 1KB sector of flash holding
- // values for 32 consecutive EEPROM words (or 128 bytes).
- //
- ui32Mask = ~(1 << (ui32Address >> 7));
- SysCtlDelay(10);
- HWREG(0x400FD0FC) = 3;
- SysCtlDelay(10);
- HWREG(0x400AE2C0) = ui32Mask;
- SysCtlDelay(10);
- HWREG(0x400FD0FC) = 0;
- SysCtlDelay(10);
- }
- //*****************************************************************************
- //
- // Clear the FSM sector erase mask to ensure that any following main array
- // flash erase operations operate as expected.
- //
- //*****************************************************************************
- static void
- _EEPROMSectorMaskClear(void)
- {
- SysCtlDelay(10);
- HWREG(0x400FD0FC) = 3;
- SysCtlDelay(10);
- HWREG(0x400AE2C0) = 0;
- SysCtlDelay(10);
- HWREG(0x400FD0FC) = 0;
- SysCtlDelay(10);
- }
- //*****************************************************************************
- //
- // Block until the EEPROM peripheral is not busy.
- //
- //*****************************************************************************
- static void
- _EEPROMWaitForDone(void)
- {
- //
- // Is the EEPROM still busy?
- //
- while(HWREG(EEPROM_EEDONE) & EEPROM_EEDONE_WORKING)
- {
- //
- // Spin while EEPROM is busy.
- //
- }
- }
- //*****************************************************************************
- //
- //! Performs any necessary recovery in case of power failures during write.
- //!
- //! This function \b must be called after SysCtlPeripheralEnable() and before
- //! the EEPROM is accessed. It is used to check for errors in the EEPROM state
- //! such as from power failure during a previous write operation. The function
- //! detects these errors and performs as much recovery as possible.
- //!
- //! If \b EEPROM_INIT_ERROR is returned, the EEPROM was unable to recover its
- //! state. If power is stable when this occurs, this indicates a fatal
- //! error and is likely an indication that the EEPROM memory has exceeded its
- //! specified lifetime write/erase specification. If the supply voltage is
- //! unstable when this return code is observed, retrying the operation once the
- //! voltage is stabilized may clear the error.
- //!
- //! Failure to call this function after a reset may lead to incorrect operation
- //! or permanent data loss if the EEPROM is later written.
- //!
- //! \return Returns \b EEPROM_INIT_OK if no errors were detected or \b
- //! EEPROM_INIT_ERROR if the EEPROM peripheral cannot currently recover from
- //! an interrupted write or erase operation.
- //
- //*****************************************************************************
- uint32_t
- EEPROMInit(void)
- {
- uint32_t ui32Status;
- //
- // Insert a small delay (6 cycles + call overhead) to guard against the
- // possibility that this function is called immediately after the EEPROM
- // peripheral is enabled. Without this delay, there is a slight chance
- // that the first EEPROM register read will fault if you are using a
- // compiler with a ridiculously good optimizer!
- //
- SysCtlDelay(2);
- //
- // Make sure the EEPROM has finished any ongoing processing.
- //
- _EEPROMWaitForDone();
- //
- // Read the EESUPP register to see if any errors have been reported.
- //
- ui32Status = HWREG(EEPROM_EESUPP);
- //
- // Did an error of some sort occur during initialization?
- //
- if(ui32Status & (EEPROM_EESUPP_PRETRY | EEPROM_EESUPP_ERETRY))
- {
- return(EEPROM_INIT_ERROR);
- }
- //
- // Perform a second EEPROM reset.
- //
- SysCtlPeripheralReset(SYSCTL_PERIPH_EEPROM0);
- //
- // Wait for the EEPROM to complete its reset processing once again.
- //
- SysCtlDelay(2);
- _EEPROMWaitForDone();
- //
- // Read EESUPP once again to determine if any error occurred.
- //
- ui32Status = HWREG(EEPROM_EESUPP);
- //
- // Was an error reported following the second reset?
- //
- if(ui32Status & (EEPROM_EESUPP_PRETRY | EEPROM_EESUPP_ERETRY))
- {
- return(EEPROM_INIT_ERROR);
- }
- //
- // The EEPROM does not indicate that any error occurred.
- //
- return(EEPROM_INIT_OK);
- }
- //*****************************************************************************
- //
- //! Determines the size of the EEPROM.
- //!
- //! This function returns the size of the EEPROM in bytes.
- //!
- //! \return Returns the total number of bytes in the EEPROM.
- //
- //*****************************************************************************
- uint32_t
- EEPROMSizeGet(void)
- {
- //
- // Return the size of the EEPROM in bytes.
- //
- return(SIZE_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
- }
- //*****************************************************************************
- //
- //! Determines the number of blocks in the EEPROM.
- //!
- //! This function may be called to determine the number of blocks in the
- //! EEPROM. Each block is the same size and the number of bytes of storage
- //! contained in a block may be determined by dividing the size of the device,
- //! obtained via a call to the EEPROMSizeGet() function, by the number of
- //! blocks returned by this function.
- //!
- //! \return Returns the total number of blocks in the device EEPROM.
- //
- //*****************************************************************************
- uint32_t
- EEPROMBlockCountGet(void)
- {
- //
- // Extract the number of blocks and return it to the caller.
- //
- #ifdef EEPROM_SIZE_LIMIT
- //
- // If a size limit has been specified, fake the number of blocks to match.
- //
- return(EEPROM_SIZE_LIMIT / 48);
- #else
- //
- // Return the actual number of blocks supported by the hardware.
- //
- return(BLOCKS_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
- #endif
- }
- //*****************************************************************************
- //
- //! Reads data from the EEPROM.
- //!
- //! \param pui32Data is a pointer to storage for the data read from the EEPROM.
- //! This pointer must point to at least \e ui32Count bytes of available memory.
- //! \param ui32Address is the byte address within the EEPROM from which data is
- //! to be read. This value must be a multiple of 4.
- //! \param ui32Count is the number of bytes of data to read from the EEPROM.
- //! This value must be a multiple of 4.
- //!
- //! This function may be called to read a number of words of data from a
- //! word-aligned address within the EEPROM. Data read is copied into the
- //! buffer pointed to by the \e pui32Data parameter.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- EEPROMRead(uint32_t *pui32Data, uint32_t ui32Address, uint32_t ui32Count)
- {
- //
- // Check parameters in a debug build.
- //
- ASSERT(pui32Data);
- ASSERT(ui32Address < SIZE_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
- ASSERT((ui32Address + ui32Count) <=
- SIZE_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
- ASSERT((ui32Address & 3) == 0);
- ASSERT((ui32Count & 3) == 0);
- //
- // Set the block and offset appropriately to read the first word.
- //
- HWREG(EEPROM_EEBLOCK) = EEPROMBlockFromAddr(ui32Address);
- HWREG(EEPROM_EEOFFSET) = OFFSET_FROM_ADDR(ui32Address);
- //
- // Convert the byte count to a word count.
- //
- ui32Count /= 4;
- //
- // Read each word in turn.
- //
- while(ui32Count)
- {
- //
- // Read the next word through the autoincrementing register.
- //
- *pui32Data = HWREG(EEPROM_EERDWRINC);
- //
- // Move on to the next word.
- //
- pui32Data++;
- ui32Count--;
- //
- // Do we need to move to the next block? This is the case if the
- // offset register has just wrapped back to 0. Note that we only
- // write the block register if we have more data to read. If this
- // register is written, the hardware expects a read or write operation
- // next. If a mass erase is requested instead, the mass erase will
- // fail.
- //
- if(ui32Count && (HWREG(EEPROM_EEOFFSET) == 0))
- {
- HWREG(EEPROM_EEBLOCK) += 1;
- }
- }
- }
- //*****************************************************************************
- //
- //! Writes data to the EEPROM.
- //!
- //! \param pui32Data points to the first word of data to write to the EEPROM.
- //! \param ui32Address defines the byte address within the EEPROM that the data
- //! is to be written to. This value must be a multiple of 4.
- //! \param ui32Count defines the number of bytes of data that is to be written.
- //! This value must be a multiple of 4.
- //!
- //! This function may be called to write data into the EEPROM at a given
- //! word-aligned address. The call is synchronous and returns only after
- //! all data has been written or an error occurs.
- //!
- //! \return Returns 0 on success or non-zero values on failure. Failure codes
- //! are logical OR combinations of \b EEPROM_RC_WRBUSY, \b EEPROM_RC_NOPERM,
- //! \b EEPROM_RC_WKCOPY, \b EEPROM_RC_WKERASE, and \b EEPROM_RC_WORKING.
- //
- //*****************************************************************************
- uint32_t
- EEPROMProgram(uint32_t *pui32Data, uint32_t ui32Address, uint32_t ui32Count)
- {
- uint32_t ui32Status;
- //
- // Check parameters in a debug build.
- //
- ASSERT(pui32Data);
- ASSERT(ui32Address < SIZE_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
- ASSERT((ui32Address + ui32Count) <=
- SIZE_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
- ASSERT((ui32Address & 3) == 0);
- ASSERT((ui32Count & 3) == 0);
- //
- // Make sure the EEPROM is idle before we start.
- //
- do
- {
- //
- // Read the status.
- //
- ui32Status = HWREG(EEPROM_EEDONE);
- }
- while(ui32Status & EEPROM_EEDONE_WORKING);
- //
- // Set the block and offset appropriately to program the first word.
- //
- HWREG(EEPROM_EEBLOCK) = EEPROMBlockFromAddr(ui32Address);
- HWREG(EEPROM_EEOFFSET) = OFFSET_FROM_ADDR(ui32Address);
- //
- // Convert the byte count to a word count.
- //
- ui32Count /= 4;
- //
- // Write each word in turn.
- //
- while(ui32Count)
- {
- //
- // This is a workaround for a silicon problem on Blizzard rev A. We
- // need to do this before every word write to ensure that we don't
- // have problems in multi-word writes that span multiple flash sectors.
- //
- if(CLASS_IS_TM4C123 && REVISION_IS_A0)
- {
- _EEPROMSectorMaskSet(ui32Address);
- }
- //
- // Write the next word through the autoincrementing register.
- //
- HWREG(EEPROM_EERDWRINC) = *pui32Data;
- //
- // Wait a few cycles. In some cases, the WRBUSY bit is not set
- // immediately and this prevents us from dropping through the polling
- // loop before the bit is set.
- //
- SysCtlDelay(10);
- //
- // Wait for the write to complete.
- //
- do
- {
- //
- // Read the status.
- //
- ui32Status = HWREG(EEPROM_EEDONE);
- }
- while(ui32Status & EEPROM_EEDONE_WORKING);
- //
- // Make sure we completed the write without errors. Note that we
- // must check this per-word because write permission can be set per
- // block resulting in only a section of the write not being performed.
- //
- if(ui32Status & EEPROM_EEDONE_NOPERM)
- {
- //
- // An error was reported that would prevent the values from
- // being written correctly.
- //
- if(CLASS_IS_TM4C123 && REVISION_IS_A0)
- {
- _EEPROMSectorMaskClear();
- }
- return(ui32Status);
- }
- //
- // Move on to the next word.
- //
- pui32Data++;
- ui32Count--;
- //
- // Do we need to move to the next block? This is the case if the
- // offset register has just wrapped back to 0. Note that we only
- // write the block register if we have more data to read. If this
- // register is written, the hardware expects a read or write operation
- // next. If a mass erase is requested instead, the mass erase will
- // fail.
- //
- if(ui32Count && (HWREG(EEPROM_EEOFFSET) == 0))
- {
- HWREG(EEPROM_EEBLOCK) += 1;
- }
- }
- //
- // Clear the sector protection bits to prevent possible problems when
- // programming the main flash array later.
- //
- if(CLASS_IS_TM4C123 && REVISION_IS_A0)
- {
- _EEPROMSectorMaskClear();
- }
- //
- // Return the current status to the caller.
- //
- return(HWREG(EEPROM_EEDONE));
- }
- //*****************************************************************************
- //
- //! Writes a word to the EEPROM.
- //!
- //! \param ui32Data is the word to write to the EEPROM.
- //! \param ui32Address defines the byte address within the EEPROM to which the
- //! data is to be written. This value must be a multiple of 4.
- //!
- //! This function is intended to allow EEPROM programming under interrupt
- //! control. It may be called to start the process of writing a single word of
- //! data into the EEPROM at a given word-aligned address. The call is
- //! asynchronous and returns immediately without waiting for the write to
- //! complete. Completion of the operation is signaled by means of an
- //! interrupt from the EEPROM module. The EEPROM peripheral shares a single
- //! interrupt vector with the flash memory subsystem, \b INT_FLASH.
- //!
- //! \return Returns status and error information in the form of a logical OR
- //! combinations of \b EEPROM_RC_WRBUSY, \b EEPROM_RC_NOPERM,
- //! \b EEPROM_RC_WKCOPY, \b EEPROM_RC_WKERASE and \b EEPROM_RC_WORKING. Flags
- //! \b EEPROM_RC_WKCOPY, \b EEPROM_RC_WKERASE, and \b EEPROM_RC_WORKING are
- //! expected in normal operation and do not indicate an error.
- //
- //*****************************************************************************
- uint32_t
- EEPROMProgramNonBlocking(uint32_t ui32Data, uint32_t ui32Address)
- {
- //
- // Check parameters in a debug build.
- //
- ASSERT(ui32Address < SIZE_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
- ASSERT((ui32Address & 3) == 0);
- //
- // This is a workaround for a silicon problem on Blizzard rev A.
- //
- if(CLASS_IS_TM4C123 && REVISION_IS_A0)
- {
- _EEPROMSectorMaskSet(ui32Address);
- }
- //
- // Set the block and offset appropriately to program the desired word.
- //
- HWREG(EEPROM_EEBLOCK) = EEPROMBlockFromAddr(ui32Address);
- HWREG(EEPROM_EEOFFSET) = OFFSET_FROM_ADDR(ui32Address);
- //
- // Write the new word using the auto-incrementing register just in case
- // the caller wants to write follow-on words using direct register access
- //
- HWREG(EEPROM_EERDWRINC) = ui32Data;
- //
- // Return the current status to the caller.
- //
- return(HWREG(EEPROM_EEDONE));
- }
- //*****************************************************************************
- //
- //! Erases the EEPROM and returns it to the factory default condition.
- //!
- //! This function completely erases the EEPROM and removes any and
- //! all access protection on its blocks, leaving the device in the factory
- //! default condition. After this operation, all EEPROM words contain the
- //! value 0xFFFFFFFF and all blocks are accessible for both read and write
- //! operations in all CPU modes. No passwords are active.
- //!
- //! The function is synchronous and does not return until the erase operation
- //! has completed.
- //!
- //! \return Returns 0 on success or non-zero values on failure. Failure codes
- //! are logical OR combinations of \b EEPROM_RC_WRBUSY, \b EEPROM_RC_NOPERM,
- //! \b EEPROM_RC_WKCOPY, \b EEPROM_RC_WKERASE, and \b EEPROM_RC_WORKING.
- //
- //*****************************************************************************
- uint32_t
- EEPROMMassErase(void)
- {
- //
- // This is a workaround for a silicon problem on Blizzard rev A.
- //
- if(CLASS_IS_TM4C123 && REVISION_IS_A0)
- {
- _EEPROMSectorMaskClear();
- }
- //
- // Start the mass erase processing
- //
- HWREG(EEPROM_EEDBGME) = EEPROM_MASS_ERASE_KEY | EEPROM_EEDBGME_ME;
- //
- // Wait for completion.
- //
- _EEPROMWaitForDone();
- //
- // Reset the peripheral. This is required so that all protection
- // mechanisms and passwords are reset now that the EEPROM data has been
- // scrubbed.
- //
- SysCtlPeripheralReset(SYSCTL_PERIPH_EEPROM0);
- //
- // Wait for completion again.
- //
- SysCtlDelay(2);
- _EEPROMWaitForDone();
- //
- // Pass any error codes back to the caller.
- //
- return(HWREG(EEPROM_EEDONE));
- }
- //*****************************************************************************
- //
- //! Returns the current protection level for an EEPROM block.
- //!
- //! \param ui32Block is the block number for which the protection level is to
- //! be queried.
- //!
- //! This function returns the current protection settings for a given
- //! EEPROM block. If block 0 is currently locked, it must be unlocked prior
- //! to calling this function to query the protection setting for other blocks.
- //!
- //! \return Returns one of \b EEPROM_PROT_RW_LRO_URW, \b EEPROM_PROT_NA_LNA_URW
- //! or \b EEPROM_PROT_RO_LNA_URO optionally OR-ed with
- //! \b EEPROM_PROT_SUPERVISOR_ONLY.
- //
- //*****************************************************************************
- uint32_t
- EEPROMBlockProtectGet(uint32_t ui32Block)
- {
- //
- // Parameter validity check.
- //
- ASSERT(ui32Block < BLOCKS_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
- //
- // Set the current block.
- //
- HWREG(EEPROM_EEBLOCK) = ui32Block;
- //
- // Return the protection flags for this block.
- //
- return(HWREG(EEPROM_EEPROT));
- }
- //*****************************************************************************
- //
- //! Set the current protection options for an EEPROM block.
- //!
- //! \param ui32Block is the block number for which the protection options are
- //! to be set.
- //! \param ui32Protect consists of one of the values \b EEPROM_PROT_RW_LRO_URW,
- //! \b EEPROM_PROT_NA_LNA_URW or \b EEPROM_PROT_RO_LNA_URO optionally ORed with
- //! \b EEPROM_PROT_SUPERVISOR_ONLY.
- //!
- //! This function sets the protection settings for a given EEPROM block
- //! assuming no protection settings have previously been written. Note that
- //! protection settings applied to block 0 have special meaning and control
- //! access to the EEPROM peripheral as a whole. Protection settings applied to
- //! blocks numbered 1 and above are layered above any protection set on block 0
- //! such that the effective protection on each block is the logical OR of the
- //! protection flags set for block 0 and for the target block. This protocol
- //! allows global protection options to be set for the whole device via block
- //! 0 and more restrictive protection settings to be set on a block-by-block
- //! basis.
- //!
- //! The protection flags indicate access permissions as follow:
- //!
- //! \b EEPROM_PROT_SUPERVISOR_ONLY restricts access to the block to threads
- //! running in supervisor mode. If clear, both user and supervisor threads
- //! can access the block.
- //!
- //! \b EEPROM_PROT_RW_LRO_URW provides read/write access to the block if no
- //! password is set or if a password is set and the block is unlocked. If the
- //! block is locked, only read access is permitted.
- //!
- //! \b EEPROM_PROT_NA_LNA_URW provides neither read nor write access unless
- //! a password is set and the block is unlocked. If the block is unlocked,
- //! both read and write access are permitted.
- //!
- //! \b EEPROM_PROT_RO_LNA_URO provides read access to the block if no password
- //! is set or if a password is set and the block is unlocked. If the block is
- //! password protected and locked, neither read nor write access is permitted.
- //!
- //! \return Returns a logical OR combination of \b EEPROM_RC_WRBUSY, \b
- //! EEPROM_RC_NOPERM, \b EEPROM_RC_WKCOPY, \b EEPROM_RC_WKERASE, and \b
- //! EEPROM_RC_WORKING to indicate status and error conditions.
- //
- //*****************************************************************************
- uint32_t
- EEPROMBlockProtectSet(uint32_t ui32Block, uint32_t ui32Protect)
- {
- //
- // Parameter validity check.
- //
- ASSERT(ui32Block < BLOCKS_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
- //
- // Set the current block.
- //
- HWREG(EEPROM_EEBLOCK) = ui32Block;
- //
- // Set the protection options for this block.
- //
- HWREG(EEPROM_EEPROT) = ui32Protect;
- //
- // Wait for the write to complete.
- //
- while(HWREG(EEPROM_EEDONE) & EEPROM_EEDONE_WORKING)
- {
- //
- // Still working.
- //
- }
- //
- // Pass any error codes back to the caller.
- //
- return(HWREG(EEPROM_EEDONE));
- }
- //*****************************************************************************
- //
- //! Sets the password used to protect an EEPROM block.
- //!
- //! \param ui32Block is the EEPROM block number for which the password is to be
- //! set.
- //! \param pui32Password points to an array of uint32_t values comprising
- //! the password to set. Each element may be any 32-bit value other than
- //! 0xFFFFFFFF. This array must contain the number of elements given by the
- //! \e ui32Count parameter.
- //! \param ui32Count provides the number of uint32_ts in the \e ui32Password.
- //! Valid values are 1, 2 and 3.
- //!
- //! This function allows the password used to unlock an EEPROM block to be
- //! set. Valid passwords may be either 32, 64 or 96 bits comprising words
- //! with any value other than 0xFFFFFFFF. The password may only be set once.
- //! Any further attempts to set the password result in an error. Once the
- //! password is set, the block remains unlocked until EEPROMBlockLock() is
- //! called for that block or block 0, or a reset occurs.
- //!
- //! If a password is set on block 0, this affects locking of the peripheral as
- //! a whole. When block 0 is locked, all other EEPROM blocks are inaccessible
- //! until block 0 is unlocked. Once block 0 is unlocked, other blocks
- //! become accessible according to any passwords set on those blocks and the
- //! protection set for that block via a call to EEPROMBlockProtectSet().
- //!
- //! \return Returns a logical OR combination of \b EEPROM_RC_WRBUSY, \b
- //! EEPROM_RC_NOPERM, \b EEPROM_RC_WKCOPY, \b EEPROM_RC_WKERASE, and \b
- //! EEPROM_RC_WORKING to indicate status and error conditions.
- //
- //*****************************************************************************
- uint32_t
- EEPROMBlockPasswordSet(uint32_t ui32Block, uint32_t *pui32Password,
- uint32_t ui32Count)
- {
- uint32_t ui32Reg;
- //
- // Check parameters in a debug build.
- //
- ASSERT(pui32Password);
- ASSERT(ui32Block < BLOCKS_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
- ASSERT(ui32Count <= 3);
- //
- // Set the block number whose password we are about to write.
- //
- HWREG(EEPROM_EEBLOCK) = ui32Block;
- //
- // Start with the first password word.
- //
- ui32Reg = EEPROM_EEPASS0;
- //
- // Write the password.
- //
- while(ui32Count)
- {
- //
- // Start the process of writing the password.
- //
- HWREG(ui32Reg) = *pui32Password;
- //
- // Update values in preparation for writing the next word.
- //
- pui32Password++;
- ui32Reg += 4;
- ui32Count--;
- //
- // Wait for the last word write to complete or an error to be reported.
- //
- while(HWREG(EEPROM_EEDONE) & EEPROM_EEDONE_WORKING)
- {
- //
- // Still working.
- //
- }
- }
- //
- // Return the final write status.
- //
- return(HWREG(EEPROM_EEDONE));
- }
- //*****************************************************************************
- //
- //! Locks a password-protected EEPROM block.
- //!
- //! \param ui32Block is the EEPROM block number which is to be locked.
- //!
- //! This function locks an EEPROM block that has previously been protected by
- //! writing a password. Access to the block once it is locked is determined
- //! by the protection settings applied via a previous call to the
- //! EEPROMBlockProtectSet() function. If no password has previously been set
- //! for the block, this function has no effect.
- //!
- //! Locking block 0 has the effect of making all other blocks in the EEPROM
- //! inaccessible.
- //!
- //! \return Returns the lock state for the block on exit, 1 if unlocked (as
- //! would be the case if no password was set) or 0 if locked.
- //!
- //*****************************************************************************
- uint32_t
- EEPROMBlockLock(uint32_t ui32Block)
- {
- //
- // Check parameters in a debug build.
- //
- ASSERT(ui32Block < BLOCKS_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
- //
- // Select the block we are going to lock.
- //
- HWREG(EEPROM_EEBLOCK) = ui32Block;
- //
- // Lock the block.
- //
- HWREG(EEPROM_EEUNLOCK) = 0xFFFFFFFF;
- //
- // Return the current lock state.
- //
- return(HWREG(EEPROM_EEUNLOCK));
- }
- //*****************************************************************************
- //
- //! Unlocks a password-protected EEPROM block.
- //!
- //! \param ui32Block is the EEPROM block number which is to be unlocked.
- //! \param pui32Password points to an array of uint32_t values containing
- //! the password for the block. Each element must match the password
- //! originally set via a call to EEPROMBlockPasswordSet().
- //! \param ui32Count provides the number of elements in the \e pui32Password
- //! array and must match the value originally passed to
- //! EEPROMBlockPasswordSet(). Valid values are 1, 2 and 3.
- //!
- //! This function unlocks an EEPROM block that has previously been protected by
- //! writing a password. Access to the block once it is unlocked is determined
- //! by the protection settings applied via a previous call to the
- //! EEPROMBlockProtectSet() function.
- //!
- //! To successfully unlock an EEPROM block, the password provided must match
- //! the password provided on the original call to EEPROMBlockPasswordSet(). If
- //! an incorrect password is provided, the block remains locked.
- //!
- //! Unlocking block 0 has the effect of making all other blocks in the device
- //! accessible according to their own access protection settings. When block
- //! 0 is locked, all other EEPROM blocks are inaccessible.
- //!
- //! \return Returns the lock state for the block on exit, 1 if unlocked or 0 if
- //! locked.
- //!
- //*****************************************************************************
- uint32_t
- EEPROMBlockUnlock(uint32_t ui32Block, uint32_t *pui32Password,
- uint32_t ui32Count)
- {
- //
- // Check parameters in a debug build.
- //
- ASSERT(pui32Password);
- ASSERT(ui32Block < BLOCKS_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
- ASSERT(ui32Count <= 3);
- //
- // Set the block that we are trying to unlock.
- //
- HWREG(EEPROM_EEBLOCK) = ui32Block;
- //
- // Write the unlock register with 0xFFFFFFFF to reset the unlock
- // sequence just in case a short password was previously used to try to
- // unlock the block.
- //
- HWREG(EEPROM_EEUNLOCK) = 0xFFFFFFFF;
- //
- // We need to write the password words in the opposite order when unlocking
- // compared to locking so start at the end of the array.
- //
- pui32Password += (ui32Count - 1);
- //
- // Write the supplied password to unlock the block.
- //
- while(ui32Count)
- {
- HWREG(EEPROM_EEUNLOCK) = *pui32Password--;
- ui32Count--;
- }
- //
- // Let the caller know if their password worked.
- //
- return(HWREG(EEPROM_EEUNLOCK));
- }
- //*****************************************************************************
- //
- //! Hides an EEPROM block until the next reset.
- //!
- //! \param ui32Block is the EEPROM block number which is to be hidden.
- //!
- //! This function hides an EEPROM block other than block 0. Once hidden, a
- //! block is completely inaccessible until the next reset. This mechanism
- //! allows initialization code to have access to data which is to be hidden
- //! from the rest of the application. Unlike applications using passwords, an
- //! application making using of block hiding need not contain any embedded
- //! passwords which could be found through disassembly.
- //!
- //! \return None.
- //!
- //*****************************************************************************
- void
- EEPROMBlockHide(uint32_t ui32Block)
- {
- //
- // Check parameters in a debug build.
- //
- ASSERT(!ui32Block);
- ASSERT(ui32Block < BLOCKS_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
- //
- // Hide the requested block.
- //
- HWREG(EEPROM_EEHIDE) = (1 << ui32Block);
- }
- //*****************************************************************************
- //
- //! Enables the EEPROM interrupt.
- //!
- //! \param ui32IntFlags indicates which EEPROM interrupt source to enable.
- //! This must be \b EEPROM_INT_PROGRAM currently.
- //!
- //! This function enables the EEPROM interrupt. When enabled, an interrupt
- //! is generated when any EEPROM write or erase operation completes. The
- //! EEPROM peripheral shares a single interrupt vector with the flash memory
- //! subsystem, \b INT_FLASH. This function is provided as a convenience but
- //! the EEPROM interrupt can also be enabled using a call to FlashIntEnable()
- //! passing FLASH_INT_EEPROM in the \e ui32IntFlags parameter.
- //!
- //! \return None.
- //!
- //*****************************************************************************
- void
- EEPROMIntEnable(uint32_t ui32IntFlags)
- {
- //
- // Look for valid interrupt sources.
- //
- ASSERT(ui32IntFlags == EEPROM_INT_PROGRAM);
- //
- // Enable interrupts from the EEPROM module.
- //
- HWREG(EEPROM_EEINT) |= EEPROM_EEINT_INT;
- //
- // Enable the EEPROM interrupt in the flash controller module.
- //
- HWREG(FLASH_FCIM) |= FLASH_FCRIS_ERIS;
- }
- //*****************************************************************************
- //
- //! Disables the EEPROM interrupt.
- //!
- //! \param ui32IntFlags indicates which EEPROM interrupt source to disable.
- //! This must be \b EEPROM_INT_PROGRAM currently.
- //!
- //! This function disables the EEPROM interrupt and prevents calls to the
- //! interrupt vector when any EEPROM write or erase operation completes. The
- //! EEPROM peripheral shares a single interrupt vector with the flash memory
- //! subsystem, \b INT_FLASH. This function is provided as a convenience but
- //! the EEPROM interrupt can also be disabled using a call to FlashIntDisable()
- //! passing FLASH_INT_EEPROM in the \e ui32IntFlags parameter.
- //!
- //! \return None.
- //!
- //*****************************************************************************
- void
- EEPROMIntDisable(uint32_t ui32IntFlags)
- {
- //
- // Look for valid interrupt sources.
- //
- ASSERT(ui32IntFlags == EEPROM_INT_PROGRAM);
- //
- // Disable the EEPROM interrupt in the flash controller module.
- //
- HWREG(FLASH_FCIM) &= ~FLASH_FCIM_EMASK;
- //
- // Disable interrupts from the EEPROM module.
- //
- HWREG(EEPROM_EEINT) &= ~EEPROM_EEINT_INT;
- }
- //*****************************************************************************
- //
- //! Reports the state of the EEPROM interrupt.
- //!
- //! \param bMasked determines whether the masked or unmasked state of the
- //! interrupt is to be returned. If bMasked is \b true, the masked state is
- //! returned, otherwise the unmasked state is returned.
- //!
- //! This function allows an application to query the state of the EEPROM
- //! interrupt. If active, the interrupt may be cleared by calling
- //! EEPROMIntClear().
- //!
- //! \return Returns \b EEPROM_INT_PROGRAM if an interrupt is being signaled or
- //! 0 otherwise.
- //
- //*****************************************************************************
- uint32_t
- EEPROMIntStatus(bool bMasked)
- {
- if(bMasked)
- {
- //
- // If asked for the masked interrupt status, we check to see if the
- // relevant interrupt is pending in the flash controller then return
- // the appropriate EEPROM flag if it is.
- //
- return((HWREG(FLASH_FCMISC) & FLASH_FCMISC_EMISC) ?
- EEPROM_INT_PROGRAM : 0);
- }
- else
- {
- //
- // If asked for the unmasked interrupt status, infer that an interrupt
- // is pending if the WORKING bit of the EEDONE register is clear. The
- // actual interrupt fires on the high to low transition of this bit
- // but we don't have access to an unmasked interrupt status for the
- // EEPROM because it's handled via the flash controller so we have to
- // make do with this instead.
- //
- return((HWREG(EEPROM_EEDONE) & EEPROM_EEDONE_WORKING) ?
- 0 : EEPROM_INT_PROGRAM);
- }
- }
- //*****************************************************************************
- //
- //! Clears the EEPROM interrupt.
- //!
- //! \param ui32IntFlags indicates which interrupt sources to clear. Currently,
- //! the only valid value is \b EEPROM_INT_PROGRAM.
- //!
- //! This function allows an application to clear the EEPROM interrupt.
- //!
- //! \note Because there is a write buffer in the Cortex-M processor, it may
- //! take several clock cycles before the interrupt source is actually cleared.
- //! Therefore, it is recommended that the interrupt source be cleared early in
- //! the interrupt handler (as opposed to the very last action) to avoid
- //! returning from the interrupt handler before the interrupt source is
- //! actually cleared. Failure to do so may result in the interrupt handler
- //! being immediately reentered (because the interrupt controller still sees
- //! the interrupt source asserted).
- //!
- //! \return None.
- //!
- //*****************************************************************************
- void
- EEPROMIntClear(uint32_t ui32IntFlags)
- {
- //
- // Clear the flash interrupt.
- //
- HWREG(FLASH_FCMISC) = FLASH_FCMISC_EMISC;
- //
- // Clear the sector protection bits to prevent possible problems when
- // programming the main flash array later.
- //
- if(CLASS_IS_TM4C123 && REVISION_IS_A0)
- {
- _EEPROMSectorMaskClear();
- }
- }
- //*****************************************************************************
- //
- //! Returns status on the last EEPROM program or erase operation.
- //!
- //! This function returns the current status of the last program or erase
- //! operation performed by the EEPROM. It is intended to provide error
- //! information to applications programming or setting EEPROM protection
- //! options under interrupt control.
- //!
- //! \return Returns 0 if the last program or erase operation completed without
- //! any errors. If an operation is ongoing or an error occurred, the return
- //! value is a logical OR combination of \b EEPROM_RC_WRBUSY, \b
- //! EEPROM_RC_NOPERM, \b EEPROM_RC_WKCOPY, \b EEPROM_RC_WKERASE, and \b
- //! EEPROM_RC_WORKING.
- //!
- //*****************************************************************************
- uint32_t
- EEPROMStatusGet(void)
- {
- return(HWREG(EEPROM_EEDONE));
- }
- //*****************************************************************************
- //
- // Close the Doxygen group.
- //! @}
- //
- //*****************************************************************************
|