aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libmaple/exc.S40
-rw-r--r--libmaple/util.c50
-rw-r--r--libmaple/util.h1
3 files changed, 58 insertions, 33 deletions
diff --git a/libmaple/exc.S b/libmaple/exc.S
index d01e3d5..823bbc5 100644
--- a/libmaple/exc.S
+++ b/libmaple/exc.S
@@ -48,40 +48,50 @@
.globl __exc_busfault
.globl __exc_usagefault
-/* TODO: Fix this up. */
+.code 16
.thumb_func
__exc_nmi:
mov r0, #1
+ b __default_exc
.thumb_func
__exc_hardfault:
mov r0, #2
+ b __default_exc
.thumb_func
__exc_memmanage:
mov r0, #3
+ b __default_exc
.thumb_func
__exc_busfault:
mov r0, #4
+ b __default_exc
.thumb_func
__exc_usagefault:
mov r0, #5
+ b __default_exc
-__default:
- ldr r1, CPSR_MASK @ Set default CPSR
- push {r1}
- ldr r1, TARGET_PC @ Set target pc
- push {r1}
- sub sp, sp, #24 @ Don't care
- ldr r1, EXC_RETURN @ Return to thread mode
- mov lr, r1
- bx lr @ Exception exit
-
- .align 4
- CPSR_MASK: .word 0x61000000
- EXC_RETURN: .word 0xFFFFFFF9
- TARGET_PC: .word throb
+.thumb_func
+__default_exc:
+ ldr r2, NVIC_CCR @ Enabling returning to thread mode from an
+ mov r1 ,#1 @ exception. See flag NONEBASETHRDENA.
+ str r1, [r2]
+ cpsid i @ Disable global interrupts
+ ldr r1, CPSR_MASK @ Set default CPSR
+ push {r1}
+ ldr r1, TARGET_PC @ Set target pc
+ push {r1}
+ sub sp, sp, #24 @ Don't care
+ ldr r1, EXC_RETURN @ Return to thread mode
+ mov lr, r1
+ bx lr @ Exception exit
+.align 4
+CPSR_MASK: .word 0x61000000
+EXC_RETURN: .word 0xFFFFFFF9
+TARGET_PC: .word __error
+NVIC_CCR: .word 0xE000ED14 @ NVIC configuration control register
diff --git a/libmaple/util.c b/libmaple/util.c
index 481cd60..3408a2e 100644
--- a/libmaple/util.c
+++ b/libmaple/util.c
@@ -49,14 +49,14 @@
#define HAVE_ERROR_LED
#endif
-/* Error assert + fade */
-void _fail(const char* file, int line, const char* exp) {
- int32 slope = 1;
- uint32 CC = 0x0000;
- uint32 TOP_CNT = 0x02FF;
- uint32 i = 0;
-
- /* Turn off interrupts */
+/**
+ * @brief Disables all peripheral interrupts except USB and fades the
+ * error LED.
+ *
+ * Called from exc.S with global interrupts disabled.
+ */
+void __error(void) {
+ /* Turn off peripheral interrupts */
nvic_irq_disable_all();
/* Turn off timers */
@@ -68,6 +68,24 @@ void _fail(const char* file, int line, const char* exp) {
/* Turn off all usarts */
usart_disable_all();
+ /* Turn the USB interrupt back on so the bootloader keeps on functioning */
+ nvic_irq_enable(NVIC_INT_USBHP);
+ nvic_irq_enable(NVIC_INT_USBLP);
+
+ /* Reenable global interrupts */
+ nvic_globalirq_enable();
+ throb();
+}
+
+/**
+ * @brief Prints an error message on a uart upon a failed assertion
+ * and error throbs.
+ * @param file Source file of failed assertion
+ * @param line Source line of failed assertion
+ * @param exp String representation of failed assertion
+ * @sideeffect Turns of all peripheral interrupts except USB.
+ */
+void _fail(const char* file, int line, const char* exp) {
/* Initialize the error usart */
gpio_set_mode(ERROR_TX_PORT, ERROR_TX_PIN, GPIO_MODE_AF_OUTPUT_PP);
usart_init(ERROR_USART_NUM, ERROR_USART_BAUD);
@@ -82,19 +100,15 @@ void _fail(const char* file, int line, const char* exp) {
usart_putc(ERROR_USART_NUM, '\n');
usart_putc(ERROR_USART_NUM, '\r');
-#ifdef HAVE_ERROR_LED
- /* Turn on the error LED */
- gpio_set_mode(ERROR_LED_PORT, ERROR_LED_PIN, GPIO_MODE_OUTPUT_PP);
-#endif
-
- /* Turn the USB interrupt back on so the bootloader keeps on functioning */
- nvic_irq_enable(NVIC_INT_USBHP);
- nvic_irq_enable(NVIC_INT_USBLP);
-
/* Error fade */
- throb();
+ __error();
}
+
+/**
+ * @brief Fades the error LED on and off
+ * @sideeffect Sets output push-pull on ERROR_LED_PIN.
+ */
void throb(void) {
#ifdef HAVE_ERROR_LED
int32 slope = 1;
diff --git a/libmaple/util.h b/libmaple/util.h
index 28ce970..fb524c2 100644
--- a/libmaple/util.h
+++ b/libmaple/util.h
@@ -79,6 +79,7 @@ extern "C"{
#define __write(reg, value) (*(volatile uint32*)(reg) = (value))
#define IS_POWER_OF_TWO(v) (v && !(v & (v - 1)))
+void __error(void);
void _fail(const char*, int, const char*);
void throb(void);