diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2007-07-29 04:49:19 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2007-07-29 04:49:19 +0000 |
commit | e64f7e3a6f3019be855469373920198ac19ee654 (patch) | |
tree | df75ceff98beb6d4eff222fa18de74b155d33ddc | |
parent | 4f08483b3992d0d66300fd2109529965301ee880 (diff) | |
download | rockbox-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.h | 2 | ||||
-rw-r--r-- | firmware/export/kernel.h | 22 | ||||
-rw-r--r-- | firmware/kernel.c | 102 | ||||
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/ata-e200.c | 15 |
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); | |||
126 | int tick_add_task(void (*f)(void)); | 126 | int tick_add_task(void (*f)(void)); |
127 | int tick_remove_task(void (*f)(void)); | 127 | int tick_remove_task(void (*f)(void)); |
128 | 128 | ||
129 | struct timeout; | ||
130 | |||
131 | /* timeout callback type | ||
132 | * tmo - pointer to struct timeout associated with event | ||
133 | */ | ||
134 | typedef bool (* timeout_cb_type)(struct timeout *tmo); | ||
135 | |||
136 | struct 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 | |||
147 | void timeout_register(struct timeout *tmo, timeout_cb_type callback, | ||
148 | int ticks, intptr_t data); | ||
149 | void timeout_cancel(struct timeout *tmo); | ||
150 | |||
129 | extern void queue_init(struct event_queue *q, bool register_queue); | 151 | extern void queue_init(struct event_queue *q, bool register_queue); |
130 | #if NUM_CORES > 1 | 152 | #if NUM_CORES > 1 |
131 | extern void queue_set_irq_safe(struct event_queue *q, bool state); | 153 | extern 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 | ||
759 | static 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 | */ | ||
764 | static 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 */ | ||
785 | void 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 */ | ||
819 | void 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 | ||
1125 | static 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 */ |
1126 | void microsd_int(void) | 1134 | void 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 | } |