Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
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 + +/** @}*/