ChibiOS 21.11.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 * @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
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__)
319
321extern os_instance_t ch0;
322
323#if PORT_CORES_NUMBER > 1
325extern os_instance_t ch1;
326#endif
327
328#endif /* !defined(__DOXYGEN__) */
329
330#ifdef __cplusplus
331extern "C" {
332#endif
334 void chSysInit(void);
336 bool chSysIntegrityCheckI(unsigned testmask);
337 void chSysTimerHandlerI(void);
340#if PORT_SUPPORTS_RT == TRUE
341 bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end);
342 void chSysPolledDelayX(rtcnt_t cycles);
343#endif
344#ifdef __cplusplus
345}
346#endif
347
348/*===========================================================================*/
349/* Module inline functions. */
350/*===========================================================================*/
351
352/**
353 * @brief Raises the system interrupt priority mask to the maximum level.
354 * @details All the maskable interrupt sources are disabled regardless their
355 * hardware priority.
356 * @note Do not invoke this API from within a kernel lock.
357 * @note This API is no replacement for @p chSysLock()and @p chSysUnock()
358 * which could do more than just disable interrupts.
359 *
360 * @special
361 */
362static inline void chSysDisable(void) {
363
364 port_disable();
366}
367
368/**
369 * @brief Raises the system interrupt priority mask to system level.
370 * @details The interrupt sources that should not be able to preempt the kernel
371 * are disabled, interrupt sources with higher priority are still
372 * enabled.
373 * @note Do not invoke this API from within a kernel lock.
374 * @note This API is no replacement for @p chSysLock() which
375 * could do more than just disable interrupts.
376 *
377 * @special
378 */
379static inline void chSysSuspend(void) {
380
381 port_suspend();
383}
384
385/**
386 * @brief Lowers the system interrupt priority mask to user level.
387 * @details All the interrupt sources are enabled.
388 * @note Do not invoke this API from within a kernel lock.
389 * @note This API is no replacement for @p chSysUnlock() which
390 * could do more than just enable interrupts.
391 *
392 * @special
393 */
394static inline void chSysEnable(void) {
395
397 port_enable();
398}
399
400/**
401 * @brief Enters the kernel lock state.
402 * @note The exact behavior of this function is port-dependent and could
403 * not be limited to disabling interrupts.
404 *
405 * @special
406 */
407static inline void chSysLock(void) {
408
409 port_lock();
412}
413
414/**
415 * @brief Leaves the kernel lock state.
416 * @note The exact behavior of this function is port-dependent and could
417 * not be limited to enabling interrupts.
418 *
419 * @special
420 */
421static inline void chSysUnlock(void) {
422
425
426 /* The following condition can be triggered by the use of i-class functions
427 in a critical section not followed by a chSchRescheduleS(), this means
428 that the current thread has a lower priority than the next thread in
429 the ready list.*/
430 chDbgAssert((currcore->rlist.pqueue.next == &currcore->rlist.pqueue) ||
431 (currcore->rlist.current->hdr.pqueue.prio >= currcore->rlist.pqueue.next->prio),
432 "priority order violation");
433
434 port_unlock();
435}
436
437/**
438 * @brief Enters the kernel lock state from within an interrupt handler.
439 * @note This API may do nothing on some architectures, it is required
440 * because on ports that support preemptable interrupt handlers
441 * it is required to raise the interrupt mask to the same level of
442 * the system mutual exclusion zone.<br>
443 * It is good practice to invoke this API before invoking any I-class
444 * syscall from an interrupt handler.
445 * @note The exact behavior of this function is port-dependent and could
446 * not be limited to disabling interrupts.
447 * @note This API must be invoked exclusively from interrupt handlers.
448 *
449 * @special
450 */
457
458/**
459 * @brief Leaves the kernel lock state from within an interrupt handler.
460 *
461 * @note This API may do nothing on some architectures, it is required
462 * because on ports that support preemptable interrupt handlers
463 * it is required to raise the interrupt mask to the same level of
464 * the system mutual exclusion zone.<br>
465 * It is good practice to invoke this API after invoking any I-class
466 * syscall from an interrupt handler.
467 * @note The exact behavior of this function is port-dependent and could
468 * not be limited to enabling interrupts.
469 * @note This API must be invoked exclusively from interrupt handlers.
470 *
471 * @special
472 */
479
480#if (CH_PORT_SUPPORTS_RECURSIVE_LOCKS == TRUE) || defined(__DOXYGEN__)
481/**
482 * @brief Unconditionally enters the kernel lock state.
483 * @note Can be called without previous knowledge of the current lock state.
484 * The final state is "s-locked".
485 * @note This function is only available if the underlying port supports
486 * @p port_get_lock_status() and @p port_is_locked().
487 *
488 * @special
489 */
490static inline void chSysUnconditionalLock(void) {
491
493 chSysLock();
494 }
495}
496
497/**
498 * @brief Unconditionally leaves the kernel lock state.
499 * @note Can be called without previous knowledge of the current lock state.
500 * The final state is "normal".
501 * @note This function is only available if the underlying port supports
502 * @p port_get_lock_status() and @p port_is_locked().
503 *
504 * @special
505 */
506static inline void chSysUnconditionalUnlock(void) {
507
509 chSysUnlock();
510 }
511}
512#endif /* CH_PORT_SUPPORTS_RECURSIVE_LOCKS == TRUE */
513
514#if (CH_CFG_SMP_MODE == TRUE) || defined(__DOXYGEN__)
515/**
516 * @brief Notifies an OS instance to check for reschedule.
517 * @details An OS instance is notified to check if a reschedule is required,
518 * the implementation is port-dependent.
519 *
520 * @param[in] oip pointer to the instance to be notified
521 */
522static inline void chSysNotifyInstance(os_instance_t *oip) {
523
524 port_notify_instance(oip);
525}
526#endif
527
528#endif /* CHSYS_H */
529
530/** @} */
#define chDbgAssert(c, r)
Condition assertion.
Definition chdebug.h:144
#define __dbg_check_unlock()
Definition chdebug.h:94
#define __dbg_check_suspend()
Definition chdebug.h:91
#define __dbg_check_lock()
Definition chdebug.h:93
#define __dbg_check_disable()
Definition chdebug.h:90
#define __dbg_check_enable()
Definition chdebug.h:92
#define __dbg_check_unlock_from_isr()
Definition chdebug.h:96
#define __dbg_check_lock_from_isr()
Definition chdebug.h:95
port_syssts_t syssts_t
Definition chearly.h:79
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:138
struct ch_os_instance_config os_instance_config_t
Type of an system instance configuration.
port_rtcnt_t rtcnt_t
Definition chearly.h:77
system_state_t
Global state of the operating system.
Definition chobjects.h:50
struct ch_thread thread_t
Type of a thread structure.
Definition chearly.h:133
static void port_unlock_from_isr(void)
Kernel-unlock action from an interrupt handler.
Definition chcore.h:368
static void port_disable(void)
Disables all the interrupt sources.
Definition chcore.h:376
static void port_lock_from_isr(void)
Kernel-lock action from an interrupt handler.
Definition chcore.h:358
static void port_enable(void)
Enables all the interrupt sources.
Definition chcore.h:391
static void port_lock(void)
Kernel-lock action.
Definition chcore.h:339
#define port_get_lock_status()
Returns a word representing a critical section status.
Definition chcore.h:283
#define port_is_locked(sts)
Determines if in a critical section.
Definition chcore.h:293
static void port_suspend(void)
Disables the interrupt sources below kernel-level priority.
Definition chcore.h:384
static void port_unlock(void)
Kernel-unlock action.
Definition chcore.h:348
void __stats_stop_measure_crit_isr(void)
Stops the measurement of an ISR critical zone.
Definition chstats.c:106
void __stats_start_measure_crit_isr(void)
Starts the measurement of an ISR critical zone.
Definition chstats.c:98
void __stats_stop_measure_crit_thd(void)
Stops the measurement of a thread critical zone.
Definition chstats.c:90
void __stats_start_measure_crit_thd(void)
Starts the measurement of a thread critical zone.
Definition chstats.c:82
static void chSysSuspend(void)
Raises the system interrupt priority mask to system level.
Definition chsys.h:379
syssts_t chSysGetStatusAndLockX(void)
Returns the execution status and enters a critical zone.
Definition chsys.c:423
CH_SYS_CORE1_MEMORY os_instance_t ch1
Core 1 OS instance.
Definition chsys.c:86
bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end)
Realtime window test.
Definition chsys.c:481
void chSysTimerHandlerI(void)
Handles time ticks for round robin preemption and timer increments.
Definition chsys.c:386
CH_SYS_CORE0_MEMORY os_instance_t ch0
Core 0 OS instance.
Definition chsys.c:50
bool chSysIntegrityCheckI(unsigned testmask)
System integrity check.
Definition chsys.c:280
thread_t * chSysGetIdleThreadX(void)
Returns a pointer to the idle thread.
Definition chsys.c:248
static void chSysUnlockFromISR(void)
Leaves the kernel lock state from within an interrupt handler.
Definition chsys.h:473
static void chSysLock(void)
Enters the kernel lock state.
Definition chsys.h:407
void chSysPolledDelayX(rtcnt_t cycles)
Polled delay.
Definition chsys.c:498
const os_instance_config_t ch_core0_cfg
Core 0 OS instance configuration.
Definition chsys.c:67
void chSysWaitSystemState(system_state_t state)
Waits for the system state to be equal to the specified one.
Definition chsys.c:142
const os_instance_config_t ch_core1_cfg
Core 1 OS instance configuration.
Definition chsys.c:103
static void chSysDisable(void)
Raises the system interrupt priority mask to the maximum level.
Definition chsys.h:362
static void chSysUnconditionalLock(void)
Unconditionally enters the kernel lock state.
Definition chsys.h:490
void chSysRestoreStatusX(syssts_t sts)
Restores the specified execution status and leaves a critical zone.
Definition chsys.c:448
#define currcore
Access to current core's instance structure.
Definition chsys.h:90
static void chSysLockFromISR(void)
Enters the kernel lock state from within an interrupt handler.
Definition chsys.h:451
static void chSysEnable(void)
Lowers the system interrupt priority mask to user level.
Definition chsys.h:394
static void chSysUnlock(void)
Leaves the kernel lock state.
Definition chsys.h:421
static void chSysUnconditionalUnlock(void)
Unconditionally leaves the kernel lock state.
Definition chsys.h:506
static void chSysNotifyInstance(os_instance_t *oip)
Notifies an OS instance to check for reschedule.
Definition chsys.h:522
void chSysInit(void)
System initialization.
Definition chsys.c:159
Type of system data structure.
Definition chobjects.h:457