stm32/pendsv: Add ability to schedule callbacks at pendsv IRQ level.

This commit is contained in:
Damien George 2019-02-08 01:11:21 +11:00
parent b178958c07
commit 18cfa156d6
2 changed files with 45 additions and 0 deletions

View File

@ -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"
);

View File

@ -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