os_port_ucos3.c
Go to the documentation of this file.
1 /**
2  * @file os_port_ucos3.c
3  * @brief RTOS abstraction layer (Micrium uC/OS-III)
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 <string.h>
36 #include "os_port.h"
37 #include "os_port_ucos3.h"
38 #include "os_cfg.h"
39 #include "debug.h"
40 
41 //Default task parameters
43 {
44  NULL, //Task control block
45  NULL, //Stack
46  0, //Size of the stack
47  OS_CFG_PRIO_MAX - 1 //Task priority
48 };
49 
50 
51 /**
52  * @brief Kernel initialization
53  **/
54 
55 void osInitKernel(void)
56 {
57  OS_ERR err;
58 
59  //Scheduler initialization
60  OSInit(&err);
61 }
62 
63 
64 /**
65  * @brief Start kernel
66  **/
67 
68 void osStartKernel(void)
69 {
70  OS_ERR err;
71 
72  //Start the scheduler
73  OSStart(&err);
74 }
75 
76 
77 /**
78  * @brief Create a task
79  * @param[in] name NULL-terminated string identifying the task
80  * @param[in] taskCode Pointer to the task entry function
81  * @param[in] arg Argument passed to the task function
82  * @param[in] params Task parameters
83  * @return Task identifier referencing the newly created task
84  **/
85 
86 OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg,
87  const OsTaskParameters *params)
88 {
89  OS_ERR err;
90  CPU_STK stackLimit;
91  OsTaskId taskId;
92 
93  //Check parameters
94  if(params->tcb != NULL && params->stack != NULL)
95  {
96  //The watermark limit is used to monitor and ensure that the stack
97  //does not overflow
98  stackLimit = params->stackSize / 10;
99 
100  //Create a new task
101  OSTaskCreate(params->tcb, (CPU_CHAR *) name, taskCode, arg,
102  params->priority, params->stack, stackLimit, params->stackSize, 0, 1,
103  NULL, OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR, &err);
104 
105  //Check whether the task was successfully created
106  if(err == OS_ERR_NONE)
107  {
108  taskId = (OsTaskId) params->tcb;
109  }
110  else
111  {
112  taskId = OS_INVALID_TASK_ID;
113  }
114  }
115  else
116  {
117  //Invalid parameters
118  taskId = OS_INVALID_TASK_ID;
119  }
120 
121  //Return the handle referencing the newly created task
122  return taskId;
123 }
124 
125 
126 /**
127  * @brief Delete a task
128  * @param[in] taskId Task identifier referencing the task to be deleted
129  **/
130 
131 void osDeleteTask(OsTaskId taskId)
132 {
133  OS_ERR err;
134 
135  //Delete the specified task
136  OSTaskDel((OS_TCB *) taskId, &err);
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  OS_ERR err;
148 
149  //Delay the task for the specified duration
150  OSTimeDly(OS_MS_TO_SYSTICKS(delay), OS_OPT_TIME_DLY, &err);
151 }
152 
153 
154 /**
155  * @brief Yield control to the next task
156  **/
157 
158 void osSwitchTask(void)
159 {
160  //Force a context switch
161  OSSched();
162 }
163 
164 
165 /**
166  * @brief Suspend scheduler activity
167  **/
168 
170 {
171  OS_ERR err;
172 
173  //Make sure the operating system is running
174  if(OSRunning == OS_STATE_OS_RUNNING)
175  {
176  //Suspend scheduler activity
177  OSSchedLock(&err);
178  }
179 }
180 
181 
182 /**
183  * @brief Resume scheduler activity
184  **/
185 
187 {
188  OS_ERR err;
189 
190  //Make sure the operating system is running
191  if(OSRunning == OS_STATE_OS_RUNNING)
192  {
193  //Resume scheduler activity
194  OSSchedUnlock(&err);
195  }
196 }
197 
198 
199 /**
200  * @brief Create an event object
201  * @param[in] event Pointer to the event object
202  * @return The function returns TRUE if the event object was successfully
203  * created. Otherwise, FALSE is returned
204  **/
205 
207 {
208  OS_ERR err;
209 
210  //Create an event flag group
211  OSFlagCreate(event, "EVENT", 0, &err);
212 
213  //Check whether the event flag group was successfully created
214  if(err == OS_ERR_NONE)
215  {
216  return TRUE;
217  }
218  else
219  {
220  return FALSE;
221  }
222 }
223 
224 
225 /**
226  * @brief Delete an event object
227  * @param[in] event Pointer to the event object
228  **/
229 
230 void osDeleteEvent(OsEvent *event)
231 {
232  OS_ERR err;
233 
234  //Make sure the operating system is running
235  if(OSRunning == OS_STATE_OS_RUNNING)
236  {
237  //Properly dispose the event object
238  OSFlagDel(event, OS_OPT_DEL_ALWAYS, &err);
239  }
240 }
241 
242 
243 /**
244  * @brief Set the specified event object to the signaled state
245  * @param[in] event Pointer to the event object
246  **/
247 
248 void osSetEvent(OsEvent *event)
249 {
250  OS_ERR err;
251 
252  //Set the specified event to the signaled state
253  OSFlagPost(event, 1, OS_OPT_POST_FLAG_SET, &err);
254 }
255 
256 
257 /**
258  * @brief Set the specified event object to the nonsignaled state
259  * @param[in] event Pointer to the event object
260  **/
261 
262 void osResetEvent(OsEvent *event)
263 {
264  OS_ERR err;
265 
266  //Force the specified event to the nonsignaled state
267  OSFlagPost(event, 1, OS_OPT_POST_FLAG_CLR, &err);
268 }
269 
270 
271 /**
272  * @brief Wait until the specified event is in the signaled state
273  * @param[in] event Pointer to the event object
274  * @param[in] timeout Timeout interval
275  * @return The function returns TRUE if the state of the specified object is
276  * signaled. FALSE is returned if the timeout interval elapsed
277  **/
278 
280 {
281  OS_ERR err;
282 
283  //Wait until the specified event is in the signaled state or the timeout
284  //interval elapses
285  if(timeout == 0)
286  {
287  //Non-blocking call
288  OSFlagPend(event, 1, 0, OS_OPT_PEND_FLAG_SET_ANY |
289  OS_OPT_PEND_FLAG_CONSUME | OS_OPT_PEND_NON_BLOCKING, NULL, &err);
290  }
291  else if(timeout == INFINITE_DELAY)
292  {
293  //Infinite timeout period
294  OSFlagPend(event, 1, 0, OS_OPT_PEND_FLAG_SET_ANY |
295  OS_OPT_PEND_FLAG_CONSUME | OS_OPT_PEND_BLOCKING, NULL, &err);
296  }
297  else
298  {
299  //Wait until the specified event becomes set
300  OSFlagPend(event, 1, OS_MS_TO_SYSTICKS(timeout), OS_OPT_PEND_FLAG_SET_ANY |
301  OS_OPT_PEND_FLAG_CONSUME | OS_OPT_PEND_BLOCKING, NULL, &err);
302  }
303 
304  //Check whether the specified event is set
305  if(err == OS_ERR_NONE)
306  {
307  return TRUE;
308  }
309  else
310  {
311  return FALSE;
312  }
313 }
314 
315 
316 /**
317  * @brief Set an event object to the signaled state from an interrupt service routine
318  * @param[in] event Pointer to the event object
319  * @return TRUE if setting the event to signaled state caused a task to unblock
320  * and the unblocked task has a priority higher than the currently running task
321  **/
322 
324 {
325  OS_ERR err;
326 
327  //Set the specified event to the signaled state
328  OSFlagPost(event, 1, OS_OPT_POST_FLAG_SET, &err);
329 
330  //The return value is not relevant
331  return FALSE;
332 }
333 
334 
335 /**
336  * @brief Create a semaphore object
337  * @param[in] semaphore Pointer to the semaphore object
338  * @param[in] count The maximum count for the semaphore object. This value
339  * must be greater than zero
340  * @return The function returns TRUE if the semaphore was successfully
341  * created. Otherwise, FALSE is returned
342  **/
343 
345 {
346  OS_ERR err;
347 
348  //Create a semaphore
349  OSSemCreate(semaphore, "SEMAPHORE", count, &err);
350 
351  //Check whether the semaphore was successfully created
352  if(err == OS_ERR_NONE)
353  {
354  return TRUE;
355  }
356  else
357  {
358  return FALSE;
359  }
360 }
361 
362 
363 /**
364  * @brief Delete a semaphore object
365  * @param[in] semaphore Pointer to the semaphore object
366  **/
367 
369 {
370  OS_ERR err;
371 
372  //Make sure the operating system is running
373  if(OSRunning == OS_STATE_OS_RUNNING)
374  {
375  //Properly dispose the specified semaphore
376  OSSemDel(semaphore, OS_OPT_DEL_ALWAYS, &err);
377  }
378 }
379 
380 
381 /**
382  * @brief Wait for the specified semaphore to be available
383  * @param[in] semaphore Pointer to the semaphore object
384  * @param[in] timeout Timeout interval
385  * @return The function returns TRUE if the semaphore is available. FALSE is
386  * returned if the timeout interval elapsed
387  **/
388 
390 {
391  OS_ERR err;
392 
393  //Wait until the semaphore is available or the timeout interval elapses
394  if(timeout == 0)
395  {
396  //Non-blocking call
397  OSSemPend(semaphore, 0, OS_OPT_PEND_NON_BLOCKING, NULL, &err);
398  }
399  else if(timeout == INFINITE_DELAY)
400  {
401  //Infinite timeout period
402  OSSemPend(semaphore, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
403  }
404  else
405  {
406  //Wait until the specified semaphore becomes available
407  OSSemPend(semaphore, OS_MS_TO_SYSTICKS(timeout),
408  OS_OPT_PEND_BLOCKING, NULL, &err);
409  }
410 
411  //Check whether the specified semaphore is available
412  if(err == OS_ERR_NONE)
413  {
414  return TRUE;
415  }
416  else
417  {
418  return FALSE;
419  }
420 }
421 
422 
423 /**
424  * @brief Release the specified semaphore object
425  * @param[in] semaphore Pointer to the semaphore object
426  **/
427 
429 {
430  OS_ERR err;
431 
432  //Release the semaphore
433  OSSemPost(semaphore, OS_OPT_POST_1, &err);
434 }
435 
436 
437 /**
438  * @brief Create a mutex object
439  * @param[in] mutex Pointer to the mutex object
440  * @return The function returns TRUE if the mutex was successfully
441  * created. Otherwise, FALSE is returned
442  **/
443 
445 {
446  OS_ERR err;
447 
448  //Create a mutex
449  OSMutexCreate(mutex, "MUTEX", &err);
450 
451  //Check whether the mutex was successfully created
452  if(err == OS_ERR_NONE)
453  {
454  return TRUE;
455  }
456  else
457  {
458  return FALSE;
459  }
460 }
461 
462 
463 /**
464  * @brief Delete a mutex object
465  * @param[in] mutex Pointer to the mutex object
466  **/
467 
468 void osDeleteMutex(OsMutex *mutex)
469 {
470  OS_ERR err;
471 
472  //Make sure the operating system is running
473  if(OSRunning == OS_STATE_OS_RUNNING)
474  {
475  //Properly dispose the specified mutex
476  OSMutexDel(mutex, OS_OPT_DEL_ALWAYS, &err);
477  }
478 }
479 
480 
481 /**
482  * @brief Acquire ownership of the specified mutex object
483  * @param[in] mutex Pointer to the mutex object
484  **/
485 
487 {
488  OS_ERR err;
489 
490  //Obtain ownership of the mutex object
491  OSMutexPend(mutex, 0, OS_OPT_PEND_BLOCKING, NULL, &err);
492 }
493 
494 
495 /**
496  * @brief Release ownership of the specified mutex object
497  * @param[in] mutex Pointer to the mutex object
498  **/
499 
501 {
502  OS_ERR err;
503 
504  //Release ownership of the mutex object
505  OSMutexPost(mutex, OS_OPT_POST_NONE, &err);
506 }
507 
508 
509 /**
510  * @brief Retrieve system time
511  * @return Number of milliseconds elapsed since the system was last started
512  **/
513 
515 {
516  OS_ERR err;
517  systime_t time;
518 
519  //Get current tick count
520  time = OSTimeGet(&err);
521 
522  //Convert system ticks to milliseconds
523  return OS_SYSTICKS_TO_MS(time);
524 }
525 
526 
527 /**
528  * @brief Allocate a memory block
529  * @param[in] size Bytes to allocate
530  * @return A pointer to the allocated memory block or NULL if
531  * there is insufficient memory available
532  **/
533 
534 __weak_func void *osAllocMem(size_t size)
535 {
536  void *p;
537 
538  //Enter critical section
540  //Allocate a memory block
541  p = malloc(size);
542  //Leave critical section
544 
545  //Debug message
546  TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n",
547  size, (uintptr_t) p);
548 
549  //Return a pointer to the newly allocated memory block
550  return p;
551 }
552 
553 
554 /**
555  * @brief Release a previously allocated memory block
556  * @param[in] p Previously allocated memory block to be freed
557  **/
558 
559 __weak_func void osFreeMem(void *p)
560 {
561  //Make sure the pointer is valid
562  if(p != NULL)
563  {
564  //Debug message
565  TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
566 
567  //Enter critical section
569  //Free memory block
570  free(p);
571  //Leave critical section
573  }
574 }
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_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
Definition: os_port_ucos3.c:42
__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.
Definition: os_port_ucos3.c:86
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.
Definition: os_port_ucos3.c:68
void osInitKernel(void)
Kernel initialization.
Definition: os_port_ucos3.c:55
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
RTOS abstraction layer (Micrium uC/OS-III)
char_t name[]
Event object.
Mutex object.
Semaphore object.
Task parameters.