diff options
Diffstat (limited to 'lib/chibios-contrib/os/common/ports/MSP430X/chcore.h')
-rw-r--r-- | lib/chibios-contrib/os/common/ports/MSP430X/chcore.h | 443 |
1 files changed, 443 insertions, 0 deletions
diff --git a/lib/chibios-contrib/os/common/ports/MSP430X/chcore.h b/lib/chibios-contrib/os/common/ports/MSP430X/chcore.h new file mode 100644 index 000000000..7776e9f93 --- /dev/null +++ b/lib/chibios-contrib/os/common/ports/MSP430X/chcore.h | |||
@@ -0,0 +1,443 @@ | |||
1 | /* | ||
2 | ChibiOS/HAL - Copyright (C) 2016 Andrew Wygle aka awygle | ||
3 | |||
4 | Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | you may not use this file except in compliance with the License. | ||
6 | You may obtain a copy of the License at | ||
7 | |||
8 | http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | |||
10 | Unless required by applicable law or agreed to in writing, software | ||
11 | distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | See the License for the specific language governing permissions and | ||
14 | limitations under the License. | ||
15 | */ | ||
16 | |||
17 | /** | ||
18 | * @file MSP430X/nilcore.h | ||
19 | * @brief MSP430X port macros and structures. | ||
20 | * | ||
21 | * @addtogroup MSP430X_CORE | ||
22 | * @{ | ||
23 | */ | ||
24 | |||
25 | #ifndef CHCORE_H | ||
26 | #define CHCORE_H | ||
27 | |||
28 | #include <msp430.h> | ||
29 | #include <in430.h> | ||
30 | |||
31 | extern bool __msp430x_in_isr; | ||
32 | |||
33 | /*===========================================================================*/ | ||
34 | /* Module constants. */ | ||
35 | /*===========================================================================*/ | ||
36 | |||
37 | /** | ||
38 | * @name Architecture and Compiler | ||
39 | * @{ | ||
40 | */ | ||
41 | /** | ||
42 | * @brief Macro defining the port architecture. | ||
43 | */ | ||
44 | #define PORT_ARCHITECTURE_MSP430X | ||
45 | |||
46 | /** | ||
47 | * @brief Name of the implemented architecture. | ||
48 | */ | ||
49 | #define PORT_ARCHITECTURE_NAME "MSP430X" | ||
50 | |||
51 | /** | ||
52 | * @brief Name of the architecture variant. | ||
53 | */ | ||
54 | #define PORT_CORE_VARIANT_NAME "MSP430Xv2" | ||
55 | |||
56 | /* The following code is not processed when the file is included from an | ||
57 | * asm module because those intrinsic macrosa re not necessarily defined | ||
58 | * by the assembler too.*/ | ||
59 | #if !defined(_FROM_ASM_) | ||
60 | |||
61 | /** | ||
62 | * @brief Compiler name and version. | ||
63 | */ | ||
64 | #if defined(__GNUC__) || defined(__DOXYGEN__) | ||
65 | #define PORT_COMPILER_NAME "GCC " __VERSION__ | ||
66 | |||
67 | #else | ||
68 | #error "unsupported compiler" | ||
69 | #endif | ||
70 | |||
71 | #endif /* !defined(_FROM_ASM_) */ | ||
72 | /** | ||
73 | * @brief Port-specific information string. | ||
74 | */ | ||
75 | #define PORT_INFO "16 bits code addressing" | ||
76 | |||
77 | /** | ||
78 | * @brief This port supports a realtime counter. | ||
79 | */ | ||
80 | #define PORT_SUPPORTS_RT FALSE | ||
81 | /** @} */ | ||
82 | |||
83 | /*===========================================================================*/ | ||
84 | /* Module pre-compile time settings. */ | ||
85 | /*===========================================================================*/ | ||
86 | |||
87 | /** | ||
88 | * @brief Stack size for the system idle thread. | ||
89 | * @details This size depends on the idle thread implementation, usually | ||
90 | * the idle thread should take no more space than those reserved | ||
91 | * by @p PORT_INT_REQUIRED_STACK. | ||
92 | * @note In this port it is set to 8. | ||
93 | */ | ||
94 | #if !defined(PORT_IDLE_THREAD_STACK_SIZE) || defined(__DOXYGEN__) | ||
95 | #define PORT_IDLE_THREAD_STACK_SIZE 8 | ||
96 | #endif | ||
97 | |||
98 | /** | ||
99 | * @brief Per-thread stack overhead for interrupts servicing. | ||
100 | * @details This constant is used in the calculation of the correct working | ||
101 | * area size. | ||
102 | * @note In this port the default is 32 bytes per thread. | ||
103 | */ | ||
104 | #if !defined(PORT_INT_REQUIRED_STACK) || defined(__DOXYGEN__) | ||
105 | #define PORT_INT_REQUIRED_STACK 32 | ||
106 | #endif | ||
107 | |||
108 | /** | ||
109 | * @brief Enables an alternative timer implementation. | ||
110 | * @details Usually the port uses a timer interface defined in the file | ||
111 | * @p nilcore_timer.h, if this option is enabled then the file | ||
112 | * @p nilcore_timer_alt.h is included instead. | ||
113 | */ | ||
114 | #if !defined(PORT_USE_ALT_TIMER) | ||
115 | #define PORT_USE_ALT_TIMER FALSE | ||
116 | #endif | ||
117 | |||
118 | /*===========================================================================*/ | ||
119 | /* Derived constants and error checks. */ | ||
120 | /*===========================================================================*/ | ||
121 | |||
122 | /*===========================================================================*/ | ||
123 | /* Module data structures and types. */ | ||
124 | /*===========================================================================*/ | ||
125 | |||
126 | /* The following code is not processed when the file is included from an | ||
127 | asm module.*/ | ||
128 | #if !defined(_FROM_ASM_) | ||
129 | |||
130 | /** | ||
131 | * @brief Type of stack and memory alignment enforcement. | ||
132 | */ | ||
133 | typedef uint16_t stkalign_t; | ||
134 | |||
135 | /** | ||
136 | * @brief Type of natural register size - depends on memory model. | ||
137 | */ | ||
138 | #if defined(__MSP430X_LARGE__) | ||
139 | typedef unsigned __int20 reg_t; | ||
140 | #else | ||
141 | typedef uint16_t reg_t; | ||
142 | #endif | ||
143 | |||
144 | /** | ||
145 | * @brief Natural alignment constant. | ||
146 | * @note It is the minimum alignment for pointer-size variables. | ||
147 | */ | ||
148 | #define PORT_NATURAL_ALIGN 2U | ||
149 | |||
150 | /** | ||
151 | * @brief Stack alignment constant. | ||
152 | * @note It is the alignement required for the stack pointer. | ||
153 | */ | ||
154 | #define PORT_STACK_ALIGN 2U | ||
155 | |||
156 | /** | ||
157 | * @brief Working Areas alignment constant. | ||
158 | * @note It is the alignment to be enforced for thread working areas. | ||
159 | */ | ||
160 | #define PORT_WORKING_AREA_ALIGN 2U | ||
161 | /** @} */ | ||
162 | |||
163 | /** | ||
164 | * @brief System saved context. | ||
165 | * @details This structure represents the inner stack frame during a context | ||
166 | * switching. | ||
167 | */ | ||
168 | struct port_intctx { | ||
169 | reg_t r4; | ||
170 | reg_t r5; | ||
171 | reg_t r6; | ||
172 | reg_t r7; | ||
173 | reg_t r8; | ||
174 | reg_t r9; | ||
175 | reg_t r10; | ||
176 | reg_t r0; /* program counter */ | ||
177 | }; | ||
178 | |||
179 | /** | ||
180 | * @brief Platform dependent part of the @p thread_t structure. | ||
181 | * @details This structure usually contains just the saved stack pointer | ||
182 | * defined as a pointer to a @p port_intctx structure. | ||
183 | */ | ||
184 | struct port_context { | ||
185 | struct port_intctx *sp; | ||
186 | }; | ||
187 | |||
188 | #endif /* !defined(_FROM_ASM_) */ | ||
189 | |||
190 | /*===========================================================================*/ | ||
191 | /* Module macros. */ | ||
192 | /*===========================================================================*/ | ||
193 | |||
194 | /** | ||
195 | * @brief Platform dependent thread stack setup. | ||
196 | * @details This code usually setup the context switching frame represented | ||
197 | * by an @p port_intctx structure. | ||
198 | */ | ||
199 | #define PORT_SETUP_CONTEXT(tp, wbase, wtop, pf, arg) { \ | ||
200 | (tp)->ctx.sp = (struct port_intctx*)(((uint8_t *)(wtop)) - \ | ||
201 | sizeof(struct port_intctx)); \ | ||
202 | (tp)->ctx.sp->r4 = (reg_t)pf; \ | ||
203 | (tp)->ctx.sp->r5 = (reg_t)arg; \ | ||
204 | (tp)->ctx.sp->r0 = (reg_t)_port_thread_start; \ | ||
205 | } | ||
206 | |||
207 | /** | ||
208 | * @brief Static working area allocation. | ||
209 | * @details This macro is used to allocate a static thread working area | ||
210 | * aligned as both position and size. | ||
211 | * | ||
212 | * @param[in] s the name to be assigned to the stack array | ||
213 | * @param[in] n the stack size to be assigned to the thread | ||
214 | */ | ||
215 | #define PORT_WORKING_AREA(s, n) \ | ||
216 | stkalign_t s[THD_WORKING_AREA_SIZE(n) / sizeof (stkalign_t)] | ||
217 | |||
218 | /** | ||
219 | * @brief Computes the thread working area global size. | ||
220 | * @note There is no need to perform alignments in this macro. | ||
221 | */ | ||
222 | #define PORT_WA_SIZE(n) ((sizeof(struct port_intctx) - 1) + \ | ||
223 | (n) + (PORT_INT_REQUIRED_STACK)) | ||
224 | |||
225 | /** | ||
226 | * @brief IRQ prologue code. | ||
227 | * @details This macro must be inserted at the start of all IRQ handlers | ||
228 | * enabled to invoke system APIs. | ||
229 | */ | ||
230 | #define PORT_IRQ_PROLOGUE() __msp430x_in_isr = true; | ||
231 | |||
232 | /** | ||
233 | * @brief IRQ epilogue code. | ||
234 | * @details This macro must be inserted at the end of all IRQ handlers | ||
235 | * enabled to invoke system APIs. | ||
236 | */ | ||
237 | #define PORT_IRQ_EPILOGUE() { \ | ||
238 | __msp430x_in_isr = false; \ | ||
239 | _dbg_check_lock(); \ | ||
240 | if (chSchIsPreemptionRequired()) \ | ||
241 | chSchDoReschedule(); \ | ||
242 | _dbg_check_unlock(); \ | ||
243 | } | ||
244 | |||
245 | /** | ||
246 | * @brief IRQ handler function declaration. | ||
247 | * @note @p id can be a function name or a vector number depending on the | ||
248 | * port implementation. | ||
249 | */ | ||
250 | #define PORT_IRQ_HANDLER(id) __attribute__ ((interrupt(id))) \ | ||
251 | void ISR_ ## id (void) | ||
252 | |||
253 | /** | ||
254 | * @brief Fast IRQ handler function declaration. | ||
255 | * @note @p id can be a function name or a vector number depending on the | ||
256 | * port implementation. | ||
257 | */ | ||
258 | #define PORT_FAST_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id) | ||
259 | |||
260 | /** | ||
261 | * @brief Performs a context switch between two threads. | ||
262 | * @details This is the most critical code in any port, this function | ||
263 | * is responsible for the context switch between 2 threads. | ||
264 | * @note The implementation of this code affects <b>directly</b> the context | ||
265 | * switch performance so optimize here as much as you can. | ||
266 | * | ||
267 | * @param[in] ntp the thread to be switched in | ||
268 | * @param[in] otp the thread to be switched out | ||
269 | */ | ||
270 | #define port_switch(ntp, otp) _port_switch(ntp, otp) | ||
271 | |||
272 | /*===========================================================================*/ | ||
273 | /* External declarations. */ | ||
274 | /*===========================================================================*/ | ||
275 | |||
276 | /* The following code is not processed when the file is included from an | ||
277 | asm module.*/ | ||
278 | #if !defined(_FROM_ASM_) | ||
279 | |||
280 | #ifdef __cplusplus | ||
281 | extern "C" { | ||
282 | #endif | ||
283 | void _port_irq_epilogue(void); | ||
284 | void _port_switch(thread_t *ntp, thread_t *otp); | ||
285 | void _port_thread_start(void); | ||
286 | #ifdef __cplusplus | ||
287 | } | ||
288 | #endif | ||
289 | |||
290 | #endif /* !defined(_FROM_ASM_) */ | ||
291 | |||
292 | /*===========================================================================*/ | ||
293 | /* Module inline functions. */ | ||
294 | /*===========================================================================*/ | ||
295 | |||
296 | /* The following code is not processed when the file is included from an | ||
297 | asm module.*/ | ||
298 | #if !defined(_FROM_ASM_) | ||
299 | |||
300 | /** | ||
301 | * @brief Port-related initialization code. | ||
302 | */ | ||
303 | static inline void port_init(void) { | ||
304 | __msp430x_in_isr = false; | ||
305 | } | ||
306 | |||
307 | /** | ||
308 | * @brief Returns a word encoding the current interrupts status. | ||
309 | * | ||
310 | * @return The interrupts status. | ||
311 | */ | ||
312 | static inline syssts_t port_get_irq_status(void) { | ||
313 | |||
314 | return __get_SR_register(); | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * @brief Checks the interrupt status. | ||
319 | * | ||
320 | * @param[in] sts the interrupt status word | ||
321 | * | ||
322 | * @return The interrupt status. | ||
323 | * @retvel false the word specified a disabled interrupts status. | ||
324 | * @retvel true the word specified an enabled interrupts status. | ||
325 | */ | ||
326 | static inline bool port_irq_enabled(syssts_t sts) { | ||
327 | |||
328 | return sts & GIE; | ||
329 | } | ||
330 | |||
331 | /** | ||
332 | * @brief Determines the current execution context. | ||
333 | * | ||
334 | * @return The execution context. | ||
335 | * @retval false not running in ISR mode. | ||
336 | * @retval true running in ISR mode. | ||
337 | */ | ||
338 | static inline bool port_is_isr_context(void) { | ||
339 | return __msp430x_in_isr; | ||
340 | } | ||
341 | |||
342 | /** | ||
343 | * @brief Kernel-lock action. | ||
344 | */ | ||
345 | static inline void port_lock(void) { | ||
346 | |||
347 | _disable_interrupts(); | ||
348 | asm volatile("nop"); | ||
349 | } | ||
350 | |||
351 | /** | ||
352 | * @brief Kernel-unlock action. | ||
353 | */ | ||
354 | static inline void port_unlock(void) { | ||
355 | asm volatile("nop"); | ||
356 | _enable_interrupts(); | ||
357 | } | ||
358 | |||
359 | /** | ||
360 | * @brief Kernel-lock action from an interrupt handler. | ||
361 | * @note This function is empty in this port. | ||
362 | */ | ||
363 | static inline void port_lock_from_isr(void) { | ||
364 | |||
365 | } | ||
366 | |||
367 | /** | ||
368 | * @brief Kernel-unlock action from an interrupt handler. | ||
369 | * @note This function is empty in this port. | ||
370 | */ | ||
371 | static inline void port_unlock_from_isr(void) { | ||
372 | |||
373 | } | ||
374 | |||
375 | /** | ||
376 | * @brief Disables all the interrupt sources. | ||
377 | */ | ||
378 | static inline void port_disable(void) { | ||
379 | |||
380 | _disable_interrupts(); | ||
381 | asm volatile("nop"); | ||
382 | } | ||
383 | |||
384 | /** | ||
385 | * @brief Disables the interrupt sources below kernel-level priority. | ||
386 | */ | ||
387 | static inline void port_suspend(void) { | ||
388 | |||
389 | _disable_interrupts(); | ||
390 | asm volatile("nop"); | ||
391 | } | ||
392 | |||
393 | /** | ||
394 | * @brief Enables all the interrupt sources. | ||
395 | */ | ||
396 | static inline void port_enable(void) { | ||
397 | |||
398 | asm volatile("nop"); | ||
399 | _enable_interrupts(); | ||
400 | } | ||
401 | |||
402 | /** | ||
403 | * @brief Enters an architecture-dependent IRQ-waiting mode. | ||
404 | * @details The function is meant to return when an interrupt becomes pending. | ||
405 | * The simplest implementation is an empty function or macro but this | ||
406 | * would not take advantage of architecture-specific power saving | ||
407 | * modes. | ||
408 | */ | ||
409 | static inline void port_wait_for_interrupt(void) { | ||
410 | |||
411 | } | ||
412 | |||
413 | /** | ||
414 | * @brief Returns the current value of the realtime counter. | ||
415 | * | ||
416 | * @return The realtime counter value. | ||
417 | */ | ||
418 | static inline rtcnt_t port_rt_get_counter_value(void) { | ||
419 | /* TODO implement realtime counter */ | ||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | #endif /* !defined(_FROM_ASM_) */ | ||
424 | |||
425 | /*===========================================================================*/ | ||
426 | /* Module late inclusions. */ | ||
427 | /*===========================================================================*/ | ||
428 | |||
429 | #if !defined(_FROM_ASM_) | ||
430 | |||
431 | #if CH_CFG_ST_TIMEDELTA > 0 | ||
432 | #if !PORT_USE_ALT_TIMER | ||
433 | #include "chcore_timer.h" | ||
434 | #else /* PORT_USE_ALT_TIMER */ | ||
435 | #include "chcore_timer_alt.h" | ||
436 | #endif /* PORT_USE_ALT_TIMER */ | ||
437 | #endif /* CH_CFG_ST_TIMEDELTA > 0 */ | ||
438 | |||
439 | #endif /* !defined(_FROM_ASM_) */ | ||
440 | |||
441 | #endif /* CHCORE_H */ | ||
442 | |||
443 | /** @} */ | ||