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