TNeo  v1.06
 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  * ACTUAL PORT IMPLEMENTATION
57  ******************************************************************************/
58 
59 #if defined(__TN_ARCH_PIC32MX__)
60 # include "pic32/tn_arch_pic32.h"
61 #elif defined(__TN_ARCH_PIC24_DSPIC__)
63 #elif defined(__TN_ARCH_CORTEX_M__)
65 #else
66 # error "unknown platform"
67 #endif
68 
69 
70 
71 #ifdef __cplusplus
72 extern "C" { /*}*/
73 #endif
74 
75 /*******************************************************************************
76  * PUBLIC FUNCTION PROTOTYPES
77  ******************************************************************************/
78 
79 
80 /**
81  * Unconditionally disable <i>system interrupts</i>.
82  *
83  * Refer to the section \ref interrupt_types for details on what is <i>system
84  * interrupt</i>.
85  */
86 void tn_arch_int_dis(void);
87 
88 /**
89  * Unconditionally enable interrupts
90  *
91  * Refer to the section \ref interrupt_types for details on what is <i>system
92  * interrupt</i>.
93  */
94 void tn_arch_int_en(void);
95 
96 /**
97  * Disable <i>system interrupts</i> and return previous value of status
98  * register, atomically.
99  *
100  * Refer to the section \ref interrupt_types for details on what is <i>system
101  * interrupt</i>.
102  *
103  * @see `tn_arch_sr_restore()`
104  */
106 
107 /**
108  * Restore previously saved status register.
109  *
110  * @param sr status register value previously from
111  * `tn_arch_sr_save_int_dis()`
112  *
113  * @see `tn_arch_sr_save_int_dis()`
114  */
116 
117 
118 
119 /**
120  * Should return top of the stack.
121  *
122  * A stack implementation is characterized by two attributes:
123  *
124  * - Where the stack pointer points:
125  * - *Full stack*: The stack pointer points to the last full location;
126  * - *Empty stack*: The stack pointer points to the first empty location.
127  * - How the stack grows:
128  * - *Descending stack*: The stack grows downward (i.e., toward lower memory
129  * addresses);
130  * - *Ascending stack*: The stack grows upward (i.e., toward higher memory
131  * addresses).
132  *
133  * So, depending on the stack implementation used in the particular
134  * architecture, the value returned from this function can be one of the
135  * following:
136  *
137  * - `(stack_low_address - 1)` (*Full ascending stack*)
138  * - `(stack_low_address + stack_size)` (*Full descending stack*)
139  * - `(stack_low_address)` (*Empty ascending stack*)
140  * - `(stack_low_address + stack_size - 1)` (*Empty descending stack*)
141  *
142  * @param stack_low_address
143  * Start address of the stack array.
144  * @param stack_size
145  * Size of the stack in `#TN_UWord`-s, not in bytes.
146  */
148  TN_UWord *stack_low_address,
149  int stack_size
150  );
151 
152 /**
153  * This function should return address of bottom empty element of stack, it is
154  * needed for software stack overflow control (see `#TN_STACK_OVERFLOW_CHECK`).
155  *
156  * For details on various hardware stack implementations, refer to
157  * `#_tn_arch_stack_top_get()`.
158  *
159  * Depending on the stack implementation used in the particular architecture,
160  * the value returned from this function can be one of the following:
161  *
162  * - `(stack_top - stack_size)` (*Full descending stack*)
163  * - `(stack_top + stack_size)` (*Full ascending stack*)
164  * - `(stack_top - stack_size + 1)` (*Empty descending stack*)
165  * - `(stack_top + stack_size - 1)` (*Empty ascending stack*)
166  *
167  * @param stack_top
168  * Top of the stack, returned by `_tn_arch_stack_top_get()`.
169  * @param stack_size
170  * Size of the stack in `#TN_UWord`-s, not in bytes.
171  */
173  TN_UWord *stack_top,
174  int stack_size
175  );
176 
177 /**
178  * Should put initial CPU context to the provided stack pointer for new task
179  * and return current stack pointer.
180  *
181  * When resulting context gets restored by
182  * `_tn_arch_context_switch_now_nosave()` or `_tn_arch_context_switch_pend()`,
183  * the following conditions should be met:
184  *
185  * - Interrupts are enabled;
186  * - Return address is set to `tn_task_exit()`, so that when task body function
187  * returns, `tn_task_exit()` gets automatially called;
188  * - Argument 0 contains `param` pointer
189  *
190  * @param task_func
191  * Pointer to task body function.
192  * @param stack_top
193  * Top of the stack, returned by `_tn_arch_stack_top_get()`.
194  * @param stack_size
195  * Size of the stack in `#TN_UWord`-s, not in bytes.
196  * @param param
197  * User-provided parameter for task body function.
198  *
199  * @return current stack pointer (top of the stack)
200  */
202  TN_TaskBody *task_func,
203  TN_UWord *stack_top,
204  int stack_size,
205  void *param
206  );
207 
208 
209 
210 /**
211  * Should return 1 if <i>system ISR</i> is currently running, 0 otherwise.
212  *
213  * Refer to the section \ref interrupt_types for details on what is <i>system
214  * ISR</i>.
215  */
216 int _tn_arch_inside_isr(void);
217 
218 /**
219  * Should return 1 if <i>system interrupts</i> are currently disabled, 0
220  * otherwise.
221  *
222  * Refer to the section \ref interrupt_types for details on what is <i>system
223  * interrupt</i>.
224  */
225 int _tn_arch_is_int_disabled(void);
226 
227 /**
228  * Called whenever we need to switch context from one task to another.
229  *
230  * This function typically does NOT switch context; it merely pends it,
231  * that is, it sets appropriate interrupt flag. If current level is an
232  * application level, interrupt is fired immediately, and context gets
233  * switched. Otherwise (if some ISR is currently running), context switch
234  * keeps pending until all ISR return.
235  *
236  * **Preconditions:**
237  *
238  * - interrupts are enabled;
239  * - `_tn_curr_run_task` points to currently running (preempted) task;
240  * - `_tn_next_task_to_run` points to new task to run.
241  *
242  * **Actions to perform in actual context switching routine:**
243  *
244  * - save context of the preempted task to its stack;
245  * - if preprocessor macro `#_TN_ON_CONTEXT_SWITCH_HANDLER` is non-zero, call
246  * `_tn_sys_on_context_switch(_tn_curr_run_task, _tn_next_task_to_run);`.
247  * - set `_tn_curr_run_task` to `_tn_next_task_to_run`;
248  * - restore context of the newly activated task from its stack.
249  *
250  * @see `_tn_curr_run_task`
251  * @see `_tn_next_task_to_run`
252  */
254 
255 /**
256  * Called whenever we need to switch context to new task, but don't save
257  * current context. This happens:
258  * - At system start, inside `tn_sys_start()`
259  * (well, it is actually called indirectly but from `_tn_arch_sys_start()`);
260  * - At task exit, inside `tn_task_exit()`.
261  *
262  * This function doesn't need to pend context switch, it switches context
263  * immediately.
264  *
265  * **Preconditions:**
266  *
267  * - interrupts are disabled;
268  * - `_tn_next_task_to_run` is already set to needed task.
269  *
270  * **Actions to perform:**
271  *
272  * - if preprocessor macro `#_TN_ON_CONTEXT_SWITCH_HANDLER` is non-zero, call
273  * `_tn_sys_on_context_switch(_tn_curr_run_task, _tn_next_task_to_run);`.
274  * - set `_tn_curr_run_task` to `_tn_next_task_to_run`;
275  * - restore context of the newly activated task from its stack.
276  *
277  * @see `_tn_curr_run_task`
278  * @see `_tn_next_task_to_run`
279  */
281 
282 /**
283  * Performs first context switch to the first task (`_tn_next_task_to_run` is
284  * already set to needed task).
285  *
286  * Typically, this function just calls `_tn_arch_context_switch_now_nosave()`,
287  * but it also can perform any architecture-dependent actions first, if needed.
288  */
289 void _tn_arch_sys_start(
290  TN_UWord *int_stack,
291  unsigned int int_stack_size
292  );
293 
294 #ifdef __cplusplus
295 } /* extern "C" */
296 #endif
297 
298 
299 
300 
301 
302 
303 
304 
305 
306 #endif /* _TN_ARCH_H */
307 
TN_UWord * _tn_arch_stack_init(TN_TaskBody *task_func, TN_UWord *stack_top, int stack_size, void *param)
Should put initial CPU context to the provided stack pointer for new task and return current stack po...
Cortex-M0/M0+/M3/M4/M4F architecture-dependent routines.
PIC32 architecture-dependent routines.
int _tn_arch_is_int_disabled(void)
Should return 1 if system interrupts are currently disabled, 0 otherwise.
void _tn_arch_context_switch_pend(void)
Called whenever we need to switch context from one task to another.
TN_UWord * _tn_arch_stack_top_get(TN_UWord *stack_low_address, int stack_size)
Should return top of the stack.
void tn_arch_int_en(void)
Unconditionally enable interrupts.
void _tn_arch_sys_start(TN_UWord *int_stack, unsigned int int_stack_size)
Performs first context switch to the first task (_tn_next_task_to_run is already set to needed task)...
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.
TN_UWord * _tn_arch_stack_bottom_empty_get(TN_UWord *stack_top, int stack_size)
This function should return address of bottom empty element of stack, it is needed for software stack...
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.