eeprom.c 37 KB

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