Maintain legacy RTOS behavior before mbed-5

Fork of mbed-rtos by mbed official

Files at this revision

API Documentation at this revision

Comitter:
c1728p9
Date:
Mon Nov 14 17:14:42 2016 -0600
Parent:
122:b744dfee1cf2
Commit message:
Configure RTOS to behave as it did before 5.0

Changed in this revision

rtos/Mail.h Show annotated file Show diff for this revision Revisions of this file
rtos/MemoryPool.h Show annotated file Show diff for this revision Revisions of this file
rtos/Mutex.cpp Show annotated file Show diff for this revision Revisions of this file
rtos/Mutex.h Show annotated file Show diff for this revision Revisions of this file
rtos/Queue.h Show annotated file Show diff for this revision Revisions of this file
rtos/RtosTimer.cpp Show annotated file Show diff for this revision Revisions of this file
rtos/RtosTimer.h Show annotated file Show diff for this revision Revisions of this file
rtos/Semaphore.cpp Show annotated file Show diff for this revision Revisions of this file
rtos/Semaphore.h Show annotated file Show diff for this revision Revisions of this file
rtos/Thread.cpp Show annotated file Show diff for this revision Revisions of this file
rtos/Thread.h Show annotated file Show diff for this revision Revisions of this file
rtos/rtos.h Show annotated file Show diff for this revision Revisions of this file
rtos/rtos_idle.c Show annotated file Show diff for this revision Revisions of this file
rtos/rtos_idle.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_ARM7/RTX_CM_lib.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_ARM7/RTX_Conf_CM.c Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_A/RTX_CM_lib.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_A/RTX_Conf_CA.c Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_A/cmsis_os.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_A/rt_CMSIS.c Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_A/rt_TypeDef.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/HAL_CM.c Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/RTX_CM_lib.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/RTX_Conf_CM.c Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/RTX_Config.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_ARM/HAL_CM4.c Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_IAR/HAL_CM4.S Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/cmsis_os.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_CMSIS.c Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_Event.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_HAL_CM.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_List.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_Mailbox.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_MemBox.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_Memory.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_Mutex.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_OsEventObserver.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_Robin.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_Semaphore.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_System.c Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_System.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_Task.c Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_Task.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_Time.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_Timer.h Show annotated file Show diff for this revision Revisions of this file
rtx/TARGET_CORTEX_M/rt_TypeDef.h Show annotated file Show diff for this revision Revisions of this file
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/Mail.h
--- a/rtos/Mail.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/Mail.h	Mon Nov 14 17:14:42 2016 -0600
@@ -28,6 +28,8 @@
 #include "cmsis_os.h"
 
 namespace rtos {
+/** \addtogroup rtos */
+/** @{*/
 
 /** The Mail class allow to control, send, receive, or wait for mail.
  A mail is a memory block that is send to a thread or interrupt service routine.
@@ -107,3 +109,5 @@
 
 #endif
 
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/MemoryPool.h
--- a/rtos/MemoryPool.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/MemoryPool.h	Mon Nov 14 17:14:42 2016 -0600
@@ -28,6 +28,8 @@
 #include "cmsis_os.h"
 
 namespace rtos {
+/** \addtogroup rtos */
+/** @{*/
 
 /** Define and manage fixed-size memory pools of objects of a given type.
   @tparam  T         data type of a single object (element).
@@ -80,3 +82,5 @@
 
 }
 #endif
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/Mutex.cpp
--- a/rtos/Mutex.cpp	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/Mutex.cpp	Mon Nov 14 17:14:42 2016 -0600
@@ -19,10 +19,10 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-#include "Mutex.h"
+#include "rtos/Mutex.h"
 
 #include <string.h>
-#include "mbed_error.h"
+#include "platform/mbed_error.h"
 
 namespace rtos {
 
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/Mutex.h
--- a/rtos/Mutex.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/Mutex.h	Mon Nov 14 17:14:42 2016 -0600
@@ -26,6 +26,8 @@
 #include "cmsis_os.h"
 
 namespace rtos {
+/** \addtogroup rtos */
+/** @{*/
 
 /** The Mutex class is used to synchronise the execution of threads.
  This is for example used to protect access to a shared resource.
@@ -67,3 +69,5 @@
 
 }
 #endif
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/Queue.h
--- a/rtos/Queue.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/Queue.h	Mon Nov 14 17:14:42 2016 -0600
@@ -26,9 +26,11 @@
 #include <string.h>
 
 #include "cmsis_os.h"
-#include "mbed_error.h"
+#include "platform/mbed_error.h"
 
 namespace rtos {
+/** \addtogroup rtos */
+/** @{*/
 
 /** The Queue class allow to control, send, receive, or wait for messages.
  A message can be a integer or pointer value  to a certain type T that is send
@@ -79,3 +81,5 @@
 
 }
 #endif
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/RtosTimer.cpp
--- a/rtos/RtosTimer.cpp	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/RtosTimer.cpp	Mon Nov 14 17:14:42 2016 -0600
@@ -19,13 +19,13 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-#include "RtosTimer.h"
+#include "rtos/RtosTimer.h"
 
 #include <string.h>
 
 #include "mbed.h"
 #include "cmsis_os.h"
-#include "mbed_error.h"
+#include "platform/mbed_error.h"
 
 namespace rtos {
 
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/RtosTimer.h
--- a/rtos/RtosTimer.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/RtosTimer.h	Mon Nov 14 17:14:42 2016 -0600
@@ -24,10 +24,12 @@
 
 #include <stdint.h>
 #include "cmsis_os.h"
-#include "Callback.h"
-#include "toolchain.h"
+#include "platform/Callback.h"
+#include "platform/toolchain.h"
 
 namespace rtos {
+/** \addtogroup rtos */
+/** @{*/
 
 /** The RtosTimer class allow creating and and controlling of timer functions in the system.
  A timer function is called when a time period expires whereby both on-shot and
@@ -47,7 +49,7 @@
     MBED_DEPRECATED_SINCE("mbed-os-5.1",
         "Replaced with RtosTimer(Callback<void()>, os_timer_type)")
     RtosTimer(void (*func)(void const *argument), os_timer_type type=osTimerPeriodic, void *argument=NULL) {
-        constructor(mbed::Callback<void()>(argument, (void (*)(void *))func), type);
+        constructor(mbed::callback((void (*)(void *))func, argument), type);
     }
     
     /** Create timer.
@@ -62,10 +64,16 @@
       @param   obj       pointer to the object to call the member function on.
       @param   method    member function to be executed by this timer.
       @param   type      osTimerOnce for one-shot or osTimerPeriodic for periodic behaviour. (default: osTimerPeriodic)
+      @deprecated
+          The RtosTimer constructor does not support cv-qualifiers. Replaced by
+          RtosTimer(callback(obj, method), os_timer_type).
     */
     template <typename T, typename M>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+        "The RtosTimer constructor does not support cv-qualifiers. Replaced by "
+        "RtosTimer(callback(obj, method), os_timer_type).")
     RtosTimer(T *obj, M method, os_timer_type type=osTimerPeriodic) {
-        constructor(mbed::Callback<void()>(obj, method), type);
+        constructor(mbed::callback(obj, method), type);
     }
 
     /** Stop the timer.
@@ -99,3 +107,5 @@
 }
 
 #endif
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/Semaphore.cpp
--- a/rtos/Semaphore.cpp	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/Semaphore.cpp	Mon Nov 14 17:14:42 2016 -0600
@@ -19,7 +19,7 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-#include "Semaphore.h"
+#include "rtos/Semaphore.h"
 
 #include <string.h>
 
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/Semaphore.h
--- a/rtos/Semaphore.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/Semaphore.h	Mon Nov 14 17:14:42 2016 -0600
@@ -26,6 +26,8 @@
 #include "cmsis_os.h"
 
 namespace rtos {
+/** \addtogroup rtos */
+/** @{*/
 
 /** The Semaphore class is used to manage and protect access to a set of shared resources. */
 class Semaphore {
@@ -58,3 +60,5 @@
 
 }
 #endif
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/Thread.cpp
--- a/rtos/Thread.cpp	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/Thread.cpp	Mon Nov 14 17:14:42 2016 -0600
@@ -19,10 +19,10 @@
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
  */
-#include "Thread.h"
+#include "rtos/Thread.h"
 
 #include "mbed.h"
-#include "rtos_idle.h"
+#include "rtos/rtos_idle.h"
 
 // rt_tid2ptcb is an internal function which we exposed to get TCB for thread id
 #undef NULL  //Workaround for conflicting macros in rt_TypeDef.h and stdio.h
@@ -30,6 +30,15 @@
 
 extern "C" P_TCB rt_tid2ptcb(osThreadId thread_id);
 
+
+static void (*terminate_hook)(osThreadId id) = 0;
+extern "C" void thread_terminate_hook(osThreadId id)
+{
+    if (terminate_hook != (void (*)(osThreadId))NULL) {
+        terminate_hook(id);
+    }
+}
+
 namespace rtos {
 
 void Thread::constructor(osPriority priority,
@@ -74,10 +83,7 @@
     _thread_def.pthread = Thread::_thunk;
     if (_thread_def.stack_pointer == NULL) {
         _thread_def.stack_pointer = new uint32_t[_thread_def.stacksize/sizeof(uint32_t)];
-        if (_thread_def.stack_pointer == NULL) {
-            _mutex.unlock();
-            return osErrorNoMemory;
-        }
+        MBED_ASSERT(_thread_def.stack_pointer != NULL);
     }
 
     //Fill the stack with a magic word for maximum usage checking
@@ -88,8 +94,12 @@
     _task = task;
     _tid = osThreadCreate(&_thread_def, this);
     if (_tid == NULL) {
-        if (_dynamic_stack) delete[] (_thread_def.stack_pointer);
+        if (_dynamic_stack) {
+            delete[] (_thread_def.stack_pointer);
+            _thread_def.stack_pointer = (uint32_t*)NULL;
+        }
         _mutex.unlock();
+        _join_sem.release();
         return osErrorResource;
     }
 
@@ -101,11 +111,14 @@
     osStatus ret;
     _mutex.lock();
 
-    ret = osThreadTerminate(_tid);
+    // Set the Thread's tid to NULL and
+    // release the semaphore before terminating
+    // since this thread could be terminating itself
+    osThreadId local_id = _tid;
+    _join_sem.release();
     _tid = (osThreadId)NULL;
 
-    // Wake threads joining the terminated thread
-    _join_sem.release();
+    ret = osThreadTerminate(local_id);
 
     _mutex.unlock();
     return ret;
@@ -116,6 +129,14 @@
     if (ret < 0) {
         return osErrorOS;
     }
+
+    // The semaphore has been released so this thread is being
+    // terminated or has been terminated. Once the mutex has
+    // been locked it is ensured that the thread is deleted.
+    _mutex.lock();
+    MBED_ASSERT(NULL == _tid);
+    _mutex.unlock();
+
     // Release sem so any other threads joining this thread wake up
     _join_sem.release();
     return osOK;
@@ -325,12 +346,17 @@
     rtos_attach_idle_hook(fptr);
 }
 
+void Thread::attach_terminate_hook(void (*fptr)(osThreadId id)) {
+    terminate_hook = fptr;
+}
+
 Thread::~Thread() {
     // terminate is thread safe
     terminate();
 #ifdef __MBED_CMSIS_RTOS_CM
     if (_dynamic_stack) {
         delete[] (_thread_def.stack_pointer);
+        _thread_def.stack_pointer = (uint32_t*)NULL;
     }
 #endif
 }
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/Thread.h
--- a/rtos/Thread.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/Thread.h	Mon Nov 14 17:14:42 2016 -0600
@@ -24,14 +24,43 @@
 
 #include <stdint.h>
 #include "cmsis_os.h"
-#include "Callback.h"
-#include "toolchain.h"
-#include "Semaphore.h"
-#include "Mutex.h"
+#include "platform/Callback.h"
+#include "platform/toolchain.h"
+#include "rtos/Semaphore.h"
+#include "rtos/Mutex.h"
 
 namespace rtos {
+/** \addtogroup rtos */
+/** @{*/
 
-/** The Thread class allow defining, creating, and controlling thread functions in the system. */
+/** The Thread class allow defining, creating, and controlling thread functions in the system.
+ *
+ *  Example:
+ *  @code
+ *  #include "mbed.h"
+ *  #include "rtos.h"
+ *
+ *  Thread thread;
+ *  DigitalOut led1(LED1);
+ *  volatile bool running = true;
+ *
+ *  // Blink function toggles the led in a long running loop
+ *  void blink(DigitalOut *led) {
+ *      while (running) {
+ *          *led = !*led;
+ *          Thread::wait(1000);
+ *      }
+ *  }
+ *
+ *  // Spawns a thread to run blink for 5 seconds
+ *  int main() {
+ *      thread.start(led1, blink);
+ *      Thread::wait(5000);
+ *      running = false;
+ *      thread.join();
+ *  }
+ *  @endcode
+ */
 class Thread {
 public:
     /** Allocate a new thread without starting execution
@@ -52,15 +81,20 @@
       @param   stack_size      stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE).
       @param   stack_pointer  pointer to the stack area to be used by this thread (default: NULL).
       @deprecated
-        Thread-spawning constructors hide errors and may lead to complex
-        program state when a thread is declared.
+        Thread-spawning constructors hide errors. Replaced by thread.start(task).
+
+        @code
+        Thread thread(priority, stack_size, stack_pointer);
 
-        The explicit Thread::start member function should be used to spawn
-        a thread.
+        osStatus status = thread.start(task);
+        if (status != osOK) {
+            error("oh no!");
+        }
+        @endcode
     */
     MBED_DEPRECATED_SINCE("mbed-os-5.1",
-        "Thread-spawning constructors hide errors and may lead to complex "
-        "program state when a thread is declared")
+        "Thread-spawning constructors hide errors. "
+        "Replaced by thread.start(task).")
     Thread(mbed::Callback<void()> task,
            osPriority priority=osPriorityNormal,
            uint32_t stack_size=DEFAULT_STACK_SIZE,
@@ -76,21 +110,26 @@
       @param   stack_size      stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE).
       @param   stack_pointer  pointer to the stack area to be used by this thread (default: NULL).
       @deprecated
-        Thread-spawning constructors hide errors and may lead to complex
-        program state when a thread is declared.
+        Thread-spawning constructors hide errors. Replaced by thread.start(callback(task, argument)).
+
+        @code
+        Thread thread(priority, stack_size, stack_pointer);
 
-        The explicit Thread::start member function should be used to spawn
-        a thread.
+        osStatus status = thread.start(callback(task, argument));
+        if (status != osOK) {
+            error("oh no!");
+        }
+        @endcode
     */
     template <typename T>
     MBED_DEPRECATED_SINCE("mbed-os-5.1",
-        "Thread-spawning constructors hide errors and may lead to complex "
-        "program state when a thread is declared")
-    Thread(T *obj, void (T::*method)(),
+        "Thread-spawning constructors hide errors. "
+        "Replaced by thread.start(callback(task, argument)).")
+    Thread(T *argument, void (T::*task)(),
            osPriority priority=osPriorityNormal,
            uint32_t stack_size=DEFAULT_STACK_SIZE,
            unsigned char *stack_pointer=NULL) {
-        constructor(mbed::Callback<void()>(obj, method),
+        constructor(mbed::callback(task, argument),
                     priority, stack_size, stack_pointer);
     }
 
@@ -102,21 +141,26 @@
       @param   stack_size      stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE).
       @param   stack_pointer  pointer to the stack area to be used by this thread (default: NULL).
       @deprecated
-        Thread-spawning constructors hide errors and may lead to complex
-        program state when a thread is declared.
+        Thread-spawning constructors hide errors. Replaced by thread.start(callback(task, argument)).
+
+        @code
+        Thread thread(priority, stack_size, stack_pointer);
 
-        The explicit Thread::start member function should be used to spawn
-        a thread.
+        osStatus status = thread.start(callback(task, argument));
+        if (status != osOK) {
+            error("oh no!");
+        }
+        @endcode
     */
     template <typename T>
     MBED_DEPRECATED_SINCE("mbed-os-5.1",
-        "Thread-spawning constructors hide errors and may lead to complex "
-        "program state when a thread is declared")
-    Thread(T *obj, void (*method)(T *),
+        "Thread-spawning constructors hide errors. "
+        "Replaced by thread.start(callback(task, argument)).")
+    Thread(T *argument, void (*task)(T *),
            osPriority priority=osPriorityNormal,
            uint32_t stack_size=DEFAULT_STACK_SIZE,
            unsigned char *stack_pointer=NULL) {
-        constructor(mbed::Callback<void()>(obj, method),
+        constructor(mbed::callback(task, argument),
                     priority, stack_size, stack_pointer);
     }
 
@@ -128,20 +172,25 @@
       @param   stack_size      stack size (in bytes) requirements for the thread function. (default: DEFAULT_STACK_SIZE).
       @param   stack_pointer  pointer to the stack area to be used by this thread (default: NULL).
       @deprecated
-        Thread-spawning constructors hide errors and may lead to complex
-        program state when a thread is declared.
+        Thread-spawning constructors hide errors. Replaced by thread.start(callback(task, argument)).
+
+        @code
+        Thread thread(priority, stack_size, stack_pointer);
 
-        The explicit Thread::start member function should be used to spawn
-        a thread.
+        osStatus status = thread.start(callback(task, argument));
+        if (status != osOK) {
+            error("oh no!");
+        }
+        @endcode
     */
     MBED_DEPRECATED_SINCE("mbed-os-5.1",
-        "Thread-spawning constructors hide errors and may lead to complex "
-        "program state when a thread is declared")
+        "Thread-spawning constructors hide errors. "
+        "Replaced by thread.start(callback(task, argument)).")
     Thread(void (*task)(void const *argument), void *argument=NULL,
            osPriority priority=osPriorityNormal,
            uint32_t stack_size=DEFAULT_STACK_SIZE,
            unsigned char *stack_pointer=NULL) {
-        constructor(mbed::Callback<void()>(argument, (void (*)(void *))task),
+        constructor(mbed::callback((void (*)(void *))task, argument),
                     priority, stack_size, stack_pointer);
     }
 
@@ -155,10 +204,15 @@
       @param   obj            argument to task
       @param   method         function to be executed by this thread.
       @return  status code that indicates the execution status of the function.
+      @deprecated
+          The start function does not support cv-qualifiers. Replaced by start(callback(obj, method)).
     */
     template <typename T, typename M>
+    MBED_DEPRECATED_SINCE("mbed-os-5.1",
+        "The start function does not support cv-qualifiers. "
+        "Replaced by thread.start(callback(obj, method)).")
     osStatus start(T *obj, M method) {
-        return start(mbed::Callback<void()>(obj, method));
+        return start(mbed::callback(obj, method));
     }
 
     /** Wait for thread to terminate
@@ -268,6 +322,11 @@
     */
     static void attach_idle_hook(void (*fptr)(void));
 
+    /** Attach a function to be called when a task is killed
+      @param   fptr  pointer to the function to be called
+    */
+    static void attach_terminate_hook(void (*fptr)(osThreadId id));
+
     virtual ~Thread();
 
 private:
@@ -292,3 +351,5 @@
 
 }
 #endif
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/rtos.h
--- a/rtos/rtos.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/rtos.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /* mbed Microcontroller Library
  * Copyright (c) 2006-2012 ARM Limited
  *
@@ -22,13 +25,13 @@
 #ifndef RTOS_H
 #define RTOS_H
 
-#include "Thread.h"
-#include "Mutex.h"
-#include "RtosTimer.h"
-#include "Semaphore.h"
-#include "Mail.h"
-#include "MemoryPool.h"
-#include "Queue.h"
+#include "rtos/Thread.h"
+#include "rtos/Mutex.h"
+#include "rtos/RtosTimer.h"
+#include "rtos/Semaphore.h"
+#include "rtos/Mail.h"
+#include "rtos/MemoryPool.h"
+#include "rtos/Queue.h"
 
 using namespace rtos;
 
@@ -37,8 +40,10 @@
 */
 #include "mbed.h"
 
-#if (MBED_LIBRARY_VERSION < 124)
-#error "This version of RTOS requires mbed library version > 123"
+#if (MBED_LIBRARY_VERSION < 122)
+#error "This version of RTOS requires mbed library version > 121"
 #endif
 
 #endif
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/rtos_idle.c
--- a/rtos/rtos_idle.c	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/rtos_idle.c	Mon Nov 14 17:14:42 2016 -0600
@@ -20,7 +20,7 @@
  * SOFTWARE.
  */
 
-#include "rtos_idle.h"
+#include "rtos/rtos_idle.h"
 
 static void default_idle_hook(void)
 {
diff -r b744dfee1cf2 -r 58563e6cba1e rtos/rtos_idle.h
--- a/rtos/rtos_idle.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtos/rtos_idle.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /* mbed Microcontroller Library
  * Copyright (c) 2006-2012 ARM Limited
  *
@@ -35,3 +38,5 @@
 #endif
 
 #endif
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_ARM7/RTX_CM_lib.h
--- a/rtx/TARGET_ARM7/RTX_CM_lib.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_ARM7/RTX_CM_lib.h	Mon Nov 14 17:14:42 2016 -0600
@@ -198,15 +198,8 @@
 extern void pre_main (void);
 osThreadDef_t os_thread_def_main = {(os_pthread)pre_main, osPriorityNormal, 0, NULL};
 
-// This define should be probably moved to the CMSIS layer
-
-#if defined(TARGET_LPC2460)
-extern unsigned char     __usr_stack_top__[];
-#define INITIAL_SP            (__usr_stack_top__)
-
-#else
-#error "no target defined"
-
+#ifndef INITIAL_SP
+ #error "no target defined"
 #endif
 
 #ifdef __CC_ARM
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_ARM7/RTX_Conf_CM.c
--- a/rtx/TARGET_ARM7/RTX_Conf_CM.c	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_ARM7/RTX_Conf_CM.c	Mon Nov 14 17:14:42 2016 -0600
@@ -39,6 +39,9 @@
  *      RTX User configuration part BEGIN
  *---------------------------------------------------------------------------*/
 
+// Include per-target RTX config file
+#include "mbed_rtx.h"
+
 //-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
 //
 // <h>Thread Configuration
@@ -49,20 +52,12 @@
 //       counting "main", but not counting "osTimerThread"
 //   <i> Default: 6
 #ifndef OS_TASKCNT
-#  if  defined(TARGET_LPC2368) || defined(TARGET_LPC2460)
-#    define OS_TASKCNT         14
-#  else
-#    error "no target defined"
-#  endif
+ #error "no target defined"
 #endif
 
 //   <o>Scheduler (+ interrupts) stack size [bytes] <64-4096:8><#/4>
 #ifndef OS_SCHEDULERSTKSIZE
-#  if  defined(TARGET_LPC2368)  ||  defined(TARGET_LPC2460)
-#      define OS_SCHEDULERSTKSIZE    (136*2)
-#  else
-#    error "no target defined"
-#  endif
+ #error "no target defined"
 #endif
 
 //   <o>Idle stack size [bytes] <64-4096:8><#/4>
@@ -101,15 +96,7 @@
 //   <i> Defines the timer clock value.
 //   <i> Default: 6000000  (6MHz)
 #ifndef OS_CLOCK
-#  if defined(TARGET_LPC2368)
-#    define OS_CLOCK       96000000
-
-#  elif defined(TARGET_LPC2460)
-#    define OS_CLOCK       72000000
-
-#  else
-#    error "no target defined"
-#  endif
+ #error "no target defined"
 #endif
 
 //   <o>Timer tick value [us] <1-1000000>
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_A/RTX_CM_lib.h
--- a/rtx/TARGET_CORTEX_A/RTX_CM_lib.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_A/RTX_CM_lib.h	Mon Nov 14 17:14:42 2016 -0600
@@ -51,7 +51,7 @@
 #define _declare_box(pool,size,cnt)  uint32_t pool[(((size)+3)/4)*(cnt) + 3]
 #define _declare_box8(pool,size,cnt) uint64_t pool[(((size)+7)/8)*(cnt) + 2]
 
-#define OS_TCB_SIZE     60
+#define OS_TCB_SIZE     64
 #define OS_TMR_SIZE     8
 
 #if defined (__CC_ARM) && !defined (__MICROLIB)
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_A/RTX_Conf_CA.c
--- a/rtx/TARGET_CORTEX_A/RTX_Conf_CA.c	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_A/RTX_Conf_CA.c	Mon Nov 14 17:14:42 2016 -0600
@@ -38,10 +38,8 @@
  *      RTX User configuration part BEGIN
  *---------------------------------------------------------------------------*/
 
-#if defined(MBED_RTOS_SINGLE_THREAD)
-#define OS_TASKCNT  1
-#define OS_TIMERS   0
-#endif
+// Include per-target RTX config file
+#include "mbed_rtx.h"
 
 //-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
 //
@@ -122,11 +120,7 @@
 //   <i> Defines the timer clock value.
 //   <i> Default: 12000000  (12MHz)
 #ifndef OS_CLOCK
-#  if defined(TARGET_RZ_A1H) || defined(TARGET_VK_RZ_A1H)
- #define OS_CLOCK       12000000
-#  else
-#    error "no target defined"
-#  endif
+ #error "no target defined"
 #endif
 
 //   <o>Timer tick value [us] <1-1000000>
@@ -320,6 +314,14 @@
   for (;;);
 }
 
+/*----------------------------------------------------------------------------
+ *      RTX Hooks
+ *---------------------------------------------------------------------------*/
+extern void thread_terminate_hook(osThreadId id);
+
+void sysThreadTerminate(osThreadId id) {
+    thread_terminate_hook(id);
+}
 
 /*----------------------------------------------------------------------------
  *      RTX Configuration Functions
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_A/cmsis_os.h
--- a/rtx/TARGET_CORTEX_A/cmsis_os.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_A/cmsis_os.h	Mon Nov 14 17:14:42 2016 -0600
@@ -160,6 +160,7 @@
 #define osFeature_Semaphore    65535   ///< maximum count for \ref osSemaphoreCreate function
 #define osFeature_Wait         0       ///< osWait function: 1=available, 0=not available
 #define osFeature_SysTick      1       ///< osKernelSysTick functions: 1=available, 0=not available
+#define osFeature_ThreadEnum   1       ///< Thread enumeration available
 
 #if defined (__CC_ARM)
 #define os_InRegs __value_in_regs      // Compiler specific: force struct in registers
@@ -223,6 +224,16 @@
   osTimerPeriodic         =     1        ///< repeating timer
 } os_timer_type;
 
+typedef enum {
+  osThreadInfoState,
+  osThreadInfoStackSize,
+  osThreadInfoStackMax,
+  osThreadInfoEntry,
+  osThreadInfoArg,
+
+  osThreadInfo_reserved   =  0x7FFFFFFF  ///< prevent from enum down-size compiler optimization.
+} osThreadInfo;
+
 /// Entry point of a thread.
 /// \note MUST REMAIN UNCHANGED: \b os_pthread shall be consistent in every CMSIS-RTOS.
 typedef void (*os_pthread) (void const *argument);
@@ -261,6 +272,8 @@
 /// \note CAN BE CHANGED: \b os_mailQ_cb is implementation specific in every CMSIS-RTOS.
 typedef struct os_mailQ_cb *osMailQId;
 
+/// Thread enumeration ID identifies the enumeration (pointer to a thread enumeration control block).
+typedef uint32_t *osThreadEnumId;
 
 /// Thread Definition structure contains startup information of a thread.
 /// \note CAN BE CHANGED: \b os_thread_def is implementation specific in every CMSIS-RTOS.
@@ -448,6 +461,13 @@
 uint8_t osThreadGetState (osThreadId thread_id);
 #endif
 
+/// Get into from an active thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
+/// \param[in]     info          information to read.
+/// \return current state of the thread function.
+/// \return requested info that includes the status code.
+os_InRegs osEvent _osThreadGetInfo(osThreadId thread_id, osThreadInfo info);
+
 //  ==== Generic Wait Functions ====
 
 /// Wait for Timeout (Time Delay).
@@ -823,6 +843,26 @@
 #endif  // Mail Queues available
 
 
+//  ==== Thread Enumeration Functions ====
+
+#if (defined (osFeature_ThreadEnum)  &&  (osFeature_ThreadEnum != 0))     // Thread enumeration available
+
+/// Start a thread enumeration.
+/// \return an enumeration ID or NULL on error.
+osThreadEnumId _osThreadsEnumStart(void);
+
+/// Get the next task ID in the enumeration.
+/// \return a thread ID or NULL on if the end of the enumeration has been reached.
+osThreadId _osThreadEnumNext(osThreadEnumId enum_id);
+
+/// Free the enumeration structure.
+/// \param[in]     enum_id       pointer to the enumeration ID that was obtained with \ref _osThreadsEnumStart.
+/// \return status code that indicates the execution status of the function.
+osStatus _osThreadEnumFree(osThreadEnumId enum_id);
+
+#endif  // Thread Enumeration available
+
+
 //  ==== RTX Extensions ====
 
 /// os_suspend: http://www.keil.com/support/man/docs/rlarm/rlarm_os_suspend.htm
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_A/rt_CMSIS.c
--- a/rtx/TARGET_CORTEX_A/rt_CMSIS.c	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_A/rt_CMSIS.c	Mon Nov 14 17:14:42 2016 -0600
@@ -479,6 +479,10 @@
 
 extern U32 IRQNestLevel; /* Indicates whether inside an ISR, and the depth of nesting.  0 = not in ISR. */
 
+// Thread creation and destruction
+osMutexDef(osThreadMutex);
+osMutexId osMutexId_osThreadMutex;
+void sysThreadTerminate(osThreadId id);
 
 // ==== Helper Functions ====
 
@@ -539,6 +543,11 @@
 }
 
 static __inline char __exceptional_mode(void) {
+    // Interrupts disabled
+    if (__get_CPSR() & 0x80) {
+        return 1;
+    }
+
     switch(__get_mode()) {
         case MODE_USR:
         case MODE_SYS:
@@ -596,6 +605,8 @@
     // Create OS Timers resources (Message Queue & Thread)
     osMessageQId_osTimerMessageQ = svcMessageCreate (&os_messageQ_def_osTimerMessageQ, NULL);
     osThreadId_osTimerThread = svcThreadCreate(&os_thread_def_osTimerThread, NULL);
+    // Initialize thread mutex
+    osMutexId_osThreadMutex = osMutexCreate(osMutex(osThreadMutex));
   }
 
   sysThreadError(osOK);
@@ -708,6 +719,7 @@
 SVC_0_1(svcThreadYield,       osStatus,                                      RET_osStatus)
 SVC_2_1(svcThreadSetPriority, osStatus,         osThreadId,      osPriority, RET_osStatus)
 SVC_1_1(svcThreadGetPriority, osPriority,       osThreadId,                  RET_osPriority)
+SVC_2_3(svcThreadGetInfo,    os_InRegs osEvent, osThreadId,    osThreadInfo, RET_osEvent)
 
 // Thread Service Calls
 
@@ -846,6 +858,80 @@
   return (osPriority)(ptcb->prio - 1 + osPriorityIdle);
 }
 
+/// Get info from an active thread
+os_InRegs osEvent_type svcThreadGetInfo (osThreadId thread_id, osThreadInfo info) {
+  P_TCB ptcb;
+  osEvent ret;
+  ret.status = osOK;
+
+  ptcb = rt_tid2ptcb(thread_id);                // Get TCB pointer
+  if (ptcb == NULL) {
+    ret.status = osErrorValue;
+#if defined (__GNUC__) && defined (__ARM_PCS_VFP)
+    osEvent_ret_status;
+    return;
+#else
+    return osEvent_ret_status;
+#endif
+  }
+
+  if (osThreadInfoStackSize == info) {
+    uint32_t size;
+    size = ptcb->priv_stack;
+    if (0 == size) {
+      // This is an OS task - always a fixed size
+      size = os_stackinfo & 0x3FFFF;
+    }
+    ret.value.v = size;
+#if defined (__GNUC__) && defined (__ARM_PCS_VFP)
+    osEvent_ret_value;
+    return;
+#else
+    return osEvent_ret_value;
+#endif
+  }
+
+  if (osThreadInfoStackMax == info) {
+    // Cortex-A RTX does not have stack init so
+    // the maximum stack usage cannot be obtained.
+    ret.status = osErrorResource;
+#if defined (__GNUC__) && defined (__ARM_PCS_VFP)
+    osEvent_ret_status;
+    return;
+#else
+    return osEvent_ret_status;
+#endif
+  }
+
+  if (osThreadInfoEntry == info) {
+    ret.value.p = (void*)ptcb->ptask;
+#if defined (__GNUC__) && defined (__ARM_PCS_VFP)
+    osEvent_ret_value;
+    return;
+#else
+    return osEvent_ret_value;
+#endif
+  }
+
+  if (osThreadInfoArg == info) {
+    ret.value.p = (void*)ptcb->argv;
+#if defined (__GNUC__) && defined (__ARM_PCS_VFP)
+    osEvent_ret_value;
+    return;
+#else
+    return osEvent_ret_value;
+#endif
+  }
+
+  // Unsupported option so return error
+  ret.status = osErrorParameter;
+#if defined (__GNUC__) && defined (__ARM_PCS_VFP)
+    osEvent_ret_status;
+    return;
+#else
+    return osEvent_ret_status;
+#endif
+}
 
 // Thread Public API
 
@@ -856,7 +942,12 @@
     // Privileged and not running
     return   svcThreadCreate(thread_def, argument);
   } else {
-    return __svcThreadCreate(thread_def, argument);
+    osThreadId id;
+    osMutexWait(osMutexId_osThreadMutex, osWaitForever);
+    // Thread mutex must be held when a thread is created or terminated
+    id = __svcThreadCreate(thread_def, argument);
+    osMutexRelease(osMutexId_osThreadMutex);
+    return id;
   }
 }
 
@@ -868,8 +959,14 @@
 
 /// Terminate execution of a thread and remove it from ActiveThreads
 osStatus osThreadTerminate (osThreadId thread_id) {
+  osStatus status;
   if (__exceptional_mode()) return osErrorISR;     // Not allowed in ISR
-  return __svcThreadTerminate(thread_id);
+  osMutexWait(osMutexId_osThreadMutex, osWaitForever);
+  sysThreadTerminate(thread_id);
+  // Thread mutex must be held when a thread is created or terminated
+  status = __svcThreadTerminate(thread_id);
+  osMutexRelease(osMutexId_osThreadMutex);
+  return status;
 }
 
 /// Pass control to next thread that is in state READY
@@ -893,7 +990,14 @@
 /// INTERNAL - Not Public
 /// Auto Terminate Thread on exit (used implicitly when thread exists)
 __NO_RETURN void osThreadExit (void) {
-  __svcThreadTerminate(__svcThreadGetId());
+  osThreadId id;
+  // Thread mutex must be held when a thread is created or terminated
+  // Note - the mutex will be released automatically by the os when
+  //        the thread is terminated
+  osMutexWait(osMutexId_osThreadMutex, osWaitForever);
+  id = __svcThreadGetId();
+  sysThreadTerminate(id);
+  __svcThreadTerminate(id);
   for (;;);                                     // Should never come here
 }
 
@@ -911,6 +1015,48 @@
 }
 #endif
 
+/// Get the requested info from the specified active thread
+os_InRegs osEvent _osThreadGetInfo(osThreadId thread_id, osThreadInfo info) {
+  osEvent ret;
+  if (__exceptional_mode()) {
+    ret.status = osErrorISR;
+    return ret;                                 // Not allowed in ISR
+  }
+  return __svcThreadGetInfo(thread_id, info);
+}
+
+osThreadEnumId _osThreadsEnumStart() {
+  static uint32_t thread_enum_index;
+  osMutexWait(osMutexId_osThreadMutex, osWaitForever);
+  thread_enum_index = 0;
+  return &thread_enum_index;
+}
+
+osThreadId _osThreadEnumNext(osThreadEnumId enum_id) {
+  uint32_t i;
+  osThreadId id = NULL;
+  uint32_t *index = (uint32_t*)enum_id;
+  for (i = *index; i < os_maxtaskrun; i++) {
+    if (os_active_TCB[i] != NULL) {
+      id = (osThreadId)os_active_TCB[i];
+      break;
+    }
+  }
+  if (i == os_maxtaskrun) {
+    // Include the idle task at the end of the enumeration
+    id = &os_idle_TCB;
+  }
+  *index = i + 1;
+  return id;
+}
+
+osStatus _osThreadEnumFree(osThreadEnumId enum_id) {
+  uint32_t *index = (uint32_t*)enum_id;
+  *index = 0;
+  osMutexRelease(osMutexId_osThreadMutex);
+  return osOK;
+}
+
 // ==== Generic Wait Functions ====
 
 // Generic Wait Service Calls declarations
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_A/rt_TypeDef.h
--- a/rtx/TARGET_CORTEX_A/rt_TypeDef.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_A/rt_TypeDef.h	Mon Nov 14 17:14:42 2016 -0600
@@ -85,6 +85,7 @@
 
   /* Task entry point used for uVision debugger                              */
   FUNCP  ptask;                   /* Task entry address                      */
+  void   *argv;                   /* Task argument                           */
 } *P_TCB;
 #define TCB_TID          3        /* 'task id' offset                        */
 #define TCB_STACKF      37        /* 'stack_frame' offset                    */
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/HAL_CM.c
--- a/rtx/TARGET_CORTEX_M/HAL_CM.c	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/HAL_CM.c	Mon Nov 14 17:14:42 2016 -0600
@@ -90,6 +90,32 @@
   /* Task entry point. */
   p_TCB->ptask = task_body;
 
+
+#ifdef __MBED_CMSIS_RTOS_CM
+  /* Set a magic word for checking of stack overflow.
+   For the main thread (ID: MAIN_THREAD_ID) the stack is in a memory area shared with the
+   heap, therefore the last word of the stack is a moving target.
+   We want to do stack/heap collision detection instead.
+   Similar applies to stack filling for the magic pattern.
+  */
+  if (p_TCB->task_id != MAIN_THREAD_ID) {
+    p_TCB->stack[0] = MAGIC_WORD;
+
+    /* Initialize stack with magic pattern. */
+    if (os_stackinfo & 0x10000000U) {
+      if (size > (16U+1U)) {
+        for (i = ((size - 16U)/2U) - 1U; i; i--) {
+          stk -= 2U;
+          stk[1] = MAGIC_PATTERN;
+          stk[0] = MAGIC_PATTERN;
+        }
+        if (--stk > p_TCB->stack) {
+          *stk = MAGIC_PATTERN;
+        }
+      }
+    }
+  }
+#else
   /* Initialize stack with magic pattern. */
   if (os_stackinfo & 0x10000000U) {
     if (size > (16U+1U)) {
@@ -106,6 +132,7 @@
 
   /* Set a magic word for checking of stack overflow. */
   p_TCB->stack[0] = MAGIC_WORD;
+#endif
 }
 
 
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/RTX_CM_lib.h
--- a/rtx/TARGET_CORTEX_M/RTX_CM_lib.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/RTX_CM_lib.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -52,7 +55,7 @@
 #define _declare_box(pool,size,cnt)  uint32_t pool[(((size)+3)/4)*(cnt) + 3]
 #define _declare_box8(pool,size,cnt) uint64_t pool[(((size)+7)/8)*(cnt) + 2]
 
-#define OS_TCB_SIZE     60
+#define OS_TCB_SIZE     64
 #define OS_TMR_SIZE     8
 
 typedef void    *OS_ID;
@@ -350,347 +353,43 @@
 
 /* Main Thread definition */
 extern void pre_main (void);
-
-#if defined(TARGET_MCU_NRF51822) || defined(TARGET_MCU_NRF52832) || defined (TARGET_STM32F334R8) ||\
-    defined(TARGET_STM32F302R8) || defined(TARGET_STM32F303K8) || defined (TARGET_STM32F334C8)
-static uint32_t thread_stack_main[DEFAULT_STACK_SIZE / sizeof(uint32_t)];
-#else
-static uint32_t thread_stack_main[DEFAULT_STACK_SIZE * 2 / sizeof(uint32_t)];
-#endif
-osThreadDef_t os_thread_def_main = {(os_pthread)pre_main, osPriorityNormal, 1U, sizeof(thread_stack_main), thread_stack_main};
+osThreadDef_t os_thread_def_main = {(os_pthread)pre_main, osPriorityNormal, 1U, 0U, NULL};
 
-/*
- * IAR Default Memory layout notes:
- * -Heap defined by "HEAP" region in .icf file
- * -Interrupt stack defined by "CSTACK" region in .icf file
- * -Value INITIAL_SP is ignored
- *
- * IAR Custom Memory layout notes:
- * -There is no custom layout available for IAR - everything must be defined in
- *      the .icf file and use the default layout
- *
- *
- * GCC Default Memory layout notes:
- * -Block of memory from symbol __end__ to define INITIAL_SP used to setup interrupt
- *      stack and heap in the function set_stack_heap()
- * -ISR_STACK_SIZE can be overridden to be larger or smaller
- *
- * GCC Custom Memory layout notes:
- * -Heap can be explicitly placed by defining both HEAP_START and HEAP_SIZE
- * -Interrupt stack can be explicitly placed by defining both ISR_STACK_START and ISR_STACK_SIZE
- *
- *
- * ARM Memory layout
- * -Block of memory from end of region "RW_IRAM1" to define INITIAL_SP used to setup interrupt
- *      stack and heap in the function set_stack_heap()
- * -ISR_STACK_SIZE can be overridden to be larger or smaller
- *
- * ARM Custom Memory layout notes:
- * -Heap can be explicitly placed by defining both HEAP_START and HEAP_SIZE
- * -Interrupt stack can be explicitly placed by defining both ISR_STACK_START and ISR_STACK_SIZE
- *
- */
-
-
-// This define should be probably moved to the CMSIS layer
-#if   defined(TARGET_LPC1768)
-#define INITIAL_SP            (0x10008000UL)
-
-#elif defined(TARGET_LPC11U24)
-#define INITIAL_SP            (0x10002000UL)
-
-#elif defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPCCAPPUCCINO)
-#define INITIAL_SP            (0x10002000UL)
-
-#elif defined(TARGET_LPC1114)
-#define INITIAL_SP            (0x10001000UL)
-
-#elif defined(TARGET_LPC812)
-#define INITIAL_SP            (0x10001000UL)
-
-#elif defined(TARGET_LPC824) || defined(TARGET_SSCI824)
-#define INITIAL_SP            (0x10002000UL)
-
-#elif defined(TARGET_KL25Z)
-#define INITIAL_SP            (0x20003000UL)
-
-#elif defined(TARGET_KL26Z)
-#define INITIAL_SP            (0x20003000UL)
-
-#elif defined(TARGET_KL27Z)
-#define INITIAL_SP            (0x20003000UL)
-
-#elif defined(TARGET_K64F)
-#define INITIAL_SP            (0x20030000UL)
-
-#if defined(__CC_ARM) || defined(__GNUC__)
-#define ISR_STACK_SIZE        (0x1000)
+#ifdef __CC_ARM
+#if defined(TARGET_NUMAKER_PFM_NUC472)
+extern uint32_t          Image$$ARM_LIB_HEAP$$Base[];
+#define HEAP_START      ((uint32_t) Image$$ARM_LIB_HEAP$$Base)
+#else
+extern uint32_t          Image$$RW_IRAM1$$ZI$$Limit[];
+#define HEAP_START      (Image$$RW_IRAM1$$ZI$$Limit)
+#endif
+#elif defined(__GNUC__)
+extern uint32_t          __end__[];
+#define HEAP_START      (__end__)
+#elif defined(__ICCARM__)
+#pragma section="HEAP"
+#define HEAP_END  (void *)__section_end("HEAP")
 #endif
 
-#elif defined(TARGET_K66F)
-#define INITIAL_SP            (0x20030000UL)
-
-#elif defined(TARGET_K22F)
-#define INITIAL_SP            (0x20010000UL)
-
-#elif defined(TARGET_KL46Z)
-#define INITIAL_SP            (0x20006000UL)
-
-#elif defined(TARGET_KL43Z)
-#define INITIAL_SP            (0x20006000UL)
-
-#elif defined(TARGET_KL05Z)
-#define INITIAL_SP            (0x20000C00UL)
-
-#elif defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM)
-#define INITIAL_SP            (0x10010000UL)
-
-#elif defined(TARGET_LPC4330)
-#define INITIAL_SP            (0x10008000UL)
-
-#elif defined(TARGET_LPC4337)
-#define INITIAL_SP            (0x10008000UL)
-
-#elif defined(TARGET_LPC1347)
-#define INITIAL_SP            (0x10002000UL)
-
-#elif defined(TARGET_STM32F100RB) || defined(TARGET_STM32F051R8)
-#define INITIAL_SP            (0x20002000UL)
-
-#elif defined(TARGET_DISCO_F303VC)
-#define INITIAL_SP            (0x2000A000UL)
-
-#elif defined(TARGET_STM32F407) || defined(TARGET_F407VG)
-#define INITIAL_SP            (0x20020000UL)
-
-#elif defined(TARGET_STM32F401RE)
-#define INITIAL_SP            (0x20018000UL)
-
-#elif defined(TARGET_LPC1549)
-#define INITIAL_SP            (0x02009000UL)
-
-#elif defined(TARGET_LPC11U68)
-#define INITIAL_SP            (0x10008000UL)
-
-#elif defined(TARGET_STM32F411RE)
-#define INITIAL_SP            (0x20020000UL)
-
-#elif defined(TARGET_STM32F207ZG)
-#define INITIAL_SP            (0x20020000UL)
-
-#elif defined(TARGET_STM32F410RB)
-#define INITIAL_SP            (0x20008000UL)
-
-#elif defined(TARGET_STM32F103RB) || defined(TARGET_STM32L073RZ)
-#define INITIAL_SP            (0x20005000UL)
-
-#elif defined(TARGET_STM32F302R8)
-#define INITIAL_SP            (0x20004000UL)
-
-#elif  defined(TARGET_STM32F334R8)
-#define INITIAL_SP            (0x20003000UL)
-
-#elif  defined(TARGET_STM32F334C8)
-#define INITIAL_SP            (0x20003000UL)
-
-#elif  defined(TARGET_STM32F405RG)
-#define INITIAL_SP            (0x20020000UL)
-
-#elif defined(TARGET_STM32F429ZI)
-#define INITIAL_SP            (0x20030000UL)
-
-#elif defined(TARGET_STM32L031K6) || defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8)
-#define INITIAL_SP            (0x20002000UL)
-
-#elif defined(TARGET_STM32F072RB)
-#define INITIAL_SP            (0x20004000UL)
-
-#elif defined(TARGET_STM32F091RC)
-#define INITIAL_SP            (0x20008000UL)
-
-#elif defined(TARGET_STM32F401VC)
-#define INITIAL_SP            (0x20010000UL)
-
-#elif defined(TARGET_STM32F303RE)
-#define INITIAL_SP            (0x20010000UL)
-
-#elif defined(TARGET_STM32F303K8)
-#define INITIAL_SP            (0x20003000UL)
-
-#elif (defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG))
-#define INITIAL_SP            (0x20050000UL)
-
-#elif defined(TARGET_MAX32610) || defined(TARGET_MAX32600) || defined(TARGET_MAX32620)
-#define INITIAL_SP            (0x20008000UL)
-
-#elif defined(TARGET_TEENSY3_1)
-#define INITIAL_SP            (0x20008000UL)
-
-#elif defined(TARGET_STM32L152RE)
-#define INITIAL_SP            (0x20014000UL)
-
-#elif defined(TARGET_NZ32_SC151)
-#define INITIAL_SP            (0x20008000UL)
-
-#elif defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE) || defined(TARGET_STM32F446ZE)
-#define INITIAL_SP            (0x20020000UL)
-
-#elif defined(TARGET_STM32F070RB) || defined(TARGET_STM32F030R8)
-#define INITIAL_SP            (0x20002000UL)
-
-#elif defined(TARGET_STM32L432KC)
-#define INITIAL_SP            (0x2000C000UL)
-
-#elif defined(TARGET_STM32L476VG)
-#define INITIAL_SP            (0x20018000UL)
-
-#elif defined(TARGET_STM32L476RG)
-#define INITIAL_SP            (0x20018000UL)
-
-#elif defined(TARGET_STM32F469NI)
-#define INITIAL_SP            (0x20050000UL)
-
-#elif defined(TARGET_STM32L152RC)
-#define INITIAL_SP            (0x20008000UL)
-
-#elif defined(TARGET_EFM32GG_STK3700) || defined(TARGET_BEETLE)
-#define INITIAL_SP            (0x20020000UL)
-
-#elif defined(TARGET_EFM32HG_STK3400)
-#define INITIAL_SP            (0x20002000UL)
+void set_main_stack(void) {
+#if defined(TARGET_NUMAKER_PFM_NUC472)
+    // Scheduler stack: OS_MAINSTKSIZE words
+    // Main thread stack: Reserved stack size - OS_MAINSTKSIZE words
+    os_thread_def_main.stack_pointer = (uint32_t *) FINAL_SP;
+    os_thread_def_main.stacksize = (uint32_t) INITIAL_SP - (uint32_t) FINAL_SP - OS_MAINSTKSIZE * 4;
+#else
+#if defined(__ICCARM__)
+    /* For IAR heap is defined  .icf file */
+    uint32_t main_stack_size = ((uint32_t)INITIAL_SP - (uint32_t)HEAP_END) - interrupt_stack_size;
+#else
+    /* For ARM , uARM, or GCC_ARM , heap can grow and reach main stack */
+#endif
+    // That is the bottom of the main stack block: no collision detection
+    os_thread_def_main.stack_pointer = HEAP_START;
 
-#elif defined(TARGET_EFM32LG_STK3600) || defined(TARGET_EFM32WG_STK3800) || defined(TARGET_EFM32PG_STK3401)
-#define INITIAL_SP            (0x20008000UL)
-
-#elif defined(TARGET_MCU_NORDIC_32K)
-#define INITIAL_SP            (0x20008000UL)
-
-#elif defined(TARGET_MCU_NORDIC_16K)
-#define INITIAL_SP            (0x20004000UL)
-
-#elif defined(TARGET_MCU_NRF52832)
-#define INITIAL_SP            (0x20010000UL)
-
-#elif (defined(TARGET_STM32F767ZI))
-#define INITIAL_SP            (0x20080000UL)
-
-#elif defined(TARGET_NUMAKER_PFM_NUC472)
-#   if defined(__CC_ARM)
-extern uint32_t                 Image$$ARM_LIB_HEAP$$Base[];
-extern uint32_t                 Image$$ARM_LIB_HEAP$$Length[];
-extern uint32_t                 Image$$ARM_LIB_STACK$$ZI$$Base[];
-extern uint32_t                 Image$$ARM_LIB_STACK$$ZI$$Length[];
-#define HEAP_START              ((unsigned char*) Image$$ARM_LIB_HEAP$$Base)
-#define HEAP_SIZE               ((uint32_t) Image$$ARM_LIB_HEAP$$Length)
-#define ISR_STACK_START         ((unsigned char*)Image$$ARM_LIB_STACK$$ZI$$Base)
-#define ISR_STACK_SIZE          ((uint32_t)Image$$ARM_LIB_STACK$$ZI$$Length)
-#   elif defined(__GNUC__)
-extern uint32_t	                __StackTop[];
-extern uint32_t	                __StackLimit[];
-extern uint32_t                 __end__[];
-extern uint32_t                 __HeapLimit[];
-#define HEAP_START              ((unsigned char*)__end__)
-#define HEAP_SIZE               ((uint32_t)((uint32_t)__HeapLimit - (uint32_t)HEAP_START))
-#define ISR_STACK_START         ((unsigned char*)__StackLimit)
-#define ISR_STACK_SIZE          ((uint32_t)((uint32_t)__StackTop - (uint32_t)__StackLimit))
-#   elif defined(__ICCARM__)
-/* No region declarations needed */
-#   else
-#error "no toolchain defined"
-#   endif
-
-#elif defined(TARGET_NCS36510)
-#define INITIAL_SP            (0x40000000UL)
-
-#else
-#error "no target defined"
-
-#endif
-
-extern unsigned char *mbed_heap_start;
-extern uint32_t mbed_heap_size;
-
-unsigned char *mbed_stack_isr_start = 0;
-uint32_t mbed_stack_isr_size = 0;
-
-/*
- * Sanity check values
- */
-#if defined(__ICCARM__) &&                                  \
-    (defined(HEAP_START) || defined(HEAP_SIZE) ||           \
-     defined(ISR_STACK_START) && defined(ISR_STACK_SIZE))
-    #error "No custom layout allowed for IAR. Use .icf file instead"
-#endif
-#if defined(HEAP_START) && !defined(HEAP_SIZE)
-    #error "HEAP_SIZE must be defined if HEAP_START is defined"
+    // Leave OS_MAINSTKSIZE words for the scheduler and interrupts
+    os_thread_def_main.stacksize = (INITIAL_SP - (unsigned int)HEAP_START) - (OS_MAINSTKSIZE * 4);
 #endif
-#if defined(ISR_STACK_START) && !defined(ISR_STACK_SIZE)
-    #error "ISR_STACK_SIZE must be defined if ISR_STACK_START is defined"
-#endif
-#if defined(HEAP_SIZE) && !defined(HEAP_START)
-    #error "HEAP_START must be defined if HEAP_SIZE is defined"
-#endif
-
-/* Interrupt stack and heap always defined for IAR
- * Main thread defined here
- */
-#if defined(__ICCARM__)
-    #pragma section="CSTACK"
-    #pragma section="HEAP"
-    #define HEAP_START          ((unsigned char*)__section_begin("HEAP"))
-    #define HEAP_SIZE           ((uint32_t)__section_size("HEAP"))
-    #define ISR_STACK_START     ((unsigned char*)__section_begin("CSTACK"))
-    #define ISR_STACK_SIZE      ((uint32_t)__section_size("CSTACK"))
-#endif
-
-/* Define heap region if it has not been defined already */
-#if !defined(HEAP_START)
-    #if defined(__ICCARM__)
-        #error "Heap should already be defined for IAR"
-    #elif defined(__CC_ARM)
-        extern uint32_t          Image$$RW_IRAM1$$ZI$$Limit[];
-        #define HEAP_START      ((unsigned char*)Image$$RW_IRAM1$$ZI$$Limit)
-        #define HEAP_SIZE       ((uint32_t)((uint32_t)INITIAL_SP - (uint32_t)HEAP_START))
-    #elif defined(__GNUC__)
-        extern uint32_t         __end__[];
-        #define HEAP_START      ((unsigned char*)__end__)
-        #define HEAP_SIZE       ((uint32_t)((uint32_t)INITIAL_SP - (uint32_t)HEAP_START))
-    #endif
-#endif
-
-/* Define stack sizes if they haven't been set already */
-#if !defined(ISR_STACK_SIZE)
-    #define ISR_STACK_SIZE ((uint32_t)OS_MAINSTKSIZE * 4)
-#endif
-
-/*
- * set_stack_heap purpose is to set the following variables:
- * -mbed_heap_start
- * -mbed_heap_size
- * -mbed_stack_isr_start
- * -mbed_stack_isr_size
- *
- * Along with setting up os_thread_def_main
- */
-void set_stack_heap(void) {
-
-    unsigned char *free_start = HEAP_START;
-    uint32_t free_size = HEAP_SIZE;
-
-#ifdef ISR_STACK_START
-    /* Interrupt stack explicitly specified */
-    mbed_stack_isr_size = ISR_STACK_SIZE;
-    mbed_stack_isr_start = ISR_STACK_START;
-#else
-    /* Interrupt stack -  reserve space at the end of the free block */
-    mbed_stack_isr_size = ISR_STACK_SIZE;
-    mbed_stack_isr_start = free_start + free_size - mbed_stack_isr_size;
-    free_size -= mbed_stack_isr_size;
-#endif
-
-    /* Heap - everything else */
-    mbed_heap_size = free_size;
-    mbed_heap_start = free_start;
 }
 
 #if defined (__CC_ARM)
@@ -704,7 +403,7 @@
 void _main_init (void) {
   osKernelInitialize();
 #ifdef __MBED_CMSIS_RTOS_CM
-  set_stack_heap();
+  set_main_stack();
 #endif
   osThreadCreate(&os_thread_def_main, NULL);
   osKernelStart();
@@ -726,12 +425,15 @@
 
 #else
 
+void * armcc_heap_base;
+void * armcc_heap_top;
+
 int main(void);
 
 void pre_main (void)
 {
     singleton_mutex_id = osMutexCreate(osMutex(singleton_mutex));
-    __rt_lib_init((unsigned)mbed_heap_start, (unsigned)(mbed_heap_start + mbed_heap_size));
+    __rt_lib_init((unsigned)armcc_heap_base, (unsigned)armcc_heap_top);
     main();
 }
 
@@ -746,10 +448,13 @@
 __asm void __rt_entry (void) {
 
   IMPORT  __user_setup_stackheap
+  IMPORT  armcc_heap_base
+  IMPORT  armcc_heap_top
+  IMPORT  _platform_post_stackheap_init
   IMPORT  os_thread_def_main
   IMPORT  osKernelInitialize
 #ifdef __MBED_CMSIS_RTOS_CM
-  IMPORT  set_stack_heap
+  IMPORT  set_main_stack
 #endif
   IMPORT  osKernelStart
   IMPORT  osThreadCreate
@@ -763,12 +468,14 @@
    * ARM Compiler ARM C and C++ Libraries and Floating-Point Support User Guide
    */
   BL      __user_setup_stackheap
-  /* Ignore return value of __user_setup_stackheap since
-   * this will be setup by set_stack_heap
-   */
+  LDR     R3,=armcc_heap_base
+  LDR     R4,=armcc_heap_top
+  STR     R0,[R3]
+  STR     R2,[R4]
+  BL      _platform_post_stackheap_init
   BL      osKernelInitialize
 #ifdef __MBED_CMSIS_RTOS_CM
-  BL      set_stack_heap
+  BL      set_main_stack
 #endif
   LDR     R0,=os_thread_def_main
   MOVS    R1,#0
@@ -798,7 +505,6 @@
     singleton_mutex_id = osMutexCreate(osMutex(singleton_mutex));
     malloc_mutex_id = osMutexCreate(osMutex(malloc_mutex));
     env_mutex_id = osMutexCreate(osMutex(env_mutex));
-    atexit(__libc_fini_array);
     __libc_init_array();
     main(0, NULL);
 }
@@ -807,7 +513,7 @@
   __asm (
     "bl   osKernelInitialize\n"
 #ifdef __MBED_CMSIS_RTOS_CM
-    "bl   set_stack_heap\n"
+    "bl   set_main_stack\n"
 #endif
     "ldr  r0,=os_thread_def_main\n"
     "movs r1,#0\n"
@@ -884,7 +590,7 @@
 #endif
   osKernelInitialize();
 #ifdef __MBED_CMSIS_RTOS_CM
-  set_stack_heap();
+  set_main_stack();
 #endif
   osThreadCreate(&os_thread_def_main, NULL);
   osKernelStart();
@@ -898,3 +604,5 @@
 /*----------------------------------------------------------------------------
  * end of file
  *---------------------------------------------------------------------------*/
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/RTX_Conf_CM.c
--- a/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c	Mon Nov 14 17:14:42 2016 -0600
@@ -39,6 +39,9 @@
  *      RTX User configuration part BEGIN
  *---------------------------------------------------------------------------*/
 
+// Include per-target RTX config file
+#include "mbed_rtx.h"
+
 //-------- <<< Use Configuration Wizard in Context Menu >>> -----------------
 //
 // <h>Thread Configuration
@@ -48,23 +51,7 @@
 //   <i> Defines max. number of user threads that will run at the same time.
 //   <i> Default: 6
 #ifndef OS_TASKCNT
-#  if   defined(TARGET_LPC1768) || defined(TARGET_LPC2368)   || defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM) || defined(TARGET_LPC4330) || defined(TARGET_LPC4337) || defined(TARGET_LPC1347) || defined(TARGET_K64F) || defined(TARGET_K66F)|| defined(TARGET_STM32F401RE)\
-   || defined(TARGET_STM32F410RB) || defined(TARGET_KL46Z) || defined(TARGET_KL43Z)  || defined(TARGET_STM32F407) || defined(TARGET_F407VG)  || defined(TARGET_STM32F303VC) || defined(TARGET_LPC1549) || defined(TARGET_LPC11U68) \
-   || defined(TARGET_STM32F411RE) || defined(TARGET_STM32F207ZG) || defined(TARGET_STM32F405RG) || defined(TARGET_K22F) || defined(TARGET_STM32F429ZI) || defined(TARGET_STM32F401VC) || defined(TARGET_MAX32610) || defined(TARGET_MAX32600) || defined(TARGET_MAX32620) || defined(TARGET_TEENSY3_1) \
-   || defined(TARGET_STM32L152RE) || defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE) || defined(TARGET_STM32F446ZE) || defined(TARGET_STM32L432KC) || defined(TARGET_STM32L476VG) || defined(TARGET_STM32L476RG) || defined(TARGET_STM32F469NI) || defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG) || defined(TARGET_STM32L152RC) \
-   || defined(TARGET_EFM32GG_STK3700) || defined(TARGET_EFM32WG_STK3800) || defined(TARGET_EFM32LG_STK3600) || defined(TARGET_EFM32PG_STK3401) || defined(TARGET_STM32F767ZI) \
-   || defined(TARGET_NUMAKER_PFM_NUC472) || defined(TARGET_NCS36510)
-#    define OS_TASKCNT         14
-#  elif defined(TARGET_LPC11U24) || defined(TARGET_STM32F303RE) || defined(TARGET_STM32F303K8) || defined(TARGET_LPC11U35_401)  || defined(TARGET_LPC11U35_501) || defined(TARGET_LPCCAPPUCCINO) || defined(TARGET_LPC1114) \
-   || defined(TARGET_LPC812)   || defined(TARGET_KL25Z)         || defined(TARGET_KL26Z)       || defined(TARGET_KL27Z)         || defined(TARGET_KL05Z)        || defined(TARGET_STM32F100RB)  || defined(TARGET_STM32F051R8) \
-   || defined(TARGET_STM32F103RB) || defined(TARGET_LPC824) || defined(TARGET_STM32F302R8) || defined(TARGET_STM32F334R8) || defined(TARGET_STM32F334C8) \
-   || defined(TARGET_STM32L031K6) || defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8) || defined(TARGET_STM32L073RZ) || defined(TARGET_STM32F072RB) || defined(TARGET_STM32F091RC) || defined(TARGET_NZ32_SC151) \
-   || defined(TARGET_SSCI824)  || defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB) \
-   || defined(TARGET_EFM32HG_STK3400) || defined(TARGET_MCU_NRF51822) || defined(TARGET_BEETLE) || defined(TARGET_MCU_NRF52832)
-#    define OS_TASKCNT         6
-#  else
-#    error "no target defined"
-#  endif
+ #error "no target defined"
 #endif
 
 #ifdef __MBED_CMSIS_RTOS_CM
@@ -84,28 +71,7 @@
 
 //   <o>Main Thread stack size [bytes] <64-32768:8><#/4>
 #ifndef OS_MAINSTKSIZE
-#  if   defined(TARGET_LPC1768) || defined(TARGET_LPC2368)   || defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM) || defined(TARGET_LPC4330) || defined(TARGET_LPC4337) || defined(TARGET_LPC1347)  || defined(TARGET_K64F) || defined(TARGET_K66F) ||defined(TARGET_STM32F401RE)\
-   || defined(TARGET_STM32F410RB) || defined(TARGET_KL46Z) || defined(TARGET_KL43Z) || defined(TARGET_STM32F407) || defined(TARGET_F407VG)  || defined(TARGET_STM32F303VC) || defined(TARGET_LPC1549) || defined(TARGET_LPC11U68) \
-   || defined(TARGET_STM32F411RE) || defined(TARGET_STM32F405RG) || defined(TARGET_K22F) || defined(TARGET_STM32F429ZI) || defined(TARGET_STM32F401VC) || defined(TARGET_MAX32610) || defined(TARGET_MAX32600) || defined(TARGET_MAX32620) || defined(TARGET_TEENSY3_1) \
-   || defined(TARGET_STM32L152RE) || defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE) || defined(TARGET_STM32F446ZE) || defined(TARGET_STM32L432KC) || defined(TARGET_STM32L476VG) || defined(TARGET_STM32L476RG) || defined(TARGET_STM32F469NI) || defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG) || defined(TARGET_STM32L152RC) \
-   ||defined(TARGET_EFM32GG_STK3700) || defined(TARGET_STM32F767ZI) || defined(TARGET_STM32F207ZG) \
-   || defined(TARGET_NUMAKER_PFM_NUC472) || defined(TARGET_NCS36510)
-#      define OS_MAINSTKSIZE    256
-#  elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11U35_401)  || defined(TARGET_LPC11U35_501) || defined(TARGET_LPCCAPPUCCINO)  || defined(TARGET_LPC1114) \
-   || defined(TARGET_LPC812)   || defined(TARGET_KL25Z)         || defined(TARGET_KL26Z)        || defined(TARGET_KL27Z)        || defined(TARGET_KL05Z)        || defined(TARGET_STM32F100RB)  || defined(TARGET_STM32F051R8) \
-   || defined(TARGET_STM32F103RB) || defined(TARGET_LPC824) || defined(TARGET_STM32F302R8) || defined(TARGET_STM32F072RB) || defined(TARGET_STM32F091RC) || defined(TARGET_NZ32_SC151) \
-   || defined(TARGET_SSCI824) || defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB) \
-   || defined(TARGET_EFM32WG_STK3800) || defined(TARGET_EFM32LG_STK3600) || defined(TARGET_EFM32PG_STK3401)
-#      define OS_MAINSTKSIZE    128
-#  elif defined(TARGET_STM32F334R8) || defined(TARGET_STM32F303RE) ||  defined(TARGET_STM32F303K8) ||  defined(TARGET_STM32F334C8) \
-   || defined(TARGET_STM32L031K6) || defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8) || defined(TARGET_STM32L073RZ) \
-   || defined(TARGET_EFM32HG_STK3400) || defined(TARGET_BEETLE)
-#      define OS_MAINSTKSIZE    112
-#  elif defined(TARGET_MCU_NRF51822) ||  defined(TARGET_MCU_NRF52832)
-#      define OS_MAINSTKSIZE    512
-#  else
-#    error "no target defined"
-#  endif
+ #error "no target defined"
 #endif
 
 #ifndef __MBED_CMSIS_RTOS_CM
@@ -135,7 +101,11 @@
 //   <i> Initialize thread stack with watermark pattern for analyzing stack usage (current/maximum) in System and Thread Viewer.
 //   <i> Enabling this option increases significantly the execution time of osThreadCreate.
 #ifndef OS_STKINIT
-#define OS_STKINIT      0
+  #if (defined(MBED_STACK_STATS_ENABLED) && MBED_STACK_STATS_ENABLED)
+   #define OS_STKINIT   1
+  #else
+   #define OS_STKINIT   0
+  #endif
 #endif
 
 //   <o>Processor mode for thread execution
@@ -154,11 +124,7 @@
 //   <i> Cortex-M processors provide in most cases a SysTick timer that can be used as
 //   <i> as time-base for RTX.
 #ifndef OS_SYSTICK
-#   if defined(TARGET_MCU_NRF51822)
-#       define OS_SYSTICK                0
-#   else
-#       define OS_SYSTICK                1
-#   endif
+ #define OS_SYSTICK                1
 #endif
 //
 //   <o>RTOS Kernel Timer input clock frequency [Hz] <1-1000000000>
@@ -166,119 +132,7 @@
 //   <i> When the Cortex-M SysTick timer is used, the input clock
 //   <i> is on most systems identical with the core clock.
 #ifndef OS_CLOCK
-#  if defined(TARGET_LPC1768) || defined(TARGET_LPC2368) || defined(TARGET_TEENSY3_1)
-#    define OS_CLOCK       96000000
-
-#  elif defined(TARGET_LPC1347) || defined(TARGET_STM32F303VC) || defined(TARGET_LPC1549) || defined(TARGET_STM32F334R8) || defined(TARGET_STM32F334C8) || defined(TARGET_STM32F303RE)
-#    define OS_CLOCK       72000000
-
-#  elif defined(TARGET_STM32F303K8)
-#    define OS_CLOCK       64000000
-
-#  elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11U35_401)  || defined(TARGET_LPC11U35_501) || defined(TARGET_LPCCAPPUCCINO)  || defined(TARGET_LPC1114) || defined(TARGET_KL25Z) \
-     || defined(TARGET_KL26Z) || defined(TARGET_KL27Z) || defined(TARGET_KL05Z) || defined(TARGET_KL46Z) || defined(TARGET_KL43Z) || defined(TARGET_STM32F051R8) || defined(TARGET_LPC11U68) || defined(TARGET_STM32F072RB) || defined(TARGET_STM32F091RC)
-#    define OS_CLOCK       48000000
-
-#  elif defined(TARGET_LPC812)
-#    define OS_CLOCK       36000000
-
-#  elif defined(TARGET_LPC824) || defined(TARGET_SSCI824)
-#    define OS_CLOCK       30000000
-
-#  elif  defined(TARGET_STM32F100RB) || defined(TARGET_BEETLE)
-#    define OS_CLOCK       24000000
-
-#  elif defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM) || defined(TARGET_K64F) || defined(TARGET_K66F)
-#    define OS_CLOCK       120000000
-
-#  elif defined(TARGET_LPC4330)
-#    define OS_CLOCK       204000000
-
-#  elif defined(TARGET_LPC4337)
-#    define OS_CLOCK       204000000
-
-#  elif defined(TARGET_STM32F407) || defined(TARGET_F407VG)
-#    define OS_CLOCK       168000000
-
-#  elif defined(TARGET_STM32F401RE)
-#    define OS_CLOCK       84000000
-
-#  elif defined(TARGET_STM32F411RE)
-#     define OS_CLOCK      100000000
-
-#  elif defined(TARGET_STM32F207ZG)
-#     define OS_CLOCK      120000000
-
-#  elif defined(TARGET_STM32F410RB)
-#     define OS_CLOCK      100000000
-
-#elif defined(TARGET_STM32F103RB)
-#    define OS_CLOCK       72000000
-
-#elif defined(TARGET_STM32F429ZI)
-#    define OS_CLOCK       168000000
-
-#elif defined(TARGET_STM32F302R8)
-#    define OS_CLOCK       72000000
-
-#elif defined(TARGET_STM32L031K6) || defined(TARGET_STM32L053R8) || defined(TARGET_STM32L053C8) || defined(TARGET_STM32L073RZ) 
-#    define OS_CLOCK       32000000
-
-#elif defined(TARGET_STM32F401VC)
-#    define OS_CLOCK       84000000
-
-#  elif defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG) || defined(TARGET_STM32F767ZI)
-#     define OS_CLOCK      216000000
-
-#elif defined(TARGET_MAX32610) || defined(TARGET_MAX32600)
-#    define OS_CLOCK       24000000
-
-#elif defined(TARGET_MAX32620)
-#    define OS_CLOCK       96000000
-
-#elif defined(TARGET_NZ32_SC151)
-#    define OS_CLOCK       32000000
-
-#elif defined(TARGET_STM32L152RE)
-#    define OS_CLOCK       24000000
-
-#elif defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446ZE) || defined(TARGET_STM32F446VE)
-#    define OS_CLOCK       180000000
-
-#elif defined(TARGET_STM32F030R8)
-#    define OS_CLOCK       48000000
-
-#elif defined(TARGET_STM32F070RB)
-#    define OS_CLOCK       48000000
-
-#elif defined(TARGET_STM32L432KC) || defined(TARGET_STM32L476VG) || defined(TARGET_STM32L476RG) || defined(TARGET_K22F)
-#    define OS_CLOCK       80000000
-
-#elif defined(TARGET_STM32F469NI)
-#    define OS_CLOCK       168000000
-
-#elif defined(TARGET_STM32L152RC)
-#    define OS_CLOCK       24000000
-
-#elif defined(TARGET_EFM32)
-#    include "clocking.h"
-#    define OS_CLOCK       REFERENCE_FREQUENCY
-
-#elif defined(TARGET_MCU_NRF51822)
-#    define OS_CLOCK        32768
-
-#elif defined(TARGET_MCU_NRF52832)
-#    define OS_CLOCK        64000000
-
-#elif defined(TARGET_NUMAKER_PFM_NUC472)
-#    define OS_CLOCK       84000000
-
-#elif defined(TARGET_NCS36510)
-#    define OS_CLOCK       32000000
-
-#  else
-#    error "no target defined"
-#  endif
+ #error "no target defined"
 #endif
 
 //   <o>RTX Timer tick interval value [us] <1-1000000>
@@ -408,6 +262,15 @@
 }
 
 /*----------------------------------------------------------------------------
+ *      RTX Hooks
+ *---------------------------------------------------------------------------*/
+extern void thread_terminate_hook(osThreadId id);
+
+void sysThreadTerminate(osThreadId id) {
+    thread_terminate_hook(id);
+}
+
+/*----------------------------------------------------------------------------
  *      RTX Configuration Functions
  *---------------------------------------------------------------------------*/
 
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/RTX_Config.h
--- a/rtx/TARGET_CORTEX_M/RTX_Config.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/RTX_Config.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -77,3 +80,5 @@
 /*----------------------------------------------------------------------------
  * end of file
  *---------------------------------------------------------------------------*/
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_ARM/HAL_CM4.c
--- a/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_ARM/HAL_CM4.c	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_ARM/HAL_CM4.c	Mon Nov 14 17:14:42 2016 -0600
@@ -164,7 +164,9 @@
 
 SVC_ContextSave
         TST     LR,#0x10                ; is it extended frame?
+#if (__FPU_PRESENT == 1)
         VSTMDBEQ R12!,{S16-S31}         ; yes, stack also VFP hi-regs
+#endif
         MOVEQ   R0,#0x01                ; os_tsk->stack_frame val
         MOVNE   R0,#0x00
         STRB    R0,[R1,#TCB_STACKF]     ; os_tsk.run->stack_frame = val
@@ -184,7 +186,9 @@
         CMP     R0,#0                   ; Basic/Extended Stack Frame
         MVNEQ   LR,#:NOT:0xFFFFFFFD     ; set EXC_RETURN value
         MVNNE   LR,#:NOT:0xFFFFFFED
+#if (__FPU_PRESENT == 1)
         VLDMIANE R12!,{S16-S31}         ; restore VFP hi-registers
+#endif
         MSR     PSP,R12                 ; Write PSP
 
 SVC_Exit
@@ -247,7 +251,9 @@
 
         MRS     R12,PSP                 ; Read PSP
         TST     LR,#0x10                ; is it extended frame?
+#if (__FPU_PRESENT == 1)
         VSTMDBEQ R12!,{S16-S31}         ; yes, stack also VFP hi-regs
+#endif
         MOVEQ   R0,#0x01                ; os_tsk->stack_frame val
         MOVNE   R0,#0x00
         STRB    R0,[R1,#TCB_STACKF]     ; os_tsk.run->stack_frame = val
@@ -266,7 +272,9 @@
         CMP     R0,#0                   ; Basic/Extended Stack Frame
         MVNEQ   LR,#:NOT:0xFFFFFFFD     ; set EXC_RETURN value
         MVNNE   LR,#:NOT:0xFFFFFFED
+#if (__FPU_PRESENT == 1)
         VLDMIANE R12!,{S16-S31}         ; restore VFP hi-regs
+#endif
         MSR     PSP,R12                 ; Write PSP
 
 Sys_Exit
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_IAR/HAL_CM4.S
--- a/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_IAR/HAL_CM4.S	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/TARGET_RTOS_M4_M7/TOOLCHAIN_IAR/HAL_CM4.S	Mon Nov 14 17:14:42 2016 -0600
@@ -188,8 +188,12 @@
 
 SVC_ContextSave:
         TST     LR,#0x10                /* is it extended frame? */
+#if (__FPU_PRESENT == 1)
         ITTE    EQ
         VSTMDBEQ R12!,{S16-S31}         /* yes, stack also VFP hi-regs */
+#else
+        ITE     EQ
+#endif
         MOVEQ   R0,#0x01                /* os_tsk->stack_frame val */
         MOVNE   R0,#0x00
         STRB    R0,[R1,#TCB_STACKF]     /* os_tsk.run->stack_frame = val */
@@ -207,10 +211,16 @@
         LDMIA   R12!,{R4-R11}           /* Restore New Context */
         LDRB    R0,[R2,#TCB_STACKF]     /* Stack Frame */
         CMP     R0,#0                   /* Basic/Extended Stack Frame */
+#if (__FPU_PRESENT == 1)
         ITEE    EQ
+#else
+        ITE     EQ
+#endif
         MVNEQ   LR,#~0xFFFFFFFD         /* set EXC_RETURN value */
         MVNNE   LR,#~0xFFFFFFED
+#if (__FPU_PRESENT == 1)
         VLDMIANE R12!,{S16-S31}         /* restore VFP hi-registers */
+#endif
         MSR     PSP,R12                 /* Write PSP */
 
 SVC_Exit:
@@ -274,8 +284,12 @@
 
         MRS     R12,PSP                 /* Read PSP */
         TST     LR,#0x10                /* is it extended frame? */
+#if (__FPU_PRESENT == 1)
         ITTE    EQ
         VSTMDBEQ R12!,{S16-S31}         /* yes, stack also VFP hi-regs */
+#else
+        ITE     EQ
+#endif
         MOVEQ   R0,#0x01                /* os_tsk->stack_frame val */
         MOVNE   R0,#0x00
         STRB    R0,[R1,#TCB_STACKF]     /* os_tsk.run->stack_frame = val */
@@ -292,10 +306,16 @@
         LDMIA   R12!,{R4-R11}           /* Restore New Context */
         LDRB    R0,[R2,#TCB_STACKF]     /* Stack Frame */
         CMP     R0,#0                   /* Basic/Extended Stack Frame */
+#if (__FPU_PRESENT == 1)
         ITEE    EQ
+#else
+        ITE     EQ
+#endif
         MVNEQ   LR,#~0xFFFFFFFD         /* set EXC_RETURN value */
         MVNNE   LR,#~0xFFFFFFED
+#if (__FPU_PRESENT == 1)
         VLDMIANE R12!,{S16-S31}         /* restore VFP hi-registers */
+#endif
         MSR     PSP,R12                 /* Write PSP */
 
 Sys_Exit:
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/cmsis_os.h
--- a/rtx/TARGET_CORTEX_M/cmsis_os.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/cmsis_os.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /* ----------------------------------------------------------------------
  * $Date:        5. February 2013
  * $Revision:    V1.02
@@ -74,16 +77,22 @@
 
 #ifdef __MBED_CMSIS_RTOS_CM
 
-/* Single thread - disable timers and set task count to one */
-#if defined(MBED_RTOS_SINGLE_THREAD)
-#define OS_TASKCNT  1
-#define OS_TIMERS   0
+/* If os timers macro is set to 0, there's no timer thread created, therefore
+ * main thread has tid 0x01  
+ */
+#if defined(OS_TIMERS) && (OS_TIMERS == 0)
+#define MAIN_THREAD_ID 0x01
+#else
+#define MAIN_THREAD_ID 0x02
+#endif
 #endif
 
+#if defined(TARGET_XDOT_L151CC)
+#define DEFAULT_STACK_SIZE         (WORDS_STACK_SIZE/2)
+#else
+#define DEFAULT_STACK_SIZE         (WORDS_STACK_SIZE*4)
 #endif
 
-#define DEFAULT_STACK_SIZE         (WORDS_STACK_SIZE*4)
-
 #define osCMSIS           0x10002U     ///< CMSIS-RTOS API version (main [31:16] .sub [15:0])
 
 #define osCMSIS_RTX     ((4<<16)|80)   ///< RTOS identification and version (main [31:16] .sub [15:0])
@@ -99,6 +108,7 @@
 #define osFeature_Semaphore    65535   ///< Maximum count for \ref osSemaphoreCreate function
 #define osFeature_Wait         0       ///< osWait not available
 #define osFeature_SysTick      1       ///< osKernelSysTick functions available
+#define osFeature_ThreadEnum   1       ///< Thread enumeration available
 
 #if defined (__CC_ARM)
 #define os_InRegs __value_in_regs      // Compiler specific: force struct in registers
@@ -159,6 +169,16 @@
   osTimerPeriodic         =     1        ///< repeating timer
 } os_timer_type;
 
+typedef enum {
+  osThreadInfoState,
+  osThreadInfoStackSize,
+  osThreadInfoStackMax,
+  osThreadInfoEntry,
+  osThreadInfoArg,
+
+  osThreadInfo_reserved   =  0x7FFFFFFF  ///< prevent from enum down-size compiler optimization.
+} osThreadInfo;
+
 /// Entry point of a thread.
 typedef void (*os_pthread) (void const *argument);
 
@@ -188,6 +208,8 @@
 /// Mail ID identifies the mail queue (pointer to a mail queue control block).
 typedef struct os_mailQ_cb *osMailQId;
 
+/// Thread enumeration ID identifies the enumeration (pointer to a thread enumeration control block).
+typedef uint32_t *osThreadEnumId;
 
 /// Thread Definition structure contains startup information of a thread.
 typedef struct os_thread_def  {
@@ -358,6 +380,13 @@
 uint8_t osThreadGetState (osThreadId thread_id);
 #endif
 
+/// Get into from an active thread.
+/// \param[in]     thread_id     thread ID obtained by \ref osThreadCreate or \ref osThreadGetId.
+/// \param[in]     info          information to read.
+/// \return current state of the thread function.
+/// \return requested info that includes the status code.
+os_InRegs osEvent _osThreadGetInfo(osThreadId thread_id, osThreadInfo info);
+
 //  ==== Generic Wait Functions ====
 
 /// Wait for Timeout (Time Delay).
@@ -680,6 +709,26 @@
 #endif  // Mail Queues available
 
 
+//  ==== Thread Enumeration Functions ====
+
+#if (defined (osFeature_ThreadEnum)  &&  (osFeature_ThreadEnum != 0))     // Thread enumeration available
+
+/// Start a thread enumeration.
+/// \return an enumeration ID or NULL on error.
+osThreadEnumId _osThreadsEnumStart(void);
+
+/// Get the next task ID in the enumeration.
+/// \return a thread ID or NULL on if the end of the enumeration has been reached.
+osThreadId _osThreadEnumNext(osThreadEnumId enum_id);
+
+/// Free the enumeration structure.
+/// \param[in]     enum_id       pointer to the enumeration ID that was obtained with \ref _osThreadsEnumStart.
+/// \return status code that indicates the execution status of the function.
+osStatus _osThreadEnumFree(osThreadEnumId enum_id);
+
+#endif  // Thread Enumeration available
+
+
 //  ==== RTX Extensions ====
 
 /// Suspend the RTX task scheduler.
@@ -696,3 +745,5 @@
 #endif
 
 #endif  // _CMSIS_OS_H
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_CMSIS.c
--- a/rtx/TARGET_CORTEX_M/rt_CMSIS.c	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_CMSIS.c	Mon Nov 14 17:14:42 2016 -0600
@@ -392,6 +392,10 @@
 extern const osMessageQDef_t os_messageQ_def_osTimerMessageQ;
 extern       osMessageQId    osMessageQId_osTimerMessageQ;
 
+// Thread creation and destruction
+osMutexDef(osThreadMutex);
+osMutexId osMutexId_osThreadMutex;
+void sysThreadTerminate(osThreadId id);
 
 // ==== Helper Functions ====
 
@@ -490,6 +494,8 @@
     // Create OS Timers resources (Message Queue & Thread)
     osMessageQId_osTimerMessageQ = svcMessageCreate (&os_messageQ_def_osTimerMessageQ, NULL);
     osThreadId_osTimerThread = svcThreadCreate(&os_thread_def_osTimerThread, NULL, NULL);
+    // Initialize thread mutex
+    osMutexId_osThreadMutex = osMutexCreate(osMutex(osThreadMutex));
   }
 
   sysThreadError(osOK);
@@ -546,7 +552,7 @@
 
 /// Initialize the RTOS Kernel for creating objects
 osStatus osKernelInitialize (void) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return osErrorISR;                          // Not allowed in ISR
   }
   if ((__get_CONTROL() & 1U) == 0U) {           // Privileged mode
@@ -560,7 +566,7 @@
 osStatus osKernelStart (void) {
   uint32_t stack[8];
 
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return osErrorISR;                          // Not allowed in ISR
   }
 
@@ -601,7 +607,7 @@
 
 /// Check if the RTOS kernel is already started
 int32_t osKernelRunning (void) {
-  if ((__get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) {
+  if ((__get_PRIMASK() != 0U || __get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) {
     // in ISR or Privileged
     return (int32_t)os_running;
   } else {
@@ -611,7 +617,7 @@
 
 /// Get the RTOS kernel system timer counter
 uint32_t osKernelSysTick (void) {
-  if (__get_IPSR() != 0U) { return 0U; }        // Not allowed in ISR
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) { return 0U; }        // Not allowed in ISR
   return __svcKernelSysTick();
 }
 
@@ -632,6 +638,7 @@
 SVC_0_1(svcThreadYield,       osStatus,                                      RET_osStatus)
 SVC_2_1(svcThreadSetPriority, osStatus,         osThreadId,      osPriority, RET_osStatus)
 SVC_1_1(svcThreadGetPriority, osPriority,       osThreadId,                  RET_osPriority)
+SVC_2_3(svcThreadGetInfo,    os_InRegs osEvent, osThreadId,    osThreadInfo, RET_osEvent)
 
 // Thread Service Calls
 
@@ -791,6 +798,67 @@
   return (osPriority)(ptcb->prio - 1 + osPriorityIdle); 
 }
 
+/// Get info from an active thread
+os_InRegs osEvent_type svcThreadGetInfo (osThreadId thread_id, osThreadInfo info) {
+  P_TCB ptcb;
+  osEvent ret;
+  ret.status = osOK;
+
+  ptcb = rt_tid2ptcb(thread_id);                // Get TCB pointer
+  if (ptcb == NULL) {
+    ret.status = osErrorValue;
+    return osEvent_ret_status;
+  }
+
+  if (osThreadInfoStackSize == info) {
+    uint32_t size;
+    size = ptcb->priv_stack;
+    if (0 == size) {
+      // This is an OS task - always a fixed size
+      size = os_stackinfo & 0x3FFFF;
+    }
+    ret.value.v = size;
+    return osEvent_ret_value;
+  }
+
+  if (osThreadInfoStackMax == info) {
+    uint32_t i;
+    uint32_t *stack_ptr;
+    uint32_t stack_size;
+    if (!(os_stackinfo & (1 << 28))) {
+      // Stack init must be turned on for max stack usage
+      ret.status = osErrorResource;
+      return osEvent_ret_status;
+    }
+    stack_ptr = (uint32_t*)ptcb->stack;
+    stack_size = ptcb->priv_stack;
+    if (0 == stack_size) {
+      // This is an OS task - always a fixed size
+      stack_size = os_stackinfo & 0x3FFFF;
+    }
+    for (i = 1; i <stack_size / 4; i++) {
+      if (stack_ptr[i] != MAGIC_PATTERN) {
+        break;
+      }
+    }
+    ret.value.v = stack_size - i * 4;
+    return osEvent_ret_value;
+  }
+
+  if (osThreadInfoEntry == info) {
+    ret.value.p = (void*)ptcb->ptask;
+    return osEvent_ret_value;
+  }
+
+  if (osThreadInfoArg == info) {
+    ret.value.p = (void*)ptcb->argv;
+    return osEvent_ret_value;
+  }
+
+  // Unsupported option so return error
+  ret.status = osErrorParameter;
+  return osEvent_ret_status;
+}
 
 // Thread Public API
 
@@ -799,20 +867,25 @@
   return osThreadContextCreate(thread_def, argument, NULL);
 }
 osThreadId osThreadContextCreate (const osThreadDef_t *thread_def, void *argument, void *context) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return NULL;                                // Not allowed in ISR
   }
   if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
     // Privileged and not running
     return   svcThreadCreate(thread_def, argument, context);
   } else {
-    return __svcThreadCreate(thread_def, argument, context);
+    osThreadId id;
+    osMutexWait(osMutexId_osThreadMutex, osWaitForever);
+    // Thread mutex must be held when a thread is created or terminated
+    id = __svcThreadCreate(thread_def, argument, context);
+    osMutexRelease(osMutexId_osThreadMutex);
+    return id;
   }
 }
 
 /// Return the thread ID of the current running thread
 osThreadId osThreadGetId (void) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return NULL;                                // Not allowed in ISR
   }
   return __svcThreadGetId();
@@ -820,15 +893,21 @@
 
 /// Terminate execution of a thread and remove it from ActiveThreads
 osStatus osThreadTerminate (osThreadId thread_id) {
-  if (__get_IPSR() != 0U) { 
+  osStatus status;
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return osErrorISR;                          // Not allowed in ISR
   }
-  return __svcThreadTerminate(thread_id);
+  osMutexWait(osMutexId_osThreadMutex, osWaitForever);
+  sysThreadTerminate(thread_id);
+  // Thread mutex must be held when a thread is created or terminated
+  status = __svcThreadTerminate(thread_id);
+  osMutexRelease(osMutexId_osThreadMutex);
+  return status;
 }
 
 /// Pass control to next thread that is in state READY
 osStatus osThreadYield (void) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return osErrorISR;                          // Not allowed in ISR
   }
   return __svcThreadYield();
@@ -836,7 +915,7 @@
 
 /// Change priority of an active thread
 osStatus osThreadSetPriority (osThreadId thread_id, osPriority priority) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return osErrorISR;                          // Not allowed in ISR
   }
   return __svcThreadSetPriority(thread_id, priority);
@@ -844,7 +923,7 @@
 
 /// Get current priority of an active thread
 osPriority osThreadGetPriority (osThreadId thread_id) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return osPriorityError;                     // Not allowed in ISR
   }
   return __svcThreadGetPriority(thread_id);
@@ -852,8 +931,15 @@
 
 /// INTERNAL - Not Public
 /// Auto Terminate Thread on exit (used implicitly when thread exists)
-__NO_RETURN void osThreadExit (void) { 
-  __svcThreadTerminate(__svcThreadGetId()); 
+__NO_RETURN void osThreadExit (void) {
+  osThreadId id;
+  // Thread mutex must be held when a thread is created or terminated
+  // Note - the mutex will be released automatically by the os when
+  //        the thread is terminated
+  osMutexWait(osMutexId_osThreadMutex, osWaitForever);
+  id = __svcThreadGetId();
+  sysThreadTerminate(id);
+  __svcThreadTerminate(id);
   for (;;);                                     // Should never come here
 }
 
@@ -862,7 +948,7 @@
 uint8_t osThreadGetState (osThreadId thread_id) {
   P_TCB ptcb;
 
-  if (__get_IPSR() != 0U) return osErrorISR;     // Not allowed in ISR
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) return osErrorISR;     // Not allowed in ISR
 
   ptcb = rt_tid2ptcb(thread_id);                // Get TCB pointer
   if (ptcb == NULL) return INACTIVE;
@@ -871,6 +957,49 @@
 }
 #endif
 
+/// Get the requested info from the specified active thread
+os_InRegs osEvent _osThreadGetInfo(osThreadId thread_id, osThreadInfo info) {
+  osEvent ret;
+
+  if (__get_IPSR() != 0U) {                     // Not allowed in ISR
+    ret.status = osErrorISR;
+    return ret;
+  }
+  return __svcThreadGetInfo(thread_id, info);
+}
+
+osThreadEnumId _osThreadsEnumStart() {
+  static uint32_t thread_enum_index;
+  osMutexWait(osMutexId_osThreadMutex, osWaitForever);
+  thread_enum_index = 0;
+  return &thread_enum_index;
+}
+
+osThreadId _osThreadEnumNext(osThreadEnumId enum_id) {
+  uint32_t i;
+  osThreadId id = NULL;
+  uint32_t *index = (uint32_t*)enum_id;
+  for (i = *index; i < os_maxtaskrun; i++) {
+    if (os_active_TCB[i] != NULL) {
+      id = (osThreadId)os_active_TCB[i];
+      break;
+    }
+  }
+  if (i == os_maxtaskrun) {
+    // Include the idle task at the end of the enumeration
+    id = &os_idle_TCB;
+  }
+  *index = i + 1;
+  return id;
+}
+
+osStatus _osThreadEnumFree(osThreadEnumId enum_id) {
+  uint32_t *index = (uint32_t*)enum_id;
+  *index = 0;
+  osMutexRelease(osMutexId_osThreadMutex);
+  return osOK;
+}
+
 // ==== Generic Wait Functions ====
 
 // Generic Wait Service Calls declarations
@@ -911,7 +1040,7 @@
 
 /// Wait for Timeout (Time Delay)
 osStatus osDelay (uint32_t millisec) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return osErrorISR;                          // Not allowed in ISR
   }
   return __svcDelay(millisec);
@@ -925,7 +1054,7 @@
   ret.status = osErrorOS;
   return ret;
 #else
-  if (__get_IPSR() != 0U) {                     // Not allowed in ISR
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {                     // Not allowed in ISR
     ret.status = osErrorISR;
     return ret;
   }
@@ -1208,7 +1337,7 @@
 
 /// Create timer
 osTimerId osTimerCreate (const osTimerDef_t *timer_def, os_timer_type type, void *argument) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return NULL;                                // Not allowed in ISR
   }
   if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
@@ -1221,7 +1350,7 @@
 
 /// Start or restart timer
 osStatus osTimerStart (osTimerId timer_id, uint32_t millisec) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return osErrorISR;                          // Not allowed in ISR
   }
   return __svcTimerStart(timer_id, millisec);
@@ -1229,7 +1358,7 @@
 
 /// Stop timer
 osStatus osTimerStop (osTimerId timer_id) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return osErrorISR;                          // Not allowed in ISR
   }
   return __svcTimerStop(timer_id);
@@ -1237,7 +1366,7 @@
 
 /// Delete timer
 osStatus osTimerDelete (osTimerId timer_id) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return osErrorISR;                          // Not allowed in ISR
   }
   return __svcTimerDelete(timer_id);
@@ -1374,7 +1503,7 @@
 
 /// Set the specified Signal Flags of an active thread
 int32_t osSignalSet (osThreadId thread_id, int32_t signals) {
-  if (__get_IPSR() != 0U) {                     // in ISR
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {                     // in ISR
     return   isrSignalSet(thread_id, signals); 
   } else {                                      // in Thread
     return __svcSignalSet(thread_id, signals);
@@ -1383,7 +1512,7 @@
 
 /// Clear the specified Signal Flags of an active thread
 int32_t osSignalClear (osThreadId thread_id, int32_t signals) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return (int32_t)0x80000000U;                // Not allowed in ISR
   }
   return __svcSignalClear(thread_id, signals);
@@ -1393,7 +1522,7 @@
 os_InRegs osEvent osSignalWait (int32_t signals, uint32_t millisec) {
   osEvent ret;
 
-  if (__get_IPSR() != 0U) {                     // Not allowed in ISR
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {                     // Not allowed in ISR
     ret.status = osErrorISR;
     return ret;
   }
@@ -1505,7 +1634,7 @@
 
 /// Create and Initialize a Mutex object
 osMutexId osMutexCreate (const osMutexDef_t *mutex_def) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return NULL;                                // Not allowed in ISR
   }
   if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
@@ -1518,7 +1647,7 @@
 
 /// Wait until a Mutex becomes available
 osStatus osMutexWait (osMutexId mutex_id, uint32_t millisec) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return osErrorISR;                          // Not allowed in ISR
   }
   return __svcMutexWait(mutex_id, millisec);
@@ -1526,7 +1655,7 @@
 
 /// Release a Mutex that was obtained with osMutexWait
 osStatus osMutexRelease (osMutexId mutex_id) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return osErrorISR;                          // Not allowed in ISR
   }
   return __svcMutexRelease(mutex_id);
@@ -1534,7 +1663,7 @@
 
 /// Delete a Mutex that was created by osMutexCreate
 osStatus osMutexDelete (osMutexId mutex_id) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return osErrorISR;                          // Not allowed in ISR
   }
   return __svcMutexDelete(mutex_id);
@@ -1672,7 +1801,7 @@
 
 /// Create and Initialize a Semaphore object
 osSemaphoreId osSemaphoreCreate (const osSemaphoreDef_t *semaphore_def, int32_t count) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return NULL;                                // Not allowed in ISR
   }
   if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
@@ -1685,7 +1814,7 @@
 
 /// Wait until a Semaphore becomes available
 int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return -1;                                  // Not allowed in ISR
   }
   return __svcSemaphoreWait(semaphore_id, millisec);
@@ -1693,16 +1822,16 @@
 
 /// Release a Semaphore
 osStatus osSemaphoreRelease (osSemaphoreId semaphore_id) {
-  if (__get_IPSR() != 0U) {                     // in ISR
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {    // in ISR
     return   isrSemaphoreRelease(semaphore_id);
-  } else {                                      // in Thread
+  } else {                                              // in Thread
     return __svcSemaphoreRelease(semaphore_id);
   }
 }
 
 /// Delete a Semaphore that was created by osSemaphoreCreate
 osStatus osSemaphoreDelete (osSemaphoreId semaphore_id) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return osErrorISR;                          // Not allowed in ISR
   }
   return __svcSemaphoreDelete(semaphore_id);
@@ -1785,7 +1914,7 @@
 
 /// Create and Initialize memory pool
 osPoolId osPoolCreate (const osPoolDef_t *pool_def) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return NULL;                                // Not allowed in ISR
   }
   if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
@@ -1798,7 +1927,7 @@
 
 /// Allocate a memory block from a memory pool
 void *osPoolAlloc (osPoolId pool_id) {
-  if ((__get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) {     // in ISR or Privileged
+  if ((__get_PRIMASK() != 0U || __get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) {     // in ISR or Privileged
     return   sysPoolAlloc(pool_id);
   } else {                                      // in Thread
     return __sysPoolAlloc(pool_id);
@@ -1809,7 +1938,7 @@
 void *osPoolCAlloc (osPoolId pool_id) {
   void *mem;
 
-  if ((__get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) {     // in ISR or Privileged
+  if ((__get_PRIMASK() != 0U || __get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) {     // in ISR or Privileged
     mem =   sysPoolAlloc(pool_id);
   } else {                                      // in Thread
     mem = __sysPoolAlloc(pool_id);
@@ -1822,7 +1951,7 @@
 
 /// Return an allocated memory block back to a specific memory pool
 osStatus osPoolFree (osPoolId pool_id, void *block) {
-  if ((__get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) {     // in ISR or Privileged
+  if ((__get_PRIMASK() != 0U || __get_IPSR() != 0U) || ((__get_CONTROL() & 1U) == 0U)) {     // in ISR or Privileged
     return   sysPoolFree(pool_id, block);
   } else {                                      // in Thread
     return __sysPoolFree(pool_id, block);
@@ -1962,7 +2091,7 @@
 
 /// Create and Initialize Message Queue
 osMessageQId osMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return NULL;                                // Not allowed in ISR
   }
   if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
@@ -1975,7 +2104,7 @@
 
 /// Put a Message to a Queue
 osStatus osMessagePut (osMessageQId queue_id, uint32_t info, uint32_t millisec) {
-  if (__get_IPSR() != 0U) {                     // in ISR
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {                     // in ISR
     return   isrMessagePut(queue_id, info, millisec);
   } else {                                      // in Thread
     return __svcMessagePut(queue_id, info, millisec);
@@ -1984,7 +2113,7 @@
 
 /// Get a Message or Wait for a Message from a Queue
 os_InRegs osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec) {
-  if (__get_IPSR() != 0U) {                     // in ISR
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {                     // in ISR
     return   isrMessageGet(queue_id, millisec);
   } else {                                      // in Thread
     return __svcMessageGet(queue_id, millisec);
@@ -2121,7 +2250,7 @@
 
 /// Create and Initialize mail queue
 osMailQId osMailCreate (const osMailQDef_t *queue_def, osThreadId thread_id) {
-  if (__get_IPSR() != 0U) {
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {
     return NULL;                                // Not allowed in ISR
   }
   if (((__get_CONTROL() & 1U) == 0U) && (os_running == 0U)) {
@@ -2134,7 +2263,7 @@
 
 /// Allocate a memory block from a mail
 void *osMailAlloc (osMailQId queue_id, uint32_t millisec) {
-  if (__get_IPSR() != 0U) {                     // in ISR
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {                     // in ISR
     return   sysMailAlloc(queue_id, millisec, 1U);
   } else {                                      // in Thread
     return __sysMailAlloc(queue_id, millisec, 0U);
@@ -2146,7 +2275,7 @@
   void *pool;
   void *mem;
 
-  if (__get_IPSR() != 0U) {                     // in ISR
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {                     // in ISR
     mem =   sysMailAlloc(queue_id, millisec, 1U);
   } else {                                      // in Thread
     mem = __sysMailAlloc(queue_id, millisec, 0U);
@@ -2161,7 +2290,7 @@
 
 /// Free a memory block from a mail
 osStatus osMailFree (osMailQId queue_id, void *mail) {
-  if (__get_IPSR() != 0U) {                     // in ISR
+  if (__get_PRIMASK() != 0U || __get_IPSR() != 0U) {                     // in ISR
     return   sysMailFree(queue_id, mail, 1U);
   } else {                                      // in Thread
     return __sysMailFree(queue_id, mail, 0U);
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_Event.h
--- a/rtx/TARGET_CORTEX_M/rt_Event.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_Event.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -44,3 +47,5 @@
  * end of file
  *---------------------------------------------------------------------------*/
 
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_HAL_CM.h
--- a/rtx/TARGET_CORTEX_M/rt_HAL_CM.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_HAL_CM.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -53,11 +56,19 @@
 #endif
 
 #ifndef __CMSIS_GENERIC
+
+__attribute__((always_inline)) static inline U32 __get_PRIMASK(void)
+{
+    register U32 primask __asm("primask");
+    return primask;
+}
+
 #define __DMB() do {\
                    __schedule_barrier();\
                    __dmb(0xF);\
                    __schedule_barrier();\
                 } while (0)
+
 #endif
 
 #elif defined (__GNUC__)        /* GNU Compiler */
@@ -77,6 +88,14 @@
 
 #ifndef __CMSIS_GENERIC
 
+__attribute__((always_inline)) static inline U32 __get_PRIMASK(void)
+{
+  U32 result;
+
+  __asm volatile ("mrs %0, primask" : "=r" (result));
+  return result;
+}
+
 __attribute__((always_inline)) static inline void __enable_irq(void)
 {
   __asm volatile ("cpsie i");
@@ -101,7 +120,7 @@
 __attribute__(( always_inline)) static inline U8 __clz(U32 value)
 {
   U8 result;
-  
+
   __asm volatile ("clz %0, %1" : "=r" (result) : "r" (value));
   return(result);
 }
@@ -122,6 +141,14 @@
 
 #ifndef __CMSIS_GENERIC
 
+static inline U32 __get_PRIMASK(void)
+{
+  U32 result;
+  
+  __asm volatile ("mrs %0, primask" : "=r" (result));
+  return result;
+}
+
 static inline void __enable_irq(void)
 {
   __asm volatile ("cpsie i");
@@ -203,8 +230,22 @@
  #define rt_inc(p)     while(__strex((__ldrex(p)+1U),p))
  #define rt_dec(p)     while(__strex((__ldrex(p)-1U),p))
 #else
- #define rt_inc(p)     __disable_irq();(*p)++;__enable_irq();
- #define rt_dec(p)     __disable_irq();(*p)--;__enable_irq();
+ #define rt_inc(p) do {\
+                     U32 primask = __get_PRIMASK();\
+                     __disable_irq();\
+                     (*p)++;\
+                     if (!primask) {\
+                       __enable_irq();\
+                     }\
+                   } while (0)
+ #define rt_dec(p) do {\
+                     U32 primask = __get_PRIMASK();\
+                     __disable_irq();\
+                     (*p)--;\
+                     if (!primask) {\
+                       __enable_irq();\
+                     }\
+                   } while (0)
 #endif
 
 __inline static U32 rt_inc_qi (U32 size, U8 *count, U8 *first) {
@@ -220,6 +261,7 @@
     if (c2 == size) { c2 = 0U; }
   } while (__strex(c2, first));
 #else
+  U32 primask = __get_PRIMASK();
   __disable_irq();
   if ((cnt = *count) < size) {
     *count = (U8)(cnt+1U);
@@ -227,7 +269,9 @@
     if (c2 == size) { c2 = 0U; }
     *first = (U8)c2; 
   }
-  __enable_irq ();
+  if (!primask) {
+    __enable_irq ();
+  }
 #endif
   return (cnt);
 }
@@ -296,3 +340,5 @@
 /*----------------------------------------------------------------------------
  * end of file
  *---------------------------------------------------------------------------*/
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_List.h
--- a/rtx/TARGET_CORTEX_M/rt_List.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_List.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -65,3 +68,5 @@
  * end of file
  *---------------------------------------------------------------------------*/
 
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_Mailbox.h
--- a/rtx/TARGET_CORTEX_M/rt_Mailbox.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_Mailbox.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -46,3 +49,5 @@
  * end of file
  *---------------------------------------------------------------------------*/
 
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_MemBox.h
--- a/rtx/TARGET_CORTEX_M/rt_MemBox.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_MemBox.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -43,3 +46,5 @@
 /*----------------------------------------------------------------------------
  * end of file
  *---------------------------------------------------------------------------*/
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_Memory.h
--- a/rtx/TARGET_CORTEX_M/rt_Memory.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_Memory.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -42,3 +45,5 @@
 extern U32   rt_init_mem  (void *pool, U32  size);
 extern void *rt_alloc_mem (void *pool, U32  size);
 extern U32   rt_free_mem  (void *pool, void *mem);
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_Mutex.h
--- a/rtx/TARGET_CORTEX_M/rt_Mutex.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_Mutex.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -42,3 +45,5 @@
  * end of file
  *---------------------------------------------------------------------------*/
 
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_OsEventObserver.h
--- a/rtx/TARGET_CORTEX_M/rt_OsEventObserver.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_OsEventObserver.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -56,3 +59,5 @@
 #endif
 
 #endif
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_Robin.h
--- a/rtx/TARGET_CORTEX_M/rt_Robin.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_Robin.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -43,3 +46,5 @@
  * end of file
  *---------------------------------------------------------------------------*/
 
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_Semaphore.h
--- a/rtx/TARGET_CORTEX_M/rt_Semaphore.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_Semaphore.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -44,3 +47,5 @@
  * end of file
  *---------------------------------------------------------------------------*/
 
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_System.c
--- a/rtx/TARGET_CORTEX_M/rt_System.c	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_System.c	Mon Nov 14 17:14:42 2016 -0600
@@ -313,10 +313,22 @@
 /*--------------------------- rt_stk_check ----------------------------------*/
 
 __weak void rt_stk_check (void) {
+#ifdef __MBED_CMSIS_RTOS_CM
+    /* Check for stack overflow. */
+    if (os_tsk.run->task_id == MAIN_THREAD_ID) {
+        // TODO: For the main thread the check should be done against the main heap pointer
+    } else {
+        if ((os_tsk.run->tsk_stack < (U32)os_tsk.run->stack) ||
+            (os_tsk.run->stack[0] != MAGIC_WORD)) {
+            os_error (OS_ERR_STK_OVF);
+        }
+    }
+#else
     if ((os_tsk.run->tsk_stack < (U32)os_tsk.run->stack) ||
         (os_tsk.run->stack[0] != MAGIC_WORD)) {
         os_error (OS_ERR_STK_OVF);
     }
+#endif
 }
 
 /*----------------------------------------------------------------------------
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_System.h
--- a/rtx/TARGET_CORTEX_M/rt_System.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_System.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -50,3 +53,5 @@
  * end of file
  *---------------------------------------------------------------------------*/
 
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_Task.c
--- a/rtx/TARGET_CORTEX_M/rt_Task.c	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_Task.c	Mon Nov 14 17:14:42 2016 -0600
@@ -247,6 +247,7 @@
   task_context->task_id = (U8)i;
   /* Pass parameter 'argv' to 'rt_init_context' */
   task_context->msg = argv;
+  task_context->argv = argv;
   /* For 'size == 0' system allocates the user stack from the memory pool. */
   rt_init_context (task_context, (U8)(prio_stksz & 0xFFU), task);
 
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_Task.h
--- a/rtx/TARGET_CORTEX_M/rt_Task.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_Task.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -81,3 +84,5 @@
 /*----------------------------------------------------------------------------
  * end of file
  *---------------------------------------------------------------------------*/
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_Time.h
--- a/rtx/TARGET_CORTEX_M/rt_Time.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_Time.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -45,3 +48,5 @@
  * end of file
  *---------------------------------------------------------------------------*/
 
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_Timer.h
--- a/rtx/TARGET_CORTEX_M/rt_Timer.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_Timer.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -43,3 +46,5 @@
 /*----------------------------------------------------------------------------
  * end of file
  *---------------------------------------------------------------------------*/
+
+/** @}*/
diff -r b744dfee1cf2 -r 58563e6cba1e rtx/TARGET_CORTEX_M/rt_TypeDef.h
--- a/rtx/TARGET_CORTEX_M/rt_TypeDef.h	Wed Nov 09 12:22:14 2016 -0600
+++ b/rtx/TARGET_CORTEX_M/rt_TypeDef.h	Mon Nov 14 17:14:42 2016 -0600
@@ -1,3 +1,6 @@
+
+/** \addtogroup rtos */
+/** @{*/
 /*----------------------------------------------------------------------------
  *      CMSIS-RTOS  -  RTX
  *----------------------------------------------------------------------------
@@ -79,6 +82,7 @@
 
   /* Task entry point used for uVision debugger                              */
   FUNCP  ptask;                   /* Task entry address                      */
+  void   *argv;                   /* Task argument                           */
   void   *context;                /* Pointer to thread context               */
 } *P_TCB;
 #define TCB_STACKF      37        /* 'stack_frame' offset                    */
@@ -167,3 +171,5 @@
 #define NULL            ((void *) 0)
 
 #endif
+
+/** @}*/