diff --git a/rtos/rtos/Thread.cpp b/rtos/rtos/Thread.cpp index 004e651a64..56415264c2 100644 --- a/rtos/rtos/Thread.cpp +++ b/rtos/rtos/Thread.cpp @@ -32,34 +32,82 @@ extern "C" P_TCB rt_tid2ptcb(osThreadId thread_id); namespace rtos { -Thread::Thread(void (*task)(void const *argument), void *argument, - osPriority priority, uint32_t stack_size, unsigned char *stack_pointer) { +Thread::Thread(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)]; - if (_thread_def.stack_pointer == NULL) + _thread_def.stack_pointer = (uint32_t*)stack_pointer; +#endif +} + +Thread::Thread(void (*task)(void const *argument), void *argument, + 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.tpriority = priority; + _thread_def.stacksize = stack_size; + _thread_def.stack_pointer = (uint32_t*)stack_pointer; +#endif + switch (start(task, argument)) { + 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"); - _dynamic_stack = true; + default: + break; } - +} + +osStatus Thread::start(void (*task)(void const *argument), void *argument) { + if (_tid != NULL) { + return osErrorParameter; + } + +#if defined(__MBED_CMSIS_RTOS_CA9) || defined(__MBED_CMSIS_RTOS_CM) + _thread_def.pthread = task; + 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) + 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); + 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); } diff --git a/rtos/rtos/Thread.h b/rtos/rtos/Thread.h index 3e787983ab..275f6fe5c9 100644 --- a/rtos/rtos/Thread.h +++ b/rtos/rtos/Thread.h @@ -30,6 +30,15 @@ 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); + /** 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). @@ -42,6 +51,19 @@ public: uint32_t stack_size=DEFAULT_STACK_SIZE, unsigned char *stack_pointer=NULL); + /** Starts a thread 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). + @return status code that indicates the execution status of the function. + */ + osStatus start(void (*task)(void const *argument), void *argument=NULL); + + /** 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 +135,20 @@ public: @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();