#define AO_PANIC_BT 11 /* Communications with bluetooth device failed */
#define AO_PANIC_STACK 12 /* Stack overflow */
#define AO_PANIC_SPI 13 /* SPI communication failure */
+#define AO_PANIC_CRASH 14 /* Processor crashed */
#define AO_PANIC_SELF_TEST_CC1120 0x40 | 1 /* Self test failure */
#define AO_PANIC_SELF_TEST_HMC5883 0x40 | 2 /* Self test failure */
#define AO_PANIC_SELF_TEST_MPU6000 0x40 | 3 /* Self test failure */
#if HAS_SAMPLE_PROFILE
#include <ao_sample_profile.h>
#endif
+#if HAS_STACK_GUARD
+#include <ao_mpu.h>
+#endif
#define AO_NO_TASK_INDEX 0xff
ao_cur_task->start = ao_sample_profile_timer_value();
#endif
}
+#if HAS_STACK_GUARD
+ ao_mpu_stack_guard(ao_cur_task->stack);
+#endif
#if AO_CHECK_STACK
cli();
in_yield = 0;
ao_task.h \
ao_whiten.h \
ao_sample_profile.h \
+ ao_mpu.h \
stm32l.h
#
# Common AltOS sources
#
+# ao_hmc5883.c
#PROFILE=ao_profile.c
#PROFILE_DEF=-DAO_PROFILE=1
ao_sample_profile_timer.c
SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
-# ao_hmc5883.c
+STACK_GUARD=ao_mpu_stm.c
+STACK_GUARD_DEF=-DHAS_STACK_GUARD=1
ALTOS_SRC = \
ao_interrupt.c \
ao_companion.c \
ao_pyro.c \
$(PROFILE) \
- $(SAMPLE_PROFILE)
+ $(SAMPLE_PROFILE) \
+ $(STACK_GUARD)
PRODUCT=MegaMetrum-v0.1
PRODUCT_DEF=-DMEGAMETRUM
IDPRODUCT=0x0023
-CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) -Os -g
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
PROGNAME=megametrum-v0.1
PROG=$(PROGNAME)-$(VERSION).elf
#include <ao_sample_profile.h>
#endif
#include <ao_pyro.h>
+#if HAS_STACK_GUARD
+#include <ao_mpu.h>
+#endif
int
main(void)
{
ao_clock_init();
+#if HAS_STACK_GUARD
+ ao_mpu_init();
+#endif
+
ao_serial_init();
ao_led_init(LEDS_AVAILABLE);
ao_led_on(AO_LED_GREEN);
C_LIB=$(PDCLIB)/lib/pdclib.a
C_INC=-I$(PDCLIB)/include
-DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I../../src/stm $(C_INC)
+DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I. -I../../src/stm $(C_INC)
# to run from SRAM
LD_FLAGS_RAM=-L../stm -Wl,-Taltos-ram.ld
--- /dev/null
+/*
+ * 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.
+ */
+
+#define ao_panic(n) for(;;);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
+#include <ao.h>
#include "stm32l.h"
#include <string.h>
void stm_halt_isr(void)
{
- for(;;);
+ ao_panic(AO_PANIC_CRASH);
}
void stm_ignore_isr(void)
--- /dev/null
+/*
+ * 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_ */
--- /dev/null
+/*
+ * 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));
+}
stm_nvic = 0xe000e100;
+stm_mpu = 0xe000ed90;
+
/* calibration data in system memory */
stm_temp_cal = 0x1ff80078;
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)
#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