OCEOS Tutorials

From wiki
Jump to navigation Jump to search

Tutorials

Introduction

This section presents some typical real-time tasks and how they can be addressed using OCEOS.

Getting started

Section 9.5 provides guidance on how to structure an OCEOS application. The file asw.c provided with OCEOS is a simple example.

The directives to initialise and start OCEOS are:

  1. application_init – Initialise fixed data and start system timer(s)
  2. oceos_task_create - Create task setting priority, no of jobs, ..etc.
  3. oceos_init_finish – Initilise dynamic data area
  4. oceos_start – Start the scheduler and pass control to first task

After steps 1 to 4 above tasks implement application functionality. If mutexes, semaphores, or dataqs are required they are also created at step 2.

Note: it is mandatory to create the number of mutexes, semaphores, and dataqs declared otherwise oceos_init_finish() will return an error.

Tutorials

Tutorial 1 – Starting tasks

This exercise demonstrates starting tasks with different priorities.

  1. Two tasks, one higher priority (i.e. lower priority value), one lower priority (i.e. higher priority value. Each task allowed to have up to two concurrent jobs.
  2. Each task outputs a message when it starts, another message when it exits.
  3. Start OCEOS with the low priority task.
  4. This starts the high priority task and then exits.
  5. The high priority task starts the low priority tasks and exits.

For code example see below.

tut.h

 1 /*
 2  *********************************************************************************************************
 3  *                                                OCEOS
 4  *                                      Real-Time Operating System
 5  *                                                 for
 6  *                                        ARM Microcontroller
 7  *
 8  *                                   Example implementation of OCEOS
 9  *
10  *
11  *                               (c) Copyright 2021, O.C.E. Technology
12  *                                           All Rights Reserved
13  *
14  *
15  * Author:       jfk
16  ********************************************************************************************************
17  */
18 #ifndef TUT1_H_
19 #define TUT1_H_
20 
21 /* Sample Task names - all here start with t_ to help avoid name confusion */
22 enum TASK_NAME{
23     t_0,                 // High priority task
24     t_1                  // Low priority task
25 };
26 
27 char* nullPtr = "";			// Need pointer to pass to oceos_start
28 void (*nullFun)(void *);	// Null function
29 
30 /*
31  * APPLICATION FUNCTION DECLARATIONS
32  */
33 void fun0(void *);
34 void fun1(void *);
35 
36 #endif /* TUT1_H_ */

oceos_config.h

  1 /*
  2  *********************************************************************************************************
  3  *                                                OCEOS
  4  *                                      Real-Time Operating System
  5  *                                                 for
  6  *                                        ARM Microcontroller
  7  *
  8  *                                   Example implementation of OCEOS
  9  *
 10  *
 11  *                               (c) Copyright 2021, O.C.E. Technology
 12  *                                           All Rights Reserved
 13  *
 14  *
 15  * Author:       jfk
 16  ********************************************************************************************************
 17  */
 18 #ifndef INCLUDE_OCEOS_CONFIG_H_
 19 #define INCLUDE_OCEOS_CONFIG_H_
 20 
 21 // 1: Includes OCEOS main header file
 22 #include "oceos.h"
 23 //----------------------------------------------------------------------------
 24 // 2: Number of Log entries.
 25 #define NUMBER_OF_LOG_ENTRIES                   64 // 16 to 1024, default 64
 26 //----------------------------------------------------------------------------
 27 // 3: Number of tasks
 28 #define NUMBER_OF_TASKS                         2  // 1 to 255
 29 //----------------------------------------------------------------------------
 30 // 4: Number of ready queue entries, 0 to 254, see manual( MUST BE UPDATED BY USER);
 31 //    Defaults to number of tasks, as each task should have aa least one job;
 32 //    If Number of ready Q entries larger that number of total jobs => defaults to number of total jobs
 33 #define NUMBER_OF_READYQ_ENTRIES                NUMBER_OF_TASKS * 2
 34 //----------------------------------------------------------------------------
 35 // 5: Number of Mutexes
 36 #define NUMBER_OF_MUTEXES                       0  // 0 to 63
 37 //----------------------------------------------------------------------------
 38 // 6: Number of Semaphores
 39 #define NUMBER_OF_SEMAPHORES                    0  // 0 to 63
 40 //----------------------------------------------------------------------------
 41 // 7: Number of Data Qs
 42 #define NUMBER_OF_DATAQS                        0  // 0 to 63
 43 //----------------------------------------------------------------------------
 44 // 8: LOG data array size
 45 #define LOG_DATA_ARRAY_SIZE_U32S                0x88// Calculated value. Read manual
 46 //----------------------------------------------------------------------------
 47 // 9: FIXED data array size
 48 #define FIXED_DATA_ARRAY_SIZE_U32S              0x32// Calculated value. Read manual
 49 //----------------------------------------------------------------------------
 50 // 10: DYNAMIC data array size
 51 #define DYN_DATA_ARRAY_SIZE_U32S                0x33// Calculated value. Read manual
 52 //----------------------------------------------------------------------------
 53 // 11: Timed Actions
 54 #define NUMBER_OF_ACTION_ENTRIES                0  // User-modify field
 55 //----------------------------------------------------------------------------
 56 // 12: Log entries base 2
 57 #define CS_LOG_DEF_ENTRIES_BASE2                0
 58 //----------------------------------------------------------------------------
 59 // 13: OCEOS stack start Address
 60 #define OCEOS_STACK_START_ADDRESS               0
 61 //----------------------------------------------------------------------------
 62 // 14: OCEOS stack end address
 63 #define OCEOS_STACK_LOW_BOUND_ADDRESS           0
 64 //----------------------------------------------------------------------------
 65 /**
 66  * Target specific configurations
 67  */
 68 /*
 69  * ARM specific configurations
 70  */
 71 #ifdef __SAM3X8E__
 72 #ifndef BSP_SYSFREQ
 73 #define BSP_SYSFREQ 84                                      // ARM target frequency in Mhz
 74 #endif
 75 #endif
 76 #ifdef __SAMV71Q21__
 77 #ifndef BSP_SYSFREQ
 78 #define BSP_SYSFREQ 300                                     // ARM target frequency in Mhz
 79 #endif
 80 #endif
 81 #ifdef __VA41620__
 82 #ifndef BSP_SYSFREQ
 83 #define BSP_SYSFREQ 100                                      // ARM target frequency in Mhz
 84 #endif
 85 #endif
 86 //--------------------------------------------------------------------
 87 // User defined function to deal with system errors
 88 void oceos_on_error(void);
 89 //---------------------------------------------------------------------
 90 // User defined function to deal with log 2/3 full
 91 void oceos_on_full_log(void);
 92 //---------------------------------------------------------------------
 93 extern U32_t log_data[];
 94 extern U32_t fixed_data[];
 95 extern U32_t dynamic_data[];
 96 extern const unsigned int __oceos_bsp_sysfreq;
 97 /**
 98  * Initialize OCEOS with user configurations
 99  */
100 int application_init(void);
101 #endif /* INCLUDE_OCEOS_CONFIG_H_ */

oceos_config.c

  1 /*
  2  *********************************************************************************************************
  3  *                                                OCEOS
  4  *                                      Real-Time Operating System
  5  *                                                 for
  6  *                                        ARM Microcontroller
  7  *
  8  *                                   Example implementation of OCEOS
  9  *
 10  *
 11  *                               (c) Copyright 2021, O.C.E. Technology
 12  *                                           All Rights Reserved
 13  *
 14  *
 15  * Author:       jfk
 16  ********************************************************************************************************
 17  */
 18 #include <stdio.h>
 19 #include "oceos_config.h"
 20 
 21 /*
 22  * OCEOS INTERNAL DATA STORAGE
 23  *
 24  * This application defines arrays to hold OCEOS internal data.
 25  * The array sizes are provided by DMON by running "oceos info" command:</br>
 26  *  *Set all three arrays to guessed max zise, run application for the first time and exit.</br>
 27  *  *Run DMON command "oceos info" to get size for each array.</br>
 28  *  *Update array sizes below
 29  */
 30 U32_t log_data[LOG_DATA_ARRAY_SIZE_U32S];
 31 
 32 U32_t fixed_data[FIXED_DATA_ARRAY_SIZE_U32S] = {0};     // will be in data segment
 33 
 34 U32_t dynamic_data[DYN_DATA_ARRAY_SIZE_U32S];
 35 
 36 const unsigned int __oceos_bsp_sysfreq = BSP_SYSFREQ * 1000 * 1000;// TODO
 37 
 38 static BOOLE_t log_full_was_called = FALSE;
 39 
 40 /**
 41  * Must be defined if Application is using :
 42  *      Dataq with timeout
 43  *      Semaphore with timeout
 44  *      Timed Actions
 45  */
 46 /*
 47  * Set up the application configuration structure and pass it to oceos_init
 48  * (done this way the memory used for the structure is returned automatically)
 49  */
 50 
 51 int application_init(){
 52 
 53     /*
 54      * Create the application configuration structure
 55      */
 56     struct application_configuration           app_config = {0};
 57 
 58     /*
 59      * Fill in the application parameters
 60      */
 61     app_config.log_address                   = (adrs_t)log_data;              // required
 62     app_config.fixed_data_address            = (adrs_t)fixed_data;            // required
 63     app_config.dynamic_data_address          = (adrs_t)dynamic_data;          // required
 64 
 65     app_config.stack_start_address           = OCEOS_STACK_START_ADDRESS;     // 0 => no check
 66     app_config.stack_lower_bound_address     = OCEOS_STACK_LOW_BOUND_ADDRESS; // 0 => no check
 67 
 68     app_config.system_error_function         = &oceos_on_error;               // NULL => ignore
 69     app_config.log_full_function             = &oceos_on_full_log;            // NULL => ignore
 70     // used in setting up system log and fixed data array
 71     app_config.log_number_of_entries         = NUMBER_OF_LOG_ENTRIES;         // 0 => use default
 72 
 73     app_config.number_of_tasks               = NUMBER_OF_TASKS;               // >= 1
 74     app_config.number_of_readyQ_entries      = NUMBER_OF_READYQ_ENTRIES;      // 0 => calculate size
 75 
 76     app_config.number_of_mutexes             = NUMBER_OF_MUTEXES;
 77     app_config.number_of_counting_semaphores = NUMBER_OF_SEMAPHORES;
 78     app_config.number_of_data_queues         = NUMBER_OF_DATAQS;
 79 
 80     app_config.timed_actions_queue_size      = NUMBER_OF_ACTION_ENTRIES;
 81     app_config.CS_log_entries_base2          = CS_LOG_DEF_ENTRIES_BASE2;
 82     app_config.use_oceos_system_time         = TRUE;
 83 
 84     // initialise OCEOS
 85     enum DIRECTIVE_STATUS status;
 86     status = oceos_init(app_config);
 87 
 88     if (SUCCESSFUL == status) {
 89         return 1;
 90     } else {
 91         printf("\n oceos_init failure\n");
 92         return -1;
 93     }   // else
 94 }   // application_init()
 95 /**
 96  * User to implement in case of system error;
 97  * Comment it out if not used and set field system_error_function in app_config to NULL
 98  */
 99 void oceos_on_error() {
100   return;
101 }
102 /**
103  * User to implement in case of system log is 2/3 full;
104  * Comment it out if not used and set field log_full_function in app_config to NULL
105  */
106 void oceos_on_full_log(){
107   log_full_was_called = TRUE;
108   return;
109 }


tut1.c

 1 /*
 2  *********************************************************************************************************
 3  *                                                OCEOS
 4  *                                      Real-Time Operating System
 5  *                                                 for
 6  *                                        ARM Microcontroller
 7  *
 8  *                                   Example implementation of OCEOS
 9  *
10  *
11  *                               (c) Copyright 2021, O.C.E. Technology
12  *                                           All Rights Reserved
13  *
14  *
15  * Author:       jfk
16  ********************************************************************************************************
17  */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include "tut1.h"                        // application header
21 #include "oceos_config.h"                // OCEOS header
22 
23 int main(void) {
24   int status;
25 
26   /*
27    * Initialise the application configuration and OCEOS
28    *
29    * This application function creates the application configuration
30    * and passes it to oceos_init(), which initialises the fixed data
31    * and enables the system log
32    */
33   if (!application_init()) {
34     //LOG
35     return -1;
36   }
37 
38   // Create Main task to
39   if (oceos_task_create(t_0,// taskID, used as index, must be in range 0 to 254
40                         100,// priority,  must be in range 1 to 254, lower value is higher priority
41                         100,	// threshold, must be in range 1 to task priority
42                         2,				// jobs_max, must be in range 1 to 15
43                         0,// FALSE -> floating point hardware not used by task
44                         1,				// FALSE -> task initially not enabled
45                         fun0,			// main body of task
46                         nullFun,		// task end function
47                         0,// time_deadline, must finish no later than this after start, 0 => ignore
48                         0	// minimum time expected between start requests, 0 => no restriction
49                         ) != SUCCESSFUL)
50     return 1;
51 
52   if (oceos_task_create(t_1, 200, 200, 2, 0, 1, fun1, nullFun, 0, 0)
53       != SUCCESSFUL)
54     return 2;
55 
56   /*
57    * Finish initialising OCEOS and setting up the fixed data
58    */
59   status = oceos_init_finish();
60   if (SUCCESSFUL != status) {
61     return 3;
62   }   // if
63 
64   /*
65    * Start OCEOS scheduling
66    *
67    * The OCEOS fixed data provides all the information required.
68    *
69    * If a valid task is specified, it is started and passed the pointer.
70    * Otherwise the system is put in sleep mode
71    */
72   status = oceos_start(fixed_data, t_1, (void*) nullPtr);	// Start OCEOS with lower prioroty task
73   return status;
74 }   // main
75 
76 /*
77  * Application code functions, functions declared in asw.h
78  */
79 void fun0(void *ptr) {
80   printf("Entered high priority task\n");
81   oceos_task_start(t_1, ptr);
82   printf("Leaving high priority task\n");
83   return;
84 }   // fun0()
85 
86 void fun1(void *ptr) {
87   printf("Entered low priority task\n");
88   oceos_task_start(t_0, ptr);
89   printf("Leaving low priority task\n");
90   return;
91 }   // fun1()

Tutorial 2 – Using a mutex

This exercise will familiarise the developer with the use a mutexes.

  1. Two tasks as before.
  2. One mutex. Note the priority ceiling of the mutex..
  3. Both tasks output message when they get the mutex and when they return it
  4. Start OCEOS with the low priority task
  5. This grabs mutex, then starts high priority task
  6. Low priority task returns mutex then exits
  7. High priority task returns mutex, start low priority task and exits

For code example see example below:

  1 /*
  2  *********************************************************************************************************
  3  *                                                OCEOS
  4  *                                      Real-Time Operating System
  5  *                                                 for
  6  *                                        ARM Microcontroller
  7  *
  8  *                                   Example implementation of OCEOS
  9  *
 10  *
 11  *                               (c) Copyright 2021, O.C.E. Technology
 12  *                                           All Rights Reserved
 13  *
 14  *
 15  * Author:       jfk
 16  ********************************************************************************************************
 17  */
 18 #include <stdio.h>
 19 #include <stdlib.h>
 20 #include "tut2.h"                        // application header
 21 
 22 /* N.B.  Application header is included first */
 23 #include "oceos_config.h"                // OCEOS header for this application
 24 #include "mutex.h"
 25 
 26 int main(void) {
 27   int status;
 28 
 29   /*
 30    * Initialise the application configuration and OCEOS
 31    *
 32    * This application function creates the application configuration
 33    * and passes it to oceos_init(), which initialises the fixed data
 34    * and enables the system log
 35    */
 36   if (!application_init()) {
 37     //LOG
 38     return -1;
 39   }
 40 
 41   // Create Main task to
 42   if (oceos_task_create(t_0,// taskID, used as index, must be in range 0 to 254
 43                         100,// priority,  must be in range 1 to 254, lower value is higher priority
 44                         100,	// threshold, must be in range 1 to task priority
 45                         2,				// jobs_max, must be in range 1 to 15
 46                         0,// FALSE -> floating point hardware not used by task
 47                         1,				// FALSE -> task initially not enabled
 48                         fun0,			// main body of task
 49                         nullFun,		// task end function
 50                         0,// time_deadline, must finish no later than this after start, 0 => ignore
 51                         0	// minimum time expected between start requests, 0 => no restriction
 52                         ) != SUCCESSFUL)
 53     return 1;
 54 
 55   if (oceos_task_create(t_1, 200, 200, 2, 0, 1, fun1, nullFun, 0, 0)
 56       != SUCCESSFUL)
 57     return 2;
 58 
 59   if (oceos_mutex_create(m_0, 100) != SUCCESSFUL)	// Create mutex with ceiling of highest priority task using it
 60     return 3;
 61 
 62   /*
 63    * Finish initialising OCEOS and setting up the fixed data
 64    */
 65   status = oceos_init_finish();
 66   if (SUCCESSFUL != status) {
 67     return 4;
 68   }   // if
 69 
 70   /*
 71    * Start OCEOS scheduling
 72    *
 73    * The OCEOS fixed data provides all the information required.
 74    *
 75    * If a valid task is specified, it is started and passed the pointer.
 76    * Otherwise the system is put in sleep mode
 77    */
 78   status = oceos_start(fixed_data, t_1, (void*) nullPtr);	// Start OCEOS with lower prioroty task
 79   return status;
 80 }   // main
 81 
 82 /*
 83  * Application code functions, functions declared in asw.h
 84  */
 85 void fun0(void *ptr) {
 86   if (oceos_mutex_wait(m_0) != SUCCESSFUL) {
 87     printf("Error from high priority task getting mutex\n");
 88   } else {
 89     printf("high priority task got mutex\n");
 90   }
 91   oceos_task_start(t_1, ptr);	// Start lower priority task
 92 
 93   if (oceos_mutex_signal(m_0) != SUCCESSFUL) {
 94     printf("Error from high priority task releasing mutex\n");
 95   } else {
 96     printf("High priority task released mutex\n");
 97   }
 98   return;
 99 }   // fun0()
100 
101 void fun1(void *ptr) {
102   if (oceos_mutex_wait(m_0) != SUCCESSFUL) {
103     printf("Error from low priority task getting mutex\n");
104   } else {
105     printf("Low priority task got mutex\n");
106   }
107   oceos_task_start(t_0, ptr);	// Start higher priority task
108 
109   if (oceos_mutex_signal(m_0) != SUCCESSFUL) {
110     printf("Error from low priority task releasing mutex\n");
111   } else {
112     printf("Low priority task released mutex\n");
113   }
114   return;
115 }   // fun1()

Tutorial 3 – Using Semaphores

Semaphores can be used to synchronise task actions as in this exercise.

  1. Three tasks this time, one high priority and the other two with the same lower priority
  2. Two counting semaphores, one initially 0, one initially 4, called ‘items’ and ‘spaces’
  3. First task starts second and third tasks
  4. Second task loops
    1. wait_restart spaces
    2. signal items
    3. Output ‘item done’ message
  5. Third task loops
    1. wait_restart items
    2. Output ‘got item’ message
    3. signal spaces

For code example see below:

  1 /*
  2  *********************************************************************************************************
  3  *                                                OCEOS
  4  *                                      Real-Time Operating System
  5  *                                                 for
  6  *                                        ARM Microcontroller
  7  *
  8  *                                   Example implementation of OCEOS
  9  *
 10  *
 11  *                               (c) Copyright 2021, O.C.E. Technology
 12  *                                           All Rights Reserved
 13  *
 14  *
 15  * Author:       jfk
 16  ********************************************************************************************************
 17  */
 18 #include <stdio.h>
 19 #include <stdlib.h>
 20 
 21 /* N.B.  Application header is included first */
 22 #include "oceos_config.h"                // OCEOS header for this application
 23 #include "tut3.h"                        // application header
 24 #include "semaphore.h"
 25 
 26 int main(void) {
 27   int status;
 28   /*
 29    * Initialise the application configuration and OCEOS
 30    *
 31    * This application function creates the application configuration
 32    * and passes it to oceos_init(), which initialises the fixed data
 33    * and enables the system log
 34    */
 35   if (!application_init()) {
 36     //LOG
 37     return -1;
 38   }
 39   // Create Main task to
 40   if (oceos_task_create(t_0,// taskID, used as index, must be in range 0 to 254
 41                         10,	// priority,  must be in range 1 to 254, lower value is higher priority
 42                         10,		// threshold, must be in range 1 to task priority
 43                         1,				// jobs_max, must be in range 1 to 15
 44                         0,// FALSE -> floating point hardware not used by task
 45                         1,				// FALSE -> task initially not enabled
 46                         fun0,			// main body of task
 47                         nullFun,		// task end function
 48                         0,// time_deadline, must finish no later than this after start, 0 => ignore
 49                         0	// minimum time expected between start requests, 0 => no restriction
 50                         ) != SUCCESSFUL)
 51     return 1;
 52 
 53   if (oceos_task_create(t_1, 100, 100, 1, 0, 1, fun1, nullFun, 0, 0)
 54       != SUCCESSFUL)
 55     return 2;
 56 
 57   if (oceos_task_create(t_2, 100, 100, 1, 0, 1, fun2, nullFun, 0, 0)
 58       != SUCCESSFUL)
 59     return 3;
 60 
 61   if (oceos_sem_create(items, 10, 0, 2, FALSE) != SUCCESSFUL)// items semaphore with max permits of 10, initial permits of 0, max jobs 2
 62     return 4;
 63 
 64   if (oceos_sem_create(spaces, 10, 4, 2, FALSE) != SUCCESSFUL)	// spaces semaphore with max permits of 10, initial permits of 4, max jobs 2
 65     return 4;
 66   /*
 67    * Finish initialising OCEOS and setting up the fixed data
 68    */
 69   status = oceos_init_finish();
 70   if (SUCCESSFUL != status) {
 71     return 6;
 72   }   // if
 73   /*
 74    * Start OCEOS scheduling
 75    *
 76    * The OCEOS fixed data provides all the information required.
 77    *
 78    * If a valid task is specified, it is started and passed the pointer.
 79    * Otherwise the system is put in sleep mode
 80    */
 81   status = oceos_start(fixed_data, t_0, (void*) nullPtr);	// Start OCEOS with task to start other tasks
 82   return status;
 83 }   // main
 84 
 85 /*
 86  * Application code functions, functions declared in asw.h
 87  */
 88 void fun0(void *ptr) {
 89   oceos_task_start(t_1, ptr);	// Start consumer task
 90   oceos_task_start(t_2, ptr);	// Start consumer task
 91 }   // fun0()
 92 
 93 void fun1(void *ptr) {
 94   while (1) {	// loop forever
 95     if (oceos_sem_wait_restart(items) != SUCCESSFUL) {
 96       printf("Error from task t_0 task waiting items\n");
 97     }
 98     printf("Got item\n");
 99     if (oceos_sem_signal(spaces) != SUCCESSFUL) {
100       printf("Error from task t_0 signalling spaces\n");
101     }
102   }
103 }   // fun0()
104 
105 void fun2(void *ptr) {
106   while (1) {	// loop forever
107     if (oceos_sem_wait_restart(spaces) != SUCCESSFUL) {
108       printf("Error from task t_1 task waiting spaces\n");
109     }
110     if (oceos_sem_signal(items) != SUCCESSFUL) {
111       printf("Error from task t_1 signalling items\n");
112     } else {
113       printf("Item done\n");
114     }
115   }
116   return;
117 }   // fun1()

Tutorial 4 – Timer interrupt starts task

This exercise introduces the use of timer interrupts.

  1. Create one task
  2. Set a timer to interrupt every 2 seconds
  3. Set timer handler to start task
  4. Task outputs message, then exits

For code example see below:

 1 /*
 2  *********************************************************************************************************
 3  *                                                OCEOS
 4  *                                      Real-Time Operating System
 5  *                                                 for
 6  *                                        ARM Microcontroller
 7  *
 8  *                                   Example implementation of OCEOS
 9  *
10  *
11  *                               (c) Copyright 2021, O.C.E. Technology
12  *                                           All Rights Reserved
13  *
14  *
15  * Author:       jfk
16  ********************************************************************************************************
17  */
18 #include <stdio.h>
19 #include <stdlib.h>
20 
21 /* N.B.  Application header is included first */
22 #include "oceos_config.h"                // OCEOS header for this application
23 #include "tut4.h"                        // application header
24 
25 volatile U32_t count_task_start = 0;
26 
27 int main(void) {
28   int status;
29   /*
30    * Initialise the application configuration and OCEOS
31    *
32    * This application function creates the application configuration
33    * and passes it to oceos_init(), which initialises the fixed data
34    * and enables the system log
35    */
36   if (!application_init()) {
37     //LOG
38     return -1;
39   }
40   // Create Main task to
41   if (oceos_task_create(t_0,// taskID, used as index, must be in range 0 to 254
42                         10,	// priority,  must be in range 1 to 254, lower value is higher priority
43                         10,		// threshold, must be in range 1 to task priority
44                         1,				// jobs_max, must be in range 1 to 15
45                         0,// FALSE -> floating point hardware not used by task
46                         1,				// FALSE -> task initially not enabled
47                         fun0,			// main body of task
48                         NULL,		// task end function
49                         0,// time_deadline, must finish no later than this after start, 0 => ignore
50                         0	// minimum time expected between start requests, 0 => no restriction
51                         ) != SUCCESSFUL)
52     return 1;
53 
54   if (oceos_task_create(t_1, 100, 100, 1, 0, 1, fun1, NULL, 0, 0)
55       != SUCCESSFUL)
56     return 2;
57   /*
58    * Finish initialising OCEOS and setting up the fixed data
59    */
60   status = oceos_init_finish();
61   if (SUCCESSFUL != status) {
62     return 3;
63   }   // if
64   /*
65    * Start OCEOS scheduling
66    *
67    * The OCEOS fixed data provides all the information required.
68    *
69    * If a valid task is specified, it is started and passed the pointer.
70    * Otherwise the system is put in sleep mode
71    */
72   status = oceos_start(fixed_data, t_0, NULL);		// Start OCEOS
73   return status;
74 }   // main
75 
76 /*
77  * Task 0 starting point
78  */
79 void fun0(void *ptr) {
80   timer_setup();
81 }   // fun0()
82 /**
83  * Task 1 starting point;
84  * Triggered from Timer IRQ handler
85  */
86 void fun1(void *ptr) {
87   printf("Task started : %u times \n", count_task_start);
88   count_task_start++;
89 }   // fun1()

Tutorial 5 – Using dataq with timed action

This exercise introduces the use of dataq with timed action.

  1. Create functions to be used by tasks
  2. Create one struct – pointer to these will be placed on queues
  3. Set timeout period T
  4. Create configuration structure with above configuration values for fields
  5. Initialize OCEOS using oceos_init()
  6. Create two tasks
  7. Create two data queues

For code example see below:

  1 /*
  2 ******************************************************************************
  3 *                                   OCEOS
  4 *                        Real-Time Operating System
  5 *                              for ARM/SPARC
  6 *                             Microcontroller
  7 *
  8 *                       Application Software Example
  9 *
 10 *
 11 *                    (c) Copyright 2022, O.C.E. Technology
 12 *                             All Rights Reserved
 13 *
 14 * Author:       jfk
 15 *
 16 * Purpose                : The test here involves creating two tasks with different priorities, 
 17 *						   and two data queues with timed action implimentation.
 18 *
 19 ******************************************************************************
 20 */
 21 /* N.B.  Application header is included first */
 22 #include "tut5.h"                        // application header
 23 
 24 struct data {
 25   int status;
 26   char *message;
 27 } test_data = {
 28     1,
 29     "Test Data",
 30 };
 31 int main(void) {
 32 
 33     /*
 34      * Initialise the application configuration and OCEOS
 35      *
 36      * This application function creates the application configuration
 37      * and passes it to oceos_init(), which initialises the fixed data
 38      * and enables the system log
 39      */
 40     if ( !application_init()) {
 41         //LOG
 42         printf("\nProblem\n");
 43         return -1;
 44     }
 45 
 46     enum DIRECTIVE_STATUS status;
 47     // Task 0: priority 10, threshold 10, max jobs 1, FP_used disabled,  initially_enabled TRUE, task start address t_consumer_task, start of task end function NULL, time_deadline 0, time_mininterstart 0
 48     status  = oceos_task_create(t_consumer, 10, 10, 1, 0, TASK_ENABLED,t_consumer_task, NULL, 0, 0);
 49     assert(SUCCESSFUL == status);
 50     // Task 1: priority 254, threshold 254, max jobs 1, FP_used disabled,  initially_enabled TRUE, task start address t_consumer_task, start of task end function NULL, time_deadline 0, time_mininterstart 0
 51     status  = oceos_task_create(t_producer, 254, 254, 1, 0, TASK_ENABLED,t_producer_task, NULL, 0, 0);
 52     assert(SUCCESSFUL == status);
 53 
 54     printf("\n Tasks created\n");
 55     // no counting semaphores, data queues or user defined traps
 56 
 57     if(SUCCESSFUL != status){
 58         // LOG
 59         printf("\nAbandoning, problem creating task, resulting return code: %u\n", status);
 60         return -1;
 61     }   // if
 62     // Creating Data 0, dataq_size 1, pen_q size 1, roll_over FALSE, use_timeout TRUE
 63     status = oceos_dataq_create(queue_0, N0, JOBS0, FALSE, TRUE);
 64     assert(SUCCESSFUL == status);
 65 	// Creating Data 1, dataq_size 1, pen_q size 1, roll_over FALSE, use_timeout TRUE
 66     status = oceos_dataq_create(queue_1, N1, JOBS1, FALSE, TRUE);
 67     assert(SUCCESSFUL == status);
 68     /*
 69      * Finish initialising OCEOS and setting up the fixed data
 70      */
 71     status = oceos_init_finish();
 72     assert(SUCCESSFUL == status);
 73     if(SUCCESSFUL != status){
 74         // LOG
 75         printf("\nAbandoning, problem ending OCEOS initialisation, resulting return code: %u\n", status);
 76         return -1;
 77     }   // if
 78     //1)  Action: Start OCEOS  with Task 1 as initial task, null input pointer
 79     status = oceos_start(fixed_data, t_producer, NULL);
 80 
 81     return status;                          // returned as an integer
 82 
 83 }   // function waits for specific time interval
 84 void test_wait(U32_t interval) {
 85   volatile U32_t start_time = oceos_time_sys_get32();
 86   volatile U32_t cur_time = 0;
 87   while(1) {
 88       cur_time = oceos_time_sys_get32();
 89       if ((cur_time - start_time) >= interval ) {
 90           break;
 91       }
 92   }
 93 }
 94 /*
 95  * Tasks
 96  */
 97 void t_consumer_task() {
 98   static int case_number = 0;
 99   if (case_number == 0) {
100       case_number++;
101       // 2)  Action: Task 1 attempts to start Task 0
102       // Check:  Task 0 has started, pre-empting Task 1
103       // a.  Check: entry message from Task 0
104       // b.  Check: queue_0 entries is 0
105       // c.  Check: queue_1 entries is 0
106       printf("t_consumer was started\n");
107       assert(0 == oceos_dataq_get_size(queue_0));
108       assert(0 == oceos_dataq_get_size(queue_1));
109 
110       // 3) Action: Task 0 does read_restart on queue_0
111       oceos_dataq_read_restart_timeout(queue_0, 0);
112   } else if (case_number == 1){
113       case_number++;
114       // 5) Action: Task 1 writes pointer to struct to queue_0
115       // Check:  Task 0 has started, pre-empting Task 1
116       // a.  Check: entry message from Task 0
117       // b.  Check: queue_0 entries count is 1
118       // c.  Check: queue_1 entries count is 0
119       printf("t_consumer was started\n");
120       assert(1 == oceos_dataq_get_size(queue_0));
121       assert(0 == oceos_dataq_get_size(queue_1));
122 
123       // 6) Action: Task 0 does read_restart on queue 0
124       // Check:  Task 0 has succeeded
125       // a.  Check: non-null pointer returned
126       // b.  Check: queue_0 entries count is 0
127       // c.  Check: queue_0 entries count is 0
128       assert(NULL != oceos_dataq_read_restart_timeout(queue_0, 0));
129       assert(0 == oceos_dataq_get_size(queue_0));
130       assert(0 == oceos_dataq_get_size(queue_1));
131 
132       // 7)    Action: Task 0 writes this pointer to queue_1
133       // Check:  Task 0 has succeeded
134       // a.  Check: queue_0 entries count is 0
135       // b.  Check: queue_1 entries count is 1
136       assert(SUCCESSFUL == oceos_dataq_write(queue_1, &test_data));
137       assert(0 == oceos_dataq_get_size(queue_0));
138       assert(1 == oceos_dataq_get_size(queue_1));
139 
140       // 8) Action: Task 0 does read_restart with timeout on queue_0
141       // Check:  Task 0 exits as queues_0 is empty
142       assert(NULL == oceos_dataq_read_restart_timeout(queue_0, TIME_OUT));
143   } else {
144       case_number++;
145       // 10)   Action: Task 1 loops for at least twice timeout period T
146       // Check:  Task 0 restarts on timeout, pre-empting Task 1
147       // a.  Check: entry message from Task 0
148       // b.  Check: queue_0 entries count is 0
149       // c.  Check: queue_1 entries count is 0
150       printf("t_consumer was started\n");
151       assert(0 == oceos_dataq_get_size(queue_0));
152       assert(0 == oceos_dataq_get_size(queue_1));
153 
154       // 11)    Action: Task 0 does read_continue on queue_0
155       // Check:  Task 0 has succeeded
156       // a.  Check: null pointer returned
157       // b.  Check: queue_0 entries count is 0
158       // c.  Check: queue_1 entries count is 0
159       assert(NULL == oceos_dataq_read_continue(queue_0));
160       assert(0 == oceos_dataq_get_size(queue_0));
161       assert(0 == oceos_dataq_get_size(queue_1));
162 
163       // 12)   Action: Task 0 exits
164       // Check:  Task 0 exit message
165       // a.  Check: queue_0 entries count is 0
166       // b.  Check: queue_1 entries count is 0
167       printf("t_consumer is exiting\n");
168       assert(0 == oceos_dataq_get_size(queue_0));
169       assert(0 == oceos_dataq_get_size(queue_1));
170       return;
171   }
172 }//END  t_consumer_task
173 
174 void t_producer_task() {
175   // 1)  Action: Start OCEOS  with Task 1 as initial task, null input pointer
176   // Check: Task 1 has started
177   // a.  Check: Starting message from Task 1
178   // b.  Check: queue_0 entries count is 0
179   // c.  Check: queue_0 capacity is as created
180   // d.  Check: queue_1 entries count is 0
181   // e.  Check: queue_1 capacity is as created
182   printf("t_producer was started\n");
183   assert(0 == oceos_dataq_get_size(queue_0));
184   assert(0 == oceos_dataq_get_size(queue_1));
185 
186   // 2)  Action: Task 1 attempts to start Task 0
187   assert(SUCCESSFUL == oceos_task_start(t_consumer, NULL));
188 
189   // 3) Action: Task 0 does read_restart on queue_0
190   // Check:  Task 0 exits as queue_0 is empty
191   // Check:  Task 1 continues
192   // a.  Check: continue message from Task 1
193   // b.  Check: queue_0 entries count is 0
194   // c.  Check: queue_1 entries count is 0
195   printf("t_producer continues \n");
196   assert(0 == oceos_dataq_get_size(queue_0));
197   assert(0 == oceos_dataq_get_size(queue_1));
198 
199   // 4) Action: Task 1 does read_continue on queue_1
200   // Check:   null pointer returned
201   assert(NULL == oceos_dataq_read_continue(queue_1));
202 
203   // 5) Action: Task 1 writes pointer to struct to queue_0
204   assert(SUCCESSFUL == oceos_dataq_write(queue_0, &test_data));
205 
206   // 8) Action: Task 0 does read_restart with timeout on queue_0
207   // Check:  Task 0 exits as queues_0 is empty
208   // Check:  Task 1 continues
209   // a.  Check: continue message from Task 1
210   // b.  Check: queue_0 entries count is 0
211   // c.  Check: queue_1 entries count is 1
212   printf("t_producer continues \n");
213   assert(0 == oceos_dataq_get_size(queue_0));
214   assert(1 == oceos_dataq_get_size(queue_1));
215 
216   // 9) Action: Task 1 does read_continue on queue_1
217   // Check:  Non-null pointer returned
218   // a.  Check: pointer to same struct
219   // b.  Check: queue_0 entries count is 0
220   // c.  Check: queue_1 entries count is 0
221   struct data *temp_data = oceos_dataq_read_continue(queue_1);
222   assert(NULL != temp_data);
223   assert(test_data.message == temp_data->message);
224   assert(0 == oceos_dataq_get_size(queue_0));
225   assert(0 == oceos_dataq_get_size(queue_1));
226 
227   // 10)   Action: Task 1 loops for at least three timeout period
228   // Check:  Task 0 restarts on timeout, pre-empting Task 1
229   test_wait(TIME_OUT * 3);
230 
231   // 13)    Action: Task 1 loop resumes and terminates
232   // Check:  Task 1 loop ended message
233   //assert(i == TIME_OUT * 100);
234 
235   //Task 1 writes pointer to struct on queue_1
236   assert(SUCCESSFUL == oceos_dataq_write(queue_1, &test_data));
237   // Data q size check
238   assert(1 == oceos_dataq_get_size(queue_1));
239   // Task 1 does read restart on queue_1
240   assert(NULL != oceos_dataq_read_restart(queue_1));
241   // Data q size check
242   assert(0 == oceos_dataq_get_size(queue_1));
243   //Task 1 writes pointer to struct on queue_1
244   assert(SUCCESSFUL == oceos_dataq_write(queue_1, &test_data));
245   // Data q size check
246   assert(1 == oceos_dataq_get_size(queue_1));
247   // Data q clear
248   assert(0 == oceos_dataq_clear(queue_1));
249   // Data q size check
250   assert(0 == oceos_dataq_get_size(queue_1));
251   // Data pending q size check
252   assert(0 == oceos_dataq_penq_get_size(queue_1));
253 
254   // 14)   Action: Task 1 terminates
255    // Check:  Task 1 exit message
256    printf("t_producer is exiting\n");
257 
258 
259 
260   // 15) Action: CPU placed in sleep mode
261   // Check:  Sleep mode starting message
262   assert(SUCCESSFUL == oceos_exit());
263   return;
264 }