summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-07-29 04:49:19 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-07-29 04:49:19 +0000
commite64f7e3a6f3019be855469373920198ac19ee654 (patch)
treedf75ceff98beb6d4eff222fa18de74b155d33ddc
parent4f08483b3992d0d66300fd2109529965301ee880 (diff)
downloadrockbox-e64f7e3a6f3019be855469373920198ac19ee654.tar.gz
rockbox-e64f7e3a6f3019be855469373920198ac19ee654.zip
Add a new timeout API to the kernel. Enable only for e200 right now since it's the only user. Use that as the one-shot delay for SD card inserts.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14049 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/export/config-e200.h2
-rw-r--r--firmware/export/kernel.h22
-rw-r--r--firmware/kernel.c102
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/ata-e200.c15
4 files changed, 138 insertions, 3 deletions
diff --git a/firmware/export/config-e200.h b/firmware/export/config-e200.h
index acb23cb4d0..63f617e78d 100644
--- a/firmware/export/config-e200.h
+++ b/firmware/export/config-e200.h
@@ -176,4 +176,6 @@
176/* Range for this target: 0xffffff*(0.0-16.000000894069724921567733381255) */ 176/* Range for this target: 0xffffff*(0.0-16.000000894069724921567733381255) */
177#define WHEEL_ACCELERATION_FACTOR (0xffffff*7) 177#define WHEEL_ACCELERATION_FACTOR (0xffffff*7)
178 178
179#define INCLUDE_TIMEOUT_API
180
179#endif /* SIMULATOR */ 181#endif /* SIMULATOR */
diff --git a/firmware/export/kernel.h b/firmware/export/kernel.h
index b40d602d9f..bf5a9d10c3 100644
--- a/firmware/export/kernel.h
+++ b/firmware/export/kernel.h
@@ -126,6 +126,28 @@ extern void sleep(int ticks);
126int tick_add_task(void (*f)(void)); 126int tick_add_task(void (*f)(void));
127int tick_remove_task(void (*f)(void)); 127int tick_remove_task(void (*f)(void));
128 128
129struct timeout;
130
131/* timeout callback type
132 * tmo - pointer to struct timeout associated with event
133 */
134typedef bool (* timeout_cb_type)(struct timeout *tmo);
135
136struct timeout
137{
138 /* for use by callback/internal - read/write */
139 timeout_cb_type callback;/* callback - returning false cancels */
140 int ticks; /* timeout period in ticks */
141 intptr_t data; /* data passed to callback */
142 /* internal use - read-only */
143 const struct timeout * const next; /* next timeout in list */
144 const long expires; /* expiration tick */
145};
146
147void timeout_register(struct timeout *tmo, timeout_cb_type callback,
148 int ticks, intptr_t data);
149void timeout_cancel(struct timeout *tmo);
150
129extern void queue_init(struct event_queue *q, bool register_queue); 151extern void queue_init(struct event_queue *q, bool register_queue);
130#if NUM_CORES > 1 152#if NUM_CORES > 1
131extern void queue_set_irq_safe(struct event_queue *q, bool state); 153extern void queue_set_irq_safe(struct event_queue *q, bool state);
diff --git a/firmware/kernel.c b/firmware/kernel.c
index b1a4e62a81..bb67ced64d 100644
--- a/firmware/kernel.c
+++ b/firmware/kernel.c
@@ -750,6 +750,108 @@ int tick_remove_task(void (*f)(void))
750 return -1; 750 return -1;
751} 751}
752 752
753/****************************************************************************
754 * Tick-based interval timers/one-shots - be mindful this is not really
755 * intended for continuous timers but for events that need to run for a short
756 * time and be cancelled without further software intervention.
757 ****************************************************************************/
758#ifdef INCLUDE_TIMEOUT_API
759static struct timeout *tmo_list = NULL; /* list of active timeout events */
760
761/* timeout tick task - calls event handlers when they expire
762 * Event handlers may alter ticks, callback and data during operation.
763 */
764static void timeout_tick(void)
765{
766 unsigned long tick = current_tick;
767 struct timeout *curr, *next;
768
769 for (curr = tmo_list; curr != NULL; curr = next)
770 {
771 next = (struct timeout *)curr->next;
772
773 if (TIME_BEFORE(tick, curr->expires))
774 continue;
775
776 /* this event has expired - call callback */
777 if (curr->callback(curr))
778 *(long *)&curr->expires = tick + curr->ticks; /* reload */
779 else
780 timeout_cancel(curr); /* cancel */
781 }
782}
783
784/* Cancels a timeout callback - can be called from the ISR */
785void timeout_cancel(struct timeout *tmo)
786{
787 int oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
788
789 if (tmo_list != NULL)
790 {
791 struct timeout *curr = tmo_list;
792 struct timeout *prev = NULL;
793
794 while (curr != tmo && curr != NULL)
795 {
796 prev = curr;
797 curr = (struct timeout *)curr->next;
798 }
799
800 if (curr != NULL)
801 {
802 /* in list */
803 if (prev == NULL)
804 tmo_list = (struct timeout *)curr->next;
805 else
806 *(const struct timeout **)&prev->next = curr->next;
807
808 if (tmo_list == NULL)
809 tick_remove_task(timeout_tick); /* last one - remove task */
810 }
811 /* not in list or tmo == NULL */
812 }
813
814 set_irq_level(oldlevel);
815}
816
817/* Adds a timeout callback - calling with an active timeout resets the
818 interval - can be called from the ISR */
819void timeout_register(struct timeout *tmo, timeout_cb_type callback,
820 int ticks, intptr_t data)
821{
822 int oldlevel;
823 struct timeout *curr;
824
825 if (tmo == NULL)
826 return;
827
828 oldlevel = set_irq_level(HIGHEST_IRQ_LEVEL);
829
830 /* see if this one is already registered */
831 curr = tmo_list;
832 while (curr != tmo && curr != NULL)
833 curr = (struct timeout *)curr->next;
834
835 if (curr == NULL)
836 {
837 /* not found - add it */
838 if (tmo_list == NULL)
839 tick_add_task(timeout_tick); /* first one - add task */
840
841 *(struct timeout **)&tmo->next = tmo_list;
842 tmo_list = tmo;
843 }
844
845 tmo->callback = callback;
846 tmo->ticks = ticks;
847 tmo->data = data;
848 *(long *)&tmo->expires = current_tick + ticks;
849
850 set_irq_level(oldlevel);
851}
852
853#endif /* INCLUDE_TIMEOUT_API */
854
753#ifndef SIMULATOR 855#ifndef SIMULATOR
754/* 856/*
755 * Simulator versions in uisimulator/SIMVER/ 857 * Simulator versions in uisimulator/SIMVER/
diff --git a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
index 1b67454445..ff277ec8a3 100644
--- a/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/ata-e200.c
@@ -1122,15 +1122,24 @@ bool card_detect_target(void)
1122 return (GPIOA_INPUT_VAL & 0x80) == 0; 1122 return (GPIOA_INPUT_VAL & 0x80) == 0;
1123} 1123}
1124 1124
1125static bool sd1_oneshot_callback(struct timeout *tmo)
1126{
1127 /* Take final state only - insert/remove is bouncy */
1128 queue_remove_from_head(&sd_queue, SD_HOTSWAP);
1129 queue_post(&sd_queue, SD_HOTSWAP, tmo->data);
1130 return false;
1131}
1132
1125/* called on insertion/removal interrupt */ 1133/* called on insertion/removal interrupt */
1126void microsd_int(void) 1134void microsd_int(void)
1127{ 1135{
1136 static struct timeout sd1_oneshot;
1137
1128 int detect = GPIOA_INPUT_VAL & 0x80; 1138 int detect = GPIOA_INPUT_VAL & 0x80;
1129 1139
1130 GPIOA_INT_LEV = (GPIOA_INT_LEV & ~0x80) | (detect ^ 0x80); 1140 GPIOA_INT_LEV = (GPIOA_INT_LEV & ~0x80) | (detect ^ 0x80);
1131 GPIOA_INT_CLR = 0x80; 1141 GPIOA_INT_CLR = 0x80;
1132 1142
1133 /* Take final state only - insert/remove is bouncy */ 1143 timeout_register(&sd1_oneshot, sd1_oneshot_callback,
1134 queue_remove_from_head(&sd_queue, SD_HOTSWAP); 1144 detect ? 1 : HZ/2, detect == 0);
1135 queue_post(&sd_queue, SD_HOTSWAP, detect == 0);
1136} 1145}