OCEOS Tutorials
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:
- application_init – Initialise fixed data and start system timer(s)
 - oceos_task_create - Create task setting priority, no of jobs, ..etc.
 - oceos_init_finish – Initilise dynamic data area
 - 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.
- 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.
 - Each task outputs a message when it starts, another message when it exits.
 - Start OCEOS with the low priority task.
 - This starts the high priority task and then exits.
 - The high priority task starts the low priority tasks and exits.
 
For code example see below.
/*
*********************************************************************************************************
*                                                OCEOS
*                                      Real-Time Operating System
*                                                 for
*                                        GR716 Microcontroller
*
*                                  User Manual Section 11 Example
*
*                               (c) Copyright 2020, O.C.E. Technology
*                                           All Rights Reserved
*
* File :        tut1.c
********************************************************************************************************
 */
#include <stdio.h>
#include <stdlib.h>
#include "tut1.h"                        // application header
/* N.B.  Application header is included first */
#include "oceos_config.h"                // OCEOS header for this application
/*
 * Application specific
 *
 */
extern U32_t   fixed_data[];     // will be in data segment. Should this be in oceos.h
int main(void) {
	int status;
    /*
     * Initialise the application configuration and OCEOS
     *
     * This application function creates the application configuration
     * and passes it to oceos_init(), which initialises the fixed data
     * and enables the system log
     */
    if ( !application_init()) {
        //LOG
        return -1;
    }
    // Create Main task to
    if ( oceos_task_create(
    		t_0,			// taskID, used as index, must be in range 0 to 254
    		100,			// priority,  must be in range 1 to 254, lower value is higher priority
			100,			// threshold, must be in range 1 to task priority
			2,				// jobs_max, must be in range 1 to 15
			0,				// FALSE -> floating point hardware not used by task
			1,				// FALSE -> task initially not enabled
			fun0,			// main body of task
			nullFun,		// task end function
			0,				// time_deadline, must finish no later than this after start, 0 => ignore
			0				// minimum time expected between start requests, 0 => no restriction
			) != SUCCESSFUL )
    	return 1;
    if ( oceos_task_create(t_1,  200, 200, 2, 0, 1, fun1, nullFun, 0, 0)!= SUCCESSFUL )
    	return 2;
    /*
     * Finish initialising OCEOS and setting up the fixed data
     */
    status = oceos_init_finish();
    if(SUCCESSFUL != status){
        return 3;
    }   // if
    /*
     * Start OCEOS scheduling
     *
     * The OCEOS fixed data provides all the information required.
     *
     * If a valid task is specified, it is started and passed the pointer.
     * Otherwise the system is put in sleep mode
     */
    status = oceos_start(fixed_data, t_1, (void *)nullPtr);		// Start OCEOS with lower prioroty task
    return status;
}   // main
/*
 * Application code functions, functions declared in asw.h
 */
void fun0(void * ptr){
	printf ("Entered high priority task\n");
    oceos_task_start(t_1,ptr);
	printf ("Leaving high priority task\n");
	return;
}   // fun0()
void fun1(void * ptr){
	printf ("Entered low priority task\n");
    oceos_task_start(t_0,ptr);
	printf ("Leaving low priority task\n");
	return;
}   // fun1()
 </<nowiki>
=== Tutorial 2 – Using a mutex ===
<p>This exercise will familiarise the developer with the use a mutexes.</p>
#  Two tasks as before.
# One mutex. Note the priority ceiling of the mutex..
# Both tasks output message when they get the mutex and when they return it
# Start OCEOS with the low priority task
# This grabs mutex, then starts high priority task
# Low priority task returns mutex then exits
# High priority task returns mutex, start low priority task and exits
For code example see example below:
 <nowiki>
/*
*********************************************************************************************************
*                                                OCEOS
*                                      Real-Time Operating System
*                                                 for
*                                        GR716 Microcontroller
*
*                                  User Manual Section 11 Example 2
*
*                               (c) Copyright 2020, O.C.E. Technology
*                                           All Rights Reserved
*
* File :        tut2.c
********************************************************************************************************
 */
#include "tut2.h"                        // application header
#include <stdio.h>
#include <stdlib.h>
/* N.B.  Application header is included first */
#include "oceos_config.h"                // OCEOS header for this application
/*
 * Application specific
 *
 */
extern U32_t   fixed_data[];     // will be in data segment. Should this be in oceos.h
int main(void) {
	int status;
    /*
     * Initialise the application configuration and OCEOS
     *
     * This application function creates the application configuration
     * and passes it to oceos_init(), which initialises the fixed data
     * and enables the system log
     */
    if ( !application_init()) {
        //LOG
        return -1;
    }
    // Create Main task to
    if ( oceos_task_create(
    		t_0,			// taskID, used as index, must be in range 0 to 254
    		100,			// priority,  must be in range 1 to 254, lower value is higher priority
			100,			// threshold, must be in range 1 to task priority
			2,				// jobs_max, must be in range 1 to 15
			0,				// FALSE -> floating point hardware not used by task
			1,				// FALSE -> task initially not enabled
			fun0,			// main body of task
			nullFun,		// task end function
			0,				// time_deadline, must finish no later than this after start, 0 => ignore
			0				// minimum time expected between start requests, 0 => no restriction
			) != SUCCESSFUL )
    	return 1;
    if ( oceos_task_create(t_1,  200, 200, 2, 0, 1, fun1, nullFun, 0, 0)!= SUCCESSFUL )
    	return 2;
	if ( oceos_mutex_create(m_0, 100)!= SUCCESSFUL )	// Create mutex with ceiling of highest priority task using it
		return 3;
    /*
     * Finish initialising OCEOS and setting up the fixed data
     */
    status = oceos_init_finish();
    if(SUCCESSFUL != status){
        return 4;
    }   // if
    /*
     * Start OCEOS scheduling
     *
     * The OCEOS fixed data provides all the information required.
     *
     * If a valid task is specified, it is started and passed the pointer.
     * Otherwise the system is put in sleep mode
     */
    status = oceos_start(fixed_data, t_1, (void *)nullPtr);		// Start OCEOS with lower prioroty task
    return status;
}   // main
/*
 * Application code functions, functions declared in asw.h
 */
void fun0(void * ptr){
	if (oceos_mutex_wait(m_0) != SUCCESSFUL) {
		printf ("Error from high priority task getting mutex\n");
	} else {
		printf ("high priority task got mutex\n");
	}
    oceos_task_start(t_1,ptr);	// Start lower priority task
    if (oceos_mutex_signal(m_0) != SUCCESSFUL) {
		printf ("Error from high priority task releasing mutex\n");
	} else {
		printf ("High priority task released mutex\n");
	}
	return;
}   // fun0()
void fun1(void * ptr){
	if (oceos_mutex_wait(m_0) != SUCCESSFUL) {
		printf ("Error from low priority task getting mutex\n");
	} else {
		printf ("Low priority task got mutex\n");
	}
    oceos_task_start(t_0,ptr);	// Start higher priority task
    if (oceos_mutex_signal(m_0) != SUCCESSFUL) {
		printf ("Error from low priority task releasing mutex\n");
	} else {
		printf ("Low priority task released mutex\n");
	}
	return;
}   // fun1()
 
Tutorial 3 – Using Semaphores
Semaphores can be used to synchronise task actions as in this exercise.
- Three tasks this time, one high priority and the other two with the same lower priority
 - Two counting semaphores, one initially 0, one initially 4, called ‘items’ and ‘spaces’
 - First task starts second and third tasks
 - Second task loops
- wait_restart spaces
 - signal items
 - Output ‘item done’ message
 
 - Third task loops
- wait_restart items
 - Output ‘got item’ message
 - signal spaces
 
 
For code example see below:
/*
*********************************************************************************************************
*                                                OCEOS
*                                      Real-Time Operating System
*                                                 for
*                                        GR716 Microcontroller
*
*                                  User Manual Section 11 Example 3
*
*                               (c) Copyright 2020, O.C.E. Technology
*                                           All Rights Reserved
*
* File :        tut3.c
********************************************************************************************************
 */
#include "tut3.h"                        // application header
#include <stdio.h>
#include <stdlib.h>
/* N.B.  Application header is included first */
#include "oceos_config.h"                // OCEOS header for this application
/*
 * Application specific
 *
 */
extern U32_t   fixed_data[];     // will be in data segment. Should this be in oceos.h
int main(void) {
	int status;
    /*
     * Initialise the application configuration and OCEOS
     *
     * This application function creates the application configuration
     * and passes it to oceos_init(), which initialises the fixed data
     * and enables the system log
     */
    if ( !application_init()) {
        //LOG
        return -1;
    }
    // Create Main task to
    if ( oceos_task_create(
    		t_0,			// taskID, used as index, must be in range 0 to 254
    		10,			// priority,  must be in range 1 to 254, lower value is higher priority
			10,			// threshold, must be in range 1 to task priority
			1,				// jobs_max, must be in range 1 to 15
			0,				// FALSE -> floating point hardware not used by task
			1,				// FALSE -> task initially not enabled
			fun0,			// main body of task
			nullFun,		// task end function
			0,				// time_deadline, must finish no later than this after start, 0 => ignore
			0				// minimum time expected between start requests, 0 => no restriction
			) != SUCCESSFUL )
    	return 1;
    if ( oceos_task_create(t_1,  100, 100, 1, 0, 1, fun1, nullFun, 0, 0)!= SUCCESSFUL )
    	return 2;
    if ( oceos_task_create(t_2,  100, 100, 1, 0, 1, fun2, nullFun, 0, 0)!= SUCCESSFUL )
    	return 3;
	if ( oceos_sem_create(items, 10, 0, 2, TRUE) != SUCCESSFUL )	// items semaphore with max permits of 10, initial permits of 0, max jobs 2
		return 4;
	if ( oceos_sem_create(spaces, 10, 4, 2, TRUE) != SUCCESSFUL )	// spaces semaphore with max permits of 10, initial permits of 4, max jobs 2
		return 4;
    /*
     * Finish initialising OCEOS and setting up the fixed data
     */
    status = oceos_init_finish();
    if(SUCCESSFUL != status){
        return 6;
    }   // if
    /*
     * Start OCEOS scheduling
     *
     * The OCEOS fixed data provides all the information required.
     *
     * If a valid task is specified, it is started and passed the pointer.
     * Otherwise the system is put in sleep mode
     */
    status = oceos_start(fixed_data, t_0, (void *)nullPtr);		// Start OCEOS with task to start other tasks
    return status;
}   // main
/*
 * Application code functions, functions declared in asw.h
 */
void fun0(void * ptr){
    oceos_task_start(t_1,ptr);	// Start consumer task
    oceos_task_start(t_2,ptr);	// Start consumer task
}   // fun0()
void fun1(void * ptr){
    while (1){	// loop forever
    	if (oceos_sem_wait_restart_timeout(items,0) != SUCCESSFUL) {
    		printf ("Error from task t_0 task waiting items\n");
    	}
    	printf ("Got item\n");
    	if (oceos_sem_signal(spaces) != SUCCESSFUL) {
    		printf ("Error from task t_0 signalling spaces\n");
    	}
    }
}   // fun0()
void fun2(void * ptr){
    while (1){	// loop forever
    	if (oceos_sem_wait_restart_timeout(spaces,0) != SUCCESSFUL) {
    		printf ("Error from task t_1 task waiting spaces\n");
    	}
    	if (oceos_sem_signal(items) != SUCCESSFUL) {
    		printf ("Error from task t_1 signalling items\n");
    	} else {
    		printf ("Item done\n");
    	}
    }
	return;
}   // fun1()
 
Tutorial 4 – Timer interrupt starts task
This exercise introduces the use of timer interrupts.
- Create one task
 - Set a timer to interrupt every 2 seconds
 - Set timer handler to start task
 - 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()