
2 changed files with 235 additions and 0 deletions
@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Loci Controls Inc. |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
*/ |
||||
|
||||
/**
|
||||
* @ingroup cpu_cortexm_common |
||||
* @{ |
||||
* |
||||
* @file mpu.h |
||||
* @brief Cortex-M Memory Protection Unit (MPU) Driver Header File |
||||
* |
||||
* @author Ian Martin <ian@locicontrols.com> |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
#ifndef MPU_H_ |
||||
#define MPU_H_ |
||||
|
||||
#include <stdbool.h> |
||||
#include <stdint.h> |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Number of MPU regions available (will vary depending on the Cortex-M version) |
||||
*/ |
||||
#define MPU_NUM_REGIONS ( (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos ) |
||||
|
||||
/**
|
||||
* @brief Access Permission words |
||||
*/ |
||||
enum { |
||||
AP_NO_NO = 0, /**< no access for all levels */ |
||||
AP_RW_NO = 1, /**< read/write for privileged level, no access from user level */ |
||||
AP_RW_RO = 2, /**< read/write for privileged level, read-only for user level */ |
||||
AP_RW_RW = 3, /**< read/write for all levels */ |
||||
AP_RO_NO = 5, /**< read-only for privileged level, no access from user level */ |
||||
AP_RO_RO = 6, /**< read-only for all levels */ |
||||
}; |
||||
|
||||
/**
|
||||
* @brief MPU region sizes |
||||
*/ |
||||
enum { |
||||
MPU_SIZE_32B = 4, /**< 32 bytes */ |
||||
MPU_SIZE_64B = 5, /**< 64 bytes */ |
||||
MPU_SIZE_128B = 6, /**< 128 bytes */ |
||||
MPU_SIZE_256B = 7, /**< 256 bytes */ |
||||
MPU_SIZE_512B = 8, /**< 512 bytes */ |
||||
MPU_SIZE_1K = 9, /**< 1 kilobytes */ |
||||
MPU_SIZE_2K = 10, /**< 2 kilobytes */ |
||||
MPU_SIZE_4K = 11, /**< 4 kilobytes */ |
||||
MPU_SIZE_8K = 12, /**< 8 kilobytes */ |
||||
MPU_SIZE_16K = 13, /**< 16 kilobytes */ |
||||
MPU_SIZE_32K = 14, /**< 32 kilobytes */ |
||||
MPU_SIZE_64K = 15, /**< 64 kilobytes */ |
||||
MPU_SIZE_128K = 16, /**< 128 kilobytes */ |
||||
MPU_SIZE_256K = 17, /**< 256 kilobytes */ |
||||
MPU_SIZE_512K = 18, /**< 512 kilobytes */ |
||||
MPU_SIZE_1M = 19, /**< 1 megabytes */ |
||||
MPU_SIZE_2M = 20, /**< 2 megabytes */ |
||||
MPU_SIZE_4M = 21, /**< 4 megabytes */ |
||||
MPU_SIZE_8M = 22, /**< 8 megabytes */ |
||||
MPU_SIZE_16M = 23, /**< 16 megabytes */ |
||||
MPU_SIZE_32M = 24, /**< 32 megabytes */ |
||||
MPU_SIZE_64M = 25, /**< 64 megabytes */ |
||||
MPU_SIZE_128M = 26, /**< 128 megabytes */ |
||||
MPU_SIZE_256M = 27, /**< 256 megabytes */ |
||||
MPU_SIZE_512M = 28, /**< 512 megabytes */ |
||||
MPU_SIZE_1G = 29, /**< 1 gigabytes */ |
||||
MPU_SIZE_2G = 30, /**< 2 gigabytes */ |
||||
MPU_SIZE_4G = 31, /**< 4 gigabytes */ |
||||
}; |
||||
|
||||
/**
|
||||
* @brief convert a region size code to a size in bytes |
||||
* |
||||
* @param[in] size region size code, e.g. MPU_SIZE_32B |
||||
* |
||||
* @return region size in bytes |
||||
*/ |
||||
#define MPU_SIZE_TO_BYTES(size) ( (uintptr_t)1 << ((size) + 1) ) |
||||
|
||||
/**
|
||||
* @brief generate an MPU attribute word suitable for writing to the RASR register |
||||
* |
||||
* @param[in] xn eXecute Never flag (forbids instruction fetches) |
||||
* @param[in] ap Access Permission word, e.g. AP_RO_RO |
||||
* @param[in] tex Type Extension Field |
||||
* @param[in] c Cacheable bit |
||||
* @param[in] b Bufferable bit |
||||
* @param[in] s Sub-Region Disable (SRD) field |
||||
* @param[in] size region size code, e.g. MPU_SIZE_32B |
||||
* |
||||
* @return combined region attribute word |
||||
*/ |
||||
static inline uint32_t MPU_ATTR( |
||||
uint32_t xn, |
||||
uint32_t ap, |
||||
uint32_t tex, |
||||
uint32_t c, |
||||
uint32_t b, |
||||
uint32_t s, |
||||
uint32_t size) |
||||
{ |
||||
return |
||||
(xn << 28) | |
||||
(ap << 24) | |
||||
(tex << 19) | |
||||
(s << 18) | |
||||
(c << 17) | |
||||
(b << 16) | |
||||
(size << 1); |
||||
} |
||||
|
||||
/**
|
||||
* @brief disable the MPU |
||||
* |
||||
* @return 0 on success |
||||
* @return <0 on failure or no MPU present |
||||
*/ |
||||
int mpu_disable(void); |
||||
|
||||
/**
|
||||
* @brief enable the MPU |
||||
* |
||||
* @return 0 on success |
||||
* @return <0 on failure or no MPU present |
||||
*/ |
||||
int mpu_enable(void); |
||||
|
||||
/**
|
||||
* @brief test if the MPU is enabled |
||||
* |
||||
* @return true if enabled |
||||
* @return false if disabled |
||||
*/ |
||||
bool mpu_enabled(void); |
||||
|
||||
/**
|
||||
* @brief configure the base address and attributes for an MPU region |
||||
* |
||||
* @param[in] region MPU region to configure (0 <= @p region < MPU_NUM_REGIONS) |
||||
* @param[in] base base address in RAM (aligned to the size specified within @p attr) |
||||
* @param[in] attr attribute word generated by MPU_ATTR() |
||||
* |
||||
* @return 0 on success |
||||
* @return <0 on failure or no MPU present |
||||
*/ |
||||
int mpu_configure(uint_fast8_t region, uintptr_t base, uint_fast32_t attr); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* MPU_H_ */ |
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Loci Controls Inc. |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
*/ |
||||
|
||||
/**
|
||||
* @ingroup cpu_cortexm_common |
||||
* @{ |
||||
* |
||||
* @file mpu.c |
||||
* @brief Cortex-M Memory Protection Unit (MPU) Driver |
||||
* |
||||
* @author Ian Martin <ian@locicontrols.com> |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
#include <assert.h> |
||||
|
||||
#include "cpu.h" |
||||
#include "mpu.h" |
||||
|
||||
int mpu_disable(void) { |
||||
#if __MPU_PRESENT |
||||
MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk; |
||||
return 0; |
||||
#else |
||||
return -1; |
||||
#endif |
||||
} |
||||
|
||||
int mpu_enable(void) { |
||||
#if __MPU_PRESENT |
||||
MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk; |
||||
|
||||
/* Enable the memory fault exception */ |
||||
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; |
||||
|
||||
return 0; |
||||
#else |
||||
return -1; |
||||
#endif |
||||
} |
||||
|
||||
bool mpu_enabled(void) { |
||||
#if __MPU_PRESENT |
||||
return (MPU->CTRL & MPU_CTRL_ENABLE_Msk) != 0; |
||||
#else |
||||
return false; |
||||
#endif |
||||
} |
||||
|
||||
int mpu_configure(uint_fast8_t region, uintptr_t base, uint_fast32_t attr) { |
||||
#if __MPU_PRESENT |
||||
assert(region < MPU_NUM_REGIONS); |
||||
|
||||
MPU->RNR = region; |
||||
MPU->RBAR = base & MPU_RBAR_ADDR_Msk; |
||||
MPU->RASR = attr | MPU_RASR_ENABLE_Msk; |
||||
|
||||
if (!mpu_enabled()) { |
||||
mpu_enable(); |
||||
} |
||||
|
||||
return 0; |
||||
#else |
||||
return -1; |
||||
#endif |
||||
} |
Loading…
Reference in new issue