eeprom.c 38 KB

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