Add new ARCH option to the makefiles to (eventually) specify the target device archit...
[pub/USBasp.git] / LUFA / Scheduler / Scheduler.h
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2011.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all 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 * \brief Simple round-robbin pseudo-task scheduler.
33 *
34 * Simple round-robbin cooperative scheduler for use in basic projects where non real-time tasks need
35 * to be executed. Each task is executed in sequence, and can be enabled or disabled individually or as a group.
36 *
37 * \deprecated This module is deprecated and will be removed in a future library release.
38 */
39
40 /** \defgroup Group_Scheduler Simple Task Scheduler - LUFA/Scheduler/Scheduler.h
41 *
42 * \deprecated This module is deprecated and will be removed in a future library release.
43 *
44 * \section Sec_Dependencies Module Source Dependencies
45 * The following files must be built with any user project that uses this module:
46 * - LUFA/Scheduler/Scheduler.c <i>(Makefile source module name: LUFA_SRC_SCHEDULER)</i>
47 *
48 * \section Sec_ModDescription Module Description
49 * Simple round-robbin cooperative scheduler for use in basic projects where non real-time tasks need
50 * to be executed. Each task is executed in sequence, and can be enabled or disabled individually or as a group.
51 *
52 * For a task to yield it must \c return, thus each task should have persistent data marked with the \c static keyword.
53 *
54 * Each LUFA scheduler task should be written similar to an ISR; it should execute quickly (so that no one task
55 * hogs the processor, preventing another from running before some sort of timeout is exceeded). Unlike normal RTOS
56 * tasks, each LUFA scheduler task is a regular function, and thus must be designed to be called, and designed to
57 * return to the calling scheduler function repeatedly. Data which must be preserved between task calls should be
58 * declared as global or (preferably) as a \c static local variable inside the task.
59 *
60 * The scheduler consists of a task list, listing all the tasks which can be executed by the scheduler. Once started,
61 * each task is then called one after another, unless the task is stopped by another running task or interrupt.
62 *
63 * Usage Example:
64 * \code
65 * #include <LUFA/Scheduler/Scheduler.h>
66 *
67 * TASK(MyTask1); // Task prototype
68 * TASK(MyTask2); // Task prototype
69 *
70 * TASK_LIST
71 * {
72 * { .Task = MyTask1, .TaskStatus = TASK_RUN, .GroupID = 1 },
73 * { .Task = MyTask2, .TaskStatus = TASK_RUN, .GroupID = 1 },
74 * }
75 *
76 * int main(void)
77 * {
78 * Scheduler_Init();
79 *
80 * // Other initialisation here
81 *
82 * Scheduler_Start();
83 * }
84 *
85 * TASK(MyTask1)
86 * {
87 * // Task implementation here
88 * }
89 *
90 * TASK(MyTask2)
91 * {
92 * // Task implementation here
93 * }
94 * \endcode
95 *
96 * If desired, the LUFA scheduler <b>does not need to be used</b> in a LUFA powered application. A more conventional
97 * approach to application design can be used, or a proper scheduling RTOS inserted in the place of the LUFA scheduler.
98 * In the case of the former the USB task must be run manually repeatedly to maintain USB communications, and in the
99 * case of the latter a proper RTOS task must be set up to do the same.
100 *
101 * @{
102 */
103
104 #ifndef __SCHEDULER_H__
105 #define __SCHEDULER_H__
106
107 /* Includes: */
108 #include "../Common/Common.h"
109
110 /* Enable C linkage for C++ Compilers: */
111 #if defined(__cplusplus)
112 extern "C" {
113 #endif
114
115 /* Public Interface - May be used in end-application: */
116 /* Macros: */
117 /** Creates a new scheduler task body or prototype. Should be used in the form:
118 * \code
119 * TASK(TaskName); // Prototype
120 *
121 * TASK(TaskName)
122 * {
123 * // Task body
124 * }
125 * \endcode
126 */
127 #define TASK(name) void name (void)
128
129 /** Defines a task list array, containing one or more task entries of the type \ref TaskEntry_t. Each task list
130 * should be encased in curly braces and ended with a comma.
131 *
132 * Usage Example:
133 * \code
134 * TASK_LIST
135 * {
136 * { .Task = MyTask1, .TaskStatus = TASK_RUN, .GroupID = 1 },
137 * // More task entries here
138 * }
139 * \endcode
140 */
141 #define TASK_LIST TaskEntry_t Scheduler_TaskList[] =
142
143 /** Constant, giving the maximum delay in scheduler ticks which can be stored in a variable of type
144 * \ref SchedulerDelayCounter_t.
145 */
146 #define TASK_MAX_DELAY (MAX_DELAYCTR_COUNT - 1)
147
148 /** Task status mode constant, for passing to \ref Scheduler_SetTaskMode() or \ref Scheduler_SetGroupTaskMode(). */
149 #define TASK_RUN true
150
151 /** Task status mode constant, for passing to \ref Scheduler_SetTaskMode() or \ref Scheduler_SetGroupTaskMode(). */
152 #define TASK_STOP false
153
154 /* Pseudo-Function Macros: */
155 #if defined(__DOXYGEN__)
156 /** Starts the scheduler in its infinite loop, executing running tasks. This should be placed at the end
157 * of the user application's \c main() function, as it can never return to the calling function.
158 */
159 void Scheduler_Start(void);
160
161 /** Initialises the scheduler so that the scheduler functions can be called before the scheduler itself
162 * is started. This must be executed before any scheduler function calls other than \ref Scheduler_Start(),
163 * and can be omitted if no such functions could be called before the scheduler is started.
164 */
165 void Scheduler_Init(void);
166 #else
167 #define Scheduler_Start() Scheduler_GoSchedule(TOTAL_TASKS);
168 #define Scheduler_Init() Scheduler_InitScheduler(TOTAL_TASKS);
169 #endif
170
171 /* Type Defines: */
172 /** Type define for a pointer to a scheduler task. */
173 typedef void (*TaskPtr_t)(void);
174
175 /** Type define for a variable which can hold a tick delay value for the scheduler up to the maximum delay
176 * possible.
177 */
178 typedef uint_least16_t SchedulerDelayCounter_t;
179
180 /** \brief Scheduler Task List Entry Structure.
181 *
182 * Structure for holding a single task's information in the scheduler task list.
183 */
184 typedef struct
185 {
186 TaskPtr_t Task; /**< Pointer to the task to execute. */
187 bool TaskStatus; /**< Status of the task (either TASK_RUN or TASK_STOP). */
188 uint_least8_t GroupID; /**< Group ID of the task so that its status can be changed as a group. */
189 } TaskEntry_t;
190
191 /* Global Variables: */
192 /** Task entry list, containing the scheduler tasks, task statuses and group IDs. Each entry is of type
193 * \ref TaskEntry_t and can be manipulated as desired, although it is preferred that the proper Scheduler
194 * functions should be used instead of direct manipulation.
195 */
196 extern TaskEntry_t Scheduler_TaskList[];
197
198 /** Contains the total number of tasks in the task list, irrespective of if the task's status is set to
199 * \ref TASK_RUN or \ref TASK_STOP.
200 *
201 * \note This value should be treated as read-only, and never altered in user-code.
202 */
203 extern volatile uint_least8_t Scheduler_TotalTasks;
204
205 /** Contains the current scheduler tick count, for use with the delay functions. If the delay functions
206 * are used in the user code, this should be incremented each tick period so that the delays can be
207 * calculated.
208 */
209 extern volatile SchedulerDelayCounter_t Scheduler_TickCounter;
210
211 /* Inline Functions: */
212 /** Resets the delay counter value to the current tick count. This should be called to reset the period
213 * for a delay in a task which is dependant on the current tick value.
214 *
215 * \param[out] DelayCounter Counter which is storing the starting tick count for a given delay.
216 */
217 static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter)
218 ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
219 static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter)
220 {
221 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
222 {
223 *DelayCounter = Scheduler_TickCounter;
224 }
225 }
226
227 /* Function Prototypes: */
228 /** Determines if the given tick delay has elapsed, based on the given delay period and tick counter value.
229 *
230 * \param[in] Delay The delay to test for, measured in ticks.
231 * \param[in] DelayCounter The counter which is storing the starting tick value for the delay.
232 *
233 * \return Boolean \c true if the delay has elapsed, \c false otherwise.
234 *
235 * Usage Example:
236 * \code
237 * static SchedulerDelayCounter_t DelayCounter = 10000; // Force immediate run on start-up
238 *
239 * // Task runs every 10000 ticks, 10 seconds for this demo
240 * if (Scheduler_HasDelayElapsed(10000, &DelayCounter))
241 * {
242 * // Code to execute after delay interval elapsed here
243 * }
244 * \endcode
245 */
246 bool Scheduler_HasDelayElapsed(const uint_least16_t Delay,
247 SchedulerDelayCounter_t* const DelayCounter)
248 ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(2);
249
250 /** Sets the task mode for a given task.
251 *
252 * \param[in] Task Name of the task whose status is to be changed.
253 * \param[in] TaskStatus New task status for the task (\ref TASK_RUN or \ref TASK_STOP).
254 */
255 void Scheduler_SetTaskMode(const TaskPtr_t Task,
256 const bool TaskStatus);
257
258 /** Sets the task mode for a given task group ID, allowing for an entire group of tasks to have their
259 * statuses changed at once.
260 *
261 * \param[in] GroupID Value of the task group ID whose status is to be changed.
262 * \param[in] TaskStatus New task status for tasks in the specified group (\ref TASK_RUN or \ref TASK_STOP).
263 */
264 void Scheduler_SetGroupTaskMode(const uint_least8_t GroupID,
265 const bool TaskStatus);
266
267 /* Private Interface - For use in library only: */
268 #if !defined(__DOXYGEN__)
269 /* Macros: */
270 #define TOTAL_TASKS (sizeof(Scheduler_TaskList) / sizeof(TaskEntry_t))
271 #define MAX_DELAYCTR_COUNT UINT_LEAST16_MAX
272
273 /* Inline Functions: */
274 static inline void Scheduler_InitScheduler(const uint_least8_t TotalTasks) ATTR_ALWAYS_INLINE;
275 static inline void Scheduler_InitScheduler(const uint_least8_t TotalTasks)
276 {
277 Scheduler_TotalTasks = TotalTasks;
278 }
279
280 static inline void Scheduler_GoSchedule(const uint_least8_t TotalTasks)
281 ATTR_NO_RETURN ATTR_ALWAYS_INLINE ATTR_DEPRECATED;
282 static inline void Scheduler_GoSchedule(const uint_least8_t TotalTasks)
283 {
284 Scheduler_InitScheduler(TotalTasks);
285
286 for (;;)
287 {
288 TaskEntry_t* CurrTask = &Scheduler_TaskList[0];
289
290 while (CurrTask != &Scheduler_TaskList[TotalTasks])
291 {
292 if (CurrTask->TaskStatus == TASK_RUN)
293 CurrTask->Task();
294
295 CurrTask++;
296 }
297 }
298 }
299 #endif
300
301 /* Disable C linkage for C++ Compilers: */
302 #if defined(__cplusplus)
303 }
304 #endif
305
306 #endif
307
308 /** @} */
309