TNeoKernel  v1.04
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
tn_sys.h
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * TNeoKernel: real-time kernel initially based on TNKernel
4  *
5  * TNKernel: copyright © 2004, 2013 Yuri Tiomkin.
6  * PIC32-specific routines: copyright © 2013, 2014 Anders Montonen.
7  * TNeoKernel: copyright © 2014 Dmitry Frank.
8  *
9  * TNeoKernel was born as a thorough review and re-implementation of
10  * TNKernel. The new kernel has well-formed code, inherited bugs are fixed
11  * as well as new features being added, and it is tested carefully with
12  * unit-tests.
13  *
14  * API is changed somewhat, so it's not 100% compatible with TNKernel,
15  * hence the new name: TNeoKernel.
16  *
17  * Permission to use, copy, modify, and distribute this software in source
18  * and binary forms and its documentation for any purpose and without fee
19  * is hereby granted, provided that the above copyright notice appear
20  * in all copies and that both that copyright notice and this permission
21  * notice appear in supporting documentation.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE DMITRY FRANK AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY FRANK OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
33  * THE POSSIBILITY OF SUCH DAMAGE.
34  *
35  ******************************************************************************/
36 
37 /**
38  * \file
39  *
40  * Kernel system routines: system start, tick processing, time slice managing.
41  *
42  */
43 
44 #ifndef _TN_SYS_H
45 #define _TN_SYS_H
46 
47 
48 
49 /*******************************************************************************
50  * INCLUDED FILES
51  ******************************************************************************/
52 
53 #include "tn_list.h"
54 #include "../arch/tn_arch.h"
55 
56 
57 
58 
59 #ifdef __cplusplus
60 extern "C" { /*}*/
61 #endif
62 
63 /*******************************************************************************
64  * EXTERNAL TYPES
65  ******************************************************************************/
66 
67 struct TN_Task;
68 struct TN_Mutex;
69 
70 
71 
72 /*******************************************************************************
73  * DEFINITIONS
74  ******************************************************************************/
75 
76 /**
77  * Convenience macro for the definition of stack array. See
78  * `tn_task_create()` for the usage example.
79  *
80  * @param name
81  * C variable name of the array
82  * @param size
83  * size of the stack array in words (`#TN_UWord`), not in bytes.
84  */
85 #define TN_STACK_ARR_DEF(name, size) \
86  TN_ARCH_STK_ATTR_BEFORE \
87  TN_UWord name[ (size) ] \
88  TN_ARCH_STK_ATTR_AFTER
89 
90 
91 
92 
93 /*******************************************************************************
94  * PUBLIC TYPES
95  ******************************************************************************/
96 
97 /**
98  * System state flags
99  */
101  ///
102  /// system is running
104  ///
105  /// deadlock is active
106  /// Note: this feature works if only `#TN_MUTEX_DEADLOCK_DETECT` is non-zero.
107  /// @see `#TN_MUTEX_DEADLOCK_DETECT`
109 };
110 
111 /**
112  * System context
113  *
114  * @see `tn_sys_context_get()`
115  */
117  ///
118  /// None: this code is possible if only system is not running
119  /// (flag (`#TN_STATE_FLAG__SYS_RUNNING` is not set in the `tn_sys_state`))
121  ///
122  /// Task context
124  ///
125  /// ISR context
127 };
128 
129 /**
130  * User-provided callback function that is called directly from
131  * `tn_sys_start()` as a part of system startup routine; it should merely
132  * create at least one (and typically just one) user's task, which should
133  * perform all the rest application initialization.
134  *
135  * When `TN_CBUserTaskCreate()` returned, the kernel performs first context
136  * switch to the task with highest priority. If there are several tasks with
137  * highest priority, context is switched to the first created one.
138  *
139  * Refer to the section \ref starting_the_kernel for details about system
140  * startup process on the whole.
141  *
142  * **Note:** Although you're able to create more than one task here, it's
143  * usually not so good idea, because many things typically should be done at
144  * startup before tasks can go on with their job: we need to initialize various
145  * on-board peripherals (displays, flash memory chips, or whatever) as well as
146  * initialize software modules used by application. So, if many tasks are
147  * created here, you have to provide some synchronization object so that tasks
148  * will wait until all the initialization is done.
149  *
150  * It's usually easier to maintain if we create just one task here, which
151  * firstly performs all the necessary initialization, **then** creates the rest
152  * of your tasks, and eventually gets to its primary job (the job for which
153  * task was created at all). For the usage example, refer to the page \ref
154  * starting_the_kernel.
155  *
156  * \attention
157  * * The only system service is allowed to call in this function is
158  * `tn_task_create()`.
159  *
160  * @see `tn_sys_start()`
161  */
162 typedef void (TN_CBUserTaskCreate)(void);
163 
164 /**
165  * User-provided callback function that is called repeatedly from the idle task
166  * loop. Make sure that idle task has enough stack space to call this function.
167  *
168  * \attention
169  * * It is illegal to sleep here, because idle task (from which this
170  * function is called) should always be runnable, by design. If `#TN_DEBUG`
171  * option is set, then sleeping in idle task is checked, so if you try to
172  * sleep here, `_TN_FATAL_ERROR()` macro will be called.
173  *
174  *
175  * @see `tn_sys_start()`
176  */
177 typedef void (TN_CBIdle)(void);
178 
179 /**
180  * User-provided callback function that is called whenever
181  * deadlock becomes active or inactive.
182  * Note: this feature works if only `#TN_MUTEX_DEADLOCK_DETECT` is non-zero.
183  *
184  * @param active
185  * Boolean value indicating whether deadlock becomes active or inactive.
186  * Note: deadlock might become inactive if, for example, one of tasks
187  * involved in deadlock exits from waiting by timeout.
188  *
189  * @param mutex
190  * mutex that is involved in deadlock. You may find out other mutexes
191  * involved by means of `mutex->deadlock_list`.
192  *
193  * @param task
194  * task that is involved in deadlock. You may find out other tasks involved
195  * by means of `task->deadlock_list`.
196  */
197 typedef void (TN_CBDeadlock)(
198  TN_BOOL active,
199  struct TN_Mutex *mutex,
200  struct TN_Task *task
201  );
202 
203 
204 
205 
206 /*******************************************************************************
207  * DEFINITIONS
208  ******************************************************************************/
209 
210 /**
211  * Value to pass to `tn_sys_tslice_set()` to turn round-robin off.
212  */
213 #define TN_NO_TIME_SLICE 0
214 
215 /**
216  * Max value of time slice
217  */
218 #define TN_MAX_TIME_SLICE 0xFFFE
219 
220 
221 
222 
223 /*******************************************************************************
224  * PUBLIC FUNCTION PROTOTYPES
225  ******************************************************************************/
226 
227 /**
228  * Initial TNeoKernel system start function, never returns. Typically called
229  * from main().
230  *
231  * Refer to the \ref starting_the_kernel "Starting the kernel" section for the
232  * usage example and additional comments.
233  *
234  * $(TN_CALL_FROM_MAIN)
235  * $(TN_LEGEND_LINK)
236  *
237  * @param idle_task_stack
238  * Pointer to array for idle task stack.
239  * User must either use the macro `TN_STACK_ARR_DEF()` for the definition
240  * of stack array, or allocate it manually as an array of `#TN_UWord` with
241  * `#TN_ARCH_STK_ATTR_BEFORE` and `#TN_ARCH_STK_ATTR_AFTER` macros.
242  * @param idle_task_stack_size
243  * Size of idle task stack, in words (`#TN_UWord`)
244  * @param int_stack
245  * Pointer to array for interrupt stack.
246  * User must either use the macro `TN_STACK_ARR_DEF()` for the definition
247  * of stack array, or allocate it manually as an array of `#TN_UWord` with
248  * `#TN_ARCH_STK_ATTR_BEFORE` and `#TN_ARCH_STK_ATTR_AFTER` macros.
249  * @param int_stack_size
250  * Size of interrupt stack, in words (`#TN_UWord`)
251  * @param cb_user_task_create
252  * Callback function that should create initial user's task, see
253  * `#TN_CBUserTaskCreate` for details.
254  * @param cb_idle
255  * Callback function repeatedly called from idle task, see `#TN_CBIdle` for
256  * details.
257  */
258 void tn_sys_start(
259  TN_UWord *idle_task_stack,
260  unsigned int idle_task_stack_size,
261  TN_UWord *int_stack,
262  unsigned int int_stack_size,
263  TN_CBUserTaskCreate *cb_user_task_create,
264  TN_CBIdle *cb_idle
265  );
266 
267 /**
268  * Process system tick; should be called periodically, typically
269  * from some kind of timer ISR.
270  *
271  * The period of this timer is determined by user
272  * (typically 1 ms, but user is free to set different value)
273  *
274  * Among other things, expired \ref tn_timer.h "timers" are fired from this
275  * function.
276  *
277  * For further information, refer to \ref quick_guide "Quick guide".
278  *
279  * $(TN_CALL_FROM_ISR)
280  * $(TN_CAN_SWITCH_CONTEXT)
281  * $(TN_LEGEND_LINK)
282  *
283  * @return
284  * * `#TN_RC_OK` on success;
285  * * `#TN_RC_WCONTEXT` if called from wrong context.
286  */
288 
289 /**
290  * Set time slice ticks value for specified priority (see \ref round_robin).
291  *
292  * $(TN_CALL_FROM_TASK)
293  * $(TN_LEGEND_LINK)
294  *
295  * @param priority
296  * Priority of tasks for which time slice value should be set
297  * @param ticks
298  * Time slice value, in ticks. Set to `#TN_NO_TIME_SLICE` for no round-robin
299  * scheduling for given priority (it's default value). Value can't be
300  * higher than `#TN_MAX_TIME_SLICE`.
301  *
302  * @return
303  * * `#TN_RC_OK` on success;
304  * * `#TN_RC_WCONTEXT` if called from wrong context;
305  * * `#TN_RC_WPARAM` if given `priority` or `ticks` are invalid.
306  */
307 enum TN_RCode tn_sys_tslice_set(int priority, int ticks);
308 
309 /**
310  * Get current system ticks count.
311  *
312  * $(TN_CALL_FROM_TASK)
313  * $(TN_CALL_FROM_ISR)
314  * $(TN_LEGEND_LINK)
315  *
316  * @return
317  * Current system ticks count.
318  */
319 unsigned int tn_sys_time_get(void);
320 
321 
322 /**
323  * Set callback function that should be called whenever deadlock occurs or
324  * becomes inactive (say, if one of tasks involved in the deadlock was released
325  * from wait because of timeout)
326  *
327  * $(TN_CALL_FROM_MAIN)
328  * $(TN_LEGEND_LINK)
329  *
330  * **Note:** this function should be called from `main()`, before
331  * `tn_sys_start()`.
332  *
333  * @param cb
334  * Pointer to user-provided callback function.
335  *
336  * @see `#TN_MUTEX_DEADLOCK_DETECT`
337  * @see `#TN_CBDeadlock` for callback function prototype
338  */
340 
341 /**
342  * Returns current system state flags
343  *
344  * $(TN_CALL_FROM_TASK)
345  * $(TN_CALL_FROM_ISR)
346  * $(TN_LEGEND_LINK)
347  */
349 
350 /**
351  * Returns system context: task or ISR.
352  *
353  * $(TN_CALL_FROM_TASK)
354  * $(TN_CALL_FROM_ISR)
355  * $(TN_CALL_FROM_MAIN)
356  * $(TN_LEGEND_LINK)
357  *
358  * @see `enum #TN_Context`
359  */
360 enum TN_Context tn_sys_context_get(void);
361 
362 /**
363  * Returns whether current system context is `#TN_CONTEXT_TASK`
364  *
365  * $(TN_CALL_FROM_TASK)
366  * $(TN_CALL_FROM_ISR)
367  * $(TN_CALL_FROM_MAIN)
368  * $(TN_LEGEND_LINK)
369  *
370  * @return `TN_TRUE` if current system context is `#TN_CONTEXT_TASK`,
371  * `TN_FALSE` otherwise.
372  *
373  * @see `tn_sys_context_get()`
374  * @see `enum #TN_Context`
375  */
376 static inline TN_BOOL tn_is_task_context(void)
377 {
378  return (tn_sys_context_get() == TN_CONTEXT_TASK);
379 }
380 
381 /**
382  * Returns whether current system context is `#TN_CONTEXT_ISR`
383  *
384  * $(TN_CALL_FROM_TASK)
385  * $(TN_CALL_FROM_ISR)
386  * $(TN_CALL_FROM_MAIN)
387  * $(TN_LEGEND_LINK)
388  *
389  * @return `TN_TRUE` if current system context is `#TN_CONTEXT_ISR`,
390  * `TN_FALSE` otherwise.
391  *
392  * @see `tn_sys_context_get()`
393  * @see `enum #TN_Context`
394  */
395 static inline TN_BOOL tn_is_isr_context(void)
396 {
397  return (tn_sys_context_get() == TN_CONTEXT_ISR);
398 }
399 
400 /**
401  * Returns pointer to the currently running task.
402  *
403  * $(TN_CALL_FROM_TASK)
404  * $(TN_CALL_FROM_ISR)
405  * $(TN_LEGEND_LINK)
406  */
407 struct TN_Task *tn_cur_task_get(void);
408 
409 /**
410  * Returns pointer to the body function of the currently running task.
411  *
412  * $(TN_CALL_FROM_TASK)
413  * $(TN_CALL_FROM_ISR)
414  * $(TN_LEGEND_LINK)
415  */
417 
418 #ifdef __cplusplus
419 } /* extern "C" */
420 #endif
421 
422 #endif // _TN_SYS_H
423 
static TN_BOOL tn_is_task_context(void)
Returns whether current system context is TN_CONTEXT_TASK
Definition: tn_sys.h:376
Circular doubly linked list, for internal kernel usage.
Mutex.
Definition: tn_mutex.h:122
TN_Context
System context.
Definition: tn_sys.h:116
deadlock is active Note: this feature works if only TN_MUTEX_DEADLOCK_DETECT is non-zero.
Definition: tn_sys.h:108
Task.
Definition: tn_tasks.h:241
TN_RCode
Result code returned by kernel services.
Definition: tn_common.h:80
None: this code is possible if only system is not running (flag (TN_STATE_FLAG__SYS_RUNNING is not se...
Definition: tn_sys.h:120
TN_TaskBody * tn_cur_task_body_get(void)
Returns pointer to the body function of the currently running task.
system is running
Definition: tn_sys.h:103
void tn_callback_deadlock_set(TN_CBDeadlock *cb)
Set callback function that should be called whenever deadlock occurs or becomes inactive (say...
void tn_sys_start(TN_UWord *idle_task_stack, unsigned int idle_task_stack_size, TN_UWord *int_stack, unsigned int int_stack_size, TN_CBUserTaskCreate *cb_user_task_create, TN_CBIdle *cb_idle)
Initial TNeoKernel system start function, never returns.
static TN_BOOL tn_is_isr_context(void)
Returns whether current system context is TN_CONTEXT_ISR
Definition: tn_sys.h:395
enum TN_StateFlag tn_sys_state_flags_get(void)
Returns current system state flags.
void( TN_CBUserTaskCreate)(void)
User-provided callback function that is called directly from tn_sys_start() as a part of system start...
Definition: tn_sys.h:162
void( TN_CBDeadlock)(TN_BOOL active, struct TN_Mutex *mutex, struct TN_Task *task)
User-provided callback function that is called whenever deadlock becomes active or inactive...
Definition: tn_sys.h:197
enum TN_Context tn_sys_context_get(void)
Returns system context: task or ISR.
int priority
current task priority
Definition: tn_tasks.h:293
enum TN_RCode tn_tick_int_processing(void)
Process system tick; should be called periodically, typically from some kind of timer ISR...
struct TN_Task * tn_cur_task_get(void)
Returns pointer to the currently running task.
Task context.
Definition: tn_sys.h:123
void( TN_CBIdle)(void)
User-provided callback function that is called repeatedly from the idle task loop.
Definition: tn_sys.h:177
enum TN_RCode tn_sys_tslice_set(int priority, int ticks)
Set time slice ticks value for specified priority (see Round-robin scheduling).
void( TN_TaskBody)(void *param)
Prototype for task body function.
Definition: tn_common.h:144
unsigned int tn_sys_time_get(void)
Get current system ticks count.
unsigned int TN_UWord
Unsigned integer type whose size is equal to the size of CPU register.
TN_StateFlag
System state flags.
Definition: tn_sys.h:100
#define TN_BOOL
boolean type definition
Definition: tn_common.h:202
ISR context.
Definition: tn_sys.h:126