mpu.c 15 KB

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