os_port_freertos.c
Go to the documentation of this file.
1 /**
2  * @file os_port_freertos.c
3  * @brief RTOS abstraction layer (FreeRTOS)
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 "os_port.h"
36 #include "os_port_freertos.h"
37 #include "debug.h"
38 
39 
40 /**
41  * @brief Kernel initialization
42  **/
43 
44 void osInitKernel(void)
45 {
46 }
47 
48 
49 /**
50  * @brief Start kernel
51  **/
52 
53 void osStartKernel(void)
54 {
55  //Start the scheduler
56  vTaskStartScheduler();
57 }
58 
59 
60 /**
61  * @brief Create a new task
62  * @param[in] name A name identifying the task
63  * @param[in] taskCode Pointer to the task entry function
64  * @param[in] param A pointer to a variable to be passed to the task
65  * @param[in] stackSize The initial size of the stack, in words
66  * @param[in] priority The priority at which the task should run
67  * @return If the function succeeds, the return value is a pointer to the
68  * new task. If the function fails, the return value is NULL
69  **/
70 
72  void *param, size_t stackSize, int_t priority)
73 {
74  portBASE_TYPE status;
75  TaskHandle_t task = NULL;
76 
77  //Create a new task
78  status = xTaskCreate((TaskFunction_t) taskCode, name, stackSize, param,
79  priority, &task);
80 
81  //Check whether the task was successfully created
82  if(status == pdPASS)
83  return task;
84  else
85  return NULL;
86 }
87 
88 
89 /**
90  * @brief Delete a task
91  * @param[in] task Pointer to the task to be deleted
92  **/
93 
94 void osDeleteTask(OsTask *task)
95 {
96  //Delete the specified task
97  vTaskDelete((TaskHandle_t) task);
98 }
99 
100 
101 /**
102  * @brief Delay routine
103  * @param[in] delay Amount of time for which the calling task should block
104  **/
105 
107 {
108  //Delay the task for the specified duration
109  vTaskDelay(OS_MS_TO_SYSTICKS(delay));
110 }
111 
112 
113 /**
114  * @brief Yield control to the next task
115  **/
116 
117 void osSwitchTask(void)
118 {
119  //Force a context switch
120  taskYIELD();
121 }
122 
123 
124 /**
125  * @brief Suspend scheduler activity
126  **/
127 
129 {
130  //Make sure the operating system is running
131  if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
132  {
133  //Suspend all tasks
134  vTaskSuspendAll();
135  }
136 }
137 
138 
139 /**
140  * @brief Resume scheduler activity
141  **/
142 
144 {
145  //Make sure the operating system is running
146  if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
147  {
148  //Resume all tasks
149  xTaskResumeAll();
150  }
151 }
152 
153 
154 /**
155  * @brief Create an event object
156  * @param[in] event Pointer to the event object
157  * @return The function returns TRUE if the event object was successfully
158  * created. Otherwise, FALSE is returned
159  **/
160 
162 {
163 #if (configSUPPORT_STATIC_ALLOCATION == 1)
164  //Create a binary semaphore
165  event->handle = xSemaphoreCreateBinaryStatic(&event->buffer);
166 #else
167  //Create a binary semaphore
168  event->handle = xSemaphoreCreateBinary();
169 #endif
170 
171  //Check whether the returned handle is valid
172  if(event->handle != NULL)
173  return TRUE;
174  else
175  return FALSE;
176 }
177 
178 
179 /**
180  * @brief Delete an event object
181  * @param[in] event Pointer to the event object
182  **/
183 
184 void osDeleteEvent(OsEvent *event)
185 {
186  //Make sure the handle is valid
187  if(event->handle != NULL)
188  {
189  //Properly dispose the event object
190  vSemaphoreDelete(event->handle);
191  }
192 }
193 
194 
195 /**
196  * @brief Set the specified event object to the signaled state
197  * @param[in] event Pointer to the event object
198  **/
199 
200 void osSetEvent(OsEvent *event)
201 {
202  //Set the specified event to the signaled state
203  xSemaphoreGive(event->handle);
204 }
205 
206 
207 /**
208  * @brief Set the specified event object to the nonsignaled state
209  * @param[in] event Pointer to the event object
210  **/
211 
212 void osResetEvent(OsEvent *event)
213 {
214  //Force the specified event to the nonsignaled state
215  xSemaphoreTake(event->handle, 0);
216 }
217 
218 
219 /**
220  * @brief Wait until the specified event is in the signaled state
221  * @param[in] event Pointer to the event object
222  * @param[in] timeout Timeout interval
223  * @return The function returns TRUE if the state of the specified object is
224  * signaled. FALSE is returned if the timeout interval elapsed
225  **/
226 
228 {
229  portBASE_TYPE ret;
230 
231  //Wait until the specified event is in the signaled state
232  if(timeout == INFINITE_DELAY)
233  {
234  //Infinite timeout period
235  ret = xSemaphoreTake(event->handle, portMAX_DELAY);
236  }
237  else
238  {
239  //Wait for the specified time interval
240  ret = xSemaphoreTake(event->handle, OS_MS_TO_SYSTICKS(timeout));
241  }
242 
243  //The return value tells whether the event is set
244  return ret;
245 }
246 
247 
248 /**
249  * @brief Set an event object to the signaled state from an interrupt service routine
250  * @param[in] event Pointer to the event object
251  * @return TRUE if setting the event to signaled state caused a task to unblock
252  * and the unblocked task has a priority higher than the currently running task
253  **/
254 
256 {
257  portBASE_TYPE flag = FALSE;
258 
259  //Set the specified event to the signaled state
260  xSemaphoreGiveFromISR(event->handle, &flag);
261 
262  //A higher priority task has been woken?
263  return flag;
264 }
265 
266 
267 /**
268  * @brief Create a semaphore object
269  * @param[in] semaphore Pointer to the semaphore object
270  * @param[in] count The maximum count for the semaphore object. This value
271  * must be greater than zero
272  * @return The function returns TRUE if the semaphore was successfully
273  * created. Otherwise, FALSE is returned
274  **/
275 
277 {
278 #if (configSUPPORT_STATIC_ALLOCATION == 1)
279  //Create a semaphore
280  semaphore->handle = xSemaphoreCreateCountingStatic(count, count,
281  &semaphore->buffer);
282 #else
283  //Create a semaphore
284  semaphore->handle = xSemaphoreCreateCounting(count, count);
285 #endif
286 
287  //Check whether the returned handle is valid
288  if(semaphore->handle != NULL)
289  return TRUE;
290  else
291  return FALSE;
292 }
293 
294 
295 /**
296  * @brief Delete a semaphore object
297  * @param[in] semaphore Pointer to the semaphore object
298  **/
299 
301 {
302  //Make sure the handle is valid
303  if(semaphore->handle != NULL)
304  {
305  //Properly dispose the specified semaphore
306  vSemaphoreDelete(semaphore->handle);
307  }
308 }
309 
310 
311 /**
312  * @brief Wait for the specified semaphore to be available
313  * @param[in] semaphore Pointer to the semaphore object
314  * @param[in] timeout Timeout interval
315  * @return The function returns TRUE if the semaphore is available. FALSE is
316  * returned if the timeout interval elapsed
317  **/
318 
320 {
321  portBASE_TYPE ret;
322 
323  //Wait until the specified semaphore becomes available
324  if(timeout == INFINITE_DELAY)
325  {
326  //Infinite timeout period
327  ret = xSemaphoreTake(semaphore->handle, portMAX_DELAY);
328  }
329  else
330  {
331  //Wait for the specified time interval
332  ret = xSemaphoreTake(semaphore->handle, OS_MS_TO_SYSTICKS(timeout));
333  }
334 
335  //The return value tells whether the semaphore is available
336  return ret;
337 }
338 
339 
340 /**
341  * @brief Release the specified semaphore object
342  * @param[in] semaphore Pointer to the semaphore object
343  **/
344 
346 {
347  //Release the semaphore
348  xSemaphoreGive(semaphore->handle);
349 }
350 
351 
352 /**
353  * @brief Create a mutex object
354  * @param[in] mutex Pointer to the mutex object
355  * @return The function returns TRUE if the mutex was successfully
356  * created. Otherwise, FALSE is returned
357  **/
358 
360 {
361 #if (configSUPPORT_STATIC_ALLOCATION == 1)
362  //Create a mutex object
363  mutex->handle = xSemaphoreCreateMutexStatic(&mutex->buffer);
364 #else
365  //Create a mutex object
366  mutex->handle = xSemaphoreCreateMutex();
367 #endif
368 
369  //Check whether the returned handle is valid
370  if(mutex->handle != NULL)
371  return TRUE;
372  else
373  return FALSE;
374 }
375 
376 
377 /**
378  * @brief Delete a mutex object
379  * @param[in] mutex Pointer to the mutex object
380  **/
381 
382 void osDeleteMutex(OsMutex *mutex)
383 {
384  //Make sure the handle is valid
385  if(mutex->handle != NULL)
386  {
387  //Properly dispose the specified mutex
388  vSemaphoreDelete(mutex->handle);
389  }
390 }
391 
392 
393 /**
394  * @brief Acquire ownership of the specified mutex object
395  * @param[in] mutex Pointer to the mutex object
396  **/
397 
399 {
400  //Obtain ownership of the mutex object
401  xSemaphoreTake(mutex->handle, portMAX_DELAY);
402 }
403 
404 
405 /**
406  * @brief Release ownership of the specified mutex object
407  * @param[in] mutex Pointer to the mutex object
408  **/
409 
411 {
412  //Release ownership of the mutex object
413  xSemaphoreGive(mutex->handle);
414 }
415 
416 
417 /**
418  * @brief Retrieve system time
419  * @return Number of milliseconds elapsed since the system was last started
420  **/
421 
423 {
424  systime_t time;
425 
426  //Get current tick count
427  time = xTaskGetTickCount();
428 
429  //Convert system ticks to milliseconds
430  return OS_SYSTICKS_TO_MS(time);
431 }
432 
433 
434 /**
435  * @brief Allocate a memory block
436  * @param[in] size Bytes to allocate
437  * @return A pointer to the allocated memory block or NULL if
438  * there is insufficient memory available
439  **/
440 
441 void *osAllocMem(size_t size)
442 {
443  void *p;
444 
445  //Allocate a memory block
446  p = pvPortMalloc(size);
447 
448  //Debug message
449  TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n", size, (uintptr_t) p);
450 
451  //Return a pointer to the newly allocated memory block
452  return p;
453 }
454 
455 
456 /**
457  * @brief Release a previously allocated memory block
458  * @param[in] p Previously allocated memory block to be freed
459  **/
460 
461 void osFreeMem(void *p)
462 {
463  //Make sure the pointer is valid
464  if(p != NULL)
465  {
466  //Debug message
467  TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
468 
469  //Free memory block
470  vPortFree(p);
471  }
472 }
473 
474 
475 #if 0
476 
477 /**
478  * @brief FreeRTOS stack overflow hook
479  **/
480 
481 void vApplicationStackOverflowHook(xTaskHandle pxTask, char *pcTaskName)
482 {
483  (void) pcTaskName;
484  (void) pxTask;
485 
486  taskDISABLE_INTERRUPTS();
487  while(1);
488 }
489 
490 
491 /**
492  * @brief Trap FreeRTOS errors
493  **/
494 
495 void vAssertCalled(const char *pcFile, unsigned long ulLine)
496 {
497  volatile unsigned long ul = 0;
498 
499  (void) pcFile;
500  (void) ulLine;
501 
502  taskENTER_CRITICAL();
503 
504  //Set ul to a non-zero value using the debugger to step out of this function
505  while(ul == 0)
506  {
507  portNOP();
508  }
509 
510  taskEXIT_CRITICAL();
511 }
512 
513 #endif
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
void osDeleteEvent(OsEvent *event)
Delete an event object.
int bool_t
Definition: compiler_port.h:49
void osDeleteTask(OsTask *task)
Delete a task.
signed int int_t
Definition: compiler_port.h:44
void osSuspendAllTasks(void)
Suspend scheduler activity.
SemaphoreHandle_t handle
uint8_t p
Definition: ndp.h:298
#define TRUE
Definition: os_port.h:50
Event object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
OsTask * osCreateTask(const char_t *name, OsTaskCode taskCode, void *param, size_t stackSize, int_t priority)
Create a new task.
char_t name[]
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
systime_t osGetSystemTime(void)
Retrieve system time.
Semaphore object.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
#define FALSE
Definition: os_port.h:46
void osStartKernel(void)
Start kernel.
void osInitKernel(void)
Kernel initialization.
Task object.
#define OS_SYSTICKS_TO_MS(n)
#define OS_MS_TO_SYSTICKS(n)
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
RTOS abstraction layer (FreeRTOS)
void osDeleteSemaphore(OsSemaphore *semaphore)
Delete a semaphore object.
void osResumeAllTasks(void)
Resume scheduler activity.
void osFreeMem(void *p)
Release a previously allocated memory block.
Mutex object.
#define TRACE_DEBUG(...)
Definition: debug.h:106
char char_t
Definition: compiler_port.h:43
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
uint32_t time
SemaphoreHandle_t handle
void(* OsTaskCode)(void *param)
Task routine.
bool_t osCreateEvent(OsEvent *event)
Create an event object.
void osReleaseSemaphore(OsSemaphore *semaphore)
Release the specified semaphore object.
void osSwitchTask(void)
Yield control to the next task.
#define PRIuSIZE
Definition: compiler_port.h:78
unsigned int uint_t
Definition: compiler_port.h:45
bool_t osWaitForSemaphore(OsSemaphore *semaphore, systime_t timeout)
Wait for the specified semaphore to be available.
void * osAllocMem(size_t size)
Allocate a memory block.
uint16_t priority
Definition: dns_common.h:221
RTOS abstraction layer.
void osDelayTask(systime_t delay)
Delay routine.
uint32_t systime_t
Definition: compiler_port.h:46
bool_t osCreateSemaphore(OsSemaphore *semaphore, uint_t count)
Create a semaphore object.
Debugging facilities.
#define INFINITE_DELAY
Definition: os_port.h:74
SemaphoreHandle_t handle