SingingCat 0
application
irq_router.c
1#include "main-header.h"
2#include "irq_router.h"
3#define MAX_IRQS 15
4
5// set this bit to trigger irq
6#define IRQ_STATUS_DUE 0
7
8typedef struct softirq_registration {
9 MCULIB_HANDLE handle;
10 int pin;
11 softirq * callback;
12 void * opaque;
13 byte status;
15
16static struct softirq_registration registrations[MAX_IRQS];
17/*
18 * \brief register a softirq on a pin.
19 *
20 * caller must set up pin for input and provide call back function.
21 * softirq will be called during mainloop (it will not interrupt mainloop)
22 */
23int register_softirq(MCULIB_HANDLE handle, int pin, softirq *callback, void *opaque) {
24 int i;
25 struct softirq_registration *sf = NULL;
26 struct softirq_registration *usf = NULL;
27
28 for (i = 0; i < MAX_IRQS; i++) {
29 sf = &registrations[i];
30 if (sf->callback == NULL) {
31 if (usf == NULL) {
32 usf = sf;
33 }
34 continue;
35 }
36 if (sf->pin == pin) {
37 usf = sf;
38 break;
39 }
40 }
41 if (usf == NULL) {
42 printf("Not enough softirqs available\r\n");
43 return 1;
44 }
45 usf->pin = pin;
46 usf->handle = handle;
47 usf->callback = callback;
48 usf->opaque = opaque;
49 return 0;
50}
51void release_irq_by_handle(MCULIB_HANDLE handle) {
52 int i;
53 struct softirq_registration *sf = NULL;
54
55 for (i = 0; i < MAX_IRQS; i++) {
56 sf = &registrations[i];
57 if ((sf->callback != NULL) && (sf->handle == handle)) {
58 sf->callback = NULL;
59 }
60 }
61}
62
63static struct softirq_registration *get_by_pin(int pin) {
64 int i;
65 struct softirq_registration *sf = NULL;
66
67 for (i = 0; i < MAX_IRQS; i++) {
68 sf = &registrations[i];
69 if ((sf->callback != NULL) && (sf->pin == pin)) {
70 return sf;
71 }
72 }
73 return NULL;
74}
75
76void process_irqs() {
77 int i;
78 struct softirq_registration *sf = NULL;
79
80 for (i = 0; i < MAX_IRQS; i++) {
81 sf = &registrations[i];
82 if ((sf->callback != NULL) && (sf->status & (1 << IRQ_STATUS_DUE))) {
83 sf->status = sf->status & ~(1 << IRQ_STATUS_DUE);
84 // printf("IRQ-router: SoftIRQ on pin %i\r\n",sf->pin);
85 sf->callback(sf->pin, sf->opaque);
86 sf->status = sf->status & ~(1 << IRQ_STATUS_DUE); // clear the irq a second time, so to avoid spurious IRQs. this certainly can't be the right thing to do
87 }
88 }
89}
90
91static void pinirq(int pin) __attribute__((no_instrument_function));
92// the *REAL* irq
93// mark the fact that "real" IRQ occured on this pin
94static void pinirq(int pin) {
95 struct softirq_registration *sf = get_by_pin(pin);
96
97 if (sf == NULL) {
98 return;
99 }
100 sf->status = sf->status | (1 << IRQ_STATUS_DUE);
101}
102
103void irq_router_init() {
104 memset(&registrations, sizeof(registrations), 0);
105 mculib_pin_in_callback(MAIN_MCULIBHANDLE, &pinirq); // for ti1101
106}