Maintain legacy RTOS behavior before mbed-5
Fork of mbed-rtos by
Revision 123:58563e6cba1e, committed 2016-11-14
- 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
--- 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 + +/** @}*/
--- 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 + +/** @}*/
--- 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 {
--- 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 + +/** @}*/
--- 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 + +/** @}*/
--- 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 {
--- 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 + +/** @}*/
--- 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>
--- 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 + +/** @}*/
--- 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 }
--- 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 + +/** @}*/
--- 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 + +/** @}*/
--- 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) {
--- 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 + +/** @}*/
--- 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
--- 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>
--- 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)
--- 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
--- 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
--- 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
--- 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 */
--- 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 }
--- 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 *---------------------------------------------------------------------------*/ + +/** @}*/
--- 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 *---------------------------------------------------------------------------*/
--- 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 *---------------------------------------------------------------------------*/ + +/** @}*/
--- 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
--- 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:
--- 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 + +/** @}*/
--- 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);
--- 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 *---------------------------------------------------------------------------*/ + +/** @}*/
--- 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 *---------------------------------------------------------------------------*/ + +/** @}*/
--- 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 *---------------------------------------------------------------------------*/ + +/** @}*/
--- 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 *---------------------------------------------------------------------------*/ + +/** @}*/
--- 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 *---------------------------------------------------------------------------*/ + +/** @}*/
--- 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); + +/** @}*/
--- 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 *---------------------------------------------------------------------------*/ + +/** @}*/
--- 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 + +/** @}*/
--- 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 *---------------------------------------------------------------------------*/ + +/** @}*/
--- 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 *---------------------------------------------------------------------------*/ + +/** @}*/
--- 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 } /*----------------------------------------------------------------------------
--- 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 *---------------------------------------------------------------------------*/ + +/** @}*/
--- 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);
--- 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 *---------------------------------------------------------------------------*/ + +/** @}*/
--- 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 *---------------------------------------------------------------------------*/ + +/** @}*/
--- 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 *---------------------------------------------------------------------------*/ + +/** @}*/
--- 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 + +/** @}*/