os_port_embos.c
Go to the documentation of this file.
1 /**
2  * @file os_port_embos.c
3  * @brief RTOS abstraction layer (Segger embOS)
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_embos.h"
36 #include "debug.h"
37 
38 //Forward declaration of functions
39 void osIdleTaskHook(void);
40 
41 //Variables
42 static OS_TASK *tcbTable[OS_PORT_MAX_TASKS];
43 static void *stkTable[OS_PORT_MAX_TASKS];
44 
45 
46 /**
47  * @brief Kernel initialization
48  **/
49 
50 void osInitKernel(void)
51 {
52  //Initialize tables
53  memset(tcbTable, 0, sizeof(tcbTable));
54  memset(stkTable, 0, sizeof(stkTable));
55 
56  //Disable interrupts
57  OS_IncDI();
58  //Kernel initialization
59  OS_InitKern();
60  //Hardware initialization
61  OS_InitHW();
62 }
63 
64 
65 /**
66  * @brief Start kernel
67  **/
68 
69 void osStartKernel(void)
70 {
71  //Start the scheduler
72  OS_Start();
73 }
74 
75 
76 /**
77  * @brief Create a static task
78  * @param[out] task Pointer to the task structure
79  * @param[in] name A name identifying the task
80  * @param[in] taskCode Pointer to the task entry function
81  * @param[in] param A pointer to a variable to be passed to the task
82  * @param[in] stack Pointer to the stack
83  * @param[in] stackSize The initial size of the stack, in words
84  * @param[in] priority The priority at which the task should run
85  * @return The function returns TRUE if the task was successfully
86  * created. Otherwise, FALSE is returned
87  **/
88 
90  void *param, void *stack, size_t stackSize, int_t priority)
91 {
92  //Create a new task
93  OS_CreateTaskEx(task, name, priority, taskCode,
94  stack, stackSize * sizeof(uint_t), 1, param);
95 
96  //The task was successfully created
97  return TRUE;
98 }
99 
100 
101 /**
102  * @brief Create a new task
103  * @param[in] name A name identifying the task
104  * @param[in] taskCode Pointer to the task entry function
105  * @param[in] param A pointer to a variable to be passed to the task
106  * @param[in] stackSize The initial size of the stack, in words
107  * @param[in] priority The priority at which the task should run
108  * @return If the function succeeds, the return value is a pointer to the
109  * new task. If the function fails, the return value is NULL
110  **/
111 
113  void *param, size_t stackSize, int_t priority)
114 {
115  uint_t i;
116  OS_TASK *task;
117  void *stack;
118 
119  //Enter critical section
121 
122  //Loop through TCB table
123  for(i = 0; i < OS_PORT_MAX_TASKS; i++)
124  {
125  //Check whether the current entry is free
126  if(tcbTable[i] == NULL)
127  break;
128  }
129 
130  //Any entry available in the table?
131  if(i < OS_PORT_MAX_TASKS)
132  {
133  //Allocate a memory block to hold the task's control block
134  task = osAllocMem(sizeof(OS_TASK));
135 
136  //Successful memory allocation?
137  if(task != NULL)
138  {
139  //Allocate a memory block to hold the task's stack
140  stack = osAllocMem(stackSize * sizeof(uint_t));
141 
142  //Successful memory allocation?
143  if(stack != NULL)
144  {
145  //Create a new task
146  OS_CreateTaskEx(task, name, priority, taskCode,
147  stack, stackSize * sizeof(uint_t), 1, param);
148 
149  //Save TCB base address
150  tcbTable[i] = task;
151  //Save stack base address
152  stkTable[i] = stack;
153  }
154  else
155  {
156  osFreeMem(task);
157  //Memory allocation failed
158  task = NULL;
159  }
160  }
161  }
162  else
163  {
164  //Memory allocation failed
165  task = NULL;
166  }
167 
168  //Leave critical section
170 
171  //Return task pointer
172  return task;
173 }
174 
175 
176 /**
177  * @brief Delete a task
178  * @param[in] task Pointer to the task to be deleted
179  **/
180 
181 void osDeleteTask(OsTask *task)
182 {
183  //Delete the specified task
184  OS_TerminateTask(task);
185 }
186 
187 
188 /**
189  * @brief Delay routine
190  * @param[in] delay Amount of time for which the calling task should block
191  **/
192 
194 {
195  //Delay the task for the specified duration
196  OS_Delay(OS_MS_TO_SYSTICKS(delay));
197 }
198 
199 
200 /**
201  * @brief Yield control to the next task
202  **/
203 
204 void osSwitchTask(void)
205 {
206  //Not implemented
207 }
208 
209 
210 /**
211  * @brief Suspend scheduler activity
212  **/
213 
215 {
216  //Make sure the operating system is running
217  if(OS_IsRunning())
218  {
219  //Suspend scheduler activity
220  OS_SuspendAllTasks();
221  }
222 }
223 
224 
225 /**
226  * @brief Resume scheduler activity
227  **/
228 
230 {
231  //Make sure the operating system is running
232  if(OS_IsRunning())
233  {
234  //Resume scheduler activity
235  OS_ResumeAllSuspendedTasks();
236  }
237 }
238 
239 
240 /**
241  * @brief Create an event object
242  * @param[in] event Pointer to the event object
243  * @return The function returns TRUE if the event object was successfully
244  * created. Otherwise, FALSE is returned
245  **/
246 
248 {
249  //Create an event object
250  OS_EVENT_Create(event);
251 
252  //The event object was successfully created
253  return TRUE;
254 }
255 
256 
257 /**
258  * @brief Delete an event object
259  * @param[in] event Pointer to the event object
260  **/
261 
262 void osDeleteEvent(OsEvent *event)
263 {
264  //Make sure the operating system is running
265  if(OS_IsRunning())
266  {
267  //Properly dispose the event object
268  OS_EVENT_Delete(event);
269  }
270 }
271 
272 
273 /**
274  * @brief Set the specified event object to the signaled state
275  * @param[in] event Pointer to the event object
276  **/
277 
278 void osSetEvent(OsEvent *event)
279 {
280  //Set the specified event to the signaled state
281  OS_EVENT_Set(event);
282 }
283 
284 
285 /**
286  * @brief Set the specified event object to the nonsignaled state
287  * @param[in] event Pointer to the event object
288  **/
289 
290 void osResetEvent(OsEvent *event)
291 {
292  //Force the specified event to the nonsignaled state
293  OS_EVENT_Reset(event);
294 }
295 
296 
297 /**
298  * @brief Wait until the specified event is in the signaled state
299  * @param[in] event Pointer to the event object
300  * @param[in] timeout Timeout interval
301  * @return The function returns TRUE if the state of the specified object is
302  * signaled. FALSE is returned if the timeout interval elapsed
303  **/
304 
306 {
307  bool_t ret;
308 
309  //Wait until the specified event is in the signaled
310  //state or the timeout interval elapses
311  if(timeout == 0)
312  {
313  //Non-blocking call
314  ret = OS_EVENT_Get(event);
315  }
316  else if(timeout == INFINITE_DELAY)
317  {
318  //Infinite timeout period
319  OS_EVENT_Wait(event);
320  ret = TRUE;
321  }
322  else
323  {
324  //Wait until the specified event becomes set
325  ret = !OS_EVENT_WaitTimed(event, OS_MS_TO_SYSTICKS(timeout));
326  }
327 
328  //The return value specifies whether the event is set
329  return ret;
330 }
331 
332 
333 /**
334  * @brief Set an event object to the signaled state from an interrupt service routine
335  * @param[in] event Pointer to the event object
336  * @return TRUE if setting the event to signaled state caused a task to unblock
337  * and the unblocked task has a priority higher than the currently running task
338  **/
339 
341 {
342  //Set the specified event to the signaled state
343  OS_EVENT_Set(event);
344 
345  //The return value is not relevant
346  return FALSE;
347 }
348 
349 
350 /**
351  * @brief Create a semaphore object
352  * @param[in] semaphore Pointer to the semaphore object
353  * @param[in] count The maximum count for the semaphore object. This value
354  * must be greater than zero
355  * @return The function returns TRUE if the semaphore was successfully
356  * created. Otherwise, FALSE is returned
357  **/
358 
360 {
361  //Create a semaphore
362  OS_CreateCSema(semaphore, count);
363 
364  //The event object was successfully created
365  return TRUE;
366 }
367 
368 
369 /**
370  * @brief Delete a semaphore object
371  * @param[in] semaphore Pointer to the semaphore object
372  **/
373 
375 {
376  //Make sure the operating system is running
377  if(OS_IsRunning())
378  {
379  //Properly dispose the specified semaphore
380  OS_DeleteCSema(semaphore);
381  }
382 }
383 
384 
385 /**
386  * @brief Wait for the specified semaphore to be available
387  * @param[in] semaphore Pointer to the semaphore object
388  * @param[in] timeout Timeout interval
389  * @return The function returns TRUE if the semaphore is available. FALSE is
390  * returned if the timeout interval elapsed
391  **/
392 
394 {
395  bool_t ret;
396 
397  //Wait until the semaphore is available or the timeout interval elapses
398  if(timeout == 0)
399  {
400  //Non-blocking call
401  ret = OS_CSemaRequest(semaphore);
402  }
403  else if(timeout == INFINITE_DELAY)
404  {
405  //Infinite timeout period
406  OS_WaitCSema(semaphore);
407  ret = TRUE;
408  }
409  else
410  {
411  //Wait until the specified semaphore becomes available
412  ret = OS_WaitCSemaTimed(semaphore, OS_MS_TO_SYSTICKS(timeout));
413  }
414 
415  //The return value specifies whether the semaphore is available
416  return ret;
417 }
418 
419 
420 /**
421  * @brief Release the specified semaphore object
422  * @param[in] semaphore Pointer to the semaphore object
423  **/
424 
426 {
427  //Release the semaphore
428  OS_SignalCSema(semaphore);
429 }
430 
431 
432 /**
433  * @brief Create a mutex object
434  * @param[in] mutex Pointer to the mutex object
435  * @return The function returns TRUE if the mutex was successfully
436  * created. Otherwise, FALSE is returned
437  **/
438 
440 {
441  //Create a mutex
442  OS_CreateRSema(mutex);
443 
444  //The mutex was successfully created
445  return TRUE;
446 }
447 
448 
449 /**
450  * @brief Delete a mutex object
451  * @param[in] mutex Pointer to the mutex object
452  **/
453 
454 void osDeleteMutex(OsMutex *mutex)
455 {
456  //Make sure the operating system is running
457  if(OS_IsRunning())
458  {
459  //Properly dispose the specified mutex
460  OS_DeleteRSema(mutex);
461  }
462 }
463 
464 
465 /**
466  * @brief Acquire ownership of the specified mutex object
467  * @param[in] mutex Pointer to the mutex object
468  **/
469 
471 {
472  //Obtain ownership of the mutex object
473  OS_Use(mutex);
474 }
475 
476 
477 /**
478  * @brief Release ownership of the specified mutex object
479  * @param[in] mutex Pointer to the mutex object
480  **/
481 
483 {
484  //Release ownership of the mutex object
485  OS_Unuse(mutex);
486 }
487 
488 
489 /**
490  * @brief Retrieve system time
491  * @return Number of milliseconds elapsed since the system was last started
492  **/
493 
495 {
496  systime_t time;
497 
498  //Get current tick count
499  time = OS_GetTime32();
500 
501  //Convert system ticks to milliseconds
502  return OS_SYSTICKS_TO_MS(time);
503 }
504 
505 
506 /**
507  * @brief Allocate a memory block
508  * @param[in] size Bytes to allocate
509  * @return A pointer to the allocated memory block or NULL if
510  * there is insufficient memory available
511  **/
512 
513 void *osAllocMem(size_t size)
514 {
515  void *p;
516 
517  //Allocate a memory block
518  p = OS_malloc(size);
519 
520  //Debug message
521  TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n", size, (uintptr_t) p);
522 
523  //Return a pointer to the newly allocated memory block
524  return p;
525 }
526 
527 
528 /**
529  * @brief Release a previously allocated memory block
530  * @param[in] p Previously allocated memory block to be freed
531  **/
532 
533 void osFreeMem(void *p)
534 {
535  //Make sure the pointer is valid
536  if(p != NULL)
537  {
538  //Debug message
539  TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
540 
541  //Free memory block
542  OS_free(p);
543  }
544 }
uint16_t priority
Definition: dns_common.h:219
uint32_t systime_t
Definition: compiler_port.h:44
char char_t
Definition: compiler_port.h:41
uint32_t time
void osDeleteEvent(OsEvent *event)
Delete an event object.
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_embos.c:89
Debugging facilities.
void osDeleteSemaphore(OsSemaphore *semaphore)
Delete a semaphore object.
uint8_t p
Definition: ndp.h:295
bool_t osCreateSemaphore(OsSemaphore *semaphore, uint_t count)
Create a semaphore object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
Event object.
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
void osReleaseSemaphore(OsSemaphore *semaphore)
Release the specified semaphore object.
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
#define TRUE
Definition: os_port.h:48
systime_t osGetSystemTime(void)
Retrieve system time.
void osStartKernel(void)
Start kernel.
Definition: os_port_embos.c:69
Task object.
void osIdleTaskHook(void)
Idle task hook.
signed int int_t
Definition: compiler_port.h:42
char_t name[]
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
void osInitKernel(void)
Kernel initialization.
Definition: os_port_embos.c:50
#define OS_MS_TO_SYSTICKS(n)
OsTask * osCreateTask(const char_t *name, OsTaskCode taskCode, void *param, size_t stackSize, int_t priority)
Create a new task.
#define INFINITE_DELAY
Definition: os_port.h:72
RTOS abstraction layer.
bool_t osWaitForSemaphore(OsSemaphore *semaphore, systime_t timeout)
Wait for the specified semaphore to be available.
void osDeleteTask(OsTask *task)
Delete a task.
bool_t osCreateEvent(OsEvent *event)
Create an event object.
void osFreeMem(void *p)
Release a previously allocated memory block.
void(* OsTaskCode)(void *param)
Task routine.
#define OS_PORT_MAX_TASKS
RTOS abstraction layer (Segger embOS)
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
unsigned int uint_t
Definition: compiler_port.h:43
#define OS_SYSTICKS_TO_MS(n)
#define PRIuSIZE
Definition: compiler_port.h:72
Mutex object.
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void osResumeAllTasks(void)
Resume scheduler activity.
void osDelayTask(systime_t delay)
Delay routine.
void osSwitchTask(void)
Yield control to the next task.
void * osAllocMem(size_t size)
Allocate a memory block.
void osSuspendAllTasks(void)
Suspend scheduler activity.
Semaphore object.
#define FALSE
Definition: os_port.h:44
int bool_t
Definition: compiler_port.h:47
#define TRACE_DEBUG(...)
Definition: debug.h:98