os_port_cmsis_rtos.c
Go to the documentation of this file.
1 /**
2  * @file os_port_cmsis_rtos.c
3  * @brief RTOS abstraction layer (CMSIS-RTOS)
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  *
23  * @author Oryx Embedded SARL (www.oryx-embedded.com)
24  * @version 1.9.0
25  **/
26 
27 //Switch to the appropriate trace level
28 #define TRACE_LEVEL TRACE_LEVEL_OFF
29 
30 //Dependencies
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include "os_port.h"
34 #include "os_port_cmsis_rtos.h"
35 #include "debug.h"
36 
37 
38 /**
39  * @brief Kernel initialization
40  **/
41 
42 void osInitKernel(void)
43 {
44 #if (osCMSIS >= 0x10001)
45  //Initialize the kernel
46  osKernelInitialize();
47 #endif
48 }
49 
50 
51 /**
52  * @brief Start kernel
53  **/
54 
55 void osStartKernel(void)
56 {
57 #if (osCMSIS >= 0x10001)
58  //Start the kernel
59  osKernelStart();
60 #else
61  //Start the kernel
62  osKernelStart(NULL, NULL);
63 #endif
64 }
65 
66 
67 /**
68  * @brief Create a new task
69  * @param[in] name A name identifying the task
70  * @param[in] taskCode Pointer to the task entry function
71  * @param[in] param A pointer to a variable to be passed to the task
72  * @param[in] stackSize The initial size of the stack, in words
73  * @param[in] priority The priority at which the task should run
74  * @return If the function succeeds, the return value is a pointer to the
75  * new task. If the function fails, the return value is NULL
76  **/
77 
79  void *param, size_t stackSize, int_t priority)
80 {
81  osThreadId threadId;
82  osThreadDef_t threadDef;
83 
84 #if defined(osCMSIS_RTX) && (osCMSIS_RTX < 0x50000)
85  threadDef.pthread = (os_pthread) taskCode;
86  threadDef.tpriority = (osPriority) priority;
87  threadDef.instances = 1;
88  threadDef.stacksize = stackSize * sizeof(uint_t);
89 #elif defined(osCMSIS_RTX) && (osCMSIS_RTX >= 0x50000)
90  threadDef.pthread = (os_pthread) taskCode;
91  threadDef.attr.name = name;
92  threadDef.attr.attr_bits = 0;
93  threadDef.attr.cb_mem = NULL;
94  threadDef.attr.cb_size = 0;
95  threadDef.attr.stack_mem = NULL;
96  threadDef.attr.stack_size = stackSize * sizeof(uint_t);
97  threadDef.attr.priority = (osPriority_t) priority;
98  threadDef.attr.tz_module = 0;
99  threadDef.attr.reserved = 0;
100 #elif defined(osCMSIS_FreeRTOS)
101  threadDef.pthread = (os_pthread) taskCode;
102  threadDef.attr.name = name;
103  threadDef.attr.attr_bits = 0;
104  threadDef.attr.cb_mem = NULL;
105  threadDef.attr.cb_size = 0;
106  threadDef.attr.stack_mem = NULL;
107  threadDef.attr.stack_size = stackSize * sizeof(uint_t);
108  threadDef.attr.priority = (osPriority_t) priority;
109  threadDef.attr.tz_module = 0;
110  threadDef.attr.reserved = 0;
111 #else
112  threadDef.name = (char_t *) name;
113  threadDef.pthread = (os_pthread) taskCode;
114  threadDef.tpriority = (osPriority) priority;
115  threadDef.instances = 1;
116  threadDef.stacksize = stackSize;
117 #endif
118 
119  //Create a new thread
120  threadId = osThreadCreate(&threadDef, param);
121  //Return a handle to the newly created thread
122  return (OsTask *) threadId;
123 }
124 
125 
126 /**
127  * @brief Delete a task
128  * @param[in] task Pointer to the task to be deleted
129  **/
130 
131 void osDeleteTask(OsTask *task)
132 {
133 #if (osCMSIS >= 0x20000)
134  //Delete the specified thread
135  if(task == NULL)
136  osThreadExit();
137  else
138  osThreadTerminate((osThreadId_t) task);
139 #else
140  //Delete the specified thread
141  osThreadTerminate((osThreadId) task);
142 #endif
143 }
144 
145 
146 /**
147  * @brief Delay routine
148  * @param[in] delay Amount of time for which the calling task should block
149  **/
150 
152 {
153  //Delay the thread for the specified duration
154  osDelay(delay);
155 }
156 
157 
158 /**
159  * @brief Yield control to the next task
160  **/
161 
162 void osSwitchTask(void)
163 {
164  //Force a context switch
165  osThreadYield();
166 }
167 
168 
169 /**
170  * @brief Suspend scheduler activity
171  **/
172 
174 {
175 #if defined(osCMSIS_RTX) || defined(osCMSIS_FreeRTOS)
176  //Not implemented
177 #else
178  //Make sure the operating system is running
179  if(osKernelRunning())
180  {
181  //Suspend all threads
182  osThreadSuspendAll();
183  }
184 #endif
185 }
186 
187 
188 /**
189  * @brief Resume scheduler activity
190  **/
191 
193 {
194 #if defined(osCMSIS_RTX) || defined(osCMSIS_FreeRTOS)
195  //Not implemented
196 #else
197  //Make sure the operating system is running
198  if(osKernelRunning())
199  {
200  //Resume all threads
201  osThreadResumeAll();
202  }
203 #endif
204 }
205 
206 
207 /**
208  * @brief Create an event object
209  * @param[in] event Pointer to the event object
210  * @return The function returns TRUE if the event object was successfully
211  * created. Otherwise, FALSE is returned
212  **/
213 
215 {
216  osSemaphoreDef_t semaphoreDef;
217 
218 #if defined(osCMSIS_RTX) && (osCMSIS_RTX < 0x50000)
219  semaphoreDef.semaphore = event->cb;
220 #elif defined(osCMSIS_RTX) && (osCMSIS_RTX >= 0x50000)
221  semaphoreDef.name = NULL;
222  semaphoreDef.attr_bits = 0;
223  semaphoreDef.cb_mem = NULL;
224  semaphoreDef.cb_size = 0;
225 #elif defined(osCMSIS_FreeRTOS)
226  semaphoreDef.name = NULL;
227  semaphoreDef.attr_bits = 0;
228  semaphoreDef.cb_mem = NULL;
229  semaphoreDef.cb_size = 0;
230 #else
231  semaphoreDef.dummy = 0;
232 #endif
233 
234  //Create a binary semaphore object
235  event->id = osSemaphoreCreate(&semaphoreDef, 1);
236 
237  //Check whether the returned semaphore ID is valid
238  if(event->id != NULL)
239  {
240  //Force the specified event to the nonsignaled state
241  osSemaphoreWait(event->id, 0);
242  //Event successfully created
243  return TRUE;
244  }
245  else
246  {
247  //Failed to create event object
248  return FALSE;
249  }
250 }
251 
252 
253 /**
254  * @brief Delete an event object
255  * @param[in] event Pointer to the event object
256  **/
257 
258 void osDeleteEvent(OsEvent *event)
259 {
260  //Make sure the semaphore ID is valid
261  if(event->id != NULL)
262  {
263  //Properly dispose the event object
264  osSemaphoreDelete(event->id);
265  }
266 }
267 
268 
269 /**
270  * @brief Set the specified event object to the signaled state
271  * @param[in] event Pointer to the event object
272  **/
273 
274 void osSetEvent(OsEvent *event)
275 {
276  //Set the specified event to the signaled state
277  osSemaphoreRelease(event->id);
278 }
279 
280 
281 /**
282  * @brief Set the specified event object to the nonsignaled state
283  * @param[in] event Pointer to the event object
284  **/
285 
286 void osResetEvent(OsEvent *event)
287 {
288 #if defined(osCMSIS_RTX) && (osCMSIS_RTX < 0x50000)
289  //Force the specified event to the nonsignaled state
290  while(osSemaphoreWait(event->id, 0) > 0);
291 #else
292  //Force the specified event to the nonsignaled state
293  osSemaphoreWait(event->id, 0);
294 #endif
295 }
296 
297 
298 /**
299  * @brief Wait until the specified event is in the signaled state
300  * @param[in] event Pointer to the event object
301  * @param[in] timeout Timeout interval
302  * @return The function returns TRUE if the state of the specified object is
303  * signaled. FALSE is returned if the timeout interval elapsed
304  **/
305 
307 {
308  int32_t ret;
309 
310  //Wait until the specified event is in the signaled
311  //state or the timeout interval elapses
312  if(timeout == INFINITE_DELAY)
313  {
314  //Infinite timeout period
315  ret = osSemaphoreWait(event->id, osWaitForever);
316  }
317  else
318  {
319 #if defined(osCMSIS_RTX) && (osCMSIS_RTX < 0x50000)
320  systime_t n;
321 
322  //Loop until the assigned time period has elapsed
323  do
324  {
325  //Limit the timeout value
326  n = MIN(timeout, 10000);
327  //Wait for the specified time interval
328  ret = osSemaphoreWait(event->id, n);
329  //Decrement timeout value
330  timeout -= n;
331 
332  //Check timeout value
333  } while(ret == 0 && timeout > 0);
334 #else
335  //Wait for the specified time interval
336  ret = osSemaphoreWait(event->id, timeout);
337 #endif
338  }
339 
340 #if defined(osCMSIS_RTX) && (osCMSIS_RTX < 0x50000)
341  //Check return value
342  if(ret > 0)
343  {
344  //Force the event back to the nonsignaled state
345  while(osSemaphoreWait(event->id, 0) > 0);
346 
347  //The specified event is in the signaled state
348  return TRUE;
349  }
350  else
351  {
352  //The timeout interval elapsed
353  return FALSE;
354  }
355 #elif defined(osCMSIS_RTX) && (osCMSIS_RTX >= 0x50000)
356  //Check return value
357  if(ret > 0)
358  return TRUE;
359  else
360  return FALSE;
361 #elif defined(osCMSIS_FreeRTOS)
362  //Check return value
363  if(ret > 0)
364  return TRUE;
365  else
366  return FALSE;
367 #else
368  //Check return value
369  if(ret == osOK)
370  return TRUE;
371  else
372  return FALSE;
373 #endif
374 }
375 
376 
377 /**
378  * @brief Set an event object to the signaled state from an interrupt service routine
379  * @param[in] event Pointer to the event object
380  * @return TRUE if setting the event to signaled state caused a task to unblock
381  * and the unblocked task has a priority higher than the currently running task
382  **/
383 
385 {
386  //Set the specified event to the signaled state
387  osSemaphoreRelease(event->id);
388 
389  //The return value is not relevant
390  return FALSE;
391 }
392 
393 
394 /**
395  * @brief Create a semaphore object
396  * @param[in] semaphore Pointer to the semaphore object
397  * @param[in] count The maximum count for the semaphore object. This value
398  * must be greater than zero
399  * @return The function returns TRUE if the semaphore was successfully
400  * created. Otherwise, FALSE is returned
401  **/
402 
404 {
405  osSemaphoreDef_t semaphoreDef;
406 
407 #if defined(osCMSIS_RTX) && (osCMSIS_RTX < 0x50000)
408  semaphoreDef.semaphore = semaphore->cb;
409 #elif defined(osCMSIS_RTX) && (osCMSIS_RTX >= 0x50000)
410  semaphoreDef.name = NULL;
411  semaphoreDef.attr_bits = 0;
412  semaphoreDef.cb_mem = NULL;
413  semaphoreDef.cb_size = 0;
414 #elif defined(osCMSIS_FreeRTOS)
415  semaphoreDef.name = NULL;
416  semaphoreDef.attr_bits = 0;
417  semaphoreDef.cb_mem = NULL;
418  semaphoreDef.cb_size = 0;
419 #else
420  semaphoreDef.dummy = 0;
421 #endif
422 
423  //Create a semaphore object
424  semaphore->id = osSemaphoreCreate(&semaphoreDef, count);
425 
426  //Check whether the returned semaphore ID is valid
427  if(semaphore->id != NULL)
428  return TRUE;
429  else
430  return FALSE;
431 }
432 
433 
434 /**
435  * @brief Delete a semaphore object
436  * @param[in] semaphore Pointer to the semaphore object
437  **/
438 
440 {
441  //Make sure the semaphore ID is valid
442  if(semaphore->id != NULL)
443  {
444  //Properly dispose the specified semaphore
445  osSemaphoreDelete(semaphore->id);
446  }
447 }
448 
449 
450 /**
451  * @brief Wait for the specified semaphore to be available
452  * @param[in] semaphore Pointer to the semaphore object
453  * @param[in] timeout Timeout interval
454  * @return The function returns TRUE if the semaphore is available. FALSE is
455  * returned if the timeout interval elapsed
456  **/
457 
459 {
460  int32_t ret;
461 
462  //Wait until the semaphore is available or the timeout interval elapses
463  if(timeout == INFINITE_DELAY)
464  {
465  //Infinite timeout period
466  ret = osSemaphoreWait(semaphore->id, osWaitForever);
467  }
468  else
469  {
470 #if defined(osCMSIS_RTX) && (osCMSIS_RTX < 0x50000)
471  systime_t n;
472 
473  //Loop until the assigned time period has elapsed
474  do
475  {
476  //Limit the timeout value
477  n = MIN(timeout, 10000);
478  //Wait for the specified time interval
479  ret = osSemaphoreWait(semaphore->id, n);
480  //Decrement timeout value
481  timeout -= n;
482 
483  //Check timeout value
484  } while(ret == 0 && timeout > 0);
485 #else
486  //Wait for the specified time interval
487  ret = osSemaphoreWait(semaphore->id, timeout);
488 #endif
489  }
490 
491 #if defined(osCMSIS_RTX) || defined(osCMSIS_FreeRTOS)
492  //Check return value
493  if(ret > 0)
494  return TRUE;
495  else
496  return FALSE;
497 #else
498  //Check return value
499  if(ret == osOK)
500  return TRUE;
501  else
502  return FALSE;
503 #endif
504 }
505 
506 
507 /**
508  * @brief Release the specified semaphore object
509  * @param[in] semaphore Pointer to the semaphore object
510  **/
511 
513 {
514  //Release the semaphore
515  osSemaphoreRelease(semaphore->id);
516 }
517 
518 
519 /**
520  * @brief Create a mutex object
521  * @param[in] mutex Pointer to the mutex object
522  * @return The function returns TRUE if the mutex was successfully
523  * created. Otherwise, FALSE is returned
524  **/
525 
527 {
528  osMutexDef_t mutexDef;
529 
530 #if defined(osCMSIS_RTX) && (osCMSIS_RTX < 0x50000)
531  mutexDef.mutex = mutex->cb;
532 #elif defined(osCMSIS_RTX) && (osCMSIS_RTX >= 0x50000)
533  mutexDef.name = NULL;
534  mutexDef.attr_bits = 0;
535  mutexDef.cb_mem = NULL;
536  mutexDef.cb_size = 0;
537 #elif defined(osCMSIS_FreeRTOS)
538  mutexDef.name = NULL;
539  mutexDef.attr_bits = 0;
540  mutexDef.cb_mem = NULL;
541  mutexDef.cb_size = 0;
542 #else
543  mutexDef.dummy = 0;
544 #endif
545 
546  //Create a mutex object
547  mutex->id = osMutexCreate(&mutexDef);
548 
549  //Check whether the returned mutex ID is valid
550  if(mutex->id != NULL)
551  return TRUE;
552  else
553  return FALSE;
554 }
555 
556 
557 /**
558  * @brief Delete a mutex object
559  * @param[in] mutex Pointer to the mutex object
560  **/
561 
562 void osDeleteMutex(OsMutex *mutex)
563 {
564  //Make sure the mutex ID is valid
565  if(mutex->id != NULL)
566  {
567  //Properly dispose the specified mutex
568  osMutexDelete(mutex->id);
569  }
570 }
571 
572 
573 /**
574  * @brief Acquire ownership of the specified mutex object
575  * @param[in] mutex Pointer to the mutex object
576  **/
577 
579 {
580  //Obtain ownership of the mutex object
581  osMutexWait(mutex->id, osWaitForever);
582 }
583 
584 
585 /**
586  * @brief Release ownership of the specified mutex object
587  * @param[in] mutex Pointer to the mutex object
588  **/
589 
591 {
592  //Release ownership of the mutex object
593  osMutexRelease(mutex->id);
594 }
595 
596 
597 /**
598  * @brief Retrieve system time
599  * @return Number of milliseconds elapsed since the system was last started
600  **/
601 
603 {
604  systime_t time;
605 
606 #if defined(osCMSIS_RTX) && (osCMSIS_RTX < 0x50000)
607  //Forward function declaration
608  extern uint32_t rt_time_get(void);
609 
610  //Get current tick count
611  time = rt_time_get();
612 #elif defined(osCMSIS_RTX) && (osCMSIS_RTX >= 0x50000)
613  time = osKernelGetTickCount();
614 #elif defined(osCMSIS_FreeRTOS)
615  time = osKernelGetTickCount();
616 #else
617  //Get current tick count
618  time = osKernelSysTick();
619 #endif
620 
621  //Convert system ticks to milliseconds
622  return OS_SYSTICKS_TO_MS(time);
623 }
624 
625 
626 /**
627  * @brief Allocate a memory block
628  * @param[in] size Bytes to allocate
629  * @return A pointer to the allocated memory block or NULL if
630  * there is insufficient memory available
631  **/
632 
633 void *osAllocMem(size_t size)
634 {
635  void *p;
636 
637  //Enter critical section
639  //Allocate a memory block
640  p = malloc(size);
641  //Leave critical section
643 
644  //Debug message
645  TRACE_DEBUG("Allocating %u bytes at 0x%08X\r\n", size, (uint_t) p);
646 
647  //Return a pointer to the newly allocated memory block
648  return p;
649 }
650 
651 
652 /**
653  * @brief Release a previously allocated memory block
654  * @param[in] p Previously allocated memory block to be freed
655  **/
656 
657 void osFreeMem(void *p)
658 {
659  //Make sure the pointer is valid
660  if(p != NULL)
661  {
662  //Debug message
663  TRACE_DEBUG("Freeing memory at 0x%08X\r\n", (uint_t) p);
664 
665  //Enter critical section
667  //Free memory block
668  free(p);
669  //Leave critical section
671  }
672 }
uint16_t priority
Definition: dns_common.h:219
uint32_t systime_t
Definition: compiler_port.h:44
char char_t
Definition: compiler_port.h:41
uint32_t time
RTOS abstraction layer (CMSIS-RTOS)
Debugging facilities.
uint8_t p
Definition: ndp.h:295
bool_t osCreateSemaphore(OsSemaphore *semaphore, uint_t count)
Create a semaphore object.
void osDeleteEvent(OsEvent *event)
Delete an event object.
void osReleaseSemaphore(OsSemaphore *semaphore)
Release the specified semaphore object.
void osDelayTask(systime_t delay)
Delay routine.
void * osAllocMem(size_t size)
Allocate a memory block.
osSemaphoreId id
Event object.
#define TRUE
Definition: os_port.h:48
Task object.
signed int int_t
Definition: compiler_port.h:42
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
char_t name[]
void osStartKernel(void)
Start kernel.
void osSwitchTask(void)
Yield control to the next task.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
#define INFINITE_DELAY
Definition: os_port.h:72
RTOS abstraction layer.
void osDeleteSemaphore(OsSemaphore *semaphore)
Delete a semaphore object.
void osResumeAllTasks(void)
Resume scheduler activity.
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
#define MIN(a, b)
Definition: os_port.h:60
systime_t osGetSystemTime(void)
Retrieve system time.
void(* OsTaskCode)(void *param)
Task routine.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
bool_t osCreateEvent(OsEvent *event)
Create an event object.
unsigned int uint_t
Definition: compiler_port.h:43
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
#define OS_SYSTICKS_TO_MS(n)
void osInitKernel(void)
Kernel initialization.
Mutex object.
void osFreeMem(void *p)
Release a previously allocated memory block.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osDeleteTask(OsTask *task)
Delete a task.
osSemaphoreId id
uint8_t n
bool_t osWaitForSemaphore(OsSemaphore *semaphore, systime_t timeout)
Wait for the specified semaphore to be available.
Semaphore object.
OsTask * osCreateTask(const char_t *name, OsTaskCode taskCode, void *param, size_t stackSize, int_t priority)
Create a new task.
#define FALSE
Definition: os_port.h:44
int bool_t
Definition: compiler_port.h:47
void osSuspendAllTasks(void)
Suspend scheduler activity.
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
osMutexId id
#define TRACE_DEBUG(...)
Definition: debug.h:98