Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers os_port_ucos2.c Source File

os_port_ucos2.c

Go to the documentation of this file.
00001 /**
00002  * @file os_port_ucos2.c
00003  * @brief RTOS abstraction layer (Micrium uC/OS-II)
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_ucos2.h"
00036 #include "debug.h"
00037 
00038 //Variables
00039 static OsTask tcbTable[OS_LOWEST_PRIO];
00040 
00041 
00042 /**
00043  * @brief Kernel initialization
00044  **/
00045 
00046 void osInitKernel(void)
00047 {
00048    //Initialize table
00049    memset(tcbTable, 0, sizeof(tcbTable));
00050 
00051    //Scheduler initialization
00052    OSInit();
00053 }
00054 
00055 
00056 /**
00057  * @brief Start kernel
00058  **/
00059 
00060 void osStartKernel(void)
00061 {
00062    //Start the scheduler
00063    OSStart();
00064 }
00065 
00066 
00067 /**
00068  * @brief Create a static task
00069  * @param[out] task Pointer to the task structure
00070  * @param[in] name A name identifying the task
00071  * @param[in] taskCode Pointer to the task entry function
00072  * @param[in] params A pointer to a variable to be passed to the task
00073  * @param[in] stack Pointer to the stack
00074  * @param[in] stackSize The initial size of the stack, in words
00075  * @param[in] priority The priority at which the task should run
00076  * @return The function returns TRUE if the task was successfully
00077  *   created. Otherwise, FALSE is returned
00078  **/
00079 
00080 bool_t osCreateStaticTask(OsTask *task, const char_t *name, OsTaskCode taskCode,
00081    void *params, void *stack, size_t stackSize, int_t priority)
00082 {
00083    INT8U err;
00084    OS_STK *stackTop;
00085 
00086    //Check stack size
00087    if(stackSize == 0)
00088       return FALSE;
00089 
00090    //Top of the stack
00091    stackTop = (OS_STK *) stack + (stackSize - 1);
00092 
00093    //Search for a free TCB
00094    while(priority < (OS_LOWEST_PRIO - 3) && OSTCBPrioTbl[priority] != 0)
00095       priority++;
00096 
00097    //No more TCB available?
00098    if(priority >= (OS_LOWEST_PRIO - 3))
00099       return FALSE;
00100 
00101    //Create a new task
00102    err = OSTaskCreateExt(taskCode, params, stackTop, priority, priority,
00103       stack, stackSize, NULL, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
00104 
00105    //Check whether the task was successfully created
00106    if(err == OS_ERR_NONE)
00107    {
00108       //Save task priority
00109       task->prio = priority;
00110       //The task was successfully created
00111       return TRUE;
00112    }
00113    else
00114    {
00115       //Report an error
00116       return FALSE;
00117    }
00118 }
00119 
00120 
00121 /**
00122  * @brief Create a new task
00123  * @param[in] name A name identifying the task
00124  * @param[in] taskCode Pointer to the task entry function
00125  * @param[in] params A pointer to a variable to be passed to the task
00126  * @param[in] stackSize The initial size of the stack, in words
00127  * @param[in] priority The priority at which the task should run
00128  * @return If the function succeeds, the return value is a pointer to the
00129  *   new task. If the function fails, the return value is NULL
00130  **/
00131 
00132 OsTask *osCreateTask(const char_t *name, OsTaskCode taskCode,
00133    void *params, size_t stackSize, int_t priority)
00134 {
00135    //INT8U i;
00136    OS_STK *stack;
00137 
00138    //Allocate a memory block to hold the task's stack
00139    stack = osAllocMem(stackSize * sizeof(OS_STK));
00140 
00141    //Successful memory allocation?
00142    if(stack != NULL)
00143    {
00144       //Create task
00145       if(osCreateStaticTask(&tcbTable[priority], name,
00146          taskCode, params, stack, stackSize, priority))
00147       {
00148          //Return a valid handle
00149          return &tcbTable[priority];
00150       }
00151       else
00152       {
00153          //Clean up side effects
00154          osFreeMem(stack);
00155          //Report an error
00156          return NULL;
00157       }
00158    }
00159    else
00160    {
00161       //Memory allocation failed
00162       return NULL;
00163    }
00164 }
00165 
00166 
00167 /**
00168  * @brief Delete a task
00169  * @param[in] task Pointer to the task to be deleted
00170  **/
00171 
00172 void osDeleteTask(OsTask *task)
00173 {
00174    //Delete the specified task
00175    OSTaskDel(task->prio);
00176 }
00177 
00178 
00179 /**
00180  * @brief Delay routine
00181  * @param[in] delay Amount of time for which the calling task should block
00182  **/
00183 
00184 void osDelayTask(systime_t delay)
00185 {
00186    INT16U n;
00187 
00188    //Convert milliseconds to system ticks
00189    delay = OS_MS_TO_SYSTICKS(delay);
00190 
00191    //Delay the task for the specified duration
00192    while(delay > 0)
00193    {
00194       //The maximum delay is 65535 clock ticks
00195       n = MIN(delay, 65535);
00196       //Wait for the specified amount of time
00197       OSTimeDly(n);
00198       //Decrement delay value
00199       delay -= n;
00200    }
00201 }
00202 
00203 
00204 /**
00205  * @brief Yield control to the next task
00206  **/
00207 
00208 void osSwitchTask(void)
00209 {
00210    //Not implemented
00211 }
00212 
00213 
00214 /**
00215  * @brief Suspend scheduler activity
00216  **/
00217 
00218 void osSuspendAllTasks(void)
00219 {
00220    //Make sure the operating system is running
00221    if(OSRunning == OS_TRUE)
00222    {
00223       //Suspend scheduler activity
00224       OSSchedLock();
00225    }
00226 }
00227 
00228 
00229 /**
00230  * @brief Resume scheduler activity
00231  **/
00232 
00233 void osResumeAllTasks(void)
00234 {
00235    //Make sure the operating system is running
00236    if(OSRunning == OS_TRUE)
00237    {
00238       //Resume scheduler activity
00239       OSSchedUnlock();
00240    }
00241 }
00242 
00243 
00244 /**
00245  * @brief Create an event object
00246  * @param[in] event Pointer to the event object
00247  * @return The function returns TRUE if the event object was successfully
00248  *   created. Otherwise, FALSE is returned
00249  **/
00250 
00251 bool_t osCreateEvent(OsEvent *event)
00252 {
00253    INT8U err;
00254 
00255    //Create an event flag group
00256    event->p = OSFlagCreate(0, &err);
00257 
00258    //Check whether the event flag group was successfully created
00259    if(event->p != NULL && err == OS_ERR_NONE)
00260       return TRUE;
00261    else
00262       return FALSE;
00263 }
00264 
00265 
00266 /**
00267  * @brief Delete an event object
00268  * @param[in] event Pointer to the event object
00269  **/
00270 
00271 void osDeleteEvent(OsEvent *event)
00272 {
00273    INT8U err;
00274 
00275    //Make sure the operating system is running
00276    if(OSRunning == OS_TRUE)
00277    {
00278       //Properly dispose the event object
00279       OSFlagDel(event->p, OS_DEL_ALWAYS, &err);
00280    }
00281 }
00282 
00283 
00284 /**
00285  * @brief Set the specified event object to the signaled state
00286  * @param[in] event Pointer to the event object
00287  **/
00288 
00289 void osSetEvent(OsEvent *event)
00290 {
00291    INT8U err;
00292 
00293    //Set the specified event to the signaled state
00294    OSFlagPost(event->p, 1, OS_FLAG_SET, &err);
00295 }
00296 
00297 
00298 /**
00299  * @brief Set the specified event object to the nonsignaled state
00300  * @param[in] event Pointer to the event object
00301  **/
00302 
00303 void osResetEvent(OsEvent *event)
00304 {
00305    INT8U err;
00306 
00307    //Force the specified event to the nonsignaled state
00308    OSFlagPost(event->p, 1, OS_FLAG_CLR, &err);
00309 }
00310 
00311 
00312 /**
00313  * @brief Wait until the specified event is in the signaled state
00314  * @param[in] event Pointer to the event object
00315  * @param[in] timeout Timeout interval
00316  * @return The function returns TRUE if the state of the specified object is
00317  *   signaled. FALSE is returned if the timeout interval elapsed
00318  **/
00319 
00320 bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
00321 {
00322    INT8U err;
00323    INT16U n;
00324 
00325    //Wait until the specified event is in the signaled
00326    //state or the timeout interval elapses
00327    if(timeout == 0)
00328    {
00329       //Non-blocking call
00330       OSFlagAccept(event->p, 1, OS_FLAG_WAIT_SET_ANY | OS_FLAG_CONSUME, &err);
00331    }
00332    else if(timeout == INFINITE_DELAY)
00333    {
00334       //Infinite timeout period
00335       OSFlagPend(event->p, 1, OS_FLAG_WAIT_SET_ANY | OS_FLAG_CONSUME, 0, &err);
00336    }
00337    else
00338    {
00339       //Convert milliseconds to system ticks
00340       timeout = OS_MS_TO_SYSTICKS(timeout);
00341 
00342       //Loop until the assigned time period has elapsed
00343       do
00344       {
00345          //The maximum timeout is 65535 clock ticks
00346          n = MIN(timeout, 65535);
00347          //Wait for the specified time interval
00348          OSFlagPend(event->p, 1, OS_FLAG_WAIT_SET_ANY | OS_FLAG_CONSUME, n, &err);
00349          //Decrement timeout value
00350          timeout -= n;
00351 
00352          //Check timeout value
00353       } while(err == OS_ERR_TIMEOUT && timeout > 0);
00354    }
00355 
00356    //Check whether the specified event is set
00357    if(err == OS_ERR_NONE)
00358       return TRUE;
00359    else
00360       return FALSE;
00361 }
00362 
00363 
00364 /**
00365  * @brief Set an event object to the signaled state from an interrupt service routine
00366  * @param[in] event Pointer to the event object
00367  * @return TRUE if setting the event to signaled state caused a task to unblock
00368  *   and the unblocked task has a priority higher than the currently running task
00369  **/
00370 
00371 bool_t osSetEventFromIsr(OsEvent *event)
00372 {
00373    INT8U err;
00374 
00375    //Set the specified event to the signaled state
00376    OSFlagPost(event->p, 1, OS_FLAG_SET, &err);
00377 
00378    //The return value is not relevant
00379    return FALSE;
00380 }
00381 
00382 
00383 /**
00384  * @brief Create a semaphore object
00385  * @param[in] semaphore Pointer to the semaphore object
00386  * @param[in] count The maximum count for the semaphore object. This value
00387  *   must be greater than zero
00388  * @return The function returns TRUE if the semaphore was successfully
00389  *   created. Otherwise, FALSE is returned
00390  **/
00391 
00392 bool_t osCreateSemaphore(OsSemaphore *semaphore, uint_t count)
00393 {
00394    //Create a semaphore
00395    semaphore->p = OSSemCreate(count);
00396 
00397    //Check whether the semaphore was successfully created
00398    if(semaphore->p != NULL)
00399       return TRUE;
00400    else
00401       return FALSE;
00402 }
00403 
00404 
00405 /**
00406  * @brief Delete a semaphore object
00407  * @param[in] semaphore Pointer to the semaphore object
00408  **/
00409 
00410 void osDeleteSemaphore(OsSemaphore *semaphore)
00411 {
00412    INT8U err;
00413 
00414    //Make sure the operating system is running
00415    if(OSRunning == OS_TRUE)
00416    {
00417       //Properly dispose the specified semaphore
00418       OSSemDel(semaphore->p, OS_DEL_ALWAYS, &err);
00419    }
00420 }
00421 
00422 
00423 /**
00424  * @brief Wait for the specified semaphore to be available
00425  * @param[in] semaphore Pointer to the semaphore object
00426  * @param[in] timeout Timeout interval
00427  * @return The function returns TRUE if the semaphore is available. FALSE is
00428  *   returned if the timeout interval elapsed
00429  **/
00430 
00431 bool_t osWaitForSemaphore(OsSemaphore *semaphore, systime_t timeout)
00432 {
00433    INT8U err;
00434    INT16U n;
00435 
00436    //Wait until the semaphore is available or the timeout interval elapses
00437    if(timeout == 0)
00438    {
00439       //Non-blocking call
00440       if(OSSemAccept(semaphore->p) > 0)
00441          err = OS_ERR_NONE;
00442       else
00443          err = OS_ERR_TIMEOUT;
00444    }
00445    else if(timeout == INFINITE_DELAY)
00446    {
00447       //Infinite timeout period
00448       OSSemPend(semaphore->p, 0, &err);
00449    }
00450    else
00451    {
00452       //Convert milliseconds to system ticks
00453       timeout = OS_MS_TO_SYSTICKS(timeout);
00454 
00455       //Loop until the assigned time period has elapsed
00456       do
00457       {
00458          //The maximum timeout is 65535 clock ticks
00459          n = MIN(timeout, 65535);
00460          //Wait for the specified time interval
00461          OSSemPend(semaphore->p, n, &err);
00462          //Decrement timeout value
00463          timeout -= n;
00464 
00465          //Check timeout value
00466       } while(err == OS_ERR_TIMEOUT && timeout > 0);
00467    }
00468 
00469    //Check whether the specified semaphore is available
00470    if(err == OS_ERR_NONE)
00471       return TRUE;
00472    else
00473       return FALSE;
00474 }
00475 
00476 
00477 /**
00478  * @brief Release the specified semaphore object
00479  * @param[in] semaphore Pointer to the semaphore object
00480  **/
00481 
00482 void osReleaseSemaphore(OsSemaphore *semaphore)
00483 {
00484    //Release the semaphore
00485    OSSemPost(semaphore->p);
00486 }
00487 
00488 
00489 /**
00490  * @brief Create a mutex object
00491  * @param[in] mutex Pointer to the mutex object
00492  * @return The function returns TRUE if the mutex was successfully
00493  *   created. Otherwise, FALSE is returned
00494  **/
00495 
00496 bool_t osCreateMutex(OsMutex *mutex)
00497 {
00498 #if 1
00499    bool_t status;
00500 
00501    //Create an event object
00502    status = osCreateEvent((OsEvent *) mutex);
00503 
00504    //Check whether the event object was successfully created
00505    if(status)
00506    {
00507       //Set event
00508       osSetEvent((OsEvent *) mutex);
00509    }
00510 
00511    //Return status
00512    return status;
00513 #else
00514    INT8U err;
00515 
00516    //Create a mutex
00517    mutex->p = OSMutexCreate(10, &err);
00518 
00519    //Check whether the mutex was successfully created
00520    if(mutex->p != NULL && err == OS_ERR_NONE)
00521       return TRUE;
00522    else
00523       return FALSE;
00524 #endif
00525 }
00526 
00527 
00528 /**
00529  * @brief Delete a mutex object
00530  * @param[in] mutex Pointer to the mutex object
00531  **/
00532 
00533 void osDeleteMutex(OsMutex *mutex)
00534 {
00535 #if 1
00536    //Delete event object
00537    osDeleteEvent((OsEvent *) mutex);
00538 #else
00539    INT8U err;
00540 
00541    //Make sure the operating system is running
00542    if(OSRunning == OS_TRUE)
00543    {
00544       //Properly dispose the specified mutex
00545       OSMutexDel(mutex->p, OS_DEL_ALWAYS, &err);
00546    }
00547 #endif
00548 }
00549 
00550 
00551 /**
00552  * @brief Acquire ownership of the specified mutex object
00553  * @param[in] mutex Pointer to the mutex object
00554  **/
00555 
00556 void osAcquireMutex(OsMutex *mutex)
00557 {
00558 #if 1
00559    //Wait for event
00560    osWaitForEvent((OsEvent *) mutex, INFINITE_DELAY);
00561 #else
00562    INT8U err;
00563 
00564    //Obtain ownership of the mutex object
00565    OSMutexPend(mutex->p, 0, &err);
00566 #endif
00567 }
00568 
00569 
00570 /**
00571  * @brief Release ownership of the specified mutex object
00572  * @param[in] mutex Pointer to the mutex object
00573  **/
00574 
00575 void osReleaseMutex(OsMutex *mutex)
00576 {
00577 #if 1
00578    //Set event
00579    osSetEvent((OsEvent *) mutex);
00580 #else
00581    //Release ownership of the mutex object
00582    OSMutexPost(mutex->p);
00583 #endif
00584 }
00585 
00586 
00587 /**
00588  * @brief Retrieve system time
00589  * @return Number of milliseconds elapsed since the system was last started
00590  **/
00591 
00592 systime_t osGetSystemTime(void)
00593 {
00594    systime_t time;
00595 
00596    //Get current tick count
00597    time = OSTimeGet();
00598 
00599    //Convert system ticks to milliseconds
00600    return OS_SYSTICKS_TO_MS(time);
00601 }
00602 
00603 
00604 /**
00605  * @brief Allocate a memory block
00606  * @param[in] size Bytes to allocate
00607  * @return A pointer to the allocated memory block or NULL if
00608  *   there is insufficient memory available
00609  **/
00610 
00611 void *osAllocMem(size_t size)
00612 {
00613    void *p;
00614 
00615    //Enter critical section
00616    osSuspendAllTasks();
00617    //Allocate a memory block
00618    p = malloc(size);
00619    //Leave critical section
00620    osResumeAllTasks();
00621 
00622    //Debug message
00623    TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n", size, (uintptr_t) p);
00624 
00625    //Return a pointer to the newly allocated memory block
00626    return p;
00627 }
00628 
00629 
00630 /**
00631  * @brief Release a previously allocated memory block
00632  * @param[in] p Previously allocated memory block to be freed
00633  **/
00634 
00635 void osFreeMem(void *p)
00636 {
00637    //Make sure the pointer is valid
00638    if(p != NULL)
00639    {
00640       //Debug message
00641       TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
00642 
00643       //Enter critical section
00644       osSuspendAllTasks();
00645       //Free memory block
00646       free(p);
00647       //Leave critical section
00648       osResumeAllTasks();
00649    }
00650 }
00651