Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
os_port_ucos3.c
00001 /** 00002 * @file os_port_ucos3.c 00003 * @brief RTOS abstraction layer (Micrium uC/OS-III) 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU General Public License 00011 * as published by the Free Software Foundation; either version 2 00012 * of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with this program; if not, write to the Free Software Foundation, 00021 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00022 * 00023 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00024 * @version 1.7.6 00025 **/ 00026 00027 //Switch to the appropriate trace level 00028 #define TRACE_LEVEL TRACE_LEVEL_OFF 00029 00030 //Dependencies 00031 #include <stdio.h> 00032 #include <stdlib.h> 00033 #include <string.h> 00034 #include "os_port.h" 00035 #include "os_port_ucos3.h" 00036 #include "debug.h" 00037 00038 //Forward declaration of functions 00039 void osIdleTaskHook(void); 00040 00041 //Variables 00042 static OS_TCB *tcbTable[OS_PORT_MAX_TASKS]; 00043 static CPU_STK *stkTable[OS_PORT_MAX_TASKS]; 00044 00045 00046 /** 00047 * @brief Kernel initialization 00048 **/ 00049 00050 void osInitKernel(void) 00051 { 00052 OS_ERR err; 00053 00054 //Initialize tables 00055 memset(tcbTable, 0, sizeof(tcbTable)); 00056 memset(stkTable, 0, sizeof(stkTable)); 00057 00058 //Scheduler initialization 00059 OSInit(&err); 00060 00061 //Set idle task hook 00062 OS_AppIdleTaskHookPtr = osIdleTaskHook; 00063 } 00064 00065 00066 /** 00067 * @brief Start kernel 00068 **/ 00069 00070 void osStartKernel(void) 00071 { 00072 OS_ERR err; 00073 00074 //Start the scheduler 00075 OSStart(&err); 00076 } 00077 00078 00079 /** 00080 * @brief Create a static task 00081 * @param[out] task Pointer to the task structure 00082 * @param[in] name A name identifying the task 00083 * @param[in] taskCode Pointer to the task entry function 00084 * @param[in] params A pointer to a variable to be passed to the task 00085 * @param[in] stack Pointer to the stack 00086 * @param[in] stackSize The initial size of the stack, in words 00087 * @param[in] priority The priority at which the task should run 00088 * @return The function returns TRUE if the task was successfully 00089 * created. Otherwise, FALSE is returned 00090 **/ 00091 00092 bool_t osCreateStaticTask(OsTask *task, const char_t *name, OsTaskCode taskCode, 00093 void *params, void *stack, size_t stackSize, int_t priority) 00094 { 00095 OS_ERR err; 00096 CPU_STK stackLimit; 00097 00098 //The watermark limit is used to monitor and ensure that the stack does not overflow 00099 stackLimit = stackSize / 10; 00100 00101 //Create a new task 00102 OSTaskCreate(task, (CPU_CHAR *) name, taskCode, params, 00103 priority, stack, stackLimit, stackSize, 0, 1, NULL, 00104 OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR, &err); 00105 00106 //Check whether the task was successfully created 00107 if(err == OS_ERR_NONE) 00108 return TRUE; 00109 else 00110 return FALSE; 00111 } 00112 00113 00114 /** 00115 * @brief Create a new task 00116 * @param[in] name A name identifying the task 00117 * @param[in] taskCode Pointer to the task entry function 00118 * @param[in] params A pointer to a variable to be passed to the task 00119 * @param[in] stackSize The initial size of the stack, in words 00120 * @param[in] priority The priority at which the task should run 00121 * @return If the function succeeds, the return value is a pointer to the 00122 * new task. If the function fails, the return value is NULL 00123 **/ 00124 00125 OsTask *osCreateTask(const char_t *name, OsTaskCode taskCode, 00126 void *params, size_t stackSize, int_t priority) 00127 { 00128 OS_ERR err; 00129 CPU_INT32U i; 00130 CPU_STK stackLimit; 00131 OS_TCB *task; 00132 CPU_STK *stack; 00133 00134 //The watermark limit is used to monitor and ensure that the stack does not overflow 00135 stackLimit = stackSize / 10; 00136 00137 //Enter critical section 00138 osSuspendAllTasks(); 00139 00140 //Loop through TCB table 00141 for(i = 0; i < OS_PORT_MAX_TASKS; i++) 00142 { 00143 //Check whether the current entry is free 00144 if(tcbTable[i] == NULL) 00145 break; 00146 } 00147 00148 //Any entry available in the table? 00149 if(i < OS_PORT_MAX_TASKS) 00150 { 00151 //Allocate a memory block to hold the task's control block 00152 task = osAllocMem(sizeof(OS_TCB)); 00153 00154 //Successful memory allocation? 00155 if(task != NULL) 00156 { 00157 //Allocate a memory block to hold the task's stack 00158 stack = osAllocMem(stackSize * sizeof(CPU_STK)); 00159 00160 //Successful memory allocation? 00161 if(stack != NULL) 00162 { 00163 //Create a new task 00164 OSTaskCreate(task, (CPU_CHAR *) name, taskCode, params, 00165 priority, stack, stackLimit, stackSize, 0, 1, NULL, 00166 OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR, &err); 00167 00168 //Check the return value 00169 if(err == OS_ERR_NONE) 00170 { 00171 //Save TCB base address 00172 tcbTable[i] = task; 00173 //Save stack base address 00174 stkTable[i] = stack; 00175 } 00176 else 00177 { 00178 //Clean up side effects 00179 osFreeMem(task); 00180 osFreeMem(stack); 00181 } 00182 } 00183 else 00184 { 00185 //Memory allocation failed 00186 err = OS_ERR_MEM_FULL; 00187 //Clean up side effects 00188 osFreeMem(task); 00189 } 00190 } 00191 else 00192 { 00193 //Memory allocation failed 00194 err = OS_ERR_MEM_FULL; 00195 } 00196 } 00197 else 00198 { 00199 //No entry available in the table 00200 err = OS_ERR_MEM_FULL; 00201 } 00202 00203 //Leave critical section 00204 osResumeAllTasks(); 00205 00206 //Check whether the task was successfully created 00207 if(err == OS_ERR_NONE) 00208 return task; 00209 else 00210 return NULL; 00211 } 00212 00213 00214 /** 00215 * @brief Delete a task 00216 * @param[in] task Pointer to the task to be deleted 00217 **/ 00218 00219 void osDeleteTask(OsTask *task) 00220 { 00221 OS_ERR err; 00222 00223 //Delete the specified task 00224 OSTaskDel(task, &err); 00225 } 00226 00227 00228 /** 00229 * @brief Delay routine 00230 * @param[in] delay Amount of time for which the calling task should block 00231 **/ 00232 00233 void osDelayTask(systime_t delay) 00234 { 00235 OS_ERR err; 00236 00237 //Delay the task for the specified duration 00238 OSTimeDly(OS_MS_TO_SYSTICKS(delay), OS_OPT_TIME_DLY, &err); 00239 } 00240 00241 00242 /** 00243 * @brief Yield control to the next task 00244 **/ 00245 00246 void osSwitchTask(void) 00247 { 00248 //Force a context switch 00249 OSSched(); 00250 } 00251 00252 00253 /** 00254 * @brief Suspend scheduler activity 00255 **/ 00256 00257 void osSuspendAllTasks(void) 00258 { 00259 OS_ERR err; 00260 00261 //Make sure the operating system is running 00262 if(OSRunning == OS_STATE_OS_RUNNING) 00263 { 00264 //Suspend scheduler activity 00265 OSSchedLock(&err); 00266 } 00267 } 00268 00269 00270 /** 00271 * @brief Resume scheduler activity 00272 **/ 00273 00274 void osResumeAllTasks(void) 00275 { 00276 OS_ERR err; 00277 00278 //Make sure the operating system is running 00279 if(OSRunning == OS_STATE_OS_RUNNING) 00280 { 00281 //Resume scheduler activity 00282 OSSchedUnlock(&err); 00283 } 00284 } 00285 00286 00287 /** 00288 * @brief Create an event object 00289 * @param[in] event Pointer to the event object 00290 * @return The function returns TRUE if the event object was successfully 00291 * created. Otherwise, FALSE is returned 00292 **/ 00293 00294 bool_t osCreateEvent(OsEvent *event) 00295 { 00296 OS_ERR err; 00297 00298 //Create an event flag group 00299 OSFlagCreate(event, "EVENT", 0, &err); 00300 00301 //Check whether the event flag group was successfully created 00302 if(err == OS_ERR_NONE) 00303 return TRUE; 00304 else 00305 return FALSE; 00306 } 00307 00308 00309 /** 00310 * @brief Delete an event object 00311 * @param[in] event Pointer to the event object 00312 **/ 00313 00314 void osDeleteEvent(OsEvent *event) 00315 { 00316 OS_ERR err; 00317 00318 //Make sure the operating system is running 00319 if(OSRunning == OS_STATE_OS_RUNNING) 00320 { 00321 //Properly dispose the event object 00322 OSFlagDel(event, OS_OPT_DEL_ALWAYS, &err); 00323 } 00324 } 00325 00326 00327 /** 00328 * @brief Set the specified event object to the signaled state 00329 * @param[in] event Pointer to the event object 00330 **/ 00331 00332 void osSetEvent(OsEvent *event) 00333 { 00334 OS_ERR err; 00335 00336 //Set the specified event to the signaled state 00337 OSFlagPost(event, 1, OS_OPT_POST_FLAG_SET, &err); 00338 } 00339 00340 00341 /** 00342 * @brief Set the specified event object to the nonsignaled state 00343 * @param[in] event Pointer to the event object 00344 **/ 00345 00346 void osResetEvent(OsEvent *event) 00347 { 00348 OS_ERR err; 00349 00350 //Force the specified event to the nonsignaled state 00351 OSFlagPost(event, 1, OS_OPT_POST_FLAG_CLR, &err); 00352 } 00353 00354 00355 /** 00356 * @brief Wait until the specified event is in the signaled state 00357 * @param[in] event Pointer to the event object 00358 * @param[in] timeout Timeout interval 00359 * @return The function returns TRUE if the state of the specified object is 00360 * signaled. FALSE is returned if the timeout interval elapsed 00361 **/ 00362 00363 bool_t osWaitForEvent(OsEvent *event, systime_t timeout) 00364 { 00365 OS_ERR err; 00366 00367 //Wait until the specified event is in the signaled 00368 //state or the timeout interval elapses 00369 if(timeout == 0) 00370 { 00371 //Non-blocking call 00372 OSFlagPend(event, 1, 0, OS_OPT_PEND_FLAG_SET_ANY | 00373 OS_OPT_PEND_FLAG_CONSUME | OS_OPT_PEND_NON_BLOCKING, NULL, &err); 00374 } 00375 else if(timeout == INFINITE_DELAY) 00376 { 00377 //Infinite timeout period 00378 OSFlagPend(event, 1, 0, OS_OPT_PEND_FLAG_SET_ANY | 00379 OS_OPT_PEND_FLAG_CONSUME | OS_OPT_PEND_BLOCKING, NULL, &err); 00380 } 00381 else 00382 { 00383 //Wait until the specified event becomes set 00384 OSFlagPend(event, 1, OS_MS_TO_SYSTICKS(timeout), OS_OPT_PEND_FLAG_SET_ANY | 00385 OS_OPT_PEND_FLAG_CONSUME | OS_OPT_PEND_BLOCKING, NULL, &err); 00386 } 00387 00388 //Check whether the specified event is set 00389 if(err == OS_ERR_NONE) 00390 return TRUE; 00391 else 00392 return FALSE; 00393 } 00394 00395 00396 /** 00397 * @brief Set an event object to the signaled state from an interrupt service routine 00398 * @param[in] event Pointer to the event object 00399 * @return TRUE if setting the event to signaled state caused a task to unblock 00400 * and the unblocked task has a priority higher than the currently running task 00401 **/ 00402 00403 bool_t osSetEventFromIsr(OsEvent *event) 00404 { 00405 OS_ERR err; 00406 00407 //Set the specified event to the signaled state 00408 OSFlagPost(event, 1, OS_OPT_POST_FLAG_SET, &err); 00409 00410 //The return value is not relevant 00411 return FALSE; 00412 } 00413 00414 00415 /** 00416 * @brief Create a semaphore object 00417 * @param[in] semaphore Pointer to the semaphore object 00418 * @param[in] count The maximum count for the semaphore object. This value 00419 * must be greater than zero 00420 * @return The function returns TRUE if the semaphore was successfully 00421 * created. Otherwise, FALSE is returned 00422 **/ 00423 00424 bool_t osCreateSemaphore(OsSemaphore *semaphore, uint_t count) 00425 { 00426 OS_ERR err; 00427 00428 //Create a semaphore 00429 OSSemCreate(semaphore, "SEMAPHORE", count, &err); 00430 00431 //Check whether the semaphore was successfully created 00432 if(err == OS_ERR_NONE) 00433 return TRUE; 00434 else 00435 return FALSE; 00436 } 00437 00438 00439 /** 00440 * @brief Delete a semaphore object 00441 * @param[in] semaphore Pointer to the semaphore object 00442 **/ 00443 00444 void osDeleteSemaphore(OsSemaphore *semaphore) 00445 { 00446 OS_ERR err; 00447 00448 //Make sure the operating system is running 00449 if(OSRunning == OS_STATE_OS_RUNNING) 00450 { 00451 //Properly dispose the specified semaphore 00452 OSSemDel(semaphore, OS_OPT_DEL_ALWAYS, &err); 00453 } 00454 } 00455 00456 00457 /** 00458 * @brief Wait for the specified semaphore to be available 00459 * @param[in] semaphore Pointer to the semaphore object 00460 * @param[in] timeout Timeout interval 00461 * @return The function returns TRUE if the semaphore is available. FALSE is 00462 * returned if the timeout interval elapsed 00463 **/ 00464 00465 bool_t osWaitForSemaphore(OsSemaphore *semaphore, systime_t timeout) 00466 { 00467 OS_ERR err; 00468 00469 //Wait until the semaphore is available or the timeout interval elapses 00470 if(timeout == 0) 00471 { 00472 //Non-blocking call 00473 OSSemPend(semaphore, 0, OS_OPT_PEND_NON_BLOCKING, NULL, &err); 00474 } 00475 else if(timeout == INFINITE_DELAY) 00476 { 00477 //Infinite timeout period 00478 OSSemPend(semaphore, 0, OS_OPT_PEND_BLOCKING, NULL, &err); 00479 } 00480 else 00481 { 00482 //Wait until the specified semaphore becomes available 00483 OSSemPend(semaphore, OS_MS_TO_SYSTICKS(timeout), 00484 OS_OPT_PEND_BLOCKING, NULL, &err); 00485 } 00486 00487 //Check whether the specified semaphore is available 00488 if(err == OS_ERR_NONE) 00489 return TRUE; 00490 else 00491 return FALSE; 00492 } 00493 00494 00495 /** 00496 * @brief Release the specified semaphore object 00497 * @param[in] semaphore Pointer to the semaphore object 00498 **/ 00499 00500 void osReleaseSemaphore(OsSemaphore *semaphore) 00501 { 00502 OS_ERR err; 00503 00504 //Release the semaphore 00505 OSSemPost(semaphore, OS_OPT_POST_1, &err); 00506 } 00507 00508 00509 /** 00510 * @brief Create a mutex object 00511 * @param[in] mutex Pointer to the mutex object 00512 * @return The function returns TRUE if the mutex was successfully 00513 * created. Otherwise, FALSE is returned 00514 **/ 00515 00516 bool_t osCreateMutex(OsMutex *mutex) 00517 { 00518 OS_ERR err; 00519 00520 //Create a mutex 00521 OSMutexCreate(mutex, "MUTEX", &err); 00522 00523 //Check whether the mutex was successfully created 00524 if(err == OS_ERR_NONE) 00525 return TRUE; 00526 else 00527 return FALSE; 00528 } 00529 00530 00531 /** 00532 * @brief Delete a mutex object 00533 * @param[in] mutex Pointer to the mutex object 00534 **/ 00535 00536 void osDeleteMutex(OsMutex *mutex) 00537 { 00538 OS_ERR err; 00539 00540 //Make sure the operating system is running 00541 if(OSRunning == OS_STATE_OS_RUNNING) 00542 { 00543 //Properly dispose the specified mutex 00544 OSMutexDel(mutex, OS_OPT_DEL_ALWAYS, &err); 00545 } 00546 } 00547 00548 00549 /** 00550 * @brief Acquire ownership of the specified mutex object 00551 * @param[in] mutex Pointer to the mutex object 00552 **/ 00553 00554 void osAcquireMutex(OsMutex *mutex) 00555 { 00556 OS_ERR err; 00557 00558 //Obtain ownership of the mutex object 00559 OSMutexPend(mutex, 0, OS_OPT_PEND_BLOCKING, NULL, &err); 00560 } 00561 00562 00563 /** 00564 * @brief Release ownership of the specified mutex object 00565 * @param[in] mutex Pointer to the mutex object 00566 **/ 00567 00568 void osReleaseMutex(OsMutex *mutex) 00569 { 00570 OS_ERR err; 00571 00572 //Release ownership of the mutex object 00573 OSMutexPost(mutex, OS_OPT_POST_NONE, &err); 00574 } 00575 00576 00577 /** 00578 * @brief Retrieve system time 00579 * @return Number of milliseconds elapsed since the system was last started 00580 **/ 00581 00582 systime_t osGetSystemTime(void) 00583 { 00584 OS_ERR err; 00585 systime_t time; 00586 00587 //Get current tick count 00588 time = OSTimeGet(&err); 00589 00590 //Convert system ticks to milliseconds 00591 return OS_SYSTICKS_TO_MS(time); 00592 } 00593 00594 00595 /** 00596 * @brief Allocate a memory block 00597 * @param[in] size Bytes to allocate 00598 * @return A pointer to the allocated memory block or NULL if 00599 * there is insufficient memory available 00600 **/ 00601 00602 void *osAllocMem(size_t size) 00603 { 00604 void *p; 00605 00606 //Enter critical section 00607 osSuspendAllTasks(); 00608 //Allocate a memory block 00609 p = malloc(size); 00610 //Leave critical section 00611 osResumeAllTasks(); 00612 00613 //Debug message 00614 TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n", size, (uintptr_t) p); 00615 00616 //Return a pointer to the newly allocated memory block 00617 return p; 00618 } 00619 00620 00621 /** 00622 * @brief Release a previously allocated memory block 00623 * @param[in] p Previously allocated memory block to be freed 00624 **/ 00625 00626 void osFreeMem(void *p) 00627 { 00628 //Make sure the pointer is valid 00629 if(p != NULL) 00630 { 00631 //Debug message 00632 TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p); 00633 00634 //Enter critical section 00635 osSuspendAllTasks(); 00636 //Free memory block 00637 free(p); 00638 //Leave critical section 00639 osResumeAllTasks(); 00640 } 00641 } 00642 00643 00644 /** 00645 * @brief Idle task hook 00646 **/ 00647 00648 void osIdleTaskHook(void) 00649 { 00650 uint_t i; 00651 00652 //Loop through TCB table 00653 for(i = 0; i < OS_PORT_MAX_TASKS; i++) 00654 { 00655 //Check whether current entry is used 00656 if(tcbTable[i] != NULL) 00657 { 00658 //Wait for task termination 00659 if(tcbTable[i]->TaskState == OS_TASK_STATE_DEL) 00660 { 00661 //Free previously allocated resources 00662 osFreeMem(stkTable[i]); 00663 osFreeMem(tcbTable[i]); 00664 00665 //Mark the entry as free 00666 stkTable[i] = NULL; 00667 tcbTable[i] = NULL; 00668 } 00669 } 00670 } 00671 } 00672
Generated on Tue Jul 12 2022 17:10:15 by
1.7.2