Music Visualizer

Dependencies:   mbed SDFileSystem NeoStrip PinDetect

Committer:
spatel465
Date:
Thu Apr 30 01:45:25 2020 +0000
Revision:
0:adce77867281
test

Who changed what in which revision?

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