Webserver+3d print

Dependents:   Nucleo

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers os_port_chibios.c Source File

os_port_chibios.c

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