mpu.c 15 KB

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