os_port_px5.c
Go to the documentation of this file.
1 /**
2  * @file os_port_px5.c
3  * @brief RTOS abstraction layer (PX5)
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 "os_port.h"
36 #include "os_port_px5.h"
37 #include "debug.h"
38 
39 //Pthread start routine
40 typedef void *(*PthreadTaskCode) (void *param);
41 
42 //Default task parameters
44 {
45  NULL, //Stack
46  0, //Size of the stack
47  0 //Task priority
48 };
49 
50 //Forward declaration of functions
51 void *osAllocMemCallback(u_int type, u_long size);
52 void osFreeMemCallback(u_int type, void *p);
53 
54 
55 /**
56  * @brief Kernel initialization
57  **/
58 
59 void osInitKernel(void)
60 {
61  //Start RTOS
62  px5_pthread_start(1, NULL, 0);
63 
64  //Setup the memory manager allocate and release memory routines
65  px5_pthread_memory_manager_set(osAllocMemCallback, osFreeMemCallback);
66 }
67 
68 
69 /**
70  * @brief Start kernel
71  **/
72 
73 void osStartKernel(void)
74 {
75  //Not implemented
76 }
77 
78 
79 /**
80  * @brief Create a task
81  * @param[in] name NULL-terminated string identifying the task
82  * @param[in] taskCode Pointer to the task entry function
83  * @param[in] arg Argument passed to the task function
84  * @param[in] params Task parameters
85  * @return Task identifier referencing the newly created task
86  **/
87 
88 OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg,
89  const OsTaskParameters *params)
90 {
91  int_t ret;
92  px5_pthread_t thread;
93  px5_pthread_attr_t threadAttr;
94 
95  //Set thread attributes
96  ret = pthread_attr_init(&threadAttr);
97 
98  //Check status code
99  if(ret == PX5_SUCCESS)
100  {
101  //Static allocation?
102  if(params->stack != NULL)
103  {
104  //Specify the stack address
105  ret = px5_pthread_attr_setstackaddr(&threadAttr, params->stack);
106  }
107  }
108 
109  //Check status code
110  if(ret == PX5_SUCCESS)
111  {
112  //Specify the size of the stack
113  ret = px5_pthread_attr_setstacksize(&threadAttr,
114  params->stackSize * sizeof(uint32_t));
115  }
116 
117  //Check status code
118  if(ret == PX5_SUCCESS)
119  {
120  //Specify the priority of the task
121  ret = px5_pthread_attr_setpriority(&threadAttr, params->priority);
122  }
123 
124  //Create a new thread
125  ret = px5_pthread_create(&thread, &threadAttr, (PthreadTaskCode) taskCode,
126  arg);
127 
128  //Return a pointer to the newly created thread
129  if(ret == PX5_SUCCESS)
130  {
131  return (OsTaskId) thread;
132  }
133  else
134  {
135  return OS_INVALID_TASK_ID;
136  }
137 }
138 
139 
140 /**
141  * @brief Delete a task
142  * @param[in] taskId Task identifier referencing the task to be deleted
143  **/
144 
145 void osDeleteTask(OsTaskId taskId)
146 {
147  //Delete the calling thread?
148  if(taskId == OS_SELF_TASK_ID)
149  {
150  //Kill ourselves
151  px5_pthread_exit(NULL);
152  }
153  else
154  {
155  //Delete the specified thread
156  pthread_cancel(taskId);
157  }
158 }
159 
160 
161 /**
162  * @brief Delay routine
163  * @param[in] delay Amount of time for which the calling task should block
164  **/
165 
167 {
168  //Delay the task for the specified duration
169  px5_pthread_tick_sleep(OS_MS_TO_SYSTICKS(delay));
170 }
171 
172 
173 /**
174  * @brief Yield control to the next task
175  **/
176 
177 void osSwitchTask(void)
178 {
179  //Force a context switch
180  px5_sched_yield();
181 }
182 
183 
184 /**
185  * @brief Suspend scheduler activity
186  **/
187 
189 {
190  //Not implemented
191 }
192 
193 
194 /**
195  * @brief Resume scheduler activity
196  **/
197 
199 {
200  //Not implemented
201 }
202 
203 
204 /**
205  * @brief Create an event object
206  * @param[in] event Pointer to the event object
207  * @return The function returns TRUE if the event object was successfully
208  * created. Otherwise, FALSE is returned
209  **/
210 
212 {
213  int_t ret;
214 
215  //Create a semaphore object
216  ret = px5_sem_init(event, 0, 0);
217 
218  //Check whether the semaphore was successfully created
219  if(ret == PX5_SUCCESS)
220  {
221  return TRUE;
222  }
223  else
224  {
225  return FALSE;
226  }
227 }
228 
229 
230 /**
231  * @brief Delete an event object
232  * @param[in] event Pointer to the event object
233  **/
234 
235 void osDeleteEvent(OsEvent *event)
236 {
237  //Properly dispose the event object
238  px5_sem_destroy(event);
239 }
240 
241 
242 /**
243  * @brief Set the specified event object to the signaled state
244  * @param[in] event Pointer to the event object
245  **/
246 
247 void osSetEvent(OsEvent *event)
248 {
249  //Set the specified event to the signaled state
250  px5_sem_post(event);
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  int_t ret;
262 
263  //Force the specified event to the nonsignaled state
264  do
265  {
266  //Decrement the semaphore's count by one
267  ret = px5_sem_trywait(event);
268 
269  //Check status
270  } while(ret == PX5_SUCCESS);
271 }
272 
273 
274 /**
275  * @brief Wait until the specified event is in the signaled state
276  * @param[in] event Pointer to the event object
277  * @param[in] timeout Timeout interval
278  * @return The function returns TRUE if the state of the specified object is
279  * signaled. FALSE is returned if the timeout interval elapsed
280  **/
281 
283 {
284  int_t ret;
285 
286  //Wait until the specified event is in the signaled state or the timeout
287  //interval elapses
288  if(timeout == 0)
289  {
290  //Non-blocking call
291  ret = px5_sem_trywait(event);
292  }
293  else if(timeout == INFINITE_DELAY)
294  {
295  //Infinite timeout period
296  ret = px5_sem_wait(event);
297  }
298  else
299  {
300  //Wait until the specified event becomes set
301  ret = px5_sem_timedwait(event, OS_MS_TO_SYSTICKS(timeout));
302  }
303 
304  //Check whether the specified event is set
305  if(ret == PX5_SUCCESS)
306  {
307  //Force the event back to the nonsignaled state
308  do
309  {
310  //Decrement the semaphore's count by one
311  ret = px5_sem_trywait(event);
312 
313  //Check status
314  } while(ret == PX5_SUCCESS);
315 
316  //The specified event is in the signaled state
317  return TRUE;
318  }
319  else
320  {
321  //The timeout interval elapsed
322  return FALSE;
323  }
324 }
325 
326 
327 /**
328  * @brief Set an event object to the signaled state from an interrupt service routine
329  * @param[in] event Pointer to the event object
330  * @return TRUE if setting the event to signaled state caused a task to unblock
331  * and the unblocked task has a priority higher than the currently running task
332  **/
333 
335 {
336  //Set the specified event to the signaled state
337  px5_sem_post(event);
338 
339  //The return value is not relevant
340  return FALSE;
341 }
342 
343 
344 /**
345  * @brief Create a semaphore object
346  * @param[in] semaphore Pointer to the semaphore object
347  * @param[in] count The maximum count for the semaphore object. This value
348  * must be greater than zero
349  * @return The function returns TRUE if the semaphore was successfully
350  * created. Otherwise, FALSE is returned
351  **/
352 
354 {
355  int_t ret;
356 
357  //Create a semaphore object
358  ret = px5_sem_init(semaphore, 0, count);
359 
360  //Check whether the semaphore was successfully created
361  if(ret == PX5_SUCCESS)
362  {
363  return TRUE;
364  }
365  else
366  {
367  return FALSE;
368  }
369 }
370 
371 
372 /**
373  * @brief Delete a semaphore object
374  * @param[in] semaphore Pointer to the semaphore object
375  **/
376 
378 {
379  //Properly dispose the semaphore object
380  px5_sem_destroy(semaphore);
381 }
382 
383 
384 /**
385  * @brief Wait for the specified semaphore to be available
386  * @param[in] semaphore Pointer to the semaphore object
387  * @param[in] timeout Timeout interval
388  * @return The function returns TRUE if the semaphore is available. FALSE is
389  * returned if the timeout interval elapsed
390  **/
391 
393 {
394  int_t ret;
395 
396  //Wait until the semaphore is available or the timeout interval elapses
397  if(timeout == 0)
398  {
399  //Non-blocking call
400  ret = px5_sem_trywait(semaphore);
401  }
402  else if(timeout == INFINITE_DELAY)
403  {
404  //Infinite timeout period
405  ret = px5_sem_wait(semaphore);
406  }
407  else
408  {
409  //Wait until the specified semaphore becomes available
410  ret = px5_sem_timedwait(semaphore, OS_MS_TO_SYSTICKS(timeout));
411  }
412 
413  //Check whether the specified semaphore is available
414  if(ret == PX5_SUCCESS)
415  {
416  return TRUE;
417  }
418  else
419  {
420  return FALSE;
421  }
422 }
423 
424 
425 /**
426  * @brief Release the specified semaphore object
427  * @param[in] semaphore Pointer to the semaphore object
428  **/
429 
431 {
432  //Release the semaphore
433  px5_sem_post(semaphore);
434 }
435 
436 
437 /**
438  * @brief Create a mutex object
439  * @param[in] mutex Pointer to the mutex object
440  * @return The function returns TRUE if the mutex was successfully
441  * created. Otherwise, FALSE is returned
442  **/
443 
445 {
446  int_t ret;
447 
448  //Create a mutex object
449  ret = px5_pthread_mutex_init(mutex, NULL);
450 
451  //Check whether the mutex was successfully created
452  if(ret == PX5_SUCCESS)
453  {
454  return TRUE;
455  }
456  else
457  {
458  return FALSE;
459  }
460 }
461 
462 
463 /**
464  * @brief Delete a mutex object
465  * @param[in] mutex Pointer to the mutex object
466  **/
467 
468 void osDeleteMutex(OsMutex *mutex)
469 {
470  //Properly dispose the mutex object
471  px5_pthread_mutex_destroy(mutex);
472 }
473 
474 
475 /**
476  * @brief Acquire ownership of the specified mutex object
477  * @param[in] mutex Pointer to the mutex object
478  **/
479 
481 {
482  //Obtain ownership of the mutex object
483  px5_pthread_mutex_lock(mutex);
484 }
485 
486 
487 /**
488  * @brief Release ownership of the specified mutex object
489  * @param[in] mutex Pointer to the mutex object
490  **/
491 
493 {
494  //Release ownership of the mutex object
495  px5_pthread_mutex_unlock(mutex);
496 }
497 
498 
499 /**
500  * @brief Retrieve system time
501  * @return Number of milliseconds elapsed since the system was last started
502  **/
503 
505 {
506  systime_t time;
507 
508  //Get current tick count
509  time = px5_pthread_ticks_get();
510 
511  //Convert system ticks to milliseconds
512  return OS_SYSTICKS_TO_MS(time);
513 }
514 
515 
516 /**
517  * @brief Allocate a memory block
518  * @param[in] size Bytes to allocate
519  * @return A pointer to the allocated memory block or NULL if
520  * there is insufficient memory available
521  **/
522 
523 __weak_func void *osAllocMem(size_t size)
524 {
525  void *p;
526 
527  //Enter critical section
529  //Allocate a memory block
530  p = malloc(size);
531  //Leave critical section
533 
534  //Debug message
535  TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n",
536  size, (uintptr_t) p);
537 
538  //Return a pointer to the newly allocated memory block
539  return p;
540 }
541 
542 
543 /**
544  * @brief Release a previously allocated memory block
545  * @param[in] p Previously allocated memory block to be freed
546  **/
547 
548 __weak_func void osFreeMem(void *p)
549 {
550  //Make sure the pointer is valid
551  if(p != NULL)
552  {
553  //Debug message
554  TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
555 
556  //Enter critical section
558  //Free memory block
559  free(p);
560  //Leave critical section
562  }
563 }
564 
565 
566 /**
567  * @brief Memory manager allocate function
568  * @param[in] type Unused parameter
569  * @param[in] size Bytes to allocate
570  * @return A pointer to the allocated memory block or NULL if
571  * there is insufficient memory available
572  **/
573 
574 void *osAllocMemCallback(u_int type, u_long size)
575 {
576  //Allocate a memory block
577  return osAllocMem(size);
578 }
579 
580 
581 /**
582  * @brief Memory manager release function
583  * @param[in] type Unused parameter
584  * @param[in] p Previously allocated memory block to be freed
585  **/
586 
587 void osFreeMemCallback(u_int type, void *p)
588 {
589  //Free memory block
590  osFreeMem(p);
591 }
592 
uint8_t type
Definition: coap_common.h:176
signed int int_t
Definition: compiler_port.h:49
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
uint32_t time
uint8_t p
Definition: ndp.h:300
RTOS abstraction layer.
#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_SELF_TASK_ID
#define OS_INVALID_TASK_ID
uint32_t systime_t
System time.
thread_t * OsTaskId
Task identifier.
void osFreeMemCallback(u_int type, void *p)
Memory manager release function.
Definition: os_port_px5.c:587
void osSwitchTask(void)
Yield control to the next task.
Definition: os_port_px5.c:177
void osResumeAllTasks(void)
Resume scheduler activity.
Definition: os_port_px5.c:198
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
Definition: os_port_px5.c:444
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
Definition: os_port_px5.c:282
void osDeleteEvent(OsEvent *event)
Delete an event object.
Definition: os_port_px5.c:235
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
Definition: os_port_px5.c:468
void osReleaseSemaphore(OsSemaphore *semaphore)
Release the specified semaphore object.
Definition: os_port_px5.c:430
const OsTaskParameters OS_TASK_DEFAULT_PARAMS
Definition: os_port_px5.c:43
__weak_func void * osAllocMem(size_t size)
Allocate a memory block.
Definition: os_port_px5.c:523
void osDeleteSemaphore(OsSemaphore *semaphore)
Delete a semaphore object.
Definition: os_port_px5.c:377
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
Definition: os_port_px5.c:480
void osDelayTask(systime_t delay)
Delay routine.
Definition: os_port_px5.c:166
__weak_func void osFreeMem(void *p)
Release a previously allocated memory block.
Definition: os_port_px5.c:548
bool_t osWaitForSemaphore(OsSemaphore *semaphore, systime_t timeout)
Wait for the specified semaphore to be available.
Definition: os_port_px5.c:392
OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg, const OsTaskParameters *params)
Create a task.
Definition: os_port_px5.c:88
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
Definition: os_port_px5.c:492
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
Definition: os_port_px5.c:259
void *(* PthreadTaskCode)(void *param)
Definition: os_port_px5.c:40
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
Definition: os_port_px5.c:334
void osDeleteTask(OsTaskId taskId)
Delete a task.
Definition: os_port_px5.c:145
bool_t osCreateSemaphore(OsSemaphore *semaphore, uint_t count)
Create a semaphore object.
Definition: os_port_px5.c:353
systime_t osGetSystemTime(void)
Retrieve system time.
Definition: os_port_px5.c:504
void osSuspendAllTasks(void)
Suspend scheduler activity.
Definition: os_port_px5.c:188
bool_t osCreateEvent(OsEvent *event)
Create an event object.
Definition: os_port_px5.c:211
void osStartKernel(void)
Start kernel.
Definition: os_port_px5.c:73
void * osAllocMemCallback(u_int type, u_long size)
Memory manager allocate function.
Definition: os_port_px5.c:574
void osInitKernel(void)
Kernel initialization.
Definition: os_port_px5.c:59
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
Definition: os_port_px5.c:247
RTOS abstraction layer (PX5)
char_t name[]
Event object.
Mutex object.
Semaphore object.
Task parameters.