summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/armv7-m
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/arch/arm/src/armv7-m')
-rw-r--r--nuttx/arch/arm/src/armv7-m/Kconfig6
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_initialstate.c10
-rw-r--r--nuttx/arch/arm/src/armv7-m/up_stackcheck.c40
3 files changed, 56 insertions, 0 deletions
diff --git a/nuttx/arch/arm/src/armv7-m/Kconfig b/nuttx/arch/arm/src/armv7-m/Kconfig
index a154a4c5c..9c55068d5 100644
--- a/nuttx/arch/arm/src/armv7-m/Kconfig
+++ b/nuttx/arch/arm/src/armv7-m/Kconfig
@@ -57,3 +57,9 @@ config ARMV7M_OABI_TOOLCHAIN
---help---
Most of the older buildroot toolchains are OABI and are named arm-nuttx-elf- vs. arm-nuttx-eabi-
+config ARMV7M_STACKCHECK
+ bool "Steck for stack overflow on function calls"
+ default n
+ ---help---
+ This check uses R10 to check for a stack overflow within function calls. This has a performance impact,
+ but will be able to catch hard to find stack overflows.
diff --git a/nuttx/arch/arm/src/armv7-m/up_initialstate.c b/nuttx/arch/arm/src/armv7-m/up_initialstate.c
index c19d32f11..04089f8ac 100644
--- a/nuttx/arch/arm/src/armv7-m/up_initialstate.c
+++ b/nuttx/arch/arm/src/armv7-m/up_initialstate.c
@@ -93,6 +93,16 @@ void up_initial_state(struct tcb_s *tcb)
xcp->regs[REG_SP] = (uint32_t)tcb->adj_stack_ptr;
+#ifdef CONFIG_ARMV7M_STACKCHECK
+ /* Set the stack limit value */
+
+ xcp->regs[REG_R10] = (uint32_t)tcb->stack_alloc_ptr + 64;
+
+ /* Fill the stack with a watermark value */
+
+ memset(tcb->stack_alloc_ptr, 0xff, tcb->adj_stack_size);
+#endif
+
/* Save the task entry point (stripping off the thumb bit) */
xcp->regs[REG_PC] = (uint32_t)tcb->start & ~1;
diff --git a/nuttx/arch/arm/src/armv7-m/up_stackcheck.c b/nuttx/arch/arm/src/armv7-m/up_stackcheck.c
new file mode 100644
index 000000000..e8f02a863
--- /dev/null
+++ b/nuttx/arch/arm/src/armv7-m/up_stackcheck.c
@@ -0,0 +1,40 @@
+
+
+void __cyg_profile_func_enter(void *func, void *caller) __attribute__((naked, no_instrument_function));
+void __cyg_profile_func_exit(void *func, void *caller) __attribute__((naked, no_instrument_function));
+void __stack_overflow_trap(void) __attribute__((naked, no_instrument_function));
+
+void
+__stack_overflow_trap(void)
+{
+ /* if we get here, the stack has overflowed */
+ asm ( "b .");
+}
+
+void
+__cyg_profile_func_enter(void *func, void *caller)
+{
+ asm volatile (
+ " mrs r2, ipsr \n" /* Check whether we are in interrupt mode */
+ " cmp r2, #0 \n" /* since we don't switch r10 on interrupt entry, we */
+ " bne 2f \n" /* can't detect overflow of the interrupt stack. */
+ " \n"
+ " sub r2, sp, #68 \n" /* compute stack pointer as though we just stacked a full frame */
+ " mrs r1, control \n" /* Test CONTROL.FPCA to see whether we also need room for the FP */
+ " tst r1, #4 \n" /* context. */
+ " beq 1f \n"
+ " sub r2, r2, #136 \n" /* subtract FP context frame size */
+ "1: \n"
+ " cmp r2, r10 \n" /* compare stack with limit */
+ " bgt 2f \n" /* stack is above limit and thus OK */
+ " b __stack_overflow_trap\n"
+ "2: \n"
+ " bx lr \n"
+ );
+}
+
+void
+__cyg_profile_func_exit(void *func, void *caller)
+{
+ asm volatile("bx lr");
+}