TNeo  v1.07
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
tn_arch.h
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * TNeo: 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  * TNeo: copyright © 2014 Dmitry Frank.
8  *
9  * TNeo 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: TNeo.
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  * Architecture-dependent routines declaration.
41  */
42 
43 #ifndef _TN_ARCH_H
44 #define _TN_ARCH_H
45 
46 
47 /*******************************************************************************
48  * INCLUDED FILES
49  ******************************************************************************/
50 
51 #include "../core/tn_common.h"
52 
53 
54 
55 /*******************************************************************************
56  * OPTION VALUES
57  ******************************************************************************/
58 
59 #ifndef DOXYGEN_SHOULD_SKIP_THIS
60 
61 #define _TN_ARCH_STACK_DIR__ASC 1
62 #define _TN_ARCH_STACK_DIR__DESC 2
63 
64 //-- Note: the macro _TN_ARCH_STACK_DIR is defined in the header for each
65 // particular achitecture
66 
67 
68 #define _TN_ARCH_STACK_PT_TYPE__FULL 3
69 #define _TN_ARCH_STACK_PT_TYPE__EMPTY 4
70 
71 //-- Note: the macro _TN_ARCH_STACK_PT_TYPE is defined in the header for each
72 // particular achitecture
73 
74 
75 
76 #define _TN_ARCH_STACK_IMPL__FULL_ASC 5
77 #define _TN_ARCH_STACK_IMPL__FULL_DESC 6
78 #define _TN_ARCH_STACK_IMPL__EMPTY_ASC 7
79 #define _TN_ARCH_STACK_IMPL__EMPTY_DESC 8
80 
81 //-- Note: the macro _TN_ARCH_STACK_IMPL is defined below in this file
82 
83 
84 #endif
85 
86 
87 
88 
89 
90 /*******************************************************************************
91  * ACTUAL PORT IMPLEMENTATION
92  ******************************************************************************/
93 
94 #if defined(__TN_ARCH_PIC32MX__)
95 # include "pic32/tn_arch_pic32.h"
96 #elif defined(__TN_ARCH_PIC24_DSPIC__)
98 #elif defined(__TN_ARCH_CORTEX_M__)
100 #else
101 # error "unknown platform"
102 #endif
103 
104 
105 
106 
107 //-- Now, define _TN_ARCH_STACK_IMPL depending on _TN_ARCH_STACK_DIR and
108 // _TN_ARCH_STACK_PT_TYPE
109 
110 #ifndef DOXYGEN_SHOULD_SKIP_THIS
111 
112 #if !defined(_TN_ARCH_STACK_DIR)
113 # error _TN_ARCH_STACK_DIR is not defined
114 #endif
115 
116 #if !defined(_TN_ARCH_STACK_PT_TYPE)
117 # error _TN_ARCH_STACK_PT_TYPE is not defined
118 #endif
119 
120 #if (_TN_ARCH_STACK_DIR == _TN_ARCH_STACK_DIR__ASC)
121 # if (_TN_ARCH_STACK_PT_TYPE == _TN_ARCH_STACK_PT_TYPE__FULL)
122 # define _TN_ARCH_STACK_IMPL _TN_ARCH_STACK_IMPL__FULL_ASC
123 # elif (_TN_ARCH_STACK_PT_TYPE == _TN_ARCH_STACK_PT_TYPE__EMPTY)
124 # define _TN_ARCH_STACK_IMPL _TN_ARCH_STACK_IMPL__EMPTY_ASC
125 # else
126 # error wrong _TN_ARCH_STACK_PT_TYPE
127 # endif
128 #elif (_TN_ARCH_STACK_DIR == _TN_ARCH_STACK_DIR__DESC)
129 # if (_TN_ARCH_STACK_PT_TYPE == _TN_ARCH_STACK_PT_TYPE__FULL)
130 # define _TN_ARCH_STACK_IMPL _TN_ARCH_STACK_IMPL__FULL_DESC
131 # elif (_TN_ARCH_STACK_PT_TYPE == _TN_ARCH_STACK_PT_TYPE__EMPTY)
132 # define _TN_ARCH_STACK_IMPL _TN_ARCH_STACK_IMPL__EMPTY_DESC
133 # else
134 # error wrong _TN_ARCH_STACK_PT_TYPE
135 # endif
136 #else
137 # error wrong _TN_ARCH_STACK_DIR
138 #endif
139 
140 #endif
141 
142 
143 
144 #ifdef __cplusplus
145 extern "C" { /*}*/
146 #endif
147 
148 /*******************************************************************************
149  * PUBLIC FUNCTION PROTOTYPES
150  ******************************************************************************/
151 
152 
153 /**
154  * Unconditionally disable <i>system interrupts</i>.
155  *
156  * Refer to the section \ref interrupt_types for details on what is <i>system
157  * interrupt</i>.
158  */
159 void tn_arch_int_dis(void);
160 
161 /**
162  * Unconditionally enable interrupts
163  *
164  * Refer to the section \ref interrupt_types for details on what is <i>system
165  * interrupt</i>.
166  */
167 void tn_arch_int_en(void);
168 
169 /**
170  * Disable <i>system interrupts</i> and return previous value of status
171  * register, atomically.
172  *
173  * Refer to the section \ref interrupt_types for details on what is <i>system
174  * interrupt</i>.
175  *
176  * @see `tn_arch_sr_restore()`
177  */
179 
180 /**
181  * Restore previously saved status register.
182  *
183  * @param sr status register value previously from
184  * `tn_arch_sr_save_int_dis()`
185  *
186  * @see `tn_arch_sr_save_int_dis()`
187  */
189 
190 /**
191  * Disable kernel scheduler and return previous state.
192  *
193  * @return
194  * Scheduler state to be restored later by `#tn_arch_sched_restore()`.
195  */
197 
198 /**
199  * Restore state of the kernel scheduler. See `#tn_arch_sched_dis_save()`.
200  *
201  * @param sched_state
202  * Value returned from `#tn_arch_sched_dis_save()`
203  */
204 void tn_arch_sched_restore(TN_UWord sched_state);
205 
206 /**
207  * Should put initial CPU context to the provided stack pointer for new task
208  * and return current stack pointer.
209  *
210  * When resulting context gets restored by
211  * `_tn_arch_context_switch_now_nosave()` or `_tn_arch_context_switch_pend()`,
212  * the following conditions should be met:
213  *
214  * - Interrupts are enabled;
215  * - Return address is set to `tn_task_exit()`, so that when task body function
216  * returns, `tn_task_exit()` gets automatially called;
217  * - Argument 0 contains `param` pointer
218  *
219  * @param task_func
220  * Pointer to task body function.
221  * @param stack_low_addr
222  * Lowest address of the stack, independently of the architecture stack
223  * implementation
224  * @param stack_high_addr
225  * Highest address of the stack, independently of the architecture stack
226  * implementation
227  * @param param
228  * User-provided parameter for task body function.
229  *
230  * @return current stack pointer (top of the stack)
231  */
233  TN_TaskBody *task_func,
234  TN_UWord *stack_low_addr,
235  TN_UWord *stack_high_addr,
236  void *param
237  );
238 
239 
240 
241 /**
242  * Should return 1 if <i>system ISR</i> is currently running, 0 otherwise.
243  *
244  * Refer to the section \ref interrupt_types for details on what is <i>system
245  * ISR</i>.
246  */
247 int _tn_arch_inside_isr(void);
248 
249 /**
250  * Should return 1 if <i>system interrupts</i> are currently disabled, 0
251  * otherwise.
252  *
253  * Refer to the section \ref interrupt_types for details on what is <i>system
254  * interrupt</i>.
255  */
256 int _tn_arch_is_int_disabled(void);
257 
258 /**
259  * Called whenever we need to switch context from one task to another.
260  *
261  * This function typically does NOT switch context; it merely pends it,
262  * that is, it sets appropriate interrupt flag. If current level is an
263  * application level, interrupt is fired immediately, and context gets
264  * switched. Otherwise (if some ISR is currently running), context switch
265  * keeps pending until all ISR return.
266  *
267  * **Preconditions:**
268  *
269  * - interrupts are enabled;
270  * - `_tn_curr_run_task` points to currently running (preempted) task;
271  * - `_tn_next_task_to_run` points to new task to run.
272  *
273  * **Actions to perform in actual context switching routine:**
274  *
275  * - save context of the preempted task to its stack;
276  * - if preprocessor macro `#_TN_ON_CONTEXT_SWITCH_HANDLER` is non-zero, call
277  * `_tn_sys_on_context_switch(_tn_curr_run_task, _tn_next_task_to_run);`.
278  * - set `_tn_curr_run_task` to `_tn_next_task_to_run`;
279  * - restore context of the newly activated task from its stack.
280  *
281  * @see `_tn_curr_run_task`
282  * @see `_tn_next_task_to_run`
283  */
285 
286 /**
287  * Called whenever we need to switch context to new task, but don't save
288  * current context. This happens:
289  * - At system start, inside `tn_sys_start()`
290  * (well, it is actually called indirectly but from `_tn_arch_sys_start()`);
291  * - At task exit, inside `tn_task_exit()`.
292  *
293  * This function doesn't need to pend context switch, it switches context
294  * immediately.
295  *
296  * **Preconditions:**
297  *
298  * - interrupts are disabled;
299  * - `_tn_next_task_to_run` is already set to needed task.
300  *
301  * **Actions to perform:**
302  *
303  * - if preprocessor macro `#_TN_ON_CONTEXT_SWITCH_HANDLER` is non-zero, call
304  * `_tn_sys_on_context_switch(_tn_curr_run_task, _tn_next_task_to_run);`.
305  * - set `_tn_curr_run_task` to `_tn_next_task_to_run`;
306  * - restore context of the newly activated task from its stack.
307  *
308  * @see `_tn_curr_run_task`
309  * @see `_tn_next_task_to_run`
310  */
312 
313 /**
314  * Performs first context switch to the first task (`_tn_next_task_to_run` is
315  * already set to needed task).
316  *
317  * Typically, this function just calls `_tn_arch_context_switch_now_nosave()`,
318  * but it also can perform any architecture-dependent actions first, if needed.
319  */
320 void _tn_arch_sys_start(
321  TN_UWord *int_stack,
322  TN_UWord int_stack_size
323  );
324 
325 
326 #ifdef __cplusplus
327 } /* extern "C" */
328 #endif
329 
330 
331 
332 
333 
334 
335 
336 
337 
338 #endif /* _TN_ARCH_H */
339 
Cortex-M0/M0+/M3/M4/M4F architecture-dependent routines.
void _tn_arch_sys_start(TN_UWord *int_stack, TN_UWord int_stack_size)
Performs first context switch to the first task (_tn_next_task_to_run is already set to needed task)...
PIC32 architecture-dependent routines.
TN_UWord tn_arch_sched_dis_save(void)
Disable kernel scheduler and return previous state.
int _tn_arch_is_int_disabled(void)
Should return 1 if system interrupts are currently disabled, 0 otherwise.
TN_UWord * _tn_arch_stack_init(TN_TaskBody *task_func, TN_UWord *stack_low_addr, TN_UWord *stack_high_addr, void *param)
Should put initial CPU context to the provided stack pointer for new task and return current stack po...
void _tn_arch_context_switch_pend(void)
Called whenever we need to switch context from one task to another.
void tn_arch_sched_restore(TN_UWord sched_state)
Restore state of the kernel scheduler.
void tn_arch_int_en(void)
Unconditionally enable interrupts.
void tn_arch_int_dis(void)
Unconditionally disable system interrupts.
PIC24/dsPIC architecture-dependent routines.
int _tn_arch_inside_isr(void)
Should return 1 if system ISR is currently running, 0 otherwise.
void( TN_TaskBody)(void *param)
Prototype for task body function.
Definition: tn_common.h:145
TN_UWord tn_arch_sr_save_int_dis(void)
Disable system interrupts and return previous value of status register, atomically.
void _tn_arch_context_switch_now_nosave(void)
Called whenever we need to switch context to new task, but don't save current context.
void tn_arch_sr_restore(TN_UWord sr)
Restore previously saved status register.
unsigned int TN_UWord
Unsigned integer type whose size is equal to the size of CPU register.