3 * This file is part of 0cpm Firmerware.
5 * 0cpm Firmerware is Copyright (c)2011 Rick van Rein, OpenFortress.
7 * 0cpm Firmerware is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation, version 3.
11 * 0cpm Firmerware is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with 0cpm Firmerware. If not, see <http://www.gnu.org/licenses/>.
30 #include <0cpm/cons.h>
33 /* Round-robin queues with interrupts and closures, ordered by priority.
34 * To be fair, the elements pointed at have already been completed
35 * and are awaiting roll-over or removal.
36 * TODO: Make the array contents volatile
38 irq_t *irqs [CPU_PRIO_COUNT] = { NULL, NULL, NULL, NULL };
39 closure_t *closures [CPU_PRIO_COUNT] = { NULL, NULL, NULL, NULL };
40 #if CPU_PRIO_COUNT != 4
41 //TODO// # error "Update the number of NULL value initialisations above"
44 /* The current priority is an optimisation; it tells what the highest
45 * active priority is, so as to avoid too much searching. The priority
46 * starts at the low value CPU_PRIO_ZERO at which nothing runs; as soon
47 * as anything is scheduled, the value is increased to signal work is to
50 volatile priority_t cur_prio = CPU_PRIO_ZERO;
53 /* Add an IRQ to the round-robin task queue to be scheduled.
54 * This routine must always be called with interrupts inactive;
55 * either as part of an interrupt routine, or when called in the
56 * course of the main program, from within a critical region.
58 void irq_fire (irq_t *irq) {
59 priority_t p = irq->irq_priority;
60 //TODO// if (irq->irq_next) return;
62 irq->irq_next = irqs [p]->irq_next;
63 irqs [p]->irq_next = irq;
67 irqs [p] = irq; // Newly added becomes last in the queue
71 //TODO:TEST// ht162x_audiolevel (1 << 5);
75 /* Hop jobs until there is nothing left to do. This is actually the main
76 * procedure for the scheduler. If it ends, then all the work has been
77 * enqueued somewhere, and is awaiting a response. In other words, it
78 * is then time to sleep. This assumes that no task or IRQ will ever
79 * be set to CPU_PRIO_ZERO.
81 void jobhopper (void) {
82 void ht162x_putchar (uint8_t idx, uint8_t ch, bool notify);
83 //OVERZEALOUSLOGGER// bottom_printf ("Jobhopper starts.\n");
84 //TODO:TEST// ht162x_putchar (0, '0', true);
85 while (cur_prio > CPU_PRIO_ZERO) {
87 //TODO:TEST// ht162x_putchar (0, '1', true);
88 while (irqs [cur_prio]) {
89 //TODO:TEST// ht162x_putchar (0, '2', true);
90 //TODO:JUSTREMOVE// irqs [cur_prio] = irqs [cur_prio]->irq_next;
94 bottom_critical_region_begin ();
95 prev = irqs [cur_prio];
97 bottom_critical_region_end ();
100 todo = prev->irq_next;
102 //TODO:TEST// ht162x_audiolevel (1 << 5);
103 //TODO:TEST// ht162x_putchar (0, '3', true);
104 prev->irq_next = todo->irq_next;
106 //TODO:TEST// ht162x_audiolevel (1 << 5);
107 //TODO:TEST// ht162x_putchar (0, '4', true);
108 irqs [cur_prio] = NULL;
110 todo->irq_next = NULL;
111 bottom_critical_region_end ();
112 //OVERZEALOUSLOGGER// bottom_printf ("Jobhopper calls interrupt handler.\n");
113 //TODO:TEST// ht162x_audiolevel (2 << 5);
114 //TODO:NAAAHHH// if (this->irq_handler)
115 (*todo->irq_handler) (todo);
116 //TODO:TEST// ht162x_putchar (0, '5', true);
119 here = closures [cur_prio];
121 closures [cur_prio] = here->cls_next;
122 here->cls_next = NULL;
123 here = (*here->cls_handler) (here);
125 closure_t **last = &closures [cur_prio];
126 while (*last != NULL) {
127 //TODO:TEST// ht162x_putchar (0, '6', true);
128 last = &(*last)->cls_next;
130 //TODO:TEST// ht162x_putchar (0, '7', true);
131 bottom_printf ("Jobhopper found closure -- TODO: call it!\n");
132 here->cls_next = NULL;
136 //TODO:TEST// ht162x_putchar (0, '8', true);
140 //TODO:TEST// ht162x_putchar (0, '9', true);
141 //OVERZEALOUSLOGGER// bottom_printf ("Jobhopper ends.\n");