diff options
Diffstat (limited to 'ChibiOS_20.3.2/os/nil/include')
-rw-r--r-- | ChibiOS_20.3.2/os/nil/include/ch.h | 1419 | ||||
-rw-r--r-- | ChibiOS_20.3.2/os/nil/include/chevt.h | 301 | ||||
-rw-r--r-- | ChibiOS_20.3.2/os/nil/include/chmsg.h | 123 | ||||
-rw-r--r-- | ChibiOS_20.3.2/os/nil/include/chsem.h | 180 |
4 files changed, 2023 insertions, 0 deletions
diff --git a/ChibiOS_20.3.2/os/nil/include/ch.h b/ChibiOS_20.3.2/os/nil/include/ch.h new file mode 100644 index 0000000..0e407bf --- /dev/null +++ b/ChibiOS_20.3.2/os/nil/include/ch.h @@ -0,0 +1,1419 @@ +/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file nil/include/ch.h
+ * @brief Nil RTOS main header file.
+ * @details This header includes all the required kernel headers so it is the
+ * only header you usually need to include in your application.
+ *
+ * @addtogroup NIL_KERNEL
+ * @{
+ */
+
+#ifndef CH_H
+#define CH_H
+
+#include "chtypes.h"
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/**
+ * @brief ChibiOS/NIL identification macro.
+ */
+#define _CHIBIOS_NIL_
+
+/**
+ * @brief Stable release flag.
+ */
+#define CH_KERNEL_STABLE 1
+
+/**
+ * @name ChibiOS/NIL version identification
+ * @{
+ */
+/**
+ * @brief Kernel version string.
+ */
+#define CH_KERNEL_VERSION "4.0.0"
+
+/**
+ * @brief Kernel version major number.
+ */
+#define CH_KERNEL_MAJOR 4
+
+/**
+ * @brief Kernel version minor number.
+ */
+#define CH_KERNEL_MINOR 0
+
+/**
+ * @brief Kernel version patch number.
+ */
+#define CH_KERNEL_PATCH 0
+/** @} */
+
+/**
+ * @name Constants for configuration options
+ */
+/**
+ * @brief Generic 'false' preprocessor boolean constant.
+ * @note It is meant to be used in configuration files as switch.
+ */
+#if !defined(FALSE) || defined(__DOXYGEN__)
+#define FALSE 0
+#endif
+
+/**
+ * @brief Generic 'true' preprocessor boolean constant.
+ * @note It is meant to be used in configuration files as switch.
+ */
+#if !defined(TRUE) || defined(__DOXYGEN__)
+#define TRUE 1
+#endif
+/** @} */
+
+/**
+ * @name Wakeup messages
+ * @{
+ */
+#define MSG_OK (msg_t)0 /**< @brief OK wakeup message. */
+#define MSG_TIMEOUT (msg_t)-1 /**< @brief Wake-up caused by
+ a timeout condition. */
+#define MSG_RESET (msg_t)-2 /**< @brief Wake-up caused by
+ a reset condition. */
+/** @} */
+
+/**
+ * @name Special time constants
+ * @{
+ */
+/**
+ * @brief Zero time specification for some functions with a timeout
+ * specification.
+ * @note Not all functions accept @p TIME_IMMEDIATE as timeout parameter,
+ * see the specific function documentation.
+ */
+#define TIME_IMMEDIATE ((sysinterval_t)-1)
+
+/**
+ * @brief Infinite time specification for all functions with a timeout
+ * specification.
+ */
+#define TIME_INFINITE ((sysinterval_t)0)
+
+/**
+ * @brief Maximum interval constant usable as timeout.
+ */
+#define TIME_MAX_INTERVAL ((sysinterval_t)-2)
+
+/**
+ * @brief Maximum system of system time before it wraps.
+ */
+#define TIME_MAX_SYSTIME ((systime_t)-1)
+/** @} */
+
+/**
+ * @name Thread state related macros
+ * @{
+ */
+#define NIL_STATE_WTSTART (tstate_t)0 /**< @brief Thread not yet
+ started or terminated. */
+#define NIL_STATE_READY (tstate_t)1 /**< @brief Thread ready or
+ executing. */
+#define NIL_STATE_SLEEPING (tstate_t)2 /**< @brief Thread sleeping. */
+#define NIL_STATE_SUSPENDED (tstate_t)3 /**< @brief Thread suspended. */
+#define NIL_STATE_WTEXIT (tstate_t)4 /**< @brief Waiting a thread. */
+#define NIL_STATE_WTQUEUE (tstate_t)5 /**< @brief On queue or semaph. */
+#define NIL_STATE_WTOREVT (tstate_t)6 /**< @brief Waiting for events. */
+#define NIL_STATE_WTANDEVT (tstate_t)7 /**< @brief Waiting for events. */
+#define NIL_STATE_SNDMSGQ (tstate_t)8 /**< @brief Sending a message,
+ in queue. */
+#define NIL_STATE_WTMSG (tstate_t)10/**< @brief Waiting for a
+ message. */
+#define NIL_STATE_FINAL (tstate_t)11/**< @brief Thread terminated. */
+
+#define NIL_THD_IS_WTSTART(tp) ((tp)->state == NIL_STATE_WTSTART)
+#define NIL_THD_IS_READY(tp) ((tp)->state == NIL_STATE_READY)
+#define NIL_THD_IS_SLEEPING(tp) ((tp)->state == NIL_STATE_SLEEPING)
+#define NIL_THD_IS_SUSPENDED(tp) ((tp)->state == NIL_STATE_SUSPENDED)
+#define NIL_THD_IS_WTEXIT(tp) ((tp)->state == NIL_STATE_WTEXIT)
+#define NIL_THD_IS_WTQUEUE(tp) ((tp)->state == NIL_STATE_WTQUEUE)
+#define NIL_THD_IS_WTOREVT(tp) ((tp)->state == NIL_STATE_WTOREVT)
+#define NIL_THD_IS_WTANDEVT(tp) ((tp)->state == NIL_STATE_WTANDEVT)
+#define NIL_THD_IS_SNDMSGQ(tp) ((tp)->state == NIL_STATE_SNDMSGQ)
+#define NIL_THD_IS_WTMSG(tp) ((tp)->state == NIL_STATE_WTMSG)
+#define NIL_THD_IS_FINAL(tp) ((tp)->state == NIL_STATE_FINAL)
+
+#define CH_STATE_NAMES \
+ "WTSTART", "READY", "SLEEPING", "SUSPENDED", "WTEXIT", "WTQUEUE", \
+ "WTOREVT", "WTANDEVT", "SNDMSGQ", "SNDMSG", "WTMSG", "FINAL"
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+#include "chconf.h"
+#include "chlicense.h"
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/* Checks on configuration options.*/
+#if !defined(CH_CFG_MAX_THREADS) || defined(__DOXYGEN__)
+#error "CH_CFG_MAX_THREADS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_AUTOSTART_THREADS) || defined(__DOXYGEN__)
+#error "CH_CFG_AUTOSTART_THREADS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_ST_RESOLUTION) || defined(__DOXYGEN__)
+#error "CH_CFG_ST_RESOLUTION not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_ST_FREQUENCY) || defined(__DOXYGEN__)
+#error "CH_CFG_ST_FREQUENCY not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_ST_TIMEDELTA) || defined(__DOXYGEN__)
+#error "CH_CFG_ST_TIMEDELTA not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_WAITEXIT)
+#error "CH_CFG_USE_WAITEXIT not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_MESSAGES) || defined(__DOXYGEN__)
+#error "CH_CFG_USE_MESSAGES not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
+#error "CH_CFG_USE_SEMAPHORES not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_EVENTS)
+#error "CH_CFG_USE_EVENTS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__)
+#error "CH_CFG_USE_MUTEXES not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_STATISTICS) || defined(__DOXYGEN__)
+#error "CH_DBG_STATISTICS not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_SYSTEM_STATE_CHECK) || defined(__DOXYGEN__)
+#error "CH_DBG_SYSTEM_STATE_CHECK not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
+#error "CH_DBG_ENABLE_CHECKS not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
+#error "CH_DBG_ENABLE_ASSERTS not defined in chconf.h"
+#endif
+
+#if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)
+#error "CH_DBG_ENABLE_STACK_CHECK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_SYSTEM_INIT_HOOK) || defined(__DOXYGEN__)
+#error "CH_CFG_SYSTEM_INIT_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_THREAD_EXT_FIELDS) || defined(__DOXYGEN__)
+#error "CH_CFG_THREAD_EXT_FIELDS not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_THREAD_EXT_INIT_HOOK) || defined(__DOXYGEN__)
+#error "CH_CFG_THREAD_EXT_INIT_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_THREAD_EXIT_HOOK) || defined(__DOXYGEN__)
+#error "CH_CFG_THREAD_EXIT_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_IDLE_ENTER_HOOK) || defined(__DOXYGEN__)
+#error "CH_CFG_IDLE_ENTER_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_IDLE_LEAVE_HOOK) || defined(__DOXYGEN__)
+#error "CH_CFG_IDLE_LEAVE_HOOK not defined in chconf.h"
+#endif
+
+#if !defined(CH_CFG_SYSTEM_HALT_HOOK) || defined(__DOXYGEN__)
+#error "CH_CFG_SYSTEM_HALT_HOOK not defined in chconf.h"
+#endif
+
+/* License checks.*/
+#if !defined(CH_CUSTOMER_LIC_NIL) || !defined(CH_LICENSE_FEATURES)
+#error "malformed chlicense.h"
+#endif
+
+#if CH_CUSTOMER_LIC_NIL == FALSE
+#error "ChibiOS/NIL not licensed"
+#endif
+
+#if (CH_LICENSE_FEATURES != CH_FEATURES_FULL) && \
+ (CH_LICENSE_FEATURES != CH_FEATURES_INTERMEDIATE) && \
+ (CH_LICENSE_FEATURES != CH_FEATURES_BASIC)
+#error "invalid CH_LICENSE_FEATURES setting"
+#endif
+
+/* Restrictions in basic and intermediate modes.*/
+#if (CH_LICENSE_FEATURES == CH_FEATURES_INTERMEDIATE) || \
+ (CH_LICENSE_FEATURES == CH_FEATURES_BASIC)
+
+/* System tick limited to 1000hz.*/
+#if CH_CFG_ST_FREQUENCY > 1000
+#undef CH_CFG_ST_FREQUENCY
+#define CH_CFG_ST_FREQUENCY 1000
+#endif
+
+#endif /* (CH_LICENSE_FEATURES == CH_FEATURES_INTERMEDIATE) ||
+ (CH_LICENSE_FEATURES == CH_FEATURES_BASIC) */
+
+/* Restrictions in basic mode.*/
+#if CH_LICENSE_FEATURES == CH_FEATURES_BASIC
+
+/* Tick-Less mode restricted.*/
+#undef CH_CFG_ST_TIMEDELTA
+#define CH_CFG_ST_TIMEDELTA 0
+
+/* Messages restricted.*/
+#undef CH_CFG_USE_MESSAGES
+#define CH_CFG_USE_MESSAGES FALSE
+
+#endif /* CH_LICENSE_FEATURES == CH_FEATURES_BASIC */
+
+#if !defined(_CHIBIOS_NIL_CONF_)
+#error "missing or wrong configuration file"
+#endif
+
+#if !defined(_CHIBIOS_NIL_CONF_VER_4_0_)
+#error "obsolete or unknown configuration file"
+#endif
+
+#if CH_CFG_MAX_THREADS < 1
+#error "at least one thread must be defined"
+#endif
+
+#if CH_CFG_MAX_THREADS > 16
+#error "ChibiOS/NIL is not recommended for thread-intensive applications," \
+ "consider ChibiOS/RT instead"
+#endif
+
+#if (CH_CFG_ST_RESOLUTION != 16) && (CH_CFG_ST_RESOLUTION != 32)
+#error "invalid CH_CFG_ST_RESOLUTION specified, must be 16 or 32"
+#endif
+
+#if CH_CFG_ST_FREQUENCY <= 0
+#error "invalid CH_CFG_ST_FREQUENCY specified, must be greater than zero"
+#endif
+
+#if (CH_CFG_ST_TIMEDELTA < 0) || (CH_CFG_ST_TIMEDELTA == 1)
+#error "invalid CH_CFG_ST_TIMEDELTA specified, must " \
+ "be zero or greater than one"
+#endif
+
+#if CH_CFG_USE_MUTEXES == TRUE
+#error "mutexes not yet supported"
+#endif
+
+#if CH_DBG_STATISTICS == TRUE
+#error "statistics not yet supported"
+#endif
+
+#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE) || \
+ (CH_DBG_ENABLE_CHECKS == TRUE) || \
+ (CH_DBG_ENABLE_ASSERTS == TRUE) || \
+ (CH_DBG_ENABLE_STACK_CHECK == TRUE)
+#define NIL_DBG_ENABLED TRUE
+#else
+#define NIL_DBG_ENABLED FALSE
+#endif
+
+/** Boundaries of the idle thread boundaries, only required if stack checking
+ is enabled.*/
+#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || defined(__DOXYGEN__)
+#define THD_IDLE_BASE (&__main_thread_stack_base__)
+#define THD_IDLE_END (&__main_thread_stack_end__)
+#else
+#define THD_IDLE_BASE NULL
+#define THD_IDLE_END NULL
+#endif
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+#if (CH_CFG_ST_RESOLUTION == 32) || defined(__DOXYGEN__)
+/**
+ * @brief Type of system time.
+ * @note It is selectable in configuration between 16 or 32 bits.
+ */
+typedef uint32_t systime_t;
+
+/**
+ * @brief Type of time interval.
+ * @note It is selectable in configuration between 16 or 32 bits.
+ */
+typedef uint32_t sysinterval_t;
+
+/**
+ * @brief Type of time conversion variable.
+ * @note This type must have double width than other time types, it is
+ * only used internally for conversions.
+ */
+typedef uint64_t time_conv_t;
+
+#else
+typedef uint16_t systime_t;
+typedef uint16_t sysinterval_t;
+typedef uint32_t time_conv_t;
+#endif
+
+/**
+ * @brief Type of a structure representing the system.
+ */
+typedef struct nil_system nil_system_t;
+
+/**
+ * @brief Thread function.
+ */
+typedef void (*tfunc_t)(void *p);
+
+/**
+ * @brief Type of a thread descriptor.
+ */
+typedef struct nil_thread_descriptor thread_descriptor_t;
+
+/**
+ * @brief Type of a structure representing a thread.
+ * @note It is required as an early definition.
+ */
+typedef struct nil_thread thread_t;
+
+/**
+ * @brief Type of a thread reference.
+ */
+typedef thread_t * thread_reference_t;
+
+/**
+ * @brief Type of a queue of threads.
+ */
+typedef struct nil_threads_queue threads_queue_t;
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+/**
+ * @brief Type of a structure representing a semaphore.
+ * @note Semaphores are implemented on thread queues, the object is the
+ * same, the behavior is slightly different.
+ */
+typedef threads_queue_t semaphore_t;
+#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
+
+/* Late inclusion of port core layer.*/
+#include "chcore.h"
+
+/**
+ * @brief Structure representing a queue of threads.
+ */
+struct nil_threads_queue {
+ volatile cnt_t cnt; /**< @brief Threads Queue counter. */
+};
+
+/**
+ * @brief Structure representing a thread descriptor.
+ */
+struct nil_thread_descriptor {
+ const char *name; /**< @brief Thread name, for debugging. */
+ stkalign_t *wbase; /**< @brief Thread working area base. */
+ stkalign_t *wend; /**< @brief Thread working area end. */
+ tprio_t prio; /**< @brief Thread priority slot. */
+ tfunc_t funcp; /**< @brief Thread function. */
+ void *arg; /**< @brief Thread function argument. */
+};
+
+/**
+ * @brief Structure representing a thread.
+ */
+struct nil_thread {
+ struct port_context ctx; /**< @brief Processor context. */
+ tstate_t state; /**< @brief Thread state. */
+ /* Note, the following union contains a pointer/value while the thread is
+ in a sleeping state or a wake-up message when the thread is made ready.*/
+ union {
+ msg_t msg; /**< @brief Wake-up/exit message. */
+ void *p; /**< @brief Generic pointer. */
+ nil_system_t *nsp; /**< @brief Pointer to nil base struct. */
+ thread_reference_t *trp; /**< @brief Pointer to thread reference.*/
+ threads_queue_t *tqp; /**< @brief Pointer to thread queue. */
+ thread_t *tp; /**< @brief Pointer to thread. */
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+ semaphore_t *semp; /**< @brief Pointer to semaphore. */
+#endif
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+ eventmask_t ewmask; /**< @brief Enabled events mask. */
+#endif
+ } u1;
+ volatile sysinterval_t timeout; /**< @brief Timeout counter, zero
+ if disabled. */
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+ eventmask_t epmask; /**< @brief Pending events mask. */
+#endif
+#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
+ msg_t sntmsg; /**< @brief Sent message. */
+#endif
+#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || defined(__DOXYGEN__)
+ stkalign_t *wabase; /**< @brief Thread stack boundary. */
+#endif
+ /* Optional extra fields.*/
+ CH_CFG_THREAD_EXT_FIELDS
+};
+
+/**
+ * @brief System data structure.
+ * @note This structure contain all the data areas used by the OS except
+ * stacks.
+ */
+struct nil_system {
+ /**
+ * @brief Pointer to the running thread.
+ */
+ thread_t *current;
+ /**
+ * @brief Pointer to the next thread to be executed.
+ * @note This pointer must point at the same thread pointed by @p current
+ * or to an higher priority thread if a switch is required.
+ */
+ thread_t *next;
+#if (CH_CFG_ST_TIMEDELTA == 0) || defined(__DOXYGEN__)
+ /**
+ * @brief System time.
+ */
+ volatile systime_t systime;
+#endif
+#if (CH_CFG_ST_TIMEDELTA > 0) || defined(__DOXYGEN__)
+ /**
+ * @brief System time of the last tick event.
+ */
+ systime_t lasttime;
+ /**
+ * @brief Time of the next scheduled tick event.
+ */
+ systime_t nexttime;
+#endif
+#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief ISR nesting level.
+ */
+ cnt_t isr_cnt;
+ /**
+ * @brief Lock nesting level.
+ */
+ cnt_t lock_cnt;
+#endif
+#if (NIL_DBG_ENABLED == TRUE) || defined(__DOXYGEN__)
+ /**
+ * @brief Panic message.
+ * @note This field is only present if some debug options have been
+ * activated.
+ * @note Accesses to this pointer must never be optimized out so the
+ * field itself is declared volatile.
+ */
+ const char * volatile dbg_panic_msg;
+#endif
+ /**
+ * @brief Thread structures for all the defined threads.
+ */
+ thread_t threads[CH_CFG_MAX_THREADS + 1];
+};
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+#if CH_DBG_SYSTEM_STATE_CHECK == TRUE
+#define _dbg_enter_lock() (nil.lock_cnt = (cnt_t)1)
+#define _dbg_leave_lock() (nil.lock_cnt = (cnt_t)0)
+#endif
+
+/**
+ * @brief Utility to make the parameter a quoted string.
+ */
+#define __CH_STRINGIFY(a) #a
+
+/**
+ * @name Threads tables definition macros
+ * @{
+ */
+/**
+ * @brief Start of user threads table.
+ */
+#define THD_TABLE_BEGIN \
+ const thread_descriptor_t nil_thd_configs[] = {
+
+/**
+ * @brief Entry of user threads table
+ */
+#define THD_TABLE_THREAD(_prio, _name, _wap, _funcp, _arg) \
+ { \
+ .name = (_name), \
+ .wbase = (_wap), \
+ .wend = THD_WORKING_AREA_END(_wap), \
+ .prio = (_prio), \
+ .funcp = (_funcp), \
+ .arg = (_arg) \
+ },
+
+/**
+ * @brief End of user threads table.
+ */
+#define THD_TABLE_END \
+ { \
+ .name = "idle", \
+ .wbase = THD_IDLE_BASE, \
+ .wend = THD_IDLE_END, \
+ .prio = CH_CFG_MAX_THREADS, \
+ .funcp = NULL, \
+ .arg = NULL \
+ } \
+};
+/** @} */
+
+/**
+ * @name Memory alignment support macros
+ */
+/**
+ * @brief Alignment mask constant.
+ *
+ * @param[in] a alignment, must be a power of two
+ */
+#define MEM_ALIGN_MASK(a) ((size_t)(a) - 1U)
+
+/**
+ * @brief Aligns to the previous aligned memory address.
+ *
+ * @param[in] p variable to be aligned
+ * @param[in] a alignment, must be a power of two
+ */
+#define MEM_ALIGN_PREV(p, a) ((size_t)(p) & ~MEM_ALIGN_MASK(a))
+
+/**
+ * @brief Aligns to the new aligned memory address.
+ *
+ * @param[in] p variable to be aligned
+ * @param[in] a alignment, must be a power of two
+ */
+#define MEM_ALIGN_NEXT(p, a) MEM_ALIGN_PREV((size_t)(p) + \
+ MEM_ALIGN_MASK(a), (a))
+
+/**
+ * @brief Returns whatever a pointer or memory size is aligned.
+ *
+ * @param[in] p variable to be aligned
+ * @param[in] a alignment, must be a power of two
+ */
+#define MEM_IS_ALIGNED(p, a) (((size_t)(p) & MEM_ALIGN_MASK(a)) == 0U)
+
+/**
+ * @brief Returns whatever a constant is a valid alignment.
+ * @details Valid alignments are powers of two.
+ *
+ * @param[in] a alignment to be checked, must be a constant
+ */
+#define MEM_IS_VALID_ALIGNMENT(a) \
+ (((size_t)(a) != 0U) && (((size_t)(a) & ((size_t)(a) - 1U)) == 0U))
+/** @} */
+
+/**
+ * @name Working Areas
+ */
+/**
+ * @brief Calculates the total Working Area size.
+ *
+ * @param[in] n the stack size to be assigned to the thread
+ * @return The total used memory in bytes.
+ *
+ * @api
+ */
+#define THD_WORKING_AREA_SIZE(n) MEM_ALIGN_NEXT(PORT_WA_SIZE(n), \
+ PORT_STACK_ALIGN)
+
+/**
+ * @brief Static working area allocation.
+ * @details This macro is used to allocate a static thread working area
+ * aligned as both position and size.
+ *
+ * @param[in] s the name to be assigned to the stack array
+ * @param[in] n the stack size to be assigned to the thread
+ *
+ * @api
+ */
+#define THD_WORKING_AREA(s, n) PORT_WORKING_AREA(s, n)
+/** @} */
+
+/**
+ * @brief Returns the top address of a working area.
+ * @note The parameter is assumed to be an array of @p stkalign_t. The
+ * macros is invalid for anything else.
+ *
+ * @param[in] wa working area array
+ *
+ * @api
+ */
+#define THD_WORKING_AREA_END(wa) \
+ ((wa) + ((sizeof wa) / sizeof (stkalign_t)))
+
+/**
+ * @name Threads abstraction macros
+ */
+/**
+ * @brief Thread declaration macro.
+ * @note Thread declarations should be performed using this macro because
+ * the port layer could define optimizations for thread functions.
+ */
+#define THD_FUNCTION(tname, arg) PORT_THD_FUNCTION(tname, arg)
+/** @} */
+
+/**
+ * @name ISRs abstraction macros
+ */
+/**
+ * @brief Priority level validation macro.
+ * @details This macro determines if the passed value is a valid priority
+ * level for the underlying architecture.
+ *
+ * @param[in] prio the priority level
+ * @return Priority range result.
+ * @retval false if the priority is invalid or if the architecture
+ * does not support priorities.
+ * @retval true if the priority is valid.
+ */
+#if defined(PORT_IRQ_IS_VALID_PRIORITY) || defined(__DOXYGEN__)
+#define CH_IRQ_IS_VALID_PRIORITY(prio) \
+ PORT_IRQ_IS_VALID_PRIORITY(prio)
+#else
+#define CH_IRQ_IS_VALID_PRIORITY(prio) false
+#endif
+
+/**
+ * @brief Priority level validation macro.
+ * @details This macro determines if the passed value is a valid priority
+ * level that cannot preempt the kernel critical zone.
+ *
+ * @param[in] prio the priority level
+ * @return Priority range result.
+ * @retval false if the priority is invalid or if the architecture
+ * does not support priorities.
+ * @retval true if the priority is valid.
+ */
+#if defined(PORT_IRQ_IS_VALID_KERNEL_PRIORITY) || defined(__DOXYGEN__)
+#define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) \
+ PORT_IRQ_IS_VALID_KERNEL_PRIORITY(prio)
+#else
+#define CH_IRQ_IS_VALID_KERNEL_PRIORITY(prio) false
+#endif
+
+/**
+ * @brief IRQ handler enter code.
+ * @note Usually IRQ handlers functions are also declared naked.
+ * @note On some architectures this macro can be empty.
+ *
+ * @special
+ */
+#define CH_IRQ_PROLOGUE() \
+ PORT_IRQ_PROLOGUE(); \
+ _dbg_check_enter_isr()
+
+/**
+ * @brief IRQ handler exit code.
+ * @note Usually IRQ handlers function are also declared naked.
+ *
+ * @special
+ */
+#define CH_IRQ_EPILOGUE() \
+ _dbg_check_leave_isr(); \
+ PORT_IRQ_EPILOGUE()
+
+/**
+ * @brief Standard normal IRQ handler declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ *
+ * @special
+ */
+#define CH_IRQ_HANDLER(id) PORT_IRQ_HANDLER(id)
+/** @} */
+
+/**
+ * @name Fast ISRs abstraction macros
+ */
+/**
+ * @brief Standard fast IRQ handler declaration.
+ * @note @p id can be a function name or a vector number depending on the
+ * port implementation.
+ * @note Not all architectures support fast interrupts.
+ *
+ * @special
+ */
+#define CH_FAST_IRQ_HANDLER(id) PORT_FAST_IRQ_HANDLER(id)
+/** @} */
+
+/**
+ * @name Time conversion utilities
+ * @{
+ */
+/**
+ * @brief Seconds to time interval.
+ * @details Converts from seconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] secs number of seconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define TIME_S2I(secs) \
+ ((sysinterval_t)((time_conv_t)(secs) * (time_conv_t)CH_CFG_ST_FREQUENCY))
+
+/**
+ * @brief Milliseconds to time interval.
+ * @details Converts from milliseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] msecs number of milliseconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define TIME_MS2I(msecs) \
+ ((sysinterval_t)((((time_conv_t)(msecs) * \
+ (time_conv_t)CH_CFG_ST_FREQUENCY) + \
+ (time_conv_t)999) / (time_conv_t)1000))
+
+/**
+ * @brief Microseconds to time interval.
+ * @details Converts from microseconds to system ticks number.
+ * @note The result is rounded upward to the next tick boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] usecs number of microseconds
+ * @return The number of ticks.
+ *
+ * @api
+ */
+#define TIME_US2I(usecs) \
+ ((sysinterval_t)((((time_conv_t)(usecs) * \
+ (time_conv_t)CH_CFG_ST_FREQUENCY) + \
+ (time_conv_t)999999) / (time_conv_t)1000000))
+
+/**
+ * @brief Time interval to seconds.
+ * @details Converts from system ticks number to seconds.
+ * @note The result is rounded up to the next second boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of seconds.
+ *
+ * @api
+ */
+#define TIME_I2S(interval) \
+ (time_secs_t)(((time_conv_t)(interval) + \
+ (time_conv_t)CH_CFG_ST_FREQUENCY - \
+ (time_conv_t)1) / (time_conv_t)CH_CFG_ST_FREQUENCY)
+
+/**
+ * @brief Time interval to milliseconds.
+ * @details Converts from system ticks number to milliseconds.
+ * @note The result is rounded up to the next millisecond boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of milliseconds.
+ *
+ * @api
+ */
+#define TIME_I2MS(interval) \
+ (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000) + \
+ (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \
+ (time_conv_t)CH_CFG_ST_FREQUENCY)
+
+/**
+ * @brief Time interval to microseconds.
+ * @details Converts from system ticks number to microseconds.
+ * @note The result is rounded up to the next microsecond boundary.
+ * @note Use of this macro for large values is not secure because
+ * integer overflows, make sure your value can be correctly
+ * converted.
+ *
+ * @param[in] interval interval in ticks
+ * @return The number of microseconds.
+ *
+ * @api
+ */
+#define TIME_I2US(interval) \
+ (time_msecs_t)((((time_conv_t)(interval) * (time_conv_t)1000000) + \
+ (time_conv_t)CH_CFG_ST_FREQUENCY - (time_conv_t)1) / \
+ (time_conv_t)CH_CFG_ST_FREQUENCY)
+/** @} */
+
+/**
+ * @name Threads queues
+ */
+/**
+ * @brief Data part of a static threads queue object initializer.
+ * @details This macro should be used when statically initializing a threads
+ * queue that is part of a bigger structure.
+ *
+ * @param[in] name the name of the threads queue variable
+ */
+#define _THREADS_QUEUE_DATA(name) {(cnt_t)0}
+
+/**
+ * @brief Static threads queue object initializer.
+ * @details Statically initialized threads queues require no explicit
+ * initialization using @p queue_init().
+ *
+ * @param[in] name the name of the threads queue variable
+ */
+#define _THREADS_QUEUE_DECL(name) \
+ threads_queue_t name = _THREADS_QUEUE_DATA(name)
+/** @} */
+
+/**
+ * @name Semaphores macros
+ * @{
+ */
+/**
+ * @brief Data part of a static semaphore initializer.
+ * @details This macro should be used when statically initializing a semaphore
+ * that is part of a bigger structure.
+ *
+ * @param[in] name the name of the semaphore variable
+ * @param[in] n the counter initial value, this value must be
+ * non-negative
+ */
+#define _SEMAPHORE_DATA(name, n) {n}
+
+/**
+ * @brief Static semaphore initializer.
+ * @details Statically initialized semaphores require no explicit
+ * initialization using @p chSemInit().
+ *
+ * @param[in] name the name of the semaphore variable
+ * @param[in] n the counter initial value, this value must be
+ * non-negative
+ */
+#define SEMAPHORE_DECL(name, n) semaphore_t name = _SEMAPHORE_DATA(name, n)
+/** @} */
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Returns the current value of the system real time counter.
+ * @note This function is only available if the port layer supports the
+ * option @p PORT_SUPPORTS_RT.
+ *
+ * @return The value of the system realtime counter of
+ * type rtcnt_t.
+ *
+ * @xclass
+ */
+#if (PORT_SUPPORTS_RT == TRUE) || defined(__DOXYGEN__)
+#define chSysGetRealtimeCounterX() (rtcnt_t)port_rt_get_counter_value()
+#endif
+
+/**
+ * @brief Raises the system interrupt priority mask to the maximum level.
+ * @details All the maskable interrupt sources are disabled regardless their
+ * hardware priority.
+ * @note Do not invoke this API from within a kernel lock.
+ *
+ * @special
+ */
+#define chSysDisable() { \
+ port_disable(); \
+ _dbg_check_disable(); \
+}
+
+/**
+ * @brief Raises the system interrupt priority mask to system level.
+ * @details The interrupt sources that should not be able to preempt the kernel
+ * are disabled, interrupt sources with higher priority are still
+ * enabled.
+ * @note Do not invoke this API from within a kernel lock.
+ * @note This API is no replacement for @p chSysLock(), the @p chSysLock()
+ * could do more than just disable the interrupts.
+ *
+ * @special
+ */
+#define chSysSuspend() { \
+ port_suspend(); \
+ _dbg_check_suspend(); \
+}
+
+/**
+ * @brief Lowers the system interrupt priority mask to user level.
+ * @details All the interrupt sources are enabled.
+ * @note Do not invoke this API from within a kernel lock.
+ * @note This API is no replacement for @p chSysUnlock(), the
+ * @p chSysUnlock() could do more than just enable the interrupts.
+ *
+ * @special
+ */
+#define chSysEnable() { \
+ _dbg_check_enable(); \
+ port_enable(); \
+}
+
+/**
+ * @brief Enters the kernel lock state.
+ *
+ * @special
+ */
+#define chSysLock() { \
+ port_lock(); \
+ _dbg_check_lock(); \
+}
+
+/**
+ * @brief Leaves the kernel lock state.
+ *
+ * @special
+ */
+#define chSysUnlock() { \
+ _dbg_check_unlock(); \
+ port_unlock(); \
+}
+
+/**
+ * @brief Enters the kernel lock state from within an interrupt handler.
+ * @note This API may do nothing on some architectures, it is required
+ * because on ports that support preemptable interrupt handlers
+ * it is required to raise the interrupt mask to the same level of
+ * the system mutual exclusion zone.<br>
+ * It is good practice to invoke this API before invoking any I-class
+ * syscall from an interrupt handler.
+ * @note This API must be invoked exclusively from interrupt handlers.
+ *
+ * @special
+ */
+#define chSysLockFromISR() { \
+ port_lock_from_isr(); \
+ _dbg_check_lock_from_isr(); \
+}
+
+/**
+ * @brief Leaves the kernel lock state from within an interrupt handler.
+ *
+ * @note This API may do nothing on some architectures, it is required
+ * because on ports that support preemptable interrupt handlers
+ * it is required to raise the interrupt mask to the same level of
+ * the system mutual exclusion zone.<br>
+ * It is good practice to invoke this API after invoking any I-class
+ * syscall from an interrupt handler.
+ * @note This API must be invoked exclusively from interrupt handlers.
+ *
+ * @special
+ */
+#define chSysUnlockFromISR() { \
+ _dbg_check_unlock_from_isr(); \
+ port_unlock_from_isr(); \
+}
+
+/**
+ * @brief Puts the current thread to sleep into the specified state.
+ *
+ * @param[in] newstate the new thread state or a semaphore pointer
+ * @return The wakeup message.
+ *
+ * @sclass
+ */
+#define chSchGoSleepS(newstate) chSchGoSleepTimeoutS(newstate, TIME_INFINITE)
+
+/**
+ * @brief Wakes up a thread.
+ *
+ * @param[in] ntp the thread to be made ready
+ * @param[in] msg the wakeup message
+ *
+ * @sclass
+ */
+#define chSchWakeupS(ntp, msg) do { \
+ chSchReadyI(ntp, msg); \
+ chSchRescheduleS(); \
+} while (false)
+
+/**
+ * @brief Evaluates if a reschedule is required.
+ *
+ * @retval true if there is a thread that must go in running state
+ * immediately.
+ * @retval false if preemption is not required.
+ *
+ * @iclass
+ */
+#define chSchIsRescRequiredI() ((bool)(nil.current != nil.next))
+
+/**
+ * @brief Returns a pointer to the current @p thread_t.
+ *
+ * @xclass
+ */
+#define chThdGetSelfX() nil.current
+
+/**
+ * @brief Returns the current thread priority.
+ * @note Can be invoked in any context.
+ *
+ * @return The current thread priority.
+ *
+ * @xclass
+ */
+#define chThdGetPriorityX(void) (tprio_t)(nil.current - &nil.threads[0])
+
+/**
+ * @brief Wakes up a thread waiting on a thread reference object.
+ * @note This function must reschedule, it can only be called from thread
+ * context.
+ *
+ * @param[in] trp a pointer to a thread reference object
+ * @param[in] msg the message code
+ *
+ * @sclass
+ */
+#define chThdResumeS(trp, msg) do { \
+ chThdResumeI(trp, msg); \
+ chSchRescheduleS(); \
+} while (false)
+
+/**
+ * @brief Delays the invoking thread for the specified number of seconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system clock.
+ * @note The maximum specified value is implementation dependent.
+ *
+ * @param[in] secs time in seconds, must be different from zero
+ *
+ * @api
+ */
+#define chThdSleepSeconds(secs) chThdSleep(TIME_S2I(secs))
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * milliseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system clock.
+ * @note The maximum specified value is implementation dependent.
+ *
+ * @param[in] msecs time in milliseconds, must be different from zero
+ *
+ * @api
+ */
+#define chThdSleepMilliseconds(msecs) chThdSleep(TIME_MS2I(msecs))
+
+/**
+ * @brief Delays the invoking thread for the specified number of
+ * microseconds.
+ * @note The specified time is rounded up to a value allowed by the real
+ * system clock.
+ * @note The maximum specified value is implementation dependent.
+ *
+ * @param[in] usecs time in microseconds, must be different from zero
+ *
+ * @api
+ */
+#define chThdSleepMicroseconds(usecs) chThdSleep(TIME_US2I(usecs))
+
+/**
+ * @brief Suspends the invoking thread for the specified time.
+ *
+ * @param[in] timeout the delay in system ticks
+ *
+ * @sclass
+ */
+#define chThdSleepS(timeout) \
+ (void) chSchGoSleepTimeoutS(NIL_STATE_SLEEPING, timeout)
+
+/**
+ * @brief Suspends the invoking thread until the system time arrives to the
+ * specified value.
+ *
+ * @param[in] abstime absolute system time
+ *
+ * @sclass
+ */
+#define chThdSleepUntilS(abstime) \
+ (void) chSchGoSleepTimeoutS(NIL_STATE_SLEEPING, \
+ chTimeDiffX(chVTGetSystemTimeX(), (abstime)))
+
+/**
+ * @brief Initializes a threads queue object.
+ *
+ * @param[out] tqp pointer to the threads queue object
+ *
+ * @init
+ */
+#define chThdQueueObjectInit(tqp) ((tqp)->cnt = (cnt_t)0)
+
+/**
+ * @brief Evaluates to @p true if the specified queue is empty.
+ *
+ * @param[out] tqp pointer to the threads queue object
+ * @return The queue status.
+ * @retval false if the queue is not empty.
+ * @retval true if the queue is empty.
+ *
+ * @iclass
+ */
+#define chThdQueueIsEmptyI(tqp) ((bool)(tqp->cnt >= (cnt_t)0))
+
+/**
+ * @brief Current system time.
+ * @details Returns the number of system ticks since the @p chSysInit()
+ * invocation.
+ * @note The counter can reach its maximum and then restart from zero.
+ * @note This function can be called from any context but its atomicity
+ * is not guaranteed on architectures whose word size is less than
+ * @p systime_t size.
+ *
+ * @return The system time in ticks.
+ *
+ * @xclass
+ */
+#if (CH_CFG_ST_TIMEDELTA == 0) || defined(__DOXYGEN__)
+#define chVTGetSystemTimeX() (nil.systime)
+#else
+#define chVTGetSystemTimeX() port_timer_get_time()
+#endif
+
+/**
+ * @brief Returns the elapsed time since the specified start time.
+ *
+ * @param[in] start start time
+ * @return The elapsed time.
+ *
+ * @xclass
+ */
+#define chVTTimeElapsedSinceX(start) \
+ chTimeDiffX((start), chVTGetSystemTimeX())
+
+/**
+ * @brief Checks if the current system time is within the specified time
+ * window.
+ * @note When start==end then the function returns always false because the
+ * time window has zero size.
+ *
+ * @param[in] start the start of the time window (inclusive)
+ * @param[in] end the end of the time window (non inclusive)
+ * @retval true current time within the specified time window.
+ * @retval false current time not within the specified time window.
+ *
+ * @xclass
+ */
+#define chVTIsSystemTimeWithinX(start, end) \
+ chTimeIsInRangeX(chVTGetSystemTimeX(), start, end)
+
+/**
+ * @brief Adds an interval to a system time returning a system time.
+ *
+ * @param[in] systime base system time
+ * @param[in] interval interval to be added
+ * @return The new system time.
+ *
+ * @xclass
+ */
+#define chTimeAddX(systime, interval) \
+ ((systime_t)(systime) + (systime_t)(interval))
+
+/**
+ * @brief Subtracts two system times returning an interval.
+ *
+ * @param[in] start first system time
+ * @param[in] end second system time
+ * @return The interval representing the time difference.
+ *
+ * @xclass
+ */
+#define chTimeDiffX(start, end) \
+ ((sysinterval_t)((systime_t)((systime_t)(end) - (systime_t)(start))))
+
+/**
+ * @brief Function parameters check.
+ * @details If the condition check fails then the kernel panics and halts.
+ * @note The condition is tested only if the @p CH_DBG_ENABLE_CHECKS switch
+ * is specified in @p chconf.h else the macro does nothing.
+ *
+ * @param[in] c the condition to be verified to be true
+ *
+ * @api
+ */
+#if !defined(chDbgCheck)
+#define chDbgCheck(c) do { \
+ /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \
+ if (CH_DBG_ENABLE_CHECKS != FALSE) { \
+ if (!(c)) { \
+ /*lint -restore*/ \
+ chSysHalt(__func__); \
+ } \
+ } \
+} while (false)
+#endif /* !defined(chDbgCheck) */
+
+/**
+ * @brief Condition assertion.
+ * @details If the condition check fails then the kernel panics with a
+ * message and halts.
+ * @note The condition is tested only if the @p CH_DBG_ENABLE_ASSERTS
+ * switch is specified in @p chconf.h else the macro does nothing.
+ * @note The remark string is not currently used except for putting a
+ * comment in the code about the assertion.
+ *
+ * @param[in] c the condition to be verified to be true
+ * @param[in] r a remark string
+ *
+ * @api
+ */
+#if !defined(chDbgAssert)
+#define chDbgAssert(c, r) do { \
+ /*lint -save -e506 -e774 [2.1, 14.3] Can be a constant by design.*/ \
+ if (CH_DBG_ENABLE_ASSERTS != FALSE) { \
+ if (!(c)) { \
+ /*lint -restore*/ \
+ chSysHalt(__func__); \
+ } \
+ } \
+} while (false)
+#endif /* !defined(chDbgAssert) */
+/** @} */
+
+/* Empty macros if the state checker is not enabled.*/
+#if CH_DBG_SYSTEM_STATE_CHECK == FALSE
+#define _dbg_enter_lock()
+#define _dbg_leave_lock()
+#define _dbg_check_disable()
+#define _dbg_check_suspend()
+#define _dbg_check_enable()
+#define _dbg_check_lock()
+#define _dbg_check_unlock()
+#define _dbg_check_lock_from_isr()
+#define _dbg_check_unlock_from_isr()
+#define _dbg_check_enter_isr()
+#define _dbg_check_leave_isr()
+#define chDbgCheckClassI()
+#define chDbgCheckClassS()
+#endif
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#if !defined(__DOXYGEN__)
+#if (CH_DBG_ENABLE_STACK_CHECK == TRUE) || defined(__DOXYGEN__)
+extern stkalign_t __main_thread_stack_base__, __main_thread_stack_end__;
+#endif
+extern nil_system_t nil;
+extern const thread_descriptor_t nil_thd_configs[];
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ thread_t *nil_find_thread(tstate_t state, void *p);
+ cnt_t nil_ready_all(void *p, cnt_t cnt, msg_t msg);
+ void chSysInit(void);
+ void chSysHalt(const char *reason);
+ void chSysTimerHandlerI(void);
+ void chSysUnconditionalLock(void);
+ void chSysUnconditionalUnlock(void);
+ syssts_t chSysGetStatusAndLockX(void);
+ bool chSysIsCounterWithinX(rtcnt_t cnt, rtcnt_t start, rtcnt_t end);
+ void chSysPolledDelayX(rtcnt_t cycles);
+ void chSysRestoreStatusX(syssts_t sts);
+ thread_t *chSchReadyI(thread_t *tp, msg_t msg);
+ bool chSchIsPreemptionRequired(void);
+ void chSchDoReschedule(void);
+ void chSchRescheduleS(void);
+ msg_t chSchGoSleepTimeoutS(tstate_t newstate, sysinterval_t timeout);
+ bool chTimeIsInRangeX(systime_t time, systime_t start, systime_t end);
+ thread_t *chThdCreateI(const thread_descriptor_t *tdp);
+ thread_t *chThdCreate(const thread_descriptor_t *tdp);
+ void chThdExit(msg_t msg);
+#if CH_CFG_USE_WAITEXIT == TRUE
+ msg_t chThdWait(thread_t *tp);
+#endif
+ msg_t chThdSuspendTimeoutS(thread_reference_t *trp, sysinterval_t timeout);
+ void chThdResumeI(thread_reference_t *trp, msg_t msg);
+ void chThdResume(thread_reference_t *trp, msg_t msg);
+ void chThdSleep(sysinterval_t timeout);
+ void chThdSleepUntil(systime_t abstime);
+ msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, sysinterval_t timeout);
+ void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg);
+ void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg);
+ void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg);
+#if CH_DBG_SYSTEM_STATE_CHECK == TRUE
+ void _dbg_check_disable(void);
+ void _dbg_check_suspend(void);
+ void _dbg_check_enable(void);
+ void _dbg_check_lock(void);
+ void _dbg_check_unlock(void);
+ void _dbg_check_lock_from_isr(void);
+ void _dbg_check_unlock_from_isr(void);
+ void _dbg_check_enter_isr(void);
+ void _dbg_check_leave_isr(void);
+ void chDbgCheckClassI(void);
+ void chDbgCheckClassS(void);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/* Optional modules.*/
+#include "chsem.h"
+#include "chevt.h"
+#include "chmsg.h"
+#include "chlib.h"
+
+#endif /* CH_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/nil/include/chevt.h b/ChibiOS_20.3.2/os/nil/include/chevt.h new file mode 100644 index 0000000..7d74461 --- /dev/null +++ b/ChibiOS_20.3.2/os/nil/include/chevt.h @@ -0,0 +1,301 @@ +/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file nil/include/chevt.h
+ * @brief Nil RTOS events header file.
+ *
+ * @addtogroup NIL_EVENTS
+ * @{
+ */
+
+#ifndef CHEVT_H
+#define CHEVT_H
+
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+typedef struct event_listener event_listener_t;
+
+/**
+ * @brief Event Listener structure.
+ */
+struct event_listener {
+ event_listener_t *next; /**< @brief Next Event Listener
+ registered on the event
+ source. */
+ thread_t *listener; /**< @brief Thread interested in the
+ event source. */
+ eventmask_t events; /**< @brief Events to be set in
+ the listening thread. */
+ eventflags_t flags; /**< @brief Flags added to the listener
+ by the event source. */
+ eventflags_t wflags; /**< @brief Flags that this listener
+ interested in. */
+};
+
+/**
+ * @brief Event Source structure.
+ */
+typedef struct event_source {
+ event_listener_t *next; /**< @brief First Event Listener
+ registered on the Event
+ Source. */
+} event_source_t;
+
+/**
+ * @brief Event Handler callback function.
+ */
+typedef void (*evhandler_t)(eventid_t id);
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @brief All events allowed mask.
+ */
+#define ALL_EVENTS ((eventmask_t)-1)
+
+/**
+ * @brief Returns an event mask from an event identifier.
+ */
+#define EVENT_MASK(eid) ((eventmask_t)1 << (eventmask_t)(eid))
+
+/**
+ * @brief Data part of a static event source initializer.
+ * @details This macro should be used when statically initializing an event
+ * source that is part of a bigger structure.
+ * @param name the name of the event source variable
+ */
+#define _EVENTSOURCE_DATA(name) {(event_listener_t *)(&name)}
+
+/**
+ * @brief Static event source initializer.
+ * @details Statically initialized event sources require no explicit
+ * initialization using @p chEvtInit().
+ *
+ * @param name the name of the event source variable
+ */
+#define EVENTSOURCE_DECL(name) event_source_t name = _EVENTSOURCE_DATA(name)
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Initializes an Event Source.
+ * @note This function can be invoked before the kernel is initialized
+ * because it just prepares a @p event_source_t structure.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ *
+ * @init
+ */
+#define chEvtObjectInit(esp) do { \
+ (esp)->next = (event_listener_t *)(esp); \
+} while (0)
+
+/**
+ * @brief Registers an Event Listener on an Event Source.
+ * @details Once a thread has registered as listener on an event source it
+ * will be notified of all events broadcasted there.
+ * @note Multiple Event Listeners can specify the same bits to be ORed to
+ * different threads.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @param[out] elp pointer to the @p event_listener_t structure
+ * @param[in] events the mask of events to be ORed to the thread when
+ * the event source is broadcasted
+ *
+ * @api
+ */
+#define chEvtRegisterMask(esp, elp, events) \
+ chEvtRegisterMaskWithFlags(esp, elp, events, (eventflags_t)-1)
+
+/**
+ * @brief Registers an Event Listener on an Event Source.
+ * @note Multiple Event Listeners can use the same event identifier, the
+ * listener will share the callback function.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @param[out] elp pointer to the @p event_listener_t structure
+ * @param[in] event numeric identifier assigned to the Event Listener.
+ * The value must range between zero and the size, in bit,
+ * of the @p eventmask_t type minus one.
+ *
+ * @api
+ */
+#define chEvtRegister(esp, elp, event) \
+ chEvtRegisterMask(esp, elp, EVENT_MASK(event))
+
+/**
+ * @brief Verifies if there is at least one @p event_listener_t registered.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ * @return The event source status.
+ *
+ * @iclass
+ */
+#define chEvtIsListeningI(esp) (bool)((esp) != (event_source_t *)(esp)->next)
+
+/**
+ * @brief Signals all the Event Listeners registered on the specified Event
+ * Source.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ *
+ * @api
+ */
+#define chEvtBroadcast(esp) chEvtBroadcastFlags(esp, (eventflags_t)0)
+
+/**
+ * @brief Signals all the Event Listeners registered on the specified Event
+ * Source.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ *
+ * @param[in] esp pointer to the @p event_source_t structure
+ *
+ * @iclass
+ */
+#define chEvtBroadcastI(esp) chEvtBroadcastFlagsI(esp, (eventflags_t)0)
+
+/**
+ * @brief Adds (OR) a set of events to the current thread, this is
+ * @b much faster than using @p chEvtBroadcast() or @p chEvtSignal().
+ *
+ * @param[in] events the events to be added
+ * @return The mask of currently pending events.
+ *
+ * @iclass
+ */
+#define chEvtAddEventsI(events) (nil.current->epmask |= events)
+
+/**
+ * @brief Returns the events mask.
+ * @details The pending events mask is returned but not altered in any way.
+ *
+ * @return The pending events mask.
+ *
+ * @api
+ */
+#define chEvtGetEventsX(void) (nil.current->epmask)
+
+/**
+ * @brief Waits for exactly one of the specified events.
+ * @details The function waits for one event among those specified in
+ * @p events to become pending then the event is cleared and returned.
+ * @note One and only one event is served in the function, the one with the
+ * lowest event id. The function is meant to be invoked into a loop
+ * in order to serve all the pending events.<br>
+ * This means that Event Listeners with a lower event identifier have
+ * an higher priority.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @return The mask of the lowest event id served and cleared.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+#define chEvtWaitOne(events) chEvtWaitOneTimeout(events, TIME_INFINITE)
+
+/**
+ * @brief Waits for any of the specified events.
+ * @details The function waits for any event among those specified in
+ * @p mask to become pending then the events are cleared and
+ * returned.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+#define chEvtWaitAny(events) chEvtWaitAnyTimeout(events, TIME_INFINITE)
+
+/**
+ * @brief Waits for all the specified events.
+ * @details The function waits for all the events specified in @p mask to
+ * become pending then the events are cleared and returned.
+ *
+ * @param[in] events events that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+#define chEvtWaitAll(events) chEvtWaitAllTimeout(events, TIME_INFINITE)
+
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chEvtRegisterMaskWithFlags(event_source_t *esp,
+ event_listener_t *elp,
+ eventmask_t events,
+ eventflags_t wflags);
+ void chEvtUnregister(event_source_t *esp, event_listener_t *elp);
+ eventmask_t chEvtGetAndClearEventsI(eventmask_t events);
+ eventmask_t chEvtGetAndClearEvents(eventmask_t events);
+ eventmask_t chEvtAddEvents(eventmask_t events);
+ eventflags_t chEvtGetAndClearFlags(event_listener_t *elp);
+ eventflags_t chEvtGetAndClearFlagsI(event_listener_t *elp);
+ void chEvtSignal(thread_t *tp, eventmask_t events);
+ void chEvtSignalI(thread_t *tp, eventmask_t events);
+ void chEvtBroadcastFlags(event_source_t *esp, eventflags_t flags);
+ void chEvtBroadcastFlagsI(event_source_t *esp, eventflags_t flags);
+ void chEvtDispatch(const evhandler_t *handlers, eventmask_t events);
+ eventmask_t chEvtWaitOneTimeout(eventmask_t events, sysinterval_t timeout);
+ eventmask_t chEvtWaitAnyTimeout(eventmask_t mask, sysinterval_t timeout);
+ eventmask_t chEvtWaitAllTimeout(eventmask_t mask, sysinterval_t timeout);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CH_CFG_USE_EVENTS == TRUE */
+
+#endif /* CHEVT_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/nil/include/chmsg.h b/ChibiOS_20.3.2/os/nil/include/chmsg.h new file mode 100644 index 0000000..abe1de7 --- /dev/null +++ b/ChibiOS_20.3.2/os/nil/include/chmsg.h @@ -0,0 +1,123 @@ +/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file nil/include/chmsg.h
+ * @brief Nil RTOS synchronous messages header file.
+ *
+ * @addtogroup NIL_MESSAGES
+ * @{
+ */
+
+#ifndef CHMSG_H
+#define CHMSG_H
+
+#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Suspends the thread and waits for an incoming message.
+ * @post After receiving a message the function @p chMsgGet() must be
+ * called in order to retrieve the message and then @p chMsgRelease()
+ * must be invoked in order to acknowledge the reception and send
+ * the answer.
+ * @note If the message is a pointer then you can assume that the data
+ * pointed by the message is stable until you invoke @p chMsgRelease()
+ * because the sending thread is suspended until then.
+ * @note The reference counter of the sender thread is not increased, the
+ * returned pointer is a temporary reference.
+ *
+ * @return A pointer to the thread carrying the message.
+ *
+ * @sclass
+ */
+#define chMsgWaitS() chMsgWaitTimeoutS(TIME_INFINITE)
+
+/**
+ * @brief Returns the message carried by the specified thread.
+ * @pre This function must be invoked immediately after exiting a call
+ * to @p chMsgWait().
+ *
+ * @param[in] tp pointer to the thread
+ * @return The message carried by the sender.
+ *
+ * @api
+ */
+#define chMsgGet(tp) ((tp)->sntmsg)
+
+/**
+ * @brief Releases the thread waiting on top of the messages queue.
+ * @pre Invoke this function only after a message has been received
+ * using @p chMsgWait().
+ *
+ * @param[in] tp pointer to the thread
+ * @param[in] msg message to be returned to the sender
+ *
+ * @sclass
+ */
+#define chMsgReleaseS(tp, msg) do { \
+ (void) chSchReadyI(tp, msg); \
+ chSchRescheduleS(); \
+ } while (false)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ msg_t chMsgSend(thread_t *tp, msg_t msg);
+ thread_t *chMsgWait(void);
+ thread_t *chMsgWaitTimeout(sysinterval_t timeout);
+ thread_t *chMsgWaitTimeoutS(sysinterval_t timeout);
+ void chMsgRelease(thread_t *tp, msg_t msg);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CH_CFG_USE_MESSAGES == TRUE */
+
+#endif /* CHMSG_H */
+
+/** @} */
diff --git a/ChibiOS_20.3.2/os/nil/include/chsem.h b/ChibiOS_20.3.2/os/nil/include/chsem.h new file mode 100644 index 0000000..7caad00 --- /dev/null +++ b/ChibiOS_20.3.2/os/nil/include/chsem.h @@ -0,0 +1,180 @@ +/*
+ ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio.
+
+ This file is part of ChibiOS.
+
+ ChibiOS is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ ChibiOS is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file nil/include/chsem.h
+ * @brief Nil RTOS semaphores header file.
+ *
+ * @addtogroup NIL_SEMAPHORES
+ * @{
+ */
+
+#ifndef CHSEM_H
+#define CHSEM_H
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module constants. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/**
+ * @name Macro Functions
+ * @{
+ */
+/**
+ * @brief Initializes a semaphore with the specified counter value.
+ *
+ * @param[out] sp pointer to a @p semaphore_t structure
+ * @param[in] n initial value of the semaphore counter. Must be
+ * non-negative.
+ *
+ * @init
+ */
+#define chSemObjectInit(sp, n) ((sp)->cnt = (n))
+
+/**
+ * @brief Performs a reset operation on the semaphore.
+ * @post After invoking this function all the threads waiting on the
+ * semaphore, if any, are released and the semaphore counter is set
+ * to the specified, non negative, value.
+ * @note This function implicitly sends @p MSG_RESET as message.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] n the new value of the semaphore counter. The value must
+ * be non-negative.
+ *
+ * @api
+ */
+#define chSemReset(sp, n) chSemResetWithMessage(sp, n, MSG_RESET)
+
+/**
+ * @brief Performs a reset operation on the semaphore.
+ * @post After invoking this function all the threads waiting on the
+ * semaphore, if any, are released and the semaphore counter is set
+ * to the specified, non negative, value.
+ * @post This function does not reschedule so a call to a rescheduling
+ * function must be performed before unlocking the kernel. Note that
+ * interrupt handlers always reschedule on exit so an explicit
+ * reschedule must not be performed in ISRs.
+ * @note This function implicitly sends @p MSG_RESET as message.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] n the new value of the semaphore counter. The value must
+ * be non-negative.
+ *
+ * @iclass
+ */
+#define chSemResetI(sp, n) chSemResetWithMessageI(sp, n, MSG_RESET)
+
+/**
+ * @brief Performs a wait operation on a semaphore.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval CH_MSG_OK if the thread has not stopped on the semaphore or the
+ * semaphore has been signaled.
+ * @retval CH_MSG_RST if the semaphore has been reset using @p chSemReset().
+ *
+ * @api
+ */
+#define chSemWait(sp) chSemWaitTimeout(sp, TIME_INFINITE)
+
+/**
+ * @brief Performs a wait operation on a semaphore.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval CH_MSG_OK if the thread has not stopped on the semaphore or the
+ * semaphore has been signaled.
+ * @retval CH_MSG_RST if the semaphore has been reset using @p chSemReset().
+ *
+ * @sclass
+ */
+#define chSemWaitS(sp) chSemWaitTimeoutS(sp, TIME_INFINITE)
+
+/**
+ * @brief Decreases the semaphore counter.
+ * @details This macro can be used when the counter is known to be positive.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ *
+ * @iclass
+ */
+#define chSemFastWaitI(sp) ((sp)->cnt--)
+
+/**
+ * @brief Increases the semaphore counter.
+ * @details This macro can be used when the counter is known to be not
+ * negative.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ *
+ * @iclass
+ */
+#define chSemFastSignalI(sp) ((sp)->cnt++)
+
+/**
+ * @brief Returns the semaphore counter current value.
+ *
+ * @iclass
+ */
+#define chSemGetCounterI(sp) ((sp)->cnt)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ msg_t chSemWaitTimeout(semaphore_t *sp, sysinterval_t timeout);
+ msg_t chSemWaitTimeoutS(semaphore_t *sp, sysinterval_t timeout);
+ void chSemSignal(semaphore_t *sp);
+ void chSemSignalI(semaphore_t *sp);
+ void chSemResetWithMessage(semaphore_t *sp, cnt_t n, msg_t msg);
+ void chSemResetWithMessageI(semaphore_t *sp, cnt_t n, msg_t msg);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
+
+#endif /* CHSEM_H */
+
+/** @} */
|