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-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_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  return TRUE;
378  }
379  else
380  {
381  return FALSE;
382  }
383 }
384 
385 
386 /**
387  * @brief Set an event object to the signaled state from an interrupt service routine
388  * @param[in] event Pointer to the event object
389  * @return TRUE if setting the event to signaled state caused a task to unblock
390  * and the unblocked task has a priority higher than the currently running task
391  **/
392 
394 {
395  //Set the specified event to the signaled state
396  K_Intrp_Semaphore_Post(event->id);
397 
398  //The return value is not relevant
399  return FALSE;
400 }
401 
402 
403 /**
404  * @brief Create a semaphore object
405  * @param[in] semaphore Pointer to the semaphore object
406  * @param[in] count The maximum count for the semaphore object. This value
407  * must be greater than zero
408  * @return The function returns TRUE if the semaphore was successfully
409  * created. Otherwise, FALSE is returned
410  **/
411 
413 {
414  uint8_t status;
415 
416  //Allocate a new semaphore identifier
417  semaphore->id = osAllocateSemaphoreId();
418 
419  //Valid semaphore identifier?
420  if(semaphore->id != OS_INVALID_SEMAPHORE_ID)
421  {
422  //Create a semaphore object
423  status = K_Semaphore_Create(semaphore->id, count);
424  }
425  else
426  {
427  //Failed to allocate a new identifier
428  status = K_ERROR;
429  }
430 
431  //Check whether the semaphore was successfully created
432  if(status == K_OK)
433  {
434  return TRUE;
435  }
436  else
437  {
438  return FALSE;
439  }
440 }
441 
442 
443 /**
444  * @brief Delete a semaphore object
445  * @param[in] semaphore Pointer to the semaphore object
446  **/
447 
449 {
450  //Release semaphore identifier
451  osFreeSemaphoreId(semaphore->id);
452 }
453 
454 
455 /**
456  * @brief Wait for the specified semaphore to be available
457  * @param[in] semaphore Pointer to the semaphore object
458  * @param[in] timeout Timeout interval
459  * @return The function returns TRUE if the semaphore is available. FALSE is
460  * returned if the timeout interval elapsed
461  **/
462 
464 {
465  uint8_t status;
466 
467  //Wait until the semaphore is available or the timeout interval elapses
468  if(timeout == 0)
469  {
470  //Non-blocking call
471  status = K_Semaphore_Get(semaphore->id);
472  }
473  else if(timeout == INFINITE_DELAY)
474  {
475  //Infinite timeout period
476  status = K_Semaphore_Wait(semaphore->id, 0);
477  }
478  else
479  {
480  //Wait for the specified time interval
481  status = K_Semaphore_Wait(semaphore->id, OS_MS_TO_SYSTICKS(timeout));
482  }
483 
484  //Check whether the specified semaphore is available
485  if(status == K_OK)
486  {
487  return TRUE;
488  }
489  else
490  {
491  return FALSE;
492  }
493 }
494 
495 
496 /**
497  * @brief Release the specified semaphore object
498  * @param[in] semaphore Pointer to the semaphore object
499  **/
500 
502 {
503  //Release the semaphore
504  K_Semaphore_Post(semaphore->id);
505 }
506 
507 
508 /**
509  * @brief Create a mutex object
510  * @param[in] mutex Pointer to the mutex object
511  * @return The function returns TRUE if the mutex was successfully
512  * created. Otherwise, FALSE is returned
513  **/
514 
516 {
517  uint8_t status;
518 
519  //Allocate a new semaphore identifier
520  mutex->id = osAllocateSemaphoreId();
521 
522  //Valid semaphore identifier?
523  if(mutex->id != OS_INVALID_SEMAPHORE_ID)
524  {
525  //Create a semaphore object
526  status = K_Semaphore_Create(mutex->id, 0);
527  }
528  else
529  {
530  //Failed to allocate a new identifier
531  status = K_ERROR;
532  }
533 
534  //Check status code
535  if(status == K_OK)
536  {
537  //Release the semaphore
538  status = K_Semaphore_Post(mutex->id);
539  }
540 
541  //Check whether the semaphore was successfully created
542  if(status == K_OK)
543  {
544  return TRUE;
545  }
546  else
547  {
548  return FALSE;
549  }
550 }
551 
552 
553 /**
554  * @brief Delete a mutex object
555  * @param[in] mutex Pointer to the mutex object
556  **/
557 
558 void osDeleteMutex(OsMutex *mutex)
559 {
560  //Release semaphore identifier
561  osFreeSemaphoreId(mutex->id);
562 }
563 
564 
565 /**
566  * @brief Acquire ownership of the specified mutex object
567  * @param[in] mutex Pointer to the mutex object
568  **/
569 
571 {
572  //Obtain ownership of the mutex object
573  K_Semaphore_Wait(mutex->id, 0);
574 }
575 
576 
577 /**
578  * @brief Release ownership of the specified mutex object
579  * @param[in] mutex Pointer to the mutex object
580  **/
581 
583 {
584  //Release ownership of the mutex object
585  K_Semaphore_Post(mutex->id);
586 }
587 
588 
589 /**
590  * @brief Retrieve system time
591  * @return Number of milliseconds elapsed since the system was last started
592  **/
593 
595 {
596  systime_t time;
597 
598  //Get current tick count
599  time = K_OS_Tick_Get_Ctr();
600 
601  //Convert system ticks to milliseconds
602  return OS_SYSTICKS_TO_MS(time);
603 }
604 
605 
606 /**
607  * @brief Allocate a memory block
608  * @param[in] size Bytes to allocate
609  * @return A pointer to the allocated memory block or NULL if
610  * there is insufficient memory available
611  **/
612 
613 __weak_func void *osAllocMem(size_t size)
614 {
615  void *p;
616 
617  //Enter critical section
619  //Allocate a memory block
620  p = malloc(size);
621  //Leave critical section
623 
624  //Debug message
625  TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n",
626  size, (uintptr_t) p);
627 
628  //Return a pointer to the newly allocated memory block
629  return p;
630 }
631 
632 
633 /**
634  * @brief Release a previously allocated memory block
635  * @param[in] p Previously allocated memory block to be freed
636  **/
637 
638 __weak_func void osFreeMem(void *p)
639 {
640  //Make sure the pointer is valid
641  if(p != NULL)
642  {
643  //Debug message
644  TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
645 
646  //Enter critical section
648  //Free memory block
649  free(p);
650  //Leave critical section
652  }
653 }
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 osMemset(p, value, length)
Definition: os_port.h:135
#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
#define OS_INVALID_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.
uint8_t osAllocateSemaphoreId(void)
Allocate a new semaphore identifier.
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 osFreeSemaphoreId(uint8_t id)
Release semaphore identifier.
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 (CMX-RTX)
#define OS_INVALID_SEMAPHORE_ID
#define OS_MAX_SEMAPHORES
char_t name[]
Event object.
osSemaphoreId id
Mutex object.
osMutexId id
Semaphore object.
osSemaphoreId id
Task parameters.