summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2019-02-08 01:11:21 +1100
committerDamien George <damien.p.george@gmail.com>2019-02-08 01:20:13 +1100
commit18cfa156d628873dfe0e12bcaad19bd802f32994 (patch)
treeb86a22b92601ea3509c8dd2e9f6fdfef54cc8ada
parentb178958c0799f16847a70c7a5c717a39528407ec (diff)
stm32/pendsv: Add ability to schedule callbacks at pendsv IRQ level.
-rw-r--r--ports/stm32/pendsv.c40
-rw-r--r--ports/stm32/pendsv.h5
2 files changed, 45 insertions, 0 deletions
diff --git a/ports/stm32/pendsv.c b/ports/stm32/pendsv.c
index a6a9afc14..6c6b3c7bf 100644
--- a/ports/stm32/pendsv.c
+++ b/ports/stm32/pendsv.c
@@ -38,7 +38,15 @@
// mp_kbd_exception which is in the root-pointer set.
void *pendsv_object;
+#if PENDSV_DISPATCH_NUM_SLOTS > 0
+uint32_t pendsv_dispatch_active;
+pendsv_dispatch_t pendsv_dispatch_table[PENDSV_DISPATCH_NUM_SLOTS];
+#endif
+
void pendsv_init(void) {
+ #if PENDSV_DISPATCH_NUM_SLOTS > 0
+ pendsv_dispatch_active = false;
+ #endif
// set PendSV interrupt at lowest priority
NVIC_SetPriority(PendSV_IRQn, IRQ_PRI_PENDSV);
}
@@ -61,6 +69,23 @@ void pendsv_kbd_intr(void) {
}
}
+#if PENDSV_DISPATCH_NUM_SLOTS > 0
+void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f) {
+ pendsv_dispatch_table[slot] = f;
+ pendsv_dispatch_active = true;
+ SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
+}
+
+void pendsv_dispatch_handler(void) {
+ for (size_t i = 0; i < PENDSV_DISPATCH_NUM_SLOTS; ++i) {
+ if (pendsv_dispatch_table[i] != NULL) {
+ pendsv_dispatch_table[i] = NULL;
+ pendsv_dispatch_table[i]();
+ }
+ }
+}
+#endif
+
__attribute__((naked)) void PendSV_Handler(void) {
// Handle a PendSV interrupt
//
@@ -94,6 +119,18 @@ __attribute__((naked)) void PendSV_Handler(void) {
// sp[0]: ?
__asm volatile (
+ #if PENDSV_DISPATCH_NUM_SLOTS > 0
+ // Check if there are any pending calls to dispatch to
+ "ldr r1, pendsv_dispatch_active_ptr\n"
+ "ldr r0, [r1]\n"
+ "cmp r0, 0\n"
+ "beq .no_dispatch\n"
+ "mov r2, #0\n"
+ "str r2, [r1]\n" // clear pendsv_dispatch_active
+ "b pendsv_dispatch_handler\n" // jump to the handler
+ ".no_dispatch:\n"
+ #endif
+
// Check if there is an active object to throw via nlr_jump
"ldr r1, pendsv_object_ptr\n"
"ldr r0, [r1]\n"
@@ -137,6 +174,9 @@ __attribute__((naked)) void PendSV_Handler(void) {
// Data
".align 2\n"
+ #if PENDSV_DISPATCH_NUM_SLOTS > 0
+ "pendsv_dispatch_active_ptr: .word pendsv_dispatch_active\n"
+ #endif
"pendsv_object_ptr: .word pendsv_object\n"
"nlr_jump_ptr: .word nlr_jump\n"
);
diff --git a/ports/stm32/pendsv.h b/ports/stm32/pendsv.h
index 52ce80536..c8cc64d76 100644
--- a/ports/stm32/pendsv.h
+++ b/ports/stm32/pendsv.h
@@ -26,7 +26,12 @@
#ifndef MICROPY_INCLUDED_STM32_PENDSV_H
#define MICROPY_INCLUDED_STM32_PENDSV_H
+#define PENDSV_DISPATCH_NUM_SLOTS (0)
+
+typedef void (*pendsv_dispatch_t)(void);
+
void pendsv_init(void);
void pendsv_kbd_intr(void);
+void pendsv_schedule_dispatch(size_t slot, pendsv_dispatch_t f);
#endif // MICROPY_INCLUDED_STM32_PENDSV_H