summaryrefslogtreecommitdiff
path: root/firmware/os
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2017-05-03 15:13:45 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2017-05-03 15:13:46 +0000
commitb0a8cc4ed7a173314898fb75a286f3179b1a69e1 (patch)
tree948f07e5a12136390492873062470470155fdfe1 /firmware/os
parent57b9756da4a5953a3c0eaa9d41d9e0ebdd9b8084 (diff)
parent1870f0680a5388a729bb2e5c954c47abee468814 (diff)
downloadcontexthub-b0a8cc4ed7a173314898fb75a286f3179b1a69e1.tar.gz
Merge "mpu: actually enable the mpu (for real this time)"android-wear-o-preview-4android-wear-o-preview-3android-o-preview-2
Diffstat (limited to 'firmware/os')
-rw-r--r--firmware/os/cpu/cortexm4/cpu.c35
-rw-r--r--firmware/os/cpu/cortexm4/inc/cpu/cmsis.h3
-rw-r--r--firmware/os/inc/mpu.h1
-rw-r--r--firmware/os/platform/stm32/inc/plat/cmsis.h1
-rw-r--r--firmware/os/platform/stm32/mpu.c166
5 files changed, 152 insertions, 54 deletions
diff --git a/firmware/os/cpu/cortexm4/cpu.c b/firmware/os/cpu/cortexm4/cpu.c
index 51058106..927db359 100644
--- a/firmware/os/cpu/cortexm4/cpu.c
+++ b/firmware/os/cpu/cortexm4/cpu.c
@@ -32,14 +32,23 @@
#define HARD_FAULT_DROPBOX_MAGIC_HAVE_DROP 0x00002000
#define HARD_FAULT_DROPBOX_MAGIC_DATA_MASK 0x00001FFF
+union TidTrig {
+ struct {
+ uint32_t tid : 16;
+ uint32_t trig : 2;
+ uint32_t RFU : 14;
+ };
+ uint32_t rw;
+};
+
+// These registers only support word accesses (r/w)
+// Make sure to only use uint32_t's
struct RamPersistedDataAndDropbox {
uint32_t magic; // and part of dropbox
uint32_t r[16];
uint32_t sr_hfsr_cfsr_lo;
uint32_t bits;
- uint16_t tid;
- uint16_t trig:2;
- uint16_t RFU:14;
+ union TidTrig tid_trig; // only access via tid_trig.rw
};
/* //if your device persists ram, you can use this instead:
@@ -106,9 +115,10 @@ static void cpuUnpackSrBits(uint32_t srcLo, uint32_t srcHi, uint32_t *srP, uint3
static void cpuDbxDump(struct RamPersistedDataAndDropbox *dbx)
{
- uint32_t i, hfsr, cfsr, sr, code;
+ uint32_t i, hfsr, cfsr, sr;
+ union TidTrig tid_trig;
const char *trigName;
- static const char *trigNames[] = { "UNKNOWN", "HARD FAULT", "WDT" };
+ static const char *trigNames[] = { "UNKNOWN", "HARD FAULT", "WDT", "MPU" };
if (dbx) {
for (i = 0; i < 8; i++)
@@ -120,12 +130,13 @@ static void cpuDbxDump(struct RamPersistedDataAndDropbox *dbx)
osLog(LOG_ERROR, " xPSR = 0x%08lX HFSR = 0x%08lX\n", sr, hfsr);
osLog(LOG_ERROR, " CFSR = 0x%08lX BITS = 0x%08lX\n", cfsr, dbx->bits);
// reboot source (if known), reported as TRIG
- // so far we have 2 reboot sources reported here:
+ // so far we have 3 reboot sources reported here:
// 1 - HARD FAULT
// 2 - WDT
- code = dbx->trig;
- trigName = trigNames[code < ARRAY_SIZE(trigNames) ? code : 0];
- osLog(LOG_ERROR, " TID = 0x%04" PRIX16 " TRIG = 0x%04" PRIX16 " [%s]\n", dbx->tid, dbx->trig, trigName);
+ // 3 - MPU
+ tid_trig.rw = dbx->tid_trig.rw;
+ trigName = trigNames[tid_trig.trig < ARRAY_SIZE(trigNames) ? tid_trig.trig : 0];
+ osLog(LOG_ERROR, " TID = 0x%04" PRIX16 " TRIG = 0x%04" PRIX16 " [%s]\n\n", tid_trig.tid, tid_trig.trig, trigName);
}
}
@@ -259,6 +270,7 @@ static void __attribute__((used)) logHardFault(uintptr_t *excRegs, uintptr_t* ot
{
struct RamPersistedDataAndDropbox *dbx = getInitedPersistedData();
uint32_t i, hi;
+ union TidTrig tid_trig;
wdtPing();
@@ -273,8 +285,9 @@ static void __attribute__((used)) logHardFault(uintptr_t *excRegs, uintptr_t* ot
cpuPackSrBits(&dbx->sr_hfsr_cfsr_lo, &hi, excRegs[7], SCB->HFSR, SCB->CFSR);
dbx->magic |= HARD_FAULT_DROPBOX_MAGIC_HAVE_DROP | (hi & HARD_FAULT_DROPBOX_MAGIC_DATA_MASK);
- dbx->tid = osGetCurrentTid();
- dbx->trig = code;
+ tid_trig.tid = osGetCurrentTid();
+ tid_trig.trig = code;
+ dbx->tid_trig.rw = tid_trig.rw;
if (!tinyStack) {
osLog(LOG_ERROR, "*HARD FAULT*\n");
diff --git a/firmware/os/cpu/cortexm4/inc/cpu/cmsis.h b/firmware/os/cpu/cortexm4/inc/cpu/cmsis.h
index d740542d..8cb6d370 100644
--- a/firmware/os/cpu/cortexm4/inc/cpu/cmsis.h
+++ b/firmware/os/cpu/cortexm4/inc/cpu/cmsis.h
@@ -22,9 +22,6 @@
extern "C" {
#endif
-#define __NVIC_PRIO_BITS 4
-#define __FPU_PRESENT 1
-
#include <cpu/cmsis/core_cm4.h>
#ifdef __cplusplus
diff --git a/firmware/os/inc/mpu.h b/firmware/os/inc/mpu.h
index 45bf7a9a..a331bdc1 100644
--- a/firmware/os/inc/mpu.h
+++ b/firmware/os/inc/mpu.h
@@ -32,6 +32,7 @@ extern "C" {
void mpuStart(void);
void mpuAllowRamExecution(bool allowSvcExecute); /* for Supervisor only, if possible */
void mpuAllowRomWrite(bool allowSvcWrite); /* for Supervisor only, if possible */
+void mpuShow(void);
#ifdef __cplusplus
diff --git a/firmware/os/platform/stm32/inc/plat/cmsis.h b/firmware/os/platform/stm32/inc/plat/cmsis.h
index 8b79368d..53c7f2ba 100644
--- a/firmware/os/platform/stm32/inc/plat/cmsis.h
+++ b/firmware/os/platform/stm32/inc/plat/cmsis.h
@@ -24,6 +24,7 @@ extern "C" {
#define __NVIC_PRIO_BITS 4
#define __FPU_PRESENT 1
+#define __MPU_PRESENT 1
diff --git a/firmware/os/platform/stm32/mpu.c b/firmware/os/platform/stm32/mpu.c
index f45a1531..1a2f0a3a 100644
--- a/firmware/os/platform/stm32/mpu.c
+++ b/firmware/os/platform/stm32/mpu.c
@@ -22,64 +22,75 @@
#include <mpu.h>
#include <platform.h>
-struct CortexMpu {
- volatile uint32_t CTRL;
- volatile uint32_t RNR;
- volatile uint32_t RBAR;
- volatile uint32_t RASR;
-};
+#include <plat/cmsis.h>
-#define MPU ((struct CortexMpu*)0xE000ED94UL)
-
-#define MPU_REG_ROM 0
-#define MPU_REG_RAM 1
-#define MPU_REG_NULL_PAGE 2
+#define MPU_REG_DEFAULT 0
+#define MPU_REG_ROM 1
+#define MPU_REG_RAM 2
+#define MPU_REG_PERIPH 3
+#define MPU_REG_PRIV_PERIPH 4
+#define MPU_RASR_S 0x00040000
+#define MPU_RASR_C 0x00020000
+#define MPU_RASR_B 0x00010000
/* region type */
-#define MPU_TYPE_DEVICE (0x10UL << 16)
-#define MPU_TYPE_MEMORY (0x0FUL << 16)
+#define MPU_TYPE_SRAM (MPU_RASR_S | MPU_RASR_C)
+#define MPU_TYPE_FLASH (MPU_RASR_C)
+#define MPU_TYPE_PERIPH (MPU_RASR_S | MPU_RASR_B)
/* region execute priviledges */
-#define MPU_BIT_XN (1UL << 28) /* no execute */
+#define MPU_BIT_XN (1UL << 28) /* no execute */
/* region access priviledges */
-#define MPU_NA (0UL << 24) /* S: no access U: no access */
-#define MPU_U_NA_S_RW (1UL << 24) /* S: RW U: no access */
-#define MPU_U_RO_S_RW (2UL << 24) /* S: RW U: RO */
-#define MPU_RW (3UL << 24) /* S: RW U: RW */
-#define MPU_U_NA_S_RO (5UL << 24) /* S: RO U: no access */
-#define MPU_U_RO_S_RO (6UL << 24) /* S: RO U: RO */
+#define MPU_NA (0UL << 24) /* S: no access U: no access */
+#define MPU_U_NA_S_RW (1UL << 24) /* S: RW U: no access */
+#define MPU_U_RO_S_RW (2UL << 24) /* S: RW U: RO */
+#define MPU_RW (3UL << 24) /* S: RW U: RW */
+#define MPU_U_NA_S_RO (5UL << 24) /* S: RO U: no access */
+#define MPU_U_RO_S_RO (6UL << 24) /* S: RO U: RO */
-/* subregion mask (not used so all ones) */
-#define MPU_SRD_BITS 0xFF00UL
-#define MPU_BIT_ENABLE 1UL
+/* subregion disable (not used so all zeroes) */
+#define MPU_SRD_BITS 0x0000UL
+#define MPU_BIT_ENABLE 1UL
/* these define rom */
extern uint8_t __shared_end[];
extern uint8_t __ram_start[];
extern uint8_t __ram_end[];
-static void mpuRegionCfg(uint32_t regionNo, uint32_t start, uint32_t len, uint32_t attrs) /* region will be rounded to acceptable boundaries (32B minimum, self-aligned) by GROWTH */
+void MemoryManagemntFault_Handler(void);
+void __attribute__((naked)) MemoryManagemntFault_Handler(void)
{
- uint32_t proposedStart, proposedLen, lenVal = 1;
- uint64_t intState;
+ asm volatile(
+ "mov r0, #3 \n"
+ "b cpuCommonFaultCode \n"
+ );
+}
+
+static bool mpuRegionCfg(uint32_t regionNo, uint32_t start, uint32_t end, uint32_t attrs) /* region will be rounded to acceptable boundaries (32B minimum, self-aligned) by GROWTH */
+{
+ uint32_t proposedStart, lenVal = 1;
+ uint64_t len, proposedLen, intState;
+
+ if (start > end)
+ return false;
+ else
+ len = end - start + UINT64_C(1);
/* expand until it works */
do {
- /* special case 4GB region */
- if (lenVal == 32) {
- proposedStart = 0;
- break;
- }
-
- proposedStart = start &~ ((1ULL << lenVal) - 1);
+ proposedStart = start &~ ((UINT64_C(1) << lenVal) - 1);
proposedLen = start + len - proposedStart;
if (proposedLen < 32)
proposedLen = 32;
- lenVal = (proposedLen & (proposedLen - 1)) ? 32 - __builtin_clz(proposedLen) : 31 - __builtin_clz(proposedLen);
+ lenVal = (proposedLen & (proposedLen - UINT64_C(1))) ? 64 - __builtin_clzll(proposedLen) : 63 - __builtin_clzll(proposedLen);
- } while (proposedStart & ((1ULL << lenVal) - 1));
+ } while (proposedStart & ((UINT64_C(1) << lenVal) - UINT64_C(1)));
+
+ /* minimum size: 32 bytes */
+ if (lenVal < 5)
+ lenVal = 5;
intState = cpuIntsOff();
asm volatile("dsb\nisb");
@@ -87,30 +98,44 @@ static void mpuRegionCfg(uint32_t regionNo, uint32_t start, uint32_t len, uint32
MPU->RNR = regionNo;
MPU->RASR = 0; /* disable region before changing it */
MPU->RBAR = proposedStart;
- MPU->RASR = MPU_SRD_BITS | MPU_BIT_ENABLE | attrs | (lenVal << 1);
+ MPU->RASR = MPU_SRD_BITS | MPU_BIT_ENABLE | attrs | ((lenVal-1) << 1);
asm volatile("dsb\nisb");
cpuIntsRestore(intState);
+
+ return true;
}
static void mpuCfgRom(bool allowSvcWrite)
{
- mpuRegionCfg(MPU_REG_ROM, (uint32_t)&BL, __shared_end - (uint8_t*)&BL, MPU_TYPE_MEMORY | (allowSvcWrite ? MPU_U_RO_S_RW : MPU_U_RO_S_RO));
+ mpuRegionCfg(MPU_REG_ROM, (uint32_t)&BL, (uint32_t)&__shared_end - 1, MPU_TYPE_FLASH | (allowSvcWrite ? MPU_U_RO_S_RW : MPU_U_RO_S_RO));
}
static void mpuCfgRam(bool allowSvcExecute)
{
- mpuRegionCfg(MPU_REG_RAM, (uint32_t)&__ram_start, __ram_end - __ram_start, MPU_TYPE_MEMORY | MPU_RW | (allowSvcExecute ? 0 : MPU_BIT_XN));
+ mpuRegionCfg(MPU_REG_RAM, (uint32_t)&__ram_start, (uint32_t)&__ram_end - 1, MPU_TYPE_SRAM | MPU_RW | (allowSvcExecute ? 0 : MPU_BIT_XN));
}
void mpuStart(void)
{
- MPU->CTRL = 0x07; //MPU on, even during faults, supervisor default: allow, user default: default deny
+ MPU->CTRL = 0x00; // disable MPU
+
+ /* 0x00000000 - 0xFFFFFFFF */
+ mpuRegionCfg(MPU_REG_DEFAULT, 0, 0xFFFFFFFF, MPU_NA | MPU_BIT_XN);
mpuCfgRom(false);
mpuCfgRam(false);
- mpuRegionCfg(MPU_REG_NULL_PAGE, 0, 4096, MPU_TYPE_MEMORY | MPU_NA | MPU_BIT_XN);
+
+ /* 0x40000000 - 0x4003FFFF */
+ mpuRegionCfg(MPU_REG_PERIPH, 0x40000000, 0x4003FFFF, MPU_TYPE_PERIPH | MPU_U_NA_S_RW | MPU_BIT_XN);
+
+ /* 0xE0000000 - 0xE00FFFFF */
+ mpuRegionCfg(MPU_REG_PRIV_PERIPH, 0xE0000000, 0xE00FFFFF, MPU_TYPE_PERIPH | MPU_U_NA_S_RW | MPU_BIT_XN);
+
+ //MPU on, even during faults, supervisor default: allow, user default: default deny
+ MPU->CTRL = MPU_CTRL_ENABLE_Msk | MPU_CTRL_HFNMIENA_Msk | MPU_CTRL_PRIVDEFENA_Msk;
+ SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
}
void mpuAllowRamExecution(bool allowSvcExecute)
@@ -123,3 +148,64 @@ void mpuAllowRomWrite(bool allowSvcWrite)
mpuCfgRom(allowSvcWrite);
}
+void mpuShow()
+{
+ int i, regions = (MPU->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
+ uint32_t addr, rasr;
+ uint8_t ap;
+ bool xn;
+ char *s, *u;
+
+ osLog(LOG_INFO, "MPU: %d HFNMIENA: %d PRIVDEFENA: %d\n",
+ !!(MPU->CTRL & MPU_CTRL_ENABLE_Msk),
+ !!(MPU->CTRL & MPU_CTRL_HFNMIENA_Msk),
+ !!(MPU->CTRL & MPU_CTRL_PRIVDEFENA_Msk));
+ for (i=0; i<regions; i++) {
+ MPU->RNR = i;
+ addr = MPU->RBAR & MPU_RBAR_ADDR_Msk;
+ rasr = MPU->RASR;
+ xn = rasr & MPU_RASR_XN_Msk;
+ ap = (rasr & MPU_RASR_AP_Msk) >> MPU_RASR_AP_Pos;
+ if (ap == 0) {
+ s = "---";
+ } else if (ap == 1 || ap == 2 || ap == 3) {
+ if (xn)
+ s = "RW-";
+ else
+ s = "RWX";
+ } else if (ap == 5 || ap == 6 || ap == 7) {
+ if (xn)
+ s = "R--";
+ else
+ s = "R-X";
+ } else {
+ s = "???";
+ }
+ if (ap == 0 || ap == 1 || ap == 5) {
+ u = "---";
+ } else if (ap == 3) {
+ if (xn)
+ u = "RW-";
+ else
+ u = "RWX";
+ } else if (ap == 2 || ap == 6 || ap == 7) {
+ if (xn)
+ u = "R--";
+ else
+ u = "R-X";
+ } else {
+ u = "???";
+ }
+ osLog(LOG_INFO,
+ "%d: %c %08lx-%08lx S: %s U: %s TEX: %ld %c%c%c %02lx\n",
+ i, (rasr & MPU_RASR_ENABLE_Msk) ? 'E' : 'D',
+ addr,
+ addr + (1 << (((rasr & MPU_RASR_SIZE_Msk) >> MPU_RASR_SIZE_Pos) + 1))-1,
+ s, u,
+ (rasr & MPU_RASR_TEX_Msk) >> MPU_RASR_TEX_Pos,
+ (rasr & MPU_RASR_S_Msk) ? 'S' : ' ',
+ (rasr & MPU_RASR_C_Msk) ? 'C' : ' ',
+ (rasr & MPU_RASR_B_Msk) ? 'B' : ' ',
+ (rasr & MPU_RASR_SRD_Msk) >> MPU_RASR_SRD_Pos);
+ }
+}