mpu.c 15 KB

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