Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
Thread.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2012 ARM Limited 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy 00005 * of this software and associated documentation files (the "Software"), to deal 00006 * in the Software without restriction, including without limitation the rights 00007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 * copies of the Software, and to permit persons to whom the Software is 00009 * furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included in 00012 * all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00020 * SOFTWARE. 00021 */ 00022 #include "rtos/Thread.h" 00023 00024 #include "mbed.h" 00025 #include "rtos/rtos_idle.h" 00026 #include "mbed_assert.h" 00027 00028 #define ALIGN_UP(pos, align) ((pos) % (align) ? (pos) + ((align) - (pos) % (align)) : (pos)) 00029 MBED_STATIC_ASSERT(ALIGN_UP(0, 8) == 0, "ALIGN_UP macro error"); 00030 MBED_STATIC_ASSERT(ALIGN_UP(1, 8) == 8, "ALIGN_UP macro error"); 00031 00032 #define ALIGN_DOWN(pos, align) ((pos) - ((pos) % (align))) 00033 MBED_STATIC_ASSERT(ALIGN_DOWN(7, 8) == 0, "ALIGN_DOWN macro error"); 00034 MBED_STATIC_ASSERT(ALIGN_DOWN(8, 8) == 8, "ALIGN_DOWN macro error"); 00035 00036 static void (*terminate_hook)(osThreadId_t id) = 0; 00037 extern "C" void thread_terminate_hook(osThreadId_t id) 00038 { 00039 if (terminate_hook != (void (*)(osThreadId_t))NULL) { 00040 terminate_hook(id); 00041 } 00042 } 00043 00044 namespace rtos { 00045 00046 void Thread::constructor(osPriority priority, 00047 uint32_t stack_size, unsigned char *stack_mem, const char *name) { 00048 00049 const uintptr_t unaligned_mem = reinterpret_cast<uintptr_t>(stack_mem); 00050 const uintptr_t aligned_mem = ALIGN_UP(unaligned_mem, 8); 00051 const uint32_t offset = aligned_mem - unaligned_mem; 00052 const uint32_t aligned_size = ALIGN_DOWN(stack_size - offset, 8); 00053 00054 _tid = 0; 00055 _dynamic_stack = (stack_mem == NULL); 00056 _finished = false; 00057 memset(&_obj_mem, 0, sizeof(_obj_mem)); 00058 memset(&_attr, 0, sizeof(_attr)); 00059 _attr.priority = priority; 00060 _attr.stack_size = aligned_size; 00061 _attr.name = name ? name : "application_unnamed_thread"; 00062 _attr.stack_mem = reinterpret_cast<uint32_t*>(aligned_mem); 00063 } 00064 00065 void Thread::constructor(Callback<void()> task, 00066 osPriority priority, uint32_t stack_size, unsigned char *stack_mem, const char *name) { 00067 constructor(priority, stack_size, stack_mem, name); 00068 00069 switch (start(task)) { 00070 case osErrorResource: 00071 error("OS ran out of threads!\n"); 00072 break; 00073 case osErrorParameter: 00074 error("Thread already running!\n"); 00075 break; 00076 case osErrorNoMemory: 00077 error("Error allocating the stack memory\n"); 00078 default: 00079 break; 00080 } 00081 } 00082 00083 osStatus Thread::start(Callback<void()> task) { 00084 _mutex.lock(); 00085 00086 if ((_tid != 0) || _finished) { 00087 _mutex.unlock(); 00088 return osErrorParameter; 00089 } 00090 00091 if (_attr.stack_mem == NULL) { 00092 _attr.stack_mem = new uint32_t[_attr.stack_size/sizeof(uint32_t)]; 00093 MBED_ASSERT(_attr.stack_mem != NULL); 00094 } 00095 00096 //Fill the stack with a magic word for maximum usage checking 00097 for (uint32_t i = 0; i < (_attr.stack_size / sizeof(uint32_t)); i++) { 00098 ((uint32_t *)_attr.stack_mem)[i] = 0xE25A2EA5; 00099 } 00100 00101 memset(&_obj_mem, 0, sizeof(_obj_mem)); 00102 _attr.cb_size = sizeof(_obj_mem); 00103 _attr.cb_mem = &_obj_mem; 00104 _task = task; 00105 _tid = osThreadNew(Thread::_thunk, this, &_attr); 00106 if (_tid == NULL) { 00107 if (_dynamic_stack) { 00108 delete[] (uint32_t *)(_attr.stack_mem); 00109 _attr.stack_mem = (uint32_t*)NULL; 00110 } 00111 _mutex.unlock(); 00112 _join_sem.release(); 00113 return osErrorResource; 00114 } 00115 00116 _mutex.unlock(); 00117 return osOK; 00118 } 00119 00120 osStatus Thread::terminate() { 00121 osStatus_t ret = osOK; 00122 _mutex.lock(); 00123 00124 // Set the Thread's tid to NULL and 00125 // release the semaphore before terminating 00126 // since this thread could be terminating itself 00127 osThreadId_t local_id = _tid; 00128 _join_sem.release(); 00129 _tid = (osThreadId_t)NULL; 00130 if (!_finished) { 00131 _finished = true; 00132 ret = osThreadTerminate(local_id); 00133 } 00134 _mutex.unlock(); 00135 return ret; 00136 } 00137 00138 osStatus Thread::join() { 00139 int32_t ret = _join_sem.wait(); 00140 if (ret < 0) { 00141 return osError; 00142 } 00143 00144 // The semaphore has been released so this thread is being 00145 // terminated or has been terminated. Once the mutex has 00146 // been locked it is ensured that the thread is deleted. 00147 _mutex.lock(); 00148 MBED_ASSERT(NULL == _tid); 00149 _mutex.unlock(); 00150 00151 // Release sem so any other threads joining this thread wake up 00152 _join_sem.release(); 00153 return osOK; 00154 } 00155 00156 osStatus Thread::set_priority(osPriority priority) { 00157 osStatus_t ret; 00158 _mutex.lock(); 00159 00160 ret = osThreadSetPriority(_tid, priority); 00161 00162 _mutex.unlock(); 00163 return ret; 00164 } 00165 00166 osPriority Thread::get_priority() { 00167 osPriority_t ret; 00168 _mutex.lock(); 00169 00170 ret = osThreadGetPriority(_tid); 00171 00172 _mutex.unlock(); 00173 return ret; 00174 } 00175 00176 int32_t Thread::signal_set(int32_t flags) { 00177 return osThreadFlagsSet(_tid, flags); 00178 } 00179 00180 Thread::State Thread::get_state() { 00181 uint8_t state = osThreadTerminated; 00182 00183 _mutex.lock(); 00184 00185 if (_tid != NULL) { 00186 #if defined(MBED_OS_BACKEND_RTX5) 00187 state = _obj_mem.state; 00188 #else 00189 state = osThreadGetState(_tid); 00190 #endif 00191 } 00192 00193 _mutex.unlock(); 00194 00195 State user_state; 00196 00197 switch(state) { 00198 case osThreadInactive: 00199 user_state = Inactive; 00200 break; 00201 case osThreadReady: 00202 user_state = Ready; 00203 break; 00204 case osThreadRunning: 00205 user_state = Running; 00206 break; 00207 #if defined(MBED_OS_BACKEND_RTX5) 00208 case osRtxThreadWaitingDelay: 00209 user_state = WaitingDelay; 00210 break; 00211 case osRtxThreadWaitingJoin: 00212 user_state = WaitingJoin; 00213 break; 00214 case osRtxThreadWaitingThreadFlags: 00215 user_state = WaitingThreadFlag; 00216 break; 00217 case osRtxThreadWaitingEventFlags: 00218 user_state = WaitingEventFlag; 00219 break; 00220 case osRtxThreadWaitingMutex: 00221 user_state = WaitingMutex; 00222 break; 00223 case osRtxThreadWaitingSemaphore: 00224 user_state = WaitingSemaphore; 00225 break; 00226 case osRtxThreadWaitingMemoryPool: 00227 user_state = WaitingMemoryPool; 00228 break; 00229 case osRtxThreadWaitingMessageGet: 00230 user_state = WaitingMessageGet; 00231 break; 00232 case osRtxThreadWaitingMessagePut: 00233 user_state = WaitingMessagePut; 00234 break; 00235 #endif 00236 case osThreadTerminated: 00237 default: 00238 user_state = Deleted; 00239 break; 00240 } 00241 00242 return user_state; 00243 } 00244 00245 uint32_t Thread::stack_size() { 00246 uint32_t size = 0; 00247 _mutex.lock(); 00248 00249 if (_tid != NULL) { 00250 size = osThreadGetStackSize(_tid); 00251 } 00252 00253 _mutex.unlock(); 00254 return size; 00255 } 00256 00257 uint32_t Thread::free_stack() { 00258 uint32_t size = 0; 00259 _mutex.lock(); 00260 00261 #if defined(MBED_OS_BACKEND_RTX5) 00262 if (_tid != NULL) { 00263 os_thread_t *thread = (os_thread_t *)_tid; 00264 size = (uint32_t)thread->sp - (uint32_t)thread->stack_mem; 00265 } 00266 #endif 00267 00268 _mutex.unlock(); 00269 return size; 00270 } 00271 00272 uint32_t Thread::used_stack() { 00273 uint32_t size = 0; 00274 _mutex.lock(); 00275 00276 #if defined(MBED_OS_BACKEND_RTX5) 00277 if (_tid != NULL) { 00278 os_thread_t *thread = (os_thread_t *)_tid; 00279 size = ((uint32_t)thread->stack_mem + thread->stack_size) - thread->sp; 00280 } 00281 #endif 00282 00283 _mutex.unlock(); 00284 return size; 00285 } 00286 00287 uint32_t Thread::max_stack() { 00288 uint32_t size = 0; 00289 _mutex.lock(); 00290 00291 if (_tid != NULL) { 00292 #if defined(MBED_OS_BACKEND_RTX5) 00293 os_thread_t *thread = (os_thread_t *)_tid; 00294 uint32_t high_mark = 0; 00295 while (((uint32_t *)(thread->stack_mem))[high_mark] == 0xE25A2EA5) 00296 high_mark++; 00297 size = thread->stack_size - (high_mark * sizeof(uint32_t)); 00298 #else 00299 size = osThreadGetStackSize(_tid) - osThreadGetStackSpace(_tid); 00300 #endif 00301 } 00302 00303 _mutex.unlock(); 00304 return size; 00305 } 00306 00307 const char *Thread::get_name() { 00308 return _attr.name; 00309 } 00310 00311 int32_t Thread::signal_clr(int32_t flags) { 00312 return osThreadFlagsClear(flags); 00313 } 00314 00315 osEvent Thread::signal_wait(int32_t signals, uint32_t millisec) { 00316 uint32_t res; 00317 osEvent evt; 00318 uint32_t options = osFlagsWaitAll; 00319 if (signals == 0) { 00320 options = osFlagsWaitAny; 00321 signals = 0x7FFFFFFF; 00322 } 00323 res = osThreadFlagsWait(signals, options, millisec); 00324 if (res & osFlagsError) { 00325 switch (res) { 00326 case osFlagsErrorISR: 00327 evt.status = osErrorISR; 00328 break; 00329 case osFlagsErrorResource: 00330 evt.status = osOK; 00331 break; 00332 case osFlagsErrorTimeout: 00333 evt.status = (osStatus)osEventTimeout; 00334 break; 00335 case osFlagsErrorParameter: 00336 default: 00337 evt.status = (osStatus)osErrorValue; 00338 break; 00339 } 00340 } else { 00341 evt.status = (osStatus)osEventSignal; 00342 evt.value.signals = res; 00343 } 00344 00345 return evt; 00346 } 00347 00348 osStatus Thread::wait(uint32_t millisec) { 00349 return osDelay(millisec); 00350 } 00351 00352 osStatus Thread::yield() { 00353 return osThreadYield(); 00354 } 00355 00356 osThreadId Thread::gettid() { 00357 return osThreadGetId(); 00358 } 00359 00360 void Thread::attach_idle_hook(void (*fptr)(void)) { 00361 rtos_attach_idle_hook (fptr); 00362 } 00363 00364 void Thread::attach_terminate_hook(void (*fptr)(osThreadId_t id)) { 00365 terminate_hook = fptr; 00366 } 00367 00368 Thread::~Thread() { 00369 // terminate is thread safe 00370 terminate(); 00371 if (_dynamic_stack) { 00372 delete[] (uint32_t*)(_attr.stack_mem); 00373 _attr.stack_mem = (uint32_t*)NULL; 00374 } 00375 } 00376 00377 void Thread::_thunk(void * thread_ptr) 00378 { 00379 Thread *t = (Thread*)thread_ptr; 00380 t->_task(); 00381 t->_mutex.lock(); 00382 t->_tid = (osThreadId)NULL; 00383 t->_finished = true; 00384 t->_join_sem.release(); 00385 // rtos will release the mutex automatically 00386 } 00387 00388 }
Generated on Sun Jul 17 2022 08:25:32 by 1.7.2