BA / SerialCom

Fork of OmniWheels by Gustav Atmel

Committer:
gustavatmel
Date:
Tue May 01 15:47:08 2018 +0000
Revision:
1:9c5af431a1f1
sdf

Who changed what in which revision?

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