1

Committer:
valeyev
Date:
Tue Mar 13 07:17:50 2018 +0000
Revision:
0:e056ac8fecf8
looking for...

Who changed what in which revision?

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