mpu.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. //*****************************************************************************
  2. //
  3. // mpu.c - Driver for the Cortex-M3 memory protection unit (MPU).
  4. //
  5. // Copyright (c) 2007-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. //*****************************************************************************
  25. //
  26. //! \addtogroup mpu_api
  27. //! @{
  28. //
  29. //*****************************************************************************
  30. #include "inc/hw_ints.h"
  31. #include "inc/hw_nvic.h"
  32. #include "inc/hw_types.h"
  33. #include "driverlib/debug.h"
  34. #include "driverlib/interrupt.h"
  35. #include "driverlib/mpu.h"
  36. //*****************************************************************************
  37. //
  38. //! Enables and configures the MPU for use.
  39. //!
  40. //! \param ulMPUConfig is the logical OR of the possible configurations.
  41. //!
  42. //! This function enables the Cortex-M memory protection unit. It also
  43. //! configures the default behavior when in privileged mode and while handling
  44. //! a hard fault or NMI. Prior to enabling the MPU, at least one region must
  45. //! be set by calling MPURegionSet() or else by enabling the default region for
  46. //! privileged mode by passing the \b MPU_CONFIG_PRIV_DEFAULT flag to
  47. //! MPUEnable(). Once the MPU is enabled, a memory management fault is
  48. //! generated for memory access violations.
  49. //!
  50. //! The \e ulMPUConfig parameter should be the logical OR of any of the
  51. //! following:
  52. //!
  53. //! - \b MPU_CONFIG_PRIV_DEFAULT enables the default memory map when in
  54. //! privileged mode and when no other regions are defined. If this option
  55. //! is not enabled, then there must be at least one valid region already
  56. //! defined when the MPU is enabled.
  57. //! - \b MPU_CONFIG_HARDFLT_NMI enables the MPU while in a hard fault or NMI
  58. //! exception handler. If this option is not enabled, then the MPU is
  59. //! disabled while in one of these exception handlers and the default
  60. //! memory map is applied.
  61. //! - \b MPU_CONFIG_NONE chooses none of the above options. In this case,
  62. //! no default memory map is provided in privileged mode, and the MPU isl
  63. //! not enabled in the fault handlers.
  64. //!
  65. //! \return None.
  66. //
  67. //*****************************************************************************
  68. void
  69. MPUEnable(unsigned long ulMPUConfig)
  70. {
  71. //
  72. // Check the arguments.
  73. //
  74. ASSERT(!(ulMPUConfig & ~(MPU_CONFIG_PRIV_DEFAULT |
  75. MPU_CONFIG_HARDFLT_NMI)));
  76. //
  77. // Set the MPU control bits according to the flags passed by the user,
  78. // and also set the enable bit.
  79. //
  80. HWREG(NVIC_MPU_CTRL) = ulMPUConfig | NVIC_MPU_CTRL_ENABLE;
  81. }
  82. //*****************************************************************************
  83. //
  84. //! Disables the MPU for use.
  85. //!
  86. //! This function disables the Cortex-M memory protection unit. When the
  87. //! MPU is disabled, the default memory map is used and memory management
  88. //! faults are not generated.
  89. //!
  90. //! \return None.
  91. //
  92. //*****************************************************************************
  93. void
  94. MPUDisable(void)
  95. {
  96. //
  97. // Turn off the MPU enable bit.
  98. //
  99. HWREG(NVIC_MPU_CTRL) &= ~NVIC_MPU_CTRL_ENABLE;
  100. }
  101. //*****************************************************************************
  102. //
  103. //! Gets the count of regions supported by the MPU.
  104. //!
  105. //! This function is used to get the total number of regions that are supported
  106. //! by the MPU, including regions that are already programmed.
  107. //!
  108. //! \return The number of memory protection regions that are available
  109. //! for programming using MPURegionSet().
  110. //
  111. //*****************************************************************************
  112. unsigned long
  113. MPURegionCountGet(void)
  114. {
  115. //
  116. // Read the DREGION field of the MPU type register and mask off
  117. // the bits of interest to get the count of regions.
  118. //
  119. return((HWREG(NVIC_MPU_TYPE) & NVIC_MPU_TYPE_DREGION_M)
  120. >> NVIC_MPU_TYPE_DREGION_S);
  121. }
  122. //*****************************************************************************
  123. //
  124. //! Enables a specific region.
  125. //!
  126. //! \param ulRegion is the region number to enable.
  127. //!
  128. //! This function is used to enable a memory protection region. The region
  129. //! should already be configured with the MPURegionSet() function. Once
  130. //! enabled, the memory protection rules of the region are applied and access
  131. //! violations cause a memory management fault.
  132. //!
  133. //! \return None.
  134. //
  135. //*****************************************************************************
  136. void
  137. MPURegionEnable(unsigned long ulRegion)
  138. {
  139. //
  140. // Check the arguments.
  141. //
  142. ASSERT(ulRegion < 8);
  143. //
  144. // Select the region to modify.
  145. //
  146. HWREG(NVIC_MPU_NUMBER) = ulRegion;
  147. //
  148. // Modify the enable bit in the region attributes.
  149. //
  150. HWREG(NVIC_MPU_ATTR) |= NVIC_MPU_ATTR_ENABLE;
  151. }
  152. //*****************************************************************************
  153. //
  154. //! Disables a specific region.
  155. //!
  156. //! \param ulRegion is the region number to disable.
  157. //!
  158. //! This function is used to disable a previously enabled memory protection
  159. //! region. The region remains configured if it is not overwritten with
  160. //! another call to MPURegionSet(), and can be enabled again by calling
  161. //! MPURegionEnable().
  162. //!
  163. //! \return None.
  164. //
  165. //*****************************************************************************
  166. void
  167. MPURegionDisable(unsigned long ulRegion)
  168. {
  169. //
  170. // Check the arguments.
  171. //
  172. ASSERT(ulRegion < 8);
  173. //
  174. // Select the region to modify.
  175. //
  176. HWREG(NVIC_MPU_NUMBER) = ulRegion;
  177. //
  178. // Modify the enable bit in the region attributes.
  179. //
  180. HWREG(NVIC_MPU_ATTR) &= ~NVIC_MPU_ATTR_ENABLE;
  181. }
  182. //*****************************************************************************
  183. //
  184. //! Sets up the access rules for a specific region.
  185. //!
  186. //! \param ulRegion is the region number to set up.
  187. //! \param ulAddr is the base address of the region. It must be aligned
  188. //! according to the size of the region specified in ulFlags.
  189. //! \param ulFlags is a set of flags to define the attributes of the region.
  190. //!
  191. //! This function sets up the protection rules for a region. The region has
  192. //! a base address and a set of attributes including the size. The base
  193. //! address parameter, \e ulAddr, must be aligned according to the size, and
  194. //! the size must be a power of 2.
  195. //!
  196. //! The \e ulFlags parameter is the logical OR of all of the attributes
  197. //! of the region. It is a combination of choices for region size,
  198. //! execute permission, read/write permissions, disabled sub-regions,
  199. //! and a flag to determine if the region is enabled.
  200. //!
  201. //! The size flag determines the size of a region and must be one of the
  202. //! following:
  203. //!
  204. //! - \b MPU_RGN_SIZE_32B
  205. //! - \b MPU_RGN_SIZE_64B
  206. //! - \b MPU_RGN_SIZE_128B
  207. //! - \b MPU_RGN_SIZE_256B
  208. //! - \b MPU_RGN_SIZE_512B
  209. //! - \b MPU_RGN_SIZE_1K
  210. //! - \b MPU_RGN_SIZE_2K
  211. //! - \b MPU_RGN_SIZE_4K
  212. //! - \b MPU_RGN_SIZE_8K
  213. //! - \b MPU_RGN_SIZE_16K
  214. //! - \b MPU_RGN_SIZE_32K
  215. //! - \b MPU_RGN_SIZE_64K
  216. //! - \b MPU_RGN_SIZE_128K
  217. //! - \b MPU_RGN_SIZE_256K
  218. //! - \b MPU_RGN_SIZE_512K
  219. //! - \b MPU_RGN_SIZE_1M
  220. //! - \b MPU_RGN_SIZE_2M
  221. //! - \b MPU_RGN_SIZE_4M
  222. //! - \b MPU_RGN_SIZE_8M
  223. //! - \b MPU_RGN_SIZE_16M
  224. //! - \b MPU_RGN_SIZE_32M
  225. //! - \b MPU_RGN_SIZE_64M
  226. //! - \b MPU_RGN_SIZE_128M
  227. //! - \b MPU_RGN_SIZE_256M
  228. //! - \b MPU_RGN_SIZE_512M
  229. //! - \b MPU_RGN_SIZE_1G
  230. //! - \b MPU_RGN_SIZE_2G
  231. //! - \b MPU_RGN_SIZE_4G
  232. //!
  233. //! The execute permission flag must be one of the following:
  234. //!
  235. //! - \b MPU_RGN_PERM_EXEC enables the region for execution of code
  236. //! - \b MPU_RGN_PERM_NOEXEC disables the region for execution of code
  237. //!
  238. //! The read/write access permissions are applied separately for the
  239. //! privileged and user modes. The read/write access flags must be one
  240. //! of the following:
  241. //!
  242. //! - \b MPU_RGN_PERM_PRV_NO_USR_NO - no access in privileged or user mode
  243. //! - \b MPU_RGN_PERM_PRV_RW_USR_NO - privileged read/write, user no access
  244. //! - \b MPU_RGN_PERM_PRV_RW_USR_RO - privileged read/write, user read-only
  245. //! - \b MPU_RGN_PERM_PRV_RW_USR_RW - privileged read/write, user read/write
  246. //! - \b MPU_RGN_PERM_PRV_RO_USR_NO - privileged read-only, user no access
  247. //! - \b MPU_RGN_PERM_PRV_RO_USR_RO - privileged read-only, user read-only
  248. //!
  249. //! The region is automatically divided into 8 equally-sized sub-regions by
  250. //! the MPU. Sub-regions can only be used in regions of size 256 bytes
  251. //! or larger. Any of these 8 sub-regions can be disabled, allowing for
  252. //! creation of ``holes'' in a region which can be left open, or overlaid
  253. //! by another region with different attributes. Any of the 8 sub-regions
  254. //! can be disabled with a logical OR of any of the following flags:
  255. //!
  256. //! - \b MPU_SUB_RGN_DISABLE_0
  257. //! - \b MPU_SUB_RGN_DISABLE_1
  258. //! - \b MPU_SUB_RGN_DISABLE_2
  259. //! - \b MPU_SUB_RGN_DISABLE_3
  260. //! - \b MPU_SUB_RGN_DISABLE_4
  261. //! - \b MPU_SUB_RGN_DISABLE_5
  262. //! - \b MPU_SUB_RGN_DISABLE_6
  263. //! - \b MPU_SUB_RGN_DISABLE_7
  264. //!
  265. //! Finally, the region can be initially enabled or disabled with one of
  266. //! the following flags:
  267. //!
  268. //! - \b MPU_RGN_ENABLE
  269. //! - \b MPU_RGN_DISABLE
  270. //!
  271. //! As an example, to set a region with the following attributes: size of
  272. //! 32 KB, execution enabled, read-only for both privileged and user, one
  273. //! sub-region disabled, and initially enabled; the \e ulFlags parameter would
  274. //! have the following value:
  275. //!
  276. //! <code>
  277. //! (MPU_RG_SIZE_32K | MPU_RGN_PERM_EXEC | MPU_RGN_PERM_PRV_RO_USR_RO |
  278. //! MPU_SUB_RGN_DISABLE_2 | MPU_RGN_ENABLE)
  279. //! </code>
  280. //!
  281. //! \note This function writes to multiple registers and is not protected
  282. //! from interrupts. It is possible that an interrupt which accesses a
  283. //! region may occur while that region is in the process of being changed.
  284. //! The safest way to handle this is to disable a region before changing it.
  285. //! Refer to the discussion of this in the API Detailed Description section.
  286. //!
  287. //! \return None.
  288. //
  289. //*****************************************************************************
  290. void
  291. MPURegionSet(unsigned long ulRegion, unsigned long ulAddr,
  292. unsigned long ulFlags)
  293. {
  294. //
  295. // Check the arguments.
  296. //
  297. ASSERT(ulRegion < 8);
  298. ASSERT((ulAddr & ~0 << (((ulFlags & NVIC_MPU_ATTR_SIZE_M) >> 1) + 1))
  299. == ulAddr);
  300. //
  301. // Program the base address, use the region field to select the
  302. // region at the same time.
  303. //
  304. HWREG(NVIC_MPU_BASE) = ulAddr | ulRegion | NVIC_MPU_BASE_VALID;
  305. //
  306. // Program the region attributes. Set the TEX field and the S, C,
  307. // and B bits to fixed values that are suitable for all Stellaris
  308. // memory.
  309. //
  310. HWREG(NVIC_MPU_ATTR) = (ulFlags & ~(NVIC_MPU_ATTR_TEX_M |
  311. NVIC_MPU_ATTR_CACHEABLE)) |
  312. NVIC_MPU_ATTR_SHAREABLE |
  313. NVIC_MPU_ATTR_BUFFRABLE;
  314. }
  315. //*****************************************************************************
  316. //
  317. //! Gets the current settings for a specific region.
  318. //!
  319. //! \param ulRegion is the region number to get.
  320. //! \param pulAddr points to storage for the base address of the region.
  321. //! \param pulFlags points to the attribute flags for the region.
  322. //!
  323. //! This function retrieves the configuration of a specific region. The
  324. //! meanings and format of the parameters is the same as that of the
  325. //! MPURegionSet() function.
  326. //!
  327. //! This function can be used to save the configuration of a region for later
  328. //! use with the MPURegionSet() function. The region's enable state is
  329. //! preserved in the attributes that are saved.
  330. //!
  331. //! \return None.
  332. //
  333. //*****************************************************************************
  334. void
  335. MPURegionGet(unsigned long ulRegion, unsigned long *pulAddr,
  336. unsigned long *pulFlags)
  337. {
  338. //
  339. // Check the arguments.
  340. //
  341. ASSERT(ulRegion < 8);
  342. ASSERT(pulAddr);
  343. ASSERT(pulFlags);
  344. //
  345. // Select the region to get.
  346. //
  347. HWREG(NVIC_MPU_NUMBER) = ulRegion;
  348. //
  349. // Read and store the base address for the region.
  350. //
  351. *pulAddr = HWREG(NVIC_MPU_BASE);
  352. //
  353. // Read and store the region attributes.
  354. //
  355. *pulFlags = HWREG(NVIC_MPU_ATTR);
  356. }
  357. //*****************************************************************************
  358. //
  359. //! Registers an interrupt handler for the memory management fault.
  360. //!
  361. //! \param pfnHandler is a pointer to the function to be called when the
  362. //! memory management fault occurs.
  363. //!
  364. //! This function sets and enables the handler to be called when the MPU
  365. //! generates a memory management fault due to a protection region access
  366. //! violation.
  367. //!
  368. //! \sa IntRegister() for important information about registering interrupt
  369. //! handlers.
  370. //!
  371. //! \return None.
  372. //
  373. //*****************************************************************************
  374. void
  375. MPUIntRegister(void (*pfnHandler)(void))
  376. {
  377. //
  378. // Check the arguments.
  379. //
  380. ASSERT(pfnHandler);
  381. //
  382. // Register the interrupt handler.
  383. //
  384. IntRegister(FAULT_MPU, pfnHandler);
  385. //
  386. // Enable the memory management fault.
  387. //
  388. IntEnable(FAULT_MPU);
  389. }
  390. //*****************************************************************************
  391. //
  392. //! Unregisters an interrupt handler for the memory management fault.
  393. //!
  394. //! This function disables and clears the handler to be called when a
  395. //! memory management fault occurs.
  396. //!
  397. //! \sa IntRegister() for important information about registering interrupt
  398. //! handlers.
  399. //!
  400. //! \return None.
  401. //
  402. //*****************************************************************************
  403. void
  404. MPUIntUnregister(void)
  405. {
  406. //
  407. // Disable the interrupt.
  408. //
  409. IntDisable(FAULT_MPU);
  410. //
  411. // Unregister the interrupt handler.
  412. //
  413. IntUnregister(FAULT_MPU);
  414. }
  415. //*****************************************************************************
  416. //
  417. // Close the Doxygen group.
  418. //! @}
  419. //
  420. //*****************************************************************************