os_port_ucos2.c
Go to the documentation of this file.
1 /**
2  * @file os_port_ucos2.c
3  * @brief RTOS abstraction layer (Micrium uC/OS-II)
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_ucos2.h"
38 #include "debug.h"
39 
40 //Default task parameters
42 {
43  NULL, //Stack
44  0, //Size of the stack
45  0 //Task priority
46 };
47 
48 
49 /**
50  * @brief Kernel initialization
51  **/
52 
53 void osInitKernel(void)
54 {
55  //Scheduler initialization
56  OSInit();
57 }
58 
59 
60 /**
61  * @brief Start kernel
62  **/
63 
64 void osStartKernel(void)
65 {
66  //Start the scheduler
67  OSStart();
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  INT8U err;
84  OS_STK *stackTop;
85  OsTaskId taskId;
86 
87  //Check parameters
88  if(params->stack != NULL)
89  {
90  //Top of the stack
91  stackTop = (OS_STK *) params->stack + (params->stackSize - 1);
92 
93  //Create a new task
94  err = OSTaskCreateExt(taskCode, arg, stackTop, params->priority,
95  params->priority, params->stack, params->stackSize, NULL,
96  OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
97 
98  //Check whether the task was successfully created
99  if(err == OS_ERR_NONE)
100  {
101  taskId = (OsTaskId) params->priority;
102  }
103  else
104  {
105  taskId = OS_INVALID_TASK_ID;
106  }
107  }
108  else
109  {
110  //Invalid parameters
111  taskId = OS_INVALID_TASK_ID;
112  }
113 
114  //Return the handle referencing the newly created task
115  return taskId;
116 }
117 
118 
119 /**
120  * @brief Delete a task
121  * @param[in] taskId Task identifier referencing the task to be deleted
122  **/
123 
124 void osDeleteTask(OsTaskId taskId)
125 {
126  //Delete the specified task
127  OSTaskDel(taskId);
128 }
129 
130 
131 /**
132  * @brief Delay routine
133  * @param[in] delay Amount of time for which the calling task should block
134  **/
135 
137 {
138  INT16U n;
139 
140  //Convert milliseconds to system ticks
141  delay = OS_MS_TO_SYSTICKS(delay);
142 
143  //Delay the task for the specified duration
144  while(delay > 0)
145  {
146  //The maximum delay is 65535 clock ticks
147  n = MIN(delay, 65535);
148  //Wait for the specified amount of time
149  OSTimeDly(n);
150  //Decrement delay value
151  delay -= n;
152  }
153 }
154 
155 
156 /**
157  * @brief Yield control to the next task
158  **/
159 
160 void osSwitchTask(void)
161 {
162  //Not implemented
163 }
164 
165 
166 /**
167  * @brief Suspend scheduler activity
168  **/
169 
171 {
172  //Make sure the operating system is running
173  if(OSRunning == OS_TRUE)
174  {
175  //Suspend scheduler activity
176  OSSchedLock();
177  }
178 }
179 
180 
181 /**
182  * @brief Resume scheduler activity
183  **/
184 
186 {
187  //Make sure the operating system is running
188  if(OSRunning == OS_TRUE)
189  {
190  //Resume scheduler activity
191  OSSchedUnlock();
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  INT8U err;
206 
207  //Create an event flag group
208  event->p = OSFlagCreate(0, &err);
209 
210  //Check whether the event flag group was successfully created
211  if(event->p != NULL && err == OS_ERR_NONE)
212  {
213  return TRUE;
214  }
215  else
216  {
217  return FALSE;
218  }
219 }
220 
221 
222 /**
223  * @brief Delete an event object
224  * @param[in] event Pointer to the event object
225  **/
226 
227 void osDeleteEvent(OsEvent *event)
228 {
229  INT8U err;
230 
231  //Make sure the operating system is running
232  if(OSRunning == OS_TRUE)
233  {
234  //Properly dispose the event object
235  OSFlagDel(event->p, OS_DEL_ALWAYS, &err);
236  }
237 }
238 
239 
240 /**
241  * @brief Set the specified event object to the signaled state
242  * @param[in] event Pointer to the event object
243  **/
244 
245 void osSetEvent(OsEvent *event)
246 {
247  INT8U err;
248 
249  //Set the specified event to the signaled state
250  OSFlagPost(event->p, 1, OS_FLAG_SET, &err);
251 }
252 
253 
254 /**
255  * @brief Set the specified event object to the nonsignaled state
256  * @param[in] event Pointer to the event object
257  **/
258 
259 void osResetEvent(OsEvent *event)
260 {
261  INT8U err;
262 
263  //Force the specified event to the nonsignaled state
264  OSFlagPost(event->p, 1, OS_FLAG_CLR, &err);
265 }
266 
267 
268 /**
269  * @brief Wait until the specified event is in the signaled state
270  * @param[in] event Pointer to the event object
271  * @param[in] timeout Timeout interval
272  * @return The function returns TRUE if the state of the specified object is
273  * signaled. FALSE is returned if the timeout interval elapsed
274  **/
275 
277 {
278  INT8U err;
279  INT16U n;
280 
281  //Wait until the specified event is in the signaled state or the timeout
282  //interval elapses
283  if(timeout == 0)
284  {
285  //Non-blocking call
286  OSFlagAccept(event->p, 1, OS_FLAG_WAIT_SET_ANY | OS_FLAG_CONSUME, &err);
287  }
288  else if(timeout == INFINITE_DELAY)
289  {
290  //Infinite timeout period
291  OSFlagPend(event->p, 1, OS_FLAG_WAIT_SET_ANY | OS_FLAG_CONSUME, 0, &err);
292  }
293  else
294  {
295  //Convert milliseconds to system ticks
296  timeout = OS_MS_TO_SYSTICKS(timeout);
297 
298  //Loop until the assigned time period has elapsed
299  do
300  {
301  //The maximum timeout is 65535 clock ticks
302  n = MIN(timeout, 65535);
303  //Wait for the specified time interval
304  OSFlagPend(event->p, 1, OS_FLAG_WAIT_SET_ANY | OS_FLAG_CONSUME, n, &err);
305  //Decrement timeout value
306  timeout -= n;
307 
308  //Check timeout value
309  } while(err == OS_ERR_TIMEOUT && timeout > 0);
310  }
311 
312  //Check whether the specified event is set
313  if(err == OS_ERR_NONE)
314  {
315  return TRUE;
316  }
317  else
318  {
319  return FALSE;
320  }
321 }
322 
323 
324 /**
325  * @brief Set an event object to the signaled state from an interrupt service routine
326  * @param[in] event Pointer to the event object
327  * @return TRUE if setting the event to signaled state caused a task to unblock
328  * and the unblocked task has a priority higher than the currently running task
329  **/
330 
332 {
333  INT8U err;
334 
335  //Set the specified event to the signaled state
336  OSFlagPost(event->p, 1, OS_FLAG_SET, &err);
337 
338  //The return value is not relevant
339  return FALSE;
340 }
341 
342 
343 /**
344  * @brief Create a semaphore object
345  * @param[in] semaphore Pointer to the semaphore object
346  * @param[in] count The maximum count for the semaphore object. This value
347  * must be greater than zero
348  * @return The function returns TRUE if the semaphore was successfully
349  * created. Otherwise, FALSE is returned
350  **/
351 
353 {
354  //Create a semaphore
355  semaphore->p = OSSemCreate(count);
356 
357  //Check whether the semaphore was successfully created
358  if(semaphore->p != NULL)
359  {
360  return TRUE;
361  }
362  else
363  {
364  return FALSE;
365  }
366 }
367 
368 
369 /**
370  * @brief Delete a semaphore object
371  * @param[in] semaphore Pointer to the semaphore object
372  **/
373 
375 {
376  INT8U err;
377 
378  //Make sure the operating system is running
379  if(OSRunning == OS_TRUE)
380  {
381  //Properly dispose the specified semaphore
382  OSSemDel(semaphore->p, OS_DEL_ALWAYS, &err);
383  }
384 }
385 
386 
387 /**
388  * @brief Wait for the specified semaphore to be available
389  * @param[in] semaphore Pointer to the semaphore object
390  * @param[in] timeout Timeout interval
391  * @return The function returns TRUE if the semaphore is available. FALSE is
392  * returned if the timeout interval elapsed
393  **/
394 
396 {
397  INT8U err;
398  INT16U n;
399 
400  //Wait until the semaphore is available or the timeout interval elapses
401  if(timeout == 0)
402  {
403  //Non-blocking call
404  if(OSSemAccept(semaphore->p) > 0)
405  {
406  err = OS_ERR_NONE;
407  }
408  else
409  {
410  err = OS_ERR_TIMEOUT;
411  }
412  }
413  else if(timeout == INFINITE_DELAY)
414  {
415  //Infinite timeout period
416  OSSemPend(semaphore->p, 0, &err);
417  }
418  else
419  {
420  //Convert milliseconds to system ticks
421  timeout = OS_MS_TO_SYSTICKS(timeout);
422 
423  //Loop until the assigned time period has elapsed
424  do
425  {
426  //The maximum timeout is 65535 clock ticks
427  n = MIN(timeout, 65535);
428  //Wait for the specified time interval
429  OSSemPend(semaphore->p, n, &err);
430  //Decrement timeout value
431  timeout -= n;
432 
433  //Check timeout value
434  } while(err == OS_ERR_TIMEOUT && timeout > 0);
435  }
436 
437  //Check whether the specified semaphore is available
438  if(err == OS_ERR_NONE)
439  {
440  return TRUE;
441  }
442  else
443  {
444  return FALSE;
445  }
446 }
447 
448 
449 /**
450  * @brief Release the specified semaphore object
451  * @param[in] semaphore Pointer to the semaphore object
452  **/
453 
455 {
456  //Release the semaphore
457  OSSemPost(semaphore->p);
458 }
459 
460 
461 /**
462  * @brief Create a mutex object
463  * @param[in] mutex Pointer to the mutex object
464  * @return The function returns TRUE if the mutex was successfully
465  * created. Otherwise, FALSE is returned
466  **/
467 
469 {
470  INT8U err;
471 
472  //Create a mutex
473  mutex->p = OSMutexCreate(OS_PRIO_MUTEX_CEIL_DIS, &err);
474 
475  //Check whether the mutex was successfully created
476  if(mutex->p != NULL && err == OS_ERR_NONE)
477  {
478  return TRUE;
479  }
480  else
481  {
482  return FALSE;
483  }
484 }
485 
486 
487 /**
488  * @brief Delete a mutex object
489  * @param[in] mutex Pointer to the mutex object
490  **/
491 
492 void osDeleteMutex(OsMutex *mutex)
493 {
494  INT8U err;
495 
496  //Make sure the operating system is running
497  if(OSRunning == OS_TRUE)
498  {
499  //Properly dispose the specified mutex
500  OSMutexDel(mutex->p, OS_DEL_ALWAYS, &err);
501  }
502 }
503 
504 
505 /**
506  * @brief Acquire ownership of the specified mutex object
507  * @param[in] mutex Pointer to the mutex object
508  **/
509 
511 {
512  INT8U err;
513 
514  //Obtain ownership of the mutex object
515  OSMutexPend(mutex->p, 0, &err);
516 }
517 
518 
519 /**
520  * @brief Release ownership of the specified mutex object
521  * @param[in] mutex Pointer to the mutex object
522  **/
523 
525 {
526  //Release ownership of the mutex object
527  OSMutexPost(mutex->p);
528 }
529 
530 
531 /**
532  * @brief Retrieve system time
533  * @return Number of milliseconds elapsed since the system was last started
534  **/
535 
537 {
538  systime_t time;
539 
540  //Get current tick count
541  time = OSTimeGet();
542 
543  //Convert system ticks to milliseconds
544  return OS_SYSTICKS_TO_MS(time);
545 }
546 
547 
548 /**
549  * @brief Allocate a memory block
550  * @param[in] size Bytes to allocate
551  * @return A pointer to the allocated memory block or NULL if
552  * there is insufficient memory available
553  **/
554 
555 __weak_func void *osAllocMem(size_t size)
556 {
557  void *p;
558 
559  //Enter critical section
561  //Allocate a memory block
562  p = malloc(size);
563  //Leave critical section
565 
566  //Debug message
567  TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n",
568  size, (uintptr_t) p);
569 
570  //Return a pointer to the newly allocated memory block
571  return p;
572 }
573 
574 
575 /**
576  * @brief Release a previously allocated memory block
577  * @param[in] p Previously allocated memory block to be freed
578  **/
579 
580 __weak_func void osFreeMem(void *p)
581 {
582  //Make sure the pointer is valid
583  if(p != NULL)
584  {
585  //Debug message
586  TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
587 
588  //Enter critical section
590  //Free memory block
591  free(p);
592  //Leave critical section
594  }
595 }
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
uint8_t n
uint32_t time
uint8_t p
Definition: ndp.h:300
RTOS abstraction layer.
#define MIN(a, b)
Definition: os_port.h:63
#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_ucos2.c:41
__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_ucos2.c:80
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_ucos2.c:64
void osInitKernel(void)
Kernel initialization.
Definition: os_port_ucos2.c:53
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
RTOS abstraction layer (Micrium uC/OS-II)
char_t name[]
Event object.
OS_FLAG_GRP * p
Mutex object.
OS_EVENT * p
Semaphore object.
OS_EVENT * p
Task parameters.