Rtos API example

Committer:
marcozecchini
Date:
Sat Feb 23 12:13:36 2019 +0000
Revision:
0:9fca2b23d0ba
final commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
marcozecchini 0:9fca2b23d0ba 1 /* mbed Microcontroller Library
marcozecchini 0:9fca2b23d0ba 2 * Copyright (c) 2006-2012 ARM Limited
marcozecchini 0:9fca2b23d0ba 3 *
marcozecchini 0:9fca2b23d0ba 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
marcozecchini 0:9fca2b23d0ba 5 * of this software and associated documentation files (the "Software"), to deal
marcozecchini 0:9fca2b23d0ba 6 * in the Software without restriction, including without limitation the rights
marcozecchini 0:9fca2b23d0ba 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
marcozecchini 0:9fca2b23d0ba 8 * copies of the Software, and to permit persons to whom the Software is
marcozecchini 0:9fca2b23d0ba 9 * furnished to do so, subject to the following conditions:
marcozecchini 0:9fca2b23d0ba 10 *
marcozecchini 0:9fca2b23d0ba 11 * The above copyright notice and this permission notice shall be included in
marcozecchini 0:9fca2b23d0ba 12 * all copies or substantial portions of the Software.
marcozecchini 0:9fca2b23d0ba 13 *
marcozecchini 0:9fca2b23d0ba 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
marcozecchini 0:9fca2b23d0ba 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
marcozecchini 0:9fca2b23d0ba 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
marcozecchini 0:9fca2b23d0ba 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
marcozecchini 0:9fca2b23d0ba 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
marcozecchini 0:9fca2b23d0ba 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
marcozecchini 0:9fca2b23d0ba 20 * SOFTWARE.
marcozecchini 0:9fca2b23d0ba 21 */
marcozecchini 0:9fca2b23d0ba 22 #include "rtos/Thread.h"
marcozecchini 0:9fca2b23d0ba 23
marcozecchini 0:9fca2b23d0ba 24 #include "mbed.h"
marcozecchini 0:9fca2b23d0ba 25 #include "rtos/rtos_idle.h"
marcozecchini 0:9fca2b23d0ba 26 #include "mbed_assert.h"
marcozecchini 0:9fca2b23d0ba 27
marcozecchini 0:9fca2b23d0ba 28 #define ALIGN_UP(pos, align) ((pos) % (align) ? (pos) + ((align) - (pos) % (align)) : (pos))
marcozecchini 0:9fca2b23d0ba 29 MBED_STATIC_ASSERT(ALIGN_UP(0, 8) == 0, "ALIGN_UP macro error");
marcozecchini 0:9fca2b23d0ba 30 MBED_STATIC_ASSERT(ALIGN_UP(1, 8) == 8, "ALIGN_UP macro error");
marcozecchini 0:9fca2b23d0ba 31
marcozecchini 0:9fca2b23d0ba 32 #define ALIGN_DOWN(pos, align) ((pos) - ((pos) % (align)))
marcozecchini 0:9fca2b23d0ba 33 MBED_STATIC_ASSERT(ALIGN_DOWN(7, 8) == 0, "ALIGN_DOWN macro error");
marcozecchini 0:9fca2b23d0ba 34 MBED_STATIC_ASSERT(ALIGN_DOWN(8, 8) == 8, "ALIGN_DOWN macro error");
marcozecchini 0:9fca2b23d0ba 35
marcozecchini 0:9fca2b23d0ba 36 static void (*terminate_hook)(osThreadId_t id) = 0;
marcozecchini 0:9fca2b23d0ba 37 extern "C" void thread_terminate_hook(osThreadId_t id)
marcozecchini 0:9fca2b23d0ba 38 {
marcozecchini 0:9fca2b23d0ba 39 if (terminate_hook != (void (*)(osThreadId_t))NULL) {
marcozecchini 0:9fca2b23d0ba 40 terminate_hook(id);
marcozecchini 0:9fca2b23d0ba 41 }
marcozecchini 0:9fca2b23d0ba 42 }
marcozecchini 0:9fca2b23d0ba 43
marcozecchini 0:9fca2b23d0ba 44 namespace rtos {
marcozecchini 0:9fca2b23d0ba 45
marcozecchini 0:9fca2b23d0ba 46 void Thread::constructor(osPriority priority,
marcozecchini 0:9fca2b23d0ba 47 uint32_t stack_size, unsigned char *stack_mem, const char *name) {
marcozecchini 0:9fca2b23d0ba 48
marcozecchini 0:9fca2b23d0ba 49 const uintptr_t unaligned_mem = reinterpret_cast<uintptr_t>(stack_mem);
marcozecchini 0:9fca2b23d0ba 50 const uintptr_t aligned_mem = ALIGN_UP(unaligned_mem, 8);
marcozecchini 0:9fca2b23d0ba 51 const uint32_t offset = aligned_mem - unaligned_mem;
marcozecchini 0:9fca2b23d0ba 52 const uint32_t aligned_size = ALIGN_DOWN(stack_size - offset, 8);
marcozecchini 0:9fca2b23d0ba 53
marcozecchini 0:9fca2b23d0ba 54 _tid = 0;
marcozecchini 0:9fca2b23d0ba 55 _dynamic_stack = (stack_mem == NULL);
marcozecchini 0:9fca2b23d0ba 56 _finished = false;
marcozecchini 0:9fca2b23d0ba 57 memset(&_obj_mem, 0, sizeof(_obj_mem));
marcozecchini 0:9fca2b23d0ba 58 memset(&_attr, 0, sizeof(_attr));
marcozecchini 0:9fca2b23d0ba 59 _attr.priority = priority;
marcozecchini 0:9fca2b23d0ba 60 _attr.stack_size = aligned_size;
marcozecchini 0:9fca2b23d0ba 61 _attr.name = name ? name : "application_unnamed_thread";
marcozecchini 0:9fca2b23d0ba 62 _attr.stack_mem = reinterpret_cast<uint32_t*>(aligned_mem);
marcozecchini 0:9fca2b23d0ba 63 }
marcozecchini 0:9fca2b23d0ba 64
marcozecchini 0:9fca2b23d0ba 65 void Thread::constructor(Callback<void()> task,
marcozecchini 0:9fca2b23d0ba 66 osPriority priority, uint32_t stack_size, unsigned char *stack_mem, const char *name) {
marcozecchini 0:9fca2b23d0ba 67 constructor(priority, stack_size, stack_mem, name);
marcozecchini 0:9fca2b23d0ba 68
marcozecchini 0:9fca2b23d0ba 69 switch (start(task)) {
marcozecchini 0:9fca2b23d0ba 70 case osErrorResource:
marcozecchini 0:9fca2b23d0ba 71 error("OS ran out of threads!\n");
marcozecchini 0:9fca2b23d0ba 72 break;
marcozecchini 0:9fca2b23d0ba 73 case osErrorParameter:
marcozecchini 0:9fca2b23d0ba 74 error("Thread already running!\n");
marcozecchini 0:9fca2b23d0ba 75 break;
marcozecchini 0:9fca2b23d0ba 76 case osErrorNoMemory:
marcozecchini 0:9fca2b23d0ba 77 error("Error allocating the stack memory\n");
marcozecchini 0:9fca2b23d0ba 78 default:
marcozecchini 0:9fca2b23d0ba 79 break;
marcozecchini 0:9fca2b23d0ba 80 }
marcozecchini 0:9fca2b23d0ba 81 }
marcozecchini 0:9fca2b23d0ba 82
marcozecchini 0:9fca2b23d0ba 83 osStatus Thread::start(Callback<void()> task) {
marcozecchini 0:9fca2b23d0ba 84 _mutex.lock();
marcozecchini 0:9fca2b23d0ba 85
marcozecchini 0:9fca2b23d0ba 86 if ((_tid != 0) || _finished) {
marcozecchini 0:9fca2b23d0ba 87 _mutex.unlock();
marcozecchini 0:9fca2b23d0ba 88 return osErrorParameter;
marcozecchini 0:9fca2b23d0ba 89 }
marcozecchini 0:9fca2b23d0ba 90
marcozecchini 0:9fca2b23d0ba 91 if (_attr.stack_mem == NULL) {
marcozecchini 0:9fca2b23d0ba 92 _attr.stack_mem = new uint32_t[_attr.stack_size/sizeof(uint32_t)];
marcozecchini 0:9fca2b23d0ba 93 MBED_ASSERT(_attr.stack_mem != NULL);
marcozecchini 0:9fca2b23d0ba 94 }
marcozecchini 0:9fca2b23d0ba 95
marcozecchini 0:9fca2b23d0ba 96 //Fill the stack with a magic word for maximum usage checking
marcozecchini 0:9fca2b23d0ba 97 for (uint32_t i = 0; i < (_attr.stack_size / sizeof(uint32_t)); i++) {
marcozecchini 0:9fca2b23d0ba 98 ((uint32_t *)_attr.stack_mem)[i] = 0xE25A2EA5;
marcozecchini 0:9fca2b23d0ba 99 }
marcozecchini 0:9fca2b23d0ba 100
marcozecchini 0:9fca2b23d0ba 101 memset(&_obj_mem, 0, sizeof(_obj_mem));
marcozecchini 0:9fca2b23d0ba 102 _attr.cb_size = sizeof(_obj_mem);
marcozecchini 0:9fca2b23d0ba 103 _attr.cb_mem = &_obj_mem;
marcozecchini 0:9fca2b23d0ba 104 _task = task;
marcozecchini 0:9fca2b23d0ba 105 _tid = osThreadNew(Thread::_thunk, this, &_attr);
marcozecchini 0:9fca2b23d0ba 106 if (_tid == NULL) {
marcozecchini 0:9fca2b23d0ba 107 if (_dynamic_stack) {
marcozecchini 0:9fca2b23d0ba 108 delete[] (uint32_t *)(_attr.stack_mem);
marcozecchini 0:9fca2b23d0ba 109 _attr.stack_mem = (uint32_t*)NULL;
marcozecchini 0:9fca2b23d0ba 110 }
marcozecchini 0:9fca2b23d0ba 111 _mutex.unlock();
marcozecchini 0:9fca2b23d0ba 112 _join_sem.release();
marcozecchini 0:9fca2b23d0ba 113 return osErrorResource;
marcozecchini 0:9fca2b23d0ba 114 }
marcozecchini 0:9fca2b23d0ba 115
marcozecchini 0:9fca2b23d0ba 116 _mutex.unlock();
marcozecchini 0:9fca2b23d0ba 117 return osOK;
marcozecchini 0:9fca2b23d0ba 118 }
marcozecchini 0:9fca2b23d0ba 119
marcozecchini 0:9fca2b23d0ba 120 osStatus Thread::terminate() {
marcozecchini 0:9fca2b23d0ba 121 osStatus_t ret = osOK;
marcozecchini 0:9fca2b23d0ba 122 _mutex.lock();
marcozecchini 0:9fca2b23d0ba 123
marcozecchini 0:9fca2b23d0ba 124 // Set the Thread's tid to NULL and
marcozecchini 0:9fca2b23d0ba 125 // release the semaphore before terminating
marcozecchini 0:9fca2b23d0ba 126 // since this thread could be terminating itself
marcozecchini 0:9fca2b23d0ba 127 osThreadId_t local_id = _tid;
marcozecchini 0:9fca2b23d0ba 128 _join_sem.release();
marcozecchini 0:9fca2b23d0ba 129 _tid = (osThreadId_t)NULL;
marcozecchini 0:9fca2b23d0ba 130 if (!_finished) {
marcozecchini 0:9fca2b23d0ba 131 _finished = true;
marcozecchini 0:9fca2b23d0ba 132 ret = osThreadTerminate(local_id);
marcozecchini 0:9fca2b23d0ba 133 }
marcozecchini 0:9fca2b23d0ba 134 _mutex.unlock();
marcozecchini 0:9fca2b23d0ba 135 return ret;
marcozecchini 0:9fca2b23d0ba 136 }
marcozecchini 0:9fca2b23d0ba 137
marcozecchini 0:9fca2b23d0ba 138 osStatus Thread::join() {
marcozecchini 0:9fca2b23d0ba 139 int32_t ret = _join_sem.wait();
marcozecchini 0:9fca2b23d0ba 140 if (ret < 0) {
marcozecchini 0:9fca2b23d0ba 141 return osError;
marcozecchini 0:9fca2b23d0ba 142 }
marcozecchini 0:9fca2b23d0ba 143
marcozecchini 0:9fca2b23d0ba 144 // The semaphore has been released so this thread is being
marcozecchini 0:9fca2b23d0ba 145 // terminated or has been terminated. Once the mutex has
marcozecchini 0:9fca2b23d0ba 146 // been locked it is ensured that the thread is deleted.
marcozecchini 0:9fca2b23d0ba 147 _mutex.lock();
marcozecchini 0:9fca2b23d0ba 148 MBED_ASSERT(NULL == _tid);
marcozecchini 0:9fca2b23d0ba 149 _mutex.unlock();
marcozecchini 0:9fca2b23d0ba 150
marcozecchini 0:9fca2b23d0ba 151 // Release sem so any other threads joining this thread wake up
marcozecchini 0:9fca2b23d0ba 152 _join_sem.release();
marcozecchini 0:9fca2b23d0ba 153 return osOK;
marcozecchini 0:9fca2b23d0ba 154 }
marcozecchini 0:9fca2b23d0ba 155
marcozecchini 0:9fca2b23d0ba 156 osStatus Thread::set_priority(osPriority priority) {
marcozecchini 0:9fca2b23d0ba 157 osStatus_t ret;
marcozecchini 0:9fca2b23d0ba 158 _mutex.lock();
marcozecchini 0:9fca2b23d0ba 159
marcozecchini 0:9fca2b23d0ba 160 ret = osThreadSetPriority(_tid, priority);
marcozecchini 0:9fca2b23d0ba 161
marcozecchini 0:9fca2b23d0ba 162 _mutex.unlock();
marcozecchini 0:9fca2b23d0ba 163 return ret;
marcozecchini 0:9fca2b23d0ba 164 }
marcozecchini 0:9fca2b23d0ba 165
marcozecchini 0:9fca2b23d0ba 166 osPriority Thread::get_priority() {
marcozecchini 0:9fca2b23d0ba 167 osPriority_t ret;
marcozecchini 0:9fca2b23d0ba 168 _mutex.lock();
marcozecchini 0:9fca2b23d0ba 169
marcozecchini 0:9fca2b23d0ba 170 ret = osThreadGetPriority(_tid);
marcozecchini 0:9fca2b23d0ba 171
marcozecchini 0:9fca2b23d0ba 172 _mutex.unlock();
marcozecchini 0:9fca2b23d0ba 173 return ret;
marcozecchini 0:9fca2b23d0ba 174 }
marcozecchini 0:9fca2b23d0ba 175
marcozecchini 0:9fca2b23d0ba 176 int32_t Thread::signal_set(int32_t flags) {
marcozecchini 0:9fca2b23d0ba 177 return osThreadFlagsSet(_tid, flags);
marcozecchini 0:9fca2b23d0ba 178 }
marcozecchini 0:9fca2b23d0ba 179
marcozecchini 0:9fca2b23d0ba 180 Thread::State Thread::get_state() {
marcozecchini 0:9fca2b23d0ba 181 uint8_t state = osThreadTerminated;
marcozecchini 0:9fca2b23d0ba 182
marcozecchini 0:9fca2b23d0ba 183 _mutex.lock();
marcozecchini 0:9fca2b23d0ba 184
marcozecchini 0:9fca2b23d0ba 185 if (_tid != NULL) {
marcozecchini 0:9fca2b23d0ba 186 #if defined(MBED_OS_BACKEND_RTX5)
marcozecchini 0:9fca2b23d0ba 187 state = _obj_mem.state;
marcozecchini 0:9fca2b23d0ba 188 #else
marcozecchini 0:9fca2b23d0ba 189 state = osThreadGetState(_tid);
marcozecchini 0:9fca2b23d0ba 190 #endif
marcozecchini 0:9fca2b23d0ba 191 }
marcozecchini 0:9fca2b23d0ba 192
marcozecchini 0:9fca2b23d0ba 193 _mutex.unlock();
marcozecchini 0:9fca2b23d0ba 194
marcozecchini 0:9fca2b23d0ba 195 State user_state;
marcozecchini 0:9fca2b23d0ba 196
marcozecchini 0:9fca2b23d0ba 197 switch(state) {
marcozecchini 0:9fca2b23d0ba 198 case osThreadInactive:
marcozecchini 0:9fca2b23d0ba 199 user_state = Inactive;
marcozecchini 0:9fca2b23d0ba 200 break;
marcozecchini 0:9fca2b23d0ba 201 case osThreadReady:
marcozecchini 0:9fca2b23d0ba 202 user_state = Ready;
marcozecchini 0:9fca2b23d0ba 203 break;
marcozecchini 0:9fca2b23d0ba 204 case osThreadRunning:
marcozecchini 0:9fca2b23d0ba 205 user_state = Running;
marcozecchini 0:9fca2b23d0ba 206 break;
marcozecchini 0:9fca2b23d0ba 207 #if defined(MBED_OS_BACKEND_RTX5)
marcozecchini 0:9fca2b23d0ba 208 case osRtxThreadWaitingDelay:
marcozecchini 0:9fca2b23d0ba 209 user_state = WaitingDelay;
marcozecchini 0:9fca2b23d0ba 210 break;
marcozecchini 0:9fca2b23d0ba 211 case osRtxThreadWaitingJoin:
marcozecchini 0:9fca2b23d0ba 212 user_state = WaitingJoin;
marcozecchini 0:9fca2b23d0ba 213 break;
marcozecchini 0:9fca2b23d0ba 214 case osRtxThreadWaitingThreadFlags:
marcozecchini 0:9fca2b23d0ba 215 user_state = WaitingThreadFlag;
marcozecchini 0:9fca2b23d0ba 216 break;
marcozecchini 0:9fca2b23d0ba 217 case osRtxThreadWaitingEventFlags:
marcozecchini 0:9fca2b23d0ba 218 user_state = WaitingEventFlag;
marcozecchini 0:9fca2b23d0ba 219 break;
marcozecchini 0:9fca2b23d0ba 220 case osRtxThreadWaitingMutex:
marcozecchini 0:9fca2b23d0ba 221 user_state = WaitingMutex;
marcozecchini 0:9fca2b23d0ba 222 break;
marcozecchini 0:9fca2b23d0ba 223 case osRtxThreadWaitingSemaphore:
marcozecchini 0:9fca2b23d0ba 224 user_state = WaitingSemaphore;
marcozecchini 0:9fca2b23d0ba 225 break;
marcozecchini 0:9fca2b23d0ba 226 case osRtxThreadWaitingMemoryPool:
marcozecchini 0:9fca2b23d0ba 227 user_state = WaitingMemoryPool;
marcozecchini 0:9fca2b23d0ba 228 break;
marcozecchini 0:9fca2b23d0ba 229 case osRtxThreadWaitingMessageGet:
marcozecchini 0:9fca2b23d0ba 230 user_state = WaitingMessageGet;
marcozecchini 0:9fca2b23d0ba 231 break;
marcozecchini 0:9fca2b23d0ba 232 case osRtxThreadWaitingMessagePut:
marcozecchini 0:9fca2b23d0ba 233 user_state = WaitingMessagePut;
marcozecchini 0:9fca2b23d0ba 234 break;
marcozecchini 0:9fca2b23d0ba 235 #endif
marcozecchini 0:9fca2b23d0ba 236 case osThreadTerminated:
marcozecchini 0:9fca2b23d0ba 237 default:
marcozecchini 0:9fca2b23d0ba 238 user_state = Deleted;
marcozecchini 0:9fca2b23d0ba 239 break;
marcozecchini 0:9fca2b23d0ba 240 }
marcozecchini 0:9fca2b23d0ba 241
marcozecchini 0:9fca2b23d0ba 242 return user_state;
marcozecchini 0:9fca2b23d0ba 243 }
marcozecchini 0:9fca2b23d0ba 244
marcozecchini 0:9fca2b23d0ba 245 uint32_t Thread::stack_size() {
marcozecchini 0:9fca2b23d0ba 246 uint32_t size = 0;
marcozecchini 0:9fca2b23d0ba 247 _mutex.lock();
marcozecchini 0:9fca2b23d0ba 248
marcozecchini 0:9fca2b23d0ba 249 if (_tid != NULL) {
marcozecchini 0:9fca2b23d0ba 250 size = osThreadGetStackSize(_tid);
marcozecchini 0:9fca2b23d0ba 251 }
marcozecchini 0:9fca2b23d0ba 252
marcozecchini 0:9fca2b23d0ba 253 _mutex.unlock();
marcozecchini 0:9fca2b23d0ba 254 return size;
marcozecchini 0:9fca2b23d0ba 255 }
marcozecchini 0:9fca2b23d0ba 256
marcozecchini 0:9fca2b23d0ba 257 uint32_t Thread::free_stack() {
marcozecchini 0:9fca2b23d0ba 258 uint32_t size = 0;
marcozecchini 0:9fca2b23d0ba 259 _mutex.lock();
marcozecchini 0:9fca2b23d0ba 260
marcozecchini 0:9fca2b23d0ba 261 #if defined(MBED_OS_BACKEND_RTX5)
marcozecchini 0:9fca2b23d0ba 262 if (_tid != NULL) {
marcozecchini 0:9fca2b23d0ba 263 os_thread_t *thread = (os_thread_t *)_tid;
marcozecchini 0:9fca2b23d0ba 264 size = (uint32_t)thread->sp - (uint32_t)thread->stack_mem;
marcozecchini 0:9fca2b23d0ba 265 }
marcozecchini 0:9fca2b23d0ba 266 #endif
marcozecchini 0:9fca2b23d0ba 267
marcozecchini 0:9fca2b23d0ba 268 _mutex.unlock();
marcozecchini 0:9fca2b23d0ba 269 return size;
marcozecchini 0:9fca2b23d0ba 270 }
marcozecchini 0:9fca2b23d0ba 271
marcozecchini 0:9fca2b23d0ba 272 uint32_t Thread::used_stack() {
marcozecchini 0:9fca2b23d0ba 273 uint32_t size = 0;
marcozecchini 0:9fca2b23d0ba 274 _mutex.lock();
marcozecchini 0:9fca2b23d0ba 275
marcozecchini 0:9fca2b23d0ba 276 #if defined(MBED_OS_BACKEND_RTX5)
marcozecchini 0:9fca2b23d0ba 277 if (_tid != NULL) {
marcozecchini 0:9fca2b23d0ba 278 os_thread_t *thread = (os_thread_t *)_tid;
marcozecchini 0:9fca2b23d0ba 279 size = ((uint32_t)thread->stack_mem + thread->stack_size) - thread->sp;
marcozecchini 0:9fca2b23d0ba 280 }
marcozecchini 0:9fca2b23d0ba 281 #endif
marcozecchini 0:9fca2b23d0ba 282
marcozecchini 0:9fca2b23d0ba 283 _mutex.unlock();
marcozecchini 0:9fca2b23d0ba 284 return size;
marcozecchini 0:9fca2b23d0ba 285 }
marcozecchini 0:9fca2b23d0ba 286
marcozecchini 0:9fca2b23d0ba 287 uint32_t Thread::max_stack() {
marcozecchini 0:9fca2b23d0ba 288 uint32_t size = 0;
marcozecchini 0:9fca2b23d0ba 289 _mutex.lock();
marcozecchini 0:9fca2b23d0ba 290
marcozecchini 0:9fca2b23d0ba 291 if (_tid != NULL) {
marcozecchini 0:9fca2b23d0ba 292 #if defined(MBED_OS_BACKEND_RTX5)
marcozecchini 0:9fca2b23d0ba 293 os_thread_t *thread = (os_thread_t *)_tid;
marcozecchini 0:9fca2b23d0ba 294 uint32_t high_mark = 0;
marcozecchini 0:9fca2b23d0ba 295 while (((uint32_t *)(thread->stack_mem))[high_mark] == 0xE25A2EA5)
marcozecchini 0:9fca2b23d0ba 296 high_mark++;
marcozecchini 0:9fca2b23d0ba 297 size = thread->stack_size - (high_mark * sizeof(uint32_t));
marcozecchini 0:9fca2b23d0ba 298 #else
marcozecchini 0:9fca2b23d0ba 299 size = osThreadGetStackSize(_tid) - osThreadGetStackSpace(_tid);
marcozecchini 0:9fca2b23d0ba 300 #endif
marcozecchini 0:9fca2b23d0ba 301 }
marcozecchini 0:9fca2b23d0ba 302
marcozecchini 0:9fca2b23d0ba 303 _mutex.unlock();
marcozecchini 0:9fca2b23d0ba 304 return size;
marcozecchini 0:9fca2b23d0ba 305 }
marcozecchini 0:9fca2b23d0ba 306
marcozecchini 0:9fca2b23d0ba 307 const char *Thread::get_name() {
marcozecchini 0:9fca2b23d0ba 308 return _attr.name;
marcozecchini 0:9fca2b23d0ba 309 }
marcozecchini 0:9fca2b23d0ba 310
marcozecchini 0:9fca2b23d0ba 311 int32_t Thread::signal_clr(int32_t flags) {
marcozecchini 0:9fca2b23d0ba 312 return osThreadFlagsClear(flags);
marcozecchini 0:9fca2b23d0ba 313 }
marcozecchini 0:9fca2b23d0ba 314
marcozecchini 0:9fca2b23d0ba 315 osEvent Thread::signal_wait(int32_t signals, uint32_t millisec) {
marcozecchini 0:9fca2b23d0ba 316 uint32_t res;
marcozecchini 0:9fca2b23d0ba 317 osEvent evt;
marcozecchini 0:9fca2b23d0ba 318 uint32_t options = osFlagsWaitAll;
marcozecchini 0:9fca2b23d0ba 319 if (signals == 0) {
marcozecchini 0:9fca2b23d0ba 320 options = osFlagsWaitAny;
marcozecchini 0:9fca2b23d0ba 321 signals = 0x7FFFFFFF;
marcozecchini 0:9fca2b23d0ba 322 }
marcozecchini 0:9fca2b23d0ba 323 res = osThreadFlagsWait(signals, options, millisec);
marcozecchini 0:9fca2b23d0ba 324 if (res & osFlagsError) {
marcozecchini 0:9fca2b23d0ba 325 switch (res) {
marcozecchini 0:9fca2b23d0ba 326 case osFlagsErrorISR:
marcozecchini 0:9fca2b23d0ba 327 evt.status = osErrorISR;
marcozecchini 0:9fca2b23d0ba 328 break;
marcozecchini 0:9fca2b23d0ba 329 case osFlagsErrorResource:
marcozecchini 0:9fca2b23d0ba 330 evt.status = osOK;
marcozecchini 0:9fca2b23d0ba 331 break;
marcozecchini 0:9fca2b23d0ba 332 case osFlagsErrorTimeout:
marcozecchini 0:9fca2b23d0ba 333 evt.status = (osStatus)osEventTimeout;
marcozecchini 0:9fca2b23d0ba 334 break;
marcozecchini 0:9fca2b23d0ba 335 case osFlagsErrorParameter:
marcozecchini 0:9fca2b23d0ba 336 default:
marcozecchini 0:9fca2b23d0ba 337 evt.status = (osStatus)osErrorValue;
marcozecchini 0:9fca2b23d0ba 338 break;
marcozecchini 0:9fca2b23d0ba 339 }
marcozecchini 0:9fca2b23d0ba 340 } else {
marcozecchini 0:9fca2b23d0ba 341 evt.status = (osStatus)osEventSignal;
marcozecchini 0:9fca2b23d0ba 342 evt.value.signals = res;
marcozecchini 0:9fca2b23d0ba 343 }
marcozecchini 0:9fca2b23d0ba 344
marcozecchini 0:9fca2b23d0ba 345 return evt;
marcozecchini 0:9fca2b23d0ba 346 }
marcozecchini 0:9fca2b23d0ba 347
marcozecchini 0:9fca2b23d0ba 348 osStatus Thread::wait(uint32_t millisec) {
marcozecchini 0:9fca2b23d0ba 349 return osDelay(millisec);
marcozecchini 0:9fca2b23d0ba 350 }
marcozecchini 0:9fca2b23d0ba 351
marcozecchini 0:9fca2b23d0ba 352 osStatus Thread::yield() {
marcozecchini 0:9fca2b23d0ba 353 return osThreadYield();
marcozecchini 0:9fca2b23d0ba 354 }
marcozecchini 0:9fca2b23d0ba 355
marcozecchini 0:9fca2b23d0ba 356 osThreadId Thread::gettid() {
marcozecchini 0:9fca2b23d0ba 357 return osThreadGetId();
marcozecchini 0:9fca2b23d0ba 358 }
marcozecchini 0:9fca2b23d0ba 359
marcozecchini 0:9fca2b23d0ba 360 void Thread::attach_idle_hook(void (*fptr)(void)) {
marcozecchini 0:9fca2b23d0ba 361 rtos_attach_idle_hook(fptr);
marcozecchini 0:9fca2b23d0ba 362 }
marcozecchini 0:9fca2b23d0ba 363
marcozecchini 0:9fca2b23d0ba 364 void Thread::attach_terminate_hook(void (*fptr)(osThreadId_t id)) {
marcozecchini 0:9fca2b23d0ba 365 terminate_hook = fptr;
marcozecchini 0:9fca2b23d0ba 366 }
marcozecchini 0:9fca2b23d0ba 367
marcozecchini 0:9fca2b23d0ba 368 Thread::~Thread() {
marcozecchini 0:9fca2b23d0ba 369 // terminate is thread safe
marcozecchini 0:9fca2b23d0ba 370 terminate();
marcozecchini 0:9fca2b23d0ba 371 if (_dynamic_stack) {
marcozecchini 0:9fca2b23d0ba 372 delete[] (uint32_t*)(_attr.stack_mem);
marcozecchini 0:9fca2b23d0ba 373 _attr.stack_mem = (uint32_t*)NULL;
marcozecchini 0:9fca2b23d0ba 374 }
marcozecchini 0:9fca2b23d0ba 375 }
marcozecchini 0:9fca2b23d0ba 376
marcozecchini 0:9fca2b23d0ba 377 void Thread::_thunk(void * thread_ptr)
marcozecchini 0:9fca2b23d0ba 378 {
marcozecchini 0:9fca2b23d0ba 379 Thread *t = (Thread*)thread_ptr;
marcozecchini 0:9fca2b23d0ba 380 t->_task();
marcozecchini 0:9fca2b23d0ba 381 t->_mutex.lock();
marcozecchini 0:9fca2b23d0ba 382 t->_tid = (osThreadId)NULL;
marcozecchini 0:9fca2b23d0ba 383 t->_finished = true;
marcozecchini 0:9fca2b23d0ba 384 t->_join_sem.release();
marcozecchini 0:9fca2b23d0ba 385 // rtos will release the mutex automatically
marcozecchini 0:9fca2b23d0ba 386 }
marcozecchini 0:9fca2b23d0ba 387
marcozecchini 0:9fca2b23d0ba 388 }