diff --git a/demos/STM32/NIL-STM32F303-DISCOVERY/Makefile b/demos/STM32/NIL-STM32F303-DISCOVERY/Makefile
index 631095137..bca2377d7 100644
--- a/demos/STM32/NIL-STM32F303-DISCOVERY/Makefile
+++ b/demos/STM32/NIL-STM32F303-DISCOVERY/Makefile
@@ -5,7 +5,7 @@
# Compiler options here.
ifeq ($(USE_OPT),)
- USE_OPT = -O0 -ggdb -fomit-frame-pointer -falign-functions=16
+ USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
endif
# C specific options here (added to USE_OPT).
diff --git a/demos/STM32/NIL-STM32L476-DISCOVERY/cfg/chconf.h b/demos/STM32/NIL-STM32L476-DISCOVERY/cfg/chconf.h
index e0dca22c5..bd2e50a45 100644
--- a/demos/STM32/NIL-STM32L476-DISCOVERY/cfg/chconf.h
+++ b/demos/STM32/NIL-STM32L476-DISCOVERY/cfg/chconf.h
@@ -130,6 +130,15 @@
*/
#define CH_CFG_USE_EVENTS TRUE
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MESSAGES TRUE
+
/**
* @brief Mailboxes APIs.
* @details If enabled then the asynchronous messages (mailboxes) APIs are
diff --git a/os/nil/include/ch.h b/os/nil/include/ch.h
index 75a89766f..fb98aedad 100644
--- a/os/nil/include/ch.h
+++ b/os/nil/include/ch.h
@@ -31,8 +31,6 @@
#define CH_H
#include "chtypes.h"
-#include "chconf.h"
-#include "chlicense.h"
/*===========================================================================*/
/* Module constants. */
@@ -147,7 +145,11 @@
#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_FINAL (tstate_t)8 /**< @brief Thread terminated. */
+#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)
@@ -157,343 +159,115 @@
#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", "FINAL"
-/** @} */
-
-/**
- * @name Events related 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 << (eid)))
+ "WTOREVT", "WTANDEVT", "SNDMSGQ", "SNDMSG", "WTMSG", "FINAL"
/** @} */
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
-/*-*
- * @brief Maximum number of user threads in the application.
- * @note This number is not inclusive of the idle thread which is
- * implicitly handled.
- * @note Set this value to be exactly equal to the number of threads you
- * will use or you would be wasting RAM and cycles.
- * @note This values also defines the number of available priorities
- * (0..CH_CFG_MAX_THREADS-1).
- */
-#if !defined(CH_CFG_MAX_THREADS) || defined(__DOXYGEN__)
-#define CH_CFG_MAX_THREADS 2
-#endif
-
-/*-*
- * @brief Auto starts threads when @p chSysInit() is invoked.
- */
-#if !defined(CH_CFG_AUTOSTART_THREADS) || defined(__DOXYGEN__)
-#define CH_CFG_AUTOSTART_THREADS TRUE
-#endif
-
-/*-*
- * @brief System time counter resolution.
- * @note Allowed values are 16 or 32 bits.
- */
-#if !defined(CH_CFG_ST_RESOLUTION) || defined(__DOXYGEN__)
-#define CH_CFG_ST_RESOLUTION 32
-#endif
-
-/*-*
- * @brief System tick frequency.
- * @note This value together with the @p CH_CFG_ST_RESOLUTION
- * option defines the maximum amount of time allowed for
- * timeouts.
- */
-#if !defined(CH_CFG_ST_FREQUENCY) || defined(__DOXYGEN__)
-#define CH_CFG_ST_FREQUENCY 100
-#endif
-
-/*-*
- * @brief Time delta constant for the tick-less mode.
- * @note If this value is zero then the system uses the classic
- * periodic tick. This value represents the minimum number
- * of ticks that is safe to specify in a timeout directive.
- * The value one is not valid, timeouts are rounded up to
- * this value.
- */
-#if !defined(CH_CFG_ST_TIMEDELTA) || defined(__DOXYGEN__)
-#define CH_CFG_ST_TIMEDELTA 0
-#endif
-
-/*-*
- * @brief Threads synchronization APIs.
- * @details If enabled then the @p chThdWait() function is included in
- * the kernel.
- *
- * @note The default is @p TRUE.
- */
-#if !defined(CH_CFG_USE_WAITEXIT)
-#define CH_CFG_USE_WAITEXIT TRUE
-#endif
-
-/*-*
- * @brief Semaphores APIs.
- * @details If enabled then the Semaphores APIs are included in the kernel.
- *
- * @note The default is @p TRUE.
- */
-#if !defined(CH_CFG_USE_SEMAPHORES) || defined(__DOXYGEN__)
-#define CH_CFG_USE_SEMAPHORES TRUE
-#endif
-
-/*-*
- * @brief Mutexes APIs.
- * @details If enabled then the mutexes APIs are included in the kernel.
- *
- * @note Feature not currently implemented.
- * @note The default is @p FALSE.
- */
-#if !defined(CH_CFG_USE_MUTEXES) || defined(__DOXYGEN__)
-#define CH_CFG_USE_MUTEXES FALSE
-#endif
-
-/*-*
- * @brief Events Flags APIs.
- * @details If enabled then the event flags APIs are included in the kernel.
- *
- * @note The default is @p TRUE.
- */
-#if !defined(CH_CFG_USE_EVENTS) || defined(__DOXYGEN__)
-#define CH_CFG_USE_EVENTS TRUE
-#endif
-
-/*-*
- * @brief Mailboxes APIs.
- * @details If enabled then the asynchronous messages (mailboxes) APIs are
- * included in the kernel.
- *
- * @note The default is @p TRUE.
- * @note Requires @p CH_CFG_USE_SEMAPHORES.
- */
-#if !defined(CH_CFG_USE_MAILBOXES) || defined(__DOXYGEN__)
-#define CH_CFG_USE_MAILBOXES TRUE
-#endif
-
-/*-*
- * @brief Core Memory Manager APIs.
- * @details If enabled then the core memory manager APIs are included
- * in the kernel.
- *
- * @note The default is @p TRUE.
- */
-#if !defined(CH_CFG_USE_MEMCORE) || defined(__DOXYGEN__)
-#define CH_CFG_USE_MEMCORE TRUE
-#endif
-
-/*-*
- * @brief Heap Allocator APIs.
- * @details If enabled then the memory heap allocator APIs are included
- * in the kernel.
- *
- * @note The default is @p TRUE.
- */
-#if !defined(CH_CFG_USE_HEAP) || defined(__DOXYGEN__)
-#define CH_CFG_USE_HEAP TRUE
-#endif
-
-/*-*
- * @brief Memory Pools Allocator APIs.
- * @details If enabled then the memory pools allocator APIs are included
- * in the kernel.
- *
- * @note The default is @p TRUE.
- */
-#if !defined(CH_CFG_USE_MEMPOOLS) || defined(__DOXYGEN__)
-#define CH_CFG_USE_MEMPOOLS TRUE
-#endif
-
-/*-*
- * @brief Objects Factory APIs.
- * @details If enabled then the objects factory APIs are included in the
- * kernel.
- *
- * @note The default is @p FALSE.
- */
-#if !defined(CH_CFG_USE_FACTORY) || defined(__DOXYGEN__)
-#define CH_CFG_USE_FACTORY TRUE
-#endif
-
-/*-*
- * @brief Maximum length for object names.
- * @details If the specified length is zero then the name is stored by
- * pointer but this could have unintended side effects.
- */
-#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH) || defined(__DOXYGEN__)
-#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8
-#endif
-
-/*-*
- * @brief Enables the registry of generic objects.
- */
-#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY) || defined(__DOXYGEN__)
-#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
-#endif
-
-/*-*
- * @brief Enables factory for generic buffers.
- */
-#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS) || defined(__DOXYGEN__)
-#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
-#endif
-
-/*-*
- * @brief Enables factory for semaphores.
- */
-#if !defined(CH_CFG_FACTORY_SEMAPHORES) || defined(__DOXYGEN__)
-#define CH_CFG_FACTORY_SEMAPHORES TRUE
-#endif
-
-/*-*
- * @brief Enables factory for mailboxes.
- */
-#if !defined(CH_CFG_FACTORY_MAILBOXES) || defined(__DOXYGEN__)
-#define CH_CFG_FACTORY_MAILBOXES TRUE
-#endif
-
-/*-*
- * @brief Enables factory for objects FIFOs.
- */
-#if !defined(CH_CFG_FACTORY_OBJ_FIFOS) || defined(__DOXYGEN__)
-#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
-#endif
-
-/*-*
- * @brief Pipes APIs.
- * @details If enabled then the pipes APIs are included
- * in the kernel.
- *
- * @note The default is @p TRUE.
- */
-#if !defined(CH_CFG_USE_PIPES) || defined(__DOXYGEN__)
-#define CH_CFG_USE_PIPES TRUE
-#endif
-
-/*-*
- * @brief Debug option, kernel statistics.
- *
- * @note Feature not currently implemented.
- * @note The default is @p FALSE.
- */
-#if !defined(CH_DBG_STATISTICS) || defined(__DOXYGEN__)
-#define CH_DBG_STATISTICS FALSE
-#endif
-
-/*-*
- * @brief Debug option, system state check.
- * @note This is a planned feature, not yet implemented.
- *
- * @note The default is @p FALSE.
- */
-#if !defined(CH_DBG_SYSTEM_STATE_CHECK) || defined(__DOXYGEN__)
-#define CH_DBG_SYSTEM_STATE_CHECK FALSE
-#endif
-
-/*-*
- * @brief Debug option, parameters checks.
- *
- * @note The default is @p FALSE.
- */
-#if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__)
-#define CH_DBG_ENABLE_CHECKS FALSE
-#endif
-
-/*-*
- * @brief System assertions.
- *
- * @note The default is @p FALSE.
- */
-#if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
-#define CH_DBG_ENABLE_ASSERTS FALSE
-#endif
-
-/*-*
- * @brief Stack check.
- *
- * @note The default is @p FALSE.
- */
-#if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__)
-#define CH_DBG_ENABLE_STACK_CHECK FALSE
-#endif
-
-/*-*
- * @brief System initialization hook.
- */
-#if !defined(CH_CFG_SYSTEM_INIT_HOOK) || defined(__DOXYGEN__)
-#define CH_CFG_SYSTEM_INIT_HOOK() {}
-#endif
-
-/*-*
- * @brief Threads descriptor structure extension.
- * @details User fields added to the end of the @p thread_t structure.
- */
-#if !defined(CH_CFG_THREAD_EXT_FIELDS) || defined(__DOXYGEN__)
-#define CH_CFG_THREAD_EXT_FIELDS
-#endif
-
-/*-*
- * @brief Threads initialization hook.
- */
-#if !defined(CH_CFG_THREAD_EXT_INIT_HOOK) || defined(__DOXYGEN__)
-#define CH_CFG_THREAD_EXT_INIT_HOOK(tp) {}
-#endif
-
-/*-*
- * @brief Threads finalization hook.
- * @details User finalization code added to the @p chThdExit() API.
- */
-#if !defined(CH_CFG_THREAD_EXIT_HOOK) || defined(__DOXYGEN__)
-#define CH_CFG_THREAD_EXIT_HOOK(tp) {}
-#endif
-
-/*-*
- * @brief Idle thread enter hook.
- * @note This hook is invoked within a critical zone, no OS functions
- * should be invoked from here.
- * @note This macro can be used to activate a power saving mode.
- */
-#if !defined(CH_CFG_IDLE_ENTER_HOOK) || defined(__DOXYGEN__)
-#define CH_CFG_IDLE_ENTER_HOOK() {}
-#endif
-
-/*-*
- * @brief Idle thread leave hook.
- * @note This hook is invoked within a critical zone, no OS functions
- * should be invoked from here.
- * @note This macro can be used to deactivate a power saving mode.
- */
-#if !defined(CH_CFG_IDLE_LEAVE_HOOK) || defined(__DOXYGEN__)
-#define CH_CFG_IDLE_LEAVE_HOOK() {}
-#endif
-
-/*-*
- * @brief System halt hook.
- */
-#if !defined(CH_CFG_SYSTEM_HALT_HOOK) || defined(__DOXYGEN__)
-#define CH_CFG_SYSTEM_HALT_HOOK(reason) {}
-#endif
+#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"
@@ -707,6 +481,9 @@ struct nil_thread {
#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
@@ -1355,75 +1132,6 @@ struct nil_system {
*/
#define chThdQueueIsEmptyI(tqp) ((bool)(tqp->cnt >= (cnt_t)0))
-#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
-/**
- * @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 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)
-#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
-
/**
* @brief Current system time.
* @details Returns the number of system ticks since the @p chSysInit()
@@ -1576,6 +1284,8 @@ extern const thread_config_t nil_thd_configs[];
#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);
@@ -1605,20 +1315,6 @@ extern "C" {
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_CFG_USE_SEMAPHORES == TRUE
- 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 chSemReset(semaphore_t *sp, cnt_t n);
- void chSemResetI(semaphore_t *sp, cnt_t n);
-#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
-#if CH_CFG_USE_EVENTS == TRUE
- void chEvtSignal(thread_t *tp, eventmask_t mask);
- void chEvtSignalI(thread_t *tp, eventmask_t mask);
- eventmask_t chEvtWaitAnyTimeout(eventmask_t mask, sysinterval_t timeout);
- eventmask_t chEvtWaitAllTimeout(eventmask_t mask, sysinterval_t timeout);
-#endif
#if CH_DBG_SYSTEM_STATE_CHECK == TRUE
void _dbg_check_disable(void);
void _dbg_check_suspend(void);
@@ -1636,7 +1332,10 @@ extern "C" {
}
#endif
-/* OSLIB.*/
+/* Optional modules.*/
+#include "chsem.h"
+#include "chevt.h"
+#include "chmsg.h"
#include "chlib.h"
#endif /* CH_H */
diff --git a/os/nil/include/chevt.h b/os/nil/include/chevt.h
new file mode 100644
index 000000000..10309c462
--- /dev/null
+++ b/os/nil/include/chevt.h
@@ -0,0 +1,87 @@
+/*
+ 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 .
+*/
+
+/**
+ * @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. */
+/*===========================================================================*/
+
+/**
+ * @name Events related 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 << (eid)))
+/** @} */
+
+/*===========================================================================*/
+/* Module pre-compile time settings. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Derived constants and error checks. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module data structures and types. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module macros. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void chEvtSignal(thread_t *tp, eventmask_t mask);
+ void chEvtSignalI(thread_t *tp, eventmask_t mask);
+ 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/os/nil/include/chmsg.h b/os/nil/include/chmsg.h
new file mode 100644
index 000000000..b734645ca
--- /dev/null
+++ b/os/nil/include/chmsg.h
@@ -0,0 +1,103 @@
+/*
+ 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 .
+*/
+
+/**
+ * @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 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 { \
+ chSchReadyI(tp, msg); \
+ chSchRescheduleS(); \
+ } while (0)
+/** @} */
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ msg_t chMsgSend(thread_t *tp, msg_t msg);
+ thread_t * chMsgWait(void);
+ void chMsgRelease(thread_t *tp, msg_t msg);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CH_CFG_USE_MESSAGES == TRUE */
+
+#endif /* CHMSG_H */
+
+/** @} */
diff --git a/os/nil/include/chsem.h b/os/nil/include/chsem.h
new file mode 100644
index 000000000..84da92684
--- /dev/null
+++ b/os/nil/include/chsem.h
@@ -0,0 +1,146 @@
+/*
+ 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 .
+*/
+
+/**
+ * @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 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 chSemReset(semaphore_t *sp, cnt_t n);
+ void chSemResetI(semaphore_t *sp, cnt_t n);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
+
+#endif /* CHSEM_H */
+
+/** @} */
diff --git a/os/nil/nil.mk b/os/nil/nil.mk
index 69238e91e..b4cc92b1a 100644
--- a/os/nil/nil.mk
+++ b/os/nil/nil.mk
@@ -14,8 +14,21 @@ endif
CHCONF := $(strip $(shell cat $(CHCONFDIR)/chconf.h | egrep -e "\#define"))
KERNSRC := ${CHIBIOS}/os/nil/src/ch.c
+ifneq ($(findstring CH_CFG_USE_EVENTS TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/rt/src/chevt.c
+endif
+ifneq ($(findstring CH_CFG_USE_MESSAGES TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/rt/src/chmsg.c
+endif
+ifneq ($(findstring CH_CFG_USE_SEMAPHORES TRUE,$(CHCONF)),)
+KERNSRC += $(CHIBIOS)/os/rt/src/chsem.c
+endif
+
else
-KERNSRC := ${CHIBIOS}/os/nil/src/ch.c
+KERNSRC := ${CHIBIOS}/os/nil/src/ch.c \
+ ${CHIBIOS}/os/nil/src/chevt.c
+ ${CHIBIOS}/os/nil/src/chmsg.c \
+ ${CHIBIOS}/os/nil/src/chsem.c
endif
# Required include directories
diff --git a/os/nil/src/ch.c b/os/nil/src/ch.c
index 233a3f4ae..1d26e9565 100644
--- a/os/nil/src/ch.c
+++ b/os/nil/src/ch.c
@@ -48,27 +48,36 @@ nil_system_t nil;
/* Module local functions. */
/*===========================================================================*/
+/*===========================================================================*/
+/* Module interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
/**
* @brief Retrieves the highest priority thread in the specified state and
* associated to the specified object.
- * @note The search is unbounded, the thread is assumed to exist.
*
* @param[in] state thread state
* @param[in] p object pointer
+ * @return The pointer to the found thread.
+ * @retval NULL if the thread is not found.
+ *
+ * @notapi
*/
-static thread_t *nil_find_thread(tstate_t state, void * p) {
+thread_t *nil_find_thread(tstate_t state, void *p) {
thread_t *tp = nil.threads;
- while (true) {
+ while (tp < &nil.threads[CH_CFG_MAX_THREADS]) {
/* Is this thread matching?*/
if ((tp->state == state) && (tp->u1.p == p)) {
return tp;
}
tp++;
-
- chDbgAssert(tp < &nil.threads[CH_CFG_MAX_THREADS],
- "pointer out of range");
}
+ return NULL;
}
/**
@@ -80,9 +89,9 @@ static thread_t *nil_find_thread(tstate_t state, void * p) {
* non negative numbers are ignored
* @param[in] msg the wakeup message
*
- * @iclass
+ * @notapi
*/
-static cnt_t nil_ready_all(void * p, cnt_t cnt, msg_t msg) {
+cnt_t nil_ready_all(void *p, cnt_t cnt, msg_t msg) {
thread_t *tp = nil.threads;;
while (cnt < (cnt_t)0) {
@@ -101,14 +110,6 @@ static cnt_t nil_ready_all(void * p, cnt_t cnt, msg_t msg) {
return cnt;
}
-/*===========================================================================*/
-/* Module interrupt handlers. */
-/*===========================================================================*/
-
-/*===========================================================================*/
-/* Module exported functions. */
-/*===========================================================================*/
-
#if (CH_DBG_SYSTEM_STATE_CHECK == TRUE) || defined(__DOXYGEN__)
/**
* @brief Guard code for @p chSysDisable().
@@ -1015,6 +1016,9 @@ void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg) {
tqp->cnt++;
tp = nil_find_thread(NIL_STATE_WTQUEUE, (void *)tqp);
+
+ chDbgAssert(tp != NULL, "thread not found");
+
(void) chSchReadyI(tp, msg);
}
@@ -1053,290 +1057,4 @@ void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg) {
tqp->cnt = nil_ready_all((void *)tqp, tqp->cnt, msg);
}
-#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
-/**
- * @brief Performs a wait operation on a semaphore with timeout specification.
- *
- * @param[in] sp pointer to a @p semaphore_t structure
- * @param[in] timeout the number of ticks before the operation timeouts,
- * the following special values are allowed:
- * - @a TIME_IMMEDIATE immediate timeout.
- * - @a TIME_INFINITE no timeout.
- * .
- * @return A message specifying how the invoking thread has been
- * released from the semaphore.
- * @retval NIL_MSG_OK if the thread has not stopped on the semaphore or the
- * semaphore has been signaled.
- * @retval NIL_MSG_RST if the semaphore has been reset using @p chSemReset().
- * @retval NIL_MSG_TMO if the semaphore has not been signaled or reset within
- * the specified timeout.
- *
- * @api
- */
-msg_t chSemWaitTimeout(semaphore_t *sp, sysinterval_t timeout) {
- msg_t msg;
-
- chSysLock();
- msg = chSemWaitTimeoutS(sp, timeout);
- chSysUnlock();
-
- return msg;
-}
-
-/**
- * @brief Performs a wait operation on a semaphore with timeout specification.
- *
- * @param[in] sp pointer to a @p semaphore_t structure
- * @param[in] timeout the number of ticks before the operation timeouts,
- * the following special values are allowed:
- * - @a TIME_IMMEDIATE immediate timeout.
- * - @a TIME_INFINITE no timeout.
- * .
- * @return A message specifying how the invoking thread has been
- * released from the semaphore.
- * @retval NIL_MSG_OK if the thread has not stopped on the semaphore or the
- * semaphore has been signaled.
- * @retval NIL_MSG_RST if the semaphore has been reset using @p chSemReset().
- * @retval NIL_MSG_TMO if the semaphore has not been signaled or reset within
- * the specified timeout.
- *
- * @sclass
- */
-msg_t chSemWaitTimeoutS(semaphore_t *sp, sysinterval_t timeout) {
-
- chDbgCheckClassS();
- chDbgCheck(sp != NULL);
-
- /* Note, the semaphore counter is a volatile variable so accesses are
- manually optimized.*/
- cnt_t cnt = sp->cnt;
- if (cnt <= (cnt_t)0) {
- if (TIME_IMMEDIATE == timeout) {
-
- return MSG_TIMEOUT;
- }
- sp->cnt = cnt - (cnt_t)1;
- nil.current->u1.semp = sp;
-
- return chSchGoSleepTimeoutS(NIL_STATE_WTQUEUE, timeout);
- }
- sp->cnt = cnt - (cnt_t)1;
-
- return MSG_OK;
-}
-
-/**
- * @brief Performs a signal operation on a semaphore.
- *
- * @param[in] sp pointer to a @p semaphore_t structure
- *
- * @api
- */
-void chSemSignal(semaphore_t *sp) {
-
- chSysLock();
- chSemSignalI(sp);
- chSchRescheduleS();
- chSysUnlock();
-}
-
-/**
- * @brief Performs a signal operation on a semaphore.
- * @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] sp pointer to a @p semaphore_t structure
- *
- * @iclass
- */
-void chSemSignalI(semaphore_t *sp) {
-
- chDbgCheckClassI();
- chDbgCheck(sp != NULL);
-
- if (++sp->cnt <= (cnt_t)0) {
- thread_t *tp = nil_find_thread(NIL_STATE_WTQUEUE, (void *)sp);
- (void) chSchReadyI(tp, MSG_OK);
- }
-}
-
-/**
- * @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.
- *
- * @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
- */
-void chSemReset(semaphore_t *sp, cnt_t n) {
-
- chSysLock();
- chSemResetI(sp, n);
- chSchRescheduleS();
- chSysUnlock();
-}
-
-/**
- * @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.
- *
- * @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
- */
-void chSemResetI(semaphore_t *sp, cnt_t n) {
- cnt_t cnt;
-
- chDbgCheckClassI();
- chDbgCheck((sp != NULL) && (n >= (cnt_t)0));
-
- cnt = sp->cnt;
- sp->cnt = n;
-
- /* Does nothing for cnt >= 0, calling anyway.*/
- (void) nil_ready_all((void *)sp, cnt, MSG_RESET);
-}
-#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
-
-#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
-/**
- * @brief Adds a set of event flags directly to the specified @p thread_t.
- *
- * @param[in] tp the thread to be signaled
- * @param[in] mask the event flags set to be ORed
- *
- * @api
- */
-void chEvtSignal(thread_t *tp, eventmask_t mask) {
-
- chSysLock();
- chEvtSignalI(tp, mask);
- chSchRescheduleS();
- chSysUnlock();
-}
-
-/**
- * @brief Adds a set of event flags directly to the specified @p thread_t.
- * @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] tp the thread to be signaled
- * @param[in] mask the event flags set to be ORed
- *
- * @iclass
- */
-void chEvtSignalI(thread_t *tp, eventmask_t mask) {
-
- chDbgCheckClassI();
- chDbgCheck(tp != NULL);
-
- tp->epmask |= mask;
- if ((NIL_THD_IS_WTOREVT(tp) &&
- ((tp->epmask & tp->u1.ewmask) != (eventmask_t)0)) ||
- (NIL_THD_IS_WTANDEVT(tp) &&
- ((tp->epmask & tp->u1.ewmask) == tp->u1.ewmask))) {
- (void) chSchReadyI(tp, MSG_OK);
- }
-}
-
-/**
- * @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] mask mask of the event flags that the function should wait
- * for, @p ALL_EVENTS enables all the events
- * @param[in] timeout the number of ticks before the operation timeouts,
- * the following special values are allowed:
- * - @a TIME_IMMEDIATE immediate timeout.
- * - @a TIME_INFINITE no timeout.
- * .
- * @return The mask of the served and cleared events.
- * @retval 0 if the operation has timed out.
- *
- * @api
- */
-eventmask_t chEvtWaitAnyTimeout(eventmask_t mask, sysinterval_t timeout) {
- thread_t *ctp = nil.current;
- eventmask_t m;
-
- chSysLock();
- if ((m = (ctp->epmask & mask)) == (eventmask_t)0) {
- if (TIME_IMMEDIATE == timeout) {
- chSysUnlock();
-
- return (eventmask_t)0;
- }
- ctp->u1.ewmask = mask;
- if (chSchGoSleepTimeoutS(NIL_STATE_WTOREVT, timeout) < MSG_OK) {
- chSysUnlock();
-
- return (eventmask_t)0;
- }
- m = ctp->epmask & mask;
- }
- ctp->epmask &= ~m;
- chSysUnlock();
-
- return m;
-}
-
-/**
- * @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] mask mask of the event flags that the function should wait
- * for, @p ALL_EVENTS enables all the events
- * @param[in] timeout the number of ticks before the operation timeouts,
- * the following special values are allowed:
- * - @a TIME_IMMEDIATE immediate timeout.
- * - @a TIME_INFINITE no timeout.
- * .
- * @return The mask of the served and cleared events.
- * @retval 0 if the operation has timed out.
- *
- * @api
- */
-eventmask_t chEvtWaitAllTimeout(eventmask_t mask, sysinterval_t timeout) {
- thread_t *ctp = nil.current;
-
- chSysLock();
- if ((ctp->epmask & mask) != mask) {
- if (TIME_IMMEDIATE == timeout) {
- chSysUnlock();
-
- return (eventmask_t)0;
- }
- ctp->u1.ewmask = mask;
- if (chSchGoSleepTimeoutS(NIL_STATE_WTANDEVT, timeout) < MSG_OK) {
- chSysUnlock();
-
- return (eventmask_t)0;
- }
- }
- ctp->epmask &= ~mask;
- chSysUnlock();
-
- return mask;
-}
-#endif /* CH_CFG_USE_EVENTS == TRUE */
-
/** @} */
diff --git a/os/nil/src/chevt.c b/os/nil/src/chevt.c
new file mode 100644
index 000000000..16746177f
--- /dev/null
+++ b/os/nil/src/chevt.c
@@ -0,0 +1,183 @@
+/*
+ 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 .
+*/
+
+/**
+ * @file nil/src/chevt.c
+ * @brief Nil RTOS events source file.
+ *
+ * @addtogroup NIL_EVENTS
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Adds a set of event flags directly to the specified @p thread_t.
+ *
+ * @param[in] tp the thread to be signaled
+ * @param[in] mask the event flags set to be ORed
+ *
+ * @api
+ */
+void chEvtSignal(thread_t *tp, eventmask_t mask) {
+
+ chSysLock();
+ chEvtSignalI(tp, mask);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Adds a set of event flags directly to the specified @p thread_t.
+ * @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] tp the thread to be signaled
+ * @param[in] mask the event flags set to be ORed
+ *
+ * @iclass
+ */
+void chEvtSignalI(thread_t *tp, eventmask_t mask) {
+
+ chDbgCheckClassI();
+ chDbgCheck(tp != NULL);
+
+ tp->epmask |= mask;
+ if ((NIL_THD_IS_WTOREVT(tp) &&
+ ((tp->epmask & tp->u1.ewmask) != (eventmask_t)0)) ||
+ (NIL_THD_IS_WTANDEVT(tp) &&
+ ((tp->epmask & tp->u1.ewmask) == tp->u1.ewmask))) {
+ (void) chSchReadyI(tp, MSG_OK);
+ }
+}
+
+/**
+ * @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] mask mask of the event flags that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+eventmask_t chEvtWaitAnyTimeout(eventmask_t mask, sysinterval_t timeout) {
+ thread_t *ctp = nil.current;
+ eventmask_t m;
+
+ chSysLock();
+ if ((m = (ctp->epmask & mask)) == (eventmask_t)0) {
+ if (TIME_IMMEDIATE == timeout) {
+ chSysUnlock();
+
+ return (eventmask_t)0;
+ }
+ ctp->u1.ewmask = mask;
+ if (chSchGoSleepTimeoutS(NIL_STATE_WTOREVT, timeout) < MSG_OK) {
+ chSysUnlock();
+
+ return (eventmask_t)0;
+ }
+ m = ctp->epmask & mask;
+ }
+ ctp->epmask &= ~m;
+ chSysUnlock();
+
+ return m;
+}
+
+/**
+ * @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] mask mask of the event flags that the function should wait
+ * for, @p ALL_EVENTS enables all the events
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return The mask of the served and cleared events.
+ * @retval 0 if the operation has timed out.
+ *
+ * @api
+ */
+eventmask_t chEvtWaitAllTimeout(eventmask_t mask, sysinterval_t timeout) {
+ thread_t *ctp = nil.current;
+
+ chSysLock();
+ if ((ctp->epmask & mask) != mask) {
+ if (TIME_IMMEDIATE == timeout) {
+ chSysUnlock();
+
+ return (eventmask_t)0;
+ }
+ ctp->u1.ewmask = mask;
+ if (chSchGoSleepTimeoutS(NIL_STATE_WTANDEVT, timeout) < MSG_OK) {
+ chSysUnlock();
+
+ return (eventmask_t)0;
+ }
+ }
+ ctp->epmask &= ~mask;
+ chSysUnlock();
+
+ return mask;
+}
+
+#endif /* CH_CFG_USE_EVENTS == TRUE */
+
+/** @} */
diff --git a/os/nil/src/chmsg.c b/os/nil/src/chmsg.c
new file mode 100644
index 000000000..08a6a9a71
--- /dev/null
+++ b/os/nil/src/chmsg.c
@@ -0,0 +1,133 @@
+/*
+ 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 .
+*/
+
+/**
+ * @file nil/src/chmsg.c
+ * @brief Nil RTOS synchronous messages source file.
+ *
+ * @addtogroup NIL_MESSAGES
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Sends a message to the specified thread.
+ * @details The sender is stopped until the receiver executes a
+ * @p chMsgRelease()after receiving the message.
+ *
+ * @param[in] tp the pointer to the thread
+ * @param[in] msg the message
+ * @return The answer message from @p chMsgRelease().
+ *
+ * @api
+ */
+msg_t chMsgSend(thread_t *tp, msg_t msg) {
+ thread_t *ctp = nil.current;
+
+ chDbgCheck(tp != NULL);
+
+ chSysLock();
+ ctp->sntmsg = msg;
+ ctp->u1.tp = tp;
+ if (NIL_THD_IS_WTMSG(tp)) {
+ (void) chSchReadyI(tp, (msg_t)ctp);
+ }
+ msg = chSchGoSleepTimeoutS(NIL_STATE_SNDMSGQ, TIME_INFINITE);
+ chSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @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.
+ *
+ * @api
+ */
+thread_t *chMsgWait(void) {
+ thread_t *tp;
+
+ chSysLock();
+ tp = nil_find_thread(NIL_STATE_SNDMSGQ, nil.current);
+ if (tp == NULL) {
+ tp = (thread_t *)chSchGoSleepTimeoutS(NIL_STATE_WTMSG, TIME_INFINITE);
+ }
+ chSysUnlock();
+
+ return tp;
+}
+
+/**
+ * @brief Releases a sender thread specifying a response message.
+ * @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
+ *
+ * @api
+ */
+void chMsgRelease(thread_t *tp, msg_t msg) {
+
+ chSysLock();
+ chDbgAssert(tp->state == NIL_STATE_SNDMSGQ, "invalid state");
+ chMsgReleaseS(tp, msg);
+ chSysUnlock();
+}
+
+#endif /* CH_CFG_USE_MESSAGES == TRUE */
+
+/** @} */
diff --git a/os/nil/src/chsem.c b/os/nil/src/chsem.c
new file mode 100644
index 000000000..d56bf03c0
--- /dev/null
+++ b/os/nil/src/chsem.c
@@ -0,0 +1,218 @@
+/*
+ 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 .
+*/
+
+/**
+ * @file nil/src/chsem.c
+ * @brief Nil RTOS semaphores source file.
+ *
+ * @addtogroup NIL_SEMAPHORES
+ * @{
+ */
+
+#include "ch.h"
+
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module local definitions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local variables. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module local functions. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module interrupt handlers. */
+/*===========================================================================*/
+
+/*===========================================================================*/
+/* Module exported functions. */
+/*===========================================================================*/
+
+/**
+ * @brief Performs a wait operation on a semaphore with timeout specification.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval NIL_MSG_OK if the thread has not stopped on the semaphore or the
+ * semaphore has been signaled.
+ * @retval NIL_MSG_RST if the semaphore has been reset using @p chSemReset().
+ * @retval NIL_MSG_TMO if the semaphore has not been signaled or reset within
+ * the specified timeout.
+ *
+ * @api
+ */
+msg_t chSemWaitTimeout(semaphore_t *sp, sysinterval_t timeout) {
+ msg_t msg;
+
+ chSysLock();
+ msg = chSemWaitTimeoutS(sp, timeout);
+ chSysUnlock();
+
+ return msg;
+}
+
+/**
+ * @brief Performs a wait operation on a semaphore with timeout specification.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ * @param[in] timeout the number of ticks before the operation timeouts,
+ * the following special values are allowed:
+ * - @a TIME_IMMEDIATE immediate timeout.
+ * - @a TIME_INFINITE no timeout.
+ * .
+ * @return A message specifying how the invoking thread has been
+ * released from the semaphore.
+ * @retval NIL_MSG_OK if the thread has not stopped on the semaphore or the
+ * semaphore has been signaled.
+ * @retval NIL_MSG_RST if the semaphore has been reset using @p chSemReset().
+ * @retval NIL_MSG_TMO if the semaphore has not been signaled or reset within
+ * the specified timeout.
+ *
+ * @sclass
+ */
+msg_t chSemWaitTimeoutS(semaphore_t *sp, sysinterval_t timeout) {
+
+ chDbgCheckClassS();
+ chDbgCheck(sp != NULL);
+
+ /* Note, the semaphore counter is a volatile variable so accesses are
+ manually optimized.*/
+ cnt_t cnt = sp->cnt;
+ if (cnt <= (cnt_t)0) {
+ if (TIME_IMMEDIATE == timeout) {
+
+ return MSG_TIMEOUT;
+ }
+ sp->cnt = cnt - (cnt_t)1;
+ nil.current->u1.semp = sp;
+
+ return chSchGoSleepTimeoutS(NIL_STATE_WTQUEUE, timeout);
+ }
+ sp->cnt = cnt - (cnt_t)1;
+
+ return MSG_OK;
+}
+
+/**
+ * @brief Performs a signal operation on a semaphore.
+ *
+ * @param[in] sp pointer to a @p semaphore_t structure
+ *
+ * @api
+ */
+void chSemSignal(semaphore_t *sp) {
+
+ chSysLock();
+ chSemSignalI(sp);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @brief Performs a signal operation on a semaphore.
+ * @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] sp pointer to a @p semaphore_t structure
+ *
+ * @iclass
+ */
+void chSemSignalI(semaphore_t *sp) {
+
+ chDbgCheckClassI();
+ chDbgCheck(sp != NULL);
+
+ if (++sp->cnt <= (cnt_t)0) {
+ thread_t *tp = nil_find_thread(NIL_STATE_WTQUEUE, (void *)sp);
+
+ chDbgAssert(tp != NULL, "thread not found");
+
+ (void) chSchReadyI(tp, MSG_OK);
+ }
+}
+
+/**
+ * @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.
+ *
+ * @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
+ */
+void chSemReset(semaphore_t *sp, cnt_t n) {
+
+ chSysLock();
+ chSemResetI(sp, n);
+ chSchRescheduleS();
+ chSysUnlock();
+}
+
+/**
+ * @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.
+ *
+ * @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
+ */
+void chSemResetI(semaphore_t *sp, cnt_t n) {
+ cnt_t cnt;
+
+ chDbgCheckClassI();
+ chDbgCheck((sp != NULL) && (n >= (cnt_t)0));
+
+ cnt = sp->cnt;
+ sp->cnt = n;
+
+ /* Does nothing for cnt >= 0, calling anyway.*/
+ (void) nil_ready_all((void *)sp, cnt, MSG_RESET);
+}
+
+#endif /* CH_CFG_USE_SEMAPHORES == TRUE */
+
+/** @} */
diff --git a/test/lib/ch_test.c b/test/lib/ch_test.c
index 859ecdf9f..f7eb8f453 100644
--- a/test/lib/ch_test.c
+++ b/test/lib/ch_test.c
@@ -255,6 +255,23 @@ msg_t test_execute(BaseSequentialStream *stream, const testsuite_t *tsp) {
test_print("*** Test Board: ");
test_println(BOARD_NAME);
#endif
+#if defined(__GNUC__) && !defined(TEST_SUPPRESS_SIZE_REPORT)
+ {
+ extern uint8_t __text_base, __text_end,
+ _data_start, _data_end,
+ _bss_start, _bss_end;
+ test_println("***");
+ test_print("*** Text size: ");
+ test_printn((uint32_t)(&__text_end - &__text_base));
+ test_println(" bytes");
+ test_print("*** Data size: ");
+ test_printn((uint32_t)(&_data_end - &_data_start));
+ test_println(" bytes");
+ test_print("*** BSS size: ");
+ test_printn((uint32_t)(&_bss_end - &_bss_start));
+ test_println(" bytes");
+ }
+#endif
#if defined(TEST_REPORT_HOOK_HEADER)
TEST_REPORT_HOOK_HEADER
#endif