eeprom.c 35 KB

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