ed049711557001657c9b4bc9a054dbb50e31c511
[pub/USBasp.git] / LUFA / Scheduler / Scheduler.h
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2010.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2010 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
47 *
48 * \section 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 return, thus each task should have persistent data marked with the static attribute.
53 *
54 * Usage Example:
55 * \code
56 * #include <LUFA/Scheduler/Scheduler.h>
57 *
58 * TASK(MyTask1);
59 * TASK(MyTask2);
60 *
61 * TASK_LIST
62 * {
63 * { .Task = MyTask1, .TaskStatus = TASK_RUN, .GroupID = 1 },
64 * { .Task = MyTask2, .TaskStatus = TASK_RUN, .GroupID = 1 },
65 * }
66 *
67 * int main(void)
68 * {
69 * Scheduler_Start();
70 * }
71 *
72 * TASK(MyTask1)
73 * {
74 * // Implementation Here
75 * }
76 *
77 * TASK(MyTask2)
78 * {
79 * // Implementation Here
80 * }
81 * \endcode
82 *
83 * @{
84 */
85
86 #ifndef __SCHEDULER_H__
87 #define __SCHEDULER_H__
88
89 /* Includes: */
90 #include <avr/io.h>
91 #include <stdbool.h>
92
93 #include <util/atomic.h>
94
95 #include "../Common/Common.h"
96
97 /* Enable C linkage for C++ Compilers: */
98 #if defined(__cplusplus)
99 extern "C" {
100 #endif
101
102 /* Public Interface - May be used in end-application: */
103 /* Macros: */
104 /** Creates a new scheduler task body or prototype. Should be used in the form:
105 * \code
106 * TASK(TaskName); // Prototype
107 *
108 * TASK(TaskName)
109 * {
110 * // Task body
111 * }
112 * \endcode
113 */
114 #define TASK(name) void name (void)
115
116 /** Defines a task list array, containing one or more task entries of the type TaskEntry_t. Each task list
117 * should be encased in curly braces and ended with a comma.
118 *
119 * Usage Example:
120 * \code
121 * TASK_LIST
122 * {
123 * { .Task = MyTask1, .TaskStatus = TASK_RUN, .GroupID = 1 },
124 * // More task entries here
125 * }
126 * \endcode
127 */
128 #define TASK_LIST TaskEntry_t Scheduler_TaskList[] =
129
130 /** Constant, giving the maximum delay in scheduler ticks which can be stored in a variable of type
131 * SchedulerDelayCounter_t.
132 */
133 #define TASK_MAX_DELAY (MAX_DELAYCTR_COUNT - 1)
134
135 /** Task status mode constant, for passing to Scheduler_SetTaskMode() or Scheduler_SetGroupTaskMode(). */
136 #define TASK_RUN true
137
138 /** Task status mode constant, for passing to Scheduler_SetTaskMode() or Scheduler_SetGroupTaskMode(). */
139 #define TASK_STOP false
140
141 /* Pseudo-Function Macros: */
142 #if defined(__DOXYGEN__)
143 /** Starts the scheduler in its infinite loop, executing running tasks. This should be placed at the end
144 * of the user application's main() function, as it can never return to the calling function.
145 */
146 void Scheduler_Start(void);
147
148 /** Initializes the scheduler so that the scheduler functions can be called before the scheduler itself
149 * is started. This must be executed before any scheduler function calls other than Scheduler_Start(),
150 * and can be omitted if no such functions could be called before the scheduler is started.
151 */
152 void Scheduler_Init(void);
153 #else
154 #define Scheduler_Start() Scheduler_GoSchedule(TOTAL_TASKS);
155
156 #define Scheduler_Init() Scheduler_InitScheduler(TOTAL_TASKS);
157 #endif
158
159 /* Type Defines: */
160 /** Type define for a pointer to a scheduler task. */
161 typedef void (*TaskPtr_t)(void);
162
163 /** Type define for a variable which can hold a tick delay value for the scheduler up to the maximum delay
164 * possible.
165 */
166 typedef uint16_t SchedulerDelayCounter_t;
167
168 /** Structure for holding a single task's information in the scheduler task list. */
169 typedef struct
170 {
171 TaskPtr_t Task; /**< Pointer to the task to execute. */
172 bool TaskStatus; /**< Status of the task (either TASK_RUN or TASK_STOP). */
173 uint8_t GroupID; /**< Group ID of the task so that its status can be changed as a group. */
174 } TaskEntry_t;
175
176 /* Global Variables: */
177 /** Task entry list, containing the scheduler tasks, task statuses and group IDs. Each entry is of type
178 * TaskEntry_t and can be manipulated as desired, although it is preferential that the proper Scheduler
179 * functions should be used instead of direct manipulation.
180 */
181 extern TaskEntry_t Scheduler_TaskList[];
182
183 /** Contains the total number of tasks in the task list, irrespective of if the task's status is set to
184 * TASK_RUN or TASK_STOP.
185 *
186 * \note This value should be treated as read-only, and never altered in user-code.
187 */
188 extern volatile uint8_t Scheduler_TotalTasks;
189
190 /** Contains the current scheduler tick count, for use with the delay functions. If the delay functions
191 * are used in the user code, this should be incremented each tick period so that the delays can be
192 * calculated.
193 */
194 extern volatile SchedulerDelayCounter_t Scheduler_TickCounter;
195
196 /* Inline Functions: */
197 /** Resets the delay counter value to the current tick count. This should be called to reset the period
198 * for a delay in a task which is dependant on the current tick value.
199 *
200 * \param[out] DelayCounter Counter which is storing the starting tick count for a given delay.
201 */
202 static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter)
203 ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
204 static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter)
205 {
206 ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
207 {
208 *DelayCounter = Scheduler_TickCounter;
209 }
210 }
211
212 /* Function Prototypes: */
213 /** Determines if the given tick delay has elapsed, based on the given .
214 *
215 * \param[in] Delay The delay to test for, measured in ticks
216 * \param[in] DelayCounter The counter which is storing the starting tick value for the delay
217 *
218 * \return Boolean true if the delay has elapsed, false otherwise
219 *
220 * Usage Example:
221 * \code
222 * static SchedulerDelayCounter_t DelayCounter = 10000; // Force immediate run on start-up
223 *
224 * // Task runs every 10000 ticks, 10 seconds for this demo
225 * if (Scheduler_HasDelayElapsed(10000, &DelayCounter))
226 * {
227 * // Code to execute after delay interval elapsed here
228 * }
229 * \endcode
230 */
231 bool Scheduler_HasDelayElapsed(const uint16_t Delay,
232 SchedulerDelayCounter_t* const DelayCounter)
233 ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(2);
234
235 /** Sets the task mode for a given task.
236 *
237 * \param[in] Task Name of the task whose status is to be changed
238 * \param[in] TaskStatus New task status for the task (TASK_RUN or TASK_STOP)
239 */
240 void Scheduler_SetTaskMode(const TaskPtr_t Task, const bool TaskStatus);
241
242 /** Sets the task mode for a given task group ID, allowing for an entire group of tasks to have their
243 * statuses changed at once.
244 *
245 * \param[in] GroupID Value of the task group ID whose status is to be changed
246 * \param[in] TaskStatus New task status for tasks in the specified group (TASK_RUN or TASK_STOP)
247 */
248 void Scheduler_SetGroupTaskMode(const uint8_t GroupID, const bool TaskStatus);
249
250 /* Private Interface - For use in library only: */
251 #if !defined(__DOXYGEN__)
252 /* Macros: */
253 #define TOTAL_TASKS (sizeof(Scheduler_TaskList) / sizeof(TaskEntry_t))
254 #define MAX_DELAYCTR_COUNT 0xFFFF
255
256 /* Inline Functions: */
257 static inline void Scheduler_InitScheduler(const uint8_t TotalTasks) ATTR_ALWAYS_INLINE;
258 static inline void Scheduler_InitScheduler(const uint8_t TotalTasks)
259 {
260 Scheduler_TotalTasks = TotalTasks;
261 }
262
263 static inline void Scheduler_GoSchedule(const uint8_t TotalTasks) ATTR_NO_RETURN ATTR_ALWAYS_INLINE ATTR_DEPRECATED;
264 static inline void Scheduler_GoSchedule(const uint8_t TotalTasks)
265 {
266 Scheduler_InitScheduler(TotalTasks);
267
268 for (;;)
269 {
270 TaskEntry_t* CurrTask = &Scheduler_TaskList[0];
271
272 while (CurrTask != &Scheduler_TaskList[TotalTasks])
273 {
274 if (CurrTask->TaskStatus == TASK_RUN)
275 CurrTask->Task();
276
277 CurrTask++;
278 }
279 }
280 }
281 #endif
282
283 /* Disable C linkage for C++ Compilers: */
284 #if defined(__cplusplus)
285 }
286 #endif
287
288 #endif
289
290 /** @} */