diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h index 51eb635004..9438f6d308 100644 --- a/firmware/export/kernel.h +++ b/firmware/export/kernel.h @@ -207,6 +207,18 @@ int tick_add_task(void (*f)(void)); int tick_remove_task(void (*f)(void)); extern void tick_start(unsigned int interval_in_ms); +/* inline helper for implementing target interrupt handler */ +static inline void call_tick_tasks(void) +{ + extern void (*tick_funcs[MAX_NUM_TICK_TASKS+1])(void); + int i; + + current_tick++; + + for (i = 0; tick_funcs[i] != NULL; i++) + tick_funcs[i](); +} + struct timeout; /* timeout callback type diff --git a/firmware/kernel.c b/firmware/kernel.c index fb9c5e2449..70b3e03615 100644 --- a/firmware/kernel.c +++ b/firmware/kernel.c @@ -54,7 +54,9 @@ volatile long current_tick SHAREDDATA_ATTR = 0; #endif -void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); +/* List of tick tasks - final element always NULL for termination */ +void (*tick_funcs[MAX_NUM_TICK_TASKS+1])(void); +static int num_tick_funcs = 0; extern struct core_entry cores[NUM_CORES]; @@ -128,18 +130,8 @@ void tick_start(unsigned int interval_in_ms) void IMIA0(void) __attribute__ ((interrupt_handler)); void IMIA0(void) { - int i; - /* Run through the list of tick tasks */ - for(i = 0;i < MAX_NUM_TICK_TASKS;i++) - { - if(tick_funcs[i]) - { - tick_funcs[i](); - } - } - - current_tick++; + call_tick_tasks(); TSR0 &= ~0x01; } @@ -178,18 +170,8 @@ void tick_start(unsigned int interval_in_ms) void TIMER0(void) __attribute__ ((interrupt_handler)); void TIMER0(void) { - int i; - /* Run through the list of tick tasks */ - for(i = 0;i < MAX_NUM_TICK_TASKS;i++) - { - if(tick_funcs[i]) - { - tick_funcs[i](); - } - } - - current_tick++; + call_tick_tasks(); TER0 = 0xff; /* Clear all events */ } @@ -199,27 +181,17 @@ void TIMER0(void) #ifndef BOOTLOADER void TIMER1(void) { - int i; - /* Run through the list of tick tasks (using main core) */ TIMER1_VAL; /* Read value to ack IRQ */ /* Run through the list of tick tasks using main CPU core - wake up the COP through its control interface to provide pulse */ - for (i = 0;i < MAX_NUM_TICK_TASKS;i++) - { - if (tick_funcs[i]) - { - tick_funcs[i](); - } - } + call_tick_tasks(); #if NUM_CORES > 1 /* Pulse the COP */ core_wake(COP); #endif /* NUM_CORES */ - - current_tick++; } #endif @@ -243,16 +215,8 @@ void tick_start(unsigned int interval_in_ms) void timer_handler(void) { - int i; - /* Run through the list of tick tasks */ - for(i = 0;i < MAX_NUM_TICK_TASKS;i++) - { - if(tick_funcs[i]) - tick_funcs[i](); - } - - current_tick++; + call_tick_tasks(); TIMER0.clr = 0; } @@ -274,19 +238,16 @@ void tick_start(unsigned int interval_in_ms) int tick_add_task(void (*f)(void)) { - int i; int oldlevel = disable_irq_save(); /* Add a task if there is room */ - for(i = 0;i < MAX_NUM_TICK_TASKS;i++) + if(num_tick_funcs < MAX_NUM_TICK_TASKS) { - if(tick_funcs[i] == NULL) - { - tick_funcs[i] = f; - restore_irq(oldlevel); - return 0; - } + tick_funcs[num_tick_funcs++] = f; + restore_irq(oldlevel); + return 0; } + restore_irq(oldlevel); panicf("Error! tick_add_task(): out of tasks"); return -1; @@ -298,11 +259,16 @@ int tick_remove_task(void (*f)(void)) int oldlevel = disable_irq_save(); /* Remove a task if it is there */ - for(i = 0;i < MAX_NUM_TICK_TASKS;i++) + for(i = 0;i < num_tick_funcs;i++) { if(tick_funcs[i] == f) { - tick_funcs[i] = NULL; + /* Compact function list - propagates NULL-terminator as well */ + for(; i < num_tick_funcs; i++) + tick_funcs[i] = tick_funcs[i+1]; + + num_tick_funcs--; + restore_irq(oldlevel); return 0; } diff --git a/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c b/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c index e7bce8dc2c..3d7c577e3c 100644 --- a/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/kernel-imx31.c @@ -27,22 +27,12 @@ #include "kernel.h" #include "thread.h" -extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); - static __attribute__((interrupt("IRQ"))) void EPIT1_HANDLER(void) { - int i; - EPITSR1 = EPITSR_OCIF; /* Clear the pending status */ /* Run through the list of tick tasks */ - for(i = 0;i < MAX_NUM_TICK_TASKS;i++) - { - if(tick_funcs[i]) - tick_funcs[i](); - } - - current_tick++; + call_tick_tasks(); } void tick_start(unsigned int interval_in_ms) diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c index 4f878d4ed3..76917c8c82 100644 --- a/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c +++ b/firmware/target/arm/s3c2440/gigabeat-fx/kernel-meg-fx.c @@ -24,8 +24,6 @@ #include "timer.h" #include "thread.h" -extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); - void tick_start(unsigned int interval_in_ms) { /* @@ -62,18 +60,8 @@ void tick_start(unsigned int interval_in_ms) void TIMER4(void) { - int i; - /* Run through the list of tick tasks */ - for(i = 0; i < MAX_NUM_TICK_TASKS; i++) - { - if(tick_funcs[i]) - { - tick_funcs[i](); - } - } - - current_tick++; + call_tick_tasks(); SRCPND = TIMER4_MASK; INTPND = TIMER4_MASK; diff --git a/firmware/target/arm/tcc77x/timer-tcc77x.c b/firmware/target/arm/tcc77x/timer-tcc77x.c index 4645e388cc..924ddda625 100644 --- a/firmware/target/arm/tcc77x/timer-tcc77x.c +++ b/firmware/target/arm/tcc77x/timer-tcc77x.c @@ -51,24 +51,12 @@ void __timer_unregister(void) /* Timer interrupt processing - all timers (inc. tick) have a single IRQ */ - -extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); - void TIMER(void) { if (TIREQ & TF0) /* Timer0 reached ref value */ { - int i; - /* Run through the list of tick tasks */ - for(i = 0; i < MAX_NUM_TICK_TASKS; i++) - { - if(tick_funcs[i]) - { - tick_funcs[i](); - } - } - current_tick++; + call_tick_tasks(); /* reset Timer 0 IRQ & ref flags */ TIREQ |= TI0 | TF0; diff --git a/firmware/target/arm/tcc780x/timer-tcc780x.c b/firmware/target/arm/tcc780x/timer-tcc780x.c index c08520116a..17956131c0 100644 --- a/firmware/target/arm/tcc780x/timer-tcc780x.c +++ b/firmware/target/arm/tcc780x/timer-tcc780x.c @@ -46,25 +46,12 @@ void __timer_unregister(void) /* Timer interrupt processing - all timers (inc. tick) have a single IRQ */ - -extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); - void TIMER0(void) { if (TIREQ & TF0) /* Timer0 reached ref value */ { - int i; - /* Run through the list of tick tasks */ - for(i = 0; i < MAX_NUM_TICK_TASKS; i++) - { - if(tick_funcs[i]) - { - tick_funcs[i](); - } - } - - current_tick++; + call_tick_tasks(); /* reset Timer 0 IRQ & ref flags */ TIREQ |= TI0 | TF0; diff --git a/firmware/target/arm/tms320dm320/kernel-dm320.c b/firmware/target/arm/tms320dm320/kernel-dm320.c index 42f9773d36..b5eb4233e4 100644 --- a/firmware/target/arm/tms320dm320/kernel-dm320.c +++ b/firmware/target/arm/tms320dm320/kernel-dm320.c @@ -25,8 +25,6 @@ #include "timer.h" #include "thread.h" -extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); - void tick_start(unsigned int interval_in_ms) { /* TODO: set up TIMER1 clock settings @@ -53,16 +51,7 @@ void tick_start(unsigned int interval_in_ms) void TIMER1(void) { IO_INTC_IRQ0 = INTR_IRQ0_TMR1; - - int i; /* Run through the list of tick tasks */ - for(i = 0; i < MAX_NUM_TICK_TASKS; i++) - { - if(tick_funcs[i]) - { - tick_funcs[i](); - } - } - current_tick++; + call_tick_tasks(); } diff --git a/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c b/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c index 62176cee24..dcfdfd6a38 100644 --- a/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/kernel-jz4740.c @@ -24,8 +24,6 @@ #include "kernel.h" #include "jz4740.h" -extern void (*tick_funcs[MAX_NUM_TICK_TASKS])(void); - #define USE_RTC_CLOCK 0 void tick_start(unsigned int interval_in_ms) { @@ -70,13 +68,6 @@ void TCU0(void) { __tcu_clear_full_match_flag(0); - int i; - /* Run through the list of tick tasks */ - for(i = 0; i < MAX_NUM_TICK_TASKS; i++) - { - if(tick_funcs[i]) - tick_funcs[i](); - } - current_tick++; + call_tick_tasks(); }