4 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
6 This file is part of simavr.
8 simavr is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 simavr is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with simavr. If not, see <http://www.gnu.org/licenses/>.
27 // internal structure for a hook, never seen by the notify procs
28 typedef struct avr_irq_hook_t {
29 struct avr_irq_hook_t * next;
30 int busy; // prevent reentrance of callbacks
32 struct avr_irq_t * chain; // raise the IRQ on this too - optional if "notify" is on
33 avr_irq_notify_t notify; // called when IRQ is raised - optional if "chain" is on
34 void * param; // "notify" parameter
39 avr_irq_pool_t * pool,
42 if ((pool->count & 0xf) == 0) {
43 pool->irq = (avr_irq_t**)realloc(pool->irq,
44 (pool->count + 16) * sizeof(avr_irq_t *));
46 pool->irq[pool->count++] = irq;
52 avr_irq_pool_t * pool,
55 for (int i = 0; i < pool->count; i++)
56 if (pool->irq[i] == irq) {
64 avr_irq_pool_t * pool,
68 const char ** names /* optional */)
70 memset(irq, 0, sizeof(avr_irq_t) * count);
72 for (int i = 0; i < count; i++) {
73 irq[i].irq = base + i;
74 irq[i].flags = IRQ_FLAG_INIT;
76 _avr_irq_pool_add(pool, &irq[i]);
77 if (names && names[i])
78 irq[i].name = strdup(names[i]);
80 printf("WARNING %s() with NULL name for irq %d.\n", __func__, irq[i].irq);
87 avr_irq_pool_t * pool,
90 const char ** names /* optional */)
92 avr_irq_t * irq = (avr_irq_t*)malloc(sizeof(avr_irq_t) * count);
93 avr_init_irq(pool, irq, base, count, names);
94 for (int i = 0; i < count; i++)
95 irq[i].flags |= IRQ_FLAG_ALLOC;
99 static avr_irq_hook_t *
103 avr_irq_hook_t *hook = malloc(sizeof(avr_irq_hook_t));
104 memset(hook, 0, sizeof(avr_irq_hook_t));
105 hook->next = irq->hook;
117 for (int i = 0; i < count; i++) {
118 avr_irq_t * iq = irq + i;
120 _avr_irq_pool_remove(iq->pool, iq);
122 free((char*)iq->name);
125 avr_irq_hook_t *hook = iq->hook;
127 avr_irq_hook_t * next = hook->next;
133 // if that irq list was allocated by us, free it
134 if (irq->flags & IRQ_FLAG_ALLOC)
139 avr_irq_register_notify(
141 avr_irq_notify_t notify,
147 avr_irq_hook_t *hook = irq->hook;
149 if (hook->notify == notify && hook->param == param)
150 return; // already there
153 hook = _avr_alloc_irq_hook(irq);
154 hook->notify = notify;
159 avr_irq_unregister_notify(
161 avr_irq_notify_t notify,
164 avr_irq_hook_t *hook, *prev;
171 if (hook->notify == notify && hook->param == param) {
173 prev->next = hook->next;
175 irq->hook = hook->next;
191 uint32_t output = (irq->flags & IRQ_FLAG_NOT) ? !value : value;
192 // if value is the same but it's the first time, raise it anyway
193 if (irq->value == output &&
194 (irq->flags & IRQ_FLAG_FILTERED) && !(irq->flags & IRQ_FLAG_INIT))
196 irq->flags &= ~IRQ_FLAG_INIT;
197 avr_irq_hook_t *hook = irq->hook;
199 avr_irq_hook_t * next = hook->next;
200 // prevents reentrance / endless calling loops
201 if (hook->busy == 0) {
204 hook->notify(irq, output, hook->param);
206 avr_raise_irq(hook->chain, output);
211 // the value is set after the callbacks are called, so the callbacks
212 // can themselves compare for old/new values between their parameter
213 // they are passed (new value) and the previous irq->value
222 if (!src || !dst || src == dst) {
223 fprintf(stderr, "error: %s invalid irq %p/%p", __FUNCTION__, src, dst);
226 avr_irq_hook_t *hook = src->hook;
228 if (hook->chain == dst)
229 return; // already there
232 hook = _avr_alloc_irq_hook(src);
241 avr_irq_hook_t *hook, *prev;
243 if (!src || !dst || src == dst) {
244 fprintf(stderr, "error: %s invalid irq %p/%p", __FUNCTION__, src, dst);
250 if (hook->chain == dst) {
252 prev->next = hook->next;
254 src->hook = hook->next;