Sergey Pastor / 1

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers os_port_ucos3.c Source File

os_port_ucos3.c

Go to the documentation of this file.
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