Anasse Abdoul / Mbed 2 deprecated Test_MPU6050

Dependencies:   mbed

Committer:
anasse
Date:
Thu Mar 31 07:43:50 2022 +0000
Revision:
0:a59a3d743804
vers0

Who changed what in which revision?

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