Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Tue Jul 12 2022 17:10:15 by
