ChibiOS 21.11.5
chsys.h
Go to the documentation of this file.
1/*
2 ChibiOS - Copyright (C) 2006-2026 Giovanni Di Sirio.
3
4 This file is part of ChibiOS.
5
6 ChibiOS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation version 3 of the License.
9
10 ChibiOS is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19/**
20 * @file rt/include/chsys.h
21 * @brief System related macros and structures.
22 *
23 * @addtogroup system
24 * @{
25 */
26
27#ifndef CHSYS_H
28#define CHSYS_H
29
30/*lint -sem(chSysHalt, r_no)*/
31
32/*===========================================================================*/
33/* Module constants. */
34/*===========================================================================*/
35
36/**
37 * @name Masks of executable integrity checks.
38 * @{
39 */
40#define CH_INTEGRITY_RLIST 1U
41#define CH_INTEGRITY_VTLIST 2U
42#define CH_INTEGRITY_REGISTRY 4U
43#define CH_INTEGRITY_PORT 8U
44/** @} */
45
46/*===========================================================================*/
47/* Module pre-compile time settings. */
48/*===========================================================================*/
49
50/*===========================================================================*/
51/* Derived constants and error checks. */
52/*===========================================================================*/
53
54/**
55 * @brief Core zero memory affinity macro.
56 * @note The memory is meant to be reachable by both cores but
57 * preferred by core zero.
58 * @note Only uninitialized variables can be tagged with this attribute.
59 */
60#if defined(PORT_CORE0_BSS_SECTION) || defined(__DOXYGEN__)
61#define CH_SYS_CORE0_MEMORY PORT_CORE0_BSS_SECTION
62#else
63#define CH_SYS_CORE0_MEMORY /* Default.*/
64#endif
65
66/**
67 * @brief Core one memory affinity macro.
68 * @note The memory is meant to be reachable by both cores but
69 * preferred by core one.
70 * @note Only uninitialized variables can be tagged with this attribute.
71 */
72#if defined(PORT_CORE1_BSS_SECTION) || defined(__DOXYGEN__)
73#define CH_SYS_CORE1_MEMORY PORT_CORE1_BSS_SECTION
74#else
75#define CH_SYS_CORE1_MEMORY /* Default.*/
76#endif
77
78/*===========================================================================*/
79/* Module data structures and types. */
80/*===========================================================================*/
81
82/**
83 * @brief Access to current core's instance structure.
84 */
85#if defined(PORT_INSTANCE_ACCESS)
86 #define currcore PORT_INSTANCE_ACCESS
87#else /* !defined(PORT_INSTANCE_ACCESS) */
88 #if (PORT_CORES_NUMBER > 1) || defined(__DOXYGEN__)
89 #define currcore ch_system.instances[port_get_core_id()]
90 #else
91 #define currcore (&ch0)
92 #endif
93#endif
94
95/*===========================================================================*/
96/* Module macros. */
97/*===========================================================================*/
98
99/**
100 * @name ISRs abstraction macros
101 * @{
102 */
103/**
104 * @brief Priority level validation macro.
105 * @details This macro determines if the passed value is a valid priority
106 * level for the underlying architecture.
107 *
108 * @param[in] prio the priority level
109 * @return Priority range result.
110 * @retval false if the priority is invalid or if the architecture
111 * does not support priorities.
112 * @retval true if the priority is valid.
113 */
114#if defined(PORT_IRQ_IS_VALID_PRIORITY) || defined(__DOXYGEN__)
115#define CH_IRQ_IS_VALID_PRIORITY(prio) \
116 PORT_IRQ_IS_VALID_PRIORITY(prio)
117#else
118#define CH_IRQ_IS_VALID_PRIORITY(prio) false
119#endif
120
121/**
122 * @brief Priority level validation macro.
123 * @details This macro determines if the passed value is a valid priority
124 * level that cannot preempt the kernel critical zone.
125 *
126 * @param[in] prio the priority level
127 * @return Priority range result.
128 * @retval false if the priority is invalid or if the architecture
129 * does not support priorities.
130 * @retval true if the priority is valid.
131 */
132#if defined(PORT_IRQ_IS_VALID_KERNEL_PRIORITY) || defined(__DOXYGEN__)
133#define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) \
134 PORT_IRQ_IS_VALID_KERNEL_PRIORITY(prio)
135#else
136#define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) false
137#endif
138
139/**
140 * @brief IRQ handler enter code.
141 * @note Usually IRQ handlers functions are also declared naked.
142 * @note On some architectures this macro can be empty.
143 *
144 * @special
145 */
146#define CH_IRQ_PROLOGUE() \
147 PORT_IRQ_PROLOGUE(); \
148 CH_CFG_IRQ_PROLOGUE_HOOK(); \
149 __stats_increase_irq(); \
150 __trace_isr_enter(__func__); \
151 __dbg_check_enter_isr()
152
153/**
154 * @brief IRQ handler exit code.
155 * @note Usually IRQ handlers function are also declared naked.
156 * @note This macro usually performs the final reschedule by using
157 * @p chSchIsPreemptionRequired() and @p chSchDoReschedule().
158 *
159 * @special
160 */
161#define CH_IRQ_EPILOGUE() \
162 __dbg_check_leave_isr(); \
163 __trace_isr_leave(__func__); \
164 CH_CFG_IRQ_EPILOGUE_HOOK(); \
165 PORT_IRQ_EPILOGUE()
166
167/**
168 * @brief Standard normal IRQ handler declaration.
169 * @note @p id can be a function name or a vector number depending on the
170 * port implementation.
171 *
172 * @special
173 */
174#define CH_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id)
175/** @} */
176
177/**
178 * @name Fast ISRs abstraction macros
179 * @{
180 */
181/**
182 * @brief Standard fast IRQ handler declaration.
183 * @note @p id can be a function name or a vector number depending on the
184 * port implementation.
185 * @note Not all architectures support fast interrupts.
186 *
187 * @special
188 */
189#define CH_FAST_IRQ_HANDLER(id) PORT_FAST_IRQ_HANDLER(id)
190/** @} */
191
192/**
193 * @name Time conversion utilities for the realtime counter
194 * @{
195 */
196/**
197 * @brief Seconds to realtime counter.
198 * @details Converts from seconds to realtime counter cycles.
199 * @note The macro assumes that @p freq >= @p 1.
200 *
201 * @param[in] freq clock frequency, in Hz, of the realtime counter
202 * @param[in] sec number of seconds
203 * @return The number of cycles.
204 *
205 * @api
206 */
207#define S2RTC(freq, sec) ((freq) * (sec))
208
209/**
210 * @brief Milliseconds to realtime counter.
211 * @details Converts from milliseconds to realtime counter cycles.
212 * @note The result is rounded upward to the next millisecond boundary.
213 * @note The macro assumes that @p freq >= @p 1000.
214 *
215 * @param[in] freq clock frequency, in Hz, of the realtime counter
216 * @param[in] msec number of milliseconds
217 * @return The number of cycles.
218 *
219 * @api
220 */
221#define MS2RTC(freq, msec) (rtcnt_t)((((freq) + 999UL) / 1000UL) * (msec))
222
223/**
224 * @brief Microseconds to realtime counter.
225 * @details Converts from microseconds to realtime counter cycles.
226 * @note The result is rounded upward to the next microsecond boundary.
227 * @note The macro assumes that @p freq >= @p 1000000.
228 *
229 * @param[in] freq clock frequency, in Hz, of the realtime counter
230 * @param[in] usec number of microseconds
231 * @return The number of cycles.
232 *
233 * @api
234 */
235#define US2RTC(freq, usec) (rtcnt_t)((((freq) + 999999UL) / 1000000UL) * (usec))
236
237/**
238 * @brief Realtime counter cycles to seconds.
239 * @details Converts from realtime counter cycles number to seconds.
240 * @note The result is rounded up to the next second boundary.
241 * @note The macro assumes that @p freq >= @p 1.
242 *
243 * @param[in] freq clock frequency, in Hz, of the realtime counter
244 * @param[in] n number of cycles
245 * @return The number of seconds.
246 *
247 * @api
248 */
249#define RTC2S(freq, n) ((((n) - 1UL) / (freq)) + 1UL)
250
251/**
252 * @brief Realtime counter cycles to milliseconds.
253 * @details Converts from realtime counter cycles number to milliseconds.
254 * @note The result is rounded up to the next millisecond boundary.
255 * @note The macro assumes that @p freq >= @p 1000.
256 *
257 * @param[in] freq clock frequency, in Hz, of the realtime counter
258 * @param[in] n number of cycles
259 * @return The number of milliseconds.
260 *
261 * @api
262 */
263#define RTC2MS(freq, n) ((((n) - 1UL) / ((freq) / 1000UL)) + 1UL)
264
265/**
266 * @brief Realtime counter cycles to microseconds.
267 * @details Converts from realtime counter cycles number to microseconds.
268 * @note The result is rounded up to the next microsecond boundary.
269 * @note The macro assumes that @p freq >= @p 1000000.
270 *
271 * @param[in] freq clock frequency, in Hz, of the realtime counter
272 * @param[in] n number of cycles
273 * @return The number of microseconds.
274 *
275 * @api
276 */
277#define RTC2US(freq, n) ((((n) - 1UL) / ((freq) / 1000000UL)) + 1UL)
278/** @} */
279
280/**
281 * @brief Returns the current value of the system real time counter.
282 * @note This function is only available if the port layer supports the
283 * option @p PORT_SUPPORTS_RT.
284 *
285 * @return The value of the system realtime counter of
286 * type rtcnt_t.
287 *
288 * @xclass
289 */
290#if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__)
291#define chSysGetRealtimeCounterX() (rtcnt_t)port_rt_get_counter_value()
292#endif
293
294/**
295 * @brief Performs a context switch.
296 * @note Not a user function, it is meant to be invoked by the scheduler
297 * itself or from within the port layer.
298 *
299 * @param[in] ntp the thread to be switched in
300 * @param[in] otp the thread to be switched out
301 *
302 * @special
303 */
304#define chSysSwitch(ntp, otp) { \
305 \
306 __trace_switch(ntp, otp); \
307 __stats_ctxswc(ntp, otp); \
308 CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp); \
309 port_switch(ntp, otp); \
310}
311
312/*===========================================================================*/
313/* External declarations. */
314/*===========================================================================*/
315
316#if !defined(__DOXYGEN__)
318
320extern os_instance_t ch0;
321
322#if PORT_CORES_NUMBER > 1
324extern os_instance_t ch1;
325#endif
326
327#endif /* !defined(__DOXYGEN__) */
328
329#ifdef __cplusplus
330extern "C" {
331#endif
333 void chSysInit(void);
335 bool chSysIntegrityCheckI(unsigned testmask);
336 void chSysTimerHandlerI(void);
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 */
361static inline void chSysDisable(void) {
362
363 port_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 */
378static inline void chSysSuspend(void) {
379
380 port_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 */
393static inline void chSysEnable(void) {
394
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 */
406static inline void chSysLock(void) {
407
408 port_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 */
420static inline void chSysUnlock(void) {
421
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 */
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 */
478
479#if (CH_PORT_SUPPORTS_RECURSIVE_LOCKS == TRUE) || defined(__DOXYGEN__)
480/**
481 * @brief Unconditionally enters the kernel lock state.
482 * @note Can be called without previous knowledge of the current lock state.
483 * The final state is "s-locked".
484 * @note This function is only available if the underlying port supports
485 * @p port_get_lock_status() and @p port_is_locked().
486 *
487 * @special
488 */
489static inline void chSysUnconditionalLock(void) {
490
492 chSysLock();
493 }
494}
495
496/**
497 * @brief Unconditionally leaves the kernel lock state.
498 * @note Can be called without previous knowledge of the current lock state.
499 * The final state is "normal".
500 * @note This function is only available if the underlying port supports
501 * @p port_get_lock_status() and @p port_is_locked().
502 *
503 * @special
504 */
505static inline void chSysUnconditionalUnlock(void) {
506
508 chSysUnlock();
509 }
510}
511#endif /* CH_PORT_SUPPORTS_RECURSIVE_LOCKS == TRUE */
512
513#if (CH_CFG_SMP_MODE == TRUE) || defined(__DOXYGEN__)
514/**
515 * @brief Notifies an OS instance to check for reschedule.
516 * @details An OS instance is notified to check if a reschedule is required,
517 * the implementation is port-dependent.
518 *
519 * @param[in] oip pointer to the instance to be notified
520 */
521static inline void chSysNotifyInstance(os_instance_t *oip) {
522
523 port_notify_instance(oip);
524}
525#endif
526
527#endif /* CHSYS_H */
528
529/** @} */
#define chDbgAssert(c, r)
Condition assertion.
Definition chdebug.h:143
#define __dbg_check_unlock()
Definition chdebug.h:93
#define __dbg_check_suspend()
Definition chdebug.h:90
#define __dbg_check_lock()
Definition chdebug.h:92
#define __dbg_check_disable()
Definition chdebug.h:89
#define __dbg_check_enable()
Definition chdebug.h:91
#define __dbg_check_unlock_from_isr()
Definition chdebug.h:95
#define __dbg_check_lock_from_isr()
Definition chdebug.h:94
port_syssts_t syssts_t
Definition chearly.h:78
struct ch_system ch_system_t
Type of system data structure.
struct ch_os_instance os_instance_t
Type of an OS instance structure.
Definition chearly.h:137
struct ch_os_instance_config os_instance_config_t
Type of an system instance configuration.
port_rtcnt_t rtcnt_t
Definition chearly.h:76
system_state_t
Global state of the operating system.
Definition chobjects.h:49
struct ch_thread thread_t
Type of a thread structure.
Definition chearly.h:132
static void port_unlock_from_isr(void)
Kernel-unlock action from an interrupt handler.
Definition chcore.h:367
static void port_disable(void)
Disables all the interrupt sources.
Definition chcore.h:375
static void port_lock_from_isr(void)
Kernel-lock action from an interrupt handler.
Definition chcore.h:357
static void port_enable(void)
Enables all the interrupt sources.
Definition chcore.h:390
static void port_lock(void)
Kernel-lock action.
Definition chcore.h:338
#define port_get_lock_status()
Returns a word representing a critical section status.
Definition chcore.h:282
#define port_is_locked(sts)
Determines if in a critical section.
Definition chcore.h:292
static void port_suspend(void)
Disables the interrupt sources below kernel-level priority.
Definition chcore.h:383
static void port_unlock(void)
Kernel-unlock action.
Definition chcore.h:347
void __stats_stop_measure_crit_isr(void)
Stops the measurement of an ISR critical zone.
Definition chstats.c:105
void __stats_start_measure_crit_isr(void)
Starts the measurement of an ISR critical zone.
Definition chstats.c:97
void __stats_stop_measure_crit_thd(void)
Stops the measurement of a thread critical zone.
Definition chstats.c:89
void __stats_start_measure_crit_thd(void)
Starts the measurement of a thread critical zone.
Definition chstats.c:81
static void chSysSuspend(void)
Raises the system interrupt priority mask to system level.
Definition chsys.h:378
syssts_t chSysGetStatusAndLockX(void)
Returns the execution status and enters a critical zone.
Definition chsys.c:422
CH_SYS_CORE1_MEMORY os_instance_t ch1
Core 1 OS instance.
Definition chsys.c:85
bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end)
Realtime window test.
Definition chsys.c:480
void chSysTimerHandlerI(void)
Handles time ticks for round robin preemption and timer increments.
Definition chsys.c:385
CH_SYS_CORE0_MEMORY os_instance_t ch0
Core 0 OS instance.
Definition chsys.c:49
bool chSysIntegrityCheckI(unsigned testmask)
System integrity check.
Definition chsys.c:279
thread_t * chSysGetIdleThreadX(void)
Returns a pointer to the idle thread.
Definition chsys.c:247
static void chSysUnlockFromISR(void)
Leaves the kernel lock state from within an interrupt handler.
Definition chsys.h:472
static void chSysLock(void)
Enters the kernel lock state.
Definition chsys.h:406
void chSysPolledDelayX(rtcnt_t cycles)
Polled delay.
Definition chsys.c:497
const os_instance_config_t ch_core0_cfg
Core 0 OS instance configuration.
Definition chsys.c:66
void chSysWaitSystemState(system_state_t state)
Waits for the system state to be equal to the specified one.
Definition chsys.c:141
const os_instance_config_t ch_core1_cfg
Core 1 OS instance configuration.
Definition chsys.c:102
static void chSysDisable(void)
Raises the system interrupt priority mask to the maximum level.
Definition chsys.h:361
static void chSysUnconditionalLock(void)
Unconditionally enters the kernel lock state.
Definition chsys.h:489
void chSysRestoreStatusX(syssts_t sts)
Restores the specified execution status and leaves a critical zone.
Definition chsys.c:447
#define currcore
Access to current core's instance structure.
Definition chsys.h:89
static void chSysLockFromISR(void)
Enters the kernel lock state from within an interrupt handler.
Definition chsys.h:450
static void chSysEnable(void)
Lowers the system interrupt priority mask to user level.
Definition chsys.h:393
static void chSysUnlock(void)
Leaves the kernel lock state.
Definition chsys.h:420
static void chSysUnconditionalUnlock(void)
Unconditionally leaves the kernel lock state.
Definition chsys.h:505
static void chSysNotifyInstance(os_instance_t *oip)
Notifies an OS instance to check for reschedule.
Definition chsys.h:521
void chSysInit(void)
System initialization.
Definition chsys.c:158
Type of system data structure.
Definition chobjects.h:466