flash.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913
  1. //*****************************************************************************
  2. //
  3. // flash.c - Driver for programming the on-chip flash.
  4. //
  5. // Copyright (c) 2005-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 8049 of the Stellaris Peripheral Driver Library.
  22. //
  23. //*****************************************************************************
  24. //*****************************************************************************
  25. //
  26. //! \addtogroup flash_api
  27. //! @{
  28. //
  29. //*****************************************************************************
  30. #include "inc/hw_flash.h"
  31. #include "inc/hw_ints.h"
  32. #include "inc/hw_sysctl.h"
  33. #include "inc/hw_types.h"
  34. #include "driverlib/debug.h"
  35. #include "driverlib/flash.h"
  36. #include "driverlib/interrupt.h"
  37. //*****************************************************************************
  38. //
  39. // An array that maps the specified memory bank to the appropriate Flash
  40. // Memory Protection Program Enable (FMPPE) register.
  41. //
  42. //*****************************************************************************
  43. static const unsigned long g_pulFMPPERegs[] =
  44. {
  45. FLASH_FMPPE,
  46. FLASH_FMPPE1,
  47. FLASH_FMPPE2,
  48. FLASH_FMPPE3
  49. };
  50. //*****************************************************************************
  51. //
  52. // An array that maps the specified memory bank to the appropriate Flash
  53. // Memory Protection Read Enable (FMPRE) register.
  54. //
  55. //*****************************************************************************
  56. static const unsigned long g_pulFMPRERegs[] =
  57. {
  58. FLASH_FMPRE,
  59. FLASH_FMPRE1,
  60. FLASH_FMPRE2,
  61. FLASH_FMPRE3
  62. };
  63. //*****************************************************************************
  64. //
  65. //! Gets the number of processor clocks per micro-second.
  66. //!
  67. //! This function returns the number of clocks per micro-second, as presently
  68. //! known by the flash controller.
  69. //!
  70. //! \return Returns the number of processor clocks per micro-second.
  71. //
  72. //*****************************************************************************
  73. unsigned long
  74. FlashUsecGet(void)
  75. {
  76. //
  77. // Return the number of clocks per micro-second.
  78. //
  79. return(HWREG(FLASH_USECRL) + 1);
  80. }
  81. //*****************************************************************************
  82. //
  83. //! Sets the number of processor clocks per micro-second.
  84. //!
  85. //! \param ulClocks is the number of processor clocks per micro-second.
  86. //!
  87. //! This function is used to tell the flash controller the number of processor
  88. //! clocks per micro-second. This value must be programmed correctly or the
  89. //! flash most likely will not program correctly; it has no affect on reading
  90. //! flash.
  91. //!
  92. //! \return None.
  93. //
  94. //*****************************************************************************
  95. void
  96. FlashUsecSet(unsigned long ulClocks)
  97. {
  98. //
  99. // Set the number of clocks per micro-second.
  100. //
  101. HWREG(FLASH_USECRL) = ulClocks - 1;
  102. }
  103. //*****************************************************************************
  104. //
  105. //! Erases a block of flash.
  106. //!
  107. //! \param ulAddress is the start address of the flash block to be erased.
  108. //!
  109. //! This function will erase a 1 kB block of the on-chip flash. After erasing,
  110. //! the block is filled with 0xFF bytes. Read-only and execute-only blocks
  111. //! cannot be erased.
  112. //!
  113. //! This function will not return until the block has been erased.
  114. //!
  115. //! \return Returns 0 on success, or -1 if an invalid block address was
  116. //! specified or the block is write-protected.
  117. //
  118. //*****************************************************************************
  119. long
  120. FlashErase(unsigned long ulAddress)
  121. {
  122. //
  123. // Check the arguments.
  124. //
  125. ASSERT(!(ulAddress & (FLASH_ERASE_SIZE - 1)));
  126. //
  127. // Clear the flash access and error interrupts.
  128. //
  129. HWREG(FLASH_FCMISC) = (FLASH_FCMISC_AMISC | FLASH_FCMISC_VOLTMISC |
  130. FLASH_FCMISC_ERMISC);
  131. //
  132. // Erase the block.
  133. //
  134. HWREG(FLASH_FMA) = ulAddress;
  135. HWREG(FLASH_FMC) = FLASH_FMC_WRKEY | FLASH_FMC_ERASE;
  136. //
  137. // Wait until the block has been erased.
  138. //
  139. while(HWREG(FLASH_FMC) & FLASH_FMC_ERASE)
  140. {
  141. }
  142. //
  143. // Return an error if an access violation or erase error occurred.
  144. //
  145. if(HWREG(FLASH_FCRIS) & (FLASH_FCRIS_ARIS | FLASH_FCRIS_VOLTRIS |
  146. FLASH_FCRIS_ERRIS))
  147. {
  148. return(-1);
  149. }
  150. //
  151. // Success.
  152. //
  153. return(0);
  154. }
  155. //*****************************************************************************
  156. //
  157. //! Programs flash.
  158. //!
  159. //! \param pulData is a pointer to the data to be programmed.
  160. //! \param ulAddress is the starting address in flash to be programmed. Must
  161. //! be a multiple of four.
  162. //! \param ulCount is the number of bytes to be programmed. Must be a multiple
  163. //! of four.
  164. //!
  165. //! This function will program a sequence of words into the on-chip flash.
  166. //! Each word in a page of flash can only be programmed one time between an
  167. //! erase of that page; programming a word multiple times will result in an
  168. //! unpredictable value in that word of flash.
  169. //!
  170. //! Since the flash is programmed one word at a time, the starting address and
  171. //! byte count must both be multiples of four. It is up to the caller to
  172. //! verify the programmed contents, if such verification is required.
  173. //!
  174. //! This function will not return until the data has been programmed.
  175. //!
  176. //! \return Returns 0 on success, or -1 if a programming error is encountered.
  177. //
  178. //*****************************************************************************
  179. long
  180. FlashProgram(unsigned long *pulData, unsigned long ulAddress,
  181. unsigned long ulCount)
  182. {
  183. //
  184. // Check the arguments.
  185. //
  186. ASSERT(!(ulAddress & 3));
  187. ASSERT(!(ulCount & 3));
  188. //
  189. // Clear the flash access and error interrupts.
  190. //
  191. HWREG(FLASH_FCMISC) = (FLASH_FCMISC_AMISC | FLASH_FCMISC_VOLTMISC |
  192. FLASH_FCMISC_INVDMISC | FLASH_FCMISC_PROGMISC);
  193. //
  194. // See if this device has a write buffer.
  195. //
  196. if(HWREG(SYSCTL_NVMSTAT) & SYSCTL_NVMSTAT_FWB)
  197. {
  198. //
  199. // Loop over the words to be programmed.
  200. //
  201. while(ulCount)
  202. {
  203. //
  204. // Set the address of this block of words.
  205. //
  206. HWREG(FLASH_FMA) = ulAddress & ~(0x7f);
  207. //
  208. // Loop over the words in this 32-word block.
  209. //
  210. while(((ulAddress & 0x7c) || (HWREG(FLASH_FWBVAL) == 0)) &&
  211. (ulCount != 0))
  212. {
  213. //
  214. // Write this word into the write buffer.
  215. //
  216. HWREG(FLASH_FWBN + (ulAddress & 0x7c)) = *pulData++;
  217. ulAddress += 4;
  218. ulCount -= 4;
  219. }
  220. //
  221. // Program the contents of the write buffer into flash.
  222. //
  223. HWREG(FLASH_FMC2) = FLASH_FMC2_WRKEY | FLASH_FMC2_WRBUF;
  224. //
  225. // Wait until the write buffer has been programmed.
  226. //
  227. while(HWREG(FLASH_FMC2) & FLASH_FMC2_WRBUF)
  228. {
  229. }
  230. }
  231. }
  232. else
  233. {
  234. //
  235. // Loop over the words to be programmed.
  236. //
  237. while(ulCount)
  238. {
  239. //
  240. // Program the next word.
  241. //
  242. HWREG(FLASH_FMA) = ulAddress;
  243. HWREG(FLASH_FMD) = *pulData;
  244. HWREG(FLASH_FMC) = FLASH_FMC_WRKEY | FLASH_FMC_WRITE;
  245. //
  246. // Wait until the word has been programmed.
  247. //
  248. while(HWREG(FLASH_FMC) & FLASH_FMC_WRITE)
  249. {
  250. }
  251. //
  252. // Increment to the next word.
  253. //
  254. pulData++;
  255. ulAddress += 4;
  256. ulCount -= 4;
  257. }
  258. }
  259. //
  260. // Return an error if an access violation occurred.
  261. //
  262. if(HWREG(FLASH_FCRIS) & (FLASH_FCRIS_ARIS | FLASH_FCRIS_VOLTRIS |
  263. FLASH_FCRIS_INVDRIS | FLASH_FCRIS_PROGRIS))
  264. {
  265. return(-1);
  266. }
  267. //
  268. // Success.
  269. //
  270. return(0);
  271. }
  272. //*****************************************************************************
  273. //
  274. //! Gets the protection setting for a block of flash.
  275. //!
  276. //! \param ulAddress is the start address of the flash block to be queried.
  277. //!
  278. //! This function will get the current protection for the specified 2 kB block
  279. //! of flash. Each block can be read/write, read-only, or execute-only.
  280. //! Read/write blocks can be read, executed, erased, and programmed. Read-only
  281. //! blocks can be read and executed. Execute-only blocks can only be executed;
  282. //! processor and debugger data reads are not allowed.
  283. //!
  284. //! \return Returns the protection setting for this block. See
  285. //! FlashProtectSet() for possible values.
  286. //
  287. //*****************************************************************************
  288. tFlashProtection
  289. FlashProtectGet(unsigned long ulAddress)
  290. {
  291. unsigned long ulFMPRE, ulFMPPE;
  292. unsigned long ulBank;
  293. //
  294. // Check the argument.
  295. //
  296. ASSERT(!(ulAddress & (FLASH_PROTECT_SIZE - 1)));
  297. //
  298. // Calculate the Flash Bank from Base Address, and mask off the Bank
  299. // from ulAddress for subsequent reference.
  300. //
  301. ulBank = (((ulAddress / FLASH_PROTECT_SIZE) / 32) % 4);
  302. ulAddress &= ((FLASH_PROTECT_SIZE * 32) - 1);
  303. //
  304. // Read the appropriate flash protection registers for the specified
  305. // flash bank.
  306. //
  307. ulFMPRE = HWREG(g_pulFMPRERegs[ulBank]);
  308. ulFMPPE = HWREG(g_pulFMPPERegs[ulBank]);
  309. //
  310. // For Stellaris Sandstorm-class devices, revision C1 and C2, the upper
  311. // bits of the FMPPE register are used for JTAG protect options, and are
  312. // not available for the FLASH protection scheme. When Querying Block
  313. // Protection, assume these bits are 1.
  314. //
  315. if(CLASS_IS_SANDSTORM && (REVISION_IS_C1 || REVISION_IS_C2))
  316. {
  317. ulFMPRE |= (FLASH_FMP_BLOCK_31 | FLASH_FMP_BLOCK_30);
  318. }
  319. //
  320. // Check the appropriate protection bits for the block of memory that
  321. // is specified by the address.
  322. //
  323. switch((((ulFMPRE >> (ulAddress / FLASH_PROTECT_SIZE)) &
  324. FLASH_FMP_BLOCK_0) << 1) |
  325. ((ulFMPPE >> (ulAddress / FLASH_PROTECT_SIZE)) & FLASH_FMP_BLOCK_0))
  326. {
  327. //
  328. // This block is marked as execute only (that is, it can not be erased
  329. // or programmed, and the only reads allowed are via the instruction
  330. // fetch interface).
  331. //
  332. case 0:
  333. case 1:
  334. {
  335. return(FlashExecuteOnly);
  336. }
  337. //
  338. // This block is marked as read only (that is, it can not be erased or
  339. // programmed).
  340. //
  341. case 2:
  342. {
  343. return(FlashReadOnly);
  344. }
  345. //
  346. // This block is read/write; it can be read, erased, and programmed.
  347. //
  348. case 3:
  349. default:
  350. {
  351. return(FlashReadWrite);
  352. }
  353. }
  354. }
  355. //*****************************************************************************
  356. //
  357. //! Sets the protection setting for a block of flash.
  358. //!
  359. //! \param ulAddress is the start address of the flash block to be protected.
  360. //! \param eProtect is the protection to be applied to the block. Can be one
  361. //! of \b FlashReadWrite, \b FlashReadOnly, or \b FlashExecuteOnly.
  362. //!
  363. //! This function will set the protection for the specified 2 kB block of
  364. //! flash. Blocks which are read/write can be made read-only or execute-only.
  365. //! Blocks which are read-only can be made execute-only. Blocks which are
  366. //! execute-only cannot have their protection modified. Attempts to make the
  367. //! block protection less stringent (that is, read-only to read/write) will
  368. //! result in a failure (and be prevented by the hardware).
  369. //!
  370. //! Changes to the flash protection are maintained only until the next reset.
  371. //! This allows the application to be executed in the desired flash protection
  372. //! environment to check for inappropriate flash access (via the flash
  373. //! interrupt). To make the flash protection permanent, use the
  374. //! FlashProtectSave() function.
  375. //!
  376. //! \return Returns 0 on success, or -1 if an invalid address or an invalid
  377. //! protection was specified.
  378. //
  379. //*****************************************************************************
  380. long
  381. FlashProtectSet(unsigned long ulAddress, tFlashProtection eProtect)
  382. {
  383. unsigned long ulProtectRE, ulProtectPE;
  384. unsigned long ulBank;
  385. //
  386. // Check the argument.
  387. //
  388. ASSERT(!(ulAddress & (FLASH_PROTECT_SIZE - 1)));
  389. ASSERT((eProtect == FlashReadWrite) || (eProtect == FlashReadOnly) ||
  390. (eProtect == FlashExecuteOnly));
  391. //
  392. // Convert the address into a block number.
  393. //
  394. ulAddress /= FLASH_PROTECT_SIZE;
  395. //
  396. // ulAddress contains a "raw" block number. Derive the Flash Bank from
  397. // the "raw" block number, and convert ulAddress to a "relative"
  398. // block number.
  399. //
  400. ulBank = ((ulAddress / 32) % 4);
  401. ulAddress %= 32;
  402. //
  403. // Get the current protection for the specified flash bank.
  404. //
  405. ulProtectRE = HWREG(g_pulFMPRERegs[ulBank]);
  406. ulProtectPE = HWREG(g_pulFMPPERegs[ulBank]);
  407. //
  408. // For Stellaris Sandstorm-class devices, revision C1 and C2, the upper
  409. // bits of the FMPPE register are used for JTAG protect options, and are
  410. // not available for the FLASH protection scheme. When setting protection,
  411. // check to see if block 30 or 31 and protection is FlashExecuteOnly. If
  412. // so, return an error condition.
  413. //
  414. if(CLASS_IS_SANDSTORM && (REVISION_IS_C1 || REVISION_IS_C2))
  415. {
  416. if((ulAddress >= 30) && (eProtect == FlashExecuteOnly))
  417. {
  418. return(-1);
  419. }
  420. }
  421. //
  422. // Set the protection based on the requested proection.
  423. //
  424. switch(eProtect)
  425. {
  426. //
  427. // Make this block execute only.
  428. //
  429. case FlashExecuteOnly:
  430. {
  431. //
  432. // Turn off the read and program bits for this block.
  433. //
  434. ulProtectRE &= ~(FLASH_FMP_BLOCK_0 << ulAddress);
  435. ulProtectPE &= ~(FLASH_FMP_BLOCK_0 << ulAddress);
  436. //
  437. // We're done handling this protection.
  438. //
  439. break;
  440. }
  441. //
  442. // Make this block read only.
  443. //
  444. case FlashReadOnly:
  445. {
  446. //
  447. // The block can not be made read only if it is execute only.
  448. //
  449. if(((ulProtectRE >> ulAddress) & FLASH_FMP_BLOCK_0) !=
  450. FLASH_FMP_BLOCK_0)
  451. {
  452. return(-1);
  453. }
  454. //
  455. // Make this block read only.
  456. //
  457. ulProtectPE &= ~(FLASH_FMP_BLOCK_0 << ulAddress);
  458. //
  459. // We're done handling this protection.
  460. //
  461. break;
  462. }
  463. //
  464. // Make this block read/write.
  465. //
  466. case FlashReadWrite:
  467. default:
  468. {
  469. //
  470. // The block can not be made read/write if it is not already
  471. // read/write.
  472. //
  473. if((((ulProtectRE >> ulAddress) & FLASH_FMP_BLOCK_0) !=
  474. FLASH_FMP_BLOCK_0) ||
  475. (((ulProtectPE >> ulAddress) & FLASH_FMP_BLOCK_0) !=
  476. FLASH_FMP_BLOCK_0))
  477. {
  478. return(-1);
  479. }
  480. //
  481. // The block is already read/write, so there is nothing to do.
  482. //
  483. return(0);
  484. }
  485. }
  486. //
  487. // For Stellaris Sandstorm-class devices, revision C1 and C2, the upper
  488. // bits of the FMPPE register are used for JTAG options, and are not
  489. // available for the FLASH protection scheme. When setting block
  490. // protection, ensure that these bits are not altered.
  491. //
  492. if(CLASS_IS_SANDSTORM && (REVISION_IS_C1 || REVISION_IS_C2))
  493. {
  494. ulProtectRE &= ~(FLASH_FMP_BLOCK_31 | FLASH_FMP_BLOCK_30);
  495. ulProtectRE |= (HWREG(g_pulFMPRERegs[ulBank]) &
  496. (FLASH_FMP_BLOCK_31 | FLASH_FMP_BLOCK_30));
  497. }
  498. //
  499. // Set the new protection for the specified flash bank.
  500. //
  501. HWREG(g_pulFMPRERegs[ulBank]) = ulProtectRE;
  502. HWREG(g_pulFMPPERegs[ulBank]) = ulProtectPE;
  503. //
  504. // Success.
  505. //
  506. return(0);
  507. }
  508. //*****************************************************************************
  509. //
  510. //! Saves the flash protection settings.
  511. //!
  512. //! This function will make the currently programmed flash protection settings
  513. //! permanent. This is a non-reversible operation; a chip reset or power cycle
  514. //! will not change the flash protection.
  515. //!
  516. //! This function will not return until the protection has been saved.
  517. //!
  518. //! \return Returns 0 on success, or -1 if a hardware error is encountered.
  519. //
  520. //*****************************************************************************
  521. long
  522. FlashProtectSave(void)
  523. {
  524. unsigned long ulTemp, ulLimit;
  525. //
  526. // If running on a Sandstorm-class device, only trigger a save of the first
  527. // two protection registers (FMPRE and FMPPE). Otherwise, save the
  528. // entire bank of flash protection registers.
  529. //
  530. ulLimit = CLASS_IS_SANDSTORM ? 2 : 8;
  531. for(ulTemp = 0; ulTemp < ulLimit; ulTemp++)
  532. {
  533. //
  534. // Tell the flash controller to write the flash protection register.
  535. //
  536. HWREG(FLASH_FMA) = ulTemp;
  537. HWREG(FLASH_FMC) = FLASH_FMC_WRKEY | FLASH_FMC_COMT;
  538. //
  539. // Wait until the write has completed.
  540. //
  541. while(HWREG(FLASH_FMC) & FLASH_FMC_COMT)
  542. {
  543. }
  544. }
  545. //
  546. // Success.
  547. //
  548. return(0);
  549. }
  550. //*****************************************************************************
  551. //
  552. //! Gets the user registers.
  553. //!
  554. //! \param pulUser0 is a pointer to the location to store USER Register 0.
  555. //! \param pulUser1 is a pointer to the location to store USER Register 1.
  556. //!
  557. //! This function will read the contents of user registers (0 and 1), and
  558. //! store them in the specified locations.
  559. //!
  560. //! \return Returns 0 on success, or -1 if a hardware error is encountered.
  561. //
  562. //*****************************************************************************
  563. long
  564. FlashUserGet(unsigned long *pulUser0, unsigned long *pulUser1)
  565. {
  566. //
  567. // Verify that the pointers are valid.
  568. //
  569. ASSERT(pulUser0 != 0);
  570. ASSERT(pulUser1 != 0);
  571. //
  572. // Verify that hardware supports user registers.
  573. //
  574. if(CLASS_IS_SANDSTORM)
  575. {
  576. return(-1);
  577. }
  578. //
  579. // Get and store the current value of the user registers.
  580. //
  581. *pulUser0 = HWREG(FLASH_USERREG0);
  582. *pulUser1 = HWREG(FLASH_USERREG1);
  583. //
  584. // Success.
  585. //
  586. return(0);
  587. }
  588. //*****************************************************************************
  589. //
  590. //! Sets the user registers.
  591. //!
  592. //! \param ulUser0 is the value to store in USER Register 0.
  593. //! \param ulUser1 is the value to store in USER Register 1.
  594. //!
  595. //! This function will set the contents of the user registers (0 and 1) to
  596. //! the specified values.
  597. //!
  598. //! \return Returns 0 on success, or -1 if a hardware error is encountered.
  599. //
  600. //*****************************************************************************
  601. long
  602. FlashUserSet(unsigned long ulUser0, unsigned long ulUser1)
  603. {
  604. //
  605. // Verify that hardware supports user registers.
  606. //
  607. if(CLASS_IS_SANDSTORM)
  608. {
  609. return(-1);
  610. }
  611. //
  612. // Save the new values into the user registers.
  613. //
  614. HWREG(FLASH_USERREG0) = ulUser0;
  615. HWREG(FLASH_USERREG1) = ulUser1;
  616. //
  617. // Success.
  618. //
  619. return(0);
  620. }
  621. //*****************************************************************************
  622. //
  623. //! Saves the user registers.
  624. //!
  625. //! This function will make the currently programmed user register settings
  626. //! permanent. This is a non-reversible operation; a chip reset or power cycle
  627. //! will not change this setting.
  628. //!
  629. //! This function will not return until the protection has been saved.
  630. //!
  631. //! \return Returns 0 on success, or -1 if a hardware error is encountered.
  632. //
  633. //*****************************************************************************
  634. long
  635. FlashUserSave(void)
  636. {
  637. //
  638. // Verify that hardware supports user registers.
  639. //
  640. if(CLASS_IS_SANDSTORM)
  641. {
  642. return(-1);
  643. }
  644. //
  645. // Setting the MSB of FMA will trigger a permanent save of a USER
  646. // register. Bit 0 will indicate User 0 (0) or User 1 (1).
  647. //
  648. HWREG(FLASH_FMA) = 0x80000000;
  649. HWREG(FLASH_FMC) = FLASH_FMC_WRKEY | FLASH_FMC_COMT;
  650. //
  651. // Wait until the write has completed.
  652. //
  653. while(HWREG(FLASH_FMC) & FLASH_FMC_COMT)
  654. {
  655. }
  656. //
  657. // Tell the flash controller to write the USER1 Register.
  658. //
  659. HWREG(FLASH_FMA) = 0x80000001;
  660. HWREG(FLASH_FMC) = FLASH_FMC_WRKEY | FLASH_FMC_COMT;
  661. //
  662. // Wait until the write has completed.
  663. //
  664. while(HWREG(FLASH_FMC) & FLASH_FMC_COMT)
  665. {
  666. }
  667. //
  668. // Success.
  669. //
  670. return(0);
  671. }
  672. //*****************************************************************************
  673. //
  674. //! Registers an interrupt handler for the flash interrupt.
  675. //!
  676. //! \param pfnHandler is a pointer to the function to be called when the flash
  677. //! interrupt occurs.
  678. //!
  679. //! This sets the handler to be called when the flash interrupt occurs. The
  680. //! flash controller can generate an interrupt when an invalid flash access
  681. //! occurs, such as trying to program or erase a read-only block, or trying to
  682. //! read from an execute-only block. It can also generate an interrupt when a
  683. //! program or erase operation has completed. The interrupt is automatically
  684. //! enabled when the handler is registered.
  685. //!
  686. //! \sa IntRegister() for important information about registering interrupt
  687. //! handlers.
  688. //!
  689. //! \return None.
  690. //
  691. //*****************************************************************************
  692. void
  693. FlashIntRegister(void (*pfnHandler)(void))
  694. {
  695. //
  696. // Register the interrupt handler, returning an error if an error occurs.
  697. //
  698. IntRegister(INT_FLASH, pfnHandler);
  699. //
  700. // Enable the flash interrupt.
  701. //
  702. IntEnable(INT_FLASH);
  703. }
  704. //*****************************************************************************
  705. //
  706. //! Unregisters the interrupt handler for the flash interrupt.
  707. //!
  708. //! This function will clear the handler to be called when the flash interrupt
  709. //! occurs. This will also mask off the interrupt in the interrupt controller
  710. //! so that the interrupt handler is no longer called.
  711. //!
  712. //! \sa IntRegister() for important information about registering interrupt
  713. //! handlers.
  714. //!
  715. //! \return None.
  716. //
  717. //*****************************************************************************
  718. void
  719. FlashIntUnregister(void)
  720. {
  721. //
  722. // Disable the interrupt.
  723. //
  724. IntDisable(INT_FLASH);
  725. //
  726. // Unregister the interrupt handler.
  727. //
  728. IntUnregister(INT_FLASH);
  729. }
  730. //*****************************************************************************
  731. //
  732. //! Enables individual flash controller interrupt sources.
  733. //!
  734. //! \param ulIntFlags is a bit mask of the interrupt sources to be enabled.
  735. //! Can be any of the \b FLASH_INT_PROGRAM or \b FLASH_INT_ACCESS values.
  736. //!
  737. //! Enables the indicated flash controller interrupt sources. Only the sources
  738. //! that are enabled can be reflected to the processor interrupt; disabled
  739. //! sources have no effect on the processor.
  740. //!
  741. //! \return None.
  742. //
  743. //*****************************************************************************
  744. void
  745. FlashIntEnable(unsigned long ulIntFlags)
  746. {
  747. //
  748. // Enable the specified interrupts.
  749. //
  750. HWREG(FLASH_FCIM) |= ulIntFlags;
  751. }
  752. //*****************************************************************************
  753. //
  754. //! Disables individual flash controller interrupt sources.
  755. //!
  756. //! \param ulIntFlags is a bit mask of the interrupt sources to be disabled.
  757. //! Can be any of the \b FLASH_INT_PROGRAM or \b FLASH_INT_ACCESS values.
  758. //!
  759. //! Disables the indicated flash controller interrupt sources. Only the
  760. //! sources that are enabled can be reflected to the processor interrupt;
  761. //! disabled sources have no effect on the processor.
  762. //!
  763. //! \return None.
  764. //
  765. //*****************************************************************************
  766. void
  767. FlashIntDisable(unsigned long ulIntFlags)
  768. {
  769. //
  770. // Disable the specified interrupts.
  771. //
  772. HWREG(FLASH_FCIM) &= ~(ulIntFlags);
  773. }
  774. //*****************************************************************************
  775. //
  776. //! Gets the current interrupt status.
  777. //!
  778. //! \param bMasked is false if the raw interrupt status is required and true if
  779. //! the masked interrupt status is required.
  780. //!
  781. //! This returns the interrupt status for the flash controller. Either the raw
  782. //! interrupt status or the status of interrupts that are allowed to reflect to
  783. //! the processor can be returned.
  784. //!
  785. //! \return The current interrupt status, enumerated as a bit field of
  786. //! \b FLASH_INT_PROGRAM and \b FLASH_INT_ACCESS.
  787. //
  788. //*****************************************************************************
  789. unsigned long
  790. FlashIntStatus(tBoolean bMasked)
  791. {
  792. //
  793. // Return either the interrupt status or the raw interrupt status as
  794. // requested.
  795. //
  796. if(bMasked)
  797. {
  798. return(HWREG(FLASH_FCMISC));
  799. }
  800. else
  801. {
  802. return(HWREG(FLASH_FCRIS));
  803. }
  804. }
  805. //*****************************************************************************
  806. //
  807. //! Clears flash controller interrupt sources.
  808. //!
  809. //! \param ulIntFlags is the bit mask of the interrupt sources to be cleared.
  810. //! Can be any of the \b FLASH_INT_PROGRAM or \b FLASH_INT_AMISC values.
  811. //!
  812. //! The specified flash controller interrupt sources are cleared, so that they
  813. //! no longer assert. This must be done in the interrupt handler to keep it
  814. //! from being called again immediately upon exit.
  815. //!
  816. //! \note Because there is a write buffer in the Cortex-M3 processor, it may
  817. //! take several clock cycles before the interrupt source is actually cleared.
  818. //! Therefore, it is recommended that the interrupt source be cleared early in
  819. //! the interrupt handler (as opposed to the very last action) to avoid
  820. //! returning from the interrupt handler before the interrupt source is
  821. //! actually cleared. Failure to do so may result in the interrupt handler
  822. //! being immediately reentered (because the interrupt controller still sees
  823. //! the interrupt source asserted).
  824. //!
  825. //! \return None.
  826. //
  827. //*****************************************************************************
  828. void
  829. FlashIntClear(unsigned long ulIntFlags)
  830. {
  831. //
  832. // Clear the flash interrupt.
  833. //
  834. HWREG(FLASH_FCMISC) = ulIntFlags;
  835. }
  836. //*****************************************************************************
  837. //
  838. // Close the Doxygen group.
  839. //! @}
  840. //
  841. //*****************************************************************************