Statistics
| Branch: | Tag: | Revision:

root / LUFA / Scheduler / Scheduler.h @ 978b99e5

History | View | Annotate | Download (12.3 KB)

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
 *  \brief Simple round-robbin pseudo-task scheduler.
42
 *
43
 *  \deprecated This module is deprecated and will be removed in a future library release.
44
 *
45
 *  \section Sec_Dependencies Module Source Dependencies
46
 *  The following files must be built with any user project that uses this module:
47
 *    - LUFA/Scheduler/Scheduler.c <i>(Makefile source module name: LUFA_SRC_SCHEDULER)</i>
48
 *
49
 *  \section Sec_ModDescription Module Description
50
 *  Simple round-robbin cooperative scheduler for use in basic projects where non real-time tasks need
51
 *  to be executed. Each task is executed in sequence, and can be enabled or disabled individually or as a group.
52
 *
53
 *  For a task to yield it must \c return, thus each task should have persistent data marked with the \c static keyword.
54
 *
55
 *  Each LUFA scheduler task should be written similar to an ISR; it should execute quickly (so that no one task
56
 *  hogs the processor, preventing another from running before some sort of timeout is exceeded). Unlike normal RTOS
57
 *  tasks, each LUFA scheduler task is a regular function, and thus must be designed to be called, and designed to
58
 *  return to the calling scheduler function repeatedly. Data which must be preserved between task calls should be
59
 *  declared as global or (preferably) as a \c static local variable inside the task.
60
 *
61
 *  The scheduler consists of a task list, listing all the tasks which can be executed by the scheduler. Once started,
62
 *  each task is then called one after another, unless the task is stopped by another running task or interrupt.
63
 *
64
 *  Usage Example:
65
 *  \code
66
 *      #include <LUFA/Scheduler/Scheduler.h>
67
 *
68
 *      TASK(MyTask1); // Task prototype
69
 *      TASK(MyTask2); // Task prototype
70
 *
71
 *      TASK_LIST
72
 *      {
73
 *          { .Task = MyTask1, .TaskStatus = TASK_RUN, .GroupID = 1  },
74
 *          { .Task = MyTask2, .TaskStatus = TASK_RUN, .GroupID = 1  },
75
 *      }
76
 *
77
 *      int main(void)
78
 *      {
79
 *          Scheduler_Init();
80
 *
81
 *          // Other initialisation here
82
 *
83
 *          Scheduler_Start();
84
 *      }
85
 *
86
 *      TASK(MyTask1)
87
 *      {
88
 *          // Task implementation here
89
 *      }
90
 *
91
 *      TASK(MyTask2)
92
 *      {
93
 *          // Task implementation here
94
 *      }
95
 *  \endcode
96
 *
97
 *  If desired, the LUFA scheduler <b>does not need to be used</b> in a LUFA powered application. A more conventional
98
 *  approach to application design can be used, or a proper scheduling RTOS inserted in the place of the LUFA scheduler.
99
 *  In the case of the former the USB task must be run manually repeatedly to maintain USB communications, and in the
100
 *  case of the latter a proper RTOS task must be set up to do the same.
101
 *
102
 *  @{
103
 */
104

    
105
#ifndef __SCHEDULER_H__
106
#define __SCHEDULER_H__
107

    
108
        /* Includes: */
109
                #include "../Common/Common.h"
110

    
111
        /* Enable C linkage for C++ Compilers: */
112
                #if defined(__cplusplus)
113
                        extern "C" {
114
                #endif
115

    
116
        /* Public Interface - May be used in end-application: */
117
                /* Macros: */
118
                        /** Creates a new scheduler task body or prototype. Should be used in the form:
119
                         *  \code
120
                         *      TASK(TaskName); // Prototype
121
                         *
122
                         *      TASK(TaskName)
123
                         *      {
124
                         *           // Task body
125
                         *      }
126
                         *  \endcode
127
                         */
128
                        #define TASK(name)              void name (void)
129

    
130
                        /** Defines a task list array, containing one or more task entries of the type \ref TaskEntry_t. Each task list
131
                         *  should be encased in curly braces and ended with a comma.
132
                         *
133
                         *  Usage Example:
134
                         *  \code
135
                         *      TASK_LIST
136
                         *      {
137
                         *           { .Task = MyTask1, .TaskStatus = TASK_RUN, .GroupID = 1 },
138
                         *           // More task entries here
139
                         *      }
140
                         *  \endcode
141
                         */
142
                        #define TASK_LIST               TaskEntry_t Scheduler_TaskList[] =
143

    
144
                        /** Constant, giving the maximum delay in scheduler ticks which can be stored in a variable of type
145
                         *  \ref SchedulerDelayCounter_t.
146
                         */
147
                        #define TASK_MAX_DELAY          (MAX_DELAYCTR_COUNT - 1)
148

    
149
                        /** Task status mode constant, for passing to \ref Scheduler_SetTaskMode() or \ref Scheduler_SetGroupTaskMode(). */
150
                        #define TASK_RUN                true
151

    
152
                        /** Task status mode constant, for passing to \ref Scheduler_SetTaskMode() or \ref Scheduler_SetGroupTaskMode(). */
153
                        #define TASK_STOP               false
154

    
155
                /* Pseudo-Function Macros: */
156
                        #if defined(__DOXYGEN__)
157
                                /** Starts the scheduler in its infinite loop, executing running tasks. This should be placed at the end
158
                                 *  of the user application's \c main() function, as it can never return to the calling function.
159
                                 */
160
                                void Scheduler_Start(void);
161

    
162
                                /** Initialises the scheduler so that the scheduler functions can be called before the scheduler itself
163
                                 *  is started. This must be executed before any scheduler function calls other than \ref Scheduler_Start(),
164
                                 *  and can be omitted if no such functions could be called before the scheduler is started.
165
                                 */
166
                                void Scheduler_Init(void);
167
                        #else
168
                                #define Scheduler_Start()    Scheduler_GoSchedule(TOTAL_TASKS);
169
                                #define Scheduler_Init()     Scheduler_InitScheduler(TOTAL_TASKS);
170
                        #endif
171

    
172
                /* Type Defines: */
173
                        /** Type define for a pointer to a scheduler task. */
174
                        typedef void (*TaskPtr_t)(void);
175

    
176
                        /** Type define for a variable which can hold a tick delay value for the scheduler up to the maximum delay
177
                         *  possible.
178
                         */
179
                        typedef uint_least16_t SchedulerDelayCounter_t;
180

    
181
                        /** \brief Scheduler Task List Entry Structure.
182
                         *
183
                         *  Structure for holding a single task's information in the scheduler task list.
184
                         */
185
                        typedef struct
186
                        {
187
                                TaskPtr_t     Task;       /**< Pointer to the task to execute. */
188
                                bool          TaskStatus; /**< Status of the task (either TASK_RUN or TASK_STOP). */
189
                                uint_least8_t GroupID;    /**< Group ID of the task so that its status can be changed as a group. */
190
                        } TaskEntry_t;
191

    
192
                /* Global Variables: */
193
                        /** Task entry list, containing the scheduler tasks, task statuses and group IDs. Each entry is of type
194
                         *  \ref TaskEntry_t and can be manipulated as desired, although it is preferred that the proper Scheduler
195
                         *  functions should be used instead of direct manipulation.
196
                         */
197
                        extern TaskEntry_t Scheduler_TaskList[];
198

    
199
                        /** Contains the total number of tasks in the task list, irrespective of if the task's status is set to
200
                         *  \ref TASK_RUN or \ref TASK_STOP.
201
                         *
202
                         *  \note This value should be treated as read-only, and never altered in user-code.
203
                         */
204
                        extern volatile uint_least8_t Scheduler_TotalTasks;
205

    
206
                        /**  Contains the current scheduler tick count, for use with the delay functions. If the delay functions
207
                         *   are used in the user code, this should be incremented each tick period so that the delays can be
208
                         *   calculated.
209
                         */
210
                        extern volatile SchedulerDelayCounter_t Scheduler_TickCounter;
211

    
212
                /* Inline Functions: */
213
                        /** Resets the delay counter value to the current tick count. This should be called to reset the period
214
                         *  for a delay in a task which is dependant on the current tick value.
215
                         *
216
                         *  \param[out] DelayCounter  Counter which is storing the starting tick count for a given delay.
217
                         */
218
                        static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter)
219
                                                                ATTR_NON_NULL_PTR_ARG(1) ATTR_ALWAYS_INLINE;
220
                        static inline void Scheduler_ResetDelay(SchedulerDelayCounter_t* const DelayCounter)
221
                        {
222
                                uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask();
223
                                GlobalInterruptDisable();
224

    
225
                                *DelayCounter = Scheduler_TickCounter;
226

    
227
                                SetGlobalInterruptMask(CurrentGlobalInt);
228
                        }
229

    
230
                /* Function Prototypes: */
231
                        /** Determines if the given tick delay has elapsed, based on the given delay period and tick counter value.
232
                         *
233
                         *  \param[in] Delay         The delay to test for, measured in ticks.
234
                         *  \param[in] DelayCounter  The counter which is storing the starting tick value for the delay.
235
                         *
236
                         *  \return Boolean \c true if the delay has elapsed, \c false otherwise.
237
                         *
238
                         *  Usage Example:
239
                         *  \code
240
                         *      static SchedulerDelayCounter_t DelayCounter = 10000; // Force immediate run on start-up
241
                         *
242
                         *      // Task runs every 10000 ticks, 10 seconds for this demo
243
                         *      if (Scheduler_HasDelayElapsed(10000, &DelayCounter))
244
                         *      {
245
                         *           // Code to execute after delay interval elapsed here
246
                         *      }
247
                         *  \endcode
248
                         */
249
                        bool Scheduler_HasDelayElapsed(const uint_least16_t Delay,
250
                                                       SchedulerDelayCounter_t* const DelayCounter)
251
                                                       ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(2);
252

    
253
                        /** Sets the task mode for a given task.
254
                         *
255
                         *  \param[in] Task        Name of the task whose status is to be changed.
256
                         *  \param[in] TaskStatus  New task status for the task (\ref TASK_RUN or \ref TASK_STOP).
257
                         */
258
                        void Scheduler_SetTaskMode(const TaskPtr_t Task,
259
                                                   const bool TaskStatus);
260

    
261
                        /** Sets the task mode for a given task group ID, allowing for an entire group of tasks to have their
262
                         *  statuses changed at once.
263
                         *
264
                         *  \param[in] GroupID     Value of the task group ID whose status is to be changed.
265
                         *  \param[in] TaskStatus  New task status for tasks in the specified group (\ref TASK_RUN or \ref TASK_STOP).
266
                         */
267
                        void Scheduler_SetGroupTaskMode(const uint_least8_t GroupID,
268
                                                        const bool TaskStatus);
269

    
270
        /* Private Interface - For use in library only: */
271
        #if !defined(__DOXYGEN__)
272
                /* Macros: */
273
                        #define TOTAL_TASKS                       (sizeof(Scheduler_TaskList) / sizeof(TaskEntry_t))
274
                        #define MAX_DELAYCTR_COUNT                UINT_LEAST16_MAX
275

    
276
                /* Inline Functions: */
277
                        static inline void Scheduler_InitScheduler(const uint_least8_t TotalTasks) ATTR_ALWAYS_INLINE;
278
                        static inline void Scheduler_InitScheduler(const uint_least8_t TotalTasks)
279
                        {
280
                                Scheduler_TotalTasks = TotalTasks;
281
                        }
282

    
283
                        static inline void Scheduler_GoSchedule(const uint_least8_t TotalTasks)
284
                                                                ATTR_NO_RETURN ATTR_ALWAYS_INLINE ATTR_DEPRECATED;
285
                        static inline void Scheduler_GoSchedule(const uint_least8_t TotalTasks)
286
                        {
287
                                Scheduler_InitScheduler(TotalTasks);
288

    
289
                                for (;;)
290
                                {
291
                                        TaskEntry_t* CurrTask = &Scheduler_TaskList[0];
292

    
293
                                        while (CurrTask != &Scheduler_TaskList[TotalTasks])
294
                                        {
295
                                                if (CurrTask->TaskStatus == TASK_RUN)
296
                                                  CurrTask->Task();
297

    
298
                                                CurrTask++;
299
                                        }
300
                                }
301
                        }
302
        #endif
303

    
304
        /* Disable C linkage for C++ Compilers: */
305
                #if defined(__cplusplus)
306
                        }
307
                #endif
308

    
309
#endif
310

    
311
/** @} */
312