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/>.
28 void avr_init_irq(avr_irq_t * irq, uint32_t base, uint32_t count)
30 memset(irq, 0, sizeof(avr_irq_t) * count);
32 for (int i = 0; i < count; i++)
33 irq[i].irq = base + i;
36 avr_irq_t * avr_alloc_irq(uint32_t base, uint32_t count)
38 avr_irq_t * irq = (avr_irq_t*)malloc(sizeof(avr_irq_t) * count);
39 avr_init_irq(irq, base, count);
40 for (int i = 0; i < count; i++)
41 irq[i].flags |= IRQ_FLAG_ALLOC;
45 static avr_irq_hook_t * _avr_alloc_irq_hook(avr_irq_t * irq)
47 avr_irq_hook_t *hook = malloc(sizeof(avr_irq_hook_t));
48 memset(hook, 0, sizeof(avr_irq_hook_t));
49 hook->next = irq->hook;
54 void avr_free_irq(avr_irq_t * irq, uint32_t count)
56 for (int i = 0; i < count; i++) {
58 avr_irq_hook_t *hook = irq->hook;
60 avr_irq_hook_t * next = hook->next;
66 // if that irq list was allocated by us, free it
67 if (irq->flags & IRQ_FLAG_ALLOC)
71 void avr_irq_register_notify(avr_irq_t * irq, avr_irq_notify_t notify, void * param)
76 avr_irq_hook_t *hook = irq->hook;
78 if (hook->notify == notify && hook->param == param)
79 return; // already there
82 hook = _avr_alloc_irq_hook(irq);
83 hook->notify = notify;
87 void avr_raise_irq(avr_irq_t * irq, uint32_t value)
91 uint32_t output = (irq->flags & IRQ_FLAG_NOT) ? !value : value;
92 if (irq->value == output && (irq->flags & IRQ_FLAG_FILTERED))
94 avr_irq_hook_t *hook = irq->hook;
96 avr_irq_hook_t * next = hook->next;
97 // prevents reentrance / endless calling loops
98 if (hook->busy == 0) {
101 hook->notify(irq, output, hook->param);
103 avr_raise_irq(hook->chain, output);
108 // the value is set after the callbacks are called, so the callbacks
109 // can themselves compare for old/new values between their parameter
110 // they are passed (new value) and the previous irq->value
114 void avr_connect_irq(avr_irq_t * src, avr_irq_t * dst)
116 if (!src || !dst || src == dst) {
117 printf("avr_connect_irq invalid irq %p/%p", src, dst);
120 avr_irq_hook_t *hook = src->hook;
122 if (hook->chain == dst)
123 return; // already there
126 hook = _avr_alloc_irq_hook(src);