diff options
-rw-r--r-- | demos/STM32/NIL-STM32F303-DISCOVERY/debug/NIL-STM32F303-DISCOVERY (OpenOCD, Flash and Run).launch | 104 | ||||
-rw-r--r-- | os/hal/osal/nil/osal.c | 64 | ||||
-rw-r--r-- | os/hal/osal/nil/osal.h | 38 | ||||
-rw-r--r-- | os/nil/include/ch.h | 27 | ||||
-rw-r--r-- | os/nil/src/ch.c | 75 | ||||
-rw-r--r-- | release_note_next.txt | 2 |
6 files changed, 178 insertions, 132 deletions
diff --git a/demos/STM32/NIL-STM32F303-DISCOVERY/debug/NIL-STM32F303-DISCOVERY (OpenOCD, Flash and Run).launch b/demos/STM32/NIL-STM32F303-DISCOVERY/debug/NIL-STM32F303-DISCOVERY (OpenOCD, Flash and Run).launch index 335ac55b7..9df8eea30 100644 --- a/demos/STM32/NIL-STM32F303-DISCOVERY/debug/NIL-STM32F303-DISCOVERY (OpenOCD, Flash and Run).launch +++ b/demos/STM32/NIL-STM32F303-DISCOVERY/debug/NIL-STM32F303-DISCOVERY (OpenOCD, Flash and Run).launch @@ -1,52 +1,52 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.cdt.debug.gdbjtag.launchConfigurationType">
-<stringAttribute key="bad_container_name" value="\NIL-STM32F303-DISCOVERY\debug"/>
-<intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.delay" value="1"/>
-<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.doHalt" value="true"/>
-<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.doReset" value="true"/>
-<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageFileName" value=""/>
-<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageOffset" value=""/>
-<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.initCommands" value="set remotetimeout 20 monitor reset init monitor sleep 50 "/>
-<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.ipAddress" value="localhost"/>
-<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.jtagDevice" value="Generic TCP/IP"/>
-<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadImage" value="true"/>
-<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadSymbols" value="true"/>
-<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.pcRegister" value=""/>
-<intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.portNumber" value="3333"/>
-<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.runCommands" value=""/>
-<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setPcRegister" value="false"/>
-<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setResume" value="true"/>
-<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setStopAt" value="true"/>
-<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.stopAt" value="main"/>
-<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsFileName" value=""/>
-<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsOffset" value=""/>
-<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForImage" value="false"/>
-<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForSymbols" value="false"/>
-<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForImage" value="true"/>
-<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForSymbols" value="true"/>
-<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useRemoteTarget" value="true"/>
-<stringAttribute key="org.eclipse.cdt.debug.mi.core.DEBUG_NAME" value="arm-none-eabi-gdb"/>
-<stringAttribute key="org.eclipse.cdt.debug.mi.core.commandFactory" value="Standard"/>
-<stringAttribute key="org.eclipse.cdt.debug.mi.core.protocol" value="mi"/>
-<booleanAttribute key="org.eclipse.cdt.debug.mi.core.verboseMode" value="false"/>
-<stringAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_NAME" value="arm-none-eabi-gdb"/>
-<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/>
-<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/>
-<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/>
-<stringAttribute key="org.eclipse.cdt.launch.FORMAT" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?><contentList/>"/>
-<stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <globalVariableList/> "/>
-<stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <memoryBlockExpressionList/> "/>
-<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="./build/ch.elf"/>
-<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="NIL-STM32F303-DISCOVERY"/>
-<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="true"/>
-<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="0.1984968159"/>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/NIL-STM32F303-DISCOVERY"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="4"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
-<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
-</listAttribute>
-</launchConfiguration>
+<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<launchConfiguration type="org.eclipse.cdt.debug.gdbjtag.launchConfigurationType"> +<stringAttribute key="bad_container_name" value="\NIL-STM32F303-DISCOVERY\debug"/> +<intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.delay" value="1"/> +<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.doHalt" value="true"/> +<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.doReset" value="true"/> +<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageFileName" value=""/> +<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.imageOffset" value=""/> +<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.initCommands" value="set remotetimeout 20 monitor reset init monitor sleep 50 "/> +<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.ipAddress" value="localhost"/> +<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.jtagDevice" value="Generic TCP/IP"/> +<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadImage" value="true"/> +<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.loadSymbols" value="true"/> +<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.pcRegister" value=""/> +<intAttribute key="org.eclipse.cdt.debug.gdbjtag.core.portNumber" value="3333"/> +<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.runCommands" value=""/> +<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setPcRegister" value="false"/> +<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setResume" value="true"/> +<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.setStopAt" value="true"/> +<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.stopAt" value="main"/> +<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsFileName" value=""/> +<stringAttribute key="org.eclipse.cdt.debug.gdbjtag.core.symbolsOffset" value=""/> +<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForImage" value="false"/> +<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useFileForSymbols" value="false"/> +<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForImage" value="true"/> +<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useProjBinaryForSymbols" value="true"/> +<booleanAttribute key="org.eclipse.cdt.debug.gdbjtag.core.useRemoteTarget" value="true"/> +<stringAttribute key="org.eclipse.cdt.debug.mi.core.DEBUG_NAME" value="arm-none-eabi-gdb"/> +<stringAttribute key="org.eclipse.cdt.debug.mi.core.commandFactory" value="Standard"/> +<stringAttribute key="org.eclipse.cdt.debug.mi.core.protocol" value="mi"/> +<booleanAttribute key="org.eclipse.cdt.debug.mi.core.verboseMode" value="false"/> +<stringAttribute key="org.eclipse.cdt.dsf.gdb.DEBUG_NAME" value="arm-none-eabi-gdb"/> +<intAttribute key="org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR" value="2"/> +<stringAttribute key="org.eclipse.cdt.launch.COREFILE_PATH" value=""/> +<stringAttribute key="org.eclipse.cdt.launch.DEBUGGER_REGISTER_GROUPS" value=""/> +<stringAttribute key="org.eclipse.cdt.launch.FORMAT" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?><contentList/>"/> +<stringAttribute key="org.eclipse.cdt.launch.GLOBAL_VARIABLES" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <globalVariableList/> "/> +<stringAttribute key="org.eclipse.cdt.launch.MEMORY_BLOCKS" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <memoryBlockExpressionList/> "/> +<stringAttribute key="org.eclipse.cdt.launch.PROGRAM_NAME" value="./build/ch.elf"/> +<stringAttribute key="org.eclipse.cdt.launch.PROJECT_ATTR" value="NIL-STM32F303-DISCOVERY"/> +<booleanAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_AUTO_ATTR" value="true"/> +<stringAttribute key="org.eclipse.cdt.launch.PROJECT_BUILD_CONFIG_ID_ATTR" value="0.1984968159"/> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/NIL-STM32F303-DISCOVERY"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="4"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> +<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/> +</listAttribute> +</launchConfiguration> diff --git a/os/hal/osal/nil/osal.c b/os/hal/osal/nil/osal.c index e486641c5..863be6a75 100644 --- a/os/hal/osal/nil/osal.c +++ b/os/hal/osal/nil/osal.c @@ -48,68 +48,4 @@ /* Module exported functions. */
/*===========================================================================*/
-/**
- * @brief Dequeues and wakes up one thread from the queue, if any.
- *
- * @param[in] tqp pointer to the threads queue object
- * @param[in] msg the message code
- *
- * @iclass
- */
-void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg) {
- semaphore_t *sp = &tqp->sem;
-
- if (chSemGetCounterI(&tqp->sem) < (cnt_t)0) {
- thread_t *tp = nil.threads;
- while (true) {
- /* Is this thread waiting on this semaphore?*/
- if (tp->u1.semp == sp) {
- sp->cnt++;
-
- chDbgAssert(NIL_THD_IS_WTSEM(tp), "not waiting");
-
- (void) chSchReadyI(tp, msg);
- return;
- }
- tp++;
-
- chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS],
- "pointer out of range");
- }
- }
-}
-
-/**
- * @brief Dequeues and wakes up all threads from the queue.
- *
- * @param[in] tqp pointer to the threads queue object
- * @param[in] msg the message code
- *
- * @iclass
- */
-void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg) {
- semaphore_t *sp = &tqp->sem;
- thread_t *tp;
- cnt_t cnt;
-
- cnt = sp->cnt;
- sp->cnt = (cnt_t)0;
- tp = nil.threads;
- while (cnt < (cnt_t)0) {
-
- chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS],
- "pointer out of range");
-
- /* Is this thread waiting on this semaphore?*/
- if (tp->u1.semp == sp) {
-
- chDbgAssert(NIL_THD_IS_WTSEM(tp), "not waiting");
-
- cnt++;
- (void) chSchReadyI(tp, msg);
- }
- tp++;
- }
-}
-
/** @} */
diff --git a/os/hal/osal/nil/osal.h b/os/hal/osal/nil/osal.h index 4f81bd53a..807b660c2 100644 --- a/os/hal/osal/nil/osal.h +++ b/os/hal/osal/nil/osal.h @@ -219,6 +219,8 @@ struct event_source { */
typedef semaphore_t mutex_t;
+
+#if 0
/**
* @brief Type of a thread queue.
* @details A thread queue is a queue of sleeping threads, queued threads
@@ -227,8 +229,9 @@ typedef semaphore_t mutex_t; * because there are no real threads.
*/
typedef struct {
- semaphore_t sem;
+ thread_reference_t tr;
} threads_queue_t;
+#endif
/*===========================================================================*/
/* Module macros. */
@@ -444,8 +447,7 @@ typedef struct { #ifdef __cplusplus
extern "C" {
#endif
- void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg);
- void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg);
+
#ifdef __cplusplus
}
#endif
@@ -766,7 +768,7 @@ static inline void osalThreadResumeS(thread_reference_t *trp, msg_t msg) { */
static inline void osalThreadQueueObjectInit(threads_queue_t *tqp) {
- chSemObjectInit(&tqp->sem, (cnt_t)0);
+ chThdQueueObjectInit(tqp);
}
/**
@@ -795,7 +797,33 @@ static inline void osalThreadQueueObjectInit(threads_queue_t *tqp) { static inline msg_t osalThreadEnqueueTimeoutS(threads_queue_t *tqp,
systime_t time) {
- return chSemWaitTimeoutS(&tqp->sem, time);
+ return chThdEnqueueTimeoutS(tqp, time);
+}
+
+/**
+ * @brief Dequeues and wakes up one thread from the queue, if any.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+static inline void osalThreadDequeueNextI(threads_queue_t *tqp, msg_t msg) {
+
+ chThdDequeueNextI(tqp, msg);
+}
+
+/**
+ * @brief Dequeues and wakes up all threads from the queue.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] msg the message code
+ *
+ * @iclass
+ */
+static inline void osalThreadDequeueAllI(threads_queue_t *tqp, msg_t msg) {
+
+ chThdDequeueAllI(tqp, msg);
}
/**
diff --git a/os/nil/include/ch.h b/os/nil/include/ch.h index f21527c2d..8fc480776 100644 --- a/os/nil/include/ch.h +++ b/os/nil/include/ch.h @@ -534,6 +534,9 @@ struct nil_thread { void *p; /**< @brief Generic pointer. */
thread_reference_t *trp; /**< @brief Pointer to thread reference.*/
threads_queue_t *tqp; /**< @brief Pointer to thread queue. */
+#if (CH_CFG_USE_SEMAPHORES == TRUE) || defined(__DOXYGEN__)
+ semaphore_t *semp; /**< @brief Pointer to semaphore. */
+#endif
#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__)
eventmask_t ewmask; /**< @brief Enabled events mask. */
#endif
@@ -912,6 +915,29 @@ struct nil_system { /** @} */
/**
+ * @name Threads queues
+ */
+/**
+ * @brief Data part of a static threads queue object initializer.
+ * @details This macro should be used when statically initializing a threads
+ * queue that is part of a bigger structure.
+ *
+ * @param[in] name the name of the threads queue variable
+ */
+#define _THREADS_QUEUE_DATA(name) {(cnt_t)0}
+
+/**
+ * @brief Static threads queue object initializer.
+ * @details Statically initialized threads queues require no explicit
+ * initialization using @p queue_init().
+ *
+ * @param[in] name the name of the threads queue variable
+ */
+#define _THREADS_QUEUE_DECL(name) \
+ threads_queue_t name = _THREADS_QUEUE_DATA(name)
+/** @} */
+
+/**
* @name Semaphores macros
* @{
*/
@@ -1367,6 +1393,7 @@ extern "C" { void chThdResumeI(thread_reference_t *trp, msg_t msg);
void chThdSleep(systime_t timeout);
void chThdSleepUntil(systime_t abstime);
+ msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, systime_t timeout);
void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg);
void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg);
void chThdDequeueAllI(threads_queue_t *tqp, msg_t msg);
diff --git a/os/nil/src/ch.c b/os/nil/src/ch.c index faf725164..db811f7b2 100644 --- a/os/nil/src/ch.c +++ b/os/nil/src/ch.c @@ -758,6 +758,45 @@ void chThdSleepUntil(systime_t abstime) { }
/**
+ * @brief Enqueues the caller thread on a threads queue object.
+ * @details The caller thread is enqueued and put to sleep until it is
+ * dequeued or the specified timeouts expires.
+ *
+ * @param[in] tqp pointer to the threads queue object
+ * @param[in] timeout the timeout in system ticks, the special values are
+ * handled as follow:
+ * - @a TIME_INFINITE the thread enters an infinite sleep
+ * state.
+ * - @a TIME_IMMEDIATE the thread is not enqueued and
+ * the function returns @p MSG_TIMEOUT as if a timeout
+ * occurred.
+ * .
+ * @return The message from @p osalQueueWakeupOneI() or
+ * @p osalQueueWakeupAllI() functions.
+ * @retval MSG_TIMEOUT if the thread has not been dequeued within the
+ * specified timeout or if the function has been
+ * invoked with @p TIME_IMMEDIATE as timeout
+ * specification.
+ *
+ * @sclass
+ */
+msg_t chThdEnqueueTimeoutS(threads_queue_t *tqp, systime_t timeout) {
+
+ chDbgCheckClassS();
+ chDbgCheck(tqp != NULL);
+
+ chDbgAssert(tqp->cnt <= (cnt_t)0, "invalid counter");
+
+ if (TIME_IMMEDIATE == timeout) {
+ return MSG_TIMEOUT;
+ }
+
+ tqp->cnt--;
+ nil.current->u1.tqp = tqp;
+ return chSchGoSleepTimeoutS(NIL_STATE_WTQUEUE, timeout);
+}
+
+/**
* @brief Dequeues and wakes up one thread from the threads queue object.
* @details Dequeues one thread from the queue without checking if the queue
* is empty.
@@ -769,23 +808,23 @@ void chThdSleepUntil(systime_t abstime) { * @iclass
*/
void chThdDoDequeueNextI(threads_queue_t *tqp, msg_t msg) {
- thread_reference_t tr = nil.threads;
+ thread_t *tp = nil.threads;
- chDbgAssert(tqp->cnt > (cnt_t)0, "empty queue");
+ chDbgAssert(tqp->cnt < (cnt_t)0, "empty queue");
while (true) {
/* Is this thread waiting on this queue?*/
- if (tr->u1.tqp == tqp) {
+ if (tp->u1.tqp == tqp) {
tqp->cnt++;
- chDbgAssert(NIL_THD_IS_WTQUEUE(tr), "not waiting");
+ chDbgAssert(NIL_THD_IS_WTQUEUE(tp), "not waiting");
- (void) chSchReadyI(tr, msg);
+ (void) chSchReadyI(tp, msg);
return;
}
- tr++;
+ tp++;
- chDbgAssert(tr < &nil.threads[CH_CFG_NUM_THREADS],
+ chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS],
"pointer out of range");
}
}
@@ -804,7 +843,7 @@ void chThdDequeueNextI(threads_queue_t *tqp, msg_t msg) { chDbgCheckClassI();
chDbgCheck(tqp != NULL);
- if (tqp->cnt <= (cnt_t)0) {
+ if (tqp->cnt < (cnt_t)0) {
chThdDoDequeueNextI(tqp, msg);
}
}
@@ -903,7 +942,7 @@ msg_t chSemWaitTimeoutS(semaphore_t *sp, systime_t timeout) { return MSG_TIMEOUT;
}
sp->cnt = cnt - (cnt_t)1;
- nil.current->u1.tqp = (threads_queue_t *)sp;
+ nil.current->u1.semp = sp;
return chSchGoSleepTimeoutS(NIL_STATE_WTQUEUE, timeout);
}
sp->cnt = cnt - (cnt_t)1;
@@ -942,7 +981,21 @@ void chSemSignalI(semaphore_t *sp) { chDbgCheck(sp != NULL);
if (++sp->cnt <= (cnt_t)0) {
- chThdDoDequeueNextI((threads_queue_t *)sp, MSG_OK);
+ thread_t *tp = nil.threads;
+ while (true) {
+ /* Is this thread waiting on this semaphore?*/
+ if (tp->u1.semp == sp) {
+
+ chDbgAssert(NIL_THD_IS_WTQUEUE(tp), "not waiting");
+
+ (void) chSchReadyI(tp, MSG_OK);
+ return;
+ }
+ tp++;
+
+ chDbgAssert(tp < &nil.threads[CH_CFG_NUM_THREADS],
+ "pointer out of range");
+ }
}
}
@@ -998,7 +1051,7 @@ void chSemResetI(semaphore_t *sp, cnt_t n) { "pointer out of range");
/* Is this thread waiting on this semaphore?*/
- if (tp->u1.tqp == (threads_queue_t *)sp) {
+ if (tp->u1.semp == sp) {
chDbgAssert(NIL_THD_IS_WTQUEUE(tp), "not waiting");
diff --git a/release_note_next.txt b/release_note_next.txt index 78a5905d2..aee19b04a 100644 --- a/release_note_next.txt +++ b/release_note_next.txt @@ -65,6 +65,8 @@ a series of important improvements, new features have been added. - Now uses the common ports architecture.
- Now uses the new shared RTOS components.
+- Added implementation of thread queues directly in the kernel, removed it
+ from NIL OSAL.
- All new features are optional so there is no code size increase.
- Enhanced source-level compatibility with RT.
- Enhanced debug features.
|