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-2024 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 2.4.4
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 //Default task parameters
42 {
43  NULL, //Stack
44  256, //Size of the stack
45  NORMALPRIO //Task priority
46 };
47 
48 
49 /**
50  * @brief Kernel initialization
51  **/
52 
53 void osInitKernel(void)
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 task
73  * @param[in] name NULL-terminated string identifying the task
74  * @param[in] taskCode Pointer to the task entry function
75  * @param[in] arg Argument passed to the task function
76  * @param[in] params Task parameters
77  * @return Task identifier referencing the newly created task
78  **/
79 
80 OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg,
81  const OsTaskParameters *params)
82 {
83  thread_t *handle;
84 
85  //Static allocation?
86  if(params->stack != NULL)
87  {
88  //Create a new task
89  handle = chThdCreateStatic(params->stack,
90  params->stackSize * sizeof(uint32_t), params->priority,
91  (tfunc_t) taskCode, arg);
92  }
93  else
94  {
95  //Create a new task
96  handle = chThdCreateFromHeap(0, THD_WORKING_AREA_SIZE(params->stackSize),
97  params->priority, taskCode, arg);
98  }
99 
100  //Return the handle referencing the newly created thread
101  return (OsTaskId) handle;
102 }
103 
104 
105 /**
106  * @brief Delete a task
107  * @param[in] taskId Task identifier referencing the task to be deleted
108  **/
109 
110 void osDeleteTask(OsTaskId taskId)
111 {
112  //Delete the specified task
113  if(taskId == OS_SELF_TASK_ID)
114  {
115  chThdExit(MSG_OK);
116  }
117  else
118  {
119  chThdTerminate((thread_t *) taskId);
120  }
121 }
122 
123 
124 /**
125  * @brief Delay routine
126  * @param[in] delay Amount of time for which the calling task should block
127  **/
128 
130 {
131  //Delay the task for the specified duration
132  chThdSleep(OS_MS_TO_SYSTICKS(delay));
133 }
134 
135 
136 /**
137  * @brief Yield control to the next task
138  **/
139 
140 void osSwitchTask(void)
141 {
142  //Force a context switch
143  chThdYield();
144 }
145 
146 
147 /**
148  * @brief Suspend scheduler activity
149  **/
150 
152 {
153  //Suspend scheduler activity
154  chSysLock();
155 }
156 
157 
158 /**
159  * @brief Resume scheduler activity
160  **/
161 
163 {
164  //Resume scheduler activity
165  chSysUnlock();
166 }
167 
168 
169 /**
170  * @brief Create an event object
171  * @param[in] event Pointer to the event object
172  * @return The function returns TRUE if the event object was successfully
173  * created. Otherwise, FALSE is returned
174  **/
175 
177 {
178  //Initialize the binary semaphore object
179  chBSemObjectInit(event, TRUE);
180 
181  //Event successfully created
182  return TRUE;
183 }
184 
185 
186 /**
187  * @brief Delete an event object
188  * @param[in] event Pointer to the event object
189  **/
190 
191 void osDeleteEvent(OsEvent *event)
192 {
193  //No resource to release
194 }
195 
196 
197 /**
198  * @brief Set the specified event object to the signaled state
199  * @param[in] event Pointer to the event object
200  **/
201 
202 void osSetEvent(OsEvent *event)
203 {
204  //Set the specified event to the signaled state
205  chBSemSignal(event);
206 }
207 
208 
209 /**
210  * @brief Set the specified event object to the nonsignaled state
211  * @param[in] event Pointer to the event object
212  **/
213 
214 void osResetEvent(OsEvent *event)
215 {
216  //Force the specified event to the nonsignaled state
217  chBSemReset(event, TRUE);
218 }
219 
220 
221 /**
222  * @brief Wait until the specified event is in the signaled state
223  * @param[in] event Pointer to the event object
224  * @param[in] timeout Timeout interval
225  * @return The function returns TRUE if the state of the specified object is
226  * signaled. FALSE is returned if the timeout interval elapsed
227  **/
228 
230 {
231  msg_t msg;
232 
233  //Wait until the specified event is in the signaled state or the timeout
234  //interval elapses
235  if(timeout == 0)
236  {
237  //Non-blocking call
238  msg = chBSemWaitTimeout(event, TIME_IMMEDIATE);
239  }
240  else if(timeout == INFINITE_DELAY)
241  {
242  //Infinite timeout period
243  msg = chBSemWaitTimeout(event, TIME_INFINITE);
244  }
245  else
246  {
247  //Wait until the specified event becomes set
248  msg = chBSemWaitTimeout(event, OS_MS_TO_SYSTICKS(timeout));
249  }
250 
251  //Check whether the specified event is set
252  if(msg == MSG_OK)
253  {
254  return TRUE;
255  }
256  else
257  {
258  return FALSE;
259  }
260 }
261 
262 
263 /**
264  * @brief Set an event object to the signaled state from an interrupt service routine
265  * @param[in] event Pointer to the event object
266  * @return TRUE if setting the event to signaled state caused a task to unblock
267  * and the unblocked task has a priority higher than the currently running task
268  **/
269 
271 {
272  //Set the specified event to the signaled state
273  chBSemSignalI(event);
274 
275  //The return value is not relevant
276  return FALSE;
277 }
278 
279 
280 /**
281  * @brief Create a semaphore object
282  * @param[in] semaphore Pointer to the semaphore object
283  * @param[in] count The maximum count for the semaphore object. This value
284  * must be greater than zero
285  * @return The function returns TRUE if the semaphore was successfully
286  * created. Otherwise, FALSE is returned
287  **/
288 
290 {
291  //Initialize the semaphore object
292  chSemObjectInit(semaphore, count);
293 
294  //Semaphore successfully created
295  return TRUE;
296 }
297 
298 
299 /**
300  * @brief Delete a semaphore object
301  * @param[in] semaphore Pointer to the semaphore object
302  **/
303 
305 {
306  //No resource to release
307 }
308 
309 
310 /**
311  * @brief Wait for the specified semaphore to be available
312  * @param[in] semaphore Pointer to the semaphore object
313  * @param[in] timeout Timeout interval
314  * @return The function returns TRUE if the semaphore is available. FALSE is
315  * returned if the timeout interval elapsed
316  **/
317 
319 {
320  msg_t msg;
321 
322  //Wait until the semaphore is available or the timeout interval elapses
323  if(timeout == 0)
324  {
325  //Non-blocking call
326  msg = chSemWaitTimeout(semaphore, TIME_IMMEDIATE);
327  }
328  else if(timeout == INFINITE_DELAY)
329  {
330  //Infinite timeout period
331  msg = chSemWaitTimeout(semaphore, TIME_INFINITE);
332  }
333  else
334  {
335  //Wait until the specified semaphore becomes available
336  msg = chSemWaitTimeout(semaphore, OS_MS_TO_SYSTICKS(timeout));
337  }
338 
339  //Check whether the specified semaphore is available
340  if(msg == MSG_OK)
341  {
342  return TRUE;
343  }
344  else
345  {
346  return FALSE;
347  }
348 }
349 
350 
351 /**
352  * @brief Release the specified semaphore object
353  * @param[in] semaphore Pointer to the semaphore object
354  **/
355 
357 {
358  //Release the semaphore
359  chSemSignal(semaphore);
360 }
361 
362 
363 /**
364  * @brief Create a mutex object
365  * @param[in] mutex Pointer to the mutex object
366  * @return The function returns TRUE if the mutex was successfully
367  * created. Otherwise, FALSE is returned
368  **/
369 
371 {
372  //Initialize the mutex object
373  chMtxObjectInit(mutex);
374 
375  //Mutex successfully created
376  return TRUE;
377 }
378 
379 
380 /**
381  * @brief Delete a mutex object
382  * @param[in] mutex Pointer to the mutex object
383  **/
384 
385 void osDeleteMutex(OsMutex *mutex)
386 {
387  //No resource to release
388 }
389 
390 
391 /**
392  * @brief Acquire ownership of the specified mutex object
393  * @param[in] mutex Pointer to the mutex object
394  **/
395 
397 {
398  //Obtain ownership of the mutex object
399  chMtxLock(mutex);
400 }
401 
402 
403 /**
404  * @brief Release ownership of the specified mutex object
405  * @param[in] mutex Pointer to the mutex object
406  **/
407 
409 {
410  //Release ownership of the mutex object
411 #if (CH_KERNEL_MAJOR < 3)
412  chMtxUnlock();
413 #else
414  chMtxUnlock(mutex);
415 #endif
416 }
417 
418 
419 /**
420  * @brief Retrieve system time
421  * @return Number of milliseconds elapsed since the system was last started
422  **/
423 
425 {
426  systime_t time;
427 
428  //Get current tick count
430 
431  //Convert system ticks to milliseconds
432  return OS_SYSTICKS_TO_MS(time);
433 }
434 
435 
436 /**
437  * @brief Allocate a memory block
438  * @param[in] size Bytes to allocate
439  * @return A pointer to the allocated memory block or NULL if
440  * there is insufficient memory available
441  **/
442 
443 __weak_func void *osAllocMem(size_t size)
444 {
445  void *p;
446 
447  //Allocate a memory block
448  p = chHeapAlloc(NULL, size);
449 
450  //Debug message
451  TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n",
452  size, (uintptr_t) p);
453 
454  //Return a pointer to the newly allocated memory block
455  return p;
456 }
457 
458 
459 /**
460  * @brief Release a previously allocated memory block
461  * @param[in] p Previously allocated memory block to be freed
462  **/
463 
464 __weak_func void osFreeMem(void *p)
465 {
466  //Make sure the pointer is valid
467  if(p != NULL)
468  {
469  //Debug message
470  TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
471 
472  //Free memory block
473  chHeapFree(p);
474  }
475 }
476 
477 
478 /**
479  * @brief Idle loop hook
480  **/
481 
482 void osIdleLoopHook(void)
483 {
484  //Not implemented
485 }
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg, const OsTaskParameters *params)
Create a task.
RTOS abstraction layer (ChibiOS/RT)
int bool_t
Definition: compiler_port.h:53
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
void osReleaseSemaphore(OsSemaphore *semaphore)
Release the specified semaphore object.
uint8_t p
Definition: ndp.h:300
void osStartKernel(void)
Start kernel.
#define TRUE
Definition: os_port.h:50
Event object.
char_t name[]
#define OS_SELF_TASK_ID
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.
__weak_func void * osAllocMem(size_t size)
Allocate a memory block.
void osDeleteTask(OsTaskId taskId)
Delete a task.
#define FALSE
Definition: os_port.h:46
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
#define chSemObjectInit
void(* OsTaskCode)(void *arg)
Task routine.
__weak_func void osFreeMem(void *p)
Release a previously allocated memory block.
void osIdleLoopHook(void)
Idle loop hook.
void osDeleteEvent(OsEvent *event)
Delete an event object.
void osInitKernel(void)
Kernel initialization.
#define OS_SYSTICKS_TO_MS(n)
const OsTaskParameters OS_TASK_DEFAULT_PARAMS
#define OS_MS_TO_SYSTICKS(n)
Task parameters.
void osResumeAllTasks(void)
Resume scheduler activity.
#define thread_t
void osSwitchTask(void)
Yield control to the next task.
Mutex object.
uint32_t systime_t
System time.
#define THD_WORKING_AREA_SIZE
#define TRACE_DEBUG(...)
Definition: debug.h:107
char char_t
Definition: compiler_port.h:48
uint32_t time
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
#define chBSemObjectInit
void osSuspendAllTasks(void)
Suspend scheduler activity.
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.
#define MSG_OK
void osDelayTask(systime_t delay)
Delay routine.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
thread_t * OsTaskId
Task identifier.
#define chVTGetSystemTime
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:50
RTOS abstraction layer.
Debugging facilities.
#define chMtxObjectInit
#define INFINITE_DELAY
Definition: os_port.h:75
systime_t osGetSystemTime(void)
Retrieve system time.