mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			
						commit
						52822cb8af
					
				| 
						 | 
				
			
			@ -21,6 +21,7 @@
 | 
			
		|||
#include "utest/utest.h"
 | 
			
		||||
#include "unity/unity.h"
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
#include "platform/mbed_mpu_mgmt.h"
 | 
			
		||||
 | 
			
		||||
#include "mbed.h"
 | 
			
		||||
#include "flash_api.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -251,11 +252,22 @@ Case cases[] = {
 | 
			
		|||
 | 
			
		||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
 | 
			
		||||
{
 | 
			
		||||
    mbed_mpu_manager_lock_ram_execution();
 | 
			
		||||
    mbed_mpu_manager_lock_rom_write();
 | 
			
		||||
 | 
			
		||||
    GREENTEA_SETUP(20, "default_auto");
 | 
			
		||||
    return greentea_test_setup_handler(number_of_cases);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
 | 
			
		||||
void greentea_test_teardown(const size_t passed, const size_t failed, const failure_t failure)
 | 
			
		||||
{
 | 
			
		||||
    mbed_mpu_manager_unlock_ram_execution();
 | 
			
		||||
    mbed_mpu_manager_unlock_rom_write();
 | 
			
		||||
 | 
			
		||||
    greentea_test_teardown_handler(passed, failed, failure);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown);
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,201 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2017 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "utest/utest.h"
 | 
			
		||||
#include "unity/unity.h"
 | 
			
		||||
#include "greentea-client/test_env.h"
 | 
			
		||||
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include "mpu_api.h"
 | 
			
		||||
#include "mpu_test.h"
 | 
			
		||||
 | 
			
		||||
#if !DEVICE_MPU
 | 
			
		||||
#error [NOT_SUPPORTED] MPU API not supported for this target
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
using namespace utest::v1;
 | 
			
		||||
 | 
			
		||||
#define HARDFAULT_IRQn   ((IRQn_Type)-13)
 | 
			
		||||
#define MEMFAULT_IRQn    ((IRQn_Type)-12)
 | 
			
		||||
 | 
			
		||||
// Assembly return instruction: bx lr
 | 
			
		||||
#define ASM_BX_LR 0x4770
 | 
			
		||||
 | 
			
		||||
volatile uint32_t fault_count;
 | 
			
		||||
uint32_t real_hard_fault_handler;
 | 
			
		||||
uint32_t real_mem_fault_handler;
 | 
			
		||||
 | 
			
		||||
static volatile uint16_t data_function = ASM_BX_LR;
 | 
			
		||||
static volatile uint16_t bss_function;
 | 
			
		||||
 | 
			
		||||
static void clear_caches()
 | 
			
		||||
{
 | 
			
		||||
#if defined(__CORTEX_M7)
 | 
			
		||||
    /* Data cache clean and invalid */
 | 
			
		||||
    SCB_CleanInvalidateDCache();
 | 
			
		||||
 | 
			
		||||
    /* Instruction cache invalid */
 | 
			
		||||
    SCB_InvalidateICache();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    __ISB();
 | 
			
		||||
    __DSB();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void call_mem(const volatile uint16_t *mem_function)
 | 
			
		||||
{
 | 
			
		||||
    // or the address with 1 to ensure the thumb bit is set
 | 
			
		||||
    ((void (*)())((uint32_t)mem_function | 1))();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void hard_fault_handler_test()
 | 
			
		||||
{
 | 
			
		||||
    fault_count++;
 | 
			
		||||
    mbed_mpu_enable_ram_xn(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void mpu_fault_test(const volatile uint16_t *mem_function)
 | 
			
		||||
{
 | 
			
		||||
    mbed_mpu_init();
 | 
			
		||||
 | 
			
		||||
    // Verify that the mpu causes faults when executing ram
 | 
			
		||||
    fault_count = 0;
 | 
			
		||||
    mbed_mpu_enable_ram_xn(true);
 | 
			
		||||
    call_mem(mem_function);
 | 
			
		||||
    TEST_ASSERT_EQUAL(1, fault_count);
 | 
			
		||||
 | 
			
		||||
    // Verify that the mpu can be turned off
 | 
			
		||||
    fault_count = 0;
 | 
			
		||||
    mbed_mpu_enable_ram_xn(false);
 | 
			
		||||
    call_mem(mem_function);
 | 
			
		||||
    TEST_ASSERT_EQUAL(0, fault_count);
 | 
			
		||||
 | 
			
		||||
    // Verify that the mpu causes faults when executing ram
 | 
			
		||||
    fault_count = 0;
 | 
			
		||||
    mbed_mpu_enable_ram_xn(true);
 | 
			
		||||
    call_mem(mem_function);
 | 
			
		||||
    TEST_ASSERT_EQUAL(1, fault_count);
 | 
			
		||||
 | 
			
		||||
    // Verify that free turns off the mpu
 | 
			
		||||
    fault_count = 0;
 | 
			
		||||
    mbed_mpu_free();
 | 
			
		||||
    call_mem(mem_function);
 | 
			
		||||
    TEST_ASSERT_EQUAL(0, fault_count);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mpu_init_test()
 | 
			
		||||
{
 | 
			
		||||
    for (int i = 0; i < 10; i++) {
 | 
			
		||||
        mbed_mpu_init();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    mbed_mpu_free();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mpu_free_test()
 | 
			
		||||
{
 | 
			
		||||
    mbed_mpu_init();
 | 
			
		||||
 | 
			
		||||
    // Enable the MPU
 | 
			
		||||
    mbed_mpu_enable_ram_xn(true);
 | 
			
		||||
 | 
			
		||||
    // Free and ensure execution from RAM is allowed
 | 
			
		||||
    mbed_mpu_free();
 | 
			
		||||
 | 
			
		||||
    call_mem(&data_function);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mpu_fault_test_data()
 | 
			
		||||
{
 | 
			
		||||
    mpu_fault_test(&data_function);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mpu_fault_test_bss()
 | 
			
		||||
{
 | 
			
		||||
    bss_function = ASM_BX_LR;
 | 
			
		||||
    clear_caches();
 | 
			
		||||
    mpu_fault_test(&bss_function);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mpu_fault_test_stack()
 | 
			
		||||
{
 | 
			
		||||
    uint16_t stack_function;
 | 
			
		||||
 | 
			
		||||
    stack_function = ASM_BX_LR;
 | 
			
		||||
    clear_caches();
 | 
			
		||||
    mpu_fault_test(&stack_function);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mpu_fault_test_heap()
 | 
			
		||||
{
 | 
			
		||||
    uint16_t *heap_function = (uint16_t *)malloc(2);
 | 
			
		||||
 | 
			
		||||
    TEST_ASSERT_NOT_EQUAL(NULL, heap_function);
 | 
			
		||||
    *heap_function = ASM_BX_LR;
 | 
			
		||||
    clear_caches();
 | 
			
		||||
    mpu_fault_test(heap_function);
 | 
			
		||||
 | 
			
		||||
    free(heap_function);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t fault_override_setup(const Case *const source, const size_t index_of_case)
 | 
			
		||||
{
 | 
			
		||||
    // Save old fault handlers and replace it with a new one
 | 
			
		||||
    real_hard_fault_handler = NVIC_GetVector(HARDFAULT_IRQn);
 | 
			
		||||
    real_mem_fault_handler = NVIC_GetVector(MEMFAULT_IRQn);
 | 
			
		||||
    NVIC_SetVector(HARDFAULT_IRQn, (uint32_t)&hard_fault_handler_test);
 | 
			
		||||
    NVIC_SetVector(MEMFAULT_IRQn, (uint32_t)&hard_fault_handler_test);
 | 
			
		||||
 | 
			
		||||
    return greentea_case_setup_handler(source, index_of_case);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t fault_override_teardown(const Case *const source, const size_t passed, const size_t failed,
 | 
			
		||||
                                            const failure_t reason)
 | 
			
		||||
{
 | 
			
		||||
    // Restore real fault handlers
 | 
			
		||||
    NVIC_SetVector(HARDFAULT_IRQn, real_hard_fault_handler);
 | 
			
		||||
    NVIC_SetVector(MEMFAULT_IRQn, real_mem_fault_handler);
 | 
			
		||||
 | 
			
		||||
    return greentea_case_teardown_handler(source, passed, failed, reason);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Case cases[] = {
 | 
			
		||||
    Case("MPU - init", fault_override_setup, mpu_init_test, fault_override_teardown),
 | 
			
		||||
    Case("MPU - free", fault_override_setup, mpu_free_test, fault_override_teardown),
 | 
			
		||||
#if !((__ARM_ARCH_8M_BASE__ == 1U) || (__ARM_ARCH_8M_MAIN__ == 1U))
 | 
			
		||||
    // Skip fault tests for ARMv8-M until a fault handler hook is provided
 | 
			
		||||
    Case("MPU - data fault", fault_override_setup, mpu_fault_test_data, fault_override_teardown),
 | 
			
		||||
    Case("MPU - bss fault", fault_override_setup, mpu_fault_test_bss, fault_override_teardown),
 | 
			
		||||
    Case("MPU - stack fault", fault_override_setup, mpu_fault_test_stack, fault_override_teardown),
 | 
			
		||||
    Case("MPU - heap fault", fault_override_setup, mpu_fault_test_heap, fault_override_teardown)
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
 | 
			
		||||
{
 | 
			
		||||
    GREENTEA_SETUP(20, "default_auto");
 | 
			
		||||
    return greentea_test_setup_handler(number_of_cases);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    Harness::run(specification);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,94 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \addtogroup hal_mpu_tests
 | 
			
		||||
 *  @{
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef MBED_MPU_TEST_H
 | 
			
		||||
#define MBED_MPU_TEST_H
 | 
			
		||||
 | 
			
		||||
#if DEVICE_MPU
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** Test that ::mbed_mpu_init can be called multiple times.
 | 
			
		||||
 *
 | 
			
		||||
 *  Given board provides MPU.
 | 
			
		||||
 *  When ::mbed_mpu_init is called multiple times.
 | 
			
		||||
 *  Then ::mbed_mpu_init are successfully performed (no exception is generated).
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
void mpu_init_test(void);
 | 
			
		||||
 | 
			
		||||
/** Test that ::mbed_mpu_free disables the MPU
 | 
			
		||||
 *
 | 
			
		||||
 * Given board provides MPU.
 | 
			
		||||
 * When ::mbed_mpu_free is called.
 | 
			
		||||
 * Then execution from RAM is allowed.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
void mpu_free_test(void);
 | 
			
		||||
 | 
			
		||||
/** Test that MPU protection works for global data
 | 
			
		||||
 *
 | 
			
		||||
 * Given board provides MPU.
 | 
			
		||||
 * When RAM execution is disabled with a call to ::mbed_mpu_enable_ram_xn.
 | 
			
		||||
 * Then execution from global initialized data results in a fault.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
void mpu_fault_test_data(void);
 | 
			
		||||
 | 
			
		||||
/** Test that MPU protection works for zero initialized data
 | 
			
		||||
 *
 | 
			
		||||
 * Given board provides MPU.
 | 
			
		||||
 * When RAM execution is disabled with a call to ::mbed_mpu_enable_ram_xn.
 | 
			
		||||
 * Then execution from global uninitialized data results in a fault.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
void mpu_fault_test_bss(void);
 | 
			
		||||
 | 
			
		||||
/** Test that MPU protection works for the stack
 | 
			
		||||
 *
 | 
			
		||||
 * Given board provides MPU.
 | 
			
		||||
 * When RAM execution is disabled with a call to ::mbed_mpu_enable_ram_xn.
 | 
			
		||||
 * Then execution from stack memory results in a fault.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
void mpu_fault_test_stack(void);
 | 
			
		||||
 | 
			
		||||
/** Test that MPU protection works for the heap
 | 
			
		||||
 *
 | 
			
		||||
 * Given board provides MPU.
 | 
			
		||||
 * When RAM execution is disabled with a call to ::mbed_mpu_enable_ram_xn.
 | 
			
		||||
 * Then execution from heap memory results in a fault.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
void mpu_fault_test_heap(void);
 | 
			
		||||
 | 
			
		||||
/**@}*/
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @}*/
 | 
			
		||||
| 
						 | 
				
			
			@ -2083,6 +2083,7 @@ PREDEFINED             = DOXYGEN_ONLY            \
 | 
			
		|||
                         DEVICE_INTERRUPTIN      \
 | 
			
		||||
                         DEVICE_ITM              \
 | 
			
		||||
                         DEVICE_LPTICKER         \
 | 
			
		||||
                         DEVICE_MPU              \
 | 
			
		||||
                         DEVICE_PORTIN           \
 | 
			
		||||
                         DEVICE_PORTINOUT        \
 | 
			
		||||
                         DEVICE_PORTOUT          \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
    "SEARCH_INCLUDES": "YES",
 | 
			
		||||
    "INCLUDE_PATH": "",
 | 
			
		||||
    "INCLUDE_FILE_PATTERNS": "",
 | 
			
		||||
    "PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH  DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LPTICKER DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_QSPI DEVICE_STORAGE \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\"",
 | 
			
		||||
    "PREDEFINED": "DOXYGEN_ONLY DEVICE_ANALOGIN DEVICE_ANALOGOUT DEVICE_CAN DEVICE_CRC DEVICE_ETHERNET DEVICE_EMAC DEVICE_FLASH  DEVICE_I2C DEVICE_I2CSLAVE DEVICE_I2C_ASYNCH DEVICE_INTERRUPTIN DEVICE_ITM DEVICE_LPTICKER DEVICE_MPU DEVICE_PORTIN DEVICE_PORTINOUT DEVICE_PORTOUT DEVICE_PWMOUT DEVICE_RTC DEVICE_TRNG DEVICE_SERIAL DEVICE_SERIAL_ASYNCH DEVICE_SERIAL_FC DEVICE_SLEEP DEVICE_SPI DEVICE_SPI_ASYNCH DEVICE_SPISLAVE DEVICE_QSPI DEVICE_STORAGE \"MBED_DEPRECATED_SINCE(f, g)=\" \"MBED_ENABLE_IF_CALLBACK_COMPATIBLE(F, M)=\" \"MBED_DEPRECATED(s)=\"",
 | 
			
		||||
    "EXPAND_AS_DEFINED": "",
 | 
			
		||||
    "SKIP_FUNCTION_MACROS": "NO",
 | 
			
		||||
    "STRIP_CODE_COMMENTS": "NO",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,8 @@
 | 
			
		|||
#include <algorithm>
 | 
			
		||||
#include "FlashIAP.h"
 | 
			
		||||
#include "platform/mbed_assert.h"
 | 
			
		||||
#include "platform/ScopedRamExecutionLock.h"
 | 
			
		||||
#include "platform/ScopedRomWriteLock.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef DEVICE_FLASH
 | 
			
		||||
| 
						 | 
				
			
			@ -56,8 +58,12 @@ int FlashIAP::init()
 | 
			
		|||
{
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
    _mutex->lock();
 | 
			
		||||
    if (flash_init(&_flash)) {
 | 
			
		||||
        ret = -1;
 | 
			
		||||
    {
 | 
			
		||||
        ScopedRamExecutionLock make_ram_executable;
 | 
			
		||||
        ScopedRomWriteLock make_rom_writable;
 | 
			
		||||
        if (flash_init(&_flash)) {
 | 
			
		||||
            ret = -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    uint32_t page_size = get_page_size();
 | 
			
		||||
    _page_buf = new uint8_t[page_size];
 | 
			
		||||
| 
						 | 
				
			
			@ -70,8 +76,12 @@ int FlashIAP::deinit()
 | 
			
		|||
{
 | 
			
		||||
    int ret = 0;
 | 
			
		||||
    _mutex->lock();
 | 
			
		||||
    if (flash_free(&_flash)) {
 | 
			
		||||
        ret = -1;
 | 
			
		||||
    {
 | 
			
		||||
        ScopedRamExecutionLock make_ram_executable;
 | 
			
		||||
        ScopedRomWriteLock make_rom_writable;
 | 
			
		||||
        if (flash_free(&_flash)) {
 | 
			
		||||
            ret = -1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    delete[] _page_buf;
 | 
			
		||||
    _mutex->unlock();
 | 
			
		||||
| 
						 | 
				
			
			@ -83,7 +93,11 @@ int FlashIAP::read(void *buffer, uint32_t addr, uint32_t size)
 | 
			
		|||
{
 | 
			
		||||
    int32_t ret = -1;
 | 
			
		||||
    _mutex->lock();
 | 
			
		||||
    ret = flash_read(&_flash, addr, (uint8_t *) buffer, size);
 | 
			
		||||
    {
 | 
			
		||||
        ScopedRamExecutionLock make_ram_executable;
 | 
			
		||||
        ScopedRomWriteLock make_rom_writable;
 | 
			
		||||
        ret = flash_read(&_flash, addr, (uint8_t *) buffer, size);
 | 
			
		||||
    }
 | 
			
		||||
    _mutex->unlock();
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -126,9 +140,13 @@ int FlashIAP::program(const void *buffer, uint32_t addr, uint32_t size)
 | 
			
		|||
            prog_buf = buf;
 | 
			
		||||
            prog_size = chunk;
 | 
			
		||||
        }
 | 
			
		||||
        if (flash_program_page(&_flash, addr, prog_buf, prog_size)) {
 | 
			
		||||
            ret = -1;
 | 
			
		||||
            break;
 | 
			
		||||
        {
 | 
			
		||||
            ScopedRamExecutionLock make_ram_executable;
 | 
			
		||||
            ScopedRomWriteLock make_rom_writable;
 | 
			
		||||
            if (flash_program_page(&_flash, addr, prog_buf, prog_size)) {
 | 
			
		||||
                ret = -1;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        size -= chunk;
 | 
			
		||||
        addr += chunk;
 | 
			
		||||
| 
						 | 
				
			
			@ -170,7 +188,11 @@ int FlashIAP::erase(uint32_t addr, uint32_t size)
 | 
			
		|||
    int32_t ret = 0;
 | 
			
		||||
    _mutex->lock();
 | 
			
		||||
    while (size) {
 | 
			
		||||
        ret = flash_erase_sector(&_flash, addr);
 | 
			
		||||
        {
 | 
			
		||||
            ScopedRamExecutionLock make_ram_executable;
 | 
			
		||||
            ScopedRomWriteLock make_rom_writable;
 | 
			
		||||
            ret = flash_erase_sector(&_flash, addr);
 | 
			
		||||
        }
 | 
			
		||||
        if (ret != 0) {
 | 
			
		||||
            ret = -1;
 | 
			
		||||
            break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,230 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
#include "hal/mpu_api.h"
 | 
			
		||||
#include "platform/mbed_assert.h"
 | 
			
		||||
#include "platform/mbed_error.h"
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
 | 
			
		||||
#if ((__ARM_ARCH_7M__ == 1U) || (__ARM_ARCH_7EM__ == 1U) || (__ARM_ARCH_6M__ == 1U)) && \
 | 
			
		||||
    defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) && \
 | 
			
		||||
    !defined(MBED_MPU_CUSTOM)
 | 
			
		||||
 | 
			
		||||
#if !DEVICE_MPU
 | 
			
		||||
#error "Device has v7m MPU but it is not enabled. Add 'MPU' to device_has in targets.json"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(MBED_MPU_ROM_END)
 | 
			
		||||
#define MBED_MPU_ROM_END             (0x10000000 - 1)
 | 
			
		||||
#endif
 | 
			
		||||
#define MBED_MPU_RAM_START           (MBED_MPU_ROM_END + 1)
 | 
			
		||||
 | 
			
		||||
MBED_STATIC_ASSERT(
 | 
			
		||||
    MBED_MPU_ROM_END == 0x04000000 - 1 ||
 | 
			
		||||
    MBED_MPU_ROM_END == 0x08000000 - 1 ||
 | 
			
		||||
    MBED_MPU_ROM_END == 0x0C000000 - 1 ||
 | 
			
		||||
    MBED_MPU_ROM_END == 0x10000000 - 1 ||
 | 
			
		||||
    MBED_MPU_ROM_END == 0x14000000 - 1 ||
 | 
			
		||||
    MBED_MPU_ROM_END == 0x18000000 - 1 ||
 | 
			
		||||
    MBED_MPU_ROM_END == 0x1C000000 - 1 ||
 | 
			
		||||
    MBED_MPU_ROM_END == 0x20000000 - 1,
 | 
			
		||||
    "Unsupported value for MBED_MPU_ROM_END");
 | 
			
		||||
 | 
			
		||||
void mbed_mpu_init()
 | 
			
		||||
{
 | 
			
		||||
    // Flush memory writes before configuring the MPU.
 | 
			
		||||
    __DSB();
 | 
			
		||||
 | 
			
		||||
    const uint32_t regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
 | 
			
		||||
    if (regions < 4) {
 | 
			
		||||
        MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_EINVAL), "Device is not capable of supporting an MPU - remove DEVICE_MPU for device_has.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Disable the MCU
 | 
			
		||||
    MPU->CTRL = 0;
 | 
			
		||||
 | 
			
		||||
    // Reset all mapping
 | 
			
		||||
    for (uint32_t i = 0; i < regions; i++) {
 | 
			
		||||
        ARM_MPU_ClrRegion(i);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * ARMv6m and ARMv7-M memory map:
 | 
			
		||||
     *
 | 
			
		||||
     * Start        End            Name            Executable by default        Mbed MPU protection
 | 
			
		||||
     * 0x00000000 - 0x1FFFFFFF     Code            Yes                          Write disabled for first portion and execute disabled for the rest
 | 
			
		||||
     * 0x20000000 - 0x3FFFFFFF     SRAM            Yes                          Execute disabled
 | 
			
		||||
     * 0x40000000 - 0x5FFFFFFF     Peripheral      No
 | 
			
		||||
     * 0x60000000 - 0x7FFFFFFF     RAM             Yes                          Execute disabled
 | 
			
		||||
     * 0x80000000 - 0x9FFFFFFF     RAM             Yes                          Execute disabled
 | 
			
		||||
     * 0xA0000000 - 0xBFFFFFFF     Device          No
 | 
			
		||||
     * 0xC0000000 - 0xDFFFFFFF     Device          No
 | 
			
		||||
     * 0xE0000000 - 0xFFFFFFFF     System          No
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    // Select region 1 and used it for the WT rom region
 | 
			
		||||
    // - RAM 0x00000000 to MBED_MPU_ROM_END
 | 
			
		||||
    MPU->RNR = 0;
 | 
			
		||||
    // Set address to 0
 | 
			
		||||
    MPU->RBAR = 0;
 | 
			
		||||
    // Configure and enable region
 | 
			
		||||
    MPU->RASR =
 | 
			
		||||
        ARM_MPU_RASR(
 | 
			
		||||
            0,                          // DisableExec
 | 
			
		||||
            ARM_MPU_AP_RO,              // AccessPermission
 | 
			
		||||
            0,                          // TypeExtField
 | 
			
		||||
            0,                          // IsShareable
 | 
			
		||||
            1,                          // IsCacheable
 | 
			
		||||
            0,                          // IsBufferable
 | 
			
		||||
            // SubRegionDisable - based on where ROM ends
 | 
			
		||||
            ((MBED_MPU_ROM_END >= 0x00000000) ? 0 : (1 << 0)) |    // 0 to enable, 1 << n to disable
 | 
			
		||||
            ((MBED_MPU_ROM_END >= 0x04000000) ? 0 : (1 << 1)) |
 | 
			
		||||
            ((MBED_MPU_ROM_END >= 0x08000000) ? 0 : (1 << 2)) |
 | 
			
		||||
            ((MBED_MPU_ROM_END >= 0x0C000000) ? 0 : (1 << 3)) |
 | 
			
		||||
            ((MBED_MPU_ROM_END >= 0x10000000) ? 0 : (1 << 4)) |
 | 
			
		||||
            ((MBED_MPU_ROM_END >= 0x14000000) ? 0 : (1 << 5)) |
 | 
			
		||||
            ((MBED_MPU_ROM_END >= 0x18000000) ? 0 : (1 << 6)) |
 | 
			
		||||
            ((MBED_MPU_ROM_END >= 0x1C000000) ? 0 : (1 << 7)),
 | 
			
		||||
            ARM_MPU_REGION_SIZE_512MB   // Size
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
    // Select region 1 and used it for the WT rom region
 | 
			
		||||
    // - RAM MBED_MPU_ROM_END + 1 to 0x1FFFFFFF
 | 
			
		||||
    MPU->RNR = 1;
 | 
			
		||||
    // Set address to 0
 | 
			
		||||
    MPU->RBAR = 0;
 | 
			
		||||
    // Configure and enable region
 | 
			
		||||
    MPU->RASR =
 | 
			
		||||
        ARM_MPU_RASR(
 | 
			
		||||
            1,                          // DisableExec
 | 
			
		||||
            ARM_MPU_AP_FULL,            // AccessPermission
 | 
			
		||||
            0,                          // TypeExtField
 | 
			
		||||
            0,                          // IsShareable
 | 
			
		||||
            1,                          // IsCacheable
 | 
			
		||||
            0,                          // IsBufferable
 | 
			
		||||
            // SubRegionDisable - based on where RAM starts
 | 
			
		||||
            ((MBED_MPU_RAM_START <= 0x04000000) ? 0 : (1 << 0)) |    // 0 to enable, 1 << n to disable
 | 
			
		||||
            ((MBED_MPU_RAM_START <= 0x08000000) ? 0 : (1 << 1)) |
 | 
			
		||||
            ((MBED_MPU_RAM_START <= 0x0C000000) ? 0 : (1 << 2)) |
 | 
			
		||||
            ((MBED_MPU_RAM_START <= 0x10000000) ? 0 : (1 << 3)) |
 | 
			
		||||
            ((MBED_MPU_RAM_START <= 0x14000000) ? 0 : (1 << 4)) |
 | 
			
		||||
            ((MBED_MPU_RAM_START <= 0x18000000) ? 0 : (1 << 5)) |
 | 
			
		||||
            ((MBED_MPU_RAM_START <= 0x1C000000) ? 0 : (1 << 6)) |
 | 
			
		||||
            ((MBED_MPU_RAM_START <= 0x20000000) ? 0 : (1 << 7)),
 | 
			
		||||
            ARM_MPU_REGION_SIZE_512MB   // Size
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
    // Select region 2 and used it for WBWA ram regions
 | 
			
		||||
    // - SRAM 0x20000000 to 0x3FFFFFFF
 | 
			
		||||
    // - RAM  0x60000000 to 0x7FFFFFFF
 | 
			
		||||
    MPU->RNR = 2;
 | 
			
		||||
    // Set address to 0
 | 
			
		||||
    MPU->RBAR = 0;
 | 
			
		||||
    // Configure and enable region
 | 
			
		||||
    MPU->RASR =
 | 
			
		||||
        ARM_MPU_RASR(
 | 
			
		||||
            1,                          // DisableExec
 | 
			
		||||
            ARM_MPU_AP_FULL,            // AccessPermission
 | 
			
		||||
            1,                          // TypeExtField
 | 
			
		||||
            0,                          // IsShareable
 | 
			
		||||
            1,                          // IsCacheable
 | 
			
		||||
            1,                          // IsBufferable
 | 
			
		||||
            // SubRegionDisable
 | 
			
		||||
            (1 << 0) |     // Disable Sub-region
 | 
			
		||||
            (0 << 1) |     // Enable Sub-region SRAM 0x20000000 - 0x3FFFFFFF
 | 
			
		||||
            (1 << 2) |     // Disable Sub-region
 | 
			
		||||
            (0 << 3) |     // Enable Sub-region RAM 0x60000000 - 0x7FFFFFFF
 | 
			
		||||
            (1 << 4) |     // Disable Sub-region
 | 
			
		||||
            (1 << 5) |     // Disable Sub-region
 | 
			
		||||
            (1 << 6) |     // Disable Sub-region
 | 
			
		||||
            (1 << 7),      // Disable Sub-region
 | 
			
		||||
            ARM_MPU_REGION_SIZE_4GB     // Size
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
    // Select region 3 and used it for the WT ram region
 | 
			
		||||
    // - RAM RAM 0x80000000 to 0x9FFFFFFF
 | 
			
		||||
    MPU->RNR = 3;
 | 
			
		||||
    // Set address
 | 
			
		||||
    MPU->RBAR = 0x80000000;
 | 
			
		||||
    // Configure and enable region
 | 
			
		||||
    MPU->RASR =
 | 
			
		||||
        ARM_MPU_RASR(
 | 
			
		||||
            1,                          // DisableExec
 | 
			
		||||
            ARM_MPU_AP_FULL,            // AccessPermission
 | 
			
		||||
            0,                          // TypeExtField
 | 
			
		||||
            0,                          // IsShareable
 | 
			
		||||
            1,                          // IsCacheable
 | 
			
		||||
            0,                          // IsBufferable
 | 
			
		||||
            ~0U,                        // SubRegionDisable
 | 
			
		||||
            ARM_MPU_REGION_SIZE_512MB   // Size
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
    // Enable the MPU
 | 
			
		||||
    MPU->CTRL =
 | 
			
		||||
        (1 << MPU_CTRL_PRIVDEFENA_Pos) |            // Use the default memory map for unmapped addresses
 | 
			
		||||
        (1 << MPU_CTRL_HFNMIENA_Pos) |              // Keep MPU turned on for faults
 | 
			
		||||
        (1 << MPU_CTRL_ENABLE_Pos);                 // Enable MPU
 | 
			
		||||
 | 
			
		||||
    // Ensure changes take effect
 | 
			
		||||
    __ISB();
 | 
			
		||||
    __DSB();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbed_mpu_free()
 | 
			
		||||
{
 | 
			
		||||
    // Flush memory writes before configuring the MPU.
 | 
			
		||||
    __DSB();
 | 
			
		||||
 | 
			
		||||
    // Disable the MPU
 | 
			
		||||
    MPU->CTRL = 0;
 | 
			
		||||
 | 
			
		||||
    // Ensure changes take effect
 | 
			
		||||
    __ISB();
 | 
			
		||||
    __DSB();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbed_mpu_enable_rom_wn(bool enable)
 | 
			
		||||
{
 | 
			
		||||
    // Flush memory writes before configuring the MPU.
 | 
			
		||||
    __DSB();
 | 
			
		||||
 | 
			
		||||
    MPU->RNR = 0;
 | 
			
		||||
    MPU->RASR = (MPU->RASR & ~MPU_RASR_ENABLE_Msk) | (enable ? MPU_RASR_ENABLE_Msk : 0);
 | 
			
		||||
 | 
			
		||||
    // Ensure changes take effect
 | 
			
		||||
    __ISB();
 | 
			
		||||
    __DSB();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbed_mpu_enable_ram_xn(bool enable)
 | 
			
		||||
{
 | 
			
		||||
    // Flush memory writes before configuring the MPU.
 | 
			
		||||
    __DSB();
 | 
			
		||||
 | 
			
		||||
    MPU->RNR = 1;
 | 
			
		||||
    MPU->RASR = (MPU->RASR & ~MPU_RASR_ENABLE_Msk) | (enable ? MPU_RASR_ENABLE_Msk : 0);
 | 
			
		||||
 | 
			
		||||
    MPU->RNR = 2;
 | 
			
		||||
    MPU->RASR = (MPU->RASR & ~MPU_RASR_ENABLE_Msk) | (enable ? MPU_RASR_ENABLE_Msk : 0);
 | 
			
		||||
 | 
			
		||||
    MPU->RNR = 3;
 | 
			
		||||
    MPU->RASR = (MPU->RASR & ~MPU_RASR_ENABLE_Msk) | (enable ? MPU_RASR_ENABLE_Msk : 0);
 | 
			
		||||
 | 
			
		||||
    // Ensure changes take effect
 | 
			
		||||
    __ISB();
 | 
			
		||||
    __DSB();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,175 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
#include "hal/mpu_api.h"
 | 
			
		||||
#include "platform/mbed_assert.h"
 | 
			
		||||
#include "platform/mbed_error.h"
 | 
			
		||||
#include "cmsis.h"
 | 
			
		||||
 | 
			
		||||
#if ((__ARM_ARCH_8M_BASE__ == 1U) || (__ARM_ARCH_8M_MAIN__ == 1U)) && \
 | 
			
		||||
    defined (__MPU_PRESENT) && (__MPU_PRESENT == 1U) && \
 | 
			
		||||
    !defined(MBED_MPU_CUSTOM)
 | 
			
		||||
 | 
			
		||||
#if !DEVICE_MPU
 | 
			
		||||
#error "Device has v8m MPU but it is not enabled. Add 'MPU' to device_has in targets.json"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(MBED_MPU_ROM_END)
 | 
			
		||||
#define MBED_MPU_ROM_END             (0x20000000 - 1)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
MBED_STATIC_ASSERT(MBED_MPU_ROM_END == 0x1fffffff, "Changing MBED_MPU_ROM_END for ARMv8-M is not supported.");
 | 
			
		||||
 | 
			
		||||
void mbed_mpu_init()
 | 
			
		||||
{
 | 
			
		||||
    // Flush memory writes before configuring the MPU.
 | 
			
		||||
    __DSB();
 | 
			
		||||
 | 
			
		||||
    const uint32_t regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
 | 
			
		||||
    if (regions < 4) {
 | 
			
		||||
        MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_HAL, MBED_ERROR_CODE_EINVAL), "Device is not capable of supporting an MPU - remove DEVICE_MPU for device_has.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Disable the MCU
 | 
			
		||||
    MPU->CTRL = 0;
 | 
			
		||||
 | 
			
		||||
    // Reset all mapping
 | 
			
		||||
    for (uint32_t i = 0; i < regions; i++) {
 | 
			
		||||
        ARM_MPU_ClrRegionEx(MPU, i);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * ARMv8-M memory map:
 | 
			
		||||
     *
 | 
			
		||||
     * Start        End            Name            Executable by default    Default cache       Mbed MPU protection
 | 
			
		||||
     * 0x00000000 - 0x1FFFFFFF     Code            Yes                      WT, WA              Write disabled
 | 
			
		||||
     * 0x20000000 - 0x3FFFFFFF     SRAM            Yes                      WB, WA, RA          Execute disabled
 | 
			
		||||
     * 0x40000000 - 0x5FFFFFFF     Peripheral      No
 | 
			
		||||
     * 0x60000000 - 0x7FFFFFFF     RAM             Yes                      WB, WA, RA          Execute disabled
 | 
			
		||||
     * 0x80000000 - 0x9FFFFFFF     RAM             Yes                      WT, RA              Execute disabled
 | 
			
		||||
     * 0xA0000000 - 0xBFFFFFFF     Device          No
 | 
			
		||||
     * 0xC0000000 - 0xDFFFFFFF     Device          No
 | 
			
		||||
     * 0xE0000000 - 0xFFFFFFFF     System          No
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    uint32_t region;
 | 
			
		||||
    uint8_t outer;
 | 
			
		||||
    uint8_t inner;
 | 
			
		||||
 | 
			
		||||
    region = 0;
 | 
			
		||||
    MPU->RNR = region;
 | 
			
		||||
    outer = 0xA;    // Write-Through, Non-transient, Read-allocate
 | 
			
		||||
    inner = 0xA;    // Write-Through, Non-transient, Read-allocate
 | 
			
		||||
    ARM_MPU_SetMemAttrEx(MPU, region, (outer << 4) | (inner << 0));
 | 
			
		||||
    MPU->RBAR = (0x00000000 & MPU_RBAR_BASE_Msk) |      // Start address is 0x00000000
 | 
			
		||||
                (0 << MPU_RBAR_SH_Pos) |             // Not shareable
 | 
			
		||||
                (3 << MPU_RBAR_AP_Pos) |             // RO allowed by all privilege levels
 | 
			
		||||
                (0 << MPU_RBAR_XN_Pos);              // Execute Never disabled
 | 
			
		||||
    MPU->RLAR = (0x1FFFFFFF & MPU_RLAR_LIMIT_Msk) |     // Last address is 0x1FFFFFFF
 | 
			
		||||
                (region << MPU_RLAR_AttrIndx_Pos);   // Attribute index - configured to be the same as the region number
 | 
			
		||||
 | 
			
		||||
    region = 1;
 | 
			
		||||
    MPU->RNR = region;
 | 
			
		||||
    outer = 0xF;    // Write-Back, Non-transient, Read-allocate, Write-allocate
 | 
			
		||||
    outer = 0xF;    // Write-Back, Non-transient, Read-allocate, Write-allocate
 | 
			
		||||
    ARM_MPU_SetMemAttrEx(MPU, region, (outer << 4) | (inner << 0));
 | 
			
		||||
    MPU->RBAR = (0x20000000 & MPU_RBAR_BASE_Msk) |      // Start address is 0x20000000
 | 
			
		||||
                (0 << MPU_RBAR_SH_Pos) |             // Not shareable
 | 
			
		||||
                (1 << MPU_RBAR_AP_Pos) |             // RW allowed by all privilege levels
 | 
			
		||||
                (1 << MPU_RBAR_XN_Pos);              // Execute Never enabled
 | 
			
		||||
    MPU->RLAR = (0x3FFFFFFF & MPU_RLAR_LIMIT_Msk) |     // Last address is 0x3FFFFFFF
 | 
			
		||||
                (region << MPU_RLAR_AttrIndx_Pos);   // Attribute index - configured to be the same as the region number
 | 
			
		||||
 | 
			
		||||
    region = 2;
 | 
			
		||||
    MPU->RNR = region;
 | 
			
		||||
    outer = 0xF;    // Write-Back, Non-transient, Read-allocate, Write-allocate
 | 
			
		||||
    outer = 0xF;    // Write-Back, Non-transient, Read-allocate, Write-allocate
 | 
			
		||||
    ARM_MPU_SetMemAttrEx(MPU, region, (outer << 4) | (inner << 0));
 | 
			
		||||
    MPU->RBAR = (0x60000000 & MPU_RBAR_BASE_Msk) |      // Start address is 0x60000000
 | 
			
		||||
                (0 << MPU_RBAR_SH_Pos) |             // Not shareable
 | 
			
		||||
                (1 << MPU_RBAR_AP_Pos) |             // RW allowed by all privilege levels
 | 
			
		||||
                (1 << MPU_RBAR_XN_Pos);              // Execute Never enabled
 | 
			
		||||
    MPU->RLAR = (0x7FFFFFFF & MPU_RLAR_LIMIT_Msk) |     // Last address is 0x7FFFFFFF
 | 
			
		||||
                (region << MPU_RLAR_AttrIndx_Pos);   // Attribute index - configured to be the same as the region number
 | 
			
		||||
 | 
			
		||||
    region = 3;
 | 
			
		||||
    MPU->RNR = region;
 | 
			
		||||
    outer = 0xA;    // Write-Through, Non-transient, Read-allocate
 | 
			
		||||
    inner = 0xA;    // Write-Through, Non-transient, Read-allocate
 | 
			
		||||
    ARM_MPU_SetMemAttrEx(MPU, region, (outer << 4) | (inner << 0));
 | 
			
		||||
    MPU->RBAR = (0x80000000 & MPU_RBAR_BASE_Msk) |      // Start address is 0x80000000
 | 
			
		||||
                (0 << MPU_RBAR_SH_Pos) |             // Not shareable
 | 
			
		||||
                (1 << MPU_RBAR_AP_Pos) |             // RW allowed by all privilege levels
 | 
			
		||||
                (1 << MPU_RBAR_XN_Pos);              // Execute Never enabled
 | 
			
		||||
    MPU->RLAR = (0x9FFFFFFF & MPU_RLAR_LIMIT_Msk) |     // Last address is 0x9FFFFFFF
 | 
			
		||||
                (region << MPU_RLAR_AttrIndx_Pos);   // Attribute index - configured to be the same as the region number
 | 
			
		||||
 | 
			
		||||
    // Enable the MPU
 | 
			
		||||
    MPU->CTRL =
 | 
			
		||||
        (1 << MPU_CTRL_PRIVDEFENA_Pos) |            // Use the default memory map for unmapped addresses
 | 
			
		||||
        (1 << MPU_CTRL_HFNMIENA_Pos) |              // Keep MPU turned on for faults
 | 
			
		||||
        (1 << MPU_CTRL_ENABLE_Pos);                 // Enable MPU
 | 
			
		||||
 | 
			
		||||
    // Ensure changes take effect
 | 
			
		||||
    __ISB();
 | 
			
		||||
    __DSB();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbed_mpu_free()
 | 
			
		||||
{
 | 
			
		||||
    // Flush memory writes before configuring the MPU.
 | 
			
		||||
    __DSB();
 | 
			
		||||
 | 
			
		||||
    // Disable the MCU
 | 
			
		||||
    MPU->CTRL = 0;
 | 
			
		||||
 | 
			
		||||
    // Ensure changes take effect
 | 
			
		||||
    __ISB();
 | 
			
		||||
    __DSB();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbed_mpu_enable_rom_wn(bool enable)
 | 
			
		||||
{
 | 
			
		||||
    // Flush memory writes before configuring the MPU.
 | 
			
		||||
    __DSB();
 | 
			
		||||
 | 
			
		||||
    MPU->RNR = 0;
 | 
			
		||||
    MPU->RLAR = (MPU->RLAR & ~MPU_RLAR_EN_Msk) | (enable ? MPU_RLAR_EN_Msk : 0);
 | 
			
		||||
 | 
			
		||||
    // Ensure changes take effect
 | 
			
		||||
    __ISB();
 | 
			
		||||
    __DSB();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbed_mpu_enable_ram_xn(bool enable)
 | 
			
		||||
{
 | 
			
		||||
    // Flush memory writes before configuring the MPU.
 | 
			
		||||
    __DSB();
 | 
			
		||||
 | 
			
		||||
    MPU->RNR = 1;
 | 
			
		||||
    MPU->RLAR = (MPU->RLAR & ~MPU_RLAR_EN_Msk) | (enable ? MPU_RLAR_EN_Msk : 0);
 | 
			
		||||
 | 
			
		||||
    MPU->RNR = 2;
 | 
			
		||||
    MPU->RLAR = (MPU->RLAR & ~MPU_RLAR_EN_Msk) | (enable ? MPU_RLAR_EN_Msk : 0);
 | 
			
		||||
 | 
			
		||||
    MPU->RNR = 3;
 | 
			
		||||
    MPU->RLAR = (MPU->RLAR & ~MPU_RLAR_EN_Msk) | (enable ? MPU_RLAR_EN_Msk : 0);
 | 
			
		||||
 | 
			
		||||
    // Ensure changes take effect
 | 
			
		||||
    __ISB();
 | 
			
		||||
    __DSB();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,118 @@
 | 
			
		|||
 | 
			
		||||
/** \addtogroup hal */
 | 
			
		||||
/** @{*/
 | 
			
		||||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef MBED_MPU_API_H
 | 
			
		||||
#define MBED_MPU_API_H
 | 
			
		||||
 | 
			
		||||
#include "device.h"
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if DEVICE_MPU
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \defgroup hal_mpu MPU hal
 | 
			
		||||
 *
 | 
			
		||||
 * The MPU hal provides a simple MPU API to enhance device security by preventing
 | 
			
		||||
 * execution from ram.
 | 
			
		||||
 *
 | 
			
		||||
 * # Defined behavior
 | 
			
		||||
 * * The function ::mbed_mpu_init is safe to call repeatedly - Verified by ::mpu_init_test
 | 
			
		||||
 * * The function ::mbed_mpu_free disables MPU protection - Verified by ::mpu_free_test
 | 
			
		||||
 * * Execution from RAM results in a fault when execute never is enabled.
 | 
			
		||||
 *      This RAM includes heap, stack, data and zero init - Verified  by ::mpu_fault_test_data,
 | 
			
		||||
 *      ::mpu_fault_test_bss, ::mpu_fault_test_stack and ::mpu_fault_test_heap.
 | 
			
		||||
 * * Writing to ROM results in a fault when write never is enabled - Not verified
 | 
			
		||||
 *
 | 
			
		||||
 * # Undefined behavior
 | 
			
		||||
 * * Calling any function other than ::mbed_mpu_init before the initialization of the MPU.
 | 
			
		||||
 *
 | 
			
		||||
 * @see hal_mpu_tests
 | 
			
		||||
 *
 | 
			
		||||
 * @{
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \defgroup hal_mpu_tests MPU hal tests
 | 
			
		||||
 * The MPU test validates proper implementation of the MPU hal.
 | 
			
		||||
 *
 | 
			
		||||
 * To run the MPU hal tests use the command:
 | 
			
		||||
 *
 | 
			
		||||
 *     mbed test -t <toolchain> -m <target> -n tests-mbed_hal-mpu*
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Initialize the MPU
 | 
			
		||||
 *
 | 
			
		||||
 * Initialize or re-initialize the memory protection unit.
 | 
			
		||||
 * It is implementation defined what region are protected
 | 
			
		||||
 * by the MPU after initialization.
 | 
			
		||||
 */
 | 
			
		||||
void mbed_mpu_init(void);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Enable or disable ROM MPU protection
 | 
			
		||||
 *
 | 
			
		||||
 * This function is used to mark all of ROM as read and execute only.
 | 
			
		||||
 * When enabled writes to ROM cause a fault.
 | 
			
		||||
 *
 | 
			
		||||
 * @param enable true to disable execution in ram, false otherwise
 | 
			
		||||
 */
 | 
			
		||||
void mbed_mpu_enable_rom_wn(bool enable);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Enable or disable ram MPU protection
 | 
			
		||||
 *
 | 
			
		||||
 * This function is used to mark all of RAM as execute never.
 | 
			
		||||
 * When enabled code is only allowed to execute from flash.
 | 
			
		||||
 *
 | 
			
		||||
 * @param enable true to disable execution in ram, false otherwise
 | 
			
		||||
 */
 | 
			
		||||
void mbed_mpu_enable_ram_xn(bool enable);
 | 
			
		||||
 | 
			
		||||
/** Deinitialize the MPU
 | 
			
		||||
 *
 | 
			
		||||
 * Powerdown the MPU in preparation for powerdown, reset or jumping to another application.
 | 
			
		||||
 */
 | 
			
		||||
void mbed_mpu_free(void);
 | 
			
		||||
 | 
			
		||||
/**@}*/
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#define mbed_mpu_init()
 | 
			
		||||
 | 
			
		||||
#define mbed_mpu_enable_rom_wn(enable) (void)enable
 | 
			
		||||
 | 
			
		||||
#define mbed_mpu_enable_ram_xn(enable) (void)enable
 | 
			
		||||
 | 
			
		||||
#define mbed_mpu_free()
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @}*/
 | 
			
		||||
							
								
								
									
										2
									
								
								mbed.h
								
								
								
								
							
							
						
						
									
										2
									
								
								mbed.h
								
								
								
								
							| 
						 | 
				
			
			@ -95,6 +95,8 @@
 | 
			
		|||
#include "platform/DirHandle.h"
 | 
			
		||||
#include "platform/CriticalSectionLock.h"
 | 
			
		||||
#include "platform/DeepSleepLock.h"
 | 
			
		||||
#include "platform/ScopedRomWriteLock.h"
 | 
			
		||||
#include "platform/ScopedRamExecutionLock.h"
 | 
			
		||||
#include "platform/mbed_stats.h"
 | 
			
		||||
 | 
			
		||||
// mbed Non-hardware components
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef MBED_SCOPEDRAMEXECUTIONLOCK_H
 | 
			
		||||
#define MBED_SCOPEDRAMEXECUTIONLOCK_H
 | 
			
		||||
 | 
			
		||||
#include "platform/mbed_mpu_mgmt.h"
 | 
			
		||||
#include "platform/NonCopyable.h"
 | 
			
		||||
 | 
			
		||||
namespace mbed {
 | 
			
		||||
 | 
			
		||||
/** \addtogroup platform */
 | 
			
		||||
/** @{*/
 | 
			
		||||
 | 
			
		||||
/** RAII object for disabling, then restoring RAM execute never mode
 | 
			
		||||
  * Usage:
 | 
			
		||||
  * @code
 | 
			
		||||
  *
 | 
			
		||||
  * void f() {
 | 
			
		||||
  *     // some code here
 | 
			
		||||
  *     {
 | 
			
		||||
  *         ScopedRamExecutionLock make_ram_executable;
 | 
			
		||||
  *         // Code in this block is allowed to call functions in RAM
 | 
			
		||||
  *     }
 | 
			
		||||
  *     // Execution from RAM is no longer allowed
 | 
			
		||||
  * }
 | 
			
		||||
  * @endcode
 | 
			
		||||
  */
 | 
			
		||||
class ScopedRamExecutionLock : private mbed::NonCopyable<ScopedRamExecutionLock> {
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Allow execution from RAM
 | 
			
		||||
     *
 | 
			
		||||
     * Increment the execute never lock to ensure code can
 | 
			
		||||
     * be executed from RAM. This class uses RAII to allow
 | 
			
		||||
     * execution from ram while it is in scope.
 | 
			
		||||
     */
 | 
			
		||||
    ScopedRamExecutionLock()
 | 
			
		||||
    {
 | 
			
		||||
        mbed_mpu_manager_lock_ram_execution();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Restore previous execution from RAM settings
 | 
			
		||||
     *
 | 
			
		||||
     * Decrement the execute never lock to return execute from RAM
 | 
			
		||||
     * to its prior state.
 | 
			
		||||
     */
 | 
			
		||||
    ~ScopedRamExecutionLock()
 | 
			
		||||
    {
 | 
			
		||||
        mbed_mpu_manager_unlock_ram_execution();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**@}*/
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,72 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef MBED_SCOPEDROMWRITELOCK_H
 | 
			
		||||
#define MBED_SCOPEDROMWRITELOCK_H
 | 
			
		||||
 | 
			
		||||
#include "platform/mbed_mpu_mgmt.h"
 | 
			
		||||
#include "platform/NonCopyable.h"
 | 
			
		||||
 | 
			
		||||
namespace mbed {
 | 
			
		||||
 | 
			
		||||
/** \addtogroup platform */
 | 
			
		||||
/** @{*/
 | 
			
		||||
 | 
			
		||||
/** RAII object for disabling, then restoring ROM write never mode
 | 
			
		||||
  * Usage:
 | 
			
		||||
  * @code
 | 
			
		||||
  *
 | 
			
		||||
  * void f() {
 | 
			
		||||
  *     // some code here
 | 
			
		||||
  *     {
 | 
			
		||||
  *         ScopedRomWriteLock make_ram_executable;
 | 
			
		||||
  *         // Code in this block is allowed to write to ROM
 | 
			
		||||
  *     }
 | 
			
		||||
  *     // Writing to ROM is no longer allowed
 | 
			
		||||
  * }
 | 
			
		||||
  * @endcode
 | 
			
		||||
  */
 | 
			
		||||
class ScopedRomWriteLock : private mbed::NonCopyable<ScopedRomWriteLock> {
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Allow writing to ROM
 | 
			
		||||
     *
 | 
			
		||||
     * Increment the ROM write lock to ensure code can
 | 
			
		||||
     * write to ROM. This class uses RAII to allow
 | 
			
		||||
     * writing to ROM while it is in scope.
 | 
			
		||||
     */
 | 
			
		||||
    ScopedRomWriteLock()
 | 
			
		||||
    {
 | 
			
		||||
        mbed_mpu_manager_lock_rom_write();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Restore previous write to ROM settings
 | 
			
		||||
     *
 | 
			
		||||
     * Decrement the ROM write lock to return ROM write
 | 
			
		||||
     * to its prior state.
 | 
			
		||||
     */
 | 
			
		||||
    ~ScopedRomWriteLock()
 | 
			
		||||
    {
 | 
			
		||||
        mbed_mpu_manager_unlock_rom_write();
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**@}*/
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -18,6 +18,7 @@
 | 
			
		|||
#include <stdarg.h>
 | 
			
		||||
#include "device.h"
 | 
			
		||||
#include "platform/mbed_application.h"
 | 
			
		||||
#include "hal/mpu_api.h"
 | 
			
		||||
 | 
			
		||||
#if MBED_APPLICATION_SUPPORT
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -67,6 +68,7 @@ void mbed_start_application(uintptr_t address)
 | 
			
		|||
    SysTick->CTRL = 0x00000000;
 | 
			
		||||
    powerdown_nvic();
 | 
			
		||||
    powerdown_scb(address);
 | 
			
		||||
    mbed_mpu_free();
 | 
			
		||||
 | 
			
		||||
    sp = *((void **)address + 0);
 | 
			
		||||
    pc = *((void **)address + 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,80 @@
 | 
			
		|||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "platform/mbed_mpu_mgmt.h"
 | 
			
		||||
#include "platform/mbed_critical.h"
 | 
			
		||||
#include "platform/mbed_error.h"
 | 
			
		||||
#include "hal/mpu_api.h"
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
 | 
			
		||||
static uint16_t mem_xn_lock;
 | 
			
		||||
static uint16_t mem_wn_lock;
 | 
			
		||||
 | 
			
		||||
void mbed_mpu_manager_lock_ram_execution()
 | 
			
		||||
{
 | 
			
		||||
    core_util_critical_section_enter();
 | 
			
		||||
    if (mem_xn_lock == USHRT_MAX) {
 | 
			
		||||
        core_util_critical_section_exit();
 | 
			
		||||
        MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OVERFLOW), "Ram execute never lock overflow (> USHRT_MAX)", mem_xn_lock);
 | 
			
		||||
    }
 | 
			
		||||
    if (mem_xn_lock == 0) {
 | 
			
		||||
        mbed_mpu_enable_ram_xn(false);
 | 
			
		||||
    }
 | 
			
		||||
    mem_xn_lock++;
 | 
			
		||||
    core_util_critical_section_exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbed_mpu_manager_unlock_ram_execution()
 | 
			
		||||
{
 | 
			
		||||
    core_util_critical_section_enter();
 | 
			
		||||
    if (mem_xn_lock == 0) {
 | 
			
		||||
        core_util_critical_section_exit();
 | 
			
		||||
        MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNDERFLOW), "Ram execute never lock underflow (< 0)", mem_xn_lock);
 | 
			
		||||
    }
 | 
			
		||||
    mem_xn_lock--;
 | 
			
		||||
    if (mem_xn_lock == 0) {
 | 
			
		||||
        mbed_mpu_enable_ram_xn(true);
 | 
			
		||||
    }
 | 
			
		||||
    core_util_critical_section_exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbed_mpu_manager_lock_rom_write()
 | 
			
		||||
{
 | 
			
		||||
    core_util_critical_section_enter();
 | 
			
		||||
    if (mem_wn_lock == USHRT_MAX) {
 | 
			
		||||
        core_util_critical_section_exit();
 | 
			
		||||
        MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_OVERFLOW), "Rom write never lock overflow (> USHRT_MAX)", mem_wn_lock);
 | 
			
		||||
    }
 | 
			
		||||
    if (mem_wn_lock == 0) {
 | 
			
		||||
        mbed_mpu_enable_rom_wn(false);
 | 
			
		||||
    }
 | 
			
		||||
    mem_wn_lock++;
 | 
			
		||||
    core_util_critical_section_exit();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void mbed_mpu_manager_unlock_rom_write()
 | 
			
		||||
{
 | 
			
		||||
    core_util_critical_section_enter();
 | 
			
		||||
    if (mem_wn_lock == 0) {
 | 
			
		||||
        core_util_critical_section_exit();
 | 
			
		||||
        MBED_ERROR1(MBED_MAKE_ERROR(MBED_MODULE_PLATFORM, MBED_ERROR_CODE_UNDERFLOW), "Rom write never lock underflow (< 0)", mem_wn_lock);
 | 
			
		||||
    }
 | 
			
		||||
    mem_wn_lock--;
 | 
			
		||||
    if (mem_wn_lock == 0) {
 | 
			
		||||
        mbed_mpu_enable_rom_wn(true);
 | 
			
		||||
    }
 | 
			
		||||
    core_util_critical_section_exit();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,90 @@
 | 
			
		|||
/** \addtogroup platform */
 | 
			
		||||
/** @{*/
 | 
			
		||||
/**
 | 
			
		||||
 * \defgroup platform_mpu_mgmt MPU management functions
 | 
			
		||||
 * @{
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* mbed Microcontroller Library
 | 
			
		||||
 * Copyright (c) 2006-2018 ARM Limited
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef MBED_MPU_MGMT_H
 | 
			
		||||
#define MBED_MPU_MGMT_H
 | 
			
		||||
 | 
			
		||||
#include "hal/sleep_api.h"
 | 
			
		||||
#include "mbed_toolchain.h"
 | 
			
		||||
#include "hal/ticker_api.h"
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
extern "C" {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** Lock ram execute never mode off
 | 
			
		||||
 *
 | 
			
		||||
 * This disables the MPU's execute never ram protection and allows
 | 
			
		||||
 * functions to run from RAM. Execution directly from ram will be
 | 
			
		||||
 * allowed if this function is invoked at least once (the internal
 | 
			
		||||
 * counter is non-zero).
 | 
			
		||||
 *
 | 
			
		||||
 * Use this locking mechanism for code which needs to execute from
 | 
			
		||||
 * ram such as flash programming algorithms and ram thunks.
 | 
			
		||||
 *
 | 
			
		||||
 * The lock is a counter, can be locked up to USHRT_MAX
 | 
			
		||||
 * This function is IRQ and thread safe
 | 
			
		||||
 */
 | 
			
		||||
void mbed_mpu_manager_lock_ram_execution(void);
 | 
			
		||||
 | 
			
		||||
/** Unlock ram execute never mode
 | 
			
		||||
 *
 | 
			
		||||
 * Use unlocking in pair with mbed_mpu_manager_lock_ram_execution().
 | 
			
		||||
 *
 | 
			
		||||
 * The lock is a counter, should be equally unlocked as locked
 | 
			
		||||
 * This function is IRQ and thread safe
 | 
			
		||||
 */
 | 
			
		||||
void mbed_mpu_manager_unlock_ram_execution(void);
 | 
			
		||||
 | 
			
		||||
/** Lock rom write never mode off
 | 
			
		||||
 *
 | 
			
		||||
 * This disables the MPU's read only ROM protection and allows
 | 
			
		||||
 * ROM to be written to. Writing to ROM will not result in an MPU
 | 
			
		||||
 * fault if this function is invoked at least once (the internal
 | 
			
		||||
 * counter is non-zero).
 | 
			
		||||
 *
 | 
			
		||||
 * Use this locking mechanism for code which needs to write to
 | 
			
		||||
 * ROM such as flash programming algorithms.
 | 
			
		||||
 *
 | 
			
		||||
 * The lock is a counter, can be locked up to USHRT_MAX
 | 
			
		||||
 * This function is IRQ and thread safe
 | 
			
		||||
 */
 | 
			
		||||
void mbed_mpu_manager_lock_rom_write(void);
 | 
			
		||||
 | 
			
		||||
/** Unlock rom write never mode
 | 
			
		||||
 *
 | 
			
		||||
 * Use unlocking in pair with mbed_mpu_manager_lock_rom_write().
 | 
			
		||||
 *
 | 
			
		||||
 * The lock is a counter, should be equally unlocked as locked
 | 
			
		||||
 * This function is IRQ and thread safe
 | 
			
		||||
 */
 | 
			
		||||
void mbed_mpu_manager_unlock_rom_write(void);
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/** @}*/
 | 
			
		||||
/** @}*/
 | 
			
		||||
| 
						 | 
				
			
			@ -76,6 +76,7 @@
 | 
			
		|||
#include "mbed_toolchain.h"
 | 
			
		||||
#include "mbed_boot.h"
 | 
			
		||||
#include "mbed_error.h"
 | 
			
		||||
#include "mpu_api.h"
 | 
			
		||||
 | 
			
		||||
int main(void);
 | 
			
		||||
static void mbed_cpy_nvic(void);
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +87,9 @@ uint32_t mbed_stack_isr_size = 0;
 | 
			
		|||
 | 
			
		||||
void mbed_init(void)
 | 
			
		||||
{
 | 
			
		||||
    mbed_mpu_init();
 | 
			
		||||
    mbed_mpu_enable_ram_xn(true);
 | 
			
		||||
    mbed_mpu_enable_rom_wn(true);
 | 
			
		||||
    mbed_cpy_nvic();
 | 
			
		||||
    mbed_sdk_init();
 | 
			
		||||
    mbed_rtos_init();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue