Fixed GenericHIDHost demo report write routine incorrect for control type requests...
[pub/USBasp.git] / LUFA / Scheduler / Scheduler.h
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2009.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, and distribute this software
13 and its documentation for any purpose and without fee is hereby
14 granted, provided that the above copyright notice appear in all
15 copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaim all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29 */
30
31 /** \file
32 *
33 * Simple round-robbin cooperative scheduler for use in basic projects where non real-time tasks need
34 * to be executed. Each task is executed in sequence, and can be enabled or disabled individually or as a group.
35 *
36 * For a task to yield it must return, thus each task should have persistent data marked with the static attribute.
37 *
38 * Usage Example:
39 * \code
40 * #include <LUFA/Scheduler/Scheduler.h>
41 *
42 * TASK(MyTask1);
43 * TASK(MyTask2);
44 *
45 * TASK_LIST
46 * {
47 * { Task: MyTask1, TaskStatus: TASK_RUN, GroupID: 1 },
48 * { Task: MyTask2, TaskStatus: TASK_RUN, GroupID: 1 },
49 * }
50 *
51 * int main(void)
52 * {
53 * Scheduler_Start();
54 * }
55 *
56 * TASK(MyTask1)
57 * {
58 * // Implementation Here
59 * }
60 *
61 * TASK(MyTask2)
62 * {
63 * // Implementation Here
64 * }
65 * \endcode
66 */
67
68 /** @defgroup Group_Scheduler Simple Task Scheduler - LUFA/Scheduler/Scheduler.h
69 *
70 * Simple round-robbin task scheduler. See Scheduler.h description for more details.
71 *
72 * @{
73 */
74
75 #ifndef __SCHEDULER_H__
76 #define __SCHEDULER_H__
77
78 /* Includes: */
79 #include <avr/io.h>
80 #include <stdbool.h>
81
82 #include <util/atomic.h>
83
84 #include "../Common/Common.h"
85
86 /* Enable C linkage for C++ Compilers: */
87 #if defined(__cplusplus)
88 extern "C" {
89 #endif
90
91 /* Public Interface - May be used in end-application: */
92 /* Macros: */
93 /** Creates a new scheduler task body or prototype. Should be used in the form:
94 * \code
95 * TASK(TaskName); // Prototype
96 *
97 * TASK(TaskName)
98 * {
99 * // Task body
100 * }
101 * \endcode
102 */
103 #define TASK(name) void name (void)
104
105 /** Defines a task list array, containing one or more task entries of the type TaskEntry_t. Each task list
106 * should be encased in curly braces and ended with a comma.
107 *
108 * Usage Example:
109 * \code
110 * TASK_LIST
111 * {
112 * { Task: MyTask1, TaskStatus: TASK_RUN, GroupID: 1 },
113 * // More task entries here
114 * }
115 * \endcode
116 */
117 #define TASK_LIST extern TaskEntry_t Scheduler_TaskList[]; TaskEntry_t Scheduler_TaskList[] =
118
119 /** Constant, giving the maximum delay in scheduler ticks which can be stored in a variable of type
120 * SchedulerDelayCounter_t.
121 */
122 #define TASK_MAX_DELAY (MAX_DELAYCTR_COUNT - 1)
123
124 /** Task status mode constant, for passing to Scheduler_SetTaskMode() or Scheduler_SetGroupTaskMode(). */
125 #define TASK_RUN true
126
127 /** Task status mode constant, for passing to Scheduler_SetTaskMode() or Scheduler_SetGroupTaskMode(). */
128 #define TASK_STOP false
129
130 /** Starts the scheduler in its infinite loop, executing running tasks. This should be placed at the end
131 * of the user application's main() function, as it can never return to the calling function.
132 */
133 #define Scheduler_Start() Scheduler_GoSchedule(TOTAL_TASKS);
134
135 /** Initializes the scheduler so that the scheduler functions can be called before the scheduler itself
136 * is started. This must be executed before any scheduler function calls other than Scheduler_Start(),
137 * and can be omitted if no such functions could be called before the scheduler is started.
138 */
139 #define Scheduler_Init() Scheduler_InitScheduler(TOTAL_TASKS);
140
141 /* Type Defines: */
142 /** Type define for a pointer to a scheduler task. */
143 typedef void (*TaskPtr_t)(void);
144
145 /** Type define for a variable which can hold a tick delay value for the scheduler up to the maximum delay
146 * possible.
147 */
148 typedef uint16_t SchedulerDelayCounter_t;
149
150 /** Structure for holding a single task's information in the scheduler task list. */
151 typedef struct
152 {
153 TaskPtr_t Task; /**< Pointer to the task to execute. */
154 bool TaskStatus; /**< Status of the task (either TASK_RUN or TASK_STOP). */
155 uint8_t GroupID; /**< Group ID of the task so that its status can be changed as a group. */
156 } TaskEntry_t;
157
158 /* Global Variables: */
159 /** Task entry list, containing the scheduler tasks, task statuses and group IDs. Each entry is of type
160 * TaskEntry_t and can be manipulated as desired, although it is preferential that the proper Scheduler
161 * functions should be used instead of direct manipulation.
162 */
163 extern TaskEntry_t Scheduler_TaskList[];
164
165 /** Contains the total number of tasks in the task list, irrespective of if the task's status is set to
166 * TASK_RUN or TASK_STOP.
167 *
168 * \note This value should be treated as read-only, and never altered in user-code.
169 */
170 extern volatile uint8_t Scheduler_TotalTasks;
171
172 /** Contains the current scheduler tick count, for use with the delay functions. If the delay functions
173 * are used in the user code, this should be incremented each tick period so that the delays can be
174 * calculated.
175 */
176 extern volatile SchedulerDelayCounter_t Scheduler_TickCounter;
177
178 /* Inline Functions: */
179 /** Resets the delay counter value to the current tick count. This should be called to reset the period
180 * for a delay in a task which is dependant on the current tick value.
181 *
182 * \param DelayCounter Counter which is storing the starting tick count for a given delay.
183 */
184 static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter)
185 ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
186 static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter)
187 {
188 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
189 {
190 *DelayCounter = Scheduler_TickCounter;
191 }
192 }
193
194 /* Function Prototypes: */
195 /** Determines if the given tick delay has elapsed, based on the given .
196 *
197 * \param Delay The delay to test for, measured in ticks
198 * \param DelayCounter The counter which is storing the starting tick value for the delay
199 *
200 * \return Boolean true if the delay has elapsed, false otherwise
201 *
202 * Usage Example:
203 * \code
204 * static SchedulerDelayCounter_t DelayCounter = 10000; // Force immediate run on start-up
205 *
206 * // Task runs every 10000 ticks, 10 seconds for this demo
207 * if (Scheduler_HasDelayElapsed(10000, &DelayCounter))
208 * {
209 * // Code to execute after delay interval elapsed here
210 * }
211 * \endcode
212 */
213 bool Scheduler_HasDelayElapsed(const uint16_t Delay,
214 SchedulerDelayCounter_t* const DelayCounter)
215 ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(2);
216
217 /** Sets the task mode for a given task.
218 *
219 * \param Task Name of the task whose status is to be changed
220 * \param TaskStatus New task status for the task (TASK_RUN or TASK_STOP)
221 */
222 void Scheduler_SetTaskMode(const TaskPtr_t Task, const bool TaskStatus);
223
224 /** Sets the task mode for a given task group ID, allowing for an entire group of tasks to have their
225 * statuses changed at once.
226 *
227 * \param GroupID Value of the task group ID whose status is to be changed
228 * \param TaskStatus New task status for tasks in the specified group (TASK_RUN or TASK_STOP)
229 */
230 void Scheduler_SetGroupTaskMode(const uint8_t GroupID, const bool TaskStatus);
231
232 /* Private Interface - For use in library only: */
233 #if !defined(__DOXYGEN__)
234 /* Macros: */
235 #define TOTAL_TASKS (sizeof(Scheduler_TaskList) / sizeof(TaskEntry_t))
236 #define MAX_DELAYCTR_COUNT 0xFFFF
237
238 /* Inline Functions: */
239 static inline void Scheduler_InitScheduler(const uint8_t TotalTasks) ATTR_ALWAYS_INLINE;
240 static inline void Scheduler_InitScheduler(const uint8_t TotalTasks)
241 {
242 Scheduler_TotalTasks = TotalTasks;
243 }
244
245 static inline void Scheduler_GoSchedule(const uint8_t TotalTasks) ATTR_NO_RETURN ATTR_ALWAYS_INLINE;
246 static inline void Scheduler_GoSchedule(const uint8_t TotalTasks)
247 {
248 Scheduler_InitScheduler(TotalTasks);
249
250 for (;;)
251 {
252 TaskEntry_t* CurrTask = &Scheduler_TaskList[0];
253
254 while (CurrTask != &Scheduler_TaskList[TotalTasks])
255 {
256 if (CurrTask->TaskStatus == TASK_RUN)
257 CurrTask->Task();
258
259 CurrTask++;
260 }
261 }
262 }
263 #endif
264
265 /* Disable C linkage for C++ Compilers: */
266 #if defined(__cplusplus)
267 }
268 #endif
269
270 #endif
271
272 /** @} */