ChibiOS  21.6.0
chsys.c
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/src/chsys.c
22  * @brief System related code.
23  *
24  * @addtogroup system
25  * @details System related APIs and services:
26  * - Initialization.
27  * - Locks.
28  * - Interrupt Handling.
29  * - Power Management.
30  * - Abnormal Termination.
31  * - Realtime counter.
32  * .
33  * @{
34  */
35 
36 #include "ch.h"
37 
38 /*===========================================================================*/
39 /* Module exported variables. */
40 /*===========================================================================*/
41 
42 /**
43  * @brief System root object.
44  */
46 
47 /**
48  * @brief Core 0 OS instance.
49  */
51 
52 #if (CH_CFG_NO_IDLE_THREAD == FALSE) || defined(__DOXYGEN__)
53 /**
54  * @brief Working area for core 0 idle thread.
55  */
56 static CH_SYS_CORE0_MEMORY THD_WORKING_AREA(ch_c0_idle_thread_wa,
58 
59 #if CH_DBG_ENABLE_STACK_CHECK == TRUE
60 extern stkalign_t __main_thread_stack_base__, __main_thread_stack_end__;
61 #endif
62 
63 /**
64  * @brief Core 0 OS instance configuration.
65  */
67  .name = "c0",
68 #if CH_DBG_ENABLE_STACK_CHECK == TRUE
69  .mainthread_base = &__main_thread_stack_base__,
70  .mainthread_end = &__main_thread_stack_end__,
71 #elif CH_CFG_USE_DYNAMIC == TRUE
72  .mainthread_base = NULL,
73  .mainthread_end = NULL,
74 #endif
75 #if CH_CFG_NO_IDLE_THREAD == FALSE
76  .idlethread_base = THD_WORKING_AREA_BASE(ch_c0_idle_thread_wa),
77  .idlethread_end = THD_WORKING_AREA_END(ch_c0_idle_thread_wa)
78 #endif
79 };
80 #endif
81 
82 #if (PORT_CORES_NUMBER > 1) || defined(__DOXYGEN__)
83 /**
84  * @brief Core 1 OS instance.
85  */
87 
88 #if (CH_CFG_NO_IDLE_THREAD == FALSE) || defined(__DOXYGEN__)
89 /**
90  * @brief Working area for core 1 idle thread.
91  */
92 static CH_SYS_CORE1_MEMORY THD_WORKING_AREA(ch_c1_idle_thread_wa,
94 #endif
95 
96 #if CH_DBG_ENABLE_STACK_CHECK == TRUE
97 extern stkalign_t __c1_main_thread_stack_base__, __c1_main_thread_stack_end__;
98 #endif
99 
100 /**
101  * @brief Core 1 OS instance configuration.
102  */
104  .name = "c1",
105 #if CH_DBG_ENABLE_STACK_CHECK == TRUE
106  .mainthread_base = &__c1_main_thread_stack_base__,
107  .mainthread_end = &__c1_main_thread_stack_end__,
108 #elif CH_CFG_USE_DYNAMIC == TRUE
109  .mainthread_base = NULL,
110  .mainthread_end = NULL,
111 #endif
112 #if CH_CFG_NO_IDLE_THREAD == FALSE
113  .idlethread_base = THD_WORKING_AREA_BASE(ch_c1_idle_thread_wa),
114  .idlethread_end = THD_WORKING_AREA_END(ch_c1_idle_thread_wa)
115 #endif
116 };
117 #endif /* PORT_CORES_NUMBER > 1 */
118 
119 /*===========================================================================*/
120 /* Module local types. */
121 /*===========================================================================*/
122 
123 /*===========================================================================*/
124 /* Module local variables. */
125 /*===========================================================================*/
126 
127 /*===========================================================================*/
128 /* Module local functions. */
129 /*===========================================================================*/
130 
131 /*===========================================================================*/
132 /* Module exported functions. */
133 /*===========================================================================*/
134 
135 /**
136  * @brief Waits for the system state to be equal to the specified one.
137  * @note Can be called before @p chSchObjectInit() in order to wait
138  * for system initialization by another core.
139  *
140  * @special
141  */
143 
144  while (ch_system.state != state) {
145  }
146 }
147 
148 /**
149  * @brief System initialization.
150  * @details After executing this function the current instructions stream
151  * becomes the main thread.
152  * @pre Interrupts must disabled before invoking this function.
153  * @post The main thread is created with priority @p NORMALPRIO and
154  * interrupts are enabled.
155  * @post the system is in @p ch_sys_running state.
156  *
157  * @special
158  */
159 void chSysInit(void) {
160  unsigned i;
161 
162  /* System object initialization.*/
163  ch_system.state = ch_sys_initializing;
164  for (i = 0U; i < (unsigned)PORT_CORES_NUMBER; i++) {
165  ch_system.instances[i] = NULL;
166  }
167 
168 #if CH_CFG_USE_TM == TRUE
169  /* Time Measurement calibration.*/
171 #endif
172 
173 #if (CH_CFG_USE_REGISTRY == TRUE) && (CH_CFG_SMP_MODE == TRUE)
174  /* Registry initialization when SMP mode is enabled.*/
176 #endif
177 
178 #if CH_CFG_SMP_MODE == TRUE
179  /* RFCU initialization when SMP mode is enabled.*/
181 #endif
182 
183  /* User system initialization hook.*/
185 
186  /* OS library modules.*/
187  __oslib_init();
188 
189  /* Initializing default OS instance.*/
191 
192  /* It is alive now.*/
193  ch_system.state = ch_sys_running;
194  chSysUnlock();
195 }
196 
197 /**
198  * @brief Halts the system.
199  * @details This function is invoked by the operating system when an
200  * unrecoverable error is detected, for example because a programming
201  * error in the application code that triggers an assertion while
202  * in debug mode.
203  * @note Can be invoked from any system state.
204  *
205  * @param[in] reason pointer to an error string
206  *
207  * @special
208  */
209 void chSysHalt(const char *reason) {
210 
211  port_disable();
212 
213  /* Logging the event.*/
214  __trace_halt(reason);
215 
216  /* Pointing to the passed message.*/
217  currcore->dbg.panic_msg = reason;
218 
219  /* Halt hook code, usually empty.*/
220  CH_CFG_SYSTEM_HALT_HOOK(reason);
221 
222 #if defined(PORT_SYSTEM_HALT_HOOK)
223  /* Port-related actions, this could include halting other instances
224  via some inter-core messaging or other means.*/
225  PORT_SYSTEM_HALT_HOOK();
226 #endif
227 
228  /* Entering the halted state.*/
229  ch_system.state = ch_sys_halted;
230 
231  /* Harmless infinite loop.*/
232  while (true) {
233  }
234 }
235 
236 /**
237  * @brief System integrity check.
238  * @details Performs an integrity check of the important ChibiOS/RT data
239  * structures.
240  * @note The appropriate action in case of failure is to halt the system
241  * before releasing the critical zone.
242  * @note If the system is corrupted then one possible outcome of this
243  * function is an exception caused by @p NULL or corrupted pointers
244  * in list elements. Exception vectors must be monitored as well.
245  * @note This function is not used internally, it is up to the
246  * application to define if and where to perform system
247  * checking.
248  * @note Performing all tests at once can be a slow operation and can
249  * degrade the system response time. It is suggested to execute
250  * one test at time and release the critical zone in between tests.
251  *
252  * @param[in] testmask Each bit in this mask is associated to a test to be
253  * performed.
254  * @return The test result.
255  * @retval false The test succeeded.
256  * @retval true Test failed.
257  *
258  * @iclass
259  */
260 bool chSysIntegrityCheckI(unsigned testmask) {
261  os_instance_t *oip = currcore;
262  cnt_t n;
263 
264  chDbgCheckClassI();
265 
266  /* Ready List integrity check.*/
267  if ((testmask & CH_INTEGRITY_RLIST) != 0U) {
268  ch_priority_queue_t *pqp;
269 
270  /* Scanning the ready list forward.*/
271  n = (cnt_t)0;
272  pqp = oip->rlist.pqueue.next;
273  while (pqp != &oip->rlist.pqueue) {
274  n++;
275  pqp = pqp->next;
276  }
277 
278  /* Scanning the ready list backward.*/
279  pqp = oip->rlist.pqueue.prev;
280  while (pqp != &oip->rlist.pqueue) {
281  n--;
282  pqp = pqp->prev;
283  }
284 
285  /* The number of elements must match.*/
286  if (n != (cnt_t)0) {
287  return true;
288  }
289  }
290 
291  /* Timers list integrity check.*/
292  if ((testmask & CH_INTEGRITY_VTLIST) != 0U) {
293  ch_delta_list_t *dlp;
294 
295  /* Scanning the timers list forward.*/
296  n = (cnt_t)0;
297  dlp = oip->vtlist.dlist.next;
298  while (dlp != &oip->vtlist.dlist) {
299  n++;
300  dlp = dlp->next;
301  }
302 
303  /* Scanning the timers list backward.*/
304  dlp = oip->vtlist.dlist.prev;
305  while (dlp != &oip->vtlist.dlist) {
306  n--;
307  dlp = dlp->prev;
308  }
309 
310  /* The number of elements must match.*/
311  if (n != (cnt_t)0) {
312  return true;
313  }
314  }
315 
316 #if CH_CFG_USE_REGISTRY == TRUE
317  if ((testmask & CH_INTEGRITY_REGISTRY) != 0U) {
318  ch_queue_t *qp, *rqp;
319 
320  /* Registry header, access to this list depends on the current
321  kernel configuration.*/
322  rqp = REG_HEADER(oip);
323 
324  /* Scanning the ready list forward.*/
325  n = (cnt_t)0;
326  qp = rqp->next;
327  while (qp != rqp) {
328  n++;
329  qp = qp->next;
330  }
331 
332  /* Scanning the ready list backward.*/
333  qp = rqp->prev;
334  while (qp != rqp) {
335  n--;
336  qp = qp->prev;
337  }
338 
339  /* The number of elements must match.*/
340  if (n != (cnt_t)0) {
341  return true;
342  }
343  }
344 #endif /* CH_CFG_USE_REGISTRY == TRUE */
345 
346 #if defined(PORT_INTEGRITY_CHECK)
347  if ((testmask & CH_INTEGRITY_PORT) != 0U) {
348  PORT_INTEGRITY_CHECK();
349  }
350 #endif
351 
352  return false;
353 }
354 
355 /**
356  * @brief Handles time ticks for round robin preemption and timer increments.
357  * @details Decrements the remaining time quantum of the running thread
358  * and preempts it when the quantum is used up. Increments system
359  * time and manages the timers.
360  * @note The frequency of the timer determines the system tick granularity
361  * and, together with the @p CH_CFG_TIME_QUANTUM macro, the round robin
362  * interval.
363  *
364  * @iclass
365  */
366 void chSysTimerHandlerI(void) {
367 #if (CH_CFG_TIME_QUANTUM > 0) || (CH_DBG_THREADS_PROFILING == TRUE)
368  thread_t *currtp = chThdGetSelfX();
369 #endif
370 
371  chDbgCheckClassI();
372 
373 #if CH_CFG_TIME_QUANTUM > 0
374  /* Running thread has not used up quantum yet? */
375  if (currtp->ticks > (tslices_t)0) {
376  /* Decrement remaining quantum.*/
377  currtp->ticks--;
378  }
379 #endif
380 #if CH_DBG_THREADS_PROFILING == TRUE
381  currtp->time++;
382 #endif
383  chVTDoTickI();
385 }
386 
387 /**
388  * @brief Returns the execution status and enters a critical zone.
389  * @details This functions enters into a critical zone and can be called
390  * from any context. Because its flexibility it is less efficient
391  * than @p chSysLock() which is preferable when the calling context
392  * is known.
393  * @post The system is in a critical zone.
394  *
395  * @return The previous system status, the encoding of this
396  * status word is architecture-dependent and opaque.
397  *
398  * @xclass
399  */
401 
403  if (port_irq_enabled(sts)) {
404  if (port_is_isr_context()) {
406  }
407  else {
408  chSysLock();
409  }
410  }
411  return sts;
412 }
413 
414 /**
415  * @brief Restores the specified execution status and leaves a critical zone.
416  * @note A call to @p chSchRescheduleS() is automatically performed
417  * if exiting the critical zone and if not in ISR context.
418  *
419  * @param[in] sts the system status to be restored.
420  *
421  * @xclass
422  */
424 
425  if (port_irq_enabled(sts)) {
426  if (port_is_isr_context()) {
428  }
429  else {
431  chSysUnlock();
432  }
433  }
434 }
435 
436 #if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__)
437 /**
438  * @brief Realtime window test.
439  * @details This function verifies if the current realtime counter value
440  * lies within the specified range or not. The test takes care
441  * of the realtime counter wrapping to zero on overflow.
442  * @note When start==end then the function returns always false because a
443  * null time range is specified.
444  * @note This function is only available if the port layer supports the
445  * option @p PORT_SUPPORTS_RT.
446  *
447  * @param[in] cnt the counter value to be tested
448  * @param[in] start the start of the time window (inclusive)
449  * @param[in] end the end of the time window (non inclusive)
450  * @retval true current time within the specified time window.
451  * @retval false current time not within the specified time window.
452  *
453  * @xclass
454  */
456 
457  return (bool)(((rtcnt_t)cnt - (rtcnt_t)start) <
458  ((rtcnt_t)end - (rtcnt_t)start));
459 }
460 
461 /**
462  * @brief Polled delay.
463  * @note The real delay is always few cycles in excess of the specified
464  * value.
465  * @note This function is only available if the port layer supports the
466  * option @p PORT_SUPPORTS_RT.
467  *
468  * @param[in] cycles number of cycles
469  *
470  * @xclass
471  */
474  rtcnt_t end = start + cycles;
475 
476  while (chSysIsCounterWithinX(chSysGetRealtimeCounterX(), start, end)) {
477  }
478 }
479 #endif /* PORT_SUPPORTS_RT == TRUE */
480 
481 /** @} */
chVTDoTickI
void chVTDoTickI(void)
Virtual timers ticker.
Definition: chvt.c:377
chSysRestoreStatusX
void chSysRestoreStatusX(syssts_t sts)
Restores the specified execution status and leaves a critical zone.
Definition: chsys.c:423
chSysHalt
void chSysHalt(const char *reason)
Halts the system.
Definition: chsys.c:209
chSysIsCounterWithinX
bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end)
Realtime window test.
Definition: chsys.c:455
ch_queue::next
ch_queue_t * next
Next in the list/queue.
Definition: chlists.h:70
port_irq_enabled
static bool port_irq_enabled(syssts_t sts)
Checks the interrupt status.
Definition: chcore.h:324
ch_os_instance_config::name
const char * name
Instance name.
Definition: chobjects.h:367
ch_system::rfcu
rfcu_t rfcu
Runtime Faults Collection Unit.
Definition: chobjects.h:485
stkalign_t
port_stkalign_t stkalign_t
Definition: chearly.h:80
ch_os_instance::vtlist
virtual_timers_list_t vtlist
Virtual timers delta list header.
Definition: chobjects.h:402
currcore
#define currcore
Access to current core's instance structure.
Definition: chsys.h:90
CH_CFG_SYSTEM_HALT_HOOK
#define CH_CFG_SYSTEM_HALT_HOOK(reason)
System halt hook.
Definition: rt/templates/chconf.h:789
chSysUnlockFromISR
#define chSysUnlockFromISR()
Leaves the kernel lock state from within an interrupt handler.
Definition: nil/include/ch.h:1088
system_state_t
system_state_t
Global state of the operating system.
Definition: chobjects.h:50
__trace_halt
void __trace_halt(const char *reason)
Inserts in the circular debug trace buffer an halt record.
Definition: chtrace.c:186
chSysLockFromISR
#define chSysLockFromISR()
Enters the kernel lock state from within an interrupt handler.
Definition: nil/include/ch.h:1070
ch_os_instance
System instance data structure.
Definition: chobjects.h:394
chInstanceObjectInit
void chInstanceObjectInit(os_instance_t *oip, const os_instance_config_t *oicp)
Initializes a system instance.
Definition: chinstances.c:89
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_is_isr_context
static bool port_is_isr_context(void)
Determines the current execution context.
Definition: chcore.h:338
CH_CFG_SYSTEM_TICK_HOOK
#define CH_CFG_SYSTEM_TICK_HOOK()
System tick event hook.
Definition: rt/templates/chconf.h:780
CH_CFG_SYSTEM_INIT_HOOK
#define CH_CFG_SYSTEM_INIT_HOOK()
System initialization hook.
Definition: rt/templates/chconf.h:672
chSysGetRealtimeCounterX
#define chSysGetRealtimeCounterX()
Returns the current value of the system real time counter.
Definition: chsys.h:292
ch_system::tmc
tm_calibration_t tmc
Time measurement calibration data.
Definition: chobjects.h:470
PORT_IDLE_THREAD_STACK_SIZE
#define PORT_IDLE_THREAD_STACK_SIZE
Stack size for the system idle thread.
Definition: chcore.h:111
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
cnt_t
int32_t cnt_t
Definition: chearly.h:92
ch_virtual_timers_list::dlist
ch_delta_list_t dlist
Delta list header.
Definition: chobjects.h:104
syssts_t
port_syssts_t syssts_t
Definition: chearly.h:79
ch_system
ch_system_t ch_system
System root object.
Definition: chsys.c:45
ch_thread::ticks
tslices_t ticks
Number of ticks remaining to this thread.
Definition: chobjects.h:221
rtcnt_t
port_rtcnt_t rtcnt_t
Definition: chearly.h:77
THD_WORKING_AREA_BASE
#define THD_WORKING_AREA_BASE(s)
Base of a working area casted to the correct type.
Definition: chthreads.h:150
ch_system::reglist
registry_t reglist
Registry header.
Definition: chobjects.h:478
ch_delta_list::next
ch_delta_list_t * next
Next in the delta list.
Definition: chlists.h:101
tslices_t
uint8_t tslices_t
Definition: chearly.h:86
__tm_calibration_object_init
static void __tm_calibration_object_init(tm_calibration_t *tcp)
Time measurement initialization.
Definition: chtm.h:119
port_get_irq_status
static syssts_t port_get_irq_status(void)
Returns a word encoding the current interrupts status.
Definition: chcore.h:310
THD_WORKING_AREA_END
#define THD_WORKING_AREA_END(s)
End of a working area casted to the correct type.
Definition: chthreads.h:157
ch_queue
Structure representing a generic bidirectional linked list header and element.
Definition: chlists.h:69
chSysGetStatusAndLockX
syssts_t chSysGetStatusAndLockX(void)
Returns the execution status and enters a critical zone.
Definition: chsys.c:400
chSchRescheduleS
void chSchRescheduleS(void)
Performs a reschedule if a higher priority thread is runnable.
Definition: chschd.c:454
ch_thread::time
volatile systime_t time
Thread consumed time in ticks.
Definition: chobjects.h:228
port_disable
static void port_disable(void)
Disables all the interrupt sources.
Definition: chcore.h:385
__rfcu_object_init
static void __rfcu_object_init(rfcu_t *rfcup)
Runtime Faults Collection Unit initialization.
Definition: chrfcu.h:104
ch_priority_queue::next
ch_priority_queue_t * next
Next in the queue.
Definition: chlists.h:86
REG_HEADER
#define REG_HEADER(oip)
Access to the registry list header.
Definition: chregistry.h:81
chSysInit
void chSysInit(void)
System initialization.
Definition: chsys.c:159
ch_queue::prev
ch_queue_t * prev
Previous in the queue.
Definition: chlists.h:71
ch_delta_list::prev
ch_delta_list_t * prev
Previous in the delta list.
Definition: chlists.h:102
ch_priority_queue::prev
ch_priority_queue_t * prev
Previous in the queue.
Definition: chlists.h:87
ch_system::state
system_state_t state
Operating system state.
Definition: chobjects.h:461
ch_os_instance_config
Type of an system instance configuration.
Definition: chobjects.h:363
ch_system::instances
os_instance_t * instances[PORT_CORES_NUMBER]
Initialized OS instances or NULL.
Definition: chobjects.h:465
CH_SYS_CORE0_MEMORY
#define CH_SYS_CORE0_MEMORY
Core zero memory affinity macro.
Definition: chsys.h:62
__oslib_init
static void __oslib_init(void)
Initialization of all library modules.
Definition: chlib.h:249
ch_os_instance::rlist
ready_list_t rlist
Ready list header.
Definition: chobjects.h:398
ch0
CH_SYS_CORE0_MEMORY os_instance_t ch0
Core 0 OS instance.
Definition: chsys.c:50
THD_WORKING_AREA
static CH_SYS_CORE0_MEMORY THD_WORKING_AREA(ch_c0_idle_thread_wa, PORT_IDLE_THREAD_STACK_SIZE)
Working area for core 0 idle thread.
__reg_object_init
static void __reg_object_init(registry_t *rp)
Initializes a registry.
Definition: chregistry.h:134
ch_priority_queue
Structure representing a generic priority-ordered bidirectional linked list header and element.
Definition: chlists.h:85
ch_delta_list
Delta list element and header structure.
Definition: chlists.h:100
chSysUnlock
#define chSysUnlock()
Leaves the kernel lock state.
Definition: nil/include/ch.h:1053
ch_ready_list::pqueue
ch_priority_queue_t pqueue
Threads ordered queues header.
Definition: chobjects.h:353
chThdGetSelfX
#define chThdGetSelfX()
Returns a pointer to the current thread_t.
Definition: nil/include/ch.h:1132
CH_SYS_CORE1_MEMORY
#define CH_SYS_CORE1_MEMORY
Core one memory affinity macro.
Definition: chsys.h:74
chSysLock
#define chSysLock()
Enters the kernel lock state.
Definition: nil/include/ch.h:1043