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.

 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 *                                        GR716 Microcontroller
  7 *
  8 *                                  User Manual Section 11 Example 2
  9 *
 10 *                               (c) Copyright 2020, O.C.E. Technology
 11 *                                           All Rights Reserved
 12 *
 13 * File :        tut2.c
 14 ********************************************************************************************************
 15  */
 16 #include "tut2.h"                        // application header
 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 
 24 /*
 25  * Application specific
 26  *
 27  */
 28 extern U32_t   fixed_data[];     // will be in data segment. Should this be in oceos.h
 29 
 30 int main(void) {
 31 	int status;
 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         return -1;
 43     }
 44 
 45     // Create Main task to
 46     if ( oceos_task_create(
 47     		t_0,			// taskID, used as index, must be in range 0 to 254
 48     		100,			// priority,  must be in range 1 to 254, lower value is higher priority
 49 			100,			// threshold, must be in range 1 to task priority
 50 			2,				// jobs_max, must be in range 1 to 15
 51 			0,				// FALSE -> floating point hardware not used by task
 52 			1,				// FALSE -> task initially not enabled
 53 			fun0,			// main body of task
 54 			nullFun,		// task end function
 55 			0,				// time_deadline, must finish no later than this after start, 0 => ignore
 56 			0				// minimum time expected between start requests, 0 => no restriction
 57 			) != SUCCESSFUL )
 58     	return 1;
 59 
 60     if ( oceos_task_create(t_1,  200, 200, 2, 0, 1, fun1, nullFun, 0, 0)!= SUCCESSFUL )
 61     	return 2;
 62 
 63 	if ( oceos_mutex_create(m_0, 100)!= SUCCESSFUL )	// Create mutex with ceiling of highest priority task using it
 64 		return 3;
 65 
 66 
 67     /*
 68      * Finish initialising OCEOS and setting up the fixed data
 69      */
 70     status = oceos_init_finish();
 71     if(SUCCESSFUL != status){
 72         return 4;
 73     }   // if
 74 
 75     /*
 76      * Start OCEOS scheduling
 77      *
 78      * The OCEOS fixed data provides all the information required.
 79      *
 80      * If a valid task is specified, it is started and passed the pointer.
 81      * Otherwise the system is put in sleep mode
 82      */
 83     status = oceos_start(fixed_data, t_1, (void *)nullPtr);		// Start OCEOS with lower prioroty task
 84     return status;
 85 }   // main
 86 
 87 
 88 /*
 89  * Application code functions, functions declared in asw.h
 90  */
 91 void fun0(void * ptr){
 92 	if (oceos_mutex_wait(m_0) != SUCCESSFUL) {
 93 		printf ("Error from high priority task getting mutex\n");
 94 	} else {
 95 		printf ("high priority task got mutex\n");
 96 	}
 97     oceos_task_start(t_1,ptr);	// Start lower priority task
 98 
 99     if (oceos_mutex_signal(m_0) != SUCCESSFUL) {
100 		printf ("Error from high priority task releasing mutex\n");
101 	} else {
102 		printf ("High priority task released mutex\n");
103 	}
104 	return;
105 }   // fun0()
106 
107 
108 void fun1(void * ptr){
109 	if (oceos_mutex_wait(m_0) != SUCCESSFUL) {
110 		printf ("Error from low priority task getting mutex\n");
111 	} else {
112 		printf ("Low priority task got mutex\n");
113 	}
114     oceos_task_start(t_0,ptr);	// Start higher priority task
115 
116     if (oceos_mutex_signal(m_0) != SUCCESSFUL) {
117 		printf ("Error from low priority task releasing mutex\n");
118 	} else {
119 		printf ("Low priority task released mutex\n");
120 	}
121 	return;
122 }   // 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 *                                        GR716 Microcontroller
  7 *
  8 *                                  User Manual Section 11 Example 3
  9 *
 10 *                               (c) Copyright 2020, O.C.E. Technology
 11 *                                           All Rights Reserved
 12 *
 13 * File :        tut3.c
 14 ********************************************************************************************************
 15  */
 16 #include "tut3.h"                        // application header
 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 
 24 /*
 25  * Application specific
 26  *
 27  */
 28 extern U32_t   fixed_data[];     // will be in data segment. Should this be in oceos.h
 29 
 30 int main(void) {
 31 	int status;
 32     /*
 33      * Initialise the application configuration and OCEOS
 34      *
 35      * This application function creates the application configuration
 36      * and passes it to oceos_init(), which initialises the fixed data
 37      * and enables the system log
 38      */
 39     if ( !application_init()) {
 40         //LOG
 41         return -1;
 42     }
 43     // Create Main task to
 44     if ( oceos_task_create(
 45     		t_0,			// taskID, used as index, must be in range 0 to 254
 46     		10,			// priority,  must be in range 1 to 254, lower value is higher priority
 47 			10,			// threshold, must be in range 1 to task priority
 48 			1,				// jobs_max, must be in range 1 to 15
 49 			0,				// FALSE -> floating point hardware not used by task
 50 			1,				// FALSE -> task initially not enabled
 51 			fun0,			// main body of task
 52 			nullFun,		// task end function
 53 			0,				// time_deadline, must finish no later than this after start, 0 => ignore
 54 			0				// minimum time expected between start requests, 0 => no restriction
 55 			) != SUCCESSFUL )
 56     	return 1;
 57 
 58     if ( oceos_task_create(t_1,  100, 100, 1, 0, 1, fun1, nullFun, 0, 0)!= SUCCESSFUL )
 59     	return 2;
 60 
 61     if ( oceos_task_create(t_2,  100, 100, 1, 0, 1, fun2, nullFun, 0, 0)!= SUCCESSFUL )
 62     	return 3;
 63 
 64 	if ( oceos_sem_create(items, 10, 0, 2, TRUE) != SUCCESSFUL )	// items semaphore with max permits of 10, initial permits of 0, max jobs 2
 65 		return 4;
 66 
 67 	if ( oceos_sem_create(spaces, 10, 4, 2, TRUE) != SUCCESSFUL )	// spaces semaphore with max permits of 10, initial permits of 4, max jobs 2
 68 		return 4;
 69     /*
 70      * Finish initialising OCEOS and setting up the fixed data
 71      */
 72     status = oceos_init_finish();
 73     if(SUCCESSFUL != status){
 74         return 6;
 75     }   // if
 76     /*
 77      * Start OCEOS scheduling
 78      *
 79      * The OCEOS fixed data provides all the information required.
 80      *
 81      * If a valid task is specified, it is started and passed the pointer.
 82      * Otherwise the system is put in sleep mode
 83      */
 84     status = oceos_start(fixed_data, t_0, (void *)nullPtr);		// Start OCEOS with task to start other tasks
 85     return status;
 86 }   // main
 87 
 88 /*
 89  * Application code functions, functions declared in asw.h
 90  */
 91 void fun0(void * ptr){
 92     oceos_task_start(t_1,ptr);	// Start consumer task
 93     oceos_task_start(t_2,ptr);	// Start consumer task
 94 }   // fun0()
 95 
 96 void fun1(void * ptr){
 97     while (1){	// loop forever
 98     	if (oceos_sem_wait_restart_timeout(items,0) != SUCCESSFUL) {
 99     		printf ("Error from task t_0 task waiting items\n");
100     	}
101     	printf ("Got item\n");
102     	if (oceos_sem_signal(spaces) != SUCCESSFUL) {
103     		printf ("Error from task t_0 signalling spaces\n");
104     	}
105     }
106 }   // fun0()
107 
108 void fun2(void * ptr){
109     while (1){	// loop forever
110     	if (oceos_sem_wait_restart_timeout(spaces,0) != SUCCESSFUL) {
111     		printf ("Error from task t_1 task waiting spaces\n");
112     	}
113     	if (oceos_sem_signal(items) != SUCCESSFUL) {
114     		printf ("Error from task t_1 signalling items\n");
115     	} else {
116     		printf ("Item done\n");
117     	}
118     }
119 	return;
120 }   // 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 *                                        GR716 Microcontroller
  7 *
  8 *                                  User Manual Section 11 Example 4
  9 *
 10 *                               (c) Copyright 2020, O.C.E. Technology
 11 *                                           All Rights Reserved
 12 *
 13 * File :        tut4.c
 14 ********************************************************************************************************
 15  */
 16 #include "tut4.h"                        // application header
 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 <bcc/regs/gptimer.h>
 24 
 25 #include "oceos_interrupt.h"
 26 /*
 27  * Application specific
 28  *
 29  */
 30 extern U32_t   fixed_data[];     // will be in data segment. Should this be in oceos.h
 31 
 32 struct gptimer_regs *timer_regs = (void *)OCEOS_TA_TIMER_ADDRESS;
 33 struct gptimer_timer_regs *task_timer;
 34 struct bcc_isr_node node;
 35 
 36 int main(void) {
 37 	int status;
 38     /*
 39      * Initialise the application configuration and OCEOS
 40      *
 41      * This application function creates the application configuration
 42      * and passes it to oceos_init(), which initialises the fixed data
 43      * and enables the system log
 44      */
 45     if ( !application_init()) {
 46         //LOG
 47         return -1;
 48     }
 49     // Create Main task to
 50     if ( oceos_task_create(
 51     		t_0,			// taskID, used as index, must be in range 0 to 254
 52     		10,				// priority,  must be in range 1 to 254, lower value is higher priority
 53 			10,				// threshold, must be in range 1 to task priority
 54 			1,				// jobs_max, must be in range 1 to 15
 55 			0,				// FALSE -> floating point hardware not used by task
 56 			1,				// FALSE -> task initially not enabled
 57 			fun0,			// main body of task
 58 			nullFun,		// task end function
 59 			0,				// time_deadline, must finish no later than this after start, 0 => ignore
 60 			0				// minimum time expected between start requests, 0 => no restriction
 61 			) != SUCCESSFUL )
 62     	return 1;
 63 
 64     if ( oceos_task_create(t_1,  100, 100, 1, 0, 1, fun1, nullFun, 0, 0)!= SUCCESSFUL )
 65     	return 2;
 66     /*
 67      * Finish initialising OCEOS and setting up the fixed data
 68      */
 69     status = oceos_init_finish();
 70     if(SUCCESSFUL != status){
 71         return 3;
 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
 82     return status;
 83 }   // main
 84 
 85 /*
 86  * Application code functions, functions declared in asw.h
 87  */
 88 void fun0(void * ptr){
 89 	//set up timer and add handle
 90     task_timer = &timer_regs->timer[3];
 91     task_timer->ctrl = 0x0;
 92     enum DIRECTIVE_STATUS ret = 0;
 93 #ifdef TARGET_PM
 94     node.source = 9;
 95 #endif
 96 #ifdef TARGET_GR716
 97     node.source = 12;
 98 #endif
 99     node.handler = start_task;
100     node.arg = ptr;
101     ret = oceos_interrupt_handle_register(&node);
102     if (SUCCESSFUL != ret) {
103         printf("ERROR :: Failed to add ISR handler\n");
104     }
105 #ifdef TARGET_PM
106     bcc_int_unmask(9);
107 #endif
108 #ifdef TARGET_GR716
109     bcc_int_unmask(12);
110 #endif
111     task_timer->reload = 0x2DC6C0; // 3 seconds
112     task_timer->counter = 0x2DC6C0; // 3 seconds
113     task_timer->ctrl = GPTIMER_CTRL_EN | GPTIMER_CTRL_RS | GPTIMER_CTRL_IE;     // 0x1 | (1 << 1) | (1 << 3);
114 
115     // The interrupt shoud keep starting t_1 so this task can exit
116 }   // fun0()
117 /*
118  * Handler for timer interrupt
119  */
120 void start_task(void *arg, int source){
121   oceos_task_start(t_1,arg);
122 }
123 
124 void fun1(void * ptr){
125 	printf ("Task started\n");
126 }   // fun1()