os_port_safertos.c
Go to the documentation of this file.
1 /**
2  * @file os_port_safertos.c
3  * @brief RTOS abstraction layer (SafeRTOS)
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 <string.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include "os_port.h"
37 #include "os_port_safertos.h"
38 #include "debug.h"
39 
40 //Default task parameters
42 {
43  NULL, //Task control block
44  NULL, //Stack
45  0, //Size of the stack
46  taskIDLE_PRIORITY + 1, //Task priority
47 };
48 
49 //Declaration of functions
50 extern portBaseType xInitializeScheduler(void);
51 
52 
53 /**
54  * @brief Kernel initialization
55  **/
56 
57 void osInitKernel(void)
58 {
59  //Initialize kernel
61 }
62 
63 
64 /**
65  * @brief Start kernel
66  **/
67 
68 void osStartKernel(void)
69 {
70  //Start the scheduler
71  xTaskStartScheduler(pdTRUE);
72 }
73 
74 
75 /**
76  * @brief Create a task
77  * @param[in] name NULL-terminated string identifying the task
78  * @param[in] taskCode Pointer to the task entry function
79  * @param[in] arg Argument passed to the task function
80  * @param[in] params Task parameters
81  * @return Task identifier referencing the newly created task
82  **/
83 
84 __weak_func OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode,
85  void *arg, const OsTaskParameters *params)
86 {
87  portBaseType status;
88  portTaskHandleType handle;
89  xTaskParameters taskParams;
90 
91  //Check parameters
92  if(params->tcb != NULL && params->stack != NULL)
93  {
94  //Initialize task parameters
95  memset(&taskParams, 0, sizeof(taskParams));
96 
97  //Set task parameters
98  taskParams.pvTaskCode = (pdTASK_CODE) taskCode;
99  taskParams.pcTaskName = name;
100  taskParams.pxTCB = params->tcb;
101  taskParams.pcStackBuffer = params->stack;
102  taskParams.ulStackDepthBytes = params->stackSize;
103  taskParams.pvParameters = arg;
104  taskParams.uxPriority = params->priority;
105  taskParams.xUsingFPU = pdTRUE;
106  taskParams.xMPUParameters.uxPrivilegeLevel = mpuPRIVILEGED_TASK;
107 
108  //Create a new task
109  status = xTaskCreate(&taskParams, &handle);
110 
111  //Failed to create task?
112  if(status != pdPASS)
113  {
114  handle = OS_INVALID_TASK_ID;
115  }
116  }
117  else
118  {
119  //Invalid parameters
120  handle = OS_INVALID_TASK_ID;
121  }
122 
123  //Return the handle referencing the newly created task
124  return (OsTaskId) handle;
125 }
126 
127 
128 /**
129  * @brief Delete a task
130  * @param[in] taskId Task identifier referencing the task to be deleted
131  **/
132 
133 void osDeleteTask(OsTaskId taskId)
134 {
135  //Delete the specified task
136  xTaskDelete((portTaskHandleType) taskId);
137 }
138 
139 
140 /**
141  * @brief Delay routine
142  * @param[in] delay Amount of time for which the calling task should block
143  **/
144 
146 {
147  //Delay the task for the specified duration
148  xTaskDelay(OS_MS_TO_SYSTICKS(delay));
149 }
150 
151 
152 /**
153  * @brief Yield control to the next task
154  **/
155 
156 void osSwitchTask(void)
157 {
158  //Force a context switch
159  taskYIELD();
160 }
161 
162 
163 /**
164  * @brief Suspend scheduler activity
165  **/
166 
168 {
169  //Make sure the operating system is running
170  if(xTaskIsSchedulerStarted() == pdTRUE)
171  {
172  //Suspend all tasks
173  vTaskSuspendScheduler();
174  }
175 }
176 
177 
178 /**
179  * @brief Resume scheduler activity
180  **/
181 
183 {
184  //Make sure the operating system is running
185  if(xTaskIsSchedulerStarted() == pdTRUE)
186  {
187  //Resume all tasks
188  xTaskResumeScheduler();
189  }
190 }
191 
192 
193 /**
194  * @brief Create an event object
195  * @param[in] event Pointer to the event object
196  * @return The function returns TRUE if the event object was successfully
197  * created. Otherwise, FALSE is returned
198  **/
199 
201 {
202  portBaseType status;
203 
204  uint32_t n;
205  uint32_t p = (uint32_t) event->buffer;
206  n = p % portQUEUE_OVERHEAD_BYTES;
207  p += portQUEUE_OVERHEAD_BYTES - n;
208 
209  //Create a binary semaphore
210  status = xSemaphoreCreateBinary((portInt8Type *) p, &event->handle);
211 
212  //Check whether the semaphore was successfully created
213  if(status == pdPASS)
214  {
215  //Force the event to the nonsignaled state
216  xSemaphoreTake(event->handle, 0);
217  //Event successfully created
218  return TRUE;
219  }
220  else
221  {
222  //Failed to create event object
223  return FALSE;
224  }
225 }
226 
227 
228 /**
229  * @brief Delete an event object
230  * @param[in] event Pointer to the event object
231  **/
232 
233 void osDeleteEvent(OsEvent *event)
234 {
235  //Not implemented
236 }
237 
238 
239 /**
240  * @brief Set the specified event object to the signaled state
241  * @param[in] event Pointer to the event object
242  **/
243 
244 void osSetEvent(OsEvent *event)
245 {
246  //Set the specified event to the signaled state
247  xSemaphoreGive(event->handle);
248 }
249 
250 
251 /**
252  * @brief Set the specified event object to the nonsignaled state
253  * @param[in] event Pointer to the event object
254  **/
255 
256 void osResetEvent(OsEvent *event)
257 {
258  //Force the specified event to the nonsignaled state
259  xSemaphoreTake(event->handle, 0);
260 }
261 
262 
263 /**
264  * @brief Wait until the specified event is in the signaled state
265  * @param[in] event Pointer to the event object
266  * @param[in] timeout Timeout interval
267  * @return The function returns TRUE if the state of the specified object is
268  * signaled. FALSE is returned if the timeout interval elapsed
269  **/
270 
272 {
273  portBaseType status;
274 
275  //Wait until the specified event is in the signaled state or the timeout
276  //interval elapses
277  if(timeout == INFINITE_DELAY)
278  {
279  //Infinite timeout period
280  status = xSemaphoreTake(event->handle, portMAX_DELAY);
281  }
282  else
283  {
284  //Wait for the specified time interval
285  status = xSemaphoreTake(event->handle, OS_MS_TO_SYSTICKS(timeout));
286  }
287 
288  //The return value tells whether the event is set
289  if(status == pdPASS)
290  {
291  return TRUE;
292  }
293  else
294  {
295  return FALSE;
296  }
297 }
298 
299 
300 /**
301  * @brief Set an event object to the signaled state from an interrupt service routine
302  * @param[in] event Pointer to the event object
303  * @return TRUE if setting the event to signaled state caused a task to unblock
304  * and the unblocked task has a priority higher than the currently running task
305  **/
306 
308 {
309  portBaseType flag = FALSE;
310 
311  //Set the specified event to the signaled state
312  xSemaphoreGiveFromISR(event->handle, &flag);
313 
314  //A higher priority task has been woken?
315  return flag;
316 }
317 
318 
319 /**
320  * @brief Create a semaphore object
321  * @param[in] semaphore Pointer to the semaphore object
322  * @param[in] count The maximum count for the semaphore object. This value
323  * must be greater than zero
324  * @return The function returns TRUE if the semaphore was successfully
325  * created. Otherwise, FALSE is returned
326  **/
327 
329 {
330  portBaseType status;
331 
332  uint32_t n;
333  uint32_t p = (uint32_t) semaphore->buffer;
334  n = p % portQUEUE_OVERHEAD_BYTES;
335  p += portQUEUE_OVERHEAD_BYTES - n;
336 
337  //Create a semaphore
338  status = xSemaphoreCreateCounting(count, count, (portInt8Type *) p,
339  &semaphore->handle);
340 
341  //Check whether the semaphore was successfully created
342  if(status == pdPASS)
343  {
344  return TRUE;
345  }
346  else
347  {
348  return FALSE;
349  }
350 }
351 
352 
353 /**
354  * @brief Delete a semaphore object
355  * @param[in] semaphore Pointer to the semaphore object
356  **/
357 
359 {
360  //Not implemented
361 }
362 
363 
364 /**
365  * @brief Wait for the specified semaphore to be available
366  * @param[in] semaphore Pointer to the semaphore object
367  * @param[in] timeout Timeout interval
368  * @return The function returns TRUE if the semaphore is available. FALSE is
369  * returned if the timeout interval elapsed
370  **/
371 
373 {
374  portBaseType status;
375 
376  //Wait until the specified semaphore becomes available
377  if(timeout == INFINITE_DELAY)
378  {
379  //Infinite timeout period
380  status = xSemaphoreTake(semaphore->handle, portMAX_DELAY);
381  }
382  else
383  {
384  //Wait for the specified time interval
385  status = xSemaphoreTake(semaphore->handle, OS_MS_TO_SYSTICKS(timeout));
386  }
387 
388  //The return value tells whether the semaphore is available
389  if(status == pdPASS)
390  {
391  return TRUE;
392  }
393  else
394  {
395  return FALSE;
396  }
397 }
398 
399 
400 /**
401  * @brief Release the specified semaphore object
402  * @param[in] semaphore Pointer to the semaphore object
403  **/
404 
406 {
407  //Release the semaphore
408  xSemaphoreGive(semaphore->handle);
409 }
410 
411 
412 /**
413  * @brief Create a mutex object
414  * @param[in] mutex Pointer to the mutex object
415  * @return The function returns TRUE if the mutex was successfully
416  * created. Otherwise, FALSE is returned
417  **/
418 
420 {
421  portBaseType status;
422 
423  uint32_t n;
424  uint32_t p = (uint32_t) mutex->buffer;
425  n = p % portQUEUE_OVERHEAD_BYTES;
426  p += portQUEUE_OVERHEAD_BYTES - n;
427 
428  //Create a binary semaphore
429  status = xSemaphoreCreateBinary((portInt8Type *) p, &mutex->handle);
430 
431  //Check whether the semaphore was successfully created
432  if(status == pdPASS)
433  {
434  //Force the binary semaphore to the signaled state
435  xSemaphoreGive(mutex->handle);
436 
437  //Semaphore successfully created
438  return TRUE;
439  }
440  else
441  {
442  //Failed to create semaphore
443  return FALSE;
444  }
445 }
446 
447 
448 /**
449  * @brief Delete a mutex object
450  * @param[in] mutex Pointer to the mutex object
451  **/
452 
453 void osDeleteMutex(OsMutex *mutex)
454 {
455  //Not implemented
456 }
457 
458 
459 /**
460  * @brief Acquire ownership of the specified mutex object
461  * @param[in] mutex Pointer to the mutex object
462  **/
463 
465 {
466  //Obtain ownership of the mutex object
467  xSemaphoreTake(mutex->handle, portMAX_DELAY);
468 }
469 
470 
471 /**
472  * @brief Release ownership of the specified mutex object
473  * @param[in] mutex Pointer to the mutex object
474  **/
475 
477 {
478  //Release ownership of the mutex object
479  xSemaphoreGive(mutex->handle);
480 }
481 
482 
483 /**
484  * @brief Retrieve system time
485  * @return Number of milliseconds elapsed since the system was last started
486  **/
487 
489 {
490  systime_t time;
491 
492  //Get current tick count
493  time = xTaskGetTickCount();
494 
495  //Convert system ticks to milliseconds
496  return OS_SYSTICKS_TO_MS(time);
497 }
498 
499 
500 /**
501  * @brief Allocate a memory block
502  * @param[in] size Bytes to allocate
503  * @return A pointer to the allocated memory block or NULL if
504  * there is insufficient memory available
505  **/
506 
507 __weak_func void *osAllocMem(size_t size)
508 {
509  //Not implemented
510  return NULL;
511 }
512 
513 
514 /**
515  * @brief Release a previously allocated memory block
516  * @param[in] p Previously allocated memory block to be freed
517  **/
518 
519 __weak_func void osFreeMem(void *p)
520 {
521  //Not implemented
522 }
int bool_t
Definition: compiler_port.h:53
SemaphoreHandle_t handle
uint8_t p
Definition: ndp.h:300
#define TRUE
Definition: os_port.h:50
#define OS_INVALID_TASK_ID
Event object.
portInt8Type buffer[portQUEUE_OVERHEAD_BYTES *2]
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
char_t name[]
bool_t osCreateEvent(OsEvent *event)
Create an event object.
systime_t osGetSystemTime(void)
Retrieve system time.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
Semaphore object.
portInt8Type buffer[portQUEUE_OVERHEAD_BYTES *2]
const OsTaskParameters OS_TASK_DEFAULT_PARAMS
#define FALSE
Definition: os_port.h:46
void osInitKernel(void)
Kernel initialization.
void(* OsTaskCode)(void *arg)
Task routine.
void osDelayTask(systime_t delay)
Delay routine.
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
RTOS abstraction layer (SafeRTOS)
__weak_func void osFreeMem(void *p)
Release a previously allocated memory block.
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
#define OS_SYSTICKS_TO_MS(n)
bool_t osCreateSemaphore(OsSemaphore *semaphore, uint_t count)
Create a semaphore object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
#define OS_MS_TO_SYSTICKS(n)
Task parameters.
portInt8Type buffer[portQUEUE_OVERHEAD_BYTES *2]
bool_t osWaitForSemaphore(OsSemaphore *semaphore, systime_t timeout)
Wait for the specified semaphore to be available.
void osStartKernel(void)
Start kernel.
Mutex object.
uint32_t systime_t
System time.
void osSuspendAllTasks(void)
Suspend scheduler activity.
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
char char_t
Definition: compiler_port.h:48
uint32_t time
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
SemaphoreHandle_t handle
uint8_t n
void osDeleteEvent(OsEvent *event)
Delete an event object.
__weak_func void * osAllocMem(size_t size)
Allocate a memory block.
void osDeleteTask(OsTaskId taskId)
Delete a task.
void osDeleteSemaphore(OsSemaphore *semaphore)
Delete a semaphore object.
void osReleaseSemaphore(OsSemaphore *semaphore)
Release the specified semaphore object.
void osSwitchTask(void)
Yield control to the next task.
thread_t * OsTaskId
Task identifier.
unsigned int uint_t
Definition: compiler_port.h:50
portBaseType xInitializeScheduler(void)
RTOS abstraction layer.
void osResumeAllTasks(void)
Resume scheduler activity.
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
Debugging facilities.
#define INFINITE_DELAY
Definition: os_port.h:75
SemaphoreHandle_t handle
__weak_func OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg, const OsTaskParameters *params)
Create a task.