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  * 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 <string.h>
34 #include "os_port.h"
35 #include "os_port_ucos2.h"
36 #include "debug.h"
37 
38 //Variables
39 static OsTask tcbTable[OS_LOWEST_PRIO];
40 
41 
42 /**
43  * @brief Kernel initialization
44  **/
45 
46 void osInitKernel(void)
47 {
48  //Initialize table
49  memset(tcbTable, 0, sizeof(tcbTable));
50 
51  //Scheduler initialization
52  OSInit();
53 }
54 
55 
56 /**
57  * @brief Start kernel
58  **/
59 
60 void osStartKernel(void)
61 {
62  //Start the scheduler
63  OSStart();
64 }
65 
66 
67 /**
68  * @brief Create a static task
69  * @param[out] task Pointer to the task structure
70  * @param[in] name A name identifying the task
71  * @param[in] taskCode Pointer to the task entry function
72  * @param[in] param A pointer to a variable to be passed to the task
73  * @param[in] stack Pointer to the stack
74  * @param[in] stackSize The initial size of the stack, in words
75  * @param[in] priority The priority at which the task should run
76  * @return The function returns TRUE if the task was successfully
77  * created. Otherwise, FALSE is returned
78  **/
79 
81  void *param, void *stack, size_t stackSize, int_t priority)
82 {
83  INT8U err;
84  OS_STK *stackTop;
85 
86  //Check stack size
87  if(stackSize == 0)
88  return FALSE;
89 
90  //Top of the stack
91  stackTop = (OS_STK *) stack + (stackSize - 1);
92 
93  //Search for a free TCB
94  while(priority < (OS_LOWEST_PRIO - 3) && OSTCBPrioTbl[priority] != 0)
95  priority++;
96 
97  //No more TCB available?
98  if(priority >= (OS_LOWEST_PRIO - 3))
99  return FALSE;
100 
101  //Create a new task
102  err = OSTaskCreateExt(taskCode, param, stackTop, priority, priority,
103  stack, stackSize, NULL, OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
104 
105  //Check whether the task was successfully created
106  if(err == OS_ERR_NONE)
107  {
108  //Save task priority
109  task->prio = priority;
110  //The task was successfully created
111  return TRUE;
112  }
113  else
114  {
115  //Report an error
116  return FALSE;
117  }
118 }
119 
120 
121 /**
122  * @brief Create a new task
123  * @param[in] name A name identifying the task
124  * @param[in] taskCode Pointer to the task entry function
125  * @param[in] param A pointer to a variable to be passed to the task
126  * @param[in] stackSize The initial size of the stack, in words
127  * @param[in] priority The priority at which the task should run
128  * @return If the function succeeds, the return value is a pointer to the
129  * new task. If the function fails, the return value is NULL
130  **/
131 
133  void *param, size_t stackSize, int_t priority)
134 {
135  //INT8U i;
136  OS_STK *stack;
137 
138  //Allocate a memory block to hold the task's stack
139  stack = osAllocMem(stackSize * sizeof(OS_STK));
140 
141  //Successful memory allocation?
142  if(stack != NULL)
143  {
144  //Create task
145  if(osCreateStaticTask(&tcbTable[priority], name,
146  taskCode, param, stack, stackSize, priority))
147  {
148  //Return a valid handle
149  return &tcbTable[priority];
150  }
151  else
152  {
153  //Clean up side effects
154  osFreeMem(stack);
155  //Report an error
156  return NULL;
157  }
158  }
159  else
160  {
161  //Memory allocation failed
162  return NULL;
163  }
164 }
165 
166 
167 /**
168  * @brief Delete a task
169  * @param[in] task Pointer to the task to be deleted
170  **/
171 
172 void osDeleteTask(OsTask *task)
173 {
174  //Delete the specified task
175  OSTaskDel(task->prio);
176 }
177 
178 
179 /**
180  * @brief Delay routine
181  * @param[in] delay Amount of time for which the calling task should block
182  **/
183 
185 {
186  INT16U n;
187 
188  //Convert milliseconds to system ticks
189  delay = OS_MS_TO_SYSTICKS(delay);
190 
191  //Delay the task for the specified duration
192  while(delay > 0)
193  {
194  //The maximum delay is 65535 clock ticks
195  n = MIN(delay, 65535);
196  //Wait for the specified amount of time
197  OSTimeDly(n);
198  //Decrement delay value
199  delay -= n;
200  }
201 }
202 
203 
204 /**
205  * @brief Yield control to the next task
206  **/
207 
208 void osSwitchTask(void)
209 {
210  //Not implemented
211 }
212 
213 
214 /**
215  * @brief Suspend scheduler activity
216  **/
217 
219 {
220  //Make sure the operating system is running
221  if(OSRunning == OS_TRUE)
222  {
223  //Suspend scheduler activity
224  OSSchedLock();
225  }
226 }
227 
228 
229 /**
230  * @brief Resume scheduler activity
231  **/
232 
234 {
235  //Make sure the operating system is running
236  if(OSRunning == OS_TRUE)
237  {
238  //Resume scheduler activity
239  OSSchedUnlock();
240  }
241 }
242 
243 
244 /**
245  * @brief Create an event object
246  * @param[in] event Pointer to the event object
247  * @return The function returns TRUE if the event object was successfully
248  * created. Otherwise, FALSE is returned
249  **/
250 
252 {
253  INT8U err;
254 
255  //Create an event flag group
256  event->p = OSFlagCreate(0, &err);
257 
258  //Check whether the event flag group was successfully created
259  if(event->p != NULL && err == OS_ERR_NONE)
260  return TRUE;
261  else
262  return FALSE;
263 }
264 
265 
266 /**
267  * @brief Delete an event object
268  * @param[in] event Pointer to the event object
269  **/
270 
271 void osDeleteEvent(OsEvent *event)
272 {
273  INT8U err;
274 
275  //Make sure the operating system is running
276  if(OSRunning == OS_TRUE)
277  {
278  //Properly dispose the event object
279  OSFlagDel(event->p, OS_DEL_ALWAYS, &err);
280  }
281 }
282 
283 
284 /**
285  * @brief Set the specified event object to the signaled state
286  * @param[in] event Pointer to the event object
287  **/
288 
289 void osSetEvent(OsEvent *event)
290 {
291  INT8U err;
292 
293  //Set the specified event to the signaled state
294  OSFlagPost(event->p, 1, OS_FLAG_SET, &err);
295 }
296 
297 
298 /**
299  * @brief Set the specified event object to the nonsignaled state
300  * @param[in] event Pointer to the event object
301  **/
302 
303 void osResetEvent(OsEvent *event)
304 {
305  INT8U err;
306 
307  //Force the specified event to the nonsignaled state
308  OSFlagPost(event->p, 1, OS_FLAG_CLR, &err);
309 }
310 
311 
312 /**
313  * @brief Wait until the specified event is in the signaled state
314  * @param[in] event Pointer to the event object
315  * @param[in] timeout Timeout interval
316  * @return The function returns TRUE if the state of the specified object is
317  * signaled. FALSE is returned if the timeout interval elapsed
318  **/
319 
321 {
322  INT8U err;
323  INT16U n;
324 
325  //Wait until the specified event is in the signaled
326  //state or the timeout interval elapses
327  if(timeout == 0)
328  {
329  //Non-blocking call
330  OSFlagAccept(event->p, 1, OS_FLAG_WAIT_SET_ANY | OS_FLAG_CONSUME, &err);
331  }
332  else if(timeout == INFINITE_DELAY)
333  {
334  //Infinite timeout period
335  OSFlagPend(event->p, 1, OS_FLAG_WAIT_SET_ANY | OS_FLAG_CONSUME, 0, &err);
336  }
337  else
338  {
339  //Convert milliseconds to system ticks
340  timeout = OS_MS_TO_SYSTICKS(timeout);
341 
342  //Loop until the assigned time period has elapsed
343  do
344  {
345  //The maximum timeout is 65535 clock ticks
346  n = MIN(timeout, 65535);
347  //Wait for the specified time interval
348  OSFlagPend(event->p, 1, OS_FLAG_WAIT_SET_ANY | OS_FLAG_CONSUME, n, &err);
349  //Decrement timeout value
350  timeout -= n;
351 
352  //Check timeout value
353  } while(err == OS_ERR_TIMEOUT && timeout > 0);
354  }
355 
356  //Check whether the specified event is set
357  if(err == OS_ERR_NONE)
358  return TRUE;
359  else
360  return FALSE;
361 }
362 
363 
364 /**
365  * @brief Set an event object to the signaled state from an interrupt service routine
366  * @param[in] event Pointer to the event object
367  * @return TRUE if setting the event to signaled state caused a task to unblock
368  * and the unblocked task has a priority higher than the currently running task
369  **/
370 
372 {
373  INT8U err;
374 
375  //Set the specified event to the signaled state
376  OSFlagPost(event->p, 1, OS_FLAG_SET, &err);
377 
378  //The return value is not relevant
379  return FALSE;
380 }
381 
382 
383 /**
384  * @brief Create a semaphore object
385  * @param[in] semaphore Pointer to the semaphore object
386  * @param[in] count The maximum count for the semaphore object. This value
387  * must be greater than zero
388  * @return The function returns TRUE if the semaphore was successfully
389  * created. Otherwise, FALSE is returned
390  **/
391 
393 {
394  //Create a semaphore
395  semaphore->p = OSSemCreate(count);
396 
397  //Check whether the semaphore was successfully created
398  if(semaphore->p != NULL)
399  return TRUE;
400  else
401  return FALSE;
402 }
403 
404 
405 /**
406  * @brief Delete a semaphore object
407  * @param[in] semaphore Pointer to the semaphore object
408  **/
409 
411 {
412  INT8U err;
413 
414  //Make sure the operating system is running
415  if(OSRunning == OS_TRUE)
416  {
417  //Properly dispose the specified semaphore
418  OSSemDel(semaphore->p, OS_DEL_ALWAYS, &err);
419  }
420 }
421 
422 
423 /**
424  * @brief Wait for the specified semaphore to be available
425  * @param[in] semaphore Pointer to the semaphore object
426  * @param[in] timeout Timeout interval
427  * @return The function returns TRUE if the semaphore is available. FALSE is
428  * returned if the timeout interval elapsed
429  **/
430 
432 {
433  INT8U err;
434  INT16U n;
435 
436  //Wait until the semaphore is available or the timeout interval elapses
437  if(timeout == 0)
438  {
439  //Non-blocking call
440  if(OSSemAccept(semaphore->p) > 0)
441  err = OS_ERR_NONE;
442  else
443  err = OS_ERR_TIMEOUT;
444  }
445  else if(timeout == INFINITE_DELAY)
446  {
447  //Infinite timeout period
448  OSSemPend(semaphore->p, 0, &err);
449  }
450  else
451  {
452  //Convert milliseconds to system ticks
453  timeout = OS_MS_TO_SYSTICKS(timeout);
454 
455  //Loop until the assigned time period has elapsed
456  do
457  {
458  //The maximum timeout is 65535 clock ticks
459  n = MIN(timeout, 65535);
460  //Wait for the specified time interval
461  OSSemPend(semaphore->p, n, &err);
462  //Decrement timeout value
463  timeout -= n;
464 
465  //Check timeout value
466  } while(err == OS_ERR_TIMEOUT && timeout > 0);
467  }
468 
469  //Check whether the specified semaphore is available
470  if(err == OS_ERR_NONE)
471  return TRUE;
472  else
473  return FALSE;
474 }
475 
476 
477 /**
478  * @brief Release the specified semaphore object
479  * @param[in] semaphore Pointer to the semaphore object
480  **/
481 
483 {
484  //Release the semaphore
485  OSSemPost(semaphore->p);
486 }
487 
488 
489 /**
490  * @brief Create a mutex object
491  * @param[in] mutex Pointer to the mutex object
492  * @return The function returns TRUE if the mutex was successfully
493  * created. Otherwise, FALSE is returned
494  **/
495 
497 {
498 #if 1
499  bool_t status;
500 
501  //Create an event object
502  status = osCreateEvent((OsEvent *) mutex);
503 
504  //Check whether the event object was successfully created
505  if(status)
506  {
507  //Set event
508  osSetEvent((OsEvent *) mutex);
509  }
510 
511  //Return status
512  return status;
513 #else
514  INT8U err;
515 
516  //Create a mutex
517  mutex->p = OSMutexCreate(10, &err);
518 
519  //Check whether the mutex was successfully created
520  if(mutex->p != NULL && err == OS_ERR_NONE)
521  return TRUE;
522  else
523  return FALSE;
524 #endif
525 }
526 
527 
528 /**
529  * @brief Delete a mutex object
530  * @param[in] mutex Pointer to the mutex object
531  **/
532 
533 void osDeleteMutex(OsMutex *mutex)
534 {
535 #if 1
536  //Delete event object
537  osDeleteEvent((OsEvent *) mutex);
538 #else
539  INT8U err;
540 
541  //Make sure the operating system is running
542  if(OSRunning == OS_TRUE)
543  {
544  //Properly dispose the specified mutex
545  OSMutexDel(mutex->p, OS_DEL_ALWAYS, &err);
546  }
547 #endif
548 }
549 
550 
551 /**
552  * @brief Acquire ownership of the specified mutex object
553  * @param[in] mutex Pointer to the mutex object
554  **/
555 
557 {
558 #if 1
559  //Wait for event
561 #else
562  INT8U err;
563 
564  //Obtain ownership of the mutex object
565  OSMutexPend(mutex->p, 0, &err);
566 #endif
567 }
568 
569 
570 /**
571  * @brief Release ownership of the specified mutex object
572  * @param[in] mutex Pointer to the mutex object
573  **/
574 
576 {
577 #if 1
578  //Set event
579  osSetEvent((OsEvent *) mutex);
580 #else
581  //Release ownership of the mutex object
582  OSMutexPost(mutex->p);
583 #endif
584 }
585 
586 
587 /**
588  * @brief Retrieve system time
589  * @return Number of milliseconds elapsed since the system was last started
590  **/
591 
593 {
594  systime_t time;
595 
596  //Get current tick count
597  time = OSTimeGet();
598 
599  //Convert system ticks to milliseconds
600  return OS_SYSTICKS_TO_MS(time);
601 }
602 
603 
604 /**
605  * @brief Allocate a memory block
606  * @param[in] size Bytes to allocate
607  * @return A pointer to the allocated memory block or NULL if
608  * there is insufficient memory available
609  **/
610 
611 void *osAllocMem(size_t size)
612 {
613  void *p;
614 
615  //Enter critical section
617  //Allocate a memory block
618  p = malloc(size);
619  //Leave critical section
621 
622  //Debug message
623  TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n", size, (uintptr_t) p);
624 
625  //Return a pointer to the newly allocated memory block
626  return p;
627 }
628 
629 
630 /**
631  * @brief Release a previously allocated memory block
632  * @param[in] p Previously allocated memory block to be freed
633  **/
634 
635 void osFreeMem(void *p)
636 {
637  //Make sure the pointer is valid
638  if(p != NULL)
639  {
640  //Debug message
641  TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
642 
643  //Enter critical section
645  //Free memory block
646  free(p);
647  //Leave critical section
649  }
650 }
uint16_t priority
Definition: dns_common.h:219
uint32_t systime_t
Definition: compiler_port.h:44
void osSwitchTask(void)
Yield control to the next task.
void osResumeAllTasks(void)
Resume scheduler activity.
char char_t
Definition: compiler_port.h:41
bool_t osCreateEvent(OsEvent *event)
Create an event object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
INT8U prio
Definition: os_port_ucos2.h:78
uint32_t time
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
Debugging facilities.
uint8_t p
Definition: ndp.h:295
bool_t osCreateSemaphore(OsSemaphore *semaphore, uint_t count)
Create a semaphore object.
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
RTOS abstraction layer (Micrium uC/OS-II)
void osDeleteSemaphore(OsSemaphore *semaphore)
Delete a semaphore object.
void * osAllocMem(size_t size)
Allocate a memory block.
Event object.
void osDeleteEvent(OsEvent *event)
Delete an event object.
#define TRUE
Definition: os_port.h:48
bool_t osCreateStaticTask(OsTask *task, const char_t *name, OsTaskCode taskCode, void *param, void *stack, size_t stackSize, int_t priority)
Create a static task.
Definition: os_port_ucos2.c:80
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseSemaphore(OsSemaphore *semaphore)
Release the specified semaphore object.
void osStartKernel(void)
Start kernel.
Definition: os_port_ucos2.c:60
void osDeleteTask(OsTask *task)
Delete a task.
Task object.
signed int int_t
Definition: compiler_port.h:42
char_t name[]
#define OS_MS_TO_SYSTICKS(n)
#define INFINITE_DELAY
Definition: os_port.h:72
RTOS abstraction layer.
OS_EVENT * p
Definition: os_port_ucos2.h:98
#define MIN(a, b)
Definition: os_port.h:60
systime_t osGetSystemTime(void)
Retrieve system time.
void(* OsTaskCode)(void *param)
Task routine.
OS_FLAG_GRP * p
Definition: os_port_ucos2.h:88
void osFreeMem(void *p)
Release a previously allocated memory block.
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
void osInitKernel(void)
Kernel initialization.
Definition: os_port_ucos2.c:46
unsigned int uint_t
Definition: compiler_port.h:43
#define OS_SYSTICKS_TO_MS(n)
#define PRIuSIZE
Definition: compiler_port.h:72
Mutex object.
void osSuspendAllTasks(void)
Suspend scheduler activity.
uint8_t n
bool_t osWaitForSemaphore(OsSemaphore *semaphore, systime_t timeout)
Wait for the specified semaphore to be available.
OsTask * osCreateTask(const char_t *name, OsTaskCode taskCode, void *param, size_t stackSize, int_t priority)
Create a new task.
Semaphore object.
#define FALSE
Definition: os_port.h:44
void osDelayTask(systime_t delay)
Delay routine.
int bool_t
Definition: compiler_port.h:47
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
#define TRACE_DEBUG(...)
Definition: debug.h:98