diff options
-rw-r--r-- | src/core/ao.h | 1 | ||||
-rw-r--r-- | src/core/ao_task.c | 6 | ||||
-rw-r--r-- | src/megametrum-v0.1/Makefile | 10 | ||||
-rw-r--r-- | src/megametrum-v0.1/ao_megametrum.c | 7 | ||||
-rw-r--r-- | src/stm-bringup/Makefile | 2 | ||||
-rw-r--r-- | src/stm-bringup/ao.h | 18 | ||||
-rw-r--r-- | src/stm/ao_interrupt.c | 3 | ||||
-rw-r--r-- | src/stm/ao_mpu.h | 29 | ||||
-rw-r--r-- | src/stm/ao_mpu_stm.c | 149 | ||||
-rw-r--r-- | src/stm/registers.ld | 2 | ||||
-rw-r--r-- | src/stm/stm32l.h | 64 |
11 files changed, 286 insertions, 5 deletions
diff --git a/src/core/ao.h b/src/core/ao.h index 2b375cfd..87e69e19 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -64,6 +64,7 @@ #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 */ diff --git a/src/core/ao_task.c b/src/core/ao_task.c index c2b1b270..df70b906 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -20,6 +20,9 @@ #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 @@ -127,6 +130,9 @@ ao_yield(void) ao_arch_naked_define 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; diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index b100fafc..487a643f 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -25,11 +25,13 @@ INC = \ 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 @@ -38,7 +40,8 @@ SAMPLE_PROFILE=ao_sample_profile.c \ 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 \ @@ -87,13 +90,14 @@ ALTOS_SRC = \ 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 diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 114f144f..43c2292d 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -28,12 +28,19 @@ #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); diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile index d45e836d..5cc94bd9 100644 --- a/src/stm-bringup/Makefile +++ b/src/stm-bringup/Makefile @@ -12,7 +12,7 @@ PDCLIB=/home/keithp/sat 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 diff --git a/src/stm-bringup/ao.h b/src/stm-bringup/ao.h new file mode 100644 index 00000000..27204fae --- /dev/null +++ b/src/stm-bringup/ao.h @@ -0,0 +1,18 @@ +/* + * 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(;;); 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 |