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