Patch #4736 for Chessbox from Miguel A. Arévalo - Added support for user interaction...
[Rockbox.git] / firmware / kernel.c
blobc5edacabec8ecc9083e4fd5f9accbe41879f8a61
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Björn Stenberg
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include <stdlib.h>
20 #include <string.h>
21 #include "config.h"
22 #include "kernel.h"
23 #include "thread.h"
24 #include "cpu.h"
25 #include "system.h"
26 #include "panic.h"
28 #if ((CONFIG_CPU != PP5020) && (CONFIG_CPU != PP5002)) || !defined(BOOTLOADER)
29 long current_tick = 0;
30 #endif
32 static void (*tick_funcs[MAX_NUM_TICK_TASKS])(void);
34 /* This array holds all queues that are initiated. It is used for broadcast. */
35 static struct event_queue *all_queues[32];
36 static int num_queues;
38 void sleep(int ticks) ICODE_ATTR;
39 void queue_wait(struct event_queue *q, struct event *ev) ICODE_ATTR;
41 /****************************************************************************
42 * Standard kernel stuff
43 ****************************************************************************/
44 void kernel_init(void)
46 /* Init the threading API */
47 init_threads();
49 memset(tick_funcs, 0, sizeof(tick_funcs));
51 num_queues = 0;
52 memset(all_queues, 0, sizeof(all_queues));
54 tick_start(1000/HZ);
57 void sleep(int ticks)
59 /* Always sleep at least 1 tick */
60 int timeout = current_tick + ticks + 1;
62 while (TIME_BEFORE( current_tick, timeout )) {
63 sleep_thread();
65 wake_up_thread();
68 void yield(void)
70 switch_thread();
71 wake_up_thread();
74 /****************************************************************************
75 * Queue handling stuff
76 ****************************************************************************/
77 void queue_init(struct event_queue *q)
79 q->read = 0;
80 q->write = 0;
82 /* Add it to the all_queues array */
83 all_queues[num_queues++] = q;
86 void queue_delete(struct event_queue *q)
88 int i;
89 bool found = false;
91 /* Find the queue to be deleted */
92 for(i = 0;i < num_queues;i++)
94 if(all_queues[i] == q)
96 found = true;
97 break;
101 if(found)
103 /* Move the following queues up in the list */
104 for(;i < num_queues-1;i++)
106 all_queues[i] = all_queues[i+1];
109 num_queues--;
113 void queue_wait(struct event_queue *q, struct event *ev)
115 while(q->read == q->write)
117 sleep_thread();
119 wake_up_thread();
121 *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK];
124 void queue_wait_w_tmo(struct event_queue *q, struct event *ev, int ticks)
126 unsigned int timeout = current_tick + ticks;
128 while(q->read == q->write && TIME_BEFORE( current_tick, timeout ))
130 sleep_thread();
132 wake_up_thread();
134 if(q->read != q->write)
136 *ev = q->events[(q->read++) & QUEUE_LENGTH_MASK];
138 else
140 ev->id = SYS_TIMEOUT;
144 void queue_post(struct event_queue *q, long id, void *data)
146 int wr;
147 int oldlevel;
149 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
150 wr = (q->write++) & QUEUE_LENGTH_MASK;
152 q->events[wr].id = id;
153 q->events[wr].data = data;
154 set_irq_level(oldlevel);
157 bool queue_empty(const struct event_queue* q)
159 return ( q->read == q->write );
162 void queue_clear(struct event_queue* q)
164 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
165 q->read = 0;
166 q->write = 0;
167 set_irq_level(oldlevel);
170 int queue_broadcast(long id, void *data)
172 int i;
174 for(i = 0;i < num_queues;i++)
176 queue_post(all_queues[i], id, data);
179 return num_queues;
182 /****************************************************************************
183 * Timer tick
184 ****************************************************************************/
185 #if CONFIG_CPU == SH7034
186 void tick_start(unsigned int interval_in_ms)
188 unsigned long count;
190 count = CPU_FREQ * interval_in_ms / 1000 / 8;
192 if(count > 0x10000)
194 panicf("Error! The tick interval is too long (%d ms)\n",
195 interval_in_ms);
196 return;
199 /* We are using timer 0 */
201 TSTR &= ~0x01; /* Stop the timer */
202 TSNC &= ~0x01; /* No synchronization */
203 TMDR &= ~0x01; /* Operate normally */
205 TCNT0 = 0; /* Start counting at 0 */
206 GRA0 = (unsigned short)(count - 1);
207 TCR0 = 0x23; /* Clear at GRA match, sysclock/8 */
209 /* Enable interrupt on level 1 */
210 IPRC = (IPRC & ~0x00f0) | 0x0010;
212 TSR0 &= ~0x01;
213 TIER0 = 0xf9; /* Enable GRA match interrupt */
215 TSTR |= 0x01; /* Start timer 1 */
218 void IMIA0(void) __attribute__ ((interrupt_handler));
219 void IMIA0(void)
221 int i;
223 /* Run through the list of tick tasks */
224 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
226 if(tick_funcs[i])
228 tick_funcs[i]();
232 current_tick++;
233 wake_up_thread();
235 TSR0 &= ~0x01;
237 #elif defined(CPU_COLDFIRE)
238 void tick_start(unsigned int interval_in_ms)
240 unsigned long count;
241 int prescale;
243 count = CPU_FREQ/2 * interval_in_ms / 1000 / 16;
245 if(count > 0x10000)
247 panicf("Error! The tick interval is too long (%d ms)\n",
248 interval_in_ms);
249 return;
252 prescale = cpu_frequency / CPU_FREQ;
253 /* Note: The prescaler is later adjusted on-the-fly on CPU frequency
254 changes within timer.c */
256 /* We are using timer 0 */
258 TRR0 = (unsigned short)(count - 1); /* The reference count */
259 TCN0 = 0; /* reset the timer */
260 TMR0 = 0x001d | ((unsigned short)(prescale - 1) << 8);
261 /* restart, CLK/16, enabled, prescaler */
263 TER0 = 0xff; /* Clear all events */
265 ICR1 = 0x8c; /* Interrupt on level 3.0 */
266 IMR &= ~0x200;
269 void TIMER0(void) __attribute__ ((interrupt_handler));
270 void TIMER0(void)
272 int i;
274 /* Run through the list of tick tasks */
275 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
277 if(tick_funcs[i])
279 tick_funcs[i]();
283 current_tick++;
284 wake_up_thread();
286 TER0 = 0xff; /* Clear all events */
289 #elif CONFIG_CPU == TCC730
291 void TIMER0(void)
293 int i;
295 /* Keep alive (?)
296 * If this is not done, power goes down when DC is unplugged.
298 if (current_tick % 2 == 0)
299 P8 |= 1;
300 else
301 P8 &= ~1;
303 /* Run through the list of tick tasks */
304 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
306 if(tick_funcs[i])
308 tick_funcs[i]();
312 current_tick++;
313 wake_up_thread();
315 /* re-enable timer by clearing the counter */
316 TACON |= 0x80;
319 void tick_start(unsigned int interval_in_ms)
321 long count;
322 count = (long)FREQ * (long)interval_in_ms / 1000 / 16;
324 if(count > 0xffffL)
326 panicf("Error! The tick interval is too long (%dms->%lx)\n",
327 interval_in_ms, count);
328 return;
331 /* Use timer A */
332 TAPRE = 0x0;
333 TADATA = count;
335 TACON = 0x89;
336 /* counter clear; */
337 /* interval mode; */
338 /* TICS = F(osc) / 16 */
339 /* TCS = internal clock */
340 /* enable */
342 /* enable the interrupt */
343 interrupt_vector[2] = TIMER0;
344 IMR0 |= (1<<2);
347 #elif (CONFIG_CPU == PP5002) || (CONFIG_CPU == PP5020)
349 #ifndef BOOTLOADER
350 void TIMER1(void)
352 int i;
354 TIMER1_VAL; /* Read value to ack IRQ */
355 /* Run through the list of tick tasks */
356 for (i = 0;i < MAX_NUM_TICK_TASKS;i++)
358 if (tick_funcs[i])
360 tick_funcs[i]();
364 current_tick++;
365 wake_up_thread();
367 #endif
369 void tick_start(unsigned int interval_in_ms)
371 #ifndef BOOTLOADER
372 TIMER1_CFG = 0x0;
373 TIMER1_VAL;
374 /* enable timer */
375 TIMER1_CFG = 0xc0000000 | (interval_in_ms*1000);
376 /* unmask interrupt source */
377 CPU_INT_EN = TIMER1_MASK;
378 #else
379 /* We don't enable interrupts in the bootloader */
380 (void)interval_in_ms;
381 #endif
384 #elif CONFIG_CPU == PNX0101
386 void timer_handler(void)
388 int i;
390 /* Run through the list of tick tasks */
391 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
393 if(tick_funcs[i])
394 tick_funcs[i]();
397 current_tick++;
398 wake_up_thread();
400 TIMERR0C = 1;
403 void tick_start(unsigned int interval_in_ms)
405 TIMERR08 &= ~0x80;
406 TIMERR0C = 1;
407 TIMERR08 &= ~0x80;
408 TIMERR08 |= 0x40;
409 TIMERR00 = 3000000 * interval_in_ms / 1000;
410 TIMERR08 &= ~0xc;
411 TIMERR0C = 1;
413 irq_set_int_handler(4, timer_handler);
414 irq_enable_int(4);
416 TIMERR08 |= 0x80;
419 #endif
421 int tick_add_task(void (*f)(void))
423 int i;
424 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
426 /* Add a task if there is room */
427 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
429 if(tick_funcs[i] == NULL)
431 tick_funcs[i] = f;
432 set_irq_level(oldlevel);
433 return 0;
436 set_irq_level(oldlevel);
437 panicf("Error! tick_add_task(): out of tasks");
438 return -1;
441 int tick_remove_task(void (*f)(void))
443 int i;
444 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
446 /* Remove a task if it is there */
447 for(i = 0;i < MAX_NUM_TICK_TASKS;i++)
449 if(tick_funcs[i] == f)
451 tick_funcs[i] = NULL;
452 set_irq_level(oldlevel);
453 return 0;
457 set_irq_level(oldlevel);
458 return -1;
461 #ifndef SIMULATOR
463 * Simulator versions in uisimulator/SIMVER/
466 /****************************************************************************
467 * Simple mutex functions
468 ****************************************************************************/
469 void mutex_init(struct mutex *m)
471 m->locked = false;
474 void mutex_lock(struct mutex *m)
476 /* Wait until the lock is open... */
477 while(m->locked)
478 sleep_thread();
479 wake_up_thread();
481 /* ...and lock it */
482 m->locked = true;
485 void mutex_unlock(struct mutex *m)
487 m->locked = false;
490 #endif