os_port_chibios.c
Go to the documentation of this file.
1 /**
2  * @file os_port_chibios.c
3  * @brief RTOS abstraction layer (ChibiOS/RT)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2020 Oryx Embedded SARL. All rights reserved.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.8
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL TRACE_LEVEL_OFF
31 
32 //Dependencies
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include "os_port.h"
37 #include "os_port_chibios.h"
38 #include "debug.h"
39 
40 //Variables
41 static OsTask taskTable[OS_PORT_MAX_TASKS];
42 static uint_t *waTable[OS_PORT_MAX_TASKS];
43 
44 
45 /**
46  * @brief Kernel initialization
47  **/
48 
49 void osInitKernel(void)
50 {
51  //Initialize tables
52  osMemset(taskTable, 0, sizeof(taskTable));
53  osMemset(waTable, 0, sizeof(waTable));
54 
55  //Kernel initialization
56  chSysInit();
57 }
58 
59 
60 /**
61  * @brief Start kernel
62  **/
63 
64 void osStartKernel(void)
65 {
66  //Terminate the main thread
67  chThdExit(MSG_OK);
68 }
69 
70 
71 /**
72  * @brief Create a static task
73  * @param[out] task Pointer to the task structure
74  * @param[in] name A name identifying the task
75  * @param[in] taskCode Pointer to the task entry function
76  * @param[in] param A pointer to a variable to be passed to the task
77  * @param[in] stack Pointer to the stack
78  * @param[in] stackSize The initial size of the stack, in words
79  * @param[in] priority The priority at which the task should run
80  * @return The function returns TRUE if the task was successfully
81  * created. Otherwise, FALSE is returned
82  **/
83 
85  void *param, void *stack, size_t stackSize, int_t priority)
86 {
87  //Compute the size of the working area in bytes
88  stackSize *= sizeof(uint_t);
89 
90  //Create a new task
91  task->tp = chThdCreateStatic(stack, stackSize,
92  priority, (tfunc_t) taskCode, param);
93 
94  //Check whether the task was successfully created
95  if(task->tp != NULL)
96  return TRUE;
97  else
98  return FALSE;
99 }
100 
101 
102 /**
103  * @brief Create a new task
104  * @param[in] name A name identifying the task
105  * @param[in] taskCode Pointer to the task entry function
106  * @param[in] param A pointer to a variable to be passed to the task
107  * @param[in] stackSize The initial size of the stack, in words
108  * @param[in] priority The priority at which the task should run
109  * @return If the function succeeds, the return value is a pointer to the
110  * new task. If the function fails, the return value is NULL
111  **/
112 
114  void *param, size_t stackSize, int_t priority)
115 {
116  uint_t i;
117  void *wa;
118  OsTask *task = NULL;
119 
120  //Compute the size of the stack in bytes
121  stackSize *= sizeof(uint_t);
122 
123  //Allocate a memory block to hold the working area
124  wa = osAllocMem(THD_WORKING_AREA_SIZE(stackSize));
125 
126  //Successful memory allocation?
127  if(wa != NULL)
128  {
129  //Enter critical section
130  chSysLock();
131 
132  //Loop through task table
133  for(i = 0; i < OS_PORT_MAX_TASKS; i++)
134  {
135  //Check whether the current entry is free
136  if(taskTable[i].tp == NULL)
137  break;
138  }
139 
140  //Any entry available in the table?
141  if(i < OS_PORT_MAX_TASKS)
142  {
143  //Create a new task
144  taskTable[i].tp = chThdCreateI(wa, THD_WORKING_AREA_SIZE(stackSize),
145  priority, (tfunc_t) taskCode, param);
146 
147  //Check whether the task was successfully created
148  if(taskTable[i].tp != NULL)
149  {
150  //Insert the newly created task in the ready list
151  chSchWakeupS(taskTable[i].tp, MSG_OK);
152 
153  //Save task pointer
154  task = &taskTable[i];
155  //Save working area base address
156  waTable[i] = wa;
157 
158  //Leave critical section
159  chSysUnlock();
160  }
161  else
162  {
163  //Leave critical section
164  chSysUnlock();
165  //Clean up side effects
166  osFreeMem(wa);
167  }
168  }
169  else
170  {
171  //Leave critical section
172  chSysUnlock();
173  //No entry available in the table
174  osFreeMem(wa);
175  }
176  }
177 
178  //Return a pointer to the newly created task
179  return task;
180 }
181 
182 
183 /**
184  * @brief Delete a task
185  * @param[in] task Pointer to the task to be deleted
186  **/
187 
188 void osDeleteTask(OsTask *task)
189 {
190  //Delete the specified task
191  if(task == NULL)
192  chThdExit(MSG_OK);
193  else
194  chThdTerminate(task->tp);
195 }
196 
197 
198 /**
199  * @brief Delay routine
200  * @param[in] delay Amount of time for which the calling task should block
201  **/
202 
204 {
205  //Delay the task for the specified duration
206  chThdSleep(OS_MS_TO_SYSTICKS(delay));
207 }
208 
209 
210 /**
211  * @brief Yield control to the next task
212  **/
213 
214 void osSwitchTask(void)
215 {
216  //Force a context switch
217  chThdYield();
218 }
219 
220 
221 /**
222  * @brief Suspend scheduler activity
223  **/
224 
226 {
227  //Suspend scheduler activity
228  chSysLock();
229 }
230 
231 
232 /**
233  * @brief Resume scheduler activity
234  **/
235 
237 {
238  //Resume scheduler activity
239  chSysUnlock();
240 }
241 
242 
243 /**
244  * @brief Create an event object
245  * @param[in] event Pointer to the event object
246  * @return The function returns TRUE if the event object was successfully
247  * created. Otherwise, FALSE is returned
248  **/
249 
251 {
252  //Initialize the binary semaphore object
253  chBSemObjectInit(event, TRUE);
254 
255  //Event successfully created
256  return TRUE;
257 }
258 
259 
260 /**
261  * @brief Delete an event object
262  * @param[in] event Pointer to the event object
263  **/
264 
265 void osDeleteEvent(OsEvent *event)
266 {
267  //No resource to release
268 }
269 
270 
271 /**
272  * @brief Set the specified event object to the signaled state
273  * @param[in] event Pointer to the event object
274  **/
275 
276 void osSetEvent(OsEvent *event)
277 {
278  //Set the specified event to the signaled state
279  chBSemSignal(event);
280 }
281 
282 
283 /**
284  * @brief Set the specified event object to the nonsignaled state
285  * @param[in] event Pointer to the event object
286  **/
287 
288 void osResetEvent(OsEvent *event)
289 {
290  //Force the specified event to the nonsignaled state
291  chBSemReset(event, TRUE);
292 }
293 
294 
295 /**
296  * @brief Wait until the specified event is in the signaled state
297  * @param[in] event Pointer to the event object
298  * @param[in] timeout Timeout interval
299  * @return The function returns TRUE if the state of the specified object is
300  * signaled. FALSE is returned if the timeout interval elapsed
301  **/
302 
304 {
305  msg_t msg;
306 
307  //Wait until the specified event is in the signaled
308  //state or the timeout interval elapses
309  if(timeout == 0)
310  {
311  //Non-blocking call
312  msg = chBSemWaitTimeout(event, TIME_IMMEDIATE);
313  }
314  else if(timeout == INFINITE_DELAY)
315  {
316  //Infinite timeout period
317  msg = chBSemWaitTimeout(event, TIME_INFINITE);
318  }
319  else
320  {
321  //Wait until the specified event becomes set
322  msg = chBSemWaitTimeout(event, OS_MS_TO_SYSTICKS(timeout));
323  }
324 
325  //Check whether the specified event is set
326  if(msg == MSG_OK)
327  return TRUE;
328  else
329  return FALSE;
330 }
331 
332 
333 /**
334  * @brief Set an event object to the signaled state from an interrupt service routine
335  * @param[in] event Pointer to the event object
336  * @return TRUE if setting the event to signaled state caused a task to unblock
337  * and the unblocked task has a priority higher than the currently running task
338  **/
339 
341 {
342  //Set the specified event to the signaled state
343  chBSemSignalI(event);
344 
345  //The return value is not relevant
346  return FALSE;
347 }
348 
349 
350 /**
351  * @brief Create a semaphore object
352  * @param[in] semaphore Pointer to the semaphore object
353  * @param[in] count The maximum count for the semaphore object. This value
354  * must be greater than zero
355  * @return The function returns TRUE if the semaphore was successfully
356  * created. Otherwise, FALSE is returned
357  **/
358 
360 {
361  //Initialize the semaphore object
362  chSemObjectInit(semaphore, count);
363 
364  //Semaphore successfully created
365  return TRUE;
366 }
367 
368 
369 /**
370  * @brief Delete a semaphore object
371  * @param[in] semaphore Pointer to the semaphore object
372  **/
373 
375 {
376  //No resource to release
377 }
378 
379 
380 /**
381  * @brief Wait for the specified semaphore to be available
382  * @param[in] semaphore Pointer to the semaphore object
383  * @param[in] timeout Timeout interval
384  * @return The function returns TRUE if the semaphore is available. FALSE is
385  * returned if the timeout interval elapsed
386  **/
387 
389 {
390  msg_t msg;
391 
392  //Wait until the semaphore is available or the timeout interval elapses
393  if(timeout == 0)
394  {
395  //Non-blocking call
396  msg = chSemWaitTimeout(semaphore, TIME_IMMEDIATE);
397  }
398  else if(timeout == INFINITE_DELAY)
399  {
400  //Infinite timeout period
401  msg = chSemWaitTimeout(semaphore, TIME_INFINITE);
402  }
403  else
404  {
405  //Wait until the specified semaphore becomes available
406  msg = chSemWaitTimeout(semaphore, OS_MS_TO_SYSTICKS(timeout));
407  }
408 
409  //Check whether the specified semaphore is available
410  if(msg == MSG_OK)
411  return TRUE;
412  else
413  return FALSE;
414 }
415 
416 
417 /**
418  * @brief Release the specified semaphore object
419  * @param[in] semaphore Pointer to the semaphore object
420  **/
421 
423 {
424  //Release the semaphore
425  chSemSignal(semaphore);
426 }
427 
428 
429 /**
430  * @brief Create a mutex object
431  * @param[in] mutex Pointer to the mutex object
432  * @return The function returns TRUE if the mutex was successfully
433  * created. Otherwise, FALSE is returned
434  **/
435 
437 {
438  //Initialize the mutex object
439  chMtxObjectInit(mutex);
440 
441  //Mutex successfully created
442  return TRUE;
443 }
444 
445 
446 /**
447  * @brief Delete a mutex object
448  * @param[in] mutex Pointer to the mutex object
449  **/
450 
451 void osDeleteMutex(OsMutex *mutex)
452 {
453  //No resource to release
454 }
455 
456 
457 /**
458  * @brief Acquire ownership of the specified mutex object
459  * @param[in] mutex Pointer to the mutex object
460  **/
461 
463 {
464  //Obtain ownership of the mutex object
465  chMtxLock(mutex);
466 }
467 
468 
469 /**
470  * @brief Release ownership of the specified mutex object
471  * @param[in] mutex Pointer to the mutex object
472  **/
473 
475 {
476  //Release ownership of the mutex object
477 #if (CH_KERNEL_MAJOR < 3)
478  chMtxUnlock();
479 #else
480  chMtxUnlock(mutex);
481 #endif
482 }
483 
484 
485 /**
486  * @brief Retrieve system time
487  * @return Number of milliseconds elapsed since the system was last started
488  **/
489 
491 {
492  systime_t time;
493 
494  //Get current tick count
496 
497  //Convert system ticks to milliseconds
498  return OS_SYSTICKS_TO_MS(time);
499 }
500 
501 
502 /**
503  * @brief Allocate a memory block
504  * @param[in] size Bytes to allocate
505  * @return A pointer to the allocated memory block or NULL if
506  * there is insufficient memory available
507  **/
508 
509 void *osAllocMem(size_t size)
510 {
511  void *p;
512 
513  //Allocate a memory block
514  p = chHeapAlloc(NULL, size);
515 
516  //Debug message
517  TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n", size, (uintptr_t) p);
518 
519  //Return a pointer to the newly allocated memory block
520  return p;
521 }
522 
523 
524 /**
525  * @brief Release a previously allocated memory block
526  * @param[in] p Previously allocated memory block to be freed
527  **/
528 
529 void osFreeMem(void *p)
530 {
531  //Make sure the pointer is valid
532  if(p != NULL)
533  {
534  //Debug message
535  TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
536 
537  //Free memory block
538  chHeapFree(p);
539  }
540 }
541 
542 
543 /**
544  * @brief Idle loop hook
545  **/
546 
547 void osIdleLoopHook(void)
548 {
549  uint_t i;
550 
551  //Loop through task table
552  for(i = 0; i < OS_PORT_MAX_TASKS; i++)
553  {
554  //Check whether current entry is used
555  if(taskTable[i].tp != NULL)
556  {
557  //Wait for task termination
558  if(chThdTerminatedX(taskTable[i].tp))
559  {
560  //Free working area
561  osFreeMem(waTable[i]);
562 
563  //Mark the entry as free
564  waTable[i] = NULL;
565  taskTable[i].tp = NULL;
566  }
567  }
568  }
569 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
RTOS abstraction layer (ChibiOS/RT)
int bool_t
Definition: compiler_port.h:49
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
signed int int_t
Definition: compiler_port.h:44
void osReleaseSemaphore(OsSemaphore *semaphore)
Release the specified semaphore object.
uint8_t p
Definition: ndp.h:298
void osStartKernel(void)
Start kernel.
#define TRUE
Definition: os_port.h:50
Event object.
char_t name[]
bool_t osWaitForSemaphore(OsSemaphore *semaphore, systime_t timeout)
Wait for the specified semaphore to be available.
void osDeleteSemaphore(OsSemaphore *semaphore)
Delete a semaphore object.
Semaphore object.
bool_t osCreateSemaphore(OsSemaphore *semaphore, uint_t count)
Create a semaphore object.
#define FALSE
Definition: os_port.h:46
OsTask * osCreateTask(const char_t *name, OsTaskCode taskCode, void *param, size_t stackSize, int_t priority)
Create a new task.
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
#define chSemObjectInit
void osIdleLoopHook(void)
Idle loop hook.
void osDeleteEvent(OsEvent *event)
Delete an event object.
Task object.
void osInitKernel(void)
Kernel initialization.
#define OS_SYSTICKS_TO_MS(n)
#define OS_MS_TO_SYSTICKS(n)
void * osAllocMem(size_t size)
Allocate a memory block.
void osResumeAllTasks(void)
Resume scheduler activity.
void osSwitchTask(void)
Yield control to the next task.
Mutex object.
#define THD_WORKING_AREA_SIZE
#define TRACE_DEBUG(...)
Definition: debug.h:107
char char_t
Definition: compiler_port.h:43
uint32_t time
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
#define chBSemObjectInit
void osSuspendAllTasks(void)
Suspend scheduler activity.
void(* OsTaskCode)(void *param)
Task routine.
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
bool_t osCreateEvent(OsEvent *event)
Create an event object.
void osDeleteTask(OsTask *task)
Delete a task.
#define MSG_OK
void osDelayTask(systime_t delay)
Delay routine.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
bool_t osCreateStaticTask(OsTask *task, const char_t *name, OsTaskCode taskCode, void *param, void *stack, size_t stackSize, int_t priority)
Create a static task.
#define OS_PORT_MAX_TASKS
#define chVTGetSystemTime
thread_t * tp
#define PRIuSIZE
Definition: compiler_port.h:78
unsigned int uint_t
Definition: compiler_port.h:45
#define osMemset(p, value, length)
Definition: os_port.h:128
#define chThdTerminatedX
uint16_t priority
Definition: dns_common.h:221
RTOS abstraction layer.
uint32_t systime_t
Definition: compiler_port.h:46
void osFreeMem(void *p)
Release a previously allocated memory block.
Debugging facilities.
#define chMtxObjectInit
#define INFINITE_DELAY
Definition: os_port.h:74
systime_t osGetSystemTime(void)
Retrieve system time.