update credits
[librepilot.git] / flight / pios / inc / pios_callbackscheduler.h
blob7fc883cad311e07788cbf916c51bcf3543bf03d2
1 /**
2 ******************************************************************************
4 * @file pios_callbackscheduler.h
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2014.
6 * @brief Include files of the PIOS_CALLBACKSCHEDULER
7 * @see The GNU Public License (GPL) Version 3
9 *****************************************************************************/
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19 * for more details.
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #ifndef PIOS_CALLBACKSCHEDULER_H
27 #define PIOS_CALLBACKSCHEDULER_H
29 // Public types
30 typedef enum {
31 CALLBACK_PRIORITY_CRITICAL = 0,
32 CALLBACK_PRIORITY_REGULAR = 1,
33 CALLBACK_PRIORITY_LOW = 2
34 } DelayedCallbackPriority;
35 // Use the CallbackPriority to define how frequent a callback needs to be
36 // called in relation to others in the same callback scheduling task.
37 // The scheduler will call callbacks waiting for execution with the same
38 // priority in a round robin way. However one slot in this queue is reserved
39 // for a chosen member of the next lower priority. This member will also be
40 // chosen in a round robin way.
41 // Example:
42 // Assume you have 6 callbacks in the same PriorityTask, all constantly wanting
43 // to be executed.
44 // A and B are priority CRITICAL,
45 // c and d are priority REGULAR,
46 // x and y are priority LOW.
47 // Then the execution schedule will look as follows:
48 // ...ABcABdABxABcABdAByABcABdABxABcABdABy...
49 // However if only the 3 callbacks, A, c and x want to execute, you will get:
50 // ...AcAxAcAxAcAxAcAxAcAxAcAxAcAxAcAxAcAx...
51 // And if only A and y need execution it will be:
52 // ...AyAyAyAyAyAyAyAyAyAyAyAyAyAyAyAyAyAy...
53 // despite their different priority they would get treated equally in this case.
55 // WARNING: Callbacks ALWAYS should return as quickly as possible. Otherwise
56 // a low priority callback can block a critical one from being executed.
57 // Callbacks MUST NOT block execution!
59 typedef enum {
60 CALLBACK_TASK_AUXILIARY = (tskIDLE_PRIORITY + 1),
61 CALLBACK_TASK_NAVIGATION = (tskIDLE_PRIORITY + 2),
62 CALLBACK_TASK_FLIGHTCONTROL = (tskIDLE_PRIORITY + 3),
63 CALLBACK_TASK_DEVICEDRIVER = (tskIDLE_PRIORITY + 4),
64 } DelayedCallbackPriorityTask;
65 // Use the PriorityTask to define the global importance of callback execution
66 // compared to other processes in the system.
67 // Callbacks dispatched in a higher PriorityTasks will halt the execution of
68 // any lower priority processes, including callbacks and even callback
69 // scheduling tasks until they are done!
70 // Assume you have two callbacks:
71 // A in priorityTask DEVICEDRIVER,
72 // b and c in priorityTask AUXILIARY,
73 // Then the execution schedule can look as follows: (| marks a task switch)
74 // <b ... /b><c ... |<A ... /A>| ... /c><b ...
75 // be aware that if A gets constantly dispatched this would look like this:
76 // <b ... |<A><A><A><A><A><A><A><A><A><A><A><A><A><A><A><A><A><A><A>...
78 // WARNING: Any higher priority task can prevent lower priority code from being
79 // executed! (This does not only apply to callbacks but to all FreeRTOS tasks!)
81 typedef enum {
82 CALLBACK_UPDATEMODE_NONE = 0,
83 CALLBACK_UPDATEMODE_SOONER = 1,
84 CALLBACK_UPDATEMODE_LATER = 2,
85 CALLBACK_UPDATEMODE_OVERRIDE = 3
86 } DelayedCallbackUpdateMode;
87 // When scheduling a callback for execution at a time in the future, use the
88 // update mode to define what should happen if the callback is already
89 // scheduled.
90 // With NONE, the schedule will not be updated and the callback will be
91 // executed at the original time.
92 // With SOONER, the closer of the two schedules will take precedence
93 // With LATER, the schedule more distant in the future will be used.
94 // With OVERRIDE, the original schedule will be discarded.
96 typedef void (*DelayedCallback)(void);
97 // Use this type for the callback function.
99 struct DelayedCallbackInfoStruct;
100 typedef struct DelayedCallbackInfoStruct DelayedCallbackInfo;
101 // Use a pointer to DelayedCallbackInfo as a handle to identify registered callbacks.
102 // be aware that the same callback function can be registered as a callback
103 // several times, even with different callback priorities and even
104 // priorityTasks, using different handles and as such different dispatch calls.
105 // Be aware that using different priorityTasks for the same callback function
106 // might cause your callback to be executed recursively in different task contexts!
108 // Public functions
112 * Initialize the scheduler
113 * must be called before any other functions are called
114 * \return Success (0), failure (-1)
116 int32_t PIOS_CALLBACKSCHEDULER_Initialize();
119 * Start all scheduler tasks
120 * Will instantiate all scheduler tasks registered so far. Although new
121 * callbacks CAN be registered beyond that point, any further scheduling tasks
122 * will be started the moment of instantiation. It is not possible to increase
123 * the STACK requirements of a scheduler task after this function has been
124 * run. No callbacks will be run before this function is called, although
125 * they can be marked for later execution by executing the dispatch function.
126 * \return Success (0), failure (-1)
128 int32_t PIOS_CALLBACKSCHEDULER_Start();
131 * Register a new callback to be called by a delayed callback scheduler task.
132 * If a scheduler task with the specified task priority does not exist yet, it
133 * will be created.
134 * \param[in] cb The callback to be invoked
135 * \param[in] priority Priority of the callback compared to other callbacks scheduled by the same delayed callback scheduler task.
136 * \param[in] priorityTask Task priority of the scheduler task. One scheduler task will be spawned for each distinct value specified, further callbacks created with the same priorityTask will all be handled by the same delayed callback scheduler task and scheduled according to their individual callback priorities
137 * \param[in] stacksize The stack requirements of the callback when called by the scheduler.
138 * \param[in] callbackID - CallbackInfoRunningElem from CallbackInfo UAVObject, unique identified to collect stats for the callback, -1 to ignore!
139 * \return CallbackInfo Pointer on success, NULL if failed.
141 DelayedCallbackInfo *PIOS_CALLBACKSCHEDULER_Create(
142 DelayedCallback cb,
143 DelayedCallbackPriority priority,
144 DelayedCallbackPriorityTask priorityTask,
145 int16_t callbackID,
146 uint32_t stacksize);
149 * Schedule dispatching a callback at some point in the future. The function returns immediately.
150 * \param[in] *cbinfo the callback handle
151 * \param[in] milliseconds How far in the future to dispatch the callback
152 * \param[in] updatemode What to do if the callback is already scheduled but not dispatched yet.
153 * The options are:
154 * UPDATEMODE_NONE: An existing schedule will not be touched, the call will have no effect at all if there's an existing schedule.
155 * UPDATEMODE_SOONER: The callback will be rescheduled only if the new schedule triggers before the original one would have triggered.
156 * UPDATEMODE_LATER: The callback will be rescheduled only if the new schedule triggers after the original one would have triggered.
157 * UPDATEMODE_OVERRIDE: The callback will be rescheduled in any case, effectively overriding any previous schedule. (sooner+later=override)
158 * \return 0: not scheduled, previous schedule takes precedence, 1: new schedule, 2: previous schedule overridden
160 int32_t PIOS_CALLBACKSCHEDULER_Schedule(
161 DelayedCallbackInfo *cbinfo,
162 int32_t milliseconds,
163 DelayedCallbackUpdateMode updatemode);
166 * Dispatch an event by invoking the supplied callback. The function
167 * returns immediately, the callback is invoked from the event task.
168 * \param[in] *cbinfo the callback handle
169 * \return Success (-1), failure (0)
171 int32_t PIOS_CALLBACKSCHEDULER_Dispatch(DelayedCallbackInfo *cbinfo);
174 * Dispatch an event by invoking the supplied callback. The function
175 * returns immediately, the callback is invoked from the event task.
176 * \param[in] *cbinfo the callback handle
177 * \param[in] pxHigherPriorityTaskWoken
178 * xSemaphoreGiveFromISR() will set *pxHigherPriorityTaskWoken to pdTRUE if
179 * giving the semaphore caused a task to unblock, and the unblocked task has a
180 * priority higher than the currently running task. If xSemaphoreGiveFromISR()
181 * sets this value to pdTRUE then a context switch should be requested before
182 * the interrupt is exited.
183 * From FreeRTOS Docu: Context switching from an ISR uses port specific syntax.
184 * Check the demo task for your port to find the syntax required.
185 * \return Success (-1), failure (0)
187 int32_t PIOS_CALLBACKSCHEDULER_DispatchFromISR(DelayedCallbackInfo *cbinfo, long *pxHigherPriorityTaskWoken);
190 * Information about a running callback that has been registered
191 * via a call to PIOS_CALLBACKSCHEDULER_Create().
193 struct pios_callback_info {
194 /** Remaining task stack in bytes -1 for detected stack overflow. */
195 int32_t stack_remaining;
196 /** Flag indicating whether or not the task is running. */
197 bool is_running;
198 /** Count of executions of the callback since system start */
199 uint32_t running_time_count;
203 * Iterator callback, called for each monitored callback by PIOS_CALLBACKSCHEDULER_ForEachCallback().
205 * @param task_id The id of the task the task_info refers to.
206 * @param task_info Information about the task identified by task_id.
207 * @param context Context information optionally provided by the caller to PIOS_TASK_MONITOR_TasksIterate()
209 typedef void (*CallbackSchedulerCallbackInfoCallback)(int16_t task_id, const struct pios_callback_info *callback_info, void *context);
212 * Iterator. Iterates over all callbacks and all scheduler tasks and retrieves information
214 * @param[in] callback Callback function to receive the data - will be called in same task context as the callerThe id of the task the task_info refers to.
215 * @param context Context information optionally provided to the callback.
217 void PIOS_CALLBACKSCHEDULER_ForEachCallback(CallbackSchedulerCallbackInfoCallback callback, void *context);
219 #endif // PIOS_CALLBACKSCHEDULER_H