Experimental NIL expansion.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12639 110e8d01-0319-4d1e-a829-52ad28d1bb01
This commit is contained in:
parent
f528c77ec1
commit
feb3e92fba
|
@ -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).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 <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. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @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 */
|
||||
|
||||
/** @} */
|
|
@ -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 <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 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 */
|
||||
|
||||
/** @} */
|
|
@ -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 <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 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 */
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
|
|
322
os/nil/src/ch.c
322
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 */
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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 */
|
||||
|
||||
/** @} */
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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 */
|
||||
|
||||
/** @} */
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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 */
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue