os_port_threadx.c
Go to the documentation of this file.
1 /**
2  * @file os_port_threadx.c
3  * @brief RTOS abstraction layer (Azure RTOS ThreadX)
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_threadx.h"
37 #include "debug.h"
38 
39 //Global variable
40 static TX_INTERRUPT_SAVE_AREA
41 
42 //Default task parameters
44 {
45  NULL, //Task control block
46  NULL, //Stack
47  0, //Size of the stack
48  TX_MAX_PRIORITIES - 1 //Task priority
49 };
50 
51 
52 /**
53  * @brief Kernel initialization
54  **/
55 
56 void osInitKernel(void)
57 {
58  //Low-level initialization
59  _tx_initialize_low_level();
60 }
61 
62 
63 /**
64  * @brief Start kernel
65  **/
66 
67 void osStartKernel(void)
68 {
69  //Start the scheduler
70  tx_kernel_enter();
71 }
72 
73 
74 /**
75  * @brief Create a task
76  * @param[in] name NULL-terminated string identifying the task
77  * @param[in] taskCode Pointer to the task entry function
78  * @param[in] arg Argument passed to the task function
79  * @param[in] params Task parameters
80  * @return Task identifier referencing the newly created task
81  **/
82 
83 OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg,
84  const OsTaskParameters *params)
85 {
86  UINT status;
87  OsTaskId taskId;
88 
89  //Check parameters
90  if(params->tcb != NULL && params->stack != NULL)
91  {
92  //Create a new task
93  status = tx_thread_create(params->tcb, (CHAR *) name,
94  (OsTaskFunction) taskCode, (ULONG) arg, params->stack,
95  params->stackSize * sizeof(uint32_t), params->priority,
96  params->priority, 1, TX_AUTO_START);
97 
98  //Check whether the task was successfully created
99  if(status == TX_SUCCESS)
100  {
101  taskId = (OsTaskId) params->tcb;
102  }
103  else
104  {
105  taskId = OS_INVALID_TASK_ID;
106  }
107  }
108  else
109  {
110  //Invalid parameters
111  taskId = OS_INVALID_TASK_ID;
112  }
113 
114  //Return the handle referencing the newly created thread
115  return taskId;
116 }
117 
118 
119 /**
120  * @brief Delete a task
121  * @param[in] taskId Task identifier referencing the task to be deleted
122  **/
123 
124 void osDeleteTask(OsTaskId taskId)
125 {
126  //Delete the specified task
127  tx_thread_delete((TX_THREAD *) taskId);
128 }
129 
130 
131 /**
132  * @brief Delay routine
133  * @param[in] delay Amount of time for which the calling task should block
134  **/
135 
137 {
138  //Delay the task for the specified duration
139  tx_thread_sleep(OS_MS_TO_SYSTICKS(delay));
140 }
141 
142 
143 /**
144  * @brief Yield control to the next task
145  **/
146 
147 void osSwitchTask(void)
148 {
149  //Force a context switch
150  tx_thread_relinquish();
151 }
152 
153 
154 /**
155  * @brief Suspend scheduler activity
156  **/
157 
159 {
160  //Suspend all tasks
161  TX_DISABLE
162 }
163 
164 
165 /**
166  * @brief Resume scheduler activity
167  **/
168 
170 {
171  //Resume all tasks
172  TX_RESTORE
173 }
174 
175 
176 /**
177  * @brief Create an event object
178  * @param[in] event Pointer to the event object
179  * @return The function returns TRUE if the event object was successfully
180  * created. Otherwise, FALSE is returned
181  **/
182 
184 {
185  UINT status;
186 
187  //Create an event object
188  status = tx_event_flags_create(event, "EVENT");
189 
190  //Check whether the event was successfully created
191  if(status == TX_SUCCESS)
192  {
193  return TRUE;
194  }
195  else
196  {
197  return FALSE;
198  }
199 }
200 
201 
202 /**
203  * @brief Delete an event object
204  * @param[in] event Pointer to the event object
205  **/
206 
207 void osDeleteEvent(OsEvent *event)
208 {
209  //Make sure the event object is valid
210  if(event->tx_event_flags_group_id == TX_EVENT_FLAGS_ID)
211  {
212  //Properly dispose the event object
213  tx_event_flags_delete(event);
214  }
215 }
216 
217 
218 /**
219  * @brief Set the specified event object to the signaled state
220  * @param[in] event Pointer to the event object
221  **/
222 
223 void osSetEvent(OsEvent *event)
224 {
225  //Set the specified event to the signaled state
226  tx_event_flags_set(event, 1, TX_OR);
227 }
228 
229 
230 /**
231  * @brief Set the specified event object to the nonsignaled state
232  * @param[in] event Pointer to the event object
233  **/
234 
235 void osResetEvent(OsEvent *event)
236 {
237  ULONG actualFlags;
238 
239  //Force the specified event to the nonsignaled state
240  tx_event_flags_get(event, 1, TX_AND_CLEAR, &actualFlags, 0);
241 }
242 
243 
244 /**
245  * @brief Wait until the specified event is in the signaled state
246  * @param[in] event Pointer to the event object
247  * @param[in] timeout Timeout interval
248  * @return The function returns TRUE if the state of the specified object is
249  * signaled. FALSE is returned if the timeout interval elapsed
250  **/
251 
253 {
254  UINT status;
255  ULONG actualFlags;
256 
257  //Wait until the specified event is in the signaled state or the timeout
258  //interval elapses
259  if(timeout == INFINITE_DELAY)
260  {
261  //Infinite timeout period
262  status = tx_event_flags_get(event, 1, TX_OR_CLEAR, &actualFlags,
263  TX_WAIT_FOREVER);
264  }
265  else
266  {
267  //Wait until the specified event becomes set
268  status = tx_event_flags_get(event, 1, TX_OR_CLEAR, &actualFlags,
269  OS_MS_TO_SYSTICKS(timeout));
270  }
271 
272  //Check whether the specified event is set
273  if(status == TX_SUCCESS)
274  {
275  return TRUE;
276  }
277  else
278  {
279  return FALSE;
280  }
281 }
282 
283 
284 /**
285  * @brief Set an event object to the signaled state from an interrupt service routine
286  * @param[in] event Pointer to the event object
287  * @return TRUE if setting the event to signaled state caused a task to unblock
288  * and the unblocked task has a priority higher than the currently running task
289  **/
290 
292 {
293  //Set the specified event to the signaled state
294  tx_event_flags_set(event, 1, TX_OR);
295 
296  //The return value is not relevant
297  return FALSE;
298 }
299 
300 
301 /**
302  * @brief Create a semaphore object
303  * @param[in] semaphore Pointer to the semaphore object
304  * @param[in] count The maximum count for the semaphore object. This value
305  * must be greater than zero
306  * @return The function returns TRUE if the semaphore was successfully
307  * created. Otherwise, FALSE is returned
308  **/
309 
311 {
312  UINT status;
313 
314  //Create a semaphore object
315  status = tx_semaphore_create(semaphore, "SEMAPHORE", count);
316 
317  //Check whether the semaphore was successfully created
318  if(status == TX_SUCCESS)
319  {
320  return TRUE;
321  }
322  else
323  {
324  return FALSE;
325  }
326 }
327 
328 
329 /**
330  * @brief Delete a semaphore object
331  * @param[in] semaphore Pointer to the semaphore object
332  **/
333 
335 {
336  //Make sure the semaphore object is valid
337  if(semaphore->tx_semaphore_id == TX_SEMAPHORE_ID)
338  {
339  //Properly dispose the semaphore object
340  tx_semaphore_delete(semaphore);
341  }
342 }
343 
344 
345 /**
346  * @brief Wait for the specified semaphore to be available
347  * @param[in] semaphore Pointer to the semaphore object
348  * @param[in] timeout Timeout interval
349  * @return The function returns TRUE if the semaphore is available. FALSE is
350  * returned if the timeout interval elapsed
351  **/
352 
354 {
355  UINT status;
356 
357  //Wait until the semaphore is available or the timeout interval elapses
358  if(timeout == INFINITE_DELAY)
359  {
360  //Infinite timeout period
361  status = tx_semaphore_get(semaphore, TX_WAIT_FOREVER);
362  }
363  else
364  {
365  //Wait until the specified semaphore becomes available
366  status = tx_semaphore_get(semaphore, OS_MS_TO_SYSTICKS(timeout));
367  }
368 
369  //Check whether the specified semaphore is available
370  if(status == TX_SUCCESS)
371  {
372  return TRUE;
373  }
374  else
375  {
376  return FALSE;
377  }
378 }
379 
380 
381 /**
382  * @brief Release the specified semaphore object
383  * @param[in] semaphore Pointer to the semaphore object
384  **/
385 
387 {
388  //Release the semaphore
389  tx_semaphore_put(semaphore);
390 }
391 
392 
393 /**
394  * @brief Create a mutex object
395  * @param[in] mutex Pointer to the mutex object
396  * @return The function returns TRUE if the mutex was successfully
397  * created. Otherwise, FALSE is returned
398  **/
399 
401 {
402  UINT status;
403 
404  //Create a mutex object
405  status = tx_mutex_create(mutex, "MUTEX", TX_NO_INHERIT);
406 
407  //Check whether the mutex was successfully created
408  if(status == TX_SUCCESS)
409  {
410  return TRUE;
411  }
412  else
413  {
414  return FALSE;
415  }
416 }
417 
418 
419 /**
420  * @brief Delete a mutex object
421  * @param[in] mutex Pointer to the mutex object
422  **/
423 
424 void osDeleteMutex(OsMutex *mutex)
425 {
426  //Make sure the mutex object is valid
427  if(mutex->tx_mutex_id == TX_MUTEX_ID)
428  {
429  //Properly dispose the mutex object
430  tx_mutex_delete(mutex);
431  }
432 }
433 
434 
435 /**
436  * @brief Acquire ownership of the specified mutex object
437  * @param[in] mutex Pointer to the mutex object
438  **/
439 
441 {
442  //Obtain ownership of the mutex object
443  tx_mutex_get(mutex, TX_WAIT_FOREVER);
444 }
445 
446 
447 /**
448  * @brief Release ownership of the specified mutex object
449  * @param[in] mutex Pointer to the mutex object
450  **/
451 
453 {
454  //Release ownership of the mutex object
455  tx_mutex_put(mutex);
456 }
457 
458 
459 /**
460  * @brief Retrieve system time
461  * @return Number of milliseconds elapsed since the system was last started
462  **/
463 
465 {
466  systime_t time;
467 
468  //Get current tick count
469  time = tx_time_get();
470 
471  //Convert system ticks to milliseconds
472  return OS_SYSTICKS_TO_MS(time);
473 }
474 
475 
476 /**
477  * @brief Allocate a memory block
478  * @param[in] size Bytes to allocate
479  * @return A pointer to the allocated memory block or NULL if
480  * there is insufficient memory available
481  **/
482 
483 __weak_func void *osAllocMem(size_t size)
484 {
485  void *p;
486 
487  //Enter critical section
489  //Allocate a memory block
490  p = malloc(size);
491  //Leave critical section
493 
494  //Debug message
495  TRACE_DEBUG("Allocating %" PRIuSIZE " bytes at 0x%08" PRIXPTR "\r\n",
496  size, (uintptr_t) p);
497 
498  //Return a pointer to the newly allocated memory block
499  return p;
500 }
501 
502 
503 /**
504  * @brief Release a previously allocated memory block
505  * @param[in] p Previously allocated memory block to be freed
506  **/
507 
508 __weak_func void osFreeMem(void *p)
509 {
510  //Make sure the pointer is valid
511  if(p != NULL)
512  {
513  //Debug message
514  TRACE_DEBUG("Freeing memory at 0x%08" PRIXPTR "\r\n", (uintptr_t) p);
515 
516  //Enter critical section
518  //Free memory block
519  free(p);
520  //Leave critical section
522  }
523 }
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
const OsTaskParameters OS_TASK_DEFAULT_PARAMS
void(* OsTaskCode)(void *arg)
Task routine.
#define OS_SYSTICKS_TO_MS(n)
#define OS_MS_TO_SYSTICKS(n)
#define OS_INVALID_TASK_ID
uint32_t systime_t
System time.
thread_t * OsTaskId
Task identifier.
void osSwitchTask(void)
Yield control to the next task.
void osResumeAllTasks(void)
Resume scheduler activity.
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
bool_t osWaitForEvent(OsEvent *event, systime_t timeout)
Wait until the specified event is in the signaled state.
void osDeleteEvent(OsEvent *event)
Delete an event object.
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
void osReleaseSemaphore(OsSemaphore *semaphore)
Release the specified semaphore object.
__weak_func void * osAllocMem(size_t size)
Allocate a memory block.
void osDeleteSemaphore(OsSemaphore *semaphore)
Delete a semaphore object.
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osDelayTask(systime_t delay)
Delay routine.
__weak_func void osFreeMem(void *p)
Release a previously allocated memory block.
bool_t osWaitForSemaphore(OsSemaphore *semaphore, systime_t timeout)
Wait for the specified semaphore to be available.
OsTaskId osCreateTask(const char_t *name, OsTaskCode taskCode, void *arg, const OsTaskParameters *params)
Create a task.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
void osResetEvent(OsEvent *event)
Set the specified event object to the nonsignaled state.
bool_t osSetEventFromIsr(OsEvent *event)
Set an event object to the signaled state from an interrupt service routine.
void osDeleteTask(OsTaskId taskId)
Delete a task.
bool_t osCreateSemaphore(OsSemaphore *semaphore, uint_t count)
Create a semaphore object.
systime_t osGetSystemTime(void)
Retrieve system time.
void osSuspendAllTasks(void)
Suspend scheduler activity.
bool_t osCreateEvent(OsEvent *event)
Create an event object.
void osStartKernel(void)
Start kernel.
void osInitKernel(void)
Kernel initialization.
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
RTOS abstraction layer (Azure RTOS ThreadX)
VOID(* OsTaskFunction)(ULONG param)
Task function.
char_t name[]
Event object.
Mutex object.
Semaphore object.
Task parameters.