os_port_cmsis_rtos2.c
Go to the documentation of this file.
1 /**
2  * @file os_port_cmsis_rtos2.c
3  * @brief RTOS abstraction layer (CMSIS-RTOS 2 / RTX v5)
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_cmsis_rtos2.h"
37 #include "debug.h"
38 
39 //Default task parameters
41 {
42  NULL, //Task control block
43  NULL, //Stack
44  256, //Size of the stack
45  osPriorityNormal //Task priority
46 };
47 
48 
49 /**
50  * @brief Kernel initialization
51  **/
52 
53 void osInitKernel(void)
54 {
55  //Initialize the kernel
56  osKernelInitialize();
57 }
58 
59 
60 /**
61  * @brief Start kernel
62  **/
63 
64 void osStartKernel(void)
65 {
66  //Start the kernel
67  osKernelStart();
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  osThreadId_t threadId;
84  osThreadAttr_t threadAttr;
85 
86  //Initialize thread attributes
87  memset(&threadAttr, 0, sizeof(threadAttr));
88 
89  //Set thread attributes
90  threadAttr.name = name;
91  threadAttr.attr_bits = 0;
92  threadAttr.stack_mem = params->stack;
93  threadAttr.stack_size = params->stackSize * sizeof(uint32_t);
94  threadAttr.priority = (osPriority_t) params->priority;
95  threadAttr.tz_module = 0;
96  threadAttr.reserved = 0;
97 
98  //Static allocation?
99  if(params->cb != NULL)
100  {
101 #if defined(os_CMSIS_RTX)
102  threadAttr.cb_mem = params->cb;
103  threadAttr.cb_size = sizeof(os_thread_t);
104 #elif defined(osRtxVersionKernel)
105  threadAttr.cb_mem = params->cb;
106  threadAttr.cb_size = sizeof(osRtxThread_t);
107 #elif defined(configSUPPORT_STATIC_ALLOCATION)
108  threadAttr.cb_mem = params->cb;
109  threadAttr.cb_size = sizeof(StaticTask_t);
110 #else
111  threadAttr.cb_mem = NULL;
112  threadAttr.cb_size = 0;
113 #endif
114  }
115 
116  //Create a new thread
117  threadId = osThreadNew(taskCode, arg, &threadAttr);
118 
119  //Return the handle referencing the newly created thread
120  return (OsTaskId) threadId;
121 }
122 
123 
124 /**
125  * @brief Delete a task
126  * @param[in] taskId Task identifier referencing the task to be deleted
127  **/
128 
129 void osDeleteTask(OsTaskId taskId)
130 {
131  //Delete the specified thread
132  if(taskId == OS_SELF_TASK_ID)
133  {
134  osThreadExit();
135  }
136  else
137  {
138  osThreadTerminate((osThreadId_t) taskId);
139  }
140 }
141 
142 
143 /**
144  * @brief Delay routine
145  * @param[in] delay Amount of time for which the calling task should block
146  **/
147 
149 {
150  //Delay the thread for the specified duration
151  osDelay(OS_MS_TO_SYSTICKS(delay));
152 }
153 
154 
155 /**
156  * @brief Yield control to the next task
157  **/
158 
159 void osSwitchTask(void)
160 {
161  //Force a context switch
162  osThreadYield();
163 }
164 
165 
166 /**
167  * @brief Suspend scheduler activity
168  **/
169 
171 {
172  //Make sure the operating system is running
173  if(osKernelGetState() != osKernelInactive)
174  {
175  //Suspend all task switches
176  osKernelLock();
177  }
178 }
179 
180 
181 /**
182  * @brief Resume scheduler activity
183  **/
184 
186 {
187  //Make sure the operating system is running
188  if(osKernelGetState() != osKernelInactive)
189  {
190  //Resume lock all task switches
191  osKernelUnlock();
192  }
193 }
194 
195 
196 /**
197  * @brief Create an event object
198  * @param[in] event Pointer to the event object
199  * @return The function returns TRUE if the event object was successfully
200  * created. Otherwise, FALSE is returned
201  **/
202 
204 {
205  osEventFlagsAttr_t eventFlagsAttr;
206 
207  //Set event flags attributes
208  eventFlagsAttr.name = NULL;
209  eventFlagsAttr.attr_bits = 0;
210 
211 #if defined(os_CMSIS_RTX)
212  eventFlagsAttr.cb_mem = &event->cb;
213  eventFlagsAttr.cb_size = sizeof(os_event_flags_t);
214 #elif defined(osRtxVersionKernel)
215  eventFlagsAttr.cb_mem = &event->cb;
216  eventFlagsAttr.cb_size = sizeof(osRtxEventFlags_t);
217 #else
218  eventFlagsAttr.cb_mem = NULL;
219  eventFlagsAttr.cb_size = 0;
220 #endif
221 
222  //Create an event flags object
223  event->id = osEventFlagsNew(&eventFlagsAttr);
224 
225  //Check whether the returned semaphore ID is valid
226  if(event->id != NULL)
227  {
228  return TRUE;
229  }
230  else
231  {
232  return FALSE;
233  }
234 }
235 
236 
237 /**
238  * @brief Delete an event object
239  * @param[in] event Pointer to the event object
240  **/
241 
242 void osDeleteEvent(OsEvent *event)
243 {
244  //Make sure the event flags ID is valid
245  if(event->id != NULL)
246  {
247  //Properly dispose the event flags object
248  osEventFlagsDelete(event->id);
249  }
250 }
251 
252 
253 /**
254  * @brief Set the specified event object to the signaled state
255  * @param[in] event Pointer to the event object
256  **/
257 
258 void osSetEvent(OsEvent *event)
259 {
260  //Set the specified event to the signaled state
261  osEventFlagsSet(event->id, 1);
262 }
263 
264 
265 /**
266  * @brief Set the specified event object to the nonsignaled state
267  * @param[in] event Pointer to the event object
268  **/
269 
270 void osResetEvent(OsEvent *event)
271 {
272  //Force the specified event to the nonsignaled state
273  osEventFlagsClear(event->id, 1);
274 }
275 
276 
277 /**
278  * @brief Wait until the specified event is in the signaled state
279  * @param[in] event Pointer to the event object
280  * @param[in] timeout Timeout interval
281  * @return The function returns TRUE if the state of the specified object is
282  * signaled. FALSE is returned if the timeout interval elapsed
283  **/
284 
286 {
287  uint32_t flags;
288 
289  //Wait until the specified event is in the signaled state or the timeout
290  //interval elapses
291  if(timeout == INFINITE_DELAY)
292  {
293  //Infinite timeout period
294  flags = osEventFlagsWait(event->id, 1, osFlagsWaitAny, osWaitForever);
295  }
296  else
297  {
298  //Wait for the specified time interval
299  flags = osEventFlagsWait(event->id, 1, osFlagsWaitAny,
300  OS_MS_TO_SYSTICKS(timeout));
301  }
302 
303  //The function returns the event flags before clearing or an error code
304  if(flags == 1)
305  {
306  return TRUE;
307  }
308  else
309  {
310  return FALSE;
311  }
312 }
313 
314 
315 /**
316  * @brief Set an event object to the signaled state from an interrupt service routine
317  * @param[in] event Pointer to the event object
318  * @return TRUE if setting the event to signaled state caused a task to unblock
319  * and the unblocked task has a priority higher than the currently running task
320  **/
321 
323 {
324  //Set the specified event to the signaled state
325  osEventFlagsSet(event->id, 1);
326 
327  //The return value is not relevant
328  return FALSE;
329 }
330 
331 
332 /**
333  * @brief Create a semaphore object
334  * @param[in] semaphore Pointer to the semaphore object
335  * @param[in] count The maximum count for the semaphore object. This value
336  * must be greater than zero
337  * @return The function returns TRUE if the semaphore was successfully
338  * created. Otherwise, FALSE is returned
339  **/
340 
342 {
343  osSemaphoreAttr_t semaphoreAttr;
344 
345  //Set semaphore attributes
346  semaphoreAttr.name = NULL;
347  semaphoreAttr.attr_bits = 0;
348 
349 #if defined(os_CMSIS_RTX)
350  semaphoreAttr.cb_mem = &semaphore->cb;
351  semaphoreAttr.cb_size = sizeof(os_semaphore_t);
352 #elif defined(osRtxVersionKernel)
353  semaphoreAttr.cb_mem = &semaphore->cb;
354  semaphoreAttr.cb_size = sizeof(osRtxSemaphore_t);
355 #else
356  semaphoreAttr.cb_mem = NULL;
357  semaphoreAttr.cb_size = 0;
358 #endif
359 
360  //Create a semaphore object
361  semaphore->id = osSemaphoreNew(count, count, &semaphoreAttr);
362 
363  //Check whether the returned semaphore ID is valid
364  if(semaphore->id != NULL)
365  {
366  return TRUE;
367  }
368  else
369  {
370  return FALSE;
371  }
372 }
373 
374 
375 /**
376  * @brief Delete a semaphore object
377  * @param[in] semaphore Pointer to the semaphore object
378  **/
379 
381 {
382  //Make sure the semaphore ID is valid
383  if(semaphore->id != NULL)
384  {
385  //Properly dispose the specified semaphore
386  osSemaphoreDelete(semaphore->id);
387  }
388 }
389 
390 
391 /**
392  * @brief Wait for the specified semaphore to be available
393  * @param[in] semaphore Pointer to the semaphore object
394  * @param[in] timeout Timeout interval
395  * @return The function returns TRUE if the semaphore is available. FALSE is
396  * returned if the timeout interval elapsed
397  **/
398 
400 {
401  osStatus_t status;
402 
403  //Wait until the semaphore is available or the timeout interval elapses
404  if(timeout == INFINITE_DELAY)
405  {
406  //Infinite timeout period
407  status = osSemaphoreAcquire(semaphore->id, osWaitForever);
408  }
409  else
410  {
411  //Wait for the specified time interval
412  status = osSemaphoreAcquire(semaphore->id, OS_MS_TO_SYSTICKS(timeout));
413  }
414 
415  //Check return value
416  if(status == osOK)
417  {
418  return TRUE;
419  }
420  else
421  {
422  return FALSE;
423  }
424 }
425 
426 
427 /**
428  * @brief Release the specified semaphore object
429  * @param[in] semaphore Pointer to the semaphore object
430  **/
431 
433 {
434  //Release the semaphore
435  osSemaphoreRelease(semaphore->id);
436 }
437 
438 
439 /**
440  * @brief Create a mutex object
441  * @param[in] mutex Pointer to the mutex object
442  * @return The function returns TRUE if the mutex was successfully
443  * created. Otherwise, FALSE is returned
444  **/
445 
447 {
448  osMutexAttr_t mutexAttr;
449 
450  //Set mutex attributes
451  mutexAttr.name = NULL;
452  mutexAttr.attr_bits = 0;
453 
454 #if defined(os_CMSIS_RTX)
455  mutexAttr.cb_mem = &mutex->cb;
456  mutexAttr.cb_size = sizeof(os_mutex_t);
457 #elif defined(osRtxVersionKernel)
458  mutexAttr.cb_mem = &mutex->cb;
459  mutexAttr.cb_size = sizeof(osRtxMutex_t);
460 #else
461  mutexAttr.cb_mem = NULL;
462  mutexAttr.cb_size = 0;
463 #endif
464 
465  //Create a mutex object
466  mutex->id = osMutexNew(&mutexAttr);
467 
468  //Check whether the returned mutex ID is valid
469  if(mutex->id != NULL)
470  {
471  return TRUE;
472  }
473  else
474  {
475  return FALSE;
476  }
477 }
478 
479 
480 /**
481  * @brief Delete a mutex object
482  * @param[in] mutex Pointer to the mutex object
483  **/
484 
485 void osDeleteMutex(OsMutex *mutex)
486 {
487  //Make sure the mutex ID is valid
488  if(mutex->id != NULL)
489  {
490  //Properly dispose the specified mutex
491  osMutexDelete(mutex->id);
492  }
493 }
494 
495 
496 /**
497  * @brief Acquire ownership of the specified mutex object
498  * @param[in] mutex Pointer to the mutex object
499  **/
500 
502 {
503  //Obtain ownership of the mutex object
504  osMutexAcquire(mutex->id, osWaitForever);
505 }
506 
507 
508 /**
509  * @brief Release ownership of the specified mutex object
510  * @param[in] mutex Pointer to the mutex object
511  **/
512 
514 {
515  //Release ownership of the mutex object
516  osMutexRelease(mutex->id);
517 }
518 
519 
520 /**
521  * @brief Retrieve system time
522  * @return Number of milliseconds elapsed since the system was last started
523  **/
524 
526 {
527  systime_t time;
528 
529  //Get current tick count
530  time = osKernelGetTickCount();
531 
532  //Convert system ticks to milliseconds
533  return OS_SYSTICKS_TO_MS(time);
534 }
535 
536 
537 /**
538  * @brief Allocate a memory block
539  * @param[in] size Bytes to allocate
540  * @return A pointer to the allocated memory block or NULL if
541  * there is insufficient memory available
542  **/
543 
544 __weak_func void *osAllocMem(size_t size)
545 {
546  void *p;
547 
548  //Enter critical section
550  //Allocate a memory block
551  p = malloc(size);
552  //Leave critical section
554 
555  //Debug message
556  TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n",
557  size, (uintptr_t) p);
558 
559  //Return a pointer to the newly allocated memory block
560  return p;
561 }
562 
563 
564 /**
565  * @brief Release a previously allocated memory block
566  * @param[in] p Previously allocated memory block to be freed
567  **/
568 
569 __weak_func void osFreeMem(void *p)
570 {
571  //Make sure the pointer is valid
572  if(p != NULL)
573  {
574  //Debug message
575  TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
576 
577  //Enter critical section
579  //Free memory block
580  free(p);
581  //Leave critical section
583  }
584 }
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)
#define OS_SELF_TASK_ID
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.
const OsTaskParameters OS_TASK_DEFAULT_PARAMS
__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 (CMSIS-RTOS 2 / RTX v5)
char_t name[]
Event object.
osSemaphoreId id
Mutex object.
osMutexId id
Semaphore object.
osSemaphoreId id
Task parameters.
uint8_t flags
Definition: tcp.h:351