my version
Fork of mbed-rtos by
Revision 118:6635230e06ba, committed 2016-07-25
- Comitter:
- Kojto
- Date:
- Mon Jul 25 14:12:24 2016 +0100
- Parent:
- 117:4c105b8d7cae
- Child:
- 119:19af2d39a542
- Commit message:
- RTOS rev118
Compatible with the mbed library v122
Changes:
- warnings about duplicated CM symbols fix
- init sequence update - allows init array to be run prior kernel start
- RTOS with OS_TIMERS=0 fix for thread id
- Thread ctor is deprecated, use start() method
- main stack fix for IAR (set via linker script)
- add TCB context pointer
- provide thread safety for toolchains (std lib locks)
- add MBED_RTOS_SINGLE_THREAD macro (sets TSKCNT to 1 and TIMERS to 0)
- nrf51, nucleo l423kc, nucleo f767zi, nucleo f446ze, efm32 support addition
- add OSObserver function
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed_lib.json Mon Jul 25 14:12:24 2016 +0100
@@ -0,0 +1,6 @@
+{
+ "name": "rtos",
+ "config": {
+ "present": 1
+ }
+}
--- a/rtos/Thread.cpp Mon May 23 11:00:15 2016 +0100
+++ b/rtos/Thread.cpp Mon Jul 25 14:12:24 2016 +0100
@@ -21,7 +21,7 @@
*/
#include "Thread.h"
-#include "mbed_error.h"
+#include "mbed.h"
#include "rtos_idle.h"
// rt_tid2ptcb is an internal function which we exposed to get TCB for thread id
@@ -32,34 +32,81 @@
namespace rtos {
-Thread::Thread(void (*task)(void const *argument), void *argument,
- osPriority priority, uint32_t stack_size, unsigned char *stack_pointer) {
+void Thread::constructor(osPriority priority,
+ uint32_t stack_size, unsigned char *stack_pointer) {
+ _tid = 0;
+ _dynamic_stack = (stack_pointer == NULL);
+
#if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM)
- _thread_def.pthread = task;
_thread_def.tpriority = priority;
_thread_def.stacksize = stack_size;
- if (stack_pointer != NULL) {
- _thread_def.stack_pointer = (uint32_t*)stack_pointer;
- _dynamic_stack = false;
- } else {
- _thread_def.stack_pointer = new uint32_t[stack_size/sizeof(uint32_t)];
+ _thread_def.stack_pointer = (uint32_t*)stack_pointer;
+#endif
+}
+
+void Thread::constructor(Callback<void()> task,
+ osPriority priority, uint32_t stack_size, unsigned char *stack_pointer) {
+ constructor(priority, stack_size, stack_pointer);
+
+ switch (start(task)) {
+ case osErrorResource:
+ error("OS ran out of threads!\n");
+ break;
+ case osErrorParameter:
+ error("Thread already running!\n");
+ break;
+ case osErrorNoMemory:
+ error("Error allocating the stack memory\n");
+ default:
+ break;
+ }
+}
+
+osStatus Thread::start(Callback<void()> task) {
+ if (_tid != 0) {
+ return osErrorParameter;
+ }
+
+#if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM)
+ _thread_def.pthread = (void (*)(const void *))Callback<void()>::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)
- error("Error allocating the stack memory\n");
- _dynamic_stack = true;
+ return osErrorNoMemory;
}
-
+
//Fill the stack with a magic word for maximum usage checking
- for (uint32_t i = 0; i < (stack_size / sizeof(uint32_t)); i++) {
+ for (uint32_t i = 0; i < (_thread_def.stacksize / sizeof(uint32_t)); i++) {
_thread_def.stack_pointer[i] = 0xE25A2EA5;
}
#endif
- _tid = osThreadCreate(&_thread_def, argument);
+ _task = task;
+ _tid = osThreadCreate(&_thread_def, &_task);
+ if (_tid == NULL) {
+ if (_dynamic_stack) delete[] (_thread_def.stack_pointer);
+ return osErrorResource;
+ }
+ return osOK;
}
osStatus Thread::terminate() {
return osThreadTerminate(_tid);
}
+osStatus Thread::join() {
+ while (true) {
+ uint8_t state = get_state();
+ if (state == Thread::Inactive || state == osErrorParameter) {
+ return osOK;
+ }
+
+ osStatus status = yield();
+ if (status != osOK) {
+ return status;
+ }
+ }
+}
+
osStatus Thread::set_priority(osPriority priority) {
return osThreadSetPriority(_tid, priority);
}
--- a/rtos/Thread.h Mon May 23 11:00:15 2016 +0100
+++ b/rtos/Thread.h Mon Jul 25 14:12:24 2016 +0100
@@ -24,23 +24,146 @@
#include <stdint.h>
#include "cmsis_os.h"
+#include "Callback.h"
+#include "toolchain.h"
namespace rtos {
/** The Thread class allow defining, creating, and controlling thread functions in the system. */
class Thread {
public:
+ /** Allocate a new thread without starting execution
+ @param priority initial priority of the thread function. (default: osPriorityNormal).
+ @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).
+ */
+ Thread(osPriority priority=osPriorityNormal,
+ uint32_t stack_size=DEFAULT_STACK_SIZE,
+ unsigned char *stack_pointer=NULL) {
+ constructor(priority, stack_size, stack_pointer);
+ }
+
/** Create a new thread, and start it executing the specified function.
@param task function to be executed by this thread.
@param argument pointer that is passed to the thread function as start argument. (default: NULL).
@param priority initial priority of the thread function. (default: osPriorityNormal).
@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.
+
+ The explicit Thread::start member function should be used to spawn
+ a thread.
*/
+ MBED_DEPRECATED(
+ "Thread-spawning constructors hide errors and may lead to complex "
+ "program state when a thread is declared")
+ Thread(mbed::Callback<void()> task,
+ osPriority priority=osPriorityNormal,
+ uint32_t stack_size=DEFAULT_STACK_SIZE,
+ unsigned char *stack_pointer=NULL) {
+ constructor(task, priority, stack_size, stack_pointer);
+ }
+
+ /** Create a new thread, and start it executing the specified function.
+ @param obj argument to task.
+ @param method function to be executed by this thread.
+ @param argument pointer that is passed to the thread function as start argument. (default: NULL).
+ @param priority initial priority of the thread function. (default: osPriorityNormal).
+ @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.
+
+ The explicit Thread::start member function should be used to spawn
+ a thread.
+ */
+ template <typename T>
+ MBED_DEPRECATED(
+ "Thread-spawning constructors hide errors and may lead to complex "
+ "program state when a thread is declared")
+ Thread(T *obj, void (T::*method)(),
+ osPriority priority=osPriorityNormal,
+ uint32_t stack_size=DEFAULT_STACK_SIZE,
+ unsigned char *stack_pointer=NULL) {
+ constructor(mbed::Callback<void()>(obj, method),
+ priority, stack_size, stack_pointer);
+ }
+
+ /** Create a new thread, and start it executing the specified function.
+ @param obj argument to task.
+ @param method function to be executed by this thread.
+ @param argument pointer that is passed to the thread function as start argument. (default: NULL).
+ @param priority initial priority of the thread function. (default: osPriorityNormal).
+ @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.
+
+ The explicit Thread::start member function should be used to spawn
+ a thread.
+ */
+ template <typename T>
+ MBED_DEPRECATED(
+ "Thread-spawning constructors hide errors and may lead to complex "
+ "program state when a thread is declared")
+ Thread(T *obj, void (*method)(T *),
+ osPriority priority=osPriorityNormal,
+ uint32_t stack_size=DEFAULT_STACK_SIZE,
+ unsigned char *stack_pointer=NULL) {
+ constructor(mbed::Callback<void()>(obj, method),
+ priority, stack_size, stack_pointer);
+ }
+
+ /** Create a new thread, and start it executing the specified function.
+ Provided for backwards compatibility
+ @param task function to be executed by this thread.
+ @param argument pointer that is passed to the thread function as start argument. (default: NULL).
+ @param priority initial priority of the thread function. (default: osPriorityNormal).
+ @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.
+
+ The explicit Thread::start member function should be used to spawn
+ a thread.
+ */
+ MBED_DEPRECATED(
+ "Thread-spawning constructors hide errors and may lead to complex "
+ "program state when a thread is declared")
Thread(void (*task)(void const *argument), void *argument=NULL,
osPriority priority=osPriorityNormal,
uint32_t stack_size=DEFAULT_STACK_SIZE,
- unsigned char *stack_pointer=NULL);
+ unsigned char *stack_pointer=NULL) {
+ constructor(mbed::Callback<void()>(argument, (void (*)(void *))task),
+ priority, stack_size, stack_pointer);
+ }
+
+ /** Starts a thread executing the specified function.
+ @param task function to be executed by this thread.
+ @return status code that indicates the execution status of the function.
+ */
+ osStatus start(mbed::Callback<void()> task);
+
+ /** Starts a thread executing the specified function.
+ @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.
+ */
+ template <typename T, typename M>
+ osStatus start(T *obj, M method) {
+ return start(mbed::Callback<void()>(obj, method));
+ }
+
+ /** Wait for thread to terminate
+ @return status code that indicates the execution status of the function.
+ @note not callable from interrupt
+ */
+ osStatus join();
/** Terminate execution of a thread and remove it from Active Threads
@return status code that indicates the execution status of the function.
@@ -113,17 +236,20 @@
@param signals wait until all specified signal flags set or 0 for any single signal flag.
@param millisec timeout value or 0 in case of no time-out. (default: osWaitForever).
@return event flag information or error code.
+ @note not callable from interrupt
*/
static osEvent signal_wait(int32_t signals, uint32_t millisec=osWaitForever);
/** Wait for a specified time period in millisec:
@param millisec time delay value
@return status code that indicates the execution status of the function.
+ @note not callable from interrupt
*/
static osStatus wait(uint32_t millisec);
/** Pass control to next thread that is in state READY.
@return status code that indicates the execution status of the function.
+ @note not callable from interrupt
*/
static osStatus yield();
@@ -140,6 +266,17 @@
virtual ~Thread();
private:
+ // Required to share definitions without
+ // delegated constructors
+ void constructor(osPriority priority=osPriorityNormal,
+ uint32_t stack_size=DEFAULT_STACK_SIZE,
+ unsigned char *stack_pointer=NULL);
+ void constructor(mbed::Callback<void()> task,
+ osPriority priority=osPriorityNormal,
+ uint32_t stack_size=DEFAULT_STACK_SIZE,
+ unsigned char *stack_pointer=NULL);
+
+ mbed::Callback<void()> _task;
osThreadId _tid;
osThreadDef_t _thread_def;
bool _dynamic_stack;
--- a/rtos/rtos.h Mon May 23 11:00:15 2016 +0100 +++ b/rtos/rtos.h Mon Jul 25 14:12:24 2016 +0100 @@ -32,4 +32,13 @@ using namespace rtos; +/* Get mbed lib version number, as RTOS depends on mbed lib features + like mbed_error, Callback and others. +*/ +#include "mbed.h" + +#if (MBED_LIBRARY_VERSION < 122) +#error "This version of RTOS requires mbed library version > 121" #endif + +#endif
--- a/rtx/TARGET_ARM7/RTX_CM_lib.h Mon May 23 11:00:15 2016 +0100
+++ b/rtx/TARGET_ARM7/RTX_CM_lib.h Mon Jul 25 14:12:24 2016 +0100
@@ -339,7 +339,7 @@
main(0, NULL);
}
-__attribute__((naked)) void software_init_hook (void) {
+__attribute__((naked)) void software_init_hook_rtos (void) {
__asm (
".syntax unified\n"
".thumb\n"
--- a/rtx/TARGET_CORTEX_A/RTX_CM_lib.h Mon May 23 11:00:15 2016 +0100
+++ b/rtx/TARGET_CORTEX_A/RTX_CM_lib.h Mon Jul 25 14:12:24 2016 +0100
@@ -50,7 +50,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 52
+#define OS_TCB_SIZE 60
#define OS_TMR_SIZE 8
#if defined (__CC_ARM) && !defined (__MICROLIB)
@@ -395,18 +395,22 @@
*---------------------------------------------------------------------------*/
/* Main Thread definition */
-extern int main (void);
+extern void pre_main (void);
#ifdef __MBED_CMSIS_RTOS_CA9
uint32_t os_thread_def_stack_main [(4 * OS_MAINSTKSIZE) / sizeof(uint32_t)];
-osThreadDef_t os_thread_def_main = {(os_pthread)main, osPriorityNormal, 1, 4*OS_MAINSTKSIZE, os_thread_def_stack_main };
+osThreadDef_t os_thread_def_main = {(os_pthread)pre_main, osPriorityNormal, 1, 4*OS_MAINSTKSIZE, os_thread_def_stack_main };
#else
-osThreadDef_t os_thread_def_main = {(os_pthread)main, osPriorityNormal, 1, 4*OS_MAINSTKSIZE };
+osThreadDef_t os_thread_def_main = {(os_pthread)pre_main, osPriorityNormal, 1, 4*OS_MAINSTKSIZE };
#endif
#if defined (__CC_ARM)
#ifdef __MICROLIB
+
+int main(void);
void _main_init (void) __attribute__((section(".ARM.Collect$$$$000000FF")));
+void $Super$$__cpp_initialize__aeabi_(void);
+
#if __TARGET_ARCH_ARM
#pragma push
#pragma arm
@@ -420,66 +424,134 @@
#if __TARGET_ARCH_ARM
#pragma pop
#endif
+
+void $Sub$$__cpp_initialize__aeabi_(void)
+{
+ // this should invoke C++ initializers prior _main_init, we keep this empty and
+ // invoke them after _main_init (=starts RTX kernel)
+}
+
+void pre_main()
+{
+ $Super$$__cpp_initialize__aeabi_();
+ main();
+}
+
#else
+
+void * armcc_heap_base;
+void * armcc_heap_top;
+
+__asm void pre_main (void)
+{
+ IMPORT __rt_lib_init
+ IMPORT main
+ IMPORT armcc_heap_base
+ IMPORT armcc_heap_top
+
+ LDR R0,=armcc_heap_base
+ LDR R1,=armcc_heap_top
+ LDR R0,[R0]
+ LDR R1,[R1]
+ /* Save link register (keep 8 byte alignment with dummy R4) */
+ PUSH {R4, LR}
+ BL __rt_lib_init
+ BL main
+ /* Return to the thread destroy function.
+ */
+ POP {R4, PC}
+ ALIGN
+}
+
__asm void __rt_entry (void) {
IMPORT __user_setup_stackheap
- IMPORT __rt_lib_init
IMPORT os_thread_def_main
+ IMPORT armcc_heap_base
+ IMPORT armcc_heap_top
IMPORT osKernelInitialize
IMPORT osKernelStart
IMPORT osThreadCreate
- IMPORT exit
BL __user_setup_stackheap
- MOV R1,R2
- BL __rt_lib_init
+ LDR R3,=armcc_heap_base
+ LDR R4,=armcc_heap_top
+ STR R0,[R3]
+ STR R2,[R4]
BL osKernelInitialize
LDR R0,=os_thread_def_main
MOVS R1,#0
BL osThreadCreate
BL osKernelStart
- BL exit
+ /* osKernelStart should not return */
+ B .
ALIGN
}
#endif
#elif defined (__GNUC__)
+extern void __libc_fini_array(void);
+extern void __libc_init_array (void);
+extern int main(int argc, char **argv);
-__attribute__((naked)) void software_init_hook (void) {
+void pre_main(void) {
+ atexit(__libc_fini_array);
+ __libc_init_array();
+ main(0, NULL);
+}
+
+__attribute__((naked)) void software_init_hook_rtos (void) {
__asm (
".syntax unified\n"
".arm\n"
- "movs r0,#0\n"
- "movs r1,#0\n"
- "mov r4,r0\n"
- "mov r5,r1\n"
- "ldr r0,= __libc_fini_array\n"
- "bl atexit\n"
- "bl __libc_init_array\n"
- "mov r0,r4\n"
- "mov r1,r5\n"
"bl osKernelInitialize\n"
"ldr r0,=os_thread_def_main\n"
"movs r1,#0\n"
"bl osThreadCreate\n"
"bl osKernelStart\n"
- "bl exit\n"
+ /* osKernelStart should not return */
+ "B .\n"
);
}
#elif defined (__ICCARM__)
+extern void* __vector_core_a9;
+extern int __low_level_init(void);
+extern void __iar_data_init3(void);
+extern __weak void __iar_init_core( void );
+extern __weak void __iar_init_vfp( void );
+extern void __iar_dynamic_initialization(void);
+extern void mbed_sdk_init(void);
+static uint8_t low_level_init_needed;
-extern void exit(int arg);
+void pre_main(void) {
+ if (low_level_init_needed) {
+ __iar_dynamic_initialization();
+ }
+ main();
+}
-void mbed_main(void) {
- int a;
-
+#pragma required=__vector_core_a9
+void __iar_program_start( void )
+{
+ __iar_init_core();
+ __iar_init_vfp();
+
+ uint8_t low_level_init_needed_local;
+
+ low_level_init_needed_local = __low_level_init();
+ if (low_level_init_needed_local) {
+ __iar_data_init3();
+ mbed_sdk_init();
+ }
+ /* Store in a global variable after RAM has been initialized */
+ low_level_init_needed = low_level_init_needed_local;
osKernelInitialize();
osThreadCreate(&os_thread_def_main, NULL);
- a = osKernelStart();
- exit(a);
+ osKernelStart();
+ /* osKernelStart should not return */
+ while (1);
}
#endif
--- a/rtx/TARGET_CORTEX_A/RTX_Conf_CA.c Mon May 23 11:00:15 2016 +0100 +++ b/rtx/TARGET_CORTEX_A/RTX_Conf_CA.c Mon Jul 25 14:12:24 2016 +0100 @@ -38,6 +38,11 @@ * RTX User configuration part BEGIN *---------------------------------------------------------------------------*/ +#if defined(MBED_RTOS_SINGLE_THREAD) +#define OS_TASKCNT 1 +#define OS_TIMERS 0 +#endif + //-------- <<< Use Configuration Wizard in Context Menu >>> ----------------- // // <h>Thread Configuration @@ -67,9 +72,9 @@ // <o>Main Thread stack size [bytes] <64-4096:8><#/4> // <i> Defines stack size for main thread. -// <i> Default: 200 +// <i> Default: 4096 #ifndef OS_MAINSTKSIZE - #define OS_MAINSTKSIZE 2048 + #define OS_MAINSTKSIZE 4096 #endif #ifndef __MBED_CMSIS_RTOS_CA9
--- a/rtx/TARGET_CORTEX_M/HAL_CM.c Mon May 23 11:00:15 2016 +0100
+++ b/rtx/TARGET_CORTEX_M/HAL_CM.c Mon Jul 25 14:12:24 2016 +0100
@@ -35,7 +35,7 @@
#include "rt_TypeDef.h"
#include "RTX_Config.h"
#include "rt_HAL_CM.h"
-
+#include "cmsis_os.h"
/*----------------------------------------------------------------------------
* Global Variables
@@ -93,12 +93,12 @@
#ifdef __MBED_CMSIS_RTOS_CM
/* Set a magic word for checking of stack overflow.
- For the main thread (ID: 0x02) the stack is in a memory area shared with the
+ 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 != 0x02) {
+ if (p_TCB->task_id != MAIN_THREAD_ID) {
p_TCB->stack[0] = MAGIC_WORD;
/* Initialize stack with magic pattern. */
--- a/rtx/TARGET_CORTEX_M/RTX_CM_lib.h Mon May 23 11:00:15 2016 +0100
+++ b/rtx/TARGET_CORTEX_M/RTX_CM_lib.h Mon Jul 25 14:12:24 2016 +0100
@@ -51,16 +51,16 @@
#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 52
+#define OS_TCB_SIZE 60
#define OS_TMR_SIZE 8
-#if defined (__CC_ARM) && !defined (__MICROLIB)
-
typedef void *OS_ID;
typedef uint32_t OS_TID;
typedef uint32_t OS_MUT[4];
typedef uint32_t OS_RESULT;
+#if defined (__CC_ARM) && !defined (__MICROLIB)
+
#define runtask_id() rt_tsk_self()
#define mutex_init(m) rt_mut_init(m)
#define mutex_wait(m) os_mut_wait(m,0xFFFFU)
@@ -122,7 +122,11 @@
uint16_t const os_tickus_i = OS_CLOCK/1000000;
uint16_t const os_tickus_f = (((uint64_t)(OS_CLOCK-1000000*(OS_CLOCK/1000000)))<<16)/1000000;
uint32_t const os_trv = OS_TRV;
+#if defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)
+uint8_t const os_flags = 0;
+#else /* defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED) */
uint8_t const os_flags = OS_RUNPRIV;
+#endif /* defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED) */
/* Export following defines to uVision debugger. */
__USED uint32_t const CMSIS_RTOS_API_Version = osCMSIS;
@@ -178,7 +182,7 @@
#endif
/* Legacy RTX User Timers not used */
-uint32_t os_tmr = 0U;
+uint32_t os_tmr = 0U;
uint32_t const *m_tmr = NULL;
uint16_t const mp_tmr_size = 0U;
@@ -190,6 +194,77 @@
extern void *__libspace_start;
#endif
+#if defined (__ICCARM__)
+static osMutexId std_mutex_id_sys[_MAX_LOCK] = {0};
+static OS_MUT std_mutex_sys[_MAX_LOCK] = {0};
+#define _FOPEN_MAX 10
+static osMutexId std_mutex_id_file[_FOPEN_MAX] = {0};
+static OS_MUT std_mutex_file[_FOPEN_MAX] = {0};
+void __iar_system_Mtxinit(__iar_Rmtx *mutex) /* Initialize a system lock */
+{
+ osMutexDef_t def;
+ uint32_t index;
+ for (index = 0; index < _MAX_LOCK; index++) {
+ if (0 == std_mutex_id_sys[index]) {
+ def.mutex = &std_mutex_sys[index];
+ std_mutex_id_sys[index] = osMutexCreate(&def);
+ *mutex = (__iar_Rmtx*)&std_mutex_id_sys[index];
+ return;
+ }
+ }
+ // This should never happen
+ error("Not enough mutexes\n");
+}
+
+void __iar_system_Mtxdst(__iar_Rmtx *mutex)/*Destroy a system lock */
+{
+ osMutexDelete(*(osMutexId*)*mutex);
+ *mutex = 0;
+}
+
+void __iar_system_Mtxlock(__iar_Rmtx *mutex) /* Lock a system lock */
+{
+ osMutexWait(*(osMutexId*)*mutex, osWaitForever);
+}
+
+void __iar_system_Mtxunlock(__iar_Rmtx *mutex) /* Unlock a system lock */
+{
+ osMutexRelease(*(osMutexId*)*mutex);
+}
+
+void __iar_file_Mtxinit(__iar_Rmtx *mutex)/*Initialize a file lock */
+{
+ osMutexDef_t def;
+ uint32_t index;
+ for (index = 0; index < _FOPEN_MAX; index++) {
+ if (0 == std_mutex_id_file[index]) {
+ def.mutex = &std_mutex_file[index];
+ std_mutex_id_file[index] = osMutexCreate(&def);
+ *mutex = (__iar_Rmtx*)&std_mutex_id_file[index];
+ return;
+ }
+ }
+ // The variable _FOPEN_MAX needs to be increased
+ error("Not enough mutexes\n");
+}
+
+void __iar_file_Mtxdst(__iar_Rmtx *mutex) /* Destroy a file lock */
+{
+ osMutexDelete(*(osMutexId*)*mutex);
+ *mutex = 0;
+}
+
+void __iar_file_Mtxlock(__iar_Rmtx *mutex) /* Lock a file lock */
+{
+ osMutexWait(*(osMutexId*)*mutex, osWaitForever);
+}
+
+void __iar_file_Mtxunlock(__iar_Rmtx *mutex) /* Unlock a file lock */
+{
+ osMutexRelease(*(osMutexId*)*mutex);
+}
+
+#endif
/*----------------------------------------------------------------------------
* RTX Optimizations (empty functions)
@@ -301,7 +376,12 @@
#define INITIAL_SP (0x20003000UL)
#elif defined(TARGET_K64F)
+#if defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)
+extern uint32_t __StackTop[];
+#define INITIAL_SP (__StackTop)
+#else
#define INITIAL_SP (0x20030000UL)
+#endif
#elif defined(TARGET_K22F)
#define INITIAL_SP (0x20010000UL)
@@ -402,12 +482,15 @@
#elif defined(TARGET_NZ32_SC151)
#define INITIAL_SP (0x20008000UL)
-#elif (defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE))
+#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)
@@ -420,6 +503,23 @@
#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)
+
+#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_STM32F767ZI))
+#define INITIAL_SP (0x20080000UL)
#else
#error "no target defined"
@@ -434,15 +534,28 @@
#define HEAP_START (__end__)
#elif defined(__ICCARM__)
#pragma section="HEAP"
-#define HEAP_START (void *)__section_begin("HEAP")
+#define HEAP_END (void *)__section_end("HEAP")
#endif
void set_main_stack(void) {
+ uint32_t interrupt_stack_size = ((uint32_t)OS_MAINSTKSIZE * 4);
+#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 */
+ uint32_t heap_plus_stack_size = ((uint32_t)INITIAL_SP - (uint32_t)HEAP_START) - interrupt_stack_size;
+ // Main thread's stack is 1/4 of the heap
+ uint32_t main_stack_size = heap_plus_stack_size/4;
+#endif
+ // The main thread must be 4 byte aligned
+ uint32_t main_stack_start = ((uint32_t)INITIAL_SP - interrupt_stack_size - main_stack_size) & ~0x7;
+
// That is the bottom of the main stack block: no collision detection
- os_thread_def_main.stack_pointer = HEAP_START;
+ os_thread_def_main.stack_pointer = (uint32_t*)main_stack_start;
// Leave OS_MAINSTKSIZE words for the scheduler and interrupts
- os_thread_def_main.stacksize = (INITIAL_SP - (unsigned int)HEAP_START) - (OS_MAINSTKSIZE * 4);
+ os_thread_def_main.stacksize = main_stack_size;
}
#if defined (__CC_ARM)
@@ -553,20 +666,25 @@
#elif defined (__GNUC__)
+osMutexDef(malloc_mutex);
+static osMutexId malloc_mutex_id;
+osMutexDef(env_mutex);
+static osMutexId env_mutex_id;
+
extern void __libc_fini_array(void);
extern void __libc_init_array (void);
extern int main(int argc, char **argv);
void pre_main(void) {
+ malloc_mutex_id = osMutexCreate(osMutex(malloc_mutex));
+ env_mutex_id = osMutexCreate(osMutex(env_mutex));
atexit(__libc_fini_array);
__libc_init_array();
main(0, NULL);
}
-__attribute__((naked)) void software_init_hook (void) {
+__attribute__((naked)) void software_init_hook_rtos (void) {
__asm (
- ".syntax unified\n"
- ".thumb\n"
"bl osKernelInitialize\n"
#ifdef __MBED_CMSIS_RTOS_CM
"bl set_main_stack\n"
@@ -580,6 +698,29 @@
);
}
+// Opaque declaration of _reent structure
+struct _reent;
+
+void __rtos_malloc_lock( struct _reent *_r )
+{
+ osMutexWait(malloc_mutex_id, osWaitForever);
+}
+
+void __rtos_malloc_unlock( struct _reent *_r )
+{
+ osMutexRelease(malloc_mutex_id);
+}
+
+void __rtos_env_lock( struct _reent *_r )
+{
+ osMutexWait(env_mutex_id, osWaitForever);
+}
+
+void __rtos_env_unlock( struct _reent *_r )
+{
+ osMutexRelease(env_mutex_id);
+}
+
#elif defined (__ICCARM__)
extern void* __vector_table;
@@ -589,6 +730,8 @@
extern __weak void __iar_init_vfp( void );
extern void __iar_dynamic_initialization(void);
extern void mbed_sdk_init(void);
+extern void mbed_main(void);
+extern int main(void);
extern void exit(int arg);
static uint8_t low_level_init_needed;
@@ -597,6 +740,7 @@
if (low_level_init_needed) {
__iar_dynamic_initialization();
}
+ mbed_main();
main();
}
--- a/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c Mon May 23 11:00:15 2016 +0100
+++ b/rtx/TARGET_CORTEX_M/RTX_Conf_CM.c Mon Jul 25 14:12:24 2016 +0100
@@ -51,13 +51,15 @@
# 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_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_TEENSY3_1) \
- || defined(TARGET_STM32L152RE) || defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE) || defined(TARGET_STM32L476VG) || defined(TARGET_STM32L476RG) || defined(TARGET_STM32F469NI) || defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG) || defined(TARGET_STM32L152RC)
+ || 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)
# 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_SSCI824) || defined(TARGET_STM32F030R8) || defined(TARGET_STM32F070RB) \
+ || defined(TARGET_EFM32HG_STK3400) || defined(TARGET_MCU_NRF51822) || defined(TARGET_BEETLE)
# define OS_TASKCNT 6
# else
# error "no target defined"
@@ -84,15 +86,21 @@
# 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_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_TEENSY3_1) \
- || defined(TARGET_STM32L152RE) || defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE) || defined(TARGET_STM32L476VG) || defined(TARGET_STM32L476RG) || defined(TARGET_STM32F469NI) || defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG) || defined(TARGET_STM32L152RC)
+ || 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)
# 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_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)
+# 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)
+# define OS_MAINSTKSIZE 512
# else
# error "no target defined"
# endif
@@ -105,7 +113,7 @@
#ifndef OS_PRIVCNT
#define OS_PRIVCNT 0
#endif
-
+
// <o>Total stack size [bytes] for threads with user-provided stack size <0-1048576:8><#/4>
// <i> Defines the combined stack size for threads with user-provided stack size.
// <i> Default: 0
@@ -120,16 +128,16 @@
#ifndef OS_STKCHECK
#define OS_STKCHECK 1
#endif
-
+
// <q>Stack usage watermark
// <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
#endif
-
-// <o>Processor mode for thread execution
-// <0=> Unprivileged mode
+
+// <o>Processor mode for thread execution
+// <0=> Unprivileged mode
// <1=> Privileged mode
// <i> Default: Privileged mode
#ifndef OS_RUNPRIV
@@ -137,19 +145,23 @@
#endif
// </h>
-
+
// <h>RTX Kernel Timer Tick Configuration
// ======================================
// <q> Use Cortex-M SysTick timer as RTX Kernel Timer
-// <i> Cortex-M processors provide in most cases a SysTick timer that can be used as
+// <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
- #define OS_SYSTICK 1
+# if defined(TARGET_MCU_NRF51822)
+# define OS_SYSTICK 0
+# else
+# define OS_SYSTICK 1
+# endif
#endif
//
// <o>RTOS Kernel Timer input clock frequency [Hz] <1-1000000000>
-// <i> Defines the input frequency of the RTOS Kernel Timer.
-// <i> When the Cortex-M SysTick timer is used, the input clock
+// <i> Defines the input frequency of the RTOS Kernel Timer.
+// <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)
@@ -171,7 +183,7 @@
# elif defined(TARGET_LPC824) || defined(TARGET_SSCI824)
# define OS_CLOCK 30000000
-# elif defined(TARGET_STM32F100RB)
+# elif defined(TARGET_STM32F100RB) || defined(TARGET_BEETLE)
# define OS_CLOCK 24000000
# elif defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM) || defined(TARGET_K64F) || defined(TARGET_K22F)
@@ -210,7 +222,7 @@
#elif defined(TARGET_STM32F401VC)
# define OS_CLOCK 84000000
-# elif defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG)
+# elif defined(TARGET_STM32F746NG) || defined(TARGET_STM32F746ZG) || defined(TARGET_STM32F767ZI)
# define OS_CLOCK 216000000
#elif defined(TARGET_MAX32610) || defined(TARGET_MAX32600)
@@ -222,7 +234,7 @@
#elif defined(TARGET_STM32L152RE)
# define OS_CLOCK 24000000
-#elif (defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446VE))
+#elif defined(TARGET_STM32F446RE) || defined(TARGET_STM32F446ZE) || defined(TARGET_STM32F446VE)
# define OS_CLOCK 180000000
#elif defined(TARGET_STM32F030R8)
@@ -231,7 +243,7 @@
#elif defined(TARGET_STM32F070RB)
# define OS_CLOCK 48000000
-#elif defined(TARGET_STM32L476VG) || defined(TARGET_STM32L476RG)
+#elif defined(TARGET_STM32L432KC) || defined(TARGET_STM32L476VG) || defined(TARGET_STM32L476RG)
# define OS_CLOCK 80000000
#elif defined(TARGET_STM32F469NI)
@@ -240,11 +252,18 @@
#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
+
# else
# error "no target defined"
# endif
#endif
-
+
// <o>RTX Timer tick interval value [us] <1-1000000>
// <i> The RTX Timer tick interval value is used to calculate timeout values.
// <i> When the Cortex-M SysTick timer is enabled, the value also configures the SysTick timer.
@@ -292,14 +311,14 @@
#ifndef OS_TIMERPRIO
#define OS_TIMERPRIO 5
#endif
-
+
// <o>Timer Thread stack size [bytes] <64-4096:8><#/4>
// <i> Defines stack size for Timer thread.
// <i> Default: 200
#ifndef OS_TIMERSTKSZ
#define OS_TIMERSTKSZ 200
#endif
-
+
// <o>Timer Callback Queue size <1-32>
// <i> Number of concurrent active timer callback functions.
// <i> Default: 4
--- a/rtx/TARGET_CORTEX_M/cmsis_os.h Mon May 23 11:00:15 2016 +0100 +++ b/rtx/TARGET_CORTEX_M/cmsis_os.h Mon Jul 25 14:12:24 2016 +0100 @@ -57,9 +57,13 @@ #define CMSIS_OS_RTX // __MBED_CMSIS_RTOS_CM captures our changes to the RTX kernel +#ifndef __MBED_CMSIS_RTOS_CM #define __MBED_CMSIS_RTOS_CM +#endif // we use __CMSIS_RTOS version, which changes some API in the kernel +#ifndef __CMSIS_RTOS #define __CMSIS_RTOS +#endif // The stack space occupied is mainly dependent on the underling C standard library #if defined(TOOLCHAIN_GCC) || defined(TOOLCHAIN_ARM_STD) || defined(TOOLCHAIN_IAR) @@ -68,6 +72,24 @@ # define WORDS_STACK_SIZE 128 #endif +#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 +#endif + +/* If os timers macro is set to 0, there's no timer thread created, therefore + * main thread has tid 0x01 + */ +#if (OS_TIMERS != 0) +#define MAIN_THREAD_ID 0x02 +#else +#define MAIN_THREAD_ID 0x01 +#endif +#endif + #define DEFAULT_STACK_SIZE (WORDS_STACK_SIZE*4) #define osCMSIS 0x10002U ///< CMSIS-RTOS API version (main [31:16] .sub [15:0]) @@ -313,6 +335,8 @@ /// \return thread ID for reference by other functions or NULL in case of error. osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument); +osThreadId osThreadContextCreate (const osThreadDef_t *thread_def, void *argument, void *context); + /// Return the thread ID of the current running thread. /// \return thread ID for reference by other functions or NULL in case of error. osThreadId osThreadGetId (void);
--- a/rtx/TARGET_CORTEX_M/rt_CMSIS.c Mon May 23 11:00:15 2016 +0100
+++ b/rtx/TARGET_CORTEX_M/rt_CMSIS.c Mon Jul 25 14:12:24 2016 +0100
@@ -65,6 +65,7 @@
#include "rt_MemBox.h"
#include "rt_Memory.h"
#include "rt_HAL_CM.h"
+#include "rt_OsEventObserver.h"
#include "cmsis_os.h"
@@ -301,7 +302,7 @@
#define SVC_Setup(f) \
__asm( \
"mov r12,%0\n" \
- :: "r"(&f): "r12" \
+ :: "r"(&f): "r0", "r1", "r2", "r3", "r12" \
);
#define SVC_Ret3() \
@@ -458,7 +459,7 @@
SVC_0_1(svcKernelSysTick, uint32_t, RET_uint32_t)
static void sysThreadError (osStatus status);
-osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument);
+osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument, void *context);
osMessageQId svcMessageCreate (const osMessageQDef_t *queue_def, osThreadId thread_id);
// Kernel Control Service Calls
@@ -488,7 +489,7 @@
if (os_initialized == 0U) {
// Create OS Timers resources (Message Queue & Thread)
osMessageQId_osTimerMessageQ = svcMessageCreate (&os_messageQ_def_osTimerMessageQ, NULL);
- osThreadId_osTimerThread = svcThreadCreate(&os_thread_def_osTimerThread, NULL);
+ osThreadId_osTimerThread = svcThreadCreate(&os_thread_def_osTimerThread, NULL, NULL);
}
sysThreadError(osOK);
@@ -562,6 +563,15 @@
if (__get_IPSR() != 0U) {
return osErrorISR; // Not allowed in ISR
}
+
+ /* Call the pre-start event (from unprivileged mode) if the handler exists
+ * and the kernel is not running. */
+ /* FIXME osEventObs needs to be readable but not writable from unprivileged
+ * code. */
+ if (!osKernelRunning() && osEventObs && osEventObs->pre_start) {
+ osEventObs->pre_start();
+ }
+
switch (__get_CONTROL() & 0x03U) {
case 0x00U: // Privileged Thread mode & MSP
__set_PSP((uint32_t)(stack + 8)); // Initial PSP
@@ -616,7 +626,7 @@
__NO_RETURN void osThreadExit (void);
// Thread Service Calls declarations
-SVC_2_1(svcThreadCreate, osThreadId, const osThreadDef_t *, void *, RET_pointer)
+SVC_3_1(svcThreadCreate, osThreadId, const osThreadDef_t *, void *, void *, RET_pointer)
SVC_0_1(svcThreadGetId, osThreadId, RET_pointer)
SVC_1_1(svcThreadTerminate, osStatus, osThreadId, RET_osStatus)
SVC_0_1(svcThreadYield, osStatus, RET_osStatus)
@@ -626,7 +636,7 @@
// Thread Service Calls
/// Create a thread and add it to Active Threads and set it to state READY
-osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument) {
+osThreadId svcThreadCreate (const osThreadDef_t *thread_def, void *argument, void *context) {
P_TCB ptcb;
OS_TID tsk;
void *stk;
@@ -683,6 +693,12 @@
*((uint32_t *)ptcb->tsk_stack + 13) = (uint32_t)osThreadExit;
+ if (osEventObs && osEventObs->thread_create) {
+ ptcb->context = osEventObs->thread_create(ptcb->task_id, context);
+ } else {
+ ptcb->context = context;
+ }
+
return ptcb;
}
@@ -712,6 +728,10 @@
stk = ptcb->priv_stack ? ptcb->stack : NULL; // Private stack
#endif
+ if (osEventObs && osEventObs->thread_destroy) {
+ osEventObs->thread_destroy(ptcb->context);
+ }
+
res = rt_tsk_delete(ptcb->task_id); // Delete task
if (res == OS_R_NOK) {
@@ -776,14 +796,17 @@
/// Create a thread and add it to Active Threads and set it to state READY
osThreadId osThreadCreate (const osThreadDef_t *thread_def, void *argument) {
- if (__get_IPSR() != 0U) {
+ return osThreadContextCreate(thread_def, argument, NULL);
+}
+osThreadId osThreadContextCreate (const osThreadDef_t *thread_def, void *argument, void *context) {
+ if (__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);
+ return svcThreadCreate(thread_def, argument, context);
} else {
- return __svcThreadCreate(thread_def, argument);
+ return __svcThreadCreate(thread_def, argument, context);
}
}
--- a/rtx/TARGET_CORTEX_M/rt_HAL_CM.h Mon May 23 11:00:15 2016 +0100
+++ b/rtx/TARGET_CORTEX_M/rt_HAL_CM.h Mon Jul 25 14:12:24 2016 +0100
@@ -255,7 +255,11 @@
if (prigroup >= sh) {
sh = prigroup + 1U;
}
+
+/* Only change the SVCall priority if uVisor is not present. */
+#if !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED))
NVIC_SYS_PRI2 = ((0xFEFFFFFFU << sh) & 0xFF000000U) | (NVIC_SYS_PRI2 & 0x00FFFFFFU);
+#endif /* !(defined(FEATURE_UVISOR) && defined(TARGET_UVISOR_SUPPORTED)) */
#endif
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rtx/TARGET_CORTEX_M/rt_OsEventObserver.c Mon Jul 25 14:12:24 2016 +0100
@@ -0,0 +1,61 @@
+/*----------------------------------------------------------------------------
+ * CMSIS-RTOS - RTX
+ *----------------------------------------------------------------------------
+ * Name: rt_OsEventObserver.c
+ * Purpose: OS Event Callbacks for CMSIS RTOS
+ * Rev.: VX.XX
+ *----------------------------------------------------------------------------
+ *
+ * Copyright (c) 1999-2009 KEIL, 2009-2015 ARM Germany GmbH
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *---------------------------------------------------------------------------*/
+
+#include "rt_OsEventObserver.h"
+
+/*
+ * _____ _____ ____ __ _____
+ * | ___|_ _\ \/ / \/ | ____|
+ * | |_ | | \ /| |\/| | _|
+ * | _| | | / \| | | | |___
+ * |_| |___/_/\_\_| |_|_____|
+ *
+ * FIXME:
+ * The osEventObs variable must be in protected memory. If not every box
+ * and box 0 can modify osEventObs to point to any handler to run code
+ * privileged. This issue is tracked at
+ * <https://github.com/ARMmbed/uvisor/issues/235>.
+ */
+const OsEventObserver *osEventObs;
+
+void osRegisterForOsEvents(const OsEventObserver *observer)
+{
+ static uint8_t has_been_called = 0;
+ if (has_been_called) {
+ return;
+ }
+ has_been_called = 1;
+
+ osEventObs = observer;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/rtx/TARGET_CORTEX_M/rt_OsEventObserver.h Mon Jul 25 14:12:24 2016 +0100
@@ -0,0 +1,58 @@
+/*----------------------------------------------------------------------------
+ * CMSIS-RTOS - RTX
+ *----------------------------------------------------------------------------
+ * Name: os_events.h
+ * Purpose: OS Event Callbacks for CMSIS RTOS
+ * Rev.: VX.XX
+ *----------------------------------------------------------------------------
+ *
+ * Copyright (c) 1999-2009 KEIL, 2009-2016 ARM Germany GmbH
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - Neither the name of ARM nor the names of its contributors may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *---------------------------------------------------------------------------*/
+#ifndef _RT_OS_EVENT_OBSERVER_H
+#define _RT_OS_EVENT_OBSERVER_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ uint32_t version;
+ void (*pre_start)(void);
+ void *(*thread_create)(int thread_id, void *context);
+ void (*thread_destroy)(void *context);
+ void (*thread_switch)(void *context);
+} OsEventObserver;
+extern const OsEventObserver *osEventObs;
+
+void osRegisterForOsEvents(const OsEventObserver *observer);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
--- a/rtx/TARGET_CORTEX_M/rt_System.c Mon May 23 11:00:15 2016 +0100
+++ b/rtx/TARGET_CORTEX_M/rt_System.c Mon Jul 25 14:12:24 2016 +0100
@@ -315,7 +315,7 @@
__weak void rt_stk_check (void) {
#ifdef __MBED_CMSIS_RTOS_CM
/* Check for stack overflow. */
- if (os_tsk.run->task_id == 0x02) {
+ 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) ||
--- a/rtx/TARGET_CORTEX_M/rt_Task.c Mon May 23 11:00:15 2016 +0100
+++ b/rtx/TARGET_CORTEX_M/rt_Task.c Mon Jul 25 14:12:24 2016 +0100
@@ -40,6 +40,7 @@
#include "rt_MemBox.h"
#include "rt_Robin.h"
#include "rt_HAL_CM.h"
+#include "rt_OsEventObserver.h"
/*----------------------------------------------------------------------------
* Global Variables
@@ -101,6 +102,9 @@
/* Switch to next task (identified by "p_new"). */
os_tsk.new_tsk = p_new;
p_new->state = RUNNING;
+ if (osEventObs && osEventObs->thread_switch) {
+ osEventObs->thread_switch(p_new->context);
+ }
DBG_TASK_SWITCH(p_new->task_id);
}
@@ -402,6 +406,10 @@
os_tsk.run = &os_idle_TCB;
os_tsk.run->state = RUNNING;
+ /* Set the current thread to idle, so that on exit from this SVCall we do not
+ * de-reference a NULL TCB. */
+ rt_switch_req(&os_idle_TCB);
+
/* Initialize ps queue */
os_psq->first = 0U;
os_psq->last = 0U;
--- a/rtx/TARGET_CORTEX_M/rt_TypeDef.h Mon May 23 11:00:15 2016 +0100 +++ b/rtx/TARGET_CORTEX_M/rt_TypeDef.h Mon Jul 25 14:12:24 2016 +0100 @@ -79,6 +79,7 @@ /* Task entry point used for uVision debugger */ FUNCP ptask; /* Task entry address */ + void *context; /* Pointer to thread context */ } *P_TCB; #define TCB_STACKF 37 /* 'stack_frame' offset */ #define TCB_TSTACK 44 /* 'tsk_stack' offset */
