aboutsummaryrefslogtreecommitdiffstats
path: root/os/nil
diff options
context:
space:
mode:
authorgdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-09-04 10:26:42 +0000
committergdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-09-04 10:26:42 +0000
commita923a46007f6ae63deac2183319ba064e7b2921c (patch)
tree754144a11546db58a8b28720a44fc4914b1d2548 /os/nil
parent66d1c88211653eff42b6c76c8c207d43179630e8 (diff)
downloadChibiOS-a923a46007f6ae63deac2183319ba064e7b2921c.tar.gz
ChibiOS-a923a46007f6ae63deac2183319ba064e7b2921c.tar.bz2
ChibiOS-a923a46007f6ae63deac2183319ba064e7b2921c.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/kernel_3_dev@6259 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/nil')
-rw-r--r--os/nil/include/nil.h107
-rw-r--r--os/nil/osal/osal.h52
-rw-r--r--os/nil/ports/ARMCMx/compilers/GCC/niltypes.h1
-rw-r--r--os/nil/src/nil.c157
4 files changed, 235 insertions, 82 deletions
diff --git a/os/nil/include/nil.h b/os/nil/include/nil.h
index 30c8012b0..ea6839d6b 100644
--- a/os/nil/include/nil.h
+++ b/os/nil/include/nil.h
@@ -88,10 +88,27 @@
#define NIL_STATE_SLEEPING 1 /**< @brief Thread sleeping. */
#define NIL_STATE_SUSP 2 /**< @brief Thread suspended. */
#define NIL_STATE_WTSEM 3 /**< @brief Thread waiting on semaphore.*/
+#define NIL_STATE_WTOREVT 4 /**< @brief Thread waiting for events. */
#define NIL_THD_IS_READY(tr) ((tr)->state == NIL_STATE_READY)
#define NIL_THD_IS_SLEEPING(tr) ((tr)->state == NIL_STATE_SLEEPING)
#define NIL_THD_IS_SUSP(tr) ((tr)->state == NIL_STATE_SUSP)
#define NIL_THD_IS_WTSEM(tr) ((tr)->state == NIL_STATE_WTSEM)
+#define NIL_THD_IS_WTOREVT(tr) ((tr)->state == NIL_STATE_WTOREVT)
+/** @} */
+
+/**
+ * @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)))
/** @} */
/*===========================================================================*/
@@ -110,8 +127,8 @@
/**
* @brief System timer resolution in Hz.
*/
-#if !defined(NIL_CFG_FREQUENCY) || defined(__DOXYGEN__)
-#define NIL_CFG_FREQUENCY 100
+#if !defined(NIL_CFG_ST_FREQUENCY) || defined(__DOXYGEN__)
+#define NIL_CFG_ST_FREQUENCY 100
#endif
/**
@@ -127,6 +144,16 @@
#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(NIL_CFG_USE_EVENTS) || defined(__DOXYGEN__)
+#define NIL_CFG_USE_EVENTS TRUE
+#endif
+
+/**
* @brief System assertions.
*/
#if !defined(NIL_CFG_ENABLE_ASSERTS) || defined(__DOXYGEN__)
@@ -154,8 +181,8 @@
"ChibiOS/RT instead"
#endif
-#if NIL_CFG_FREQUENCY <= 0
-#error "invalid NIL_CFG_FREQUENCY specified"
+#if NIL_CFG_ST_FREQUENCY <= 0
+#error "invalid NIL_CFG_ST_FREQUENCY specified"
#endif
#if (NIL_CFG_TIMEDELTA < 0) || (NIL_CFG_TIMEDELTA == 1)
@@ -228,9 +255,15 @@ struct nil_thread {
void *p; /**< @brief Generic pointer. */
thread_reference_t *trp; /**< @brief Pointer to thread reference. */
semaphore_t *semp; /**< @brief Pointer to semaphore. */
+#if NIL_CFG_USE_EVENTS
+ eventmask_t ewmask; /**< @brief Enabled events mask. */
+#endif
} u1;
volatile systime_t timeout;/**< @brief Timeout counter, zero
if disabled. */
+#if NIL_CFG_USE_EVENTS
+ eventmask_t epmask; /**< @brief Pending events mask. */
+#endif
/* Optional extra fields.*/
NIL_CFG_THREAD_EXT_FIELDS
};
@@ -244,40 +277,40 @@ typedef struct {
/**
* @brief Pointer to the running thread.
*/
- thread_reference_t current;
+ thread_reference_t current;
/**
* @brief Pointer to the next thread to be executed.
* @note This pointer must point at the same thread pointed by @p currp
* or to an higher priority thread if a switch is required.
*/
- thread_reference_t next;
+ thread_reference_t next;
#if NIL_CFG_TIMEDELTA == 0 || defined(__DOXYGEN__)
/**
* @brief System time.
*/
- systime_t systime;
+ systime_t systime;
#endif
#if NIL_CFG_TIMEDELTA > 0 || defined(__DOXYGEN__)
/**
* @brief System time of the last tick event.
*/
- systime_t lasttime;
+ systime_t lasttime;
/**
* @brief Time of the next scheduled tick event.
*/
- systime_t nexttime;
+ systime_t nexttime;
#endif
/**
* @brief Thread structures for all the defined threads.
*/
- thread_t threads[NIL_CFG_NUM_THREADS + 1];
+ thread_t threads[NIL_CFG_NUM_THREADS + 1];
#if CH_DBG_ENABLED || defined(__DOXYGEN__)
/**
* @brief Panic message.
* @note This field is only present if some debug options have been
* activated.
*/
- const char *dbg_panic_msg;
+ const char *dbg_panic_msg;
#endif
} nil_system_t;
@@ -424,7 +457,7 @@ typedef struct {
* @api
*/
#define S2ST(sec) \
- ((systime_t)((sec) * NIL_CFG_FREQUENCY))
+ ((systime_t)((sec) * NIL_CFG_ST_FREQUENCY))
/**
* @brief Milliseconds to system ticks.
@@ -437,8 +470,8 @@ typedef struct {
* @api
*/
#define MS2ST(msec) \
- ((systime_t)(((((uint32_t)(msec)) * ((uint32_t)NIL_CFG_FREQUENCY) - 1UL) /\
- 1000UL) + 1UL))
+ ((systime_t)(((((uint32_t)(msec)) * \
+ ((uint32_t)NIL_CFG_ST_FREQUENCY) - 1UL) / 1000UL) + 1UL))
/**
* @brief Microseconds to system ticks.
@@ -451,8 +484,8 @@ typedef struct {
* @api
*/
#define US2ST(usec) \
- ((systime_t)(((((uint32_t)(usec)) * ((uint32_t)NIL_CFG_FREQUENCY) - 1UL) /\
- 1000000UL) + 1UL))
+ ((systime_t)(((((uint32_t)(usec)) * \
+ ((uint32_t)NIL_CFG_ST_FREQUENCY) - 1UL) / 1000000UL) + 1UL))
/** @} */
/**
@@ -572,7 +605,7 @@ typedef struct {
* @sclass
*/
#define chThdSleepUntilS(time) \
- chSchGoSleepTimeoutS(NIL_STATE_SLEEPING, (time) - chTimeNow())
+ chSchGoSleepTimeoutS(NIL_STATE_SLEEPING, (time) - chVTGetSystemTimeX())
/**
* @brief Initializes a semaphore with the specified counter value.
@@ -625,36 +658,20 @@ typedef struct {
* @details Returns the number of system ticks since the @p chSysInit()
* invocation.
* @note The counter can reach its maximum and then restart from zero.
- * @note This function is designed to work with the @p chThdSleepUntil().
+ * @note This function can be called from any context but its atomicity
+ * is not guaranteed on architectures whose word size is less than
+ * @systime_t size.
*
* @return The system time in ticks.
*
- * @iclass
+ * @xclass
*/
#if NIL_CFG_TIMEDELTA == 0 || defined(__DOXYGEN__)
-#define chTimeNowI() (nil.systime)
+#define chVTGetSystemTimeX() (nil.systime)
#else
-#define chTimeNowI() port_timer_get_time()
+#define chVTGetSystemTimeX() port_timer_get_time()
#endif
-/**
- * @brief Checks if the specified time is within the specified time window.
- * @note When start==end then the function returns always true because the
- * whole time range is specified.
- *
- * @param[in] time the time to be verified
- * @param[in] start the start of the time window (inclusive)
- * @param[in] end the end of the time window (non inclusive)
- *
- * @retval true current time within the specified time window.
- * @retval false current time not within the specified time window.
- *
- * @api
- */
-#define chTimeIsWithin(time, start, end) \
- ((end) > (start) ? ((time) >= (start)) && ((time) < (end)) : \
- ((time) >= (start)) || ((time) < (end)))
-
#if NIL_CFG_ENABLE_ASSERTS || defined(__DOXYGEN__)
/**
* @brief Condition assertion.
@@ -671,9 +688,9 @@ typedef struct {
* @api
*/
#if !defined(chDbgAssert)
-#define chDbgAssert(c, r) { \
+#define chDbgAssert(c, r) { \
if (!(c)) \
- chSysHalt("A:"__CH_QUOTE(__FUNCTION__)":"__CH_QUOTE(__LINE__)); \
+ chSysHalt("A:"__CH_QUOTE(__FUNCTION__)":"__CH_QUOTE(__LINE__)); \
}
#endif /* !defined(chDbgAssert) */
#else /* !NIL_CFG_ENABLE_ASSERTS */
@@ -696,6 +713,8 @@ extern "C" {
void chSysInit(void);
void chSysHalt(const char *reason);
void chSysTimerHandlerI(void);
+ syssts_t chSysGetStatusAndLockX(void);
+ void chSysRestoreStatusX(syssts_t sts);
thread_reference_t chSchReadyI(thread_reference_t trp, msg_t msg);
msg_t chSchGoSleepTimeoutS(tstate_t newstate, systime_t timeout);
void chSchRescheduleS(void);
@@ -703,14 +722,16 @@ extern "C" {
void chThdResumeI(thread_reference_t *trp, msg_t msg);
void chThdSleep(systime_t time);
void chThdSleepUntil(systime_t time);
- systime_t chTimeNow(void);
- bool chTimeNowIsWithin(systime_t start, systime_t end);
+ bool chVTIsTimeWithinX(systime_t time, systime_t start, systime_t end);
msg_t chSemWaitTimeout(semaphore_t *sp, systime_t time);
msg_t chSemWaitTimeoutS(semaphore_t *sp, systime_t time);
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);
+ void chEvtSignal(thread_t *tp, eventmask_t mask);
+ void chEvtSignalI(thread_t *tp, eventmask_t mask);
+ eventmask_t chEvtWaitAnyTimeout(eventmask_t mask, systime_t timeout);
#ifdef __cplusplus
}
#endif
diff --git a/os/nil/osal/osal.h b/os/nil/osal/osal.h
index 3e58154fa..a974452da 100644
--- a/os/nil/osal/osal.h
+++ b/os/nil/osal/osal.h
@@ -107,6 +107,10 @@
/* Derived constants and error checks. */
/*===========================================================================*/
+#if !NIL_CFG_USE_EVENTS
+#error "OSAL requires NIL_CFG_USE_EVENTS=TRUE"
+#endif
+
#if !(OSAL_ST_MODE == OSAL_ST_MODE_NONE) && \
!(OSAL_ST_MODE == OSAL_ST_MODE_PERIODIC) && \
!(OSAL_ST_MODE == OSAL_ST_MODE_FREERUNNING)
@@ -152,24 +156,41 @@ typedef uint32_t rtcnt_t;
typedef thread_t * thread_reference_t;
#endif
-typedef (*eventcallback_t)()
+/**
+ * @brief Type of an event flags object.
+ * @note The content of this structure is not part of the API and should
+ * not be relied upon. Implementers may define this structure in
+ * an entirely different way.
+ * @note Retrieval and clearing of the flags are not defined in this
+ * API and are implementation-dependent.
+ */
+typedef struct event_source event_source_t;
+
+/**
+ * @brief Type of an event source callback.
+ * @note This type is not part of the OSAL API and is provided
+ * exclusively as an example and for convenience.
+ */
+typedef void (*eventcallback_t)(event_source_t *);
+
/**
* @brief Type of an event flags mask.
*/
typedef uint32_t eventflags_t;
/**
- * @brief Type of an event flags object.
+ * @brief Events source object.
* @note The content of this structure is not part of the API and should
* not be relied upon. Implementers may define this structure in
* an entirely different way.
* @note Retrieval and clearing of the flags are not defined in this
* API and are implementation-dependent.
*/
-typedef struct {
- volatile eventflags_t flags; /**< @brief Flags stored into the
- object. */
-} eventsource_t;
+struct event_source {
+ volatile eventflags_t flags; /**< @brief Stored event flags. */
+ eventcallback_t cb; /**< @brief Event source callback. */
+ void *param; /**< @brief User defined field. */
+};
/**
* @brief Type of a mutex.
@@ -653,9 +674,11 @@ static inline msg_t osalQueueGoSleepTimeoutS(threads_queue_t *tqp,
*
* @init
*/
-static inline void osalEventObjectInit(eventsource_t *esp) {
+static inline void osalEventObjectInit(event_source_t *esp) {
- chEvtObjectInit(esp);
+ esp->flags = 0;
+ esp->cb = NULL;
+ esp->param = NULL;
}
/**
@@ -666,10 +689,12 @@ static inline void osalEventObjectInit(eventsource_t *esp) {
*
* @iclass
*/
-static inline void osalEventBroadcastFlagsI(eventsource_t *esp,
+static inline void osalEventBroadcastFlagsI(event_source_t *esp,
eventflags_t flags) {
- chEvtBroadcastFlagsI(esp, flags);
+ esp->flags |= flags;
+ if (esp->cb != NULL)
+ esp->cb(esp);
}
/**
@@ -680,10 +705,13 @@ static inline void osalEventBroadcastFlagsI(eventsource_t *esp,
*
* @iclass
*/
-static inline void osalEventBroadcastFlags(eventsource_t *esp,
+static inline void osalEventBroadcastFlags(event_source_t *esp,
eventflags_t flags) {
- chEvtBroadcastFlags(esp, flags);
+ chSysLock();
+ osalEventBroadcastFlagsI(esp, flags);
+ chSchRescheduleS();
+ chSysUnlock();
}
/**
diff --git a/os/nil/ports/ARMCMx/compilers/GCC/niltypes.h b/os/nil/ports/ARMCMx/compilers/GCC/niltypes.h
index 88dba58b8..0925c1daf 100644
--- a/os/nil/ports/ARMCMx/compilers/GCC/niltypes.h
+++ b/os/nil/ports/ARMCMx/compilers/GCC/niltypes.h
@@ -55,6 +55,7 @@ typedef uint32_t systime_t; /**< System time. */
typedef uint32_t rtcnt_t; /**< Realtime counter. */
typedef uint8_t tstate_t; /**< Thread state. */
typedef int32_t msg_t; /**< Inter-thread message. */
+typedef uint32_t eventmask_t; /**< Mask of event identifiers. */
typedef int32_t cnt_t; /**< Generic signed counter. */
typedef uint32_t ucnt_t; /**< Generic unsigned counter. */
diff --git a/os/nil/src/nil.c b/os/nil/src/nil.c
index d316f01e0..809887de3 100644
--- a/os/nil/src/nil.c
+++ b/os/nil/src/nil.c
@@ -211,6 +211,52 @@ void chSysTimerHandlerI(void) {
}
/**
+ * @brief Returns the execution status and enters a critical zone.
+ * @details This functions enters into a critical zone and can be called
+ * from any context. Because its flexibility it is less efficient
+ * than @p chSysLock() which is preferable when the calling context
+ * is known.
+ * @post The system is in a critical zone.
+ *
+ * @return The previous system status, the encoding of this
+ * status word is architecture-dependent and opaque.
+ *
+ * @xclass
+ */
+syssts_t chSysGetStatusAndLockX(void) {
+
+ syssts_t sts = port_get_irq_status();
+ if (port_irq_enabled(sts)) {
+ if (port_is_isr_context())
+ chSysLockFromISR();
+ else
+ chSysLock();
+ }
+ return sts;
+}
+
+/**
+ * @brief Restores the specified execution status and leaves a critical zone.
+ * @note A call to @p chSchRescheduleS() is automatically performed
+ * if exiting the critical zone and if not in ISR context.
+ *
+ * @param[in] sts the system status to be restored.
+ *
+ * @xclass
+ */
+void chSysRestoreStatusX(syssts_t sts) {
+
+ if (port_irq_enabled(sts)) {
+ if (port_is_isr_context())
+ chSysUnlockFromISR();
+ else {
+ chSchRescheduleS();
+ chSysUnlock();
+ }
+ }
+}
+
+/**
* @brief Makes the specified thread ready for execution.
*
* @param[in] tr reference to the @p thread_t object
@@ -409,43 +455,23 @@ void chThdSleepUntil(systime_t time) {
}
/**
- * @brief Current system time.
- * @details Returns the number of system ticks since the @p chSysInit()
- * invocation.
- * @note The counter can reach its maximum and then restart from zero.
- * @note This function is designed to work with the @p chThdSleepUntil().
- *
- * @return The system time in ticks.
- *
- * @api
- */
-systime_t chTimeNow(void) {
- systime_t time;
-
- chSysLock();
- time = chTimeNowI();
- chSysUnlock();
- return time;
-}
-
-/**
- * @brief Checks if the current system time is within the specified time
- * window.
+ * @brief Checks if the specified time is within the specified time window.
* @note When start==end then the function returns always true because the
* whole time range is specified.
+ * @note This function can be called from any context.
*
+ * @param[in] time the time to be verified
* @param[in] start the start of the time window (inclusive)
* @param[in] end the end of the time window (non inclusive)
- *
* @retval true current time within the specified time window.
* @retval false current time not within the specified time window.
*
- * @api
+ * @xclass
*/
-bool chTimeNowIsWithin(systime_t start, systime_t end) {
+bool chVTIsTimeWithinX(systime_t time, systime_t start, systime_t end) {
- systime_t time = chTimeNow();
- return chTimeIsWithin(time, start, end);
+ return end > start ? (time >= start) && (time < end) :
+ (time >= start) || (time < end);
}
/**
@@ -625,4 +651,81 @@ void chSemResetI(semaphore_t *sp, cnt_t n) {
}
}
+/**
+ * @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) {
+
+ tp->epmask |= mask;
+ if (NIL_THD_IS_WTOREVT(tp) && ((tp->epmask & tp->u1.ewmask) != 0))
+ 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, systime_t timeout) {
+ thread_t *ctp = nil.current;
+ eventmask_t m;
+
+ chSysLock();
+
+ if ((m = (ctp->epmask & mask)) == 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;
+}
+
/** @} */