OCEOS Tutorials

From wiki
Revision as of 20:36, 2 September 2021 by imported>Dtimofejevs (→‎Tutorial 4 – Timer interrupt starts task)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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.


/*
*********************************************************************************************************
*                                                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()

 

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:


/*
*********************************************************************************************************
*                                                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.

  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:


/*
*********************************************************************************************************
*                                                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.

  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:


/*
*********************************************************************************************************
*                                                OCEOS
*                                      Real-Time Operating System
*                                                 for
*                                        GR716 Microcontroller
*
*                                  User Manual Section 11 Example 4
*
*                               (c) Copyright 2020, O.C.E. Technology
*                                           All Rights Reserved
*
* File :        tut4.c
********************************************************************************************************
 */
#include "tut4.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
#include <bcc/regs/gptimer.h>

#include "oceos_interrupt.h"
/*
 * Application specific
 *
 */
extern U32_t   fixed_data[];     // will be in data segment. Should this be in oceos.h

struct gptimer_regs *timer_regs = (void *)OCEOS_TA_TIMER_ADDRESS;
struct gptimer_timer_regs *task_timer;
struct bcc_isr_node node;

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;
    /*
     * 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_0, (void *)nullPtr);		// Start OCEOS
    return status;
}   // main

/*
 * Application code functions, functions declared in asw.h
 */
void fun0(void * ptr){
	//set up timer and add handle
    task_timer = &timer_regs->timer[3];
    task_timer->ctrl = 0x0;
    enum DIRECTIVE_STATUS ret = 0;
#ifdef TARGET_PM
    node.source = 9;
#endif
#ifdef TARGET_GR716
    node.source = 12;
#endif
    node.handler = start_task;
    node.arg = ptr;
    ret = oceos_interrupt_handle_register(&node);
    if (SUCCESSFUL != ret) {
        printf("ERROR :: Failed to add ISR handler\n");
    }
#ifdef TARGET_PM
    bcc_int_unmask(9);
#endif
#ifdef TARGET_GR716
    bcc_int_unmask(12);
#endif
    task_timer->reload = 0x2DC6C0; // 3 seconds
    task_timer->counter = 0x2DC6C0; // 3 seconds
    task_timer->ctrl = GPTIMER_CTRL_EN | GPTIMER_CTRL_RS | GPTIMER_CTRL_IE;     // 0x1 | (1 << 1) | (1 << 3);

    // The interrupt shoud keep starting t_1 so this task can exit
}   // fun0()
/*
 * Handler for timer interrupt
 */
void start_task(void *arg, int source){
  oceos_task_start(t_1,arg);
}

void fun1(void * ptr){
	printf ("Task started\n");
}   // fun1()