ChibiOS/RT  6.1.4
chsys.h
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006,2007,2008,2009,2010,2011,2012,2013,2014,
3  2015,2016,2017,2018,2019,2020,2021 Giovanni Di Sirio.
4 
5  This file is part of ChibiOS.
6 
7  ChibiOS is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation version 3 of the License.
10 
11  ChibiOS is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 /**
21  * @file rt/include/chsys.h
22  * @brief System related macros and structures.
23  *
24  * @addtogroup system
25  * @{
26  */
27 
28 #ifndef CHSYS_H
29 #define CHSYS_H
30 
31 /*lint -sem(chSysHalt, r_no)*/
32 
33 /*===========================================================================*/
34 /* Module constants. */
35 /*===========================================================================*/
36 
37 /**
38  * @name Masks of executable integrity checks.
39  * @{
40  */
41 #define CH_INTEGRITY_RLIST 1U
42 #define CH_INTEGRITY_VTLIST 2U
43 #define CH_INTEGRITY_REGISTRY 4U
44 #define CH_INTEGRITY_PORT 8U
45 /** @} */
46 
47 /*===========================================================================*/
48 /* Module pre-compile time settings. */
49 /*===========================================================================*/
50 
51 /*===========================================================================*/
52 /* Derived constants and error checks. */
53 /*===========================================================================*/
54 
55 /*===========================================================================*/
56 /* Module data structures and types. */
57 /*===========================================================================*/
58 
59 /*===========================================================================*/
60 /* Module macros. */
61 /*===========================================================================*/
62 
63 /**
64  * @name ISRs abstraction macros
65  * @{
66  */
67 /**
68  * @brief Priority level validation macro.
69  * @details This macro determines if the passed value is a valid priority
70  * level for the underlying architecture.
71  *
72  * @param[in] prio the priority level
73  * @return Priority range result.
74  * @retval false if the priority is invalid or if the architecture
75  * does not support priorities.
76  * @retval true if the priority is valid.
77  */
78 #if defined(PORT_IRQ_IS_VALID_PRIORITY) || defined(__DOXYGEN__)
79 #define CH_IRQ_IS_VALID_PRIORITY(prio) \
80  PORT_IRQ_IS_VALID_PRIORITY(prio)
81 #else
82 #define CH_IRQ_IS_VALID_PRIORITY(prio) false
83 #endif
84 
85 /**
86  * @brief Priority level validation macro.
87  * @details This macro determines if the passed value is a valid priority
88  * level that cannot preempt the kernel critical zone.
89  *
90  * @param[in] prio the priority level
91  * @return Priority range result.
92  * @retval false if the priority is invalid or if the architecture
93  * does not support priorities.
94  * @retval true if the priority is valid.
95  */
96 #if defined(PORT_IRQ_IS_VALID_KERNEL_PRIORITY) || defined(__DOXYGEN__)
97 #define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) \
98  PORT_IRQ_IS_VALID_KERNEL_PRIORITY(prio)
99 #else
100 #define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) false
101 #endif
102 
103 /**
104  * @brief IRQ handler enter code.
105  * @note Usually IRQ handlers functions are also declared naked.
106  * @note On some architectures this macro can be empty.
107  *
108  * @special
109  */
110 #define CH_IRQ_PROLOGUE() \
111  PORT_IRQ_PROLOGUE(); \
112  CH_CFG_IRQ_PROLOGUE_HOOK(); \
113  _stats_increase_irq(); \
114  _trace_isr_enter(__func__); \
115  _dbg_check_enter_isr()
116 
117 /**
118  * @brief IRQ handler exit code.
119  * @note Usually IRQ handlers function are also declared naked.
120  * @note This macro usually performs the final reschedule by using
121  * @p chSchIsPreemptionRequired() and @p chSchDoReschedule().
122  *
123  * @special
124  */
125 #define CH_IRQ_EPILOGUE() \
126  _dbg_check_leave_isr(); \
127  _trace_isr_leave(__func__); \
128  CH_CFG_IRQ_EPILOGUE_HOOK(); \
129  PORT_IRQ_EPILOGUE()
130 
131 /**
132  * @brief Standard normal IRQ handler declaration.
133  * @note @p id can be a function name or a vector number depending on the
134  * port implementation.
135  *
136  * @special
137  */
138 #define CH_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id)
139 /** @} */
140 
141 /**
142  * @name Fast ISRs abstraction macros
143  * @{
144  */
145 /**
146  * @brief Standard fast IRQ handler declaration.
147  * @note @p id can be a function name or a vector number depending on the
148  * port implementation.
149  * @note Not all architectures support fast interrupts.
150  *
151  * @special
152  */
153 #define CH_FAST_IRQ_HANDLER(id) PORT_FAST_IRQ_HANDLER(id)
154 /** @} */
155 
156 /**
157  * @name Time conversion utilities for the realtime counter
158  * @{
159  */
160 /**
161  * @brief Seconds to realtime counter.
162  * @details Converts from seconds to realtime counter cycles.
163  * @note The macro assumes that @p freq >= @p 1.
164  *
165  * @param[in] freq clock frequency, in Hz, of the realtime counter
166  * @param[in] sec number of seconds
167  * @return The number of cycles.
168  *
169  * @api
170  */
171 #define S2RTC(freq, sec) ((freq) * (sec))
172 
173 /**
174  * @brief Milliseconds to realtime counter.
175  * @details Converts from milliseconds to realtime counter cycles.
176  * @note The result is rounded upward to the next millisecond boundary.
177  * @note The macro assumes that @p freq >= @p 1000.
178  *
179  * @param[in] freq clock frequency, in Hz, of the realtime counter
180  * @param[in] msec number of milliseconds
181  * @return The number of cycles.
182  *
183  * @api
184  */
185 #define MS2RTC(freq, msec) (rtcnt_t)((((freq) + 999UL) / 1000UL) * (msec))
186 
187 /**
188  * @brief Microseconds to realtime counter.
189  * @details Converts from microseconds to realtime counter cycles.
190  * @note The result is rounded upward to the next microsecond boundary.
191  * @note The macro assumes that @p freq >= @p 1000000.
192  *
193  * @param[in] freq clock frequency, in Hz, of the realtime counter
194  * @param[in] usec number of microseconds
195  * @return The number of cycles.
196  *
197  * @api
198  */
199 #define US2RTC(freq, usec) (rtcnt_t)((((freq) + 999999UL) / 1000000UL) * (usec))
200 
201 /**
202  * @brief Realtime counter cycles to seconds.
203  * @details Converts from realtime counter cycles number to seconds.
204  * @note The result is rounded up to the next second boundary.
205  * @note The macro assumes that @p freq >= @p 1.
206  *
207  * @param[in] freq clock frequency, in Hz, of the realtime counter
208  * @param[in] n number of cycles
209  * @return The number of seconds.
210  *
211  * @api
212  */
213 #define RTC2S(freq, n) ((((n) - 1UL) / (freq)) + 1UL)
214 
215 /**
216  * @brief Realtime counter cycles to milliseconds.
217  * @details Converts from realtime counter cycles number to milliseconds.
218  * @note The result is rounded up to the next millisecond boundary.
219  * @note The macro assumes that @p freq >= @p 1000.
220  *
221  * @param[in] freq clock frequency, in Hz, of the realtime counter
222  * @param[in] n number of cycles
223  * @return The number of milliseconds.
224  *
225  * @api
226  */
227 #define RTC2MS(freq, n) ((((n) - 1UL) / ((freq) / 1000UL)) + 1UL)
228 
229 /**
230  * @brief Realtime counter cycles to microseconds.
231  * @details Converts from realtime counter cycles number to microseconds.
232  * @note The result is rounded up to the next microsecond boundary.
233  * @note The macro assumes that @p freq >= @p 1000000.
234  *
235  * @param[in] freq clock frequency, in Hz, of the realtime counter
236  * @param[in] n number of cycles
237  * @return The number of microseconds.
238  *
239  * @api
240  */
241 #define RTC2US(freq, n) ((((n) - 1UL) / ((freq) / 1000000UL)) + 1UL)
242 /** @} */
243 
244 /**
245  * @brief Returns the current value of the system real time counter.
246  * @note This function is only available if the port layer supports the
247  * option @p PORT_SUPPORTS_RT.
248  *
249  * @return The value of the system realtime counter of
250  * type rtcnt_t.
251  *
252  * @xclass
253  */
254 #if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__)
255 #define chSysGetRealtimeCounterX() (rtcnt_t)port_rt_get_counter_value()
256 #endif
257 
258 /**
259  * @brief Performs a context switch.
260  * @note Not a user function, it is meant to be invoked by the scheduler
261  * itself or from within the port layer.
262  *
263  * @param[in] ntp the thread to be switched in
264  * @param[in] otp the thread to be switched out
265  *
266  * @special
267  */
268 #define chSysSwitch(ntp, otp) { \
269  \
270  _trace_switch(ntp, otp); \
271  _stats_ctxswc(ntp, otp); \
272  CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp); \
273  port_switch(ntp, otp); \
274 }
275 
276 /*===========================================================================*/
277 /* External declarations. */
278 /*===========================================================================*/
279 
280 #if !defined(__DOXYGEN__)
281 extern stkalign_t ch_idle_thread_wa[];
282 #endif
283 
284 #ifdef __cplusplus
285 extern "C" {
286 #endif
287  void chSysInit(void);
288  bool chSysIntegrityCheckI(unsigned testmask);
289  void chSysTimerHandlerI(void);
290  syssts_t chSysGetStatusAndLockX(void);
291  void chSysRestoreStatusX(syssts_t sts);
292 #if PORT_SUPPORTS_RT == TRUE
293  bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end);
294  void chSysPolledDelayX(rtcnt_t cycles);
295 #endif
296 #ifdef __cplusplus
297 }
298 #endif
299 
300 /*===========================================================================*/
301 /* Module inline functions. */
302 /*===========================================================================*/
303 
304 /**
305  * @brief Raises the system interrupt priority mask to the maximum level.
306  * @details All the maskable interrupt sources are disabled regardless their
307  * hardware priority.
308  * @note Do not invoke this API from within a kernel lock.
309  *
310  * @special
311  */
312 static inline void chSysDisable(void) {
313 
314  port_disable();
316 }
317 
318 /**
319  * @brief Raises the system interrupt priority mask to system level.
320  * @details The interrupt sources that should not be able to preempt the kernel
321  * are disabled, interrupt sources with higher priority are still
322  * enabled.
323  * @note Do not invoke this API from within a kernel lock.
324  * @note This API is no replacement for @p chSysLock(), the @p chSysLock()
325  * could do more than just disable the interrupts.
326  *
327  * @special
328  */
329 static inline void chSysSuspend(void) {
330 
331  port_suspend();
333 }
334 
335 /**
336  * @brief Lowers the system interrupt priority mask to user level.
337  * @details All the interrupt sources are enabled.
338  * @note Do not invoke this API from within a kernel lock.
339  * @note This API is no replacement for @p chSysUnlock(), the
340  * @p chSysUnlock() could do more than just enable the interrupts.
341  *
342  * @special
343  */
344 static inline void chSysEnable(void) {
345 
347  port_enable();
348 }
349 
350 /**
351  * @brief Enters the kernel lock state.
352  *
353  * @special
354  */
355 static inline void chSysLock(void) {
356 
357  port_lock();
359  _dbg_check_lock();
360 }
361 
362 /**
363  * @brief Leaves the kernel lock state.
364  *
365  * @special
366  */
367 static inline void chSysUnlock(void) {
368 
371 
372  /* The following condition can be triggered by the use of i-class functions
373  in a critical section not followed by a chSchRescheduleS(), this means
374  that the current thread has a lower priority than the next thread in
375  the ready list.*/
376  chDbgAssert((ch.rlist.pqueue.next == &ch.rlist.pqueue) ||
377  (ch.rlist.current->hdr.pqueue.prio >= ch.rlist.pqueue.next->prio),
378  "priority order violation");
379 
380  port_unlock();
381 }
382 
383 /**
384  * @brief Enters the kernel lock state from within an interrupt handler.
385  * @note This API may do nothing on some architectures, it is required
386  * because on ports that support preemptable interrupt handlers
387  * it is required to raise the interrupt mask to the same level of
388  * the system mutual exclusion zone.<br>
389  * It is good practice to invoke this API before invoking any I-class
390  * syscall from an interrupt handler.
391  * @note This API must be invoked exclusively from interrupt handlers.
392  *
393  * @special
394  */
395 static inline void chSysLockFromISR(void) {
396 
397  port_lock_from_isr();
400 }
401 
402 /**
403  * @brief Leaves the kernel lock state from within an interrupt handler.
404  *
405  * @note This API may do nothing on some architectures, it is required
406  * because on ports that support preemptable interrupt handlers
407  * it is required to raise the interrupt mask to the same level of
408  * the system mutual exclusion zone.<br>
409  * It is good practice to invoke this API after invoking any I-class
410  * syscall from an interrupt handler.
411  * @note This API must be invoked exclusively from interrupt handlers.
412  *
413  * @special
414  */
415 static inline void chSysUnlockFromISR(void) {
416 
419  port_unlock_from_isr();
420 }
421 
422 /**
423  * @brief Unconditionally enters the kernel lock state.
424  * @note Can be called without previous knowledge of the current lock state.
425  * The final state is "s-locked".
426  *
427  * @special
428  */
429 static inline void chSysUnconditionalLock(void) {
430 
431  if (port_irq_enabled(port_get_irq_status())) {
432  chSysLock();
433  }
434 }
435 
436 /**
437  * @brief Unconditionally leaves the kernel lock state.
438  * @note Can be called without previous knowledge of the current lock state.
439  * The final state is "normal".
440  *
441  * @special
442  */
443 static inline void chSysUnconditionalUnlock(void) {
444 
445  if (!port_irq_enabled(port_get_irq_status())) {
446  chSysUnlock();
447  }
448 }
449 
450 #if (CH_CFG_NO_IDLE_THREAD == FALSE) || defined(__DOXYGEN__)
451 /**
452  * @brief Returns a pointer to the idle thread.
453  * @pre In order to use this function the option @p CH_CFG_NO_IDLE_THREAD
454  * must be disabled.
455  * @note The reference counter of the idle thread is not incremented but
456  * it is not strictly required being the idle thread a static
457  * object.
458  *
459  * @return Pointer to the idle thread.
460  *
461  * @xclass
462  */
463 static inline thread_t *chSysGetIdleThreadX(void) {
464 
465  return (thread_t *)ch.rlist.pqueue.prev;
466 }
467 #endif /* CH_CFG_NO_IDLE_THREAD == FALSE */
468 
469 #endif /* CHSYS_H */
470 
471 /** @} */
chSysRestoreStatusX
void chSysRestoreStatusX(syssts_t sts)
Restores the specified execution status and leaves a critical zone.
Definition: chsys.c:387
chSysIsCounterWithinX
bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end)
Realtime window test.
Definition: chsys.c:419
chSysLock
static void chSysLock(void)
Enters the kernel lock state.
Definition: chsys.h:355
chSysUnconditionalLock
static void chSysUnconditionalLock(void)
Unconditionally enters the kernel lock state.
Definition: chsys.h:429
chDbgAssert
#define chDbgAssert(c, r)
Condition assertion.
Definition: chdebug.h:127
chSysTimerHandlerI
void chSysTimerHandlerI(void)
Handles time ticks for round robin preemption and timer increments.
Definition: chsys.c:333
chSysIntegrityCheckI
bool chSysIntegrityCheckI(unsigned testmask)
System integrity check.
Definition: chsys.c:232
chSysEnable
static void chSysEnable(void)
Lowers the system interrupt priority mask to user level.
Definition: chsys.h:344
_dbg_check_lock
void _dbg_check_lock(void)
Guard code for chSysLock().
Definition: chdebug.c:148
_dbg_check_disable
void _dbg_check_disable(void)
Guard code for chSysDisable().
Definition: chdebug.c:112
chSysDisable
static void chSysDisable(void)
Raises the system interrupt priority mask to the maximum level.
Definition: chsys.h:312
_stats_stop_measure_crit_isr
void _stats_stop_measure_crit_isr(void)
Stops the measurement of an ISR critical zone.
Definition: chstats.c:119
_stats_start_measure_crit_thd
void _stats_start_measure_crit_thd(void)
Starts the measurement of a thread critical zone.
Definition: chstats.c:95
_dbg_check_suspend
void _dbg_check_suspend(void)
Guard code for chSysSuspend().
Definition: chdebug.c:124
ch_thread
Structure representing a thread.
Definition: chschd.h:134
chSysPolledDelayX
void chSysPolledDelayX(rtcnt_t cycles)
Polled delay.
Definition: chsys.c:436
_stats_start_measure_crit_isr
void _stats_start_measure_crit_isr(void)
Starts the measurement of an ISR critical zone.
Definition: chstats.c:111
_dbg_check_lock_from_isr
void _dbg_check_lock_from_isr(void)
Guard code for chSysLockFromIsr().
Definition: chdebug.c:174
chSysLockFromISR
static void chSysLockFromISR(void)
Enters the kernel lock state from within an interrupt handler.
Definition: chsys.h:395
chSysGetStatusAndLockX
syssts_t chSysGetStatusAndLockX(void)
Returns the execution status and enters a critical zone.
Definition: chsys.c:364
ch
ch_system_t ch
System data structures.
Definition: chschd.c:42
chSysInit
void chSysInit(void)
ChibiOS/RT initialization.
Definition: chsys.c:100
chSysSuspend
static void chSysSuspend(void)
Raises the system interrupt priority mask to system level.
Definition: chsys.h:329
chSysUnlock
static void chSysUnlock(void)
Leaves the kernel lock state.
Definition: chsys.h:367
ch_system::rlist
ready_list_t rlist
Ready list header.
Definition: chschd.h:418
_stats_stop_measure_crit_thd
void _stats_stop_measure_crit_thd(void)
Stops the measurement of a thread critical zone.
Definition: chstats.c:103
_dbg_check_unlock
void _dbg_check_unlock(void)
Guard code for chSysUnlock().
Definition: chdebug.c:161
_dbg_check_unlock_from_isr
void _dbg_check_unlock_from_isr(void)
Guard code for chSysUnlockFromIsr().
Definition: chdebug.c:187
chSysUnlockFromISR
static void chSysUnlockFromISR(void)
Leaves the kernel lock state from within an interrupt handler.
Definition: chsys.h:415
chSysUnconditionalUnlock
static void chSysUnconditionalUnlock(void)
Unconditionally leaves the kernel lock state.
Definition: chsys.h:443
chSysGetIdleThreadX
static thread_t * chSysGetIdleThreadX(void)
Returns a pointer to the idle thread.
Definition: chsys.h:463
_dbg_check_enable
void _dbg_check_enable(void)
Guard code for chSysEnable().
Definition: chdebug.c:136