ChibiOS  21.6.0
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  * @brief Core zero memory affinity macro.
57  * @note The memory is meant to be reachable by both cores but
58  * preferred by core zero.
59  * @note Only uninitialized variables can be tagged with this attribute.
60  */
61 #if defined(PORT_CORE0_BSS_SECTION) || defined(__DOXYGEN__)
62 #define CH_SYS_CORE0_MEMORY PORT_CORE0_BSS_SECTION
63 #else
64 #define CH_SYS_CORE0_MEMORY /* Default.*/
65 #endif
66 
67 /**
68  * @brief Core one memory affinity macro.
69  * @note The memory is meant to be reachable by both cores but
70  * preferred by core one.
71  * @note Only uninitialized variables can be tagged with this attribute.
72  */
73 #if defined(PORT_CORE1_BSS_SECTION) || defined(__DOXYGEN__)
74 #define CH_SYS_CORE1_MEMORY PORT_CORE1_BSS_SECTION
75 #else
76 #define CH_SYS_CORE1_MEMORY /* Default.*/
77 #endif
78 
79 /*===========================================================================*/
80 /* Module data structures and types. */
81 /*===========================================================================*/
82 
83 /**
84  * @brief Access to current core's instance structure.
85  */
86 #if defined(PORT_INSTANCE_ACCESS)
87  #define currcore PORT_INSTANCE_ACCESS
88 #else /* !defined(PORT_INSTANCE_ACCESS) */
89  #if (PORT_CORES_NUMBER > 1) || defined(__DOXYGEN__)
90  #define currcore ch_system.instances[port_get_core_id()]
91  #else
92  #define currcore (&ch0)
93  #endif
94 #endif /* defined(PORT_INSTANCE_ACCESS) */
95 
96 /*===========================================================================*/
97 /* Module macros. */
98 /*===========================================================================*/
99 
100 /**
101  * @name ISRs abstraction macros
102  * @{
103  */
104 /**
105  * @brief Priority level validation macro.
106  * @details This macro determines if the passed value is a valid priority
107  * level for the underlying architecture.
108  *
109  * @param[in] prio the priority level
110  * @return Priority range result.
111  * @retval false if the priority is invalid or if the architecture
112  * does not support priorities.
113  * @retval true if the priority is valid.
114  */
115 #if defined(PORT_IRQ_IS_VALID_PRIORITY) || defined(__DOXYGEN__)
116 #define CH_IRQ_IS_VALID_PRIORITY(prio) \
117  PORT_IRQ_IS_VALID_PRIORITY(prio)
118 #else
119 #define CH_IRQ_IS_VALID_PRIORITY(prio) false
120 #endif
121 
122 /**
123  * @brief Priority level validation macro.
124  * @details This macro determines if the passed value is a valid priority
125  * level that cannot preempt the kernel critical zone.
126  *
127  * @param[in] prio the priority level
128  * @return Priority range result.
129  * @retval false if the priority is invalid or if the architecture
130  * does not support priorities.
131  * @retval true if the priority is valid.
132  */
133 #if defined(PORT_IRQ_IS_VALID_KERNEL_PRIORITY) || defined(__DOXYGEN__)
134 #define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) \
135  PORT_IRQ_IS_VALID_KERNEL_PRIORITY(prio)
136 #else
137 #define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) false
138 #endif
139 
140 /**
141  * @brief IRQ handler enter code.
142  * @note Usually IRQ handlers functions are also declared naked.
143  * @note On some architectures this macro can be empty.
144  *
145  * @special
146  */
147 #define CH_IRQ_PROLOGUE() \
148  PORT_IRQ_PROLOGUE(); \
149  CH_CFG_IRQ_PROLOGUE_HOOK(); \
150  __stats_increase_irq(); \
151  __trace_isr_enter(__func__); \
152  __dbg_check_enter_isr()
153 
154 /**
155  * @brief IRQ handler exit code.
156  * @note Usually IRQ handlers function are also declared naked.
157  * @note This macro usually performs the final reschedule by using
158  * @p chSchIsPreemptionRequired() and @p chSchDoReschedule().
159  *
160  * @special
161  */
162 #define CH_IRQ_EPILOGUE() \
163  __dbg_check_leave_isr(); \
164  __trace_isr_leave(__func__); \
165  CH_CFG_IRQ_EPILOGUE_HOOK(); \
166  PORT_IRQ_EPILOGUE()
167 
168 /**
169  * @brief Standard normal IRQ handler declaration.
170  * @note @p id can be a function name or a vector number depending on the
171  * port implementation.
172  *
173  * @special
174  */
175 #define CH_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id)
176 /** @} */
177 
178 /**
179  * @name Fast ISRs abstraction macros
180  * @{
181  */
182 /**
183  * @brief Standard fast IRQ handler declaration.
184  * @note @p id can be a function name or a vector number depending on the
185  * port implementation.
186  * @note Not all architectures support fast interrupts.
187  *
188  * @special
189  */
190 #define CH_FAST_IRQ_HANDLER(id) PORT_FAST_IRQ_HANDLER(id)
191 /** @} */
192 
193 /**
194  * @name Time conversion utilities for the realtime counter
195  * @{
196  */
197 /**
198  * @brief Seconds to realtime counter.
199  * @details Converts from seconds to realtime counter cycles.
200  * @note The macro assumes that @p freq >= @p 1.
201  *
202  * @param[in] freq clock frequency, in Hz, of the realtime counter
203  * @param[in] sec number of seconds
204  * @return The number of cycles.
205  *
206  * @api
207  */
208 #define S2RTC(freq, sec) ((freq) * (sec))
209 
210 /**
211  * @brief Milliseconds to realtime counter.
212  * @details Converts from milliseconds to realtime counter cycles.
213  * @note The result is rounded upward to the next millisecond boundary.
214  * @note The macro assumes that @p freq >= @p 1000.
215  *
216  * @param[in] freq clock frequency, in Hz, of the realtime counter
217  * @param[in] msec number of milliseconds
218  * @return The number of cycles.
219  *
220  * @api
221  */
222 #define MS2RTC(freq, msec) (rtcnt_t)((((freq) + 999UL) / 1000UL) * (msec))
223 
224 /**
225  * @brief Microseconds to realtime counter.
226  * @details Converts from microseconds to realtime counter cycles.
227  * @note The result is rounded upward to the next microsecond boundary.
228  * @note The macro assumes that @p freq >= @p 1000000.
229  *
230  * @param[in] freq clock frequency, in Hz, of the realtime counter
231  * @param[in] usec number of microseconds
232  * @return The number of cycles.
233  *
234  * @api
235  */
236 #define US2RTC(freq, usec) (rtcnt_t)((((freq) + 999999UL) / 1000000UL) * (usec))
237 
238 /**
239  * @brief Realtime counter cycles to seconds.
240  * @details Converts from realtime counter cycles number to seconds.
241  * @note The result is rounded up to the next second boundary.
242  * @note The macro assumes that @p freq >= @p 1.
243  *
244  * @param[in] freq clock frequency, in Hz, of the realtime counter
245  * @param[in] n number of cycles
246  * @return The number of seconds.
247  *
248  * @api
249  */
250 #define RTC2S(freq, n) ((((n) - 1UL) / (freq)) + 1UL)
251 
252 /**
253  * @brief Realtime counter cycles to milliseconds.
254  * @details Converts from realtime counter cycles number to milliseconds.
255  * @note The result is rounded up to the next millisecond boundary.
256  * @note The macro assumes that @p freq >= @p 1000.
257  *
258  * @param[in] freq clock frequency, in Hz, of the realtime counter
259  * @param[in] n number of cycles
260  * @return The number of milliseconds.
261  *
262  * @api
263  */
264 #define RTC2MS(freq, n) ((((n) - 1UL) / ((freq) / 1000UL)) + 1UL)
265 
266 /**
267  * @brief Realtime counter cycles to microseconds.
268  * @details Converts from realtime counter cycles number to microseconds.
269  * @note The result is rounded up to the next microsecond boundary.
270  * @note The macro assumes that @p freq >= @p 1000000.
271  *
272  * @param[in] freq clock frequency, in Hz, of the realtime counter
273  * @param[in] n number of cycles
274  * @return The number of microseconds.
275  *
276  * @api
277  */
278 #define RTC2US(freq, n) ((((n) - 1UL) / ((freq) / 1000000UL)) + 1UL)
279 /** @} */
280 
281 /**
282  * @brief Returns the current value of the system real time counter.
283  * @note This function is only available if the port layer supports the
284  * option @p PORT_SUPPORTS_RT.
285  *
286  * @return The value of the system realtime counter of
287  * type rtcnt_t.
288  *
289  * @xclass
290  */
291 #if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__)
292 #define chSysGetRealtimeCounterX() (rtcnt_t)port_rt_get_counter_value()
293 #endif
294 
295 /**
296  * @brief Performs a context switch.
297  * @note Not a user function, it is meant to be invoked by the scheduler
298  * itself or from within the port layer.
299  *
300  * @param[in] ntp the thread to be switched in
301  * @param[in] otp the thread to be switched out
302  *
303  * @special
304  */
305 #define chSysSwitch(ntp, otp) { \
306  \
307  __trace_switch(ntp, otp); \
308  __stats_ctxswc(ntp, otp); \
309  CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp); \
310  port_switch(ntp, otp); \
311 }
312 
313 /*===========================================================================*/
314 /* External declarations. */
315 /*===========================================================================*/
316 
317 #if !defined(__DOXYGEN__)
318 extern ch_system_t ch_system;
319 
321 extern os_instance_t ch0;
322 
323 #if PORT_CORES_NUMBER > 1
325 extern os_instance_t ch1;
326 #endif
327 
328 #endif /* !defined(__DOXYGEN__) */
329 
330 #ifdef __cplusplus
331 extern "C" {
332 #endif
334  void chSysInit(void);
335  bool chSysIntegrityCheckI(unsigned testmask);
336  void chSysTimerHandlerI(void);
338  void chSysRestoreStatusX(syssts_t sts);
339 #if PORT_SUPPORTS_RT == TRUE
340  bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end);
341  void chSysPolledDelayX(rtcnt_t cycles);
342 #endif
343 #ifdef __cplusplus
344 }
345 #endif
346 
347 /*===========================================================================*/
348 /* Module inline functions. */
349 /*===========================================================================*/
350 
351 /**
352  * @brief Raises the system interrupt priority mask to the maximum level.
353  * @details All the maskable interrupt sources are disabled regardless their
354  * hardware priority.
355  * @note Do not invoke this API from within a kernel lock.
356  * @note This API is no replacement for @p chSysLock()and @p chSysUnock()
357  * which could do more than just disable interrupts.
358  *
359  * @special
360  */
361 static inline void chSysDisable(void) {
362 
363  port_disable();
364  __dbg_check_disable();
365 }
366 
367 /**
368  * @brief Raises the system interrupt priority mask to system level.
369  * @details The interrupt sources that should not be able to preempt the kernel
370  * are disabled, interrupt sources with higher priority are still
371  * enabled.
372  * @note Do not invoke this API from within a kernel lock.
373  * @note This API is no replacement for @p chSysLock() which
374  * could do more than just disable interrupts.
375  *
376  * @special
377  */
378 static inline void chSysSuspend(void) {
379 
380  port_suspend();
381  __dbg_check_suspend();
382 }
383 
384 /**
385  * @brief Lowers the system interrupt priority mask to user level.
386  * @details All the interrupt sources are enabled.
387  * @note Do not invoke this API from within a kernel lock.
388  * @note This API is no replacement for @p chSysUnlock() which
389  * could do more than just enable interrupts.
390  *
391  * @special
392  */
393 static inline void chSysEnable(void) {
394 
395  __dbg_check_enable();
396  port_enable();
397 }
398 
399 /**
400  * @brief Enters the kernel lock state.
401  * @note The exact behavior of this function is port-dependent and could
402  * not be limited to disabling interrupts.
403  *
404  * @special
405  */
406 static inline void chSysLock(void) {
407 
408  port_lock();
410  __dbg_check_lock();
411 }
412 
413 /**
414  * @brief Leaves the kernel lock state.
415  * @note The exact behavior of this function is port-dependent and could
416  * not be limited to enabling interrupts.
417  *
418  * @special
419  */
420 static inline void chSysUnlock(void) {
421 
422  __dbg_check_unlock();
424 
425  /* The following condition can be triggered by the use of i-class functions
426  in a critical section not followed by a chSchRescheduleS(), this means
427  that the current thread has a lower priority than the next thread in
428  the ready list.*/
429  chDbgAssert((currcore->rlist.pqueue.next == &currcore->rlist.pqueue) ||
430  (currcore->rlist.current->hdr.pqueue.prio >= currcore->rlist.pqueue.next->prio),
431  "priority order violation");
432 
433  port_unlock();
434 }
435 
436 /**
437  * @brief Enters the kernel lock state from within an interrupt handler.
438  * @note This API may do nothing on some architectures, it is required
439  * because on ports that support preemptable interrupt handlers
440  * it is required to raise the interrupt mask to the same level of
441  * the system mutual exclusion zone.<br>
442  * It is good practice to invoke this API before invoking any I-class
443  * syscall from an interrupt handler.
444  * @note The exact behavior of this function is port-dependent and could
445  * not be limited to disabling interrupts.
446  * @note This API must be invoked exclusively from interrupt handlers.
447  *
448  * @special
449  */
450 static inline void chSysLockFromISR(void) {
451 
454  __dbg_check_lock_from_isr();
455 }
456 
457 /**
458  * @brief Leaves the kernel lock state from within an interrupt handler.
459  *
460  * @note This API may do nothing on some architectures, it is required
461  * because on ports that support preemptable interrupt handlers
462  * it is required to raise the interrupt mask to the same level of
463  * the system mutual exclusion zone.<br>
464  * It is good practice to invoke this API after invoking any I-class
465  * syscall from an interrupt handler.
466  * @note The exact behavior of this function is port-dependent and could
467  * not be limited to enabling interrupts.
468  * @note This API must be invoked exclusively from interrupt handlers.
469  *
470  * @special
471  */
472 static inline void chSysUnlockFromISR(void) {
473 
474  __dbg_check_unlock_from_isr();
477 }
478 
479 /**
480  * @brief Unconditionally enters the kernel lock state.
481  * @note Can be called without previous knowledge of the current lock state.
482  * The final state is "s-locked".
483  *
484  * @special
485  */
486 static inline void chSysUnconditionalLock(void) {
487 
489  chSysLock();
490  }
491 }
492 
493 /**
494  * @brief Unconditionally leaves the kernel lock state.
495  * @note Can be called without previous knowledge of the current lock state.
496  * The final state is "normal".
497  *
498  * @special
499  */
500 static inline void chSysUnconditionalUnlock(void) {
501 
503  chSysUnlock();
504  }
505 }
506 
507 #if (CH_CFG_SMP_MODE == TRUE) || defined(__DOXYGEN__)
508 /**
509  * @brief Notifies an OS instance to check for reschedule.
510  * @details An OS instance is notified to check if a reschedule is required,
511  * the implementation is port-dependent.
512  *
513  * @param[in] oip pointer to the instance to be notified
514  */
515 static inline void chSysNotifyInstance(os_instance_t *oip) {
516 
517  port_notify_instance(oip);
518 }
519 #endif
520 
521 #if (CH_CFG_NO_IDLE_THREAD == FALSE) || defined(__DOXYGEN__)
522 /**
523  * @brief Returns a pointer to the idle thread.
524  * @pre In order to use this function the option @p CH_CFG_NO_IDLE_THREAD
525  * must be disabled.
526  * @note The reference counter of the idle thread is not incremented but
527  * it is not strictly required being the idle thread a static
528  * object.
529  *
530  * @return Pointer to the idle thread.
531  *
532  * @xclass
533  */
534 static inline thread_t *chSysGetIdleThreadX(void) {
535 
536  return (thread_t *)currcore->rlist.pqueue.prev;
537 }
538 #endif /* CH_CFG_NO_IDLE_THREAD == FALSE */
539 
540 #endif /* CHSYS_H */
541 
542 /** @} */
chSysRestoreStatusX
void chSysRestoreStatusX(syssts_t sts)
Restores the specified execution status and leaves a critical zone.
Definition: chsys.c:423
chSysIsCounterWithinX
bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end)
Realtime window test.
Definition: chsys.c:455
port_irq_enabled
static bool port_irq_enabled(syssts_t sts)
Checks the interrupt status.
Definition: chcore.h:324
chSysLock
static void chSysLock(void)
Enters the kernel lock state.
Definition: chsys.h:406
currcore
#define currcore
Access to current core's instance structure.
Definition: chsys.h:90
system_state_t
system_state_t
Global state of the operating system.
Definition: chobjects.h:50
chSysUnconditionalLock
static void chSysUnconditionalLock(void)
Unconditionally enters the kernel lock state.
Definition: chsys.h:486
chDbgAssert
#define chDbgAssert(c, r)
Condition assertion.
Definition: chdebug.h:144
ch_os_instance
System instance data structure.
Definition: chobjects.h:394
chSysTimerHandlerI
void chSysTimerHandlerI(void)
Handles time ticks for round robin preemption and timer increments.
Definition: chsys.c:366
chSysIntegrityCheckI
bool chSysIntegrityCheckI(unsigned testmask)
System integrity check.
Definition: chsys.c:260
chSysWaitSystemState
void chSysWaitSystemState(system_state_t state)
Waits for the system state to be equal to the specified one.
Definition: chsys.c:142
port_unlock_from_isr
static void port_unlock_from_isr(void)
Kernel-unlock action from an interrupt handler.
Definition: chcore.h:377
chSysEnable
static void chSysEnable(void)
Lowers the system interrupt priority mask to user level.
Definition: chsys.h:393
chSysDisable
static void chSysDisable(void)
Raises the system interrupt priority mask to the maximum level.
Definition: chsys.h:361
__stats_stop_measure_crit_isr
void __stats_stop_measure_crit_isr(void)
Stops the measurement of an ISR critical zone.
Definition: chstats.c:106
ch1
CH_SYS_CORE1_MEMORY os_instance_t ch1
Core 1 OS instance.
Definition: chsys.c:86
ch_core0_cfg
const os_instance_config_t ch_core0_cfg
Core 0 OS instance configuration.
Definition: chsys.c:66
ch_core1_cfg
const os_instance_config_t ch_core1_cfg
Core 1 OS instance configuration.
Definition: chsys.c:103
ch_system
Type of system data structure.
Definition: chobjects.h:457
ch_thread
Structure representing a thread.
Definition: chobjects.h:156
chSysPolledDelayX
void chSysPolledDelayX(rtcnt_t cycles)
Polled delay.
Definition: chsys.c:472
syssts_t
port_syssts_t syssts_t
Definition: chearly.h:79
port_suspend
static void port_suspend(void)
Disables the interrupt sources below kernel-level priority.
Definition: chcore.h:393
ch_system
ch_system_t ch_system
System root object.
Definition: chsys.c:45
port_unlock
static void port_unlock(void)
Kernel-unlock action.
Definition: chcore.h:357
rtcnt_t
port_rtcnt_t rtcnt_t
Definition: chearly.h:77
port_get_irq_status
static syssts_t port_get_irq_status(void)
Returns a word encoding the current interrupts status.
Definition: chcore.h:310
__stats_stop_measure_crit_thd
void __stats_stop_measure_crit_thd(void)
Stops the measurement of a thread critical zone.
Definition: chstats.c:90
chSysLockFromISR
static void chSysLockFromISR(void)
Enters the kernel lock state from within an interrupt handler.
Definition: chsys.h:450
port_lock
static void port_lock(void)
Kernel-lock action.
Definition: chcore.h:348
port_enable
static void port_enable(void)
Enables all the interrupt sources.
Definition: chcore.h:400
chSysGetStatusAndLockX
syssts_t chSysGetStatusAndLockX(void)
Returns the execution status and enters a critical zone.
Definition: chsys.c:400
chSysNotifyInstance
static void chSysNotifyInstance(os_instance_t *oip)
Notifies an OS instance to check for reschedule.
Definition: chsys.h:515
port_lock_from_isr
static void port_lock_from_isr(void)
Kernel-lock action from an interrupt handler.
Definition: chcore.h:367
port_disable
static void port_disable(void)
Disables all the interrupt sources.
Definition: chcore.h:385
chSysInit
void chSysInit(void)
System initialization.
Definition: chsys.c:159
chSysSuspend
static void chSysSuspend(void)
Raises the system interrupt priority mask to system level.
Definition: chsys.h:378
chSysUnlock
static void chSysUnlock(void)
Leaves the kernel lock state.
Definition: chsys.h:420
ch_os_instance_config
Type of an system instance configuration.
Definition: chobjects.h:363
__stats_start_measure_crit_thd
void __stats_start_measure_crit_thd(void)
Starts the measurement of a thread critical zone.
Definition: chstats.c:82
ch0
CH_SYS_CORE0_MEMORY os_instance_t ch0
Core 0 OS instance.
Definition: chsys.c:50
__stats_start_measure_crit_isr
void __stats_start_measure_crit_isr(void)
Starts the measurement of an ISR critical zone.
Definition: chstats.c:98
chSysUnlockFromISR
static void chSysUnlockFromISR(void)
Leaves the kernel lock state from within an interrupt handler.
Definition: chsys.h:472
chSysUnconditionalUnlock
static void chSysUnconditionalUnlock(void)
Unconditionally leaves the kernel lock state.
Definition: chsys.h:500
chSysGetIdleThreadX
static thread_t * chSysGetIdleThreadX(void)
Returns a pointer to the idle thread.
Definition: chsys.h:534