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