1 //*****************************************************************************
2 //
3 // eeprom.c - Driver for programming the on-chip EEPROM.
4 //
5 // Copyright (c) 2010-2017 Texas Instruments Incorporated.  All rights reserved.
6 // Software License Agreement
7 //
8 //   Redistribution and use in source and binary forms, with or without
9 //   modification, are permitted provided that the following conditions
10 //   are met:
11 //
12 //   Redistributions of source code must retain the above copyright
13 //   notice, this list of conditions and the following disclaimer.
14 //
15 //   Redistributions in binary form must reproduce the above copyright
16 //   notice, this list of conditions and the following disclaimer in the
17 //   documentation and/or other materials provided with the
18 //   distribution.
19 //
20 //   Neither the name of Texas Instruments Incorporated nor the names of
21 //   its contributors may be used to endorse or promote products derived
22 //   from this software without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 //
36 //*****************************************************************************
37 
38 #include "types.h"
39 #include <stdbool.h>
40 #include <stdint.h>
41 #include "inc/hw_eeprom.h"
42 #include "inc/hw_flash.h"
43 #include "inc/hw_sysctl.h"
44 #include "debug.h"
45 #include "flash.h"
46 #include "interrupt.h"
47 #include "sysctl.h"
48 #include "eeprom.h"
49 
50 //*****************************************************************************
51 //
52 //! \addtogroup eeprom_api
53 //! @{
54 //
55 //*****************************************************************************
56 
57 //*****************************************************************************
58 //
59 // Useful macros to extract the number of EEPROM blocks available on the target
60 // device and the total EEPROM storage in bytes from the EESIZE register.
61 //
62 //*****************************************************************************
63 #define BLOCKS_FROM_EESIZE(x) (((x) & EEPROM_EESIZE_BLKCNT_M) >>              \
64                                EEPROM_EESIZE_BLKCNT_S)
65 #define SIZE_FROM_EESIZE(x)   ((((x) & EEPROM_EESIZE_WORDCNT_M) >>            \
66                                 EEPROM_EESIZE_WORDCNT_S) * 4)
67 
68 //*****************************************************************************
69 //
70 // Useful macro to extract the offset from a linear address.
71 //
72 //*****************************************************************************
73 #define OFFSET_FROM_ADDR(x) (((x) >> 2) & 0x0F)
74 
75 //*****************************************************************************
76 //
77 // The key value required to initiate a mass erase.
78 //
79 //*****************************************************************************
80 #define EEPROM_MASS_ERASE_KEY ((uint32_t)0xE37B << EEPROM_EEDBGME_KEY_S)
81 
82 //*****************************************************************************
83 //
84 // Block until the EEPROM peripheral is not busy.
85 //
86 //*****************************************************************************
87 static void
_EEPROMWaitForDone(void)88 _EEPROMWaitForDone(void)
89 {
90     //
91     // Is the EEPROM still busy?
92     //
93     while (HWREG(EEPROM_EEDONE) & EEPROM_EEDONE_WORKING)
94     {
95         //
96         // Spin while EEPROM is busy.
97         //
98     }
99 }
100 
101 //*****************************************************************************
102 //
103 //! Performs any necessary recovery in case of power failures during write.
104 //!
105 //! This function \b must be called after SysCtlPeripheralEnable() and before
106 //! the EEPROM is accessed.  It is used to check for errors in the EEPROM state
107 //! such as from power failure during a previous write operation.  The function
108 //! detects these errors and performs as much recovery as possible.
109 //!
110 //! If \b EEPROM_INIT_ERROR is returned, the EEPROM was unable to recover its
111 //! state.  If power is stable when this occurs, this indicates a fatal
112 //! error and is likely an indication that the EEPROM memory has exceeded its
113 //! specified lifetime write/erase specification.  If the supply voltage is
114 //! unstable when this return code is observed, retrying the operation once the
115 //! voltage is stabilized may clear the error.
116 //!
117 //! Failure to call this function after a reset may lead to incorrect operation
118 //! or permanent data loss if the EEPROM is later written.
119 //!
120 //! \return Returns \b EEPROM_INIT_OK if no errors were detected or \b
121 //! EEPROM_INIT_ERROR if the EEPROM peripheral cannot currently recover from
122 //! an interrupted write or erase operation.
123 //
124 //*****************************************************************************
125 uint32_t
EEPROMInit(void)126 EEPROMInit(void)
127 {
128     uint32_t ui32Status;
129 
130     //
131     // Insert a small delay (6 cycles + call overhead) to guard against the
132     // possibility that this function is called immediately after the EEPROM
133     // peripheral is enabled.  Without this delay, there is a slight chance
134     // that the first EEPROM register read will fault if you are using a
135     // compiler with a ridiculously good optimizer!
136     //
137     SysCtlDelay(2);
138 
139     //
140     // Make sure the EEPROM has finished any ongoing processing.
141     //
142     _EEPROMWaitForDone();
143 
144     //
145     // Read the EESUPP register to see if any errors have been reported.
146     //
147     ui32Status = HWREG(EEPROM_EESUPP);
148 
149     //
150     // Did an error of some sort occur during initialization?
151     //
152     if (ui32Status & (EEPROM_EESUPP_PRETRY | EEPROM_EESUPP_ERETRY))
153     {
154         return (EEPROM_INIT_ERROR);
155     }
156 
157     //
158     // Perform a second EEPROM reset.
159     //
160     SysCtlPeripheralReset(SYSCTL_PERIPH_EEPROM0);
161 
162     //
163     // Wait for the EEPROM to complete its reset processing once again.
164     //
165     SysCtlDelay(2);
166     _EEPROMWaitForDone();
167 
168     //
169     // Read EESUPP once again to determine if any error occurred.
170     //
171     ui32Status = HWREG(EEPROM_EESUPP);
172 
173     //
174     // Was an error reported following the second reset?
175     //
176     if (ui32Status & (EEPROM_EESUPP_PRETRY | EEPROM_EESUPP_ERETRY))
177     {
178         return (EEPROM_INIT_ERROR);
179     }
180 
181     //
182     // The EEPROM does not indicate that any error occurred.
183     //
184     return (EEPROM_INIT_OK);
185 }
186 
187 
188 //*****************************************************************************
189 //
190 //! Determines the size of the EEPROM.
191 //!
192 //! This function returns the size of the EEPROM in bytes.
193 //!
194 //! \return Returns the total number of bytes in the EEPROM.
195 //
196 //*****************************************************************************
197 uint32_t
EEPROMSizeGet(void)198 EEPROMSizeGet(void)
199 {
200     //
201     // Return the size of the EEPROM in bytes.
202     //
203     return (SIZE_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
204 }
205 
206 //*****************************************************************************
207 //
208 //! Determines the number of blocks in the EEPROM.
209 //!
210 //! This function may be called to determine the number of blocks in the
211 //! EEPROM.  Each block is the same size and the number of bytes of storage
212 //! contained in a block may be determined by dividing the size of the device,
213 //! obtained via a call to the EEPROMSizeGet() function, by the number of
214 //! blocks returned by this function.
215 //!
216 //! \return Returns the total number of blocks in the device EEPROM.
217 //
218 //*****************************************************************************
219 uint32_t
EEPROMBlockCountGet(void)220 EEPROMBlockCountGet(void)
221 {
222     //
223     // Extract the number of blocks and return it to the caller.
224     //
225 #ifdef EEPROM_SIZE_LIMIT
226     //
227     // If a size limit has been specified, fake the number of blocks to match.
228     //
229     return (EEPROM_SIZE_LIMIT / 48);
230 #else
231     //
232     // Return the actual number of blocks supported by the hardware.
233     //
234     return (BLOCKS_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
235 #endif
236 }
237 
238 //*****************************************************************************
239 //
240 //! Reads data from the EEPROM.
241 //!
242 //! \param pui32Data is a pointer to storage for the data read from the EEPROM.
243 //! This pointer must point to at least \e ui32Count bytes of available memory.
244 //! \param ui32Address is the byte address within the EEPROM from which data is
245 //! to be read.  This value must be a multiple of 4.
246 //! \param ui32Count is the number of bytes of data to read from the EEPROM.
247 //! This value must be a multiple of 4.
248 //!
249 //! This function may be called to read a number of words of data from a
250 //! word-aligned address within the EEPROM.  Data read is copied into the
251 //! buffer pointed to by the \e pui32Data parameter.
252 //!
253 //! \return None.
254 //
255 //*****************************************************************************
256 void
EEPROMRead(uint32_t * pui32Data,uint32_t ui32Address,uint32_t ui32Count)257 EEPROMRead(uint32_t *pui32Data, uint32_t ui32Address, uint32_t ui32Count)
258 {
259     //
260     // Check parameters in a debug build.
261     //
262     ASSERT(pui32Data);
263     ASSERT(ui32Address < SIZE_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
264     ASSERT((ui32Address + ui32Count) <=
265            SIZE_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
266     ASSERT((ui32Address & 3) == 0);
267     ASSERT((ui32Count & 3) == 0);
268 
269     //
270     // Set the block and offset appropriately to read the first word.
271     //
272     HWREG(EEPROM_EEBLOCK) = EEPROMBlockFromAddr(ui32Address);
273     HWREG(EEPROM_EEOFFSET) = OFFSET_FROM_ADDR(ui32Address);
274 
275     //
276     // Convert the byte count to a word count.
277     //
278     ui32Count /= 4;
279 
280     //
281     // Read each word in turn.
282     //
283     while (ui32Count)
284     {
285         //
286         // Read the next word through the autoincrementing register.
287         //
288         *pui32Data = HWREG(EEPROM_EERDWRINC);
289 
290         //
291         // Move on to the next word.
292         //
293         pui32Data++;
294         ui32Count--;
295 
296         //
297         // Do we need to move to the next block?  This is the case if the
298         // offset register has just wrapped back to 0.  Note that we only
299         // write the block register if we have more data to read.  If this
300         // register is written, the hardware expects a read or write operation
301         // next.  If a mass erase is requested instead, the mass erase will
302         // fail.
303         //
304         if (ui32Count && (HWREG(EEPROM_EEOFFSET) == 0))
305         {
306             HWREG(EEPROM_EEBLOCK) += 1;
307         }
308     }
309 }
310 
311 //*****************************************************************************
312 //
313 //! Writes data to the EEPROM.
314 //!
315 //! \param pui32Data points to the first word of data to write to the EEPROM.
316 //! \param ui32Address defines the byte address within the EEPROM that the data
317 //! is to be written to.  This value must be a multiple of 4.
318 //! \param ui32Count defines the number of bytes of data that is to be written.
319 //! This value must be a multiple of 4.
320 //!
321 //! This function may be called to write data into the EEPROM at a given
322 //! word-aligned address.  The call is synchronous and returns only after
323 //! all data has been written or an error occurs.
324 //!
325 //! \return Returns 0 on success or non-zero values on failure.  Failure codes
326 //! are logical OR combinations of \b EEPROM_RC_WRBUSY, \b EEPROM_RC_NOPERM,
327 //! \b EEPROM_RC_WKCOPY, \b EEPROM_RC_WKERASE, and \b EEPROM_RC_WORKING.
328 //
329 //*****************************************************************************
330 uint32_t
EEPROMProgram(uint32_t * pui32Data,uint32_t ui32Address,uint32_t ui32Count)331 EEPROMProgram(uint32_t *pui32Data, uint32_t ui32Address, uint32_t ui32Count)
332 {
333     uint32_t ui32Status;
334 
335     //
336     // Check parameters in a debug build.
337     //
338     ASSERT(pui32Data);
339     ASSERT(ui32Address < SIZE_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
340     ASSERT((ui32Address + ui32Count) <=
341            SIZE_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
342     ASSERT((ui32Address & 3) == 0);
343     ASSERT((ui32Count & 3) == 0);
344 
345     //
346     // Make sure the EEPROM is idle before we start.
347     //
348     do
349     {
350         //
351         // Read the status.
352         //
353         ui32Status = HWREG(EEPROM_EEDONE);
354     }
355     while (ui32Status & EEPROM_EEDONE_WORKING);
356 
357     //
358     // Set the block and offset appropriately to program the first word.
359     //
360     HWREG(EEPROM_EEBLOCK) = EEPROMBlockFromAddr(ui32Address);
361     HWREG(EEPROM_EEOFFSET) = OFFSET_FROM_ADDR(ui32Address);
362 
363     //
364     // Convert the byte count to a word count.
365     //
366     ui32Count /= 4;
367 
368     //
369     // Write each word in turn.
370     //
371     while (ui32Count)
372     {
373         //
374         // Write the next word through the autoincrementing register.
375         //
376         HWREG(EEPROM_EERDWRINC) = *pui32Data;
377 
378         //
379         // Wait a few cycles.  In some cases, the WRBUSY bit is not set
380         // immediately and this prevents us from dropping through the polling
381         // loop before the bit is set.
382         //
383         SysCtlDelay(10);
384 
385         //
386         // Wait for the write to complete.
387         //
388         do
389         {
390             //
391             // Read the status.
392             //
393             ui32Status = HWREG(EEPROM_EEDONE);
394         }
395         while (ui32Status & EEPROM_EEDONE_WORKING);
396 
397         //
398         // Make sure we completed the write without errors.  Note that we
399         // must check this per-word because write permission can be set per
400         // block resulting in only a section of the write not being performed.
401         //
402         if (ui32Status & EEPROM_EEDONE_NOPERM)
403         {
404             return (ui32Status);
405         }
406 
407         //
408         // Move on to the next word.
409         //
410         pui32Data++;
411         ui32Count--;
412 
413         //
414         // Do we need to move to the next block?  This is the case if the
415         // offset register has just wrapped back to 0.  Note that we only
416         // write the block register if we have more data to read.  If this
417         // register is written, the hardware expects a read or write operation
418         // next.  If a mass erase is requested instead, the mass erase will
419         // fail.
420         //
421         if (ui32Count && (HWREG(EEPROM_EEOFFSET) == 0))
422         {
423             HWREG(EEPROM_EEBLOCK) += 1;
424         }
425     }
426 
427     //
428     // Return the current status to the caller.
429     //
430     return (HWREG(EEPROM_EEDONE));
431 }
432 
433 //*****************************************************************************
434 //
435 //! Writes a word to the EEPROM.
436 //!
437 //! \param ui32Data is the word to write to the EEPROM.
438 //! \param ui32Address defines the byte address within the EEPROM to which the
439 //! data is to be written.  This value must be a multiple of 4.
440 //!
441 //! This function is intended to allow EEPROM programming under interrupt
442 //! control.  It may be called to start the process of writing a single word of
443 //! data into the EEPROM at a given word-aligned address.  The call is
444 //! asynchronous and returns immediately without waiting for the write to
445 //! complete.  Completion of the operation is signaled by means of an
446 //! interrupt from the EEPROM module.  The EEPROM peripheral shares a single
447 //! interrupt vector with the flash memory subsystem, \b INT_FLASH.
448 //!
449 //! \return Returns status and error information in the form of a logical OR
450 //! combinations of \b EEPROM_RC_WRBUSY, \b EEPROM_RC_NOPERM,
451 //! \b EEPROM_RC_WKCOPY, \b EEPROM_RC_WKERASE and \b EEPROM_RC_WORKING.  Flags
452 //! \b EEPROM_RC_WKCOPY, \b EEPROM_RC_WKERASE, and \b EEPROM_RC_WORKING are
453 //! expected in normal operation and do not indicate an error.
454 //
455 //*****************************************************************************
456 uint32_t
EEPROMProgramNonBlocking(uint32_t ui32Data,uint32_t ui32Address)457 EEPROMProgramNonBlocking(uint32_t ui32Data, uint32_t ui32Address)
458 {
459     //
460     // Check parameters in a debug build.
461     //
462     ASSERT(ui32Address < SIZE_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
463     ASSERT((ui32Address & 3) == 0);
464 
465     //
466     // Set the block and offset appropriately to program the desired word.
467     //
468     HWREG(EEPROM_EEBLOCK) = EEPROMBlockFromAddr(ui32Address);
469     HWREG(EEPROM_EEOFFSET) = OFFSET_FROM_ADDR(ui32Address);
470 
471     //
472     // Write the new word using the auto-incrementing register just in case
473     // the caller wants to write follow-on words using direct register access
474     //
475     HWREG(EEPROM_EERDWRINC) = ui32Data;
476 
477     //
478     // Return the current status to the caller.
479     //
480     return (HWREG(EEPROM_EEDONE));
481 }
482 
483 //*****************************************************************************
484 //
485 //! Erases the EEPROM and returns it to the factory default condition.
486 //!
487 //! This function completely erases the EEPROM and removes any and
488 //! all access protection on its blocks, leaving the device in the factory
489 //! default condition.  After this operation, all EEPROM words contain the
490 //! value 0xFFFFFFFF and all blocks are accessible for both read and write
491 //! operations in all CPU modes.  No passwords are active.
492 //!
493 //! The function is synchronous and does not return until the erase operation
494 //! has completed.
495 //!
496 //! \return Returns 0 on success or non-zero values on failure.  Failure codes
497 //! are logical OR combinations of \b EEPROM_RC_WRBUSY, \b EEPROM_RC_NOPERM,
498 //! \b EEPROM_RC_WKCOPY, \b EEPROM_RC_WKERASE, and \b EEPROM_RC_WORKING.
499 //
500 //*****************************************************************************
501 uint32_t
EEPROMMassErase(void)502 EEPROMMassErase(void)
503 {
504     //
505     // Start the mass erase processing
506     //
507     HWREG(EEPROM_EEDBGME) = EEPROM_MASS_ERASE_KEY | EEPROM_EEDBGME_ME;
508 
509     //
510     // Wait for completion.
511     //
512     _EEPROMWaitForDone();
513 
514     //
515     // Reset the peripheral.  This is required so that all protection
516     // mechanisms and passwords are reset now that the EEPROM data has been
517     // scrubbed.
518     //
519     SysCtlPeripheralReset(SYSCTL_PERIPH_EEPROM0);
520 
521     //
522     // Wait for completion again.
523     //
524     SysCtlDelay(2);
525     _EEPROMWaitForDone();
526 
527     //
528     // Pass any error codes back to the caller.
529     //
530     return (HWREG(EEPROM_EEDONE));
531 }
532 
533 //*****************************************************************************
534 //
535 //! Returns the current protection level for an EEPROM block.
536 //!
537 //! \param ui32Block is the block number for which the protection level is to
538 //! be queried.
539 //!
540 //! This function returns the current protection settings for a given
541 //! EEPROM block.  If block 0 is currently locked, it must be unlocked prior
542 //! to calling this function to query the protection setting for other blocks.
543 //!
544 //! \return Returns one of \b EEPROM_PROT_RW_LRO_URW, \b EEPROM_PROT_NA_LNA_URW
545 //! or \b EEPROM_PROT_RO_LNA_URO optionally OR-ed with
546 //! \b EEPROM_PROT_SUPERVISOR_ONLY.
547 //
548 //*****************************************************************************
549 uint32_t
EEPROMBlockProtectGet(uint32_t ui32Block)550 EEPROMBlockProtectGet(uint32_t ui32Block)
551 {
552     //
553     // Parameter validity check.
554     //
555     ASSERT(ui32Block < BLOCKS_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
556 
557     //
558     // Set the current block.
559     //
560     HWREG(EEPROM_EEBLOCK) = ui32Block;
561 
562     //
563     // Return the protection flags for this block.
564     //
565     return (HWREG(EEPROM_EEPROT));
566 }
567 
568 //*****************************************************************************
569 //
570 //! Set the current protection options for an EEPROM block.
571 //!
572 //! \param ui32Block is the block number for which the protection options are
573 //! to be set.
574 //! \param ui32Protect consists of one of the values \b EEPROM_PROT_RW_LRO_URW,
575 //! \b EEPROM_PROT_NA_LNA_URW or \b EEPROM_PROT_RO_LNA_URO optionally ORed with
576 //! \b EEPROM_PROT_SUPERVISOR_ONLY.
577 //!
578 //! This function sets the protection settings for a given EEPROM block
579 //! assuming no protection settings have previously been written.  Note that
580 //! protection settings applied to block 0 have special meaning and control
581 //! access to the EEPROM peripheral as a whole.  Protection settings applied to
582 //! blocks numbered 1 and above are layered above any protection set on block 0
583 //! such that the effective protection on each block is the logical OR of the
584 //! protection flags set for block 0 and for the target block.  This protocol
585 //! allows global protection options to be set for the whole device via block
586 //! 0 and more restrictive protection settings to be set on a block-by-block
587 //! basis.
588 //!
589 //! The protection flags indicate access permissions as follow:
590 //!
591 //! \b EEPROM_PROT_SUPERVISOR_ONLY restricts access to the block to threads
592 //! running in supervisor mode.  If clear, both user and supervisor threads
593 //! can access the block.
594 //!
595 //! \b EEPROM_PROT_RW_LRO_URW provides read/write access to the block if no
596 //! password is set or if a password is set and the block is unlocked.  If the
597 //! block is locked, only read access is permitted.
598 //!
599 //! \b EEPROM_PROT_NA_LNA_URW provides neither read nor write access unless
600 //! a password is set and the block is unlocked.  If the block is unlocked,
601 //! both read and write access are permitted.
602 //!
603 //! \b EEPROM_PROT_RO_LNA_URO provides read access to the block if no password
604 //! is set or if a password is set and the block is unlocked.  If the block is
605 //! password protected and locked, neither read nor write access is permitted.
606 //!
607 //! \return Returns a logical OR combination of \b EEPROM_RC_WRBUSY, \b
608 //! EEPROM_RC_NOPERM, \b EEPROM_RC_WKCOPY, \b EEPROM_RC_WKERASE, and \b
609 //! EEPROM_RC_WORKING to indicate status and error conditions.
610 //
611 //*****************************************************************************
612 uint32_t
EEPROMBlockProtectSet(uint32_t ui32Block,uint32_t ui32Protect)613 EEPROMBlockProtectSet(uint32_t ui32Block, uint32_t ui32Protect)
614 {
615     //
616     // Parameter validity check.
617     //
618     ASSERT(ui32Block < BLOCKS_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
619 
620     //
621     // Set the current block.
622     //
623     HWREG(EEPROM_EEBLOCK) = ui32Block;
624 
625     //
626     // Set the protection options for this block.
627     //
628     HWREG(EEPROM_EEPROT) = ui32Protect;
629 
630     //
631     // Wait for the write to complete.
632     //
633     while (HWREG(EEPROM_EEDONE) & EEPROM_EEDONE_WORKING)
634     {
635         //
636         // Still working.
637         //
638     }
639 
640     //
641     // Pass any error codes back to the caller.
642     //
643     return (HWREG(EEPROM_EEDONE));
644 }
645 
646 //*****************************************************************************
647 //
648 //! Sets the password used to protect an EEPROM block.
649 //!
650 //! \param ui32Block is the EEPROM block number for which the password is to be
651 //! set.
652 //! \param pui32Password points to an array of uint32_t values comprising
653 //! the password to set.  Each element may be any 32-bit value other than
654 //! 0xFFFFFFFF.  This array must contain the number of elements given by the
655 //! \e ui32Count parameter.
656 //! \param ui32Count provides the number of uint32_ts in the \e ui32Password.
657 //! Valid values are 1, 2 and 3.
658 //!
659 //! This function allows the password used to unlock an EEPROM block to be
660 //! set.  Valid passwords may be either 32, 64 or 96 bits comprising words
661 //! with any value other than 0xFFFFFFFF.  The password may only be set once.
662 //! Any further attempts to set the password result in an error.  Once the
663 //! password is set, the block remains unlocked until EEPROMBlockLock() is
664 //! called for that block or block 0, or a reset occurs.
665 //!
666 //! If a password is set on block 0, this affects locking of the peripheral as
667 //! a whole.  When block 0 is locked, all other EEPROM blocks are inaccessible
668 //! until block 0 is unlocked.  Once block 0 is unlocked, other blocks
669 //! become accessible according to any passwords set on those blocks and the
670 //! protection set for that block via a call to EEPROMBlockProtectSet().
671 //!
672 //! \return Returns a logical OR combination of \b EEPROM_RC_WRBUSY, \b
673 //! EEPROM_RC_NOPERM, \b EEPROM_RC_WKCOPY, \b EEPROM_RC_WKERASE, and \b
674 //! EEPROM_RC_WORKING to indicate status and error conditions.
675 //
676 //*****************************************************************************
677 uint32_t
EEPROMBlockPasswordSet(uint32_t ui32Block,uint32_t * pui32Password,uint32_t ui32Count)678 EEPROMBlockPasswordSet(uint32_t ui32Block, uint32_t *pui32Password,
679                        uint32_t ui32Count)
680 {
681     uint32_t ui32Reg;
682 
683     //
684     // Check parameters in a debug build.
685     //
686     ASSERT(pui32Password);
687     ASSERT(ui32Block < BLOCKS_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
688     ASSERT(ui32Count <= 3);
689 
690     //
691     // Set the block number whose password we are about to write.
692     //
693     HWREG(EEPROM_EEBLOCK) = ui32Block;
694 
695     //
696     // Start with the first password word.
697     //
698     ui32Reg = EEPROM_EEPASS0;
699 
700     //
701     // Write the password.
702     //
703     while (ui32Count)
704     {
705         //
706         // Start the process of writing the password.
707         //
708         HWREG(ui32Reg) = *pui32Password;
709 
710         //
711         // Update values in preparation for writing the next word.
712         //
713         pui32Password++;
714         ui32Reg += 4;
715         ui32Count--;
716 
717         //
718         // Wait for the last word write to complete or an error to be reported.
719         //
720         while (HWREG(EEPROM_EEDONE) & EEPROM_EEDONE_WORKING)
721         {
722             //
723             // Still working.
724             //
725         }
726     }
727 
728     //
729     // Return the final write status.
730     //
731     return (HWREG(EEPROM_EEDONE));
732 }
733 
734 //*****************************************************************************
735 //
736 //! Locks a password-protected EEPROM block.
737 //!
738 //! \param ui32Block is the EEPROM block number which is to be locked.
739 //!
740 //! This function locks an EEPROM block that has previously been protected by
741 //! writing a password.  Access to the block once it is locked is determined
742 //! by the protection settings applied via a previous call to the
743 //! EEPROMBlockProtectSet() function.  If no password has previously been set
744 //! for the block, this function has no effect.
745 //!
746 //! Locking block 0 has the effect of making all other blocks in the EEPROM
747 //! inaccessible.
748 //!
749 //! \return Returns the lock state for the block on exit, 1 if unlocked (as
750 //! would be the case if no password was set) or 0 if locked.
751 //!
752 //*****************************************************************************
753 uint32_t
EEPROMBlockLock(uint32_t ui32Block)754 EEPROMBlockLock(uint32_t ui32Block)
755 {
756     //
757     // Check parameters in a debug build.
758     //
759     ASSERT(ui32Block < BLOCKS_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
760 
761     //
762     // Select the block we are going to lock.
763     //
764     HWREG(EEPROM_EEBLOCK) = ui32Block;
765 
766     //
767     // Lock the block.
768     //
769     HWREG(EEPROM_EEUNLOCK) = 0xFFFFFFFF;
770 
771     //
772     // Return the current lock state.
773     //
774     return (HWREG(EEPROM_EEUNLOCK));
775 }
776 
777 //*****************************************************************************
778 //
779 //! Unlocks a password-protected EEPROM block.
780 //!
781 //! \param ui32Block is the EEPROM block number which is to be unlocked.
782 //! \param pui32Password points to an array of uint32_t values containing
783 //! the password for the block.  Each element must match the password
784 //! originally set via a call to EEPROMBlockPasswordSet().
785 //! \param ui32Count provides the number of elements in the \e pui32Password
786 //! array and must match the value originally passed to
787 //! EEPROMBlockPasswordSet().  Valid values are 1, 2 and 3.
788 //!
789 //! This function unlocks an EEPROM block that has previously been protected by
790 //! writing a password.  Access to the block once it is unlocked is determined
791 //! by the protection settings applied via a previous call to the
792 //! EEPROMBlockProtectSet() function.
793 //!
794 //! To successfully unlock an EEPROM block, the password provided must match
795 //! the password provided on the original call to EEPROMBlockPasswordSet().  If
796 //! an incorrect password is provided, the block remains locked.
797 //!
798 //! Unlocking block 0 has the effect of making all other blocks in the device
799 //! accessible according to their own access protection settings.  When block
800 //! 0 is locked, all other EEPROM blocks are inaccessible.
801 //!
802 //! \return Returns the lock state for the block on exit, 1 if unlocked or 0 if
803 //! locked.
804 //!
805 //*****************************************************************************
806 uint32_t
EEPROMBlockUnlock(uint32_t ui32Block,uint32_t * pui32Password,uint32_t ui32Count)807 EEPROMBlockUnlock(uint32_t ui32Block, uint32_t *pui32Password,
808                   uint32_t ui32Count)
809 {
810     //
811     // Check parameters in a debug build.
812     //
813     ASSERT(pui32Password);
814     ASSERT(ui32Block < BLOCKS_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
815     ASSERT(ui32Count <= 3);
816 
817     //
818     // Set the block that we are trying to unlock.
819     //
820     HWREG(EEPROM_EEBLOCK) = ui32Block;
821 
822     //
823     // Write the unlock register with 0xFFFFFFFF to reset the unlock
824     // sequence just in case a short password was previously used to try to
825     // unlock the block.
826     //
827     HWREG(EEPROM_EEUNLOCK) = 0xFFFFFFFF;
828 
829     //
830     // We need to write the password words in the opposite order when unlocking
831     // compared to locking so start at the end of the array.
832     //
833     pui32Password += (ui32Count - 1);
834 
835     //
836     // Write the supplied password to unlock the block.
837     //
838     while (ui32Count)
839     {
840         HWREG(EEPROM_EEUNLOCK) = *pui32Password--;
841         ui32Count--;
842     }
843 
844     //
845     // Let the caller know if their password worked.
846     //
847     return (HWREG(EEPROM_EEUNLOCK));
848 }
849 
850 //*****************************************************************************
851 //
852 //! Hides an EEPROM block until the next reset.
853 //!
854 //! \param ui32Block is the EEPROM block number which is to be hidden.
855 //!
856 //! This function hides an EEPROM block other than block 0.  Once hidden, a
857 //! block is completely inaccessible until the next reset.  This mechanism
858 //! allows initialization code to have access to data which is to be hidden
859 //! from the rest of the application.  Unlike applications using passwords, an
860 //! application making using of block hiding need not contain any embedded
861 //! passwords which could be found through disassembly.
862 //!
863 //! \return None.
864 //!
865 //*****************************************************************************
866 void
EEPROMBlockHide(uint32_t ui32Block)867 EEPROMBlockHide(uint32_t ui32Block)
868 {
869     //
870     // Check parameters in a debug build.
871     //
872     ASSERT(!ui32Block);
873     ASSERT(ui32Block < BLOCKS_FROM_EESIZE(HWREG(EEPROM_EESIZE)));
874 
875     //
876     // Hide the requested block.
877     //
878     HWREG(EEPROM_EEHIDE) = (1 << ui32Block);
879 }
880 
881 //*****************************************************************************
882 //
883 //! Enables the EEPROM interrupt.
884 //!
885 //! \param ui32IntFlags indicates which EEPROM interrupt source to enable.
886 //! This must be \b EEPROM_INT_PROGRAM currently.
887 //!
888 //! This function enables the EEPROM interrupt.  When enabled, an interrupt
889 //! is generated when any EEPROM write or erase operation completes.  The
890 //! EEPROM peripheral shares a single interrupt vector with the flash memory
891 //! subsystem, \b INT_FLASH.  This function is provided as a convenience but
892 //! the EEPROM interrupt can also be enabled using a call to FlashIntEnable()
893 //! passing FLASH_INT_EEPROM in the \e ui32IntFlags parameter.
894 //!
895 //! \return None.
896 //!
897 //*****************************************************************************
898 void
EEPROMIntEnable(uint32_t ui32IntFlags)899 EEPROMIntEnable(uint32_t ui32IntFlags)
900 {
901     //
902     // Look for valid interrupt sources.
903     //
904     ASSERT(ui32IntFlags == EEPROM_INT_PROGRAM);
905 
906     //
907     // Enable interrupts from the EEPROM module.
908     //
909     HWREG(EEPROM_EEINT) |= EEPROM_EEINT_INT;
910 
911     //
912     // Enable the EEPROM interrupt in the flash controller module.
913     //
914     HWREG(FLASH_FCIM) |= FLASH_FCRIS_ERIS;
915 }
916 
917 //*****************************************************************************
918 //
919 //! Disables the EEPROM interrupt.
920 //!
921 //! \param ui32IntFlags indicates which EEPROM interrupt source to disable.
922 //! This must be \b EEPROM_INT_PROGRAM currently.
923 //!
924 //! This function disables the EEPROM interrupt and prevents calls to the
925 //! interrupt vector when any EEPROM write or erase operation completes.  The
926 //! EEPROM peripheral shares a single interrupt vector with the flash memory
927 //! subsystem, \b INT_FLASH.  This function is provided as a convenience but
928 //! the EEPROM interrupt can also be disabled using a call to FlashIntDisable()
929 //! passing FLASH_INT_EEPROM in the \e ui32IntFlags parameter.
930 //!
931 //! \return None.
932 //!
933 //*****************************************************************************
934 void
EEPROMIntDisable(uint32_t ui32IntFlags)935 EEPROMIntDisable(uint32_t ui32IntFlags)
936 {
937     //
938     // Look for valid interrupt sources.
939     //
940     ASSERT(ui32IntFlags == EEPROM_INT_PROGRAM);
941 
942     //
943     // Disable the EEPROM interrupt in the flash controller module.
944     //
945     HWREG(FLASH_FCIM) &= ~FLASH_FCIM_EMASK;
946 
947     //
948     // Disable interrupts from the EEPROM module.
949     //
950     HWREG(EEPROM_EEINT) &= ~EEPROM_EEINT_INT;
951 }
952 
953 //*****************************************************************************
954 //
955 //! Reports the state of the EEPROM interrupt.
956 //!
957 //! \param bMasked determines whether the masked or unmasked state of the
958 //! interrupt is to be returned.  If bMasked is \b true, the masked state is
959 //! returned, otherwise the unmasked state is returned.
960 //!
961 //! This function allows an application to query the state of the EEPROM
962 //! interrupt.  If active, the interrupt may be cleared by calling
963 //! EEPROMIntClear().
964 //!
965 //! \return Returns \b EEPROM_INT_PROGRAM if an interrupt is being signaled or
966 //! 0 otherwise.
967 //
968 //*****************************************************************************
969 uint32_t
EEPROMIntStatus(bool bMasked)970 EEPROMIntStatus(bool bMasked)
971 {
972     if (bMasked)
973     {
974         //
975         // If asked for the masked interrupt status, we check to see if the
976         // relevant interrupt is pending in the flash controller then return
977         // the appropriate EEPROM flag if it is.
978         //
979         return ((HWREG(FLASH_FCMISC) & FLASH_FCMISC_EMISC) ?
980                 EEPROM_INT_PROGRAM : 0);
981     }
982     else
983     {
984         //
985         // If asked for the unmasked interrupt status, infer that an interrupt
986         // is pending if the WORKING bit of the EEDONE register is clear.  The
987         // actual interrupt fires on the high to low transition of this bit
988         // but we don't have access to an unmasked interrupt status for the
989         // EEPROM because it's handled via the flash controller so we have to
990         // make do with this instead.
991         //
992         return ((HWREG(EEPROM_EEDONE) & EEPROM_EEDONE_WORKING) ?
993                 0 : EEPROM_INT_PROGRAM);
994     }
995 }
996 
997 //*****************************************************************************
998 //
999 //! Clears the EEPROM interrupt.
1000 //!
1001 //! \param ui32IntFlags indicates which interrupt sources to clear.  Currently,
1002 //! the only valid value is \b EEPROM_INT_PROGRAM.
1003 //!
1004 //! This function allows an application to clear the EEPROM interrupt.
1005 //!
1006 //! \note Because there is a write buffer in the Cortex-M processor, it may
1007 //! take several clock cycles before the interrupt source is actually cleared.
1008 //! Therefore, it is recommended that the interrupt source be cleared early in
1009 //! the interrupt handler (as opposed to the very last action) to avoid
1010 //! returning from the interrupt handler before the interrupt source is
1011 //! actually cleared.  Failure to do so may result in the interrupt handler
1012 //! being immediately reentered (because the interrupt controller still sees
1013 //! the interrupt source asserted).
1014 //!
1015 //! \return None.
1016 //!
1017 //*****************************************************************************
1018 void
EEPROMIntClear(uint32_t ui32IntFlags)1019 EEPROMIntClear(uint32_t ui32IntFlags)
1020 {
1021     //
1022     // Clear the flash interrupt.
1023     //
1024     HWREG(FLASH_FCMISC) = FLASH_FCMISC_EMISC;
1025 }
1026 
1027 //*****************************************************************************
1028 //
1029 //! Returns status on the last EEPROM program or erase operation.
1030 //!
1031 //! This function returns the current status of the last program or erase
1032 //! operation performed by the EEPROM.  It is intended to provide error
1033 //! information to applications programming or setting EEPROM protection
1034 //! options under interrupt control.
1035 //!
1036 //! \return Returns 0 if the last program or erase operation completed without
1037 //! any errors.  If an operation is ongoing or an error occurred, the return
1038 //! value is a logical OR combination of \b EEPROM_RC_WRBUSY, \b
1039 //! EEPROM_RC_NOPERM, \b EEPROM_RC_WKCOPY, \b EEPROM_RC_WKERASE, and \b
1040 //! EEPROM_RC_WORKING.
1041 //!
1042 //*****************************************************************************
1043 uint32_t
EEPROMStatusGet(void)1044 EEPROMStatusGet(void)
1045 {
1046     return (HWREG(EEPROM_EEDONE));
1047 }
1048 
1049 //*****************************************************************************
1050 //
1051 // Close the Doxygen group.
1052 //! @}
1053 //
1054 //*****************************************************************************
1055