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.0
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  return TRUE;
254  else
255  return FALSE;
256 }
257 
258 
259 /**
260  * @brief Set an event object to the signaled state from an interrupt service routine
261  * @param[in] event Pointer to the event object
262  * @return TRUE if setting the event to signaled state caused a task to unblock
263  * and the unblocked task has a priority higher than the currently running task
264  **/
265 
267 {
268  //Set the specified event to the signaled state
269  chBSemSignalI(event);
270 
271  //The return value is not relevant
272  return FALSE;
273 }
274 
275 
276 /**
277  * @brief Create a semaphore object
278  * @param[in] semaphore Pointer to the semaphore object
279  * @param[in] count The maximum count for the semaphore object. This value
280  * must be greater than zero
281  * @return The function returns TRUE if the semaphore was successfully
282  * created. Otherwise, FALSE is returned
283  **/
284 
286 {
287  //Initialize the semaphore object
288  chSemObjectInit(semaphore, count);
289 
290  //Semaphore successfully created
291  return TRUE;
292 }
293 
294 
295 /**
296  * @brief Delete a semaphore object
297  * @param[in] semaphore Pointer to the semaphore object
298  **/
299 
301 {
302  //No resource to release
303 }
304 
305 
306 /**
307  * @brief Wait for the specified semaphore to be available
308  * @param[in] semaphore Pointer to the semaphore object
309  * @param[in] timeout Timeout interval
310  * @return The function returns TRUE if the semaphore is available. FALSE is
311  * returned if the timeout interval elapsed
312  **/
313 
315 {
316  msg_t msg;
317 
318  //Wait until the semaphore is available or the timeout interval elapses
319  if(timeout == 0)
320  {
321  //Non-blocking call
322  msg = chSemWaitTimeout(semaphore, TIME_IMMEDIATE);
323  }
324  else if(timeout == INFINITE_DELAY)
325  {
326  //Infinite timeout period
327  msg = chSemWaitTimeout(semaphore, TIME_INFINITE);
328  }
329  else
330  {
331  //Wait until the specified semaphore becomes available
332  msg = chSemWaitTimeout(semaphore, OS_MS_TO_SYSTICKS(timeout));
333  }
334 
335  //Check whether the specified semaphore is available
336  if(msg == MSG_OK)
337  return TRUE;
338  else
339  return FALSE;
340 }
341 
342 
343 /**
344  * @brief Release the specified semaphore object
345  * @param[in] semaphore Pointer to the semaphore object
346  **/
347 
349 {
350  //Release the semaphore
351  chSemSignal(semaphore);
352 }
353 
354 
355 /**
356  * @brief Create a mutex object
357  * @param[in] mutex Pointer to the mutex object
358  * @return The function returns TRUE if the mutex was successfully
359  * created. Otherwise, FALSE is returned
360  **/
361 
363 {
364  //Initialize the mutex object
365  chMtxObjectInit(mutex);
366 
367  //Mutex successfully created
368  return TRUE;
369 }
370 
371 
372 /**
373  * @brief Delete a mutex object
374  * @param[in] mutex Pointer to the mutex object
375  **/
376 
377 void osDeleteMutex(OsMutex *mutex)
378 {
379  //No resource to release
380 }
381 
382 
383 /**
384  * @brief Acquire ownership of the specified mutex object
385  * @param[in] mutex Pointer to the mutex object
386  **/
387 
389 {
390  //Obtain ownership of the mutex object
391  chMtxLock(mutex);
392 }
393 
394 
395 /**
396  * @brief Release ownership of the specified mutex object
397  * @param[in] mutex Pointer to the mutex object
398  **/
399 
401 {
402  //Release ownership of the mutex object
403 #if (CH_KERNEL_MAJOR < 3)
404  chMtxUnlock();
405 #else
406  chMtxUnlock(mutex);
407 #endif
408 }
409 
410 
411 /**
412  * @brief Retrieve system time
413  * @return Number of milliseconds elapsed since the system was last started
414  **/
415 
417 {
418  systime_t time;
419 
420  //Get current tick count
422 
423  //Convert system ticks to milliseconds
424  return OS_SYSTICKS_TO_MS(time);
425 }
426 
427 
428 /**
429  * @brief Allocate a memory block
430  * @param[in] size Bytes to allocate
431  * @return A pointer to the allocated memory block or NULL if
432  * there is insufficient memory available
433  **/
434 
435 __weak_func void *osAllocMem(size_t size)
436 {
437  void *p;
438 
439  //Allocate a memory block
440  p = chHeapAlloc(NULL, size);
441 
442  //Debug message
443  TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n",
444  size, (uintptr_t) p);
445 
446  //Return a pointer to the newly allocated memory block
447  return p;
448 }
449 
450 
451 /**
452  * @brief Release a previously allocated memory block
453  * @param[in] p Previously allocated memory block to be freed
454  **/
455 
456 __weak_func void osFreeMem(void *p)
457 {
458  //Make sure the pointer is valid
459  if(p != NULL)
460  {
461  //Debug message
462  TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
463 
464  //Free memory block
465  chHeapFree(p);
466  }
467 }
468 
469 
470 /**
471  * @brief Idle loop hook
472  **/
473 
474 void osIdleLoopHook(void)
475 {
476  //Not implemented
477 }
unsigned int uint_t
Definition: compiler_port.h:50
#define PRIuSIZE
char char_t
Definition: compiler_port.h:48
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
uint32_t time
uint8_t p
Definition: ndp.h:300
RTOS abstraction layer.
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
#define INFINITE_DELAY
Definition: os_port.h:75
void osSwitchTask(void)
Yield control to the next task.
void osResumeAllTasks(void)
Resume scheduler activity.
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
void osDeleteEvent(OsEvent *event)
Delete an event object.
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
void osReleaseSemaphore(OsSemaphore *semaphore)
Release the specified semaphore object.
const OsTaskParameters OS_TASK_DEFAULT_PARAMS
__weak_func void * osAllocMem(size_t size)
Allocate a memory block.
void osIdleLoopHook(void)
Idle loop hook.
void osDeleteSemaphore(OsSemaphore *semaphore)
Delete a semaphore object.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osDelayTask(systime_t delay)
Delay routine.
__weak_func void osFreeMem(void *p)
Release a previously allocated memory block.
bool_t osWaitForSemaphore(OsSemaphore *semaphore, systime_t timeout)
Wait for the specified semaphore to be available.
OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg, const OsTaskParameters *params)
Create a task.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void osDeleteTask(OsTaskId taskId)
Delete a task.
bool_t osCreateSemaphore(OsSemaphore *semaphore, uint_t count)
Create a semaphore object.
systime_t osGetSystemTime(void)
Retrieve system time.
void osSuspendAllTasks(void)
Suspend scheduler activity.
bool_t osCreateEvent(OsEvent *event)
Create an event object.
void osStartKernel(void)
Start kernel.
void osInitKernel(void)
Kernel initialization.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
RTOS abstraction layer (ChibiOS/RT)
void(* OsTaskCode)(void *arg)
Task routine.
#define chMtxObjectInit
#define THD_WORKING_AREA_SIZE
#define OS_SYSTICKS_TO_MS(n)
#define MSG_OK
#define thread_t
#define chSemObjectInit
#define chBSemObjectInit
#define chVTGetSystemTime
#define OS_MS_TO_SYSTICKS(n)
#define OS_SELF_TASK_ID
uint32_t systime_t
System time.
thread_t * OsTaskId
Task identifier.
char_t name[]
Event object.
Mutex object.
Semaphore object.
Task parameters.