123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459 |
- //*****************************************************************************
- //
- // mpu.c - Driver for the Cortex-M3 memory protection unit (MPU).
- //
- // Copyright (c) 2007-2020 Texas Instruments Incorporated. All rights reserved.
- // Software License Agreement
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions
- // are met:
- //
- // Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- //
- // Redistributions in binary form must reproduce the above copyright
- // notice, this list of conditions and the following disclaimer in the
- // documentation and/or other materials provided with the
- // distribution.
- //
- // Neither the name of Texas Instruments Incorporated nor the names of
- // its contributors may be used to endorse or promote products derived
- // from this software without specific prior written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- //
- // This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library.
- //
- //*****************************************************************************
- //*****************************************************************************
- //
- //! \addtogroup mpu_api
- //! @{
- //
- //*****************************************************************************
- #include <stdbool.h>
- #include <stdint.h>
- #include "inc/hw_ints.h"
- #include "inc/hw_nvic.h"
- #include "inc/hw_types.h"
- #include "driverlib/debug.h"
- #include "driverlib/interrupt.h"
- #include "driverlib/mpu.h"
- //*****************************************************************************
- //
- //! Enables and configures the MPU for use.
- //!
- //! \param ui32MPUConfig is the logical OR of the possible configurations.
- //!
- //! This function enables the Cortex-M memory protection unit. It also
- //! configures the default behavior when in privileged mode and while handling
- //! a hard fault or NMI. Prior to enabling the MPU, at least one region must
- //! be set by calling MPURegionSet() or else by enabling the default region for
- //! privileged mode by passing the \b MPU_CONFIG_PRIV_DEFAULT flag to
- //! MPUEnable(). Once the MPU is enabled, a memory management fault is
- //! generated for memory access violations.
- //!
- //! The \e ui32MPUConfig parameter should be the logical OR of any of the
- //! following:
- //!
- //! - \b MPU_CONFIG_PRIV_DEFAULT enables the default memory map when in
- //! privileged mode and when no other regions are defined. If this option
- //! is not enabled, then there must be at least one valid region already
- //! defined when the MPU is enabled.
- //! - \b MPU_CONFIG_HARDFLT_NMI enables the MPU while in a hard fault or NMI
- //! exception handler. If this option is not enabled, then the MPU is
- //! disabled while in one of these exception handlers and the default
- //! memory map is applied.
- //! - \b MPU_CONFIG_NONE chooses none of the above options. In this case,
- //! no default memory map is provided in privileged mode, and the MPU is not
- //! enabled in the fault handlers.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- MPUEnable(uint32_t ui32MPUConfig)
- {
- //
- // Check the arguments.
- //
- ASSERT(!(ui32MPUConfig & ~(MPU_CONFIG_PRIV_DEFAULT |
- MPU_CONFIG_HARDFLT_NMI)));
- //
- // Set the MPU control bits according to the flags passed by the user,
- // and also set the enable bit.
- //
- HWREG(NVIC_MPU_CTRL) = ui32MPUConfig | NVIC_MPU_CTRL_ENABLE;
- }
- //*****************************************************************************
- //
- //! Disables the MPU for use.
- //!
- //! This function disables the Cortex-M memory protection unit. When the
- //! MPU is disabled, the default memory map is used and memory management
- //! faults are not generated.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- MPUDisable(void)
- {
- //
- // Turn off the MPU enable bit.
- //
- HWREG(NVIC_MPU_CTRL) &= ~NVIC_MPU_CTRL_ENABLE;
- }
- //*****************************************************************************
- //
- //! Gets the count of regions supported by the MPU.
- //!
- //! This function is used to get the total number of regions that are supported
- //! by the MPU, including regions that are already programmed.
- //!
- //! \return The number of memory protection regions that are available
- //! for programming using MPURegionSet().
- //
- //*****************************************************************************
- uint32_t
- MPURegionCountGet(void)
- {
- //
- // Read the DREGION field of the MPU type register and mask off
- // the bits of interest to get the count of regions.
- //
- return((HWREG(NVIC_MPU_TYPE) & NVIC_MPU_TYPE_DREGION_M) >>
- NVIC_MPU_TYPE_DREGION_S);
- }
- //*****************************************************************************
- //
- //! Enables a specific region.
- //!
- //! \param ui32Region is the region number to enable.
- //!
- //! This function is used to enable a memory protection region. The region
- //! should already be configured with the MPURegionSet() function. Once
- //! enabled, the memory protection rules of the region are applied and access
- //! violations cause a memory management fault.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- MPURegionEnable(uint32_t ui32Region)
- {
- //
- // Check the arguments.
- //
- ASSERT(ui32Region < 8);
- //
- // Select the region to modify.
- //
- HWREG(NVIC_MPU_NUMBER) = ui32Region;
- //
- // Modify the enable bit in the region attributes.
- //
- HWREG(NVIC_MPU_ATTR) |= NVIC_MPU_ATTR_ENABLE;
- }
- //*****************************************************************************
- //
- //! Disables a specific region.
- //!
- //! \param ui32Region is the region number to disable.
- //!
- //! This function is used to disable a previously enabled memory protection
- //! region. The region remains configured if it is not overwritten with
- //! another call to MPURegionSet(), and can be enabled again by calling
- //! MPURegionEnable().
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- MPURegionDisable(uint32_t ui32Region)
- {
- //
- // Check the arguments.
- //
- ASSERT(ui32Region < 8);
- //
- // Select the region to modify.
- //
- HWREG(NVIC_MPU_NUMBER) = ui32Region;
- //
- // Modify the enable bit in the region attributes.
- //
- HWREG(NVIC_MPU_ATTR) &= ~NVIC_MPU_ATTR_ENABLE;
- }
- //*****************************************************************************
- //
- //! Sets up the access rules for a specific region.
- //!
- //! \param ui32Region is the region number to set up.
- //! \param ui32Addr is the base address of the region. It must be aligned
- //! according to the size of the region specified in ui32Flags.
- //! \param ui32Flags is a set of flags to define the attributes of the region.
- //!
- //! This function sets up the protection rules for a region. The region has
- //! a base address and a set of attributes including the size. The base
- //! address parameter, \e ui32Addr, must be aligned according to the size, and
- //! the size must be a power of 2.
- //!
- //! The \e ui32Flags parameter is the logical OR of all of the attributes
- //! of the region. It is a combination of choices for region size,
- //! execute permission, read/write permissions, disabled sub-regions,
- //! and a flag to determine if the region is enabled.
- //!
- //! The size flag determines the size of a region and must be one of the
- //! following:
- //!
- //! - \b MPU_RGN_SIZE_32B
- //! - \b MPU_RGN_SIZE_64B
- //! - \b MPU_RGN_SIZE_128B
- //! - \b MPU_RGN_SIZE_256B
- //! - \b MPU_RGN_SIZE_512B
- //! - \b MPU_RGN_SIZE_1K
- //! - \b MPU_RGN_SIZE_2K
- //! - \b MPU_RGN_SIZE_4K
- //! - \b MPU_RGN_SIZE_8K
- //! - \b MPU_RGN_SIZE_16K
- //! - \b MPU_RGN_SIZE_32K
- //! - \b MPU_RGN_SIZE_64K
- //! - \b MPU_RGN_SIZE_128K
- //! - \b MPU_RGN_SIZE_256K
- //! - \b MPU_RGN_SIZE_512K
- //! - \b MPU_RGN_SIZE_1M
- //! - \b MPU_RGN_SIZE_2M
- //! - \b MPU_RGN_SIZE_4M
- //! - \b MPU_RGN_SIZE_8M
- //! - \b MPU_RGN_SIZE_16M
- //! - \b MPU_RGN_SIZE_32M
- //! - \b MPU_RGN_SIZE_64M
- //! - \b MPU_RGN_SIZE_128M
- //! - \b MPU_RGN_SIZE_256M
- //! - \b MPU_RGN_SIZE_512M
- //! - \b MPU_RGN_SIZE_1G
- //! - \b MPU_RGN_SIZE_2G
- //! - \b MPU_RGN_SIZE_4G
- //!
- //! The execute permission flag must be one of the following:
- //!
- //! - \b MPU_RGN_PERM_EXEC enables the region for execution of code
- //! - \b MPU_RGN_PERM_NOEXEC disables the region for execution of code
- //!
- //! The read/write access permissions are applied separately for the
- //! privileged and user modes. The read/write access flags must be one
- //! of the following:
- //!
- //! - \b MPU_RGN_PERM_PRV_NO_USR_NO - no access in privileged or user mode
- //! - \b MPU_RGN_PERM_PRV_RW_USR_NO - privileged read/write, user no access
- //! - \b MPU_RGN_PERM_PRV_RW_USR_RO - privileged read/write, user read-only
- //! - \b MPU_RGN_PERM_PRV_RW_USR_RW - privileged read/write, user read/write
- //! - \b MPU_RGN_PERM_PRV_RO_USR_NO - privileged read-only, user no access
- //! - \b MPU_RGN_PERM_PRV_RO_USR_RO - privileged read-only, user read-only
- //!
- //! The region is automatically divided into 8 equally-sized sub-regions by
- //! the MPU. Sub-regions can only be used in regions of size 256 bytes
- //! or larger. Any of these 8 sub-regions can be disabled, allowing for
- //! creation of ``holes'' in a region which can be left open, or overlaid
- //! by another region with different attributes. Any of the 8 sub-regions
- //! can be disabled with a logical OR of any of the following flags:
- //!
- //! - \b MPU_SUB_RGN_DISABLE_0
- //! - \b MPU_SUB_RGN_DISABLE_1
- //! - \b MPU_SUB_RGN_DISABLE_2
- //! - \b MPU_SUB_RGN_DISABLE_3
- //! - \b MPU_SUB_RGN_DISABLE_4
- //! - \b MPU_SUB_RGN_DISABLE_5
- //! - \b MPU_SUB_RGN_DISABLE_6
- //! - \b MPU_SUB_RGN_DISABLE_7
- //!
- //! Finally, the region can be initially enabled or disabled with one of
- //! the following flags:
- //!
- //! - \b MPU_RGN_ENABLE
- //! - \b MPU_RGN_DISABLE
- //!
- //! As an example, to set a region with the following attributes: size of
- //! 32 KB, execution enabled, read-only for both privileged and user, one
- //! sub-region disabled, and initially enabled; the \e ui32Flags parameter
- //! would have the following value:
- //!
- //! <code>
- //! (MPU_RGN_SIZE_32K | MPU_RGN_PERM_EXEC | MPU_RGN_PERM_PRV_RO_USR_RO |
- //! MPU_SUB_RGN_DISABLE_2 | MPU_RGN_ENABLE)
- //! </code>
- //!
- //! \note This function writes to multiple registers and is not protected
- //! from interrupts. It is possible that an interrupt which accesses a
- //! region may occur while that region is in the process of being changed.
- //! The safest way to handle this is to disable a region before changing it.
- //! Refer to the discussion of this in the API Detailed Description section.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- MPURegionSet(uint32_t ui32Region, uint32_t ui32Addr, uint32_t ui32Flags)
- {
- //
- // Check the arguments.
- //
- ASSERT(ui32Region < 8);
- ASSERT(ui32Addr ==
- (ui32Addr & ~0 << (((ui32Flags & NVIC_MPU_ATTR_SIZE_M) >> 1) + 1)));
- //
- // Program the base address, use the region field to select the
- // region at the same time.
- //
- HWREG(NVIC_MPU_BASE) = ui32Addr | ui32Region | NVIC_MPU_BASE_VALID;
- //
- // Program the region attributes. Set the TEX field and the S, C,
- // and B bits to fixed values that are suitable for all Tiva C and
- // E Series memory.
- //
- HWREG(NVIC_MPU_ATTR) = ((ui32Flags & ~(NVIC_MPU_ATTR_TEX_M |
- NVIC_MPU_ATTR_CACHEABLE)) |
- NVIC_MPU_ATTR_SHAREABLE | NVIC_MPU_ATTR_BUFFRABLE);
- }
- //*****************************************************************************
- //
- //! Gets the current settings for a specific region.
- //!
- //! \param ui32Region is the region number to get.
- //! \param pui32Addr points to storage for the base address of the region.
- //! \param pui32Flags points to the attribute flags for the region.
- //!
- //! This function retrieves the configuration of a specific region. The
- //! meanings and format of the parameters is the same as that of the
- //! MPURegionSet() function.
- //!
- //! This function can be used to save the configuration of a region for later
- //! use with the MPURegionSet() function. The region's enable state is
- //! preserved in the attributes that are saved.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- MPURegionGet(uint32_t ui32Region, uint32_t *pui32Addr, uint32_t *pui32Flags)
- {
- //
- // Check the arguments.
- //
- ASSERT(ui32Region < 8);
- ASSERT(pui32Addr);
- ASSERT(pui32Flags);
- //
- // Select the region to get.
- //
- HWREG(NVIC_MPU_NUMBER) = ui32Region;
- //
- // Read and store the base address for the region.
- //
- *pui32Addr = HWREG(NVIC_MPU_BASE) & NVIC_MPU_BASE_ADDR_M;
- //
- // Read and store the region attributes.
- //
- *pui32Flags = HWREG(NVIC_MPU_ATTR);
- }
- //*****************************************************************************
- //
- //! Registers an interrupt handler for the memory management fault.
- //!
- //! \param pfnHandler is a pointer to the function to be called when the
- //! memory management fault occurs.
- //!
- //! This function sets and enables the handler to be called when the MPU
- //! generates a memory management fault due to a protection region access
- //! violation.
- //!
- //! \sa IntRegister() for important information about registering interrupt
- //! handlers.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- MPUIntRegister(void (*pfnHandler)(void))
- {
- //
- // Check the arguments.
- //
- ASSERT(pfnHandler);
- //
- // Register the interrupt handler.
- //
- IntRegister(FAULT_MPU, pfnHandler);
- //
- // Enable the memory management fault.
- //
- IntEnable(FAULT_MPU);
- }
- //*****************************************************************************
- //
- //! Unregisters an interrupt handler for the memory management fault.
- //!
- //! This function disables and clears the handler to be called when a
- //! memory management fault occurs.
- //!
- //! \sa IntRegister() for important information about registering interrupt
- //! handlers.
- //!
- //! \return None.
- //
- //*****************************************************************************
- void
- MPUIntUnregister(void)
- {
- //
- // Disable the interrupt.
- //
- IntDisable(FAULT_MPU);
- //
- // Unregister the interrupt handler.
- //
- IntUnregister(FAULT_MPU);
- }
- //*****************************************************************************
- //
- // Close the Doxygen group.
- //! @}
- //
- //*****************************************************************************
|