TNeoKernel  v1.01
 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  * PUBLIC TYPES
74  ******************************************************************************/
75 
76 /**
77  * System state flags
78  */
80  ///
81  /// system is running
83  ///
84  /// deadlock is active
85  /// Note: this feature works if only `#TN_MUTEX_DEADLOCK_DETECT` is non-zero.
86  /// @see `#TN_MUTEX_DEADLOCK_DETECT`
88 };
89 
90 /**
91  * System context
92  *
93  * @see `tn_sys_context_get()`
94  */
95 enum TN_Context {
96  ///
97  /// None: this code is possible if only system is not running
98  /// (flag (`#TN_STATE_FLAG__SYS_RUNNING` is not set in the `tn_sys_state`))
100  ///
101  /// Task context
103  ///
104  /// ISR context
106 };
107 
108 /**
109  * User-provided callback function that is called directly from
110  * `tn_sys_start()` as a part of system startup routine; it should merely
111  * create at least one (and typically just one) user's task, which should
112  * perform all the rest application initialization.
113  *
114  * When `TN_CBUserTaskCreate()` returned, the kernel performs first context
115  * switch to the task with highest priority. If there are several tasks with
116  * highest priority, context is switched to the first created one.
117  *
118  * Refer to the section \ref starting_the_kernel for details about system
119  * startup process on the whole.
120  *
121  * **Note:** Although you're able to create more than one task here, it's
122  * usually not so good idea, because many things typically should be done at
123  * startup before tasks can go on with their job: we need to initialize various
124  * on-board peripherals (displays, flash memory chips, or whatever) as well as
125  * initialize software modules used by application. So, if many tasks are
126  * created here, you have to provide some synchronization object so that tasks
127  * will wait until all the initialization is done.
128  *
129  * It's usually easier to maintain if we create just one task here, which
130  * firstly performs all the necessary initialization, **then** creates the rest
131  * of your tasks, and eventually gets to its primary job (the job for which
132  * task was created at all). For the usage example, refer to the page \ref
133  * starting_the_kernel.
134  *
135  * \attention
136  * * The only system service is allowed to call in this function is
137  * `tn_task_create()`.
138  *
139  * @see `tn_sys_start()`
140  */
141 typedef void (TN_CBUserTaskCreate)(void);
142 
143 /**
144  * User-provided callback function that is called repeatedly from the idle task
145  * loop. Make sure that idle task has enough stack space to call this function.
146  *
147  * \attention
148  * * It is illegal to sleep here, because idle task (from which this
149  * function is called) should always be runnable, by design. If `#TN_DEBUG`
150  * option is set, then sleeping in idle task is checked, so if you try to
151  * sleep here, `_TN_FATAL_ERROR()` macro will be called.
152  *
153  *
154  * @see `tn_sys_start()`
155  */
156 typedef void (TN_CBIdle)(void);
157 
158 /**
159  * User-provided callback function that is called whenever
160  * deadlock becomes active or inactive.
161  * Note: this feature works if only `#TN_MUTEX_DEADLOCK_DETECT` is non-zero.
162  *
163  * @param active if `TRUE`, deadlock becomes active, otherwise it becomes
164  * inactive (say, if task stopped waiting for mutex
165  * because of timeout)
166  * @param mutex mutex that is involved in deadlock. You may find out other
167  * mutexes involved by means of `mutex->deadlock_list`.
168  * @param task task that is involved in deadlock. You may find out other
169  * tasks involved by means of `task->deadlock_list`.
170  */
171 typedef void (TN_CBDeadlock)(
172  BOOL active,
173  struct TN_Mutex *mutex,
174  struct TN_Task *task
175  );
176 
177 
178 
179 
180 /*******************************************************************************
181  * DEFINITIONS
182  ******************************************************************************/
183 
184 /**
185  * Value to pass to `tn_sys_tslice_set()` to turn round-robin off.
186  */
187 #define TN_NO_TIME_SLICE 0
188 
189 /**
190  * Max value of time slice
191  */
192 #define TN_MAX_TIME_SLICE 0xFFFE
193 
194 
195 
196 
197 /*******************************************************************************
198  * PUBLIC FUNCTION PROTOTYPES
199  ******************************************************************************/
200 
201 /**
202  * Initial TNeoKernel system start function, never returns. Typically called
203  * from main().
204  *
205  * Refer to the \ref starting_the_kernel "Starting the kernel" section for the
206  * usage example and additional comments.
207  *
208  * $(TN_CALL_FROM_MAIN)
209  * $(TN_LEGEND_LINK)
210  *
211  * @param idle_task_stack
212  * Pointer to array for idle task stack.
213  * User must either use the macro `TN_TASK_STACK_DEF()` for the definition
214  * of stack array, or allocate it manually as an array of `#TN_UWord` with
215  * `#TN_ARCH_STK_ATTR_BEFORE` and `#TN_ARCH_STK_ATTR_AFTER` macros.
216  * @param idle_task_stack_size
217  * Size of idle task stack, in words (`#TN_UWord`)
218  * @param int_stack
219  * Pointer to array for interrupt stack.
220  * User must either use the macro `TN_TASK_STACK_DEF()` for the definition
221  * of stack array, or allocate it manually as an array of `#TN_UWord` with
222  * `#TN_ARCH_STK_ATTR_BEFORE` and `#TN_ARCH_STK_ATTR_AFTER` macros.
223  * @param int_stack_size
224  * Size of interrupt stack, in words (`#TN_UWord`)
225  * @param cb_user_task_create
226  * Callback function that should create initial user's task, see
227  * `#TN_CBUserTaskCreate` for details.
228  * @param cb_idle
229  * Callback function repeatedly called from idle task, see `#TN_CBIdle` for
230  * details.
231  */
232 void tn_sys_start(
233  TN_UWord *idle_task_stack,
234  unsigned int idle_task_stack_size,
235  TN_UWord *int_stack,
236  unsigned int int_stack_size,
237  TN_CBUserTaskCreate *cb_user_task_create,
238  TN_CBIdle *cb_idle
239  );
240 
241 /**
242  * Process system tick; should be called periodically, typically
243  * from some kind of timer ISR.
244  *
245  * The period of this timer is determined by user
246  * (typically 1 ms, but user is free to set different value)
247  *
248  * For further information, refer to \ref quick_guide "Quick guide".
249  *
250  * $(TN_CALL_FROM_ISR)
251  * $(TN_CAN_SWITCH_CONTEXT)
252  * $(TN_LEGEND_LINK)
253  *
254  * @return
255  * * `#TN_RC_OK` on success;
256  * * `#TN_RC_WCONTEXT` if called from wrong context.
257  */
259 
260 /**
261  * Set time slice ticks value for specified priority (see \ref round_robin).
262  *
263  * $(TN_CALL_FROM_TASK)
264  * $(TN_LEGEND_LINK)
265  *
266  * @param priority
267  * Priority of tasks for which time slice value should be set
268  * @param ticks
269  * Time slice value, in ticks. Set to `#TN_NO_TIME_SLICE` for no round-robin
270  * scheduling for given priority (it's default value). Value can't be
271  * higher than `#TN_MAX_TIME_SLICE`.
272  *
273  * @return
274  * * `#TN_RC_OK` on success;
275  * * `#TN_RC_WCONTEXT` if called from wrong context;
276  * * `#TN_RC_WPARAM` if given `priority` or `ticks` are invalid.
277  */
278 enum TN_RCode tn_sys_tslice_set(int priority, int ticks);
279 
280 /**
281  * Get current system ticks count.
282  *
283  * $(TN_CALL_FROM_TASK)
284  * $(TN_CALL_FROM_ISR)
285  * $(TN_LEGEND_LINK)
286  *
287  * @return
288  * Current system ticks count. Note that this value does **not** affect any
289  * of the internal TNeoKernel routines, it is just incremented each system
290  * tick (i.e. in `tn_tick_int_processing()`) and is returned to user by
291  * `tn_sys_time_get()`.
292  *
293  * It is not used by TNeoKernel itself at all.
294  */
295 unsigned int tn_sys_time_get(void);
296 
297 /**
298  * Set system ticks count. Note that this value does **not** affect any of the
299  * internal TNeoKernel routines, it is just incremented each system tick (i.e.
300  * in `tn_tick_int_processing()`) and is returned to user by
301  * `tn_sys_time_get()`.
302  *
303  * It is not used by TNeoKernel itself at all.
304  *
305  * $(TN_CALL_FROM_TASK)
306  * $(TN_CALL_FROM_ISR)
307  * $(TN_LEGEND_LINK)
308  */
309 void tn_sys_time_set(unsigned int value);
310 
311 
312 /**
313  * Set callback function that should be called whenever deadlock occurs or
314  * becomes inactive (say, if one of tasks involved in the deadlock was released
315  * from wait because of timeout)
316  *
317  * $(TN_CALL_FROM_MAIN)
318  * $(TN_LEGEND_LINK)
319  *
320  * **Note:** this function should be called before `tn_sys_start()`
321  *
322  * @param cb
323  * Pointer to user-provided callback function.
324  *
325  * @see `#TN_MUTEX_DEADLOCK_DETECT`
326  * @see `#TN_CBDeadlock` for callback function prototype
327  */
329 
330 /**
331  * Returns current system state flags
332  *
333  * $(TN_CALL_FROM_TASK)
334  * $(TN_CALL_FROM_ISR)
335  * $(TN_LEGEND_LINK)
336  */
338 
339 /**
340  * Returns system context: task or ISR.
341  *
342  * $(TN_CALL_FROM_TASK)
343  * $(TN_CALL_FROM_ISR)
344  * $(TN_CALL_FROM_MAIN)
345  * $(TN_LEGEND_LINK)
346  *
347  * @see `enum #TN_Context`
348  */
349 enum TN_Context tn_sys_context_get(void);
350 
351 /**
352  * Returns whether current system context is `#TN_CONTEXT_TASK`
353  *
354  * $(TN_CALL_FROM_TASK)
355  * $(TN_CALL_FROM_ISR)
356  * $(TN_CALL_FROM_MAIN)
357  * $(TN_LEGEND_LINK)
358  *
359  * @return `TRUE` if current system context is `#TN_CONTEXT_TASK`,
360  * `FALSE` otherwise.
361  *
362  * @see `tn_sys_context_get()`
363  * @see `enum #TN_Context`
364  */
365 static inline BOOL tn_is_task_context(void)
366 {
367  return (tn_sys_context_get() == TN_CONTEXT_TASK);
368 }
369 
370 /**
371  * Returns whether current system context is `#TN_CONTEXT_ISR`
372  *
373  * $(TN_CALL_FROM_TASK)
374  * $(TN_CALL_FROM_ISR)
375  * $(TN_CALL_FROM_MAIN)
376  * $(TN_LEGEND_LINK)
377  *
378  * @return `TRUE` if current system context is `#TN_CONTEXT_ISR`,
379  * `FALSE` otherwise.
380  *
381  * @see `tn_sys_context_get()`
382  * @see `enum #TN_Context`
383  */
384 static inline BOOL tn_is_isr_context(void)
385 {
386  return (tn_sys_context_get() == TN_CONTEXT_ISR);
387 }
388 
389 /**
390  * Returns pointer to the currently running task.
391  *
392  * $(TN_CALL_FROM_TASK)
393  * $(TN_CALL_FROM_ISR)
394  * $(TN_LEGEND_LINK)
395  */
396 struct TN_Task *tn_cur_task_get(void);
397 
398 /**
399  * Returns pointer to the body function of the currently running task.
400  *
401  * $(TN_CALL_FROM_TASK)
402  * $(TN_CALL_FROM_ISR)
403  * $(TN_LEGEND_LINK)
404  */
406 
407 #ifdef __cplusplus
408 } /* extern "C" */
409 #endif
410 
411 #endif // _TN_SYS_H
412 
Mutex.
Definition: tn_mutex.h:122
TN_Context
System context.
Definition: tn_sys.h:95
#define BOOL
boolean type definition
Definition: tn_common.h:222
deadlock is active Note: this feature works if only TN_MUTEX_DEADLOCK_DETECT is non-zero.
Definition: tn_sys.h:87
Task.
Definition: tn_tasks.h:172
TN_RCode
Result code returned by kernel services.
Definition: tn_common.h:99
None: this code is possible if only system is not running (flag (TN_STATE_FLAG__SYS_RUNNING is not se...
Definition: tn_sys.h:99
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:82
void tn_sys_time_set(unsigned int value)
Set system ticks count.
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.
void( TN_CBDeadlock)(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:171
static BOOL tn_is_task_context(void)
Returns whether current system context is TN_CONTEXT_TASK
Definition: tn_sys.h:365
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:141
enum TN_Context tn_sys_context_get(void)
Returns system context: task or ISR.
int priority
current task priority
Definition: tn_tasks.h:224
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:102
static BOOL tn_is_isr_context(void)
Returns whether current system context is TN_CONTEXT_ISR
Definition: tn_sys.h:384
void( TN_CBIdle)(void)
User-provided callback function that is called repeatedly from the idle task loop.
Definition: tn_sys.h:156
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:163
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:79
ISR context.
Definition: tn_sys.h:105