Initial commit of firmware
This commit is contained in:
85
Libs/platform/service/mpu/inc/sl_mpu.h
Normal file
85
Libs/platform/service/mpu/inc/sl_mpu.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/***************************************************************************//**
|
||||
* @file
|
||||
* @brief MPU API definition.
|
||||
*******************************************************************************
|
||||
* # License
|
||||
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* SPDX-License-Identifier: Zlib
|
||||
*
|
||||
* The licensor of this software is Silicon Laboratories Inc.
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* @addtogroup mpu RAM execution disable
|
||||
* @brief RAM execution disable utilities can be used to disable execution from
|
||||
* RAM and other selected memory regions.
|
||||
* @details
|
||||
* RAM execution disable utilities are useful to protect against code
|
||||
* injection attacks.
|
||||
* These utilities make use of MPU to disable execution from RAM and other
|
||||
* selected memory regions.
|
||||
*
|
||||
* @{
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef SL_MPU_H
|
||||
#define SL_MPU_H
|
||||
|
||||
#include "sl_status.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/***************************************************************************//**
|
||||
* Configures internal SRAM as non-executable and enable MPU.
|
||||
*
|
||||
* @note This function configures the MPU in order to make the entire RAM as
|
||||
* non-executable (with the exception of the functions marked as ramfunc).
|
||||
******************************************************************************/
|
||||
void sl_mpu_disable_execute_from_ram(void);
|
||||
|
||||
/***************************************************************************//**
|
||||
* Configures an address range as non-executable and enable MPU.
|
||||
*
|
||||
* @note Configures a MPU region in order to make an address range as
|
||||
* non-executable. The memory region must have a size of at least 32 bytes.
|
||||
*
|
||||
* @param address_begin Beginning of memory segment.
|
||||
*
|
||||
* @param address_end End of memory segment.
|
||||
*
|
||||
* @param size Size of memory segment.
|
||||
*
|
||||
* @return 0 if successful. Error code otherwise.
|
||||
******************************************************************************/
|
||||
sl_status_t sl_mpu_disable_execute(uint32_t address_begin,
|
||||
uint32_t address_end,
|
||||
uint32_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SL_MPU_H */
|
||||
|
||||
/** @} (end addtogroup mpu) */
|
||||
493
Libs/platform/service/mpu/src/sl_mpu.c
Normal file
493
Libs/platform/service/mpu/src/sl_mpu.c
Normal file
@@ -0,0 +1,493 @@
|
||||
/***************************************************************************//**
|
||||
* @file
|
||||
* @brief MPU API implementation.
|
||||
*******************************************************************************
|
||||
* # License
|
||||
* <b>Copyright 2019 Silicon Laboratories Inc. www.silabs.com</b>
|
||||
*******************************************************************************
|
||||
*
|
||||
* SPDX-License-Identifier: Zlib
|
||||
*
|
||||
* The licensor of this software is Silicon Laboratories Inc.
|
||||
*
|
||||
* This software is provided 'as-is', without any express or implied
|
||||
* warranty. In no event will the authors be held liable for any damages
|
||||
* arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose,
|
||||
* including commercial applications, and to alter it and redistribute it
|
||||
* freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not
|
||||
* claim that you wrote the original software. If you use this software
|
||||
* in a product, an acknowledgment in the product documentation would be
|
||||
* appreciated but is not required.
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be
|
||||
* misrepresented as being the original software.
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "sl_mpu.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "em_device.h"
|
||||
#include "sl_core.h"
|
||||
|
||||
/*******************************************************************************
|
||||
********************************* DEFINES *********************************
|
||||
******************************************************************************/
|
||||
|
||||
#define MPU_MEMORY_ATTRIBUTE_IX_0 0U
|
||||
#define MPU_MEMORY_ATTRIBUTE_IX_1 1U
|
||||
|
||||
#define MPU_RBAR_BASE_ADDR_NONE 0U
|
||||
#define MPU_RBAR_AP_READ_WRITE 0U
|
||||
#define MPU_RBAR_AP_READ_ONLY 1U
|
||||
#define MPU_RBAR_AP_PRIVILEGED 0U
|
||||
#define MPU_RBAR_AP_NON_PRIVILEGED 1U
|
||||
#define MPU_RBAR_XN_EXECUTION 0U
|
||||
#define MPU_RBAR_XN_NON_EXECUTION 1U
|
||||
|
||||
// Memory region attributes: non-shareable, read-write, non-privileged, non-executable.
|
||||
#define MPU_RBAR_VALUE ARM_MPU_RBAR(MPU_RBAR_BASE_ADDR_NONE, \
|
||||
ARM_MPU_SH_NON, \
|
||||
MPU_RBAR_AP_READ_WRITE, \
|
||||
MPU_RBAR_AP_NON_PRIVILEGED, \
|
||||
MPU_RBAR_XN_NON_EXECUTION)
|
||||
|
||||
// The MPU Region Limit Address Register defines the ending address of an MPU region.
|
||||
// Bit [4:0] of the address value is assigned with 0x1F to provide the limit
|
||||
// address to be checked against.
|
||||
#define MPU_RLAR_LIMIT_ADDRESS_ALIGNMENT 32U
|
||||
|
||||
// ARM memory map SRAM location and size.
|
||||
#if defined(_SILICON_LABS_32B_SERIES_2) \
|
||||
|| (defined(_SILICON_LABS_32B_SERIES_3) && defined(SL_RAM_LINKER))
|
||||
#define MPU_ARM_SRAM_MEM_BASE SRAM_BASE
|
||||
|
||||
// This RAM size is not the real device size. It corresponds to the SRAM max size in the standard
|
||||
// ARM Cortex-M33 memory map. The max size is 0.5GB.
|
||||
#define MPU_ARM_SRAM_MEM_SIZE SRAM_SIZE
|
||||
|
||||
#elif defined(_SILICON_LABS_32B_SERIES_3)
|
||||
// These local constants ensure the MPU regions for the secure/non-secure RAM aliases
|
||||
// and the secure/non-secure RAM non-aliases are properly managed for all
|
||||
// secure/non-secure project configurations.
|
||||
#define MPU_RAMFUNC_SRAM_ALIAS_START SRAM_ALIAS_BASE
|
||||
#define MPU_RAMFUNC_SRAM_ALIAS_END (SRAM_ALIAS_BASE + (SRAM_SIZE - 1U))
|
||||
|
||||
#define MPU_DATA_SRAM_START SRAM_BASE
|
||||
#define MPU_DATA_SRAM_END (SRAM_BASE + (SRAM_SIZE - 1U))
|
||||
|
||||
#if defined(SL_TRUSTZONE_SECURE)
|
||||
#define MPU_NOT_USED_SRAM_ALIAS_START DMEM_INSTR_NS_MEM_BASE
|
||||
#define MPU_NOT_USED_SRAM_ALIAS_END DMEM_INSTR_NS_MEM_END
|
||||
|
||||
#define MPU_NOT_USED_SRAM_START DMEM_NS_MEM_BASE
|
||||
#define MPU_NOT_USED_SRAM_END DMEM_NS_MEM_END
|
||||
#else
|
||||
#define MPU_NOT_USED_SRAM_ALIAS_START DMEM_INSTR_S_MEM_BASE
|
||||
#define MPU_NOT_USED_SRAM_ALIAS_END DMEM_INSTR_S_MEM_END
|
||||
|
||||
#define MPU_NOT_USED_SRAM_START DMEM_S_MEM_BASE
|
||||
#define MPU_NOT_USED_SRAM_END DMEM_S_MEM_END
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__ICCARM__)
|
||||
// iccarm
|
||||
#pragma section = "text_ram"
|
||||
#define RAMFUNC_SECTION_BEGIN ((uint32_t)(uint32_t *)__section_begin("text_ram"))
|
||||
#define RAMFUNC_SECTION_END ((uint32_t)(uint32_t *)__section_end("text_ram"))
|
||||
#define RAMFUNC_SECTION_SIZE __section_size("text_ram")
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
// armgcc
|
||||
extern uint32_t __vma_ramfuncs_start__;
|
||||
extern uint32_t __vma_ramfuncs_end__;
|
||||
#define RAMFUNC_SECTION_BEGIN (uint32_t) &__vma_ramfuncs_start__
|
||||
#define RAMFUNC_SECTION_END (uint32_t) &__vma_ramfuncs_end__
|
||||
#define RAMFUNC_SECTION_SIZE (RAMFUNC_SECTION_END - RAMFUNC_SECTION_BEGIN)
|
||||
|
||||
#elif defined(__CC_ARM)
|
||||
// armcc
|
||||
// The section name in the armcc scatter file must be "ram_code".
|
||||
extern uint32_t ram_code$$Base;
|
||||
extern uint32_t ram_code$$Limit;
|
||||
#define RAMFUNC_SECTION_BEGIN (uint32_t) &ram_code$$Base
|
||||
#define RAMFUNC_SECTION_END (uint32_t) &ram_code$$Limit
|
||||
#define RAMFUNC_SECTION_SIZE (RAMFUNC_SECTION_END - RAMFUNC_SECTION_BEGIN)
|
||||
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
*************************** LOCAL VARIABLES ********************************
|
||||
******************************************************************************/
|
||||
|
||||
static uint32_t region_nbr = 0;
|
||||
|
||||
/*******************************************************************************
|
||||
************************** GLOBAL FUNCTIONS *******************************
|
||||
******************************************************************************/
|
||||
|
||||
/**************************************************************************//**
|
||||
* Configures internal SRAM as non-executable and enable MPU.
|
||||
*
|
||||
* @note (1) On series 2 devices, the MPU regions configuration for the RAM layout
|
||||
* is for GCC and IAR:
|
||||
*
|
||||
* MPU Region Region Attributes Adresses Range
|
||||
* ------------------------------------------------------------------------
|
||||
* 0x2000_0000 0x2007_FFFF (DATA, RAMFUNC) 0 non shareable, executable RAMFunc start to RAMFunc end
|
||||
* 1 non shareable, non executable RAMFunc end to range end
|
||||
* or
|
||||
* 0x2000_0000 0x2007_FFFF (DATA) 0 shareable, non executable Entire range
|
||||
*
|
||||
* @note (2) On series 3 SIXG301 devices, there are the following RAM-related
|
||||
* address ranges.
|
||||
* - 0x0080_0000 0x0087_FFFF (Alias to DMEM_NS) - Non-secure
|
||||
* - 0x1080_0000 0x1087_FFFF (Alias to DMEM (execute only)) -Secure
|
||||
* - 0x2000_0000 0x2007_FFFF (DMEM_NS) - Non-secure
|
||||
* - 0x3000_0000 0x3007_FFFF (DMEM) - Secure
|
||||
*
|
||||
* The MPU regions are configured differently depending on the RAM layout
|
||||
* described in GCC and IAR linker scripts. A common characteristic
|
||||
* to all the MPU regions for GCC and IAR is:
|
||||
* - All MPU regions for RAM are non-cacheable.
|
||||
*
|
||||
* The table below presents the MPU regions for series 3 SIXG301 devices.
|
||||
* The table assumes there are RAMFunc in RAM. If there are no RAMFunc
|
||||
* functions, then the associated region will be a single region covering
|
||||
* the full addresses range.
|
||||
*
|
||||
* GCC
|
||||
* ---
|
||||
* MPU Region* Region Attributes Adresses Range
|
||||
* ------------------------------------------------------------------------
|
||||
* 0x0080_0000 0x0087_FFFF (RAMFUNC)* 0 shareable, executable RAMFunc start to RAMFunc end
|
||||
* 1 non shareable, non executable RAMFunc end to range end
|
||||
* or
|
||||
* 0x0080_0000 0x0087_FFFF (NOT USED)* x non shareable, non executable Entire range (if no RAMFunc)
|
||||
*
|
||||
* 0x1080_0000 0x1087_FFFF (NOT USED)* 2 non shareable, non executable Entire range
|
||||
* 0x2000_0000 0x2007_FFFF (DATA)* 3 shareable, non executable Entire range
|
||||
* 0x3000_0000 0x3007_FFFF (NOT USED)* 4 non shareable, non executable Entire range
|
||||
*
|
||||
* IAR
|
||||
* ---
|
||||
* MPU Region* Region Attributes Adresses Range
|
||||
* ------------------------------------------------------------------------
|
||||
* 0x0080_0000 0x0087_FFFF (NOT USED)* 0 non shareable, non executable Entire range
|
||||
* 0x1080_0000 0x1087_FFFF (NOT USED)* 1 non shareable, non executable Entire range
|
||||
* 0x2000_0000 0x2007_FFFF (DATA, RAMFUNC)* 2 shareable, non executable Range start to RAMFunc start
|
||||
* 3 shareable, executable RAMFunc start to RAMFunc end
|
||||
* 4 shareable, non executable RAMFunc end to range end
|
||||
* or
|
||||
* 0x2000_0000 0x2007_FFFF (NOT USED)* x non shareable, non executable Entire range (if no RAMFunc)
|
||||
*
|
||||
* 0x3000_0000 0x3007_FFFF (NOT USED)* 5 non shareable, non executable Entire range
|
||||
|
||||
* *If the ARM Cortex-M33 works in non-secure, all non-secure alias/
|
||||
* non-alias will be used by default for RAMfunc and data in RAM.
|
||||
* Same logic if the Cortex-M33 is in secure, all secure alias/non-alias
|
||||
* will be used by default. The MPU regions creation will adapt to
|
||||
* the default secure or non-secure addresses. And thus the order
|
||||
* in which the MPU regions are created can vary.
|
||||
*****************************************************************************/
|
||||
void sl_mpu_disable_execute_from_ram(void)
|
||||
{
|
||||
uint32_t mpu_region_begin = 0u;
|
||||
uint32_t mpu_region_end = 0u;
|
||||
uint32_t rbar;
|
||||
|
||||
ARM_MPU_Disable();
|
||||
|
||||
// See Note #1.
|
||||
#if defined(_SILICON_LABS_32B_SERIES_2) \
|
||||
|| (defined(_SILICON_LABS_32B_SERIES_3) && defined(SL_RAM_LINKER))
|
||||
// Memory attributes:
|
||||
// Outer memory with ARM_MPU_ATTR_MEMORY_(): non-transient data, Write-Through, cache allocation on read miss, no cache allocation on write miss.
|
||||
// ARM_MPU_ATTR(): outer attributes filled, no inner memory
|
||||
ARM_MPU_SetMemAttr(MPU_MEMORY_ATTRIBUTE_IX_0,
|
||||
ARM_MPU_ATTR(ARM_MPU_ATTR_MEMORY_(1, 0, 1, 0), 0));
|
||||
|
||||
// Region end address LSB are always considered 0x1F.
|
||||
mpu_region_begin = MPU_ARM_SRAM_MEM_BASE;
|
||||
mpu_region_end = (RAMFUNC_SECTION_SIZE > 0) ? (RAMFUNC_SECTION_BEGIN & MPU_RBAR_BASE_Msk) - MPU_RLAR_LIMIT_ADDRESS_ALIGNMENT
|
||||
: (MPU_ARM_SRAM_MEM_BASE + MPU_ARM_SRAM_MEM_SIZE);
|
||||
|
||||
// Define initial MPU region: either 1 unique region = entire RAM. Or 1 region = from RAM START to RAMFUNC START.
|
||||
if (mpu_region_begin <= mpu_region_end) {
|
||||
// A bug exists in some versions of ARM_MPU_RBAR(). Set base addr manually.
|
||||
rbar = MPU_RBAR_VALUE | (mpu_region_begin & MPU_RBAR_BASE_Msk);
|
||||
ARM_MPU_SetRegion(region_nbr, rbar, ARM_MPU_RLAR(mpu_region_end, MPU_MEMORY_ATTRIBUTE_IX_0));
|
||||
region_nbr++;
|
||||
}
|
||||
|
||||
// Only if functions placed in RAM, define another region from RAMFUNC END to RAM END.
|
||||
if (RAMFUNC_SECTION_SIZE > 0u) {
|
||||
// Region end address LSB are always considered 0x1F.
|
||||
mpu_region_begin = (RAMFUNC_SECTION_END + 31u) & MPU_RLAR_LIMIT_Msk;
|
||||
mpu_region_end = MPU_ARM_SRAM_MEM_BASE + MPU_ARM_SRAM_MEM_SIZE - MPU_RLAR_LIMIT_ADDRESS_ALIGNMENT;
|
||||
|
||||
// A bug exists in some versions of ARM_MPU_RBAR(). Set base addr manually.
|
||||
rbar = MPU_RBAR_VALUE | (mpu_region_begin & MPU_RBAR_BASE_Msk);
|
||||
ARM_MPU_SetRegion(region_nbr, rbar, ARM_MPU_RLAR(mpu_region_end, 0u));
|
||||
region_nbr++;
|
||||
}
|
||||
|
||||
// See Note #2.
|
||||
#elif (defined(_SILICON_LABS_32B_SERIES_3) && !defined(SL_RAM_LINKER))
|
||||
// 1. Set the memory attributes for the entire RAM (alias and non-alias ranges).
|
||||
// Outer & inner memories: non-cacheable.
|
||||
ARM_MPU_SetMemAttr(MPU_MEMORY_ATTRIBUTE_IX_0,
|
||||
ARM_MPU_ATTR(ARM_MPU_ATTR_NON_CACHEABLE, ARM_MPU_ATTR_NON_CACHEABLE));
|
||||
|
||||
// 2. Create different MPU regions accounting for all RAM addresses ranges (secure/non-secure alias/non-alias)
|
||||
// Secure or non secure alias (not used): 1 region (non shareable, non cacheable, non executable)
|
||||
mpu_region_begin = MPU_NOT_USED_SRAM_ALIAS_START;
|
||||
rbar = ARM_MPU_RBAR(MPU_RBAR_BASE_ADDR_NONE,
|
||||
ARM_MPU_SH_NON,
|
||||
MPU_RBAR_AP_READ_ONLY,
|
||||
MPU_RBAR_AP_NON_PRIVILEGED,
|
||||
MPU_RBAR_XN_NON_EXECUTION)
|
||||
| (mpu_region_begin & MPU_RBAR_BASE_Msk);
|
||||
mpu_region_end = (MPU_NOT_USED_SRAM_ALIAS_END & MPU_RLAR_LIMIT_Msk);
|
||||
ARM_MPU_SetRegion(region_nbr, rbar, ARM_MPU_RLAR(mpu_region_end, MPU_MEMORY_ATTRIBUTE_IX_0));
|
||||
region_nbr++;
|
||||
|
||||
// Non secure or secure alias (used for code if functions placed in RAM):
|
||||
#if defined(__GNUC__)
|
||||
if (RAMFUNC_SECTION_SIZE > 0u) {
|
||||
// Functions placed in RAM: 1 region (shareable, non cacheable, executable)
|
||||
mpu_region_begin = RAMFUNC_SECTION_BEGIN;
|
||||
rbar = ARM_MPU_RBAR(MPU_RBAR_BASE_ADDR_NONE,
|
||||
ARM_MPU_SH_OUTER,
|
||||
MPU_RBAR_AP_READ_ONLY,
|
||||
MPU_RBAR_AP_NON_PRIVILEGED,
|
||||
MPU_RBAR_XN_EXECUTION)
|
||||
| (mpu_region_begin & MPU_RBAR_BASE_Msk);
|
||||
mpu_region_end = (RAMFUNC_SECTION_END & MPU_RLAR_LIMIT_Msk);
|
||||
ARM_MPU_SetRegion(region_nbr, rbar, ARM_MPU_RLAR(mpu_region_end, MPU_MEMORY_ATTRIBUTE_IX_0));
|
||||
region_nbr++;
|
||||
|
||||
// Rest of the non secure or secure alias: non shareable, non cacheable, non executable
|
||||
mpu_region_begin = (RAMFUNC_SECTION_END + 31u) & MPU_RLAR_LIMIT_Msk; // +31u allows to round up to the next 32 bytes alignment.
|
||||
rbar = ARM_MPU_RBAR(MPU_RBAR_BASE_ADDR_NONE,
|
||||
ARM_MPU_SH_NON,
|
||||
MPU_RBAR_AP_READ_ONLY,
|
||||
MPU_RBAR_AP_NON_PRIVILEGED,
|
||||
MPU_RBAR_XN_NON_EXECUTION)
|
||||
| (mpu_region_begin & MPU_RBAR_BASE_Msk);
|
||||
mpu_region_end = (MPU_RAMFUNC_SRAM_ALIAS_END & MPU_RLAR_LIMIT_Msk);
|
||||
ARM_MPU_SetRegion(region_nbr, rbar, ARM_MPU_RLAR(mpu_region_end, MPU_MEMORY_ATTRIBUTE_IX_0));
|
||||
region_nbr++;
|
||||
} else {
|
||||
#endif
|
||||
// No functions placed in RAM: 1 region (non shareable, non cacheable, non executable)
|
||||
mpu_region_begin = MPU_RAMFUNC_SRAM_ALIAS_START;
|
||||
rbar = ARM_MPU_RBAR(MPU_RBAR_BASE_ADDR_NONE,
|
||||
ARM_MPU_SH_NON,
|
||||
MPU_RBAR_AP_READ_ONLY,
|
||||
MPU_RBAR_AP_NON_PRIVILEGED,
|
||||
MPU_RBAR_XN_NON_EXECUTION)
|
||||
| (mpu_region_begin & MPU_RBAR_BASE_Msk);
|
||||
mpu_region_end = (MPU_RAMFUNC_SRAM_ALIAS_END & MPU_RLAR_LIMIT_Msk);
|
||||
ARM_MPU_SetRegion(region_nbr, rbar, ARM_MPU_RLAR(mpu_region_end, MPU_MEMORY_ATTRIBUTE_IX_0));
|
||||
region_nbr++;
|
||||
#if defined(__GNUC__)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Secure or non secure non alias (used for data): 1 region (shareable, non cacheable, non executable)
|
||||
#if defined(__ICCARM__)
|
||||
if (RAMFUNC_SECTION_SIZE > 0u) {
|
||||
// Beginning of non secure alias: shareable, non cacheable, non executable
|
||||
mpu_region_begin = MPU_DATA_SRAM_START;
|
||||
rbar = ARM_MPU_RBAR(MPU_RBAR_BASE_ADDR_NONE,
|
||||
ARM_MPU_SH_OUTER,
|
||||
MPU_RBAR_AP_READ_WRITE,
|
||||
MPU_RBAR_AP_NON_PRIVILEGED,
|
||||
MPU_RBAR_XN_NON_EXECUTION)
|
||||
| (mpu_region_begin & MPU_RBAR_BASE_Msk);
|
||||
mpu_region_end = ((RAMFUNC_SECTION_BEGIN - 1u) & MPU_RLAR_LIMIT_Msk);
|
||||
ARM_MPU_SetRegion(region_nbr, rbar, ARM_MPU_RLAR(mpu_region_end, MPU_MEMORY_ATTRIBUTE_IX_0));
|
||||
region_nbr++;
|
||||
|
||||
// Functions placed in RAM: 1 region (shareable, non cacheable, executable)
|
||||
mpu_region_begin = RAMFUNC_SECTION_BEGIN;
|
||||
rbar = ARM_MPU_RBAR(MPU_RBAR_BASE_ADDR_NONE,
|
||||
ARM_MPU_SH_OUTER,
|
||||
MPU_RBAR_AP_READ_ONLY,
|
||||
MPU_RBAR_AP_NON_PRIVILEGED,
|
||||
MPU_RBAR_XN_EXECUTION)
|
||||
| (mpu_region_begin & MPU_RBAR_BASE_Msk);
|
||||
mpu_region_end = (RAMFUNC_SECTION_END & MPU_RLAR_LIMIT_Msk);
|
||||
ARM_MPU_SetRegion(region_nbr, rbar, ARM_MPU_RLAR(mpu_region_end, MPU_MEMORY_ATTRIBUTE_IX_0));
|
||||
region_nbr++;
|
||||
|
||||
// Rest of non secure alias: shareable, non cacheable, non executable
|
||||
mpu_region_begin = (RAMFUNC_SECTION_END + 31u) & MPU_RLAR_LIMIT_Msk; // +31u allows to round up to the next 32 bytes alignment.
|
||||
rbar = ARM_MPU_RBAR(MPU_RBAR_BASE_ADDR_NONE,
|
||||
ARM_MPU_SH_OUTER,
|
||||
MPU_RBAR_AP_READ_WRITE,
|
||||
MPU_RBAR_AP_NON_PRIVILEGED,
|
||||
MPU_RBAR_XN_NON_EXECUTION)
|
||||
| (mpu_region_begin & MPU_RBAR_BASE_Msk);
|
||||
mpu_region_end = (MPU_DATA_SRAM_END & MPU_RLAR_LIMIT_Msk);
|
||||
ARM_MPU_SetRegion(region_nbr, rbar, ARM_MPU_RLAR(mpu_region_end, MPU_MEMORY_ATTRIBUTE_IX_0));
|
||||
region_nbr++;
|
||||
} else {
|
||||
#endif
|
||||
mpu_region_begin = MPU_DATA_SRAM_START;
|
||||
rbar = ARM_MPU_RBAR(MPU_RBAR_BASE_ADDR_NONE,
|
||||
ARM_MPU_SH_OUTER,
|
||||
MPU_RBAR_AP_READ_WRITE,
|
||||
MPU_RBAR_AP_NON_PRIVILEGED,
|
||||
MPU_RBAR_XN_NON_EXECUTION)
|
||||
| (mpu_region_begin & MPU_RBAR_BASE_Msk);
|
||||
mpu_region_end = (MPU_DATA_SRAM_END & MPU_RLAR_LIMIT_Msk);
|
||||
ARM_MPU_SetRegion(region_nbr, rbar, ARM_MPU_RLAR(mpu_region_end, MPU_MEMORY_ATTRIBUTE_IX_0));
|
||||
region_nbr++;
|
||||
#if defined(__ICCARM__)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Non secure or secure non alias (not used): 1 region (non shareable, non cacheable, non executable)
|
||||
mpu_region_begin = MPU_NOT_USED_SRAM_START;
|
||||
rbar = ARM_MPU_RBAR(MPU_RBAR_BASE_ADDR_NONE,
|
||||
ARM_MPU_SH_NON,
|
||||
MPU_RBAR_AP_READ_ONLY,
|
||||
MPU_RBAR_AP_NON_PRIVILEGED,
|
||||
MPU_RBAR_XN_NON_EXECUTION)
|
||||
| (mpu_region_begin & MPU_RBAR_BASE_Msk);
|
||||
mpu_region_end = (MPU_NOT_USED_SRAM_END & MPU_RLAR_LIMIT_Msk);
|
||||
ARM_MPU_SetRegion(region_nbr, rbar, ARM_MPU_RLAR(mpu_region_end, MPU_MEMORY_ATTRIBUTE_IX_0));
|
||||
region_nbr++;
|
||||
#else
|
||||
(void)rbar;
|
||||
(void)mpu_region_begin;
|
||||
(void)mpu_region_end;
|
||||
#endif
|
||||
|
||||
// Enable MPU with default background region.
|
||||
ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk);
|
||||
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Enables simplified MPU driver. Configures memory address as non-executable.
|
||||
*****************************************************************************/
|
||||
sl_status_t sl_mpu_disable_execute(uint32_t address_begin,
|
||||
uint32_t address_end,
|
||||
uint32_t size)
|
||||
{
|
||||
uint32_t mpu_region_begin = 0u;
|
||||
uint32_t mpu_region_end = 0u;
|
||||
sl_status_t status = SL_STATUS_OK;
|
||||
|
||||
// Ensure there is still an available MPU region to configure.
|
||||
if (region_nbr > MPU_RNR_REGION_Msk) {
|
||||
status = SL_STATUS_NO_MORE_RESOURCE;
|
||||
}
|
||||
|
||||
ARM_MPU_Disable();
|
||||
|
||||
uint32_t rbar;
|
||||
uint8_t is_overlapping = 0u;
|
||||
uint32_t prev_base_address = 0u;
|
||||
uint32_t prev_limit_address = 0u;
|
||||
|
||||
// Size of memory region must be 32 bytes or more.
|
||||
if (size >= 32u) {
|
||||
// Round inside the memory region, if address is not align on 32 bytes.
|
||||
mpu_region_begin = ((address_begin % 32u) == 0u) ? address_begin
|
||||
: (address_begin + (32u - (address_begin % 32u)));
|
||||
|
||||
// Round inside the memory region, if address is not align on 32 bytes.
|
||||
mpu_region_end = ((address_end % 32u) == 0u) ? address_end
|
||||
: (address_end - (address_end % 32u));
|
||||
|
||||
// The scanning to check the overlapping region
|
||||
for (uint8_t index_region = 0; index_region < region_nbr; index_region++) {
|
||||
// Set to the previous region number
|
||||
MPU->RNR = index_region;
|
||||
|
||||
// Read the base address that was configured by the region number register before
|
||||
prev_base_address = (MPU->RBAR & MPU_RBAR_BASE_Msk);
|
||||
// Read the limit address that was configured by the region number register before
|
||||
prev_limit_address = (MPU->RLAR & MPU_RLAR_LIMIT_Msk);
|
||||
|
||||
// Check the overlapping region
|
||||
if ((mpu_region_begin == prev_base_address) && (mpu_region_end == prev_limit_address)) {
|
||||
// The new region is the same as the previous region
|
||||
is_overlapping = 1;
|
||||
status = SL_STATUS_OK;
|
||||
} else if (!((mpu_region_begin > prev_limit_address) || (mpu_region_end < prev_base_address))) {
|
||||
// The new region is invalid
|
||||
is_overlapping = 1;
|
||||
status = SL_STATUS_INVALID_RANGE;
|
||||
}
|
||||
|
||||
if (is_overlapping == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
MPU->RNR &= ~MPU_RNR_REGION_Msk;
|
||||
}
|
||||
|
||||
// Set specified memory region if no overlap has been detected.
|
||||
if (!is_overlapping) {
|
||||
// Device memory type non Gathering, non Re-ordering, Early Write Acknowledgment
|
||||
ARM_MPU_SetMemAttr(MPU_MEMORY_ATTRIBUTE_IX_1, ARM_MPU_ATTR_DEVICE_nGnRE);
|
||||
|
||||
// A bug exists in some versions of ARM_MPU_RBAR(). Set base addr manually.
|
||||
// Memory region attributes: non-shareable, read-write, non-privileged, non-executable
|
||||
rbar = ARM_MPU_RBAR(MPU_RBAR_BASE_ADDR_NONE,
|
||||
ARM_MPU_SH_NON,
|
||||
MPU_RBAR_AP_READ_WRITE,
|
||||
MPU_RBAR_AP_NON_PRIVILEGED,
|
||||
MPU_RBAR_XN_NON_EXECUTION)
|
||||
| (mpu_region_begin & MPU_RBAR_BASE_Msk);
|
||||
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
CORE_ENTER_ATOMIC();
|
||||
ARM_MPU_SetRegion(region_nbr, rbar, ARM_MPU_RLAR(mpu_region_end, MPU_MEMORY_ATTRIBUTE_IX_1));
|
||||
CORE_EXIT_ATOMIC();
|
||||
region_nbr++;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable MPU with default background region
|
||||
ARM_MPU_Enable(MPU_CTRL_PRIVDEFENA_Msk);
|
||||
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#if __CORTEX_M != (0u)
|
||||
/**************************************************************************//**
|
||||
* MemManage default exception handler. Reset target.
|
||||
*****************************************************************************/
|
||||
__WEAK void mpu_fault_handler(void)
|
||||
{
|
||||
// Force fail assert to trigger reset
|
||||
__NVIC_SystemReset();
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* MemManage exception handler.
|
||||
*****************************************************************************/
|
||||
void MemManage_Handler(void)
|
||||
{
|
||||
mpu_fault_handler();
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user