os_port_sys_bios.c
Go to the documentation of this file.
1 /**
2  * @file os_port_sys_bios.c
3  * @brief RTOS abstraction layer (SYS/BIOS)
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 "os_port.h"
36 #include "os_port_sys_bios.h"
37 #include "debug.h"
38 
39 //Variables
40 static bool_t running = FALSE;
41 
42 
43 /**
44  * @brief Kernel initialization
45  **/
46 
47 void osInitKernel(void)
48 {
49  //The scheduler is not running
50  running = FALSE;
51 }
52 
53 
54 /**
55  * @brief Start kernel
56  **/
57 
58 void osStartKernel(void)
59 {
60  //The scheduler is now running
61  running = TRUE;
62  //Start the scheduler
63  BIOS_start();
64 }
65 
66 
67 /**
68  * @brief Create a task
69  * @param[in] name NULL-terminated string identifying the task
70  * @param[in] taskCode Pointer to the task entry function
71  * @param[in] arg Argument passed to the task function
72  * @param[in] params Task parameters
73  * @return Task identifier referencing the newly created task
74  **/
75 
76 OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg,
77  const OsTaskParameters *params)
78 {
79  Error_Block eb;
80  Task_Params taskParams;
81  Task_Handle handle;
82 
83  //Initialize error block
84  Error_init(&eb);
85 
86  //Set parameters
87  Task_Params_init(&taskParams);
88  taskParams.arg0 = (UArg) arg;
89  taskParams.stackSize = params->stackSize * sizeof(uint32_t);
90  taskParams.priority = params->priority;
91 
92  //Create a new task
93  handle = Task_create((Task_FuncPtr) taskCode, &taskParams, &eb);
94 
95  //Return the handle referencing the newly created task
96  return (OsTaskId) handle;
97 }
98 
99 
100 /**
101  * @brief Delete a task
102  * @param[in] taskId Task identifier referencing the task to be deleted
103  **/
104 
105 void osDeleteTask(OsTaskId taskId)
106 {
107  //Delete the specified task
108  Task_delete(&taskId);
109 }
110 
111 
112 /**
113  * @brief Delay routine
114  * @param[in] delay Amount of time for which the calling task should block
115  **/
116 
118 {
119  //Delay the task for the specified duration
120  Task_sleep(OS_MS_TO_SYSTICKS(delay));
121 }
122 
123 
124 /**
125  * @brief Yield control to the next task
126  **/
127 
128 void osSwitchTask(void)
129 {
130  //Force a context switch
131  Task_yield();
132 }
133 
134 
135 /**
136  * @brief Suspend scheduler activity
137  **/
138 
140 {
141  //Make sure the operating system is running
142  if(running)
143  {
144  //Disable the task scheduler
145  Task_disable();
146  }
147 }
148 
149 
150 /**
151  * @brief Resume scheduler activity
152  **/
153 
155 {
156  //Make sure the operating system is running
157  if(running)
158  {
159  //Enable the task scheduler
160  Task_enable();
161  }
162 }
163 
164 
165 /**
166  * @brief Create an event object
167  * @param[in] event Pointer to the event object
168  * @return The function returns TRUE if the event object was successfully
169  * created. Otherwise, FALSE is returned
170  **/
171 
173 {
174  //Create an event object
175  event->handle = Event_create(NULL, NULL);
176 
177  //Check whether the returned handle is valid
178  if(event->handle != NULL)
179  {
180  return TRUE;
181  }
182  else
183  {
184  return FALSE;
185  }
186 }
187 
188 
189 /**
190  * @brief Delete an event object
191  * @param[in] event Pointer to the event object
192  **/
193 
194 void osDeleteEvent(OsEvent *event)
195 {
196  //Make sure the handle is valid
197  if(event->handle != NULL)
198  {
199  //Properly dispose the event object
200  Event_delete(&event->handle);
201  }
202 }
203 
204 
205 /**
206  * @brief Set the specified event object to the signaled state
207  * @param[in] event Pointer to the event object
208  **/
209 
210 void osSetEvent(OsEvent *event)
211 {
212  //Set the specified event to the signaled state
213  Event_post(event->handle, Event_Id_00);
214 }
215 
216 
217 /**
218  * @brief Set the specified event object to the nonsignaled state
219  * @param[in] event Pointer to the event object
220  **/
221 
222 void osResetEvent(OsEvent *event)
223 {
224  //Force the specified event to the nonsignaled state
225  Event_pend(event->handle, Event_Id_00, Event_Id_NONE, BIOS_NO_WAIT);
226 }
227 
228 
229 /**
230  * @brief Wait until the specified event is in the signaled state
231  * @param[in] event Pointer to the event object
232  * @param[in] timeout Timeout interval
233  * @return The function returns TRUE if the state of the specified object is
234  * signaled. FALSE is returned if the timeout interval elapsed
235  **/
236 
238 {
239  Bool ret;
240 
241  //Wait until the specified event is in the signaled state or the timeout
242  //interval elapses
243  if(timeout == 0)
244  {
245  //Non-blocking call
246  ret = Event_pend(event->handle, Event_Id_00,
247  Event_Id_NONE, BIOS_NO_WAIT);
248  }
249  else if(timeout == INFINITE_DELAY)
250  {
251  //Infinite timeout period
252  ret = Event_pend(event->handle, Event_Id_00,
253  Event_Id_NONE, BIOS_WAIT_FOREVER);
254  }
255  else
256  {
257  //Wait for the specified time interval
258  ret = Event_pend(event->handle, Event_Id_00,
259  Event_Id_NONE, OS_MS_TO_SYSTICKS(timeout));
260  }
261 
262  //The return value tells whether the event is set
263  return ret;
264 }
265 
266 
267 /**
268  * @brief Set an event object to the signaled state from an interrupt service routine
269  * @param[in] event Pointer to the event object
270  * @return TRUE if setting the event to signaled state caused a task to unblock
271  * and the unblocked task has a priority higher than the currently running task
272  **/
273 
275 {
276  //Set the specified event to the signaled state
277  Event_post(event->handle, Event_Id_00);
278 
279  //The return value is not relevant
280  return FALSE;
281 }
282 
283 
284 /**
285  * @brief Create a semaphore object
286  * @param[in] semaphore Pointer to the semaphore object
287  * @param[in] count The maximum count for the semaphore object. This value
288  * must be greater than zero
289  * @return The function returns TRUE if the semaphore was successfully
290  * created. Otherwise, FALSE is returned
291  **/
292 
294 {
295  Semaphore_Params semaphoreParams;
296 
297  //Set parameters
298  Semaphore_Params_init(&semaphoreParams);
299  semaphoreParams.mode = Semaphore_Mode_COUNTING;
300 
301  //Create a semaphore
302  semaphore->handle = Semaphore_create(count, &semaphoreParams, NULL);
303 
304  //Check whether the returned handle is valid
305  if(semaphore->handle != NULL)
306  {
307  return TRUE;
308  }
309  else
310  {
311  return FALSE;
312  }
313 }
314 
315 
316 /**
317  * @brief Delete a semaphore object
318  * @param[in] semaphore Pointer to the semaphore object
319  **/
320 
322 {
323  //Make sure the handle is valid
324  if(semaphore->handle != NULL)
325  {
326  //Properly dispose the specified semaphore
327  Semaphore_delete(&semaphore->handle);
328  }
329 }
330 
331 
332 /**
333  * @brief Wait for the specified semaphore to be available
334  * @param[in] semaphore Pointer to the semaphore object
335  * @param[in] timeout Timeout interval
336  * @return The function returns TRUE if the semaphore is available. FALSE is
337  * returned if the timeout interval elapsed
338  **/
339 
341 {
342  Bool ret;
343 
344  //Wait until the specified semaphore becomes available
345  if(timeout == 0)
346  {
347  //Non-blocking call
348  ret = Semaphore_pend(semaphore->handle, BIOS_NO_WAIT);
349  }
350  else if(timeout == INFINITE_DELAY)
351  {
352  //Infinite timeout period
353  ret = Semaphore_pend(semaphore->handle, BIOS_WAIT_FOREVER);
354  }
355  else
356  {
357  //Wait for the specified time interval
358  ret = Semaphore_pend(semaphore->handle, OS_MS_TO_SYSTICKS(timeout));
359  }
360 
361  //The return value tells whether the semaphore is available
362  return ret;
363 }
364 
365 
366 /**
367  * @brief Release the specified semaphore object
368  * @param[in] semaphore Pointer to the semaphore object
369  **/
370 
372 {
373  //Release the semaphore
374  Semaphore_post(semaphore->handle);
375 }
376 
377 
378 /**
379  * @brief Create a mutex object
380  * @param[in] mutex Pointer to the mutex object
381  * @return The function returns TRUE if the mutex was successfully
382  * created. Otherwise, FALSE is returned
383  **/
384 
386 {
387  Semaphore_Params semaphoreParams;
388 
389  //Set parameters
390  Semaphore_Params_init(&semaphoreParams);
391  semaphoreParams.mode = Semaphore_Mode_BINARY_PRIORITY;
392 
393  //Create a mutex
394  mutex->handle = Semaphore_create(1, &semaphoreParams, NULL);
395 
396  //Check whether the returned handle is valid
397  if(mutex->handle != NULL)
398  {
399  return TRUE;
400  }
401  else
402  {
403  return FALSE;
404  }
405 }
406 
407 
408 /**
409  * @brief Delete a mutex object
410  * @param[in] mutex Pointer to the mutex object
411  **/
412 
413 void osDeleteMutex(OsMutex *mutex)
414 {
415  //Make sure the handle is valid
416  if(mutex->handle != NULL)
417  {
418  //Properly dispose the specified mutex
419  Semaphore_delete(&mutex->handle);
420  }
421 }
422 
423 
424 /**
425  * @brief Acquire ownership of the specified mutex object
426  * @param[in] mutex Pointer to the mutex object
427  **/
428 
430 {
431  //Obtain ownership of the mutex object
432  Semaphore_pend(mutex->handle, BIOS_WAIT_FOREVER);
433 }
434 
435 
436 /**
437  * @brief Release ownership of the specified mutex object
438  * @param[in] mutex Pointer to the mutex object
439  **/
440 
442 {
443  //Release ownership of the mutex object
444  Semaphore_post(mutex->handle);
445 }
446 
447 
448 /**
449  * @brief Retrieve system time
450  * @return Number of milliseconds elapsed since the system was last started
451  **/
452 
454 {
455  systime_t time;
456 
457  //Get current tick count
458  time = Clock_getTicks();
459 
460  //Convert system ticks to milliseconds
461  return OS_SYSTICKS_TO_MS(time);
462 }
463 
464 
465 /**
466  * @brief Allocate a memory block
467  * @param[in] size Bytes to allocate
468  * @return A pointer to the allocated memory block or NULL if
469  * there is insufficient memory available
470  **/
471 
472 __weak_func void *osAllocMem(size_t size)
473 {
474  void *p;
475 
476  //Enter critical section
478  //Allocate a memory block
479  p = malloc(size);
480  //Leave critical section
482 
483  //Debug message
484  TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n",
485  size, (uintptr_t) p);
486 
487  //Return a pointer to the newly allocated memory block
488  return p;
489 }
490 
491 
492 /**
493  * @brief Release a previously allocated memory block
494  * @param[in] p Previously allocated memory block to be freed
495  **/
496 
497 __weak_func void osFreeMem(void *p)
498 {
499  //Make sure the pointer is valid
500  if(p != NULL)
501  {
502  //Debug message
503  TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
504 
505  //Enter critical section
507  //Free memory block
508  free(p);
509  //Leave critical section
511  }
512 }
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(* OsTaskCode)(void *arg)
Task routine.
#define OS_SYSTICKS_TO_MS(n)
#define OS_MS_TO_SYSTICKS(n)
uint32_t systime_t
System time.
thread_t * OsTaskId
Task identifier.
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.
__weak_func void * osAllocMem(size_t size)
Allocate a memory block.
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 (SYS/BIOS)
char_t name[]
Event object.
SemaphoreHandle_t handle
Mutex object.
SemaphoreHandle_t handle
Semaphore object.
SemaphoreHandle_t handle
Task parameters.