1 /**
2  * Copyright (c) 2015, Realtek Semiconductor Corporation. All rights reserved.
3  */
4 
5 #ifndef _OS_TASK_H_
6 #define _OS_TASK_H_
7 
8 #include <stdint.h>
9 #include <stdbool.h>
10 
11 #ifdef __cplusplus
12 extern "C" {
13 #endif
14 
15 /**
16  * \addtogroup  OS      OSIF
17  * \defgroup    Task    Task Management
18  *
19  * \brief   Define, create, and control task functions.
20  * \details The Task Management function group allows to create, delete, and control tasks
21  *          in the system.\n
22  * Tasks can be in the following states:\n
23  * \arg <b>RUNNING:</b> The task that is currently running is in the <b>RUNNING</b> state.
24  *                      Only one task at a time can be in this state.
25  * \arg <b>READY:</b> Tasks which are ready to run are in the <b>READY</b> state. Once the
26  *                    <b>RUNNING</b> task has terminated or is <b>WAITING</b>, the next
27  *                    <b>READY</b> task with the highest priority becomes the <b>RUNNING</b> task.
28  * \arg <b>WAITING:</b> Tasks that are waiting for an event to occur are in the WAITING state.
29  * \arg <b>INACTIVE</b>: Tasks that are not created or terminated are in the <b>INACTIVE</b> state.
30  *                       These Tasks typically consume no system resources.
31  *
32  * \image html OS-task-state-transition.jpg "Task State Transition" width=526px height=526px
33  *
34  * \ingroup     OS
35  */
36 
37 
38 /**
39  * os_task.h
40  *
41  * \brief Create a new task and add it to the list of tasks that are ready to run.
42  *
43  * \param[out]  pp_handle  Used to pass back a handle by which the created task
44  *                         can be referenced.
45  *
46  * \param[in]   p_name     A descriptive name for the task.
47  *
48  * \param[in]   p_routine  Pointer to task routine function that must be implemented
49  *                         to never return.
50  *
51  * \param[in]   p_param    Pointer parameter passed to the task routine function.
52  *
53  * \param[in]   stack_size The size of the task stack that is specified as the number
54  *                         of bytes.
55  *
56  * \param[in]   priority   The priority at which the task should run. Higher priority
57  *                         task has higher priority value.
58  *
59  * \return           The status of the task creation.
60  * \retval true      Task was created successfully and added to task ready list.
61  * \retval false     Task was failed to create.
62  *
63  * <b>Example usage</b>
64  * \code{.c}
65  * // Task routine implementation.
66  * void task_routine(void *p_param)
67  * {
68  *     for (;;)
69  *     {
70  *          // Task code goes here.
71  *     }
72  * }
73  *
74  * // Task to be created.
75  * int test(void)
76  * {
77  *     void *p_handle = NULL;
78  *     uint32_t task_param;
79  *
80  *     if (os_task_create(&p_handle, "task", task_routine,
81  *                        &task_param, STACK_SIZE, TASK_PRIORITY) == true)
82  *     {
83  *         // Task created successfully.
84  *     }
85  *     else
86  *     {
87  *         // Task failed to create.
88  *         return -1;
89  *     }
90  *
91  *     // Use the handle to delete the task.
92  *     os_task_delete(p_handle);
93  *
94  *     return 0;
95  * }
96  * \endcode
97  *
98  * \ingroup  Task
99  */
100 bool os_task_create(void **pp_handle, const char *p_name, void (*p_routine)(void *),
101                     void *p_param, uint16_t stack_size, uint16_t priority);
102 
103 /**
104  * os_task.h
105  *
106  * \brief Remove a task from RTOS's task management. The task being deleted will be removed
107  * from RUNNING, READY or WAITING state.
108  *
109  * \param[in] p_handle  The handle of the task to be deleted.
110  *
111  * \return           The status of the task deletion.
112  * \retval true      Task was deleted successfully.
113  * \retval false     Task was failed to delete.
114  *
115  * <b>Example usage</b>
116  * \code{.c}
117  * // Task routine implementation.
118  * void task_routine(void *p_param)
119  * {
120  *     for (;;)
121  *     {
122  *          // Task code goes here.
123  *     }
124  * }
125  *
126  * // Task to be created and deleted.
127  * int test(void)
128  * {
129  *     void *p_handle = NULL;
130  *     uint32_t task_param;
131  *
132  *     if (os_task_create(&p_handle, "task", task_routine,
133  *                        &task_param, STACK_SIZE, TASK_PRIORITY) == true)
134  *     {
135  *         // Task created successfully.
136  *     }
137  *     else
138  *     {
139  *         // Task failed to create.
140  *         return -1;
141  *     }
142  *
143  *     // Use the handle to delete the task.
144  *     os_task_delete(p_handle);
145  *
146  *     return 0;
147  * }
148  * \endcode
149  *
150  * \ingroup  Task
151  */
152 bool os_task_delete(void *p_handle);
153 
154 /**
155  * os_task.h
156  *
157  * \brief Suspend the task. The suspended task will not be scheduled and never get
158  * any microcontroller processing time.
159  *
160  * \param[in] p_handle  The handle of the task to be suspended.
161  *
162  * \return           The status of the task suspension.
163  * \retval true      Task was suspended successfully.
164  * \retval false     Task was failed to suspend.
165  *
166  * <b>Example usage</b>
167  * \code{.c}
168  * // Task routine implementation.
169  * void task_routine(void *p_param)
170  * {
171  *     for (;;)
172  *     {
173  *          // Task code goes here.
174  *     }
175  * }
176  *
177  * // Task to be created and suspended.
178  * int test(void)
179  * {
180  *     void *p_handle = NULL;
181  *     uint32_t task_param;
182  *
183  *     if (os_task_create(&p_handle, "task", task_routine,
184  *                        &task_param, STACK_SIZE, TASK_PRIORITY) == true)
185  *     {
186  *         // Task created successfully.
187  *     }
188  *     else
189  *     {
190  *         // Task failed to create.
191  *         return -1;
192  *     }
193  *
194  *     // Use the handle to suspend the created task.
195  *     os_task_suspend(p_handle);
196  *
197  *     return 0;
198  * }
199  * \endcode
200  *
201  * \ingroup  Task
202  */
203 bool os_task_suspend(void *p_handle);
204 
205 /**
206  * os_task.h
207  *
208  * \brief Resume the suspended task.
209  *
210  * \param[in] p_handle  The handle of the task to be resumed.
211  *
212  * \return           The status of the task resume.
213  * \retval true      Task was resumed successfully.
214  * \retval false     Task was failed to resume.
215  *
216  * <b>Example usage</b>
217  * \code{.c}
218  * // Task routine implementation.
219  * void task_routine(void *p_param)
220  * {
221  *     for (;;)
222  *     {
223  *          // Task code goes here.
224  *     }
225  * }
226  *
227  * // Task to be suspended and resumed.
228  * int test(void)
229  * {
230  *     void *p_handle = NULL;
231  *     uint32_t task_param;
232  *
233  *     if (os_task_create(&p_handle, "task", task_routine,
234  *                        &task_param, STACK_SIZE, TASK_PRIORITY) == true)
235  *     {
236  *         // Task created successfully.
237  *     }
238  *     else
239  *     {
240  *         // Task failed to create.
241  *         return -1;
242  *     }
243  *
244  *     // Use the handle to suspend the created task.
245  *     os_task_suspend(p_handle);
246  *
247  *     // Resume the suspended task by ourselves.
248  *     os_task_resume(p_handle);
249  *     return 0;
250  * }
251  * \endcode
252  *
253  * \ingroup  Task
254  */
255 bool os_task_resume(void *p_handle);
256 
257 /**
258  * os_task.h
259  *
260  * \brief Force a context swith and pass control to the next task that is in
261  * READY state.
262  *
263  * \param None
264  *
265  * \return           The status of the task resume.
266  * \retval true      Task was yielded successfully.
267  * \retval false     Task was failed to yield.
268  *
269  * <b>Example usage</b>
270  * \code{.c}
271  * // Task routine implementation.
272  * void task_routine(void *p_param)
273  * {
274  *     for (;;)
275  *     {
276  *          // Force a context switch
277  *          os_task_yield();
278  *     }
279  * }
280  *
281  * // Task to be created.
282  * int test(void)
283  * {
284  *     void *p_handle = NULL;
285  *     uint32_t task_param;
286  *
287  *     if (os_task_create(&p_handle, "task", task_routine,
288  *                        &task_param, STACK_SIZE, TASK_PRIORITY) == true)
289  *     {
290  *         // Task created successfully.
291  *     }
292  *     else
293  *     {
294  *         // Task failed to create.
295  *         return -1;
296  *     }
297  *
298  *     return 0;
299  * }
300  * \endcode
301  *
302  * \ingroup  Task
303  */
304 bool os_task_yield(void);
305 
306 /**
307  * os_task.h
308  *
309  * \brief Get the handle of the current running task.
310  *
311  * \param[out] pp_handle  Used to pass back a handle by which the current task
312  *                        can be referenced.
313  *
314  * \return           The status of getting the current task handle.
315  * \retval true      Task handle was got successfully.
316  * \retval false     Task handle was failed to get.
317  *
318  * <b>Example usage</b>
319  * \code{.c}
320  * // Get current task handle.
321  * int test(void)
322  * {
323  *     void *p_handle = NULL;
324  *
325  *     os_task_handle_get(&p_handle);
326  *
327  *     return 0;
328  * }
329  * \endcode
330  *
331  * \ingroup  Task
332  */
333 bool os_task_handle_get(void **pp_handle);
334 
335 /**
336  * os_task.h
337  *
338  * \brief Get the priority of the specified task.
339  *
340  * \param[in] p_handle    The handle of the task to be queried. Passing a NULL handle
341  *                        means querying the priority of the current task.
342  *
343  * \param[out] p_priority Used to pass back the priority of the task.
344  *
345  * \return           The status of getting the task priority.
346  * \retval true      Task priority was got successfully.
347  * \retval false     Task priority was failed to get.
348  *
349  * <b>Example usage</b>
350  * \code{.c}
351  * int test(void)
352  * {
353  *     void *p_handle = NULL;
354  *     uint16_t priority;
355  *
356  *     if (os_task_create(&p_handle, "task", task_routine,
357  *                        NULL, STACK_SIZE, TASK_PRIORITY) == true)
358  *     {
359  *         // Task created successfully.
360  *     }
361  *     else
362  *     {
363  *         // Task failed to create.
364  *         return -1;
365  *     }
366  *
367  *     // Get the task priority.
368  *     os_task_priority_get(p_handle, &priority);
369  *
370  *     return 0;
371  * }
372  * \endcode
373  *
374  * \ingroup  Task
375  */
376 bool os_task_priority_get(void *p_handle, uint16_t *p_priority);
377 
378 /**
379  * os_task.h
380  *
381  * \brief Set the priority of the specified task.
382  *
383  * \param[in] p_handle  The handle of the task for which the priority is being set.
384  *                      Passing a NULL handle means setting the priority of the
385  *                      current task.
386  *
387  * \param[in] priority  The priority to which the task will be set.
388  *
389  * \return           The status of setting the task priority.
390  * \retval true      Task priority was set successfully.
391  * \retval false     Task priority was failed to set.
392  *
393  * <b>Example usage</b>
394  * \code{.c}
395  * int test(void)
396  * {
397  *     void *p_handle = NULL;
398  *     uint16_t priority;
399  *
400  *     if (os_task_create(&p_handle, "task", task_routine,
401  *                        NULL, STACK_SIZE, TASK_PRIORITY) == true)
402  *     {
403  *         // Task created successfully.
404  *     }
405  *     else
406  *     {
407  *         // Task failed to create.
408  *         return -1;
409  *     }
410  *
411  *     // Use the handle to raise the created task priority.
412  *     os_task_priority_set(p_handle, TASK_PRIORITY + 1);
413  *
414  *     // Use a NULL handle to raise the current task priority.
415  *     os_task_priority_set(NULL, TASK_PRIORITY + 1);
416  *
417  *     return 0;
418  * }
419  * \endcode
420  *
421  * \ingroup  Task
422  */
423 bool os_task_priority_set(void *p_handle, uint16_t priority);
424 
425 bool os_task_signal_init(void);
426 void os_task_signal_deinit(void);
427 /**
428  * os_task.h
429  *
430  * \brief Send a notification signal to the specified task.
431  *
432  * The notification signal sent to a task will remain pending until it is
433  * cleared by the task calling os_task_signal_recv(). If the task was already
434  * in the WAITING state to wait for the singal, then the task will be removed
435  * from WAITING state and the signal cleared.
436  *
437  * \param[in] p_handle  The handle of the task to which the signal is sent.
438  *
439  * \param[in] signal    The signal to be sent.
440  *
441  * \return          The status of sending the signal.
442  * \retval true     Task signal was sent successfully.
443  * \retval false    Task signal was failed to send.
444  *
445  * <b>Example usage</b>
446  * \code{.c}
447  * int test(void)
448  * {
449  *     void *p_handle = NULL;
450  *     uint32_t signal;
451  *
452  *     if (os_task_create(&p_handle, "task", task_routine,
453  *                        NULL, STACK_SIZE, TASK_PRIORITY) == true)
454  *     {
455  *         // Task created successfully.
456  *     }
457  *     else
458  *     {
459  *         // Task failed to create.
460  *         return -1;
461  *     }
462  *
463  *     // Send signal to the created task.
464  *     singal = 1;
465  *     os_task_signal_send(p_handle, signal);
466  *
467  *     return 0;
468  * }
469  * \endcode
470  *
471  * \ingroup  Task
472  */
473 bool os_task_signal_send(void *p_handle, uint32_t signal);
474 
475 /**
476  * os_task.h
477  *
478  * \brief Wait for a notification signal.
479  *
480  * \param[out] p_signal Used to pass back the received signal.
481  *
482  * \param[in] wait_ms   The timeout in milliseconds to wait for the signal.
483  * \arg \c 0            No blocking and return immediately.
484  * \arg \c 0xFFFFFFFF   Block infinitely until the signal received.
485  * \arg \c others       The timeout value in milliseconds.
486  *
487  * \return          The status of receiving the signal.
488  * \retval true     Task signal was received successfully.
489  * \retval false    Task signal was failed to receive.
490  *
491  * <b>Example usage</b>
492  * \code{.c}
493  * int test(void)
494  * {
495  *     uint32_t signal;
496  *
497  *     // Block to wait for the signal sent from other tasks.
498  *     os_task_signal_recv(&signal, 0xFFFFFFFF);
499  *
500  *     return 0;
501  * }
502  * \endcode
503  *
504  * \ingroup  Task
505  */
506 bool os_task_signal_recv(uint32_t *p_signal, uint32_t wait_ms);
507 
508 /**
509  * os_task.h
510  *
511  * \brief Clear the signal of the specified task.
512  *
513  * \param[in] p_handle  The handle of the task to which the signal is clear.
514  *
515  * \return          The status of clearing the signal.
516  * \retval true     Task signal was cleared successfully.
517  * \retval false    Task signal was failed to clear.
518  *
519  * <b>Example usage</b>
520  * \code{.c}
521  * int test(void)
522  * {
523  *     void *p_handle = NULL;
524  *     uint32_t signal;
525  *
526  *     if (os_task_create(&p_handle, "task", task_routine,
527  *                        NULL, STACK_SIZE, TASK_PRIORITY) == true)
528  *     {
529  *         // Task created successfully.
530  *     }
531  *     else
532  *     {
533  *         // Task failed to create.
534  *         return -1;
535  *     }
536  *
537  *     // Send signal to the created task.
538  *     singal = 1;
539  *     os_task_signal_send(p_handle, signal);
540  *
541  *     // Clear signal of the created task.
542  *     os_task_signal_clear(p_handle);
543  *
544  *     return 0;
545  * }
546  * \endcode
547  *
548  * \ingroup  Task
549  */
550 bool os_task_signal_clear(void *p_handle);
551 
552 #ifdef __cplusplus
553 }
554 #endif
555 
556 #endif /* _OS_TASK_H_ */
557