Merge "inc: add chained ISR helper" into mnc-dev
diff --git a/firmware/inc/isr.h b/firmware/inc/isr.h
new file mode 100644
index 0000000..c1e95d6
--- /dev/null
+++ b/firmware/inc/isr.h
@@ -0,0 +1,51 @@
+#ifndef __ISR_H
+#define __ISR_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <cpu.h>
+#include <list.h>
+#include <util.h>
+
+struct ChainedInterrupt {
+ link_t isrs;
+
+ void (*const enable)(struct ChainedInterrupt *);
+ void (*const disable)(struct ChainedInterrupt *);
+};
+
+struct ChainedIsr {
+ link_t node;
+ bool (*const func)(struct ChainedIsr *);
+};
+
+static inline void chainIsr(struct ChainedInterrupt *interrupt, struct ChainedIsr *isr)
+{
+ interrupt->disable(interrupt);
+ list_add_tail(&interrupt->isrs, &isr->node);
+ interrupt->enable(interrupt);
+}
+
+static inline void unchainIsr(struct ChainedInterrupt *interrupt, struct ChainedIsr *isr)
+{
+ interrupt->disable(interrupt);
+ list_delete(&isr->node);
+ if (!list_is_empty(&interrupt->isrs))
+ interrupt->enable(interrupt);
+}
+
+static inline bool dispatchIsr(struct ChainedInterrupt *interrupt)
+{
+ struct link_t *cur, *tmp;
+ bool handled = false;
+
+ list_iterate(&interrupt->isrs, cur, tmp) {
+ struct ChainedIsr *curIsr = container_of(cur, struct ChainedIsr, node);
+ handled = handled || curIsr->func(curIsr);
+ }
+
+ return handled;
+}
+
+#endif /* __ISR_H */