os_port_cmx_rtx.c
Go to the documentation of this file.
1 /**
2  * @file os_port_cmx_rtx.c
3  * @brief RTOS abstraction layer (CMX-RTX)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 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.5.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_cmx_rtx.h"
37 #include "debug.h"
38 
39 //Global variable
40 static bool_t semaphoreTable[OS_MAX_SEMAPHORES];
41 
42 //Default task parameters
44 {
45  NULL, //Function pointer
46  NULL, //Stack
47  256, //Size of the stack
48  1 //Task priority
49 };
50 
51 
52 /**
53  * @brief Allocate a new semaphore identifier
54  * @return Semaphore identifier
55  **/
56 
57 uint8_t osAllocateSemaphoreId(void)
58 {
59  uint_t i;
60  uint8_t id;
61 
62  //Initialize identifier
64 
65  //Enter critical section
66  __disable_irq();
67 
68  //Loop through the allocation table
69  for(i = 0; i < OS_MAX_SEMAPHORES && id == OS_INVALID_SEMAPHORE_ID; i++)
70  {
71  //Check whether the current ID is available for use
72  if(semaphoreTable[i] == FALSE)
73  {
74  //Mark the entry as currently used
75  semaphoreTable[i] = TRUE;
76  //Return the current ID
77  id = (uint8_t) i;
78  }
79  }
80 
81  //Exit critical section
82  __enable_irq();
83 
84  //Return semaphore identifier
85  return id;
86 }
87 
88 
89 /**
90  * @brief Release semaphore identifier
91  * @param[in] id Semaphore identifier to be released
92  **/
93 
94 void osFreeSemaphoreId(uint8_t id)
95 {
96  //Check whether the semaphore identifier is valid
97  if(id < OS_MAX_SEMAPHORES)
98  {
99  //Enter critical section
100  __disable_irq();
101 
102  //Mark the entry as free
103  semaphoreTable[id] = FALSE;
104 
105  //Exit critical section
106  __enable_irq();
107  }
108 }
109 
110 
111 /**
112  * @brief Kernel initialization
113  **/
114 
115 void osInitKernel(void)
116 {
117  //Clear semaphore ID allocation table
118  osMemset(semaphoreTable, 0, sizeof(semaphoreTable));
119  //Initialize the kernel
120  K_OS_Init();
121 }
122 
123 
124 /**
125  * @brief Start kernel
126  **/
127 
128 void osStartKernel(void)
129 {
130  //Start the scheduler
131  K_OS_Start();
132 }
133 
134 
135 /**
136  * @brief Create a task
137  * @param[in] name NULL-terminated string identifying the task
138  * @param[in] taskCode Pointer to the task entry function
139  * @param[in] arg Argument passed to the task function
140  * @param[in] params Task parameters
141  * @return Task identifier referencing the newly created task
142  **/
143 
144 OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg,
145  const OsTaskParameters *params)
146 {
147  uint8_t status;
148  uint8_t slot;
149 
150  //Valid function pointer?
151  if(params->fp != NULL)
152  {
153  taskCode = (OsTaskCode) params->fp;
154  }
155 
156  //Static allocation?
157  if(params->stack != NULL)
158  {
159  //Create a new task
160  status = K_Task_Create_Stack(params->priority, &slot, (CMX_FP) taskCode,
161  params->stack + params->stackSize - 1);
162  }
163  else
164  {
165  //Create a new task
166  status = K_Task_Create(params->priority, &slot, (CMX_FP) taskCode,
167  params->stackSize * sizeof(uint32_t));
168  }
169 
170 #if 0
171  //Check status code
172  if(status == K_OK)
173  {
174  //Assign a name to the task
175  status = K_Task_Name(slot, (char_t *) name);
176  }
177 #endif
178 
179  //Check status code
180  if(status == K_OK)
181  {
182  //Start the task
183  status = K_Task_Start(slot);
184  }
185 
186  //Check status code
187  if(status == K_OK)
188  {
189  return (OsTaskId) slot;
190  }
191  else
192  {
193  return OS_INVALID_TASK_ID;
194  }
195 }
196 
197 
198 /**
199  * @brief Delete a task
200  * @param[in] taskId Task identifier referencing the task to be deleted
201  **/
202 
203 void osDeleteTask(OsTaskId taskId)
204 {
205  //Delete the specified task
206  if(taskId == OS_SELF_TASK_ID)
207  {
208  K_Task_End();
209  }
210  else
211  {
212  K_Task_Delete(taskId);
213  }
214 }
215 
216 
217 /**
218  * @brief Delay routine
219  * @param[in] delay Amount of time for which the calling task should block
220  **/
221 
223 {
224  //Delay the task for the specified duration
225  K_Task_Wait(OS_MS_TO_SYSTICKS(delay));
226 }
227 
228 
229 /**
230  * @brief Yield control to the next task
231  **/
232 
233 void osSwitchTask(void)
234 {
235  //Force a context switch
236  K_Task_Coop_Sched();
237 }
238 
239 
240 /**
241  * @brief Suspend scheduler activity
242  **/
243 
245 {
246  //Suspend all tasks
247  K_Task_Lock();
248 }
249 
250 
251 /**
252  * @brief Resume scheduler activity
253  **/
254 
256 {
257  //Resume all tasks
258  K_Task_Unlock();
259 }
260 
261 
262 /**
263  * @brief Create an event object
264  * @param[in] event Pointer to the event object
265  * @return The function returns TRUE if the event object was successfully
266  * created. Otherwise, FALSE is returned
267  **/
268 
270 {
271  uint8_t status;
272 
273  //Allocate a new semaphore identifier
274  event->id = osAllocateSemaphoreId();
275 
276  //Valid semaphore identifier?
277  if(event->id != OS_INVALID_SEMAPHORE_ID)
278  {
279  //Create a semaphore object
280  status = K_Semaphore_Create(event->id, 0);
281  }
282  else
283  {
284  //Failed to allocate a new identifier
285  status = K_ERROR;
286  }
287 
288  //Check whether the semaphore was successfully created
289  if(status == K_OK)
290  {
291  return TRUE;
292  }
293  else
294  {
295  return FALSE;
296  }
297 }
298 
299 
300 /**
301  * @brief Delete an event object
302  * @param[in] event Pointer to the event object
303  **/
304 
305 void osDeleteEvent(OsEvent *event)
306 {
307  //Release semaphore identifier
308  osFreeSemaphoreId(event->id);
309 }
310 
311 
312 /**
313  * @brief Set the specified event object to the signaled state
314  * @param[in] event Pointer to the event object
315  **/
316 
317 void osSetEvent(OsEvent *event)
318 {
319  //Set the specified event to the signaled state
320  K_Semaphore_Post(event->id);
321 }
322 
323 
324 /**
325  * @brief Set the specified event object to the nonsignaled state
326  * @param[in] event Pointer to the event object
327  **/
328 
329 void osResetEvent(OsEvent *event)
330 {
331  uint8_t status;
332 
333  //Force the specified event to the nonsignaled state
334  do
335  {
336  //Decrement the semaphore's count by one
337  status = K_Semaphore_Get(event->id);
338 
339  //Check status
340  } while(status == K_OK);
341 }
342 
343 
344 /**
345  * @brief Wait until the specified event is in the signaled state
346  * @param[in] event Pointer to the event object
347  * @param[in] timeout Timeout interval
348  * @return The function returns TRUE if the state of the specified object is
349  * signaled. FALSE is returned if the timeout interval elapsed
350  **/
351 
353 {
354  uint8_t status;
355 
356  //Wait until the specified event is in the signaled state or the timeout
357  //interval elapses
358  if(timeout == 0)
359  {
360  //Non-blocking call
361  status = K_Semaphore_Get(event->id);
362  }
363  else if(timeout == INFINITE_DELAY)
364  {
365  //Infinite timeout period
366  status = K_Semaphore_Wait(event->id, 0);
367  }
368  else
369  {
370  //Wait for the specified time interval
371  status = K_Semaphore_Wait(event->id, OS_MS_TO_SYSTICKS(timeout));
372  }
373 
374  //Check whether the specified event is set
375  if(status == K_OK)
376  {
377  //Force the event back to the nonsignaled state
378  do
379  {
380  //Decrement the semaphore's count by one
381  status = K_Semaphore_Get(event->id);
382 
383  //Check status
384  } while(status == K_OK);
385 
386  //The specified event is in the signaled state
387  return TRUE;
388  }
389  else
390  {
391  //The timeout interval elapsed
392  return FALSE;
393  }
394 }
395 
396 
397 /**
398  * @brief Set an event object to the signaled state from an interrupt service routine
399  * @param[in] event Pointer to the event object
400  * @return TRUE if setting the event to signaled state caused a task to unblock
401  * and the unblocked task has a priority higher than the currently running task
402  **/
403 
405 {
406  //Set the specified event to the signaled state
407  K_Intrp_Semaphore_Post(event->id);
408 
409  //The return value is not relevant
410  return FALSE;
411 }
412 
413 
414 /**
415  * @brief Create a semaphore object
416  * @param[in] semaphore Pointer to the semaphore object
417  * @param[in] count The maximum count for the semaphore object. This value
418  * must be greater than zero
419  * @return The function returns TRUE if the semaphore was successfully
420  * created. Otherwise, FALSE is returned
421  **/
422 
424 {
425  uint8_t status;
426 
427  //Allocate a new semaphore identifier
428  semaphore->id = osAllocateSemaphoreId();
429 
430  //Valid semaphore identifier?
431  if(semaphore->id != OS_INVALID_SEMAPHORE_ID)
432  {
433  //Create a semaphore object
434  status = K_Semaphore_Create(semaphore->id, count);
435  }
436  else
437  {
438  //Failed to allocate a new identifier
439  status = K_ERROR;
440  }
441 
442  //Check whether the semaphore was successfully created
443  if(status == K_OK)
444  {
445  return TRUE;
446  }
447  else
448  {
449  return FALSE;
450  }
451 }
452 
453 
454 /**
455  * @brief Delete a semaphore object
456  * @param[in] semaphore Pointer to the semaphore object
457  **/
458 
460 {
461  //Release semaphore identifier
462  osFreeSemaphoreId(semaphore->id);
463 }
464 
465 
466 /**
467  * @brief Wait for the specified semaphore to be available
468  * @param[in] semaphore Pointer to the semaphore object
469  * @param[in] timeout Timeout interval
470  * @return The function returns TRUE if the semaphore is available. FALSE is
471  * returned if the timeout interval elapsed
472  **/
473 
475 {
476  uint8_t status;
477 
478  //Wait until the semaphore is available or the timeout interval elapses
479  if(timeout == 0)
480  {
481  //Non-blocking call
482  status = K_Semaphore_Get(semaphore->id);
483  }
484  else if(timeout == INFINITE_DELAY)
485  {
486  //Infinite timeout period
487  status = K_Semaphore_Wait(semaphore->id, 0);
488  }
489  else
490  {
491  //Wait for the specified time interval
492  status = K_Semaphore_Wait(semaphore->id, OS_MS_TO_SYSTICKS(timeout));
493  }
494 
495  //Check whether the specified semaphore is available
496  if(status == K_OK)
497  {
498  return TRUE;
499  }
500  else
501  {
502  return FALSE;
503  }
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  K_Semaphore_Post(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  uint8_t status;
529 
530  //Allocate a new semaphore identifier
531  mutex->id = osAllocateSemaphoreId();
532 
533  //Valid semaphore identifier?
534  if(mutex->id != OS_INVALID_SEMAPHORE_ID)
535  {
536  //Create a semaphore object
537  status = K_Semaphore_Create(mutex->id, 0);
538  }
539  else
540  {
541  //Failed to allocate a new identifier
542  status = K_ERROR;
543  }
544 
545  //Check status code
546  if(status == K_OK)
547  {
548  //Release the semaphore
549  status = K_Semaphore_Post(mutex->id);
550  }
551 
552  //Check whether the semaphore was successfully created
553  if(status == K_OK)
554  {
555  return TRUE;
556  }
557  else
558  {
559  return FALSE;
560  }
561 }
562 
563 
564 /**
565  * @brief Delete a mutex object
566  * @param[in] mutex Pointer to the mutex object
567  **/
568 
569 void osDeleteMutex(OsMutex *mutex)
570 {
571  //Release semaphore identifier
572  osFreeSemaphoreId(mutex->id);
573 }
574 
575 
576 /**
577  * @brief Acquire ownership of the specified mutex object
578  * @param[in] mutex Pointer to the mutex object
579  **/
580 
582 {
583  //Obtain ownership of the mutex object
584  K_Semaphore_Wait(mutex->id, 0);
585 }
586 
587 
588 /**
589  * @brief Release ownership of the specified mutex object
590  * @param[in] mutex Pointer to the mutex object
591  **/
592 
594 {
595  //Release ownership of the mutex object
596  K_Semaphore_Post(mutex->id);
597 }
598 
599 
600 /**
601  * @brief Retrieve system time
602  * @return Number of milliseconds elapsed since the system was last started
603  **/
604 
606 {
607  systime_t time;
608 
609  //Get current tick count
610  time = K_OS_Tick_Get_Ctr();
611 
612  //Convert system ticks to milliseconds
613  return OS_SYSTICKS_TO_MS(time);
614 }
615 
616 
617 /**
618  * @brief Allocate a memory block
619  * @param[in] size Bytes to allocate
620  * @return A pointer to the allocated memory block or NULL if
621  * there is insufficient memory available
622  **/
623 
624 __weak_func void *osAllocMem(size_t size)
625 {
626  void *p;
627 
628  //Enter critical section
630  //Allocate a memory block
631  p = malloc(size);
632  //Leave critical section
634 
635  //Debug message
636  TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n",
637  size, (uintptr_t) p);
638 
639  //Return a pointer to the newly allocated memory block
640  return p;
641 }
642 
643 
644 /**
645  * @brief Release a previously allocated memory block
646  * @param[in] p Previously allocated memory block to be freed
647  **/
648 
649 __weak_func void osFreeMem(void *p)
650 {
651  //Make sure the pointer is valid
652  if(p != NULL)
653  {
654  //Debug message
655  TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
656 
657  //Enter critical section
659  //Free memory block
660  free(p);
661  //Leave critical section
663  }
664 }
int bool_t
Definition: compiler_port.h:61
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
uint8_t p
Definition: ndp.h:300
#define TRUE
Definition: os_port.h:50
#define OS_INVALID_TASK_ID
Event object.
__weak_func void osFreeMem(void *p)
Release a previously allocated memory block.
char_t name[]
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
void osReleaseSemaphore(OsSemaphore *semaphore)
Release the specified semaphore object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
osSemaphoreId id
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
#define OS_SELF_TASK_ID
Semaphore object.
__weak_func void * osAllocMem(size_t size)
Allocate a memory block.
uint8_t osAllocateSemaphoreId(void)
Allocate a new semaphore identifier.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
bool_t osCreateSemaphore(OsSemaphore *semaphore, uint_t count)
Create a semaphore object.
bool_t osWaitForSemaphore(OsSemaphore *semaphore, systime_t timeout)
Wait for the specified semaphore to be available.
#define FALSE
Definition: os_port.h:46
#define OS_MAX_SEMAPHORES
void(* OsTaskCode)(void *arg)
Task routine.
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg, const OsTaskParameters *params)
Create a task.
void osFreeSemaphoreId(uint8_t id)
Release semaphore identifier.
void osStartKernel(void)
Start kernel.
osSemaphoreId id
#define OS_SYSTICKS_TO_MS(n)
#define OS_MS_TO_SYSTICKS(n)
osMutexId id
Task parameters.
void osInitKernel(void)
Kernel initialization.
bool_t osCreateEvent(OsEvent *event)
Create an event object.
systime_t osGetSystemTime(void)
Retrieve system time.
const OsTaskParameters OS_TASK_DEFAULT_PARAMS
void osDeleteTask(OsTaskId taskId)
Delete a task.
Mutex object.
uint32_t systime_t
System time.
#define TRACE_DEBUG(...)
Definition: debug.h:119
char char_t
Definition: compiler_port.h:55
uint32_t time
void osDelayTask(systime_t delay)
Delay routine.
#define OS_INVALID_SEMAPHORE_ID
void osSwitchTask(void)
Yield control to the next task.
thread_t * OsTaskId
Task identifier.
RTOS abstraction layer (CMX-RTX)
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:138
void osDeleteEvent(OsEvent *event)
Delete an event object.
void osResumeAllTasks(void)
Resume scheduler activity.
RTOS abstraction layer.
void osDeleteSemaphore(OsSemaphore *semaphore)
Delete a semaphore object.
Debugging facilities.
#define INFINITE_DELAY
Definition: os_port.h:75
void osSuspendAllTasks(void)
Suspend scheduler activity.