Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers os_port_freertos.c Source File

os_port_freertos.c

Go to the documentation of this file.
00001 /**
00002  * @file os_port_freertos.c
00003  * @brief RTOS abstraction layer (FreeRTOS)
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 "os_port.h"
00034 #include "os_port_freertos.h"
00035 #include "debug.h"
00036 
00037 
00038 /**
00039  * @brief Kernel initialization
00040  **/
00041 
00042 void osInitKernel(void)
00043 {
00044 }
00045 
00046 
00047 /**
00048  * @brief Start kernel
00049  **/
00050 
00051 void osStartKernel(void)
00052 {
00053    //Start the scheduler
00054    vTaskStartScheduler();
00055 }
00056 
00057 
00058 /**
00059  * @brief Create a new task
00060  * @param[in] name A name identifying the task
00061  * @param[in] taskCode Pointer to the task entry function
00062  * @param[in] params A pointer to a variable to be passed to the task
00063  * @param[in] stackSize The initial size of the stack, in words
00064  * @param[in] priority The priority at which the task should run
00065  * @return If the function succeeds, the return value is a pointer to the
00066  *   new task. If the function fails, the return value is NULL
00067  **/
00068 
00069 OsTask *osCreateTask(const char_t *name, OsTaskCode taskCode,
00070    void *params, size_t stackSize, int_t priority)
00071 {
00072    portBASE_TYPE status;
00073    xTaskHandle task = NULL;
00074 
00075    //Create a new task
00076    status = xTaskCreate((pdTASK_CODE) taskCode,
00077       name, stackSize, params, priority, &task);
00078 
00079    //Check whether the task was successfully created
00080    if(status == pdPASS)
00081       return task;
00082    else
00083       return NULL;
00084 }
00085 
00086 
00087 /**
00088  * @brief Delete a task
00089  * @param[in] task Pointer to the task to be deleted
00090  **/
00091 
00092 void osDeleteTask(OsTask *task)
00093 {
00094    //Delete the specified task
00095    vTaskDelete((xTaskHandle) task);
00096 }
00097 
00098 
00099 /**
00100  * @brief Delay routine
00101  * @param[in] delay Amount of time for which the calling task should block
00102  **/
00103 
00104 void osDelayTask(systime_t delay)
00105 {
00106    //Delay the task for the specified duration
00107    vTaskDelay(OS_MS_TO_SYSTICKS(delay));
00108 }
00109 
00110 
00111 /**
00112  * @brief Yield control to the next task
00113  **/
00114 
00115 void osSwitchTask(void)
00116 {
00117    //Force a context switch
00118    taskYIELD();
00119 }
00120 
00121 
00122 /**
00123  * @brief Suspend scheduler activity
00124  **/
00125 
00126 void osSuspendAllTasks(void)
00127 {
00128    //Make sure the operating system is running
00129    if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
00130    {
00131       //Suspend all tasks
00132       vTaskSuspendAll();
00133    }
00134 }
00135 
00136 
00137 /**
00138  * @brief Resume scheduler activity
00139  **/
00140 
00141 void osResumeAllTasks(void)
00142 {
00143    //Make sure the operating system is running
00144    if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
00145    {
00146       //Resume all tasks
00147       xTaskResumeAll();
00148    }
00149 }
00150 
00151 
00152 /**
00153  * @brief Create an event object
00154  * @param[in] event Pointer to the event object
00155  * @return The function returns TRUE if the event object was successfully
00156  *   created. Otherwise, FALSE is returned
00157  **/
00158 
00159 bool_t osCreateEvent(OsEvent *event)
00160 {
00161    //Create a binary semaphore
00162    vSemaphoreCreateBinary(event->handle);
00163 
00164    //Check whether the returned handle is valid
00165    if(event->handle != NULL)
00166    {
00167       //Force the event to the nonsignaled state
00168       xSemaphoreTake(event->handle, 0);
00169       //Event successfully created
00170       return TRUE;
00171    }
00172    else
00173    {
00174       //Failed to create event object
00175       return FALSE;
00176    }
00177 }
00178 
00179 
00180 /**
00181  * @brief Delete an event object
00182  * @param[in] event Pointer to the event object
00183  **/
00184 
00185 void osDeleteEvent(OsEvent *event)
00186 {
00187    //Make sure the handle is valid
00188    if(event->handle != NULL)
00189    {
00190       //Properly dispose the event object
00191       vSemaphoreDelete(event->handle);
00192    }
00193 }
00194 
00195 
00196 /**
00197  * @brief Set the specified event object to the signaled state
00198  * @param[in] event Pointer to the event object
00199  **/
00200 
00201 void osSetEvent(OsEvent *event)
00202 {
00203    //Set the specified event to the signaled state
00204    xSemaphoreGive(event->handle);
00205 }
00206 
00207 
00208 /**
00209  * @brief Set the specified event object to the nonsignaled state
00210  * @param[in] event Pointer to the event object
00211  **/
00212 
00213 void osResetEvent(OsEvent *event)
00214 {
00215    //Force the specified event to the nonsignaled state
00216    xSemaphoreTake(event->handle, 0);
00217 }
00218 
00219 
00220 /**
00221  * @brief Wait until the specified event is in the signaled state
00222  * @param[in] event Pointer to the event object
00223  * @param[in] timeout Timeout interval
00224  * @return The function returns TRUE if the state of the specified object is
00225  *   signaled. FALSE is returned if the timeout interval elapsed
00226  **/
00227 
00228 bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
00229 {
00230    portBASE_TYPE ret;
00231 
00232    //Wait until the specified event is in the signaled state
00233    if(timeout == INFINITE_DELAY)
00234    {
00235       //Infinite timeout period
00236       ret = xSemaphoreTake(event->handle, portMAX_DELAY);
00237    }
00238    else
00239    {
00240       //Wait for the specified time interval
00241       ret = xSemaphoreTake(event->handle, OS_MS_TO_SYSTICKS(timeout));
00242    }
00243 
00244    //The return value tells whether the event is set
00245    return ret;
00246 }
00247 
00248 
00249 /**
00250  * @brief Set an event object to the signaled state from an interrupt service routine
00251  * @param[in] event Pointer to the event object
00252  * @return TRUE if setting the event to signaled state caused a task to unblock
00253  *   and the unblocked task has a priority higher than the currently running task
00254  **/
00255 
00256 bool_t osSetEventFromIsr(OsEvent *event)
00257 {
00258    portBASE_TYPE flag = FALSE;
00259 
00260    //Set the specified event to the signaled state
00261    xSemaphoreGiveFromISR(event->handle, &flag);
00262 
00263    //A higher priority task has been woken?
00264    return flag;
00265 }
00266 
00267 
00268 /**
00269  * @brief Create a semaphore object
00270  * @param[in] semaphore Pointer to the semaphore object
00271  * @param[in] count The maximum count for the semaphore object. This value
00272  *   must be greater than zero
00273  * @return The function returns TRUE if the semaphore was successfully
00274  *   created. Otherwise, FALSE is returned
00275  **/
00276 
00277 bool_t osCreateSemaphore(OsSemaphore *semaphore, uint_t count)
00278 {
00279    //Create a semaphore
00280    semaphore->handle = xSemaphoreCreateCounting(count, count);
00281 
00282    //Check whether the returned handle is valid
00283    if(semaphore->handle != NULL)
00284       return TRUE;
00285    else
00286       return FALSE;
00287 }
00288 
00289 
00290 /**
00291  * @brief Delete a semaphore object
00292  * @param[in] semaphore Pointer to the semaphore object
00293  **/
00294 
00295 void osDeleteSemaphore(OsSemaphore *semaphore)
00296 {
00297    //Make sure the handle is valid
00298    if(semaphore->handle != NULL)
00299    {
00300       //Properly dispose the specified semaphore
00301       vSemaphoreDelete(semaphore->handle);
00302    }
00303 }
00304 
00305 
00306 /**
00307  * @brief Wait for the specified semaphore to be available
00308  * @param[in] semaphore Pointer to the semaphore object
00309  * @param[in] timeout Timeout interval
00310  * @return The function returns TRUE if the semaphore is available. FALSE is
00311  *   returned if the timeout interval elapsed
00312  **/
00313 
00314 bool_t osWaitForSemaphore(OsSemaphore *semaphore, systime_t timeout)
00315 {
00316    portBASE_TYPE ret;
00317 
00318    //Wait until the specified semaphore becomes available
00319    if(timeout == INFINITE_DELAY)
00320    {
00321       //Infinite timeout period
00322       ret = xSemaphoreTake(semaphore->handle, portMAX_DELAY);
00323    }
00324    else
00325    {
00326       //Wait for the specified time interval
00327       ret = xSemaphoreTake(semaphore->handle, OS_MS_TO_SYSTICKS(timeout));
00328    }
00329 
00330    //The return value tells whether the semaphore is available
00331    return ret;
00332 }
00333 
00334 
00335 /**
00336  * @brief Release the specified semaphore object
00337  * @param[in] semaphore Pointer to the semaphore object
00338  **/
00339 
00340 void osReleaseSemaphore(OsSemaphore *semaphore)
00341 {
00342    //Release the semaphore
00343    xSemaphoreGive(semaphore->handle);
00344 }
00345 
00346 
00347 /**
00348  * @brief Create a mutex object
00349  * @param[in] mutex Pointer to the mutex object
00350  * @return The function returns TRUE if the mutex was successfully
00351  *   created. Otherwise, FALSE is returned
00352  **/
00353 
00354 bool_t osCreateMutex(OsMutex *mutex)
00355 {
00356    //Create a mutex object
00357    mutex->handle = xSemaphoreCreateMutex();
00358 
00359    //Check whether the returned handle is valid
00360    if(mutex->handle != NULL)
00361       return TRUE;
00362    else
00363       return FALSE;
00364 }
00365 
00366 
00367 /**
00368  * @brief Delete a mutex object
00369  * @param[in] mutex Pointer to the mutex object
00370  **/
00371 
00372 void osDeleteMutex(OsMutex *mutex)
00373 {
00374    //Make sure the handle is valid
00375    if(mutex->handle != NULL)
00376    {
00377       //Properly dispose the specified mutex
00378       vSemaphoreDelete(mutex->handle);
00379    }
00380 }
00381 
00382 
00383 /**
00384  * @brief Acquire ownership of the specified mutex object
00385  * @param[in] mutex Pointer to the mutex object
00386  **/
00387 
00388 void osAcquireMutex(OsMutex *mutex)
00389 {
00390    //Obtain ownership of the mutex object
00391    xSemaphoreTake(mutex->handle, portMAX_DELAY);
00392 }
00393 
00394 
00395 /**
00396  * @brief Release ownership of the specified mutex object
00397  * @param[in] mutex Pointer to the mutex object
00398  **/
00399 
00400 void osReleaseMutex(OsMutex *mutex)
00401 {
00402    //Release ownership of the mutex object
00403    xSemaphoreGive(mutex->handle);
00404 }
00405 
00406 
00407 /**
00408  * @brief Retrieve system time
00409  * @return Number of milliseconds elapsed since the system was last started
00410  **/
00411 
00412 systime_t osGetSystemTime(void)
00413 {
00414    systime_t time;
00415 
00416    //Get current tick count
00417    time = xTaskGetTickCount();
00418 
00419    //Convert system ticks to milliseconds
00420    return OS_SYSTICKS_TO_MS(time);
00421 }
00422 
00423 
00424 /**
00425  * @brief Allocate a memory block
00426  * @param[in] size Bytes to allocate
00427  * @return A pointer to the allocated memory block or NULL if
00428  *   there is insufficient memory available
00429  **/
00430 
00431 void *osAllocMem(size_t size)
00432 {
00433    void *p;
00434 
00435    //Allocate a memory block
00436    p = pvPortMalloc(size);
00437 
00438    //Debug message
00439    TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n", size, (uintptr_t) p);
00440 
00441    //Return a pointer to the newly allocated memory block
00442    return p;
00443 }
00444 
00445 
00446 /**
00447  * @brief Release a previously allocated memory block
00448  * @param[in] p Previously allocated memory block to be freed
00449  **/
00450 
00451 void osFreeMem(void *p)
00452 {
00453    //Make sure the pointer is valid
00454    if(p != NULL)
00455    {
00456       //Debug message
00457       TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
00458 
00459       //Free memory block
00460       vPortFree(p);
00461    }
00462 }
00463 
00464 
00465 /**
00466  * @brief FreeRTOS stack overflow hook
00467  **/
00468 
00469 void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName)
00470 {
00471    (void) pcTaskName;
00472    (void) pxTask;
00473 
00474    taskDISABLE_INTERRUPTS();
00475    while(1);
00476 }
00477 
00478 
00479 /**
00480  * @brief Trap FreeRTOS errors
00481  **/
00482 
00483 void vAssertCalled(const char *pcFile, unsigned long ulLine)
00484 {
00485    volatile unsigned long ul = 0;
00486 
00487    (void) pcFile;
00488    (void) ulLine;
00489 
00490    taskENTER_CRITICAL();
00491 
00492    //Set ul to a non-zero value using the debugger to step out of this function
00493    while(ul == 0)
00494    {
00495       portNOP();
00496    }
00497 
00498    taskEXIT_CRITICAL();
00499 }
00500