Sergey Pastor / 1

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers os_port_rtx.c Source File

os_port_rtx.c

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