summaryrefslogtreecommitdiff
path: root/src/stm
diff options
context:
space:
mode:
Diffstat (limited to 'src/stm')
-rw-r--r--src/stm/ao_interrupt.c3
-rw-r--r--src/stm/ao_mpu.h29
-rw-r--r--src/stm/ao_mpu_stm.c149
-rw-r--r--src/stm/registers.ld2
-rw-r--r--src/stm/stm32l.h64
5 files changed, 246 insertions, 1 deletions
diff --git a/src/stm/ao_interrupt.c b/src/stm/ao_interrupt.c
index 6b4a9700..a423d8b1 100644
--- a/src/stm/ao_interrupt.c
+++ b/src/stm/ao_interrupt.c
@@ -15,6 +15,7 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
+#include <ao.h>
#include "stm32l.h"
#include <string.h>
@@ -28,7 +29,7 @@ extern char __bss_start__, __bss_end__;
void stm_halt_isr(void)
{
- for(;;);
+ ao_panic(AO_PANIC_CRASH);
}
void stm_ignore_isr(void)
diff --git a/src/stm/ao_mpu.h b/src/stm/ao_mpu.h
new file mode 100644
index 00000000..cc6132a5
--- /dev/null
+++ b/src/stm/ao_mpu.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_MPU_H_
+#define _AO_MPU_H_
+
+extern uint32_t ao_mpu_dregion;
+
+void
+ao_mpu_stack_guard(void *stack);
+
+void
+ao_mpu_init(void);
+
+#endif /* _AO_MPU_H_ */
diff --git a/src/stm/ao_mpu_stm.c b/src/stm/ao_mpu_stm.c
new file mode 100644
index 00000000..969d7446
--- /dev/null
+++ b/src/stm/ao_mpu_stm.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_mpu.h>
+
+static uint32_t stm_mpu_dregion;
+
+void
+ao_mpu_init(void)
+{
+ uint32_t region;
+
+ /* Check to see how many regions we have */
+ stm_mpu_dregion = (stm_mpu.typer >> STM_MPU_TYPER_DREGION) & STM_MPU_TYPER_DREGION_MASK;
+
+ /* No MPU at all */
+ if (stm_mpu_dregion == 0)
+ return;
+
+ /* Disable MPU */
+ stm_mpu.cr = ((0 << STM_MPU_CR_PRIVDEFENA) |
+ (0 << STM_MPU_CR_HFNMIENA) |
+ (0 << STM_MPU_CR_ENABLE));
+
+ /* Disable all regions */
+ for (region = 0; region < stm_mpu_dregion; region++) {
+ /* Set the base address and RNR value */
+ stm_mpu.rbar = ((0 & (STM_MPU_RBAR_ADDR_MASK << STM_MPU_RBAR_ADDR)) |
+ (1 << STM_MPU_RBAR_VALID) |
+ (region << STM_MPU_RBAR_REGION));
+
+ /* Disable this region */
+ stm_mpu.rasr = 0;
+ }
+
+ region = 0;
+
+ /* Flash */
+ /* 0x00000000 - 0x1fffffff */
+ stm_mpu.rbar = (0x0000000 |
+ (1 << STM_MPU_RBAR_VALID) |
+ (region << STM_MPU_RBAR_REGION));
+
+ stm_mpu.rasr = ((0 << STM_MPU_RASR_XN) |
+ (STM_MPU_RASR_AP_RO_RO << STM_MPU_RASR_AP) |
+ (5 << STM_MPU_RASR_TEX) |
+ (0 << STM_MPU_RASR_C) |
+ (1 << STM_MPU_RASR_B) |
+ (0 << STM_MPU_RASR_S) |
+ (0 << STM_MPU_RASR_SRD) |
+ (28 << STM_MPU_RASR_SIZE) |
+ (1 << STM_MPU_RASR_ENABLE));
+ region++;
+
+ /* Ram */
+ /* 0x20000000 - 0x3fffffff */
+ stm_mpu.rbar = (0x20000000 |
+ (1 << STM_MPU_RBAR_VALID) |
+ (region << STM_MPU_RBAR_REGION));
+
+ stm_mpu.rasr = ((0 << STM_MPU_RASR_XN) |
+ (STM_MPU_RASR_AP_RW_RW << STM_MPU_RASR_AP) |
+ (5 << STM_MPU_RASR_TEX) |
+ (0 << STM_MPU_RASR_C) |
+ (1 << STM_MPU_RASR_B) |
+ (0 << STM_MPU_RASR_S) |
+ (0 << STM_MPU_RASR_SRD) |
+ (28 << STM_MPU_RASR_SIZE) |
+ (1 << STM_MPU_RASR_ENABLE));
+ region++;
+
+ /* Peripherals */
+
+ /* 0x4000000 - 0x7ffffff */
+ stm_mpu.rbar = (0x40000000 |
+ (1 << STM_MPU_RBAR_VALID) |
+ (region << STM_MPU_RBAR_REGION));
+
+ stm_mpu.rasr = ((1 << STM_MPU_RASR_XN) |
+ (STM_MPU_RASR_AP_RW_RW << STM_MPU_RASR_AP) |
+ (2 << STM_MPU_RASR_TEX) |
+ (0 << STM_MPU_RASR_C) |
+ (0 << STM_MPU_RASR_B) |
+ (0 << STM_MPU_RASR_S) |
+ (0 << STM_MPU_RASR_SRD) |
+ (29 << STM_MPU_RASR_SIZE) |
+ (1 << STM_MPU_RASR_ENABLE));
+ region++;
+
+ /* 0x8000000 - 0xffffffff */
+ stm_mpu.rbar = (0x80000000 |
+ (1 << STM_MPU_RBAR_VALID) |
+ (region << STM_MPU_RBAR_REGION));
+
+ stm_mpu.rasr = ((1 << STM_MPU_RASR_XN) |
+ (STM_MPU_RASR_AP_RW_RW << STM_MPU_RASR_AP) |
+ (2 << STM_MPU_RASR_TEX) |
+ (0 << STM_MPU_RASR_C) |
+ (0 << STM_MPU_RASR_B) |
+ (0 << STM_MPU_RASR_S) |
+ (0 << STM_MPU_RASR_SRD) |
+ (30 << STM_MPU_RASR_SIZE) |
+ (1 << STM_MPU_RASR_ENABLE));
+ region++;
+
+ /* Enable MPU */
+ stm_mpu.cr = ((0 << STM_MPU_CR_PRIVDEFENA) |
+ (0 << STM_MPU_CR_HFNMIENA) |
+ (1 << STM_MPU_CR_ENABLE));
+}
+
+/*
+ * Protect the base of the stack from CPU access
+ */
+
+void
+ao_mpu_stack_guard(void *base)
+{
+ uintptr_t addr = (uintptr_t) base;
+
+ /* Round up to cover the lowest possible 32-byte region */
+ addr = (addr + ~(STM_MPU_RBAR_ADDR_MASK << STM_MPU_RBAR_ADDR)) & (STM_MPU_RBAR_ADDR_MASK << STM_MPU_RBAR_ADDR);
+
+ stm_mpu.rbar = addr | (1 << STM_MPU_RBAR_VALID) | (7 << STM_MPU_RBAR_REGION);
+ stm_mpu.rasr = ((1 << STM_MPU_RASR_XN) |
+ (STM_MPU_RASR_AP_NONE_NONE << STM_MPU_RASR_AP) |
+ (5 << STM_MPU_RASR_TEX) |
+ (0 << STM_MPU_RASR_C) |
+ (1 << STM_MPU_RASR_B) |
+ (0 << STM_MPU_RASR_S) |
+ (0 << STM_MPU_RASR_SRD) |
+ (4 << STM_MPU_RASR_SIZE) |
+ (1 << STM_MPU_RASR_ENABLE));
+}
diff --git a/src/stm/registers.ld b/src/stm/registers.ld
index fd61e486..f8b224a2 100644
--- a/src/stm/registers.ld
+++ b/src/stm/registers.ld
@@ -46,5 +46,7 @@ stm_tim2 = 0x40000000;
stm_nvic = 0xe000e100;
+stm_mpu = 0xe000ed90;
+
/* calibration data in system memory */
stm_temp_cal = 0x1ff80078;
diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h
index e950d09b..d953aee4 100644
--- a/src/stm/stm32l.h
+++ b/src/stm/stm32l.h
@@ -901,6 +901,63 @@ stm_nvic_get_priority(int irq) {
return (stm_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0);
}
+struct stm_mpu {
+ vuint32_t typer;
+ vuint32_t cr;
+ vuint32_t rnr;
+ vuint32_t rbar;
+
+ vuint32_t rasr;
+ vuint32_t rbar_a1;
+ vuint32_t rasr_a1;
+ vuint32_t rbar_a2;
+ vuint32_t rasr_a2;
+ vuint32_t rbar_a3;
+ vuint32_t rasr_a3;
+};
+
+extern struct stm_mpu stm_mpu;
+
+#define STM_MPU_TYPER_IREGION 16
+#define STM_MPU_TYPER_IREGION_MASK 0xff
+#define STM_MPU_TYPER_DREGION 8
+#define STM_MPU_TYPER_DREGION_MASK 0xff
+#define STM_MPU_TYPER_SEPARATE 0
+
+#define STM_MPU_CR_PRIVDEFENA 2
+#define STM_MPU_CR_HFNMIENA 1
+#define STM_MPU_CR_ENABLE 0
+
+#define STM_MPU_RNR_REGION 0
+#define STM_MPU_RNR_REGION_MASK 0xff
+
+#define STM_MPU_RBAR_ADDR 5
+#define STM_MPU_RBAR_ADDR_MASK 0x7ffffff
+
+#define STM_MPU_RBAR_VALID 4
+#define STM_MPU_RBAR_REGION 0
+#define STM_MPU_RBAR_REGION_MASK 0xf
+
+#define STM_MPU_RASR_XN 28
+#define STM_MPU_RASR_AP 24
+#define STM_MPU_RASR_AP_NONE_NONE 0
+#define STM_MPU_RASR_AP_RW_NONE 1
+#define STM_MPU_RASR_AP_RW_RO 2
+#define STM_MPU_RASR_AP_RW_RW 3
+#define STM_MPU_RASR_AP_RO_NONE 5
+#define STM_MPU_RASR_AP_RO_RO 6
+#define STM_MPU_RASR_AP_MASK 7
+#define STM_MPU_RASR_TEX 19
+#define STM_MPU_RASR_TEX_MASK 7
+#define STM_MPU_RASR_S 18
+#define STM_MPU_RASR_C 17
+#define STM_MPU_RASR_B 16
+#define STM_MPU_RASR_SRD 8
+#define STM_MPU_RASR_SRD_MASK 0xff
+#define STM_MPU_RASR_SIZE 1
+#define STM_MPU_RASR_SIZE_MASK 0x1f
+#define STM_MPU_RASR_ENABLE 0
+
#define isr(name) void stm_ ## name ## _isr(void);
isr(nmi)
@@ -1568,6 +1625,13 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4;
#define STM_TIM234_SR_CC1IF 1
#define STM_TIM234_SR_UIF 0
+#define STM_TIM234_EGR_TG 6
+#define STM_TIM234_EGR_CC4G 4
+#define STM_TIM234_EGR_CC3G 3
+#define STM_TIM234_EGR_CC2G 2
+#define STM_TIM234_EGR_CC1G 1
+#define STM_TIM234_EGR_UG 0
+
#define STM_TIM234_CCMR1_OC2CE 15
#define STM_TIM234_CCMR1_OC2M 12
#define STM_TIM234_CCMR1_OC2M_FROZEN 0