TNeo  BETA v1.08-11-g97e5a6d
tn_arch_example.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  * Example of architecture-dependent routines
41  */
42 
43 
44 #ifndef _TN_ARCH_EXAMPLE_H
45 #define _TN_ARCH_EXAMPLE_H
46 
47 /**
48  * FFS - find first set bit. Used in `_find_next_task_to_run()` function.
49  * Say, for `0xa8` it should return `3`.
50  *
51  * May be not defined: in this case, naive algorithm will be used.
52  */
53 #define _TN_FFS(x) (32 - __builtin_clz((x) & (0 - (x))))
54 
55 /**
56  * Used by the kernel as a signal that something really bad happened.
57  * Indicates TNeo bugs as well as illegal kernel usage, e.g. sleeping in
58  * the idle task callback or build-time configuration mismatch (see
59  * `#TN_CHECK_BUILD_CFG` for details on the last one)
60  *
61  * Typically, set to assembler instruction that causes debugger to halt.
62  */
63 #define _TN_FATAL_ERRORF(error_msg, ...) \
64  {__asm__ volatile(" sdbbp 0"); __asm__ volatile ("nop");}
65 
66 
67 
68 
69 /**
70  * Compiler-specific attribute that should be placed **before** declaration of
71  * array used for stack. It is needed because there are often additional
72  * restrictions applied to alignment of stack, so, to meet them, stack arrays
73  * need to be declared with these macros.
74  *
75  * @see TN_ARCH_STK_ATTR_AFTER
76  */
77 #define TN_ARCH_STK_ATTR_BEFORE
78 
79 /**
80  * Compiler-specific attribute that should be placed **after** declaration of
81  * array used for stack. It is needed because there are often additional
82  * restrictions applied to alignment of stack, so, to meet them, stack arrays
83  * need to be declared with these macros.
84  *
85  * @see TN_ARCH_STK_ATTR_BEFORE
86  */
87 
88 #define TN_ARCH_STK_ATTR_AFTER __attribute__((aligned(0x8)))
89 
90 /**
91  * Minimum task's stack size, in words, not in bytes; includes a space for
92  * context plus for parameters passed to task's body function.
93  */
94 #define TN_MIN_STACK_SIZE 36
95 
96 /**
97  * Width of `int` type.
98  */
99 #define TN_INT_WIDTH 32
100 
101 /**
102  * Unsigned integer type whose size is equal to the size of CPU register.
103  * Typically it's plain `unsigned int`.
104  */
105 typedef unsigned int TN_UWord;
106 
107 /**
108  * Unsigned integer type that is able to store pointers.
109  * We need it because some platforms don't define `uintptr_t`.
110  * Typically it's `unsigned int`.
111  */
112 typedef unsigned int TN_UIntPtr;
113 
114 /**
115  * Maximum number of priorities available, this value usually matches
116  * `#TN_INT_WIDTH`.
117  *
118  * @see TN_PRIORITIES_CNT
119  */
120 #define TN_PRIORITIES_MAX_CNT TN_INT_WIDTH
121 
122 /**
123  * Value for infinite waiting, usually matches `ULONG_MAX`,
124  * because `#TN_TickCnt` is declared as `unsigned long`.
125  */
126 #define TN_WAIT_INFINITE (TN_TickCnt)0xFFFFFFFF
127 
128 /**
129  * Value for initializing the unused space of task's stack
130  */
131 #define TN_FILL_STACK_VAL 0xFEEDFACE
132 
133 
134 
135 
136 /**
137  * Declares variable that is used by macros `TN_INT_DIS_SAVE()` and
138  * `TN_INT_RESTORE()` for storing status register value.
139  *
140  * @see `TN_INT_DIS_SAVE()`
141  * @see `TN_INT_RESTORE()`
142  */
143 #define TN_INTSAVE_DATA int tn_save_status_reg = 0;
144 
145 /**
146  * The same as `#TN_INTSAVE_DATA` but for using in ISR together with
147  * `TN_INT_IDIS_SAVE()`, `TN_INT_IRESTORE()`.
148  *
149  * @see `TN_INT_IDIS_SAVE()`
150  * @see `TN_INT_IRESTORE()`
151  */
152 #define TN_INTSAVE_DATA_INT TN_INTSAVE_DATA
153 
154 /**
155  * Disable interrupts and return previous value of status register,
156  * atomically. Similar `tn_arch_sr_save_int_dis()`, but implemented
157  * as a macro, so it is potentially faster.
158  *
159  * Uses `#TN_INTSAVE_DATA` as a temporary storage.
160  *
161  * @see `#TN_INTSAVE_DATA`
162  * @see `tn_arch_sr_save_int_dis()`
163  */
164 #define TN_INT_DIS_SAVE() tn_save_status_reg = tn_arch_sr_save_int_dis()
165 
166 /**
167  * Restore previously saved status register.
168  * Similar to `tn_arch_sr_restore()`, but implemented as a macro,
169  * so it is potentially faster.
170  *
171  * Uses `#TN_INTSAVE_DATA` as a temporary storage.
172  *
173  * @see `#TN_INTSAVE_DATA`
174  * @see `tn_arch_sr_save_int_dis()`
175  */
176 #define TN_INT_RESTORE() tn_arch_sr_restore(tn_save_status_reg)
177 
178 /**
179  * The same as `TN_INT_DIS_SAVE()` but for using in ISR.
180  *
181  * Uses `#TN_INTSAVE_DATA_INT` as a temporary storage.
182  *
183  * @see `#TN_INTSAVE_DATA_INT`
184  */
185 #define TN_INT_IDIS_SAVE() TN_INT_DIS_SAVE()
186 
187 /**
188  * The same as `TN_INT_RESTORE()` but for using in ISR.
189  *
190  * Uses `#TN_INTSAVE_DATA_INT` as a temporary storage.
191  *
192  * @see `#TN_INTSAVE_DATA_INT`
193  */
194 #define TN_INT_IRESTORE() TN_INT_RESTORE()
195 
196 /**
197  * Returns nonzero if interrupts are disabled, zero otherwise.
198  */
199 #define TN_IS_INT_DISABLED() ((__builtin_mfc0(12, 0) & 1) == 0)
200 
201 /**
202  * Pend context switch from interrupt.
203  */
204 #define _TN_CONTEXT_SWITCH_IPEND_IF_NEEDED() \
205  _tn_context_switch_pend_if_needed()
206 
207 
208 /**
209  * Converts size in bytes to size in `#TN_UWord`.
210  * For 32-bit platforms, we should shift it by 2 bit to the right;
211  * for 16-bit platforms, we should shift it by 1 bit to the right.
212  */
213 #define _TN_SIZE_BYTES_TO_UWORDS(size_in_bytes) ((size_in_bytes) >> 2)
214 
215 /**
216  * If compiler does not conform to c99 standard, there's no inline keyword.
217  * So, there's a special macro for that.
218  */
219 #if TN_FORCED_INLINE
220 //TODO: if available, use some compiler-specific forced inline qualifier
221 # define _TN_INLINE inline
222 #else
223 # define _TN_INLINE inline
224 #endif
225 
226 /**
227  * For some compilers, order of these qualifiers matters
228  * (at least when _TN_INLINE expands to some compiler-specific forced inline)
229  */
230 #define _TN_STATIC_INLINE static _TN_INLINE
231 
232 /**
233  * Sometimes compilers are buggy in high-optimization modes, and these
234  * bugs are often could be worked around by adding the `volatile` keyword.
235  *
236  * It is compiler-dependent, so, there's a special macro for that.
237  */
238 #define _TN_VOLATILE_WORKAROUND /* nothing */
239 
240 
241 #endif // _TN_ARCH_EXAMPLE_H
unsigned int TN_UIntPtr
Unsigned integer type that is able to store pointers.
unsigned int TN_UWord
Unsigned integer type whose size is equal to the size of CPU register.