Jump to content

OCEOS Tutorials: Difference between revisions

From ocewiki
Backup20261021>Dtimofejevs
 
m 1 revision imported
 
(No difference)

Latest revision as of 10:47, 28 October 2026

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

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#ifndef TUT1_H_
#define TUT1_H_

/* Sample Task names - all here start with t_ to help avoid name confusion */
enum TASK_NAME{
    t_0,                 // High priority task
    t_1                  // Low priority task
};

char* nullPtr = "";			// Need pointer to pass to oceos_start
void (*nullFun)(void *);	// Null function

/*
 * APPLICATION FUNCTION DECLARATIONS
 */
void fun0(void *);
void fun1(void *);

#endif /* TUT1_H_ */

oceos_config.h

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#ifndef INCLUDE_OCEOS_CONFIG_H_
#define INCLUDE_OCEOS_CONFIG_H_

// 1: Includes OCEOS main header file
#include "oceos.h"
//----------------------------------------------------------------------------
// 2: Number of Log entries.
#define NUMBER_OF_LOG_ENTRIES                   64 // 16 to 1024, default 64
//----------------------------------------------------------------------------
// 3: Number of tasks
#define NUMBER_OF_TASKS                         2  // 1 to 255
//----------------------------------------------------------------------------
// 4: Number of ready queue entries, 0 to 254, see manual( MUST BE UPDATED BY USER);
//    Defaults to number of tasks, as each task should have aa least one job;
//    If Number of ready Q entries larger that number of total jobs => defaults to number of total jobs
#define NUMBER_OF_READYQ_ENTRIES                NUMBER_OF_TASKS * 2
//----------------------------------------------------------------------------
// 5: Number of Mutexes
#define NUMBER_OF_MUTEXES                       0  // 0 to 63
//----------------------------------------------------------------------------
// 6: Number of Semaphores
#define NUMBER_OF_SEMAPHORES                    0  // 0 to 63
//----------------------------------------------------------------------------
// 7: Number of Data Qs
#define NUMBER_OF_DATAQS                        0  // 0 to 63
//----------------------------------------------------------------------------
// 8: LOG data array size
#define LOG_DATA_ARRAY_SIZE_U32S                0x88// Calculated value. Read manual
//----------------------------------------------------------------------------
// 9: FIXED data array size
#define FIXED_DATA_ARRAY_SIZE_U32S              0x32// Calculated value. Read manual
//----------------------------------------------------------------------------
// 10: DYNAMIC data array size
#define DYN_DATA_ARRAY_SIZE_U32S                0x33// Calculated value. Read manual
//----------------------------------------------------------------------------
// 11: Timed Actions
#define NUMBER_OF_ACTION_ENTRIES                0  // User-modify field
//----------------------------------------------------------------------------
// 12: Log entries base 2
#define CS_LOG_DEF_ENTRIES_BASE2                0
//----------------------------------------------------------------------------
// 13: OCEOS stack start Address
#define OCEOS_STACK_START_ADDRESS               0
//----------------------------------------------------------------------------
// 14: OCEOS stack end address
#define OCEOS_STACK_LOW_BOUND_ADDRESS           0
//----------------------------------------------------------------------------
/**
 * Target specific configurations
 */
/*
 * ARM specific configurations
 */
#ifdef __SAM3X8E__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 84                                      // ARM target frequency in Mhz
#endif
#endif
#ifdef __SAMV71Q21__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 300                                     // ARM target frequency in Mhz
#endif
#endif
#ifdef __VA41620__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 100                                      // ARM target frequency in Mhz
#endif
#endif
//--------------------------------------------------------------------
// User defined function to deal with system errors
void oceos_on_error(void);
//---------------------------------------------------------------------
// User defined function to deal with log 2/3 full
void oceos_on_full_log(void);
//---------------------------------------------------------------------
extern U32_t log_data[];
extern U32_t fixed_data[];
extern U32_t dynamic_data[];
extern const unsigned int __oceos_bsp_sysfreq;
/**
 * Initialize OCEOS with user configurations
 */
int application_init(void);
#endif /* INCLUDE_OCEOS_CONFIG_H_ */

oceos_config.c

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#include <stdio.h>
#include "oceos_config.h"

/*
 * OCEOS INTERNAL DATA STORAGE
 *
 * This application defines arrays to hold OCEOS internal data.
 * The array sizes are provided by DMON by running "oceos info" command:</br>
 *  *Set all three arrays to guessed max zise, run application for the first time and exit.</br>
 *  *Run DMON command "oceos info" to get size for each array.</br>
 *  *Update array sizes below
 */
U32_t log_data[LOG_DATA_ARRAY_SIZE_U32S];

U32_t fixed_data[FIXED_DATA_ARRAY_SIZE_U32S] = {0};     // will be in data segment

U32_t dynamic_data[DYN_DATA_ARRAY_SIZE_U32S];

const unsigned int __oceos_bsp_sysfreq = BSP_SYSFREQ * 1000 * 1000;// TODO

static BOOLE_t log_full_was_called = FALSE;

/**
 * Must be defined if Application is using :
 *      Dataq with timeout
 *      Semaphore with timeout
 *      Timed Actions
 */
/*
 * Set up the application configuration structure and pass it to oceos_init
 * (done this way the memory used for the structure is returned automatically)
 */

int application_init(){

    /*
     * Create the application configuration structure
     */
    struct application_configuration           app_config = {0};

    /*
     * Fill in the application parameters
     */
    app_config.log_address                   = (adrs_t)log_data;              // required
    app_config.fixed_data_address            = (adrs_t)fixed_data;            // required
    app_config.dynamic_data_address          = (adrs_t)dynamic_data;          // required

    app_config.stack_start_address           = OCEOS_STACK_START_ADDRESS;     // 0 => no check
    app_config.stack_lower_bound_address     = OCEOS_STACK_LOW_BOUND_ADDRESS; // 0 => no check

    app_config.system_error_function         = &oceos_on_error;               // NULL => ignore
    app_config.log_full_function             = &oceos_on_full_log;            // NULL => ignore
    // used in setting up system log and fixed data array
    app_config.log_number_of_entries         = NUMBER_OF_LOG_ENTRIES;         // 0 => use default

    app_config.number_of_tasks               = NUMBER_OF_TASKS;               // >= 1
    app_config.number_of_readyQ_entries      = NUMBER_OF_READYQ_ENTRIES;      // 0 => calculate size

    app_config.number_of_mutexes             = NUMBER_OF_MUTEXES;
    app_config.number_of_counting_semaphores = NUMBER_OF_SEMAPHORES;
    app_config.number_of_data_queues         = NUMBER_OF_DATAQS;

    app_config.timed_actions_queue_size      = NUMBER_OF_ACTION_ENTRIES;
    app_config.CS_log_entries_base2          = CS_LOG_DEF_ENTRIES_BASE2;
    app_config.use_oceos_system_time         = TRUE;

    // initialise OCEOS
    enum DIRECTIVE_STATUS status;
    status = oceos_init(app_config);

    if (SUCCESSFUL == status) {
        return 1;
    } else {
        printf("\n oceos_init failure\n");
        return -1;
    }   // else
}   // application_init()
/**
 * User to implement in case of system error;
 * Comment it out if not used and set field system_error_function in app_config to NULL
 */
void oceos_on_error() {
  return;
}
/**
 * User to implement in case of system log is 2/3 full;
 * Comment it out if not used and set field log_full_function in app_config to NULL
 */
void oceos_on_full_log(){
  log_full_was_called = TRUE;
  return;
}

tut1.c

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#include <stdio.h>
#include <stdlib.h>
#include "tut1.h"                        // application header
#include "oceos_config.h"                // OCEOS header

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:

tut2.h

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#ifndef TUT2_H_
#define TUT2_H_

/* Sample Task names - all here start with t_ to help avoid name confusion */
enum TASK_NAME{
    t_0,                 // High priority task
    t_1                  // Low priority task
};
/* Sample Mutex names - all here start with m_ to help avoid name confusion */
enum MUTEX_NAME{
    m_0
};
char* nullPtr = "";			// Need pointer to pass to oceos_start
void (*nullFun)(void *);	// Null function

/*
 * APPLICATION FUNCTION DECLARATIONS
 */
void fun0(void *);
void fun1(void *);

#endif /* TUT2_H_ */

oceos_config.h

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#ifndef INCLUDE_OCEOS_CONFIG_H_
#define INCLUDE_OCEOS_CONFIG_H_

// 1: Includes OCEOS main header file
#include "oceos.h"
//----------------------------------------------------------------------------
// 2: Number of Log entries.
#define NUMBER_OF_LOG_ENTRIES                   64 // 16 to 1024, default 64
//----------------------------------------------------------------------------
// 3: Number of tasks
#define NUMBER_OF_TASKS                         2  // 1 to 255
//----------------------------------------------------------------------------
// 4: Number of ready queue entries, 0 to 254, see manual( MUST BE UPDATED BY USER);
//    Defaults to number of tasks, as each task should have aa least one job;
//    If Number of ready Q entries larger that number of total jobs => defaults to number of total jobs
#define NUMBER_OF_READYQ_ENTRIES                NUMBER_OF_TASKS * 2
//----------------------------------------------------------------------------
// 5: Number of Mutexes
#define NUMBER_OF_MUTEXES                       1  // 0 to 63
//----------------------------------------------------------------------------
// 6: Number of Semaphores
#define NUMBER_OF_SEMAPHORES                    0  // 0 to 63
//----------------------------------------------------------------------------
// 7: Number of Data Qs
#define NUMBER_OF_DATAQS                        0  // 0 to 63
//----------------------------------------------------------------------------
// 8: LOG data array size
#define LOG_DATA_ARRAY_SIZE_U32S                0x88// Calculated value. Read manual
//----------------------------------------------------------------------------
// 9: FIXED data array size
#define FIXED_DATA_ARRAY_SIZE_U32S              0x33// Calculated value. Read manual
//----------------------------------------------------------------------------
// 10: DYNAMIC data array size
#define DYN_DATA_ARRAY_SIZE_U32S                0x34// Calculated value. Read manual
//----------------------------------------------------------------------------
// 11: Timed Actions
#define NUMBER_OF_ACTION_ENTRIES                0  // User-modify field
//----------------------------------------------------------------------------
// 12: Log entries base 2
#define CS_LOG_DEF_ENTRIES_BASE2                0
//----------------------------------------------------------------------------
// 13: OCEOS stack start Address
#define OCEOS_STACK_START_ADDRESS               0
//----------------------------------------------------------------------------
// 14: OCEOS stack end address
#define OCEOS_STACK_LOW_BOUND_ADDRESS           0
//----------------------------------------------------------------------------
/**
 * Target specific configurations
 */
/*
 * ARM specific configurations
 */
#ifdef __SAM3X8E__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 84                                      // ARM target frequency in Mhz
#endif
#endif
#ifdef __SAMV71Q21__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 300                                     // ARM target frequency in Mhz
#endif
#endif
#ifdef __VA41620__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 100                                      // ARM target frequency in Mhz
#endif
#endif
//--------------------------------------------------------------------
// User defined function to deal with system errors
void oceos_on_error(void);
//---------------------------------------------------------------------
// User defined function to deal with log 2/3 full
void oceos_on_full_log(void);
//---------------------------------------------------------------------
extern U32_t log_data[];
extern U32_t fixed_data[];
extern U32_t dynamic_data[];
extern const unsigned int __oceos_bsp_sysfreq;
/**
 * Initialize OCEOS with user configurations
 */
int application_init(void);
#endif /* INCLUDE_OCEOS_CONFIG_H_ */

oceos_config.c

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#include <stdio.h>
#include "oceos_config.h"

/*
 * OCEOS INTERNAL DATA STORAGE
 *
 * This application defines arrays to hold OCEOS internal data.
 * The array sizes are provided by DMON by running "oceos info" command:</br>
 *  *Set all three arrays to guessed max zise, run application for the first time and exit.</br>
 *  *Run DMON command "oceos info" to get size for each array.</br>
 *  *Update array sizes below
 */
U32_t log_data[LOG_DATA_ARRAY_SIZE_U32S];

U32_t fixed_data[FIXED_DATA_ARRAY_SIZE_U32S] = {0};     // will be in data segment

U32_t dynamic_data[DYN_DATA_ARRAY_SIZE_U32S];

const unsigned int __oceos_bsp_sysfreq = BSP_SYSFREQ * 1000 * 1000;// TODO

static BOOLE_t log_full_was_called = FALSE;

/**
 * Must be defined if Application is using :
 *      Dataq with timeout
 *      Semaphore with timeout
 *      Timed Actions
 */
/*
 * Set up the application configuration structure and pass it to oceos_init
 * (done this way the memory used for the structure is returned automatically)
 */

int application_init(){

    /*
     * Create the application configuration structure
     */
    struct application_configuration           app_config = {0};

    /*
     * Fill in the application parameters
     */
    app_config.log_address                   = (adrs_t)log_data;              // required
    app_config.fixed_data_address            = (adrs_t)fixed_data;            // required
    app_config.dynamic_data_address          = (adrs_t)dynamic_data;          // required

    app_config.stack_start_address           = OCEOS_STACK_START_ADDRESS;     // 0 => no check
    app_config.stack_lower_bound_address     = OCEOS_STACK_LOW_BOUND_ADDRESS; // 0 => no check

    app_config.system_error_function         = &oceos_on_error;               // NULL => ignore
    app_config.log_full_function             = &oceos_on_full_log;            // NULL => ignore
    // used in setting up system log and fixed data array
    app_config.log_number_of_entries         = NUMBER_OF_LOG_ENTRIES;         // 0 => use default

    app_config.number_of_tasks               = NUMBER_OF_TASKS;               // >= 1
    app_config.number_of_readyQ_entries      = NUMBER_OF_READYQ_ENTRIES;      // 0 => calculate size

    app_config.number_of_mutexes             = NUMBER_OF_MUTEXES;
    app_config.number_of_counting_semaphores = NUMBER_OF_SEMAPHORES;
    app_config.number_of_data_queues         = NUMBER_OF_DATAQS;

    app_config.timed_actions_queue_size      = NUMBER_OF_ACTION_ENTRIES;
    app_config.CS_log_entries_base2          = CS_LOG_DEF_ENTRIES_BASE2;
    app_config.use_oceos_system_time         = TRUE;

    // initialise OCEOS
    enum DIRECTIVE_STATUS status;
    status = oceos_init(app_config);

    if (SUCCESSFUL == status) {
        return 1;
    } else {
        printf("\n oceos_init failure\n");
        return -1;
    }   // else
}   // application_init()
/**
 * User to implement in case of system error;
 * Comment it out if not used and set field system_error_function in app_config to NULL
 */
void oceos_on_error() {
  return;
}
/**
 * User to implement in case of system log is 2/3 full;
 * Comment it out if not used and set field log_full_function in app_config to NULL
 */
void oceos_on_full_log(){
  log_full_was_called = TRUE;
  return;
}

tut2.c

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#include <stdio.h>
#include <stdlib.h>
#include "tut2.h"                        // application header

/* N.B.  Application header is included first */
#include "oceos_config.h"                // OCEOS header for this application
#include "mutex.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:

tut3.h

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#ifndef TUT3_H_
#define TUT3_H_
/* Sample Task names - all here start with t_ to help avoid name confusion */
enum TASK_NAME{
    t_0,                 // Task to start other two
    t_1,                 // consumer task
    t_2                  // consumer task

};
/* Sample Counting Semaphore names - all here start with s_ to help avoid name confusion */
enum SEM_NAME{
    items,                   // Semaphore called items
    spaces                   // Semaphore called spaces
};
char* nullPtr = "";			// Need pointer to pass to oceos_start
void (*nullFun)(void *);	// Null function

/*
 * APPLICATION FUNCTION DECLARATIONS
 */
void fun0(void *);
void fun1(void *);
void fun2(void *);

#endif /* TUT3_H_ */

oceos_config.h

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#ifndef INCLUDE_OCEOS_CONFIG_H_
#define INCLUDE_OCEOS_CONFIG_H_

// 1: Includes OCEOS main header file
#include "oceos.h"
//----------------------------------------------------------------------------
// 2: Number of Log entries.
#define NUMBER_OF_LOG_ENTRIES                   64 // 16 to 1024, default 64
//----------------------------------------------------------------------------
// 3: Number of tasks
#define NUMBER_OF_TASKS                         3  // 1 to 255
//----------------------------------------------------------------------------
// 4: Number of ready queue entries, 0 to 254, see manual( MUST BE UPDATED BY USER);
//    Defaults to number of tasks, as each task should have aa least one job;
//    If Number of ready Q entries larger that number of total jobs => defaults to number of total jobs
#define NUMBER_OF_READYQ_ENTRIES                NUMBER_OF_TASKS * 2
//----------------------------------------------------------------------------
// 5: Number of Mutexes
#define NUMBER_OF_MUTEXES                       0  // 0 to 63
//----------------------------------------------------------------------------
// 6: Number of Semaphores
#define NUMBER_OF_SEMAPHORES                    2  // 0 to 63
//----------------------------------------------------------------------------
// 7: Number of Data Qs
#define NUMBER_OF_DATAQS                        0  // 0 to 63
//----------------------------------------------------------------------------
// 8: LOG data array size
#define LOG_DATA_ARRAY_SIZE_U32S                0x88// Calculated value. Read manual
//----------------------------------------------------------------------------
// 9: FIXED data array size
#define FIXED_DATA_ARRAY_SIZE_U32S              0x3a// Calculated value. Read manual
//----------------------------------------------------------------------------
// 10: DYNAMIC data array size
#define DYN_DATA_ARRAY_SIZE_U32S                0x65// Calculated value. Read manual
//----------------------------------------------------------------------------
// 11: Timed Actions
#define NUMBER_OF_ACTION_ENTRIES                0  // User-modify field
//----------------------------------------------------------------------------
// 12: Log entries base 2
#define CS_LOG_DEF_ENTRIES_BASE2                0
//----------------------------------------------------------------------------
// 13: OCEOS stack start Address
#define OCEOS_STACK_START_ADDRESS               0
//----------------------------------------------------------------------------
// 14: OCEOS stack end address
#define OCEOS_STACK_LOW_BOUND_ADDRESS           0
//----------------------------------------------------------------------------
/**
 * Target specific configurations
 */
/*
 * ARM specific configurations
 */
#ifdef __SAM3X8E__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 84                                      // ARM target frequency in Mhz
#endif
#endif
#ifdef __SAMV71Q21__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 300                                     // ARM target frequency in Mhz
#endif
#endif
#ifdef __VA41620__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 100                                      // ARM target frequency in Mhz
#endif
#endif
//--------------------------------------------------------------------
// User defined function to deal with system errors
void oceos_on_error(void);
//---------------------------------------------------------------------
// User defined function to deal with log 2/3 full
void oceos_on_full_log(void);
//---------------------------------------------------------------------
extern U32_t log_data[];
extern U32_t fixed_data[];
extern U32_t dynamic_data[];
extern const unsigned int __oceos_bsp_sysfreq;
/**
 * Initialize OCEOS with user configurations
 */
int application_init(void);
#endif /* INCLUDE_OCEOS_CONFIG_H_ */

oceos_config.c

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#include <stdio.h>
#include "oceos_config.h"

/*
 * OCEOS INTERNAL DATA STORAGE
 *
 * This application defines arrays to hold OCEOS internal data.
 * The array sizes are provided by DMON by running "oceos info" command:</br>
 *  *Set all three arrays to guessed max zise, run application for the first time and exit.</br>
 *  *Run DMON command "oceos info" to get size for each array.</br>
 *  *Update array sizes below
 */
U32_t log_data[LOG_DATA_ARRAY_SIZE_U32S];

U32_t fixed_data[FIXED_DATA_ARRAY_SIZE_U32S] = {0};     // will be in data segment

U32_t dynamic_data[DYN_DATA_ARRAY_SIZE_U32S];

const unsigned int __oceos_bsp_sysfreq = BSP_SYSFREQ * 1000 * 1000;// TODO

static BOOLE_t log_full_was_called = FALSE;

/**
 * Must be defined if Application is using :
 *      Dataq with timeout
 *      Semaphore with timeout
 *      Timed Actions
 */
/*
 * Set up the application configuration structure and pass it to oceos_init
 * (done this way the memory used for the structure is returned automatically)
 */

int application_init(){

    /*
     * Create the application configuration structure
     */
    struct application_configuration           app_config = {0};

    /*
     * Fill in the application parameters
     */
    app_config.log_address                   = (adrs_t)log_data;              // required
    app_config.fixed_data_address            = (adrs_t)fixed_data;            // required
    app_config.dynamic_data_address          = (adrs_t)dynamic_data;          // required

    app_config.stack_start_address           = OCEOS_STACK_START_ADDRESS;     // 0 => no check
    app_config.stack_lower_bound_address     = OCEOS_STACK_LOW_BOUND_ADDRESS; // 0 => no check

    app_config.system_error_function         = &oceos_on_error;               // NULL => ignore
    app_config.log_full_function             = &oceos_on_full_log;            // NULL => ignore
    // used in setting up system log and fixed data array
    app_config.log_number_of_entries         = NUMBER_OF_LOG_ENTRIES;         // 0 => use default

    app_config.number_of_tasks               = NUMBER_OF_TASKS;               // >= 1
    app_config.number_of_readyQ_entries      = NUMBER_OF_READYQ_ENTRIES;      // 0 => calculate size

    app_config.number_of_mutexes             = NUMBER_OF_MUTEXES;
    app_config.number_of_counting_semaphores = NUMBER_OF_SEMAPHORES;
    app_config.number_of_data_queues         = NUMBER_OF_DATAQS;

    app_config.timed_actions_queue_size      = NUMBER_OF_ACTION_ENTRIES;
    app_config.CS_log_entries_base2          = CS_LOG_DEF_ENTRIES_BASE2;
    app_config.use_oceos_system_time         = TRUE;

    // initialise OCEOS
    enum DIRECTIVE_STATUS status;
    status = oceos_init(app_config);

    if (SUCCESSFUL == status) {
        return 1;
    } else {
        printf("\n oceos_init failure\n");
        return -1;
    }   // else
}   // application_init()
/**
 * User to implement in case of system error;
 * Comment it out if not used and set field system_error_function in app_config to NULL
 */
void oceos_on_error() {
  return;
}
/**
 * User to implement in case of system log is 2/3 full;
 * Comment it out if not used and set field log_full_function in app_config to NULL
 */
void oceos_on_full_log(){
  log_full_was_called = TRUE;
  return;
}

tut3.c

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#include <stdio.h>
#include <stdlib.h>

/* N.B.  Application header is included first */
#include "oceos_config.h"                // OCEOS header for this application
#include "tut3.h"                        // application header
#include "semaphore.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, FALSE) != 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, FALSE) != 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(items) != 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(spaces) != 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:

tut4.h

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#ifndef TUT4_H_
#define TUT4_H_
/* Sample Task names - all here start with t_ to help avoid name confusion */
enum TASK_NAME{
    t_0,                 // Task to setup interrupt
    t_1                  // Task to be executed by interrupt routine

};
/*
 * APPLICATION FUNCTION DECLARATIONS
 */
void fun0(void *);
void fun1(void *);
void start_task(void *arg, int source);
void timer_setup(void);

#endif /* TUT4_H_ */

oceos_config.h

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#ifndef INCLUDE_OCEOS_CONFIG_H_
#define INCLUDE_OCEOS_CONFIG_H_

// 1: Includes OCEOS main header file
#include "oceos.h"
//----------------------------------------------------------------------------
// 2: Number of Log entries.
#define NUMBER_OF_LOG_ENTRIES                   64 // 16 to 1024, default 64
//----------------------------------------------------------------------------
// 3: Number of tasks
#define NUMBER_OF_TASKS                         2  // 1 to 255
//----------------------------------------------------------------------------
// 4: Number of ready queue entries, 0 to 254, see manual( MUST BE UPDATED BY USER);
//    Defaults to number of tasks, as each task should have aa least one job;
//    If Number of ready Q entries larger that number of total jobs => defaults to number of total jobs
#define NUMBER_OF_READYQ_ENTRIES                NUMBER_OF_TASKS + 1
//----------------------------------------------------------------------------
// 5: Number of Mutexes
#define NUMBER_OF_MUTEXES                       0  // 0 to 63
//----------------------------------------------------------------------------
// 6: Number of Semaphores
#define NUMBER_OF_SEMAPHORES                    0  // 0 to 63
//----------------------------------------------------------------------------
// 7: Number of Data Qs
#define NUMBER_OF_DATAQS                        0  // 0 to 63
//----------------------------------------------------------------------------
// 8: LOG data array size
#define LOG_DATA_ARRAY_SIZE_U32S                0x88// Calculated value. Read manual
//----------------------------------------------------------------------------
// 9: FIXED data array size
#define FIXED_DATA_ARRAY_SIZE_U32S              0x32// Calculated value. Read manual
//----------------------------------------------------------------------------
// 10: DYNAMIC data array size
#define DYN_DATA_ARRAY_SIZE_U32S                0x29// Calculated value. Read manual
//----------------------------------------------------------------------------
// 11: Timed Actions
#define NUMBER_OF_ACTION_ENTRIES                0  // User-modify field
//----------------------------------------------------------------------------
// 12: Log entries base 2
#define CS_LOG_DEF_ENTRIES_BASE2                0
//----------------------------------------------------------------------------
// 13: OCEOS stack start Address
#define OCEOS_STACK_START_ADDRESS               0
//----------------------------------------------------------------------------
// 14: OCEOS stack end address
#define OCEOS_STACK_LOW_BOUND_ADDRESS           0
//----------------------------------------------------------------------------
/**
 * Target specific configurations
 */
/*
 * ARM specific configurations
 */
#ifdef __SAM3X8E__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 84                                      // ARM target frequency in Mhz
#endif
#endif
#ifdef __SAMV71Q21__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 300                                     // ARM target frequency in Mhz
#endif
#endif
#ifdef __VA41620__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 100                                      // ARM target frequency in Mhz
#endif
#endif
//--------------------------------------------------------------------
// User defined function to deal with system errors
void oceos_on_error(void);
//---------------------------------------------------------------------
// User defined function to deal with log 2/3 full
void oceos_on_full_log(void);
//---------------------------------------------------------------------
extern U32_t log_data[];
extern U32_t fixed_data[];
extern U32_t dynamic_data[];
extern const unsigned int __oceos_bsp_sysfreq;
/**
 * Initialize OCEOS with user configurations
 */
int application_init(void);
#endif /* INCLUDE_OCEOS_CONFIG_H_ */

oceos_config.c

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#include <stdio.h>
#include "oceos_config.h"

/*
 * OCEOS INTERNAL DATA STORAGE
 *
 * This application defines arrays to hold OCEOS internal data.
 * The array sizes are provided by DMON by running "oceos info" command:</br>
 *  *Set all three arrays to guessed max zise, run application for the first time and exit.</br>
 *  *Run DMON command "oceos info" to get size for each array.</br>
 *  *Update array sizes below
 */
U32_t log_data[LOG_DATA_ARRAY_SIZE_U32S];

U32_t fixed_data[FIXED_DATA_ARRAY_SIZE_U32S] = {0};     // will be in data segment

U32_t dynamic_data[DYN_DATA_ARRAY_SIZE_U32S];

const unsigned int __oceos_bsp_sysfreq = BSP_SYSFREQ * 1000 * 1000;// TODO

static BOOLE_t log_full_was_called = FALSE;

/**
 * Must be defined if Application is using :
 *      Dataq with timeout
 *      Semaphore with timeout
 *      Timed Actions
 */
/*
 * Set up the application configuration structure and pass it to oceos_init
 * (done this way the memory used for the structure is returned automatically)
 */

int application_init(){

    /*
     * Create the application configuration structure
     */
    struct application_configuration           app_config = {0};

    /*
     * Fill in the application parameters
     */
    app_config.log_address                   = (adrs_t)log_data;              // required
    app_config.fixed_data_address            = (adrs_t)fixed_data;            // required
    app_config.dynamic_data_address          = (adrs_t)dynamic_data;          // required

    app_config.stack_start_address           = OCEOS_STACK_START_ADDRESS;     // 0 => no check
    app_config.stack_lower_bound_address     = OCEOS_STACK_LOW_BOUND_ADDRESS; // 0 => no check

    app_config.system_error_function         = &oceos_on_error;               // NULL => ignore
    app_config.log_full_function             = &oceos_on_full_log;            // NULL => ignore
    // used in setting up system log and fixed data array
    app_config.log_number_of_entries         = NUMBER_OF_LOG_ENTRIES;         // 0 => use default

    app_config.number_of_tasks               = NUMBER_OF_TASKS;               // >= 1
    app_config.number_of_readyQ_entries      = NUMBER_OF_READYQ_ENTRIES;      // 0 => calculate size

    app_config.number_of_mutexes             = NUMBER_OF_MUTEXES;
    app_config.number_of_counting_semaphores = NUMBER_OF_SEMAPHORES;
    app_config.number_of_data_queues         = NUMBER_OF_DATAQS;

    app_config.timed_actions_queue_size      = NUMBER_OF_ACTION_ENTRIES;
    app_config.CS_log_entries_base2          = CS_LOG_DEF_ENTRIES_BASE2;
    app_config.use_oceos_system_time         = TRUE;

    // initialise OCEOS
    enum DIRECTIVE_STATUS status;
    status = oceos_init(app_config);

    if (SUCCESSFUL == status) {
        return 1;
    } else {
        printf("\n oceos_init failure\n");
        return -1;
    }   // else
}   // application_init()
/**
 * User to implement in case of system error;
 * Comment it out if not used and set field system_error_function in app_config to NULL
 */
void oceos_on_error() {
  return;
}
/**
 * User to implement in case of system log is 2/3 full;
 * Comment it out if not used and set field log_full_function in app_config to NULL
 */
void oceos_on_full_log(){
  log_full_was_called = TRUE;
  return;
}

arm_task_src.c

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#include <stdio.h>
#include <stdlib.h>
#include "tut4.h"
#include "oceos_config.h"

#if defined(__SAM3X8E__) || defined(__SAMV71Q21__)
#include "sam.h"

#define ENABLE_WAVE_MODE           (0x1 << TC_CMR_WAVE_Pos)
#define TC_CMR_WAVE_SEL_Pos        13
#define SET_WAVE_SELECT            (~(0x3 << TC_CMR_WAVE_SEL_Pos)) //00
#define TC_CMR_CPCSTOP_Pos         6
#define TC_CMR_CPCSTOP             (0x1 << TC_CMR_CPCSTOP_Pos)

static Tc *timer_regs;
static TcChannel *tc;

#endif

/*
 * Set up timer and register handler
 */
void timer_setup(){

#ifdef __SAM3X8E__
  // Enabling Peripheral Clocks
 // REmove write protect
 int pmc_was_enabled = 0;
 if (0 != (PMC->PMC_WPMR & PMC_WPMR_WPEN)) {
     PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD;
     pmc_was_enabled = 1;
 }
 // Enable Clock
 PMC->PMC_PCER0 |= PMC_PCER0_PID28;
 // Enable write protect
 if (pmc_was_enabled) {
   PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD | PMC_WPMR_WPEN;
 }

 timer_regs = (Tc *)TC0;
 tc = &(timer_regs->TC_CHANNEL[1]);

 // Enable Wave Mode
  tc->TC_CMR |= ENABLE_WAVE_MODE;
  // Set WAVESEL to 00
  tc->TC_CMR &= (U32_t)SET_WAVE_SELECT;
  // Set TC_CMR_CPCSTOP and Clock input
  tc->TC_CMR |= (TC_CMR_CPCSTOP | TC_CMR_TCCLKS_TIMER_CLOCK1); // MCK/8


 // Set Block Clock
 timer_regs->TC_BMR &= (U32_t)(~(1 << 1));
 // Interrupt Enable
   // Enable Timer interrupt (RC Compare)
 tc->TC_IER = TC_IER_CPCS;

 NVIC_EnableIRQ(TC1_IRQn);
 // Set Highest Priority for interrupt number
 NVIC_SetPriority(TC1_IRQn, 1);
 float base_scaler        = (float)(__oceos_bsp_sysfreq / 2) / 1000000.0f;

 //tc->TC_RC  = base_scaler * 0x3DC6C0;
 tc->TC_RC  = base_scaler * 1349;
 // Enable clock
 tc->TC_CCR = TC_CCR_CLKEN;

 // Start clock
 tc->TC_CCR = TC_CCR_SWTRG;
#endif
#ifdef __SAMV71Q21__
  // Enabling Peripheral Clocks
 // REmove write protect
 int pmc_was_enabled = 0;
 if (0 != (PMC->PMC_WPMR & PMC_WPMR_WPEN)) {
     PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD;
     pmc_was_enabled = 1;
 }
 // Enable Clock
 PMC->PMC_PCER0 |= PMC_PCER0_PID24;
 // Enable write protect
 if (pmc_was_enabled) {
   PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD | PMC_WPMR_WPEN;
 }
 timer_regs = (Tc *)TC0;
 tc = &(timer_regs->TC_CHANNEL[1]);

 // Enable Wave Mode
  tc->TC_CMR |= ENABLE_WAVE_MODE;
  // Set WAVESEL to 00
  tc->TC_CMR &= (U32_t)SET_WAVE_SELECT;
  // Set TC_CMR_CPCSTOP and Clock input
  tc->TC_CMR |= (TC_CMR_CPCSTOP | TC_CMR_TCCLKS_TIMER_CLOCK5_Val); //

 // Set Block Clock
 timer_regs->TC_BMR &= (U32_t)(~(1 << 1));
 // Interrupt Enable
 // Enable Timer interrupt (RC Compare)
 tc->TC_IER = TC_IER_CPCS;

 NVIC_EnableIRQ(TC1_IRQn);
 // Set Highest Priority for interrupt number
 NVIC_SetPriority(TC1_IRQn, 1);

 tc->TC_RC  = 0x61a8;// 1s

 // Enable clock
 tc->TC_CCR = TC_CCR_CLKEN;

 // Start clock
 tc->TC_CCR = TC_CCR_SWTRG;
#endif
}   // setup_timer()

void TC1_IRQHandler() {
#if defined(__SAM3X8E__) || defined(__SAMV71Q21__)
  tc->TC_SR;// Read to remove pending bit
#endif
  // Start task
  oceos_task_start(t_1, NULL);

#if defined(__SAM3X8E__) || defined(__SAMV71Q21__)
  tc->TC_CCR = TC_CCR_SWTRG;
#endif
}

tut4.c

/*
 *********************************************************************************************************
 *                                                OCEOS
 *                                      Real-Time Operating System
 *                                                 for
 *                                        ARM Microcontroller
 *
 *                                   Example implementation of OCEOS
 *
 *
 *                               (c) Copyright 2021, O.C.E. Technology
 *                                           All Rights Reserved
 *
 *
 * Author:       jfk
 ********************************************************************************************************
 */
#include <stdio.h>
#include <stdlib.h>

/* N.B.  Application header is included first */
#include "oceos_config.h"                // OCEOS header for this application
#include "tut4.h"                        // application header

volatile U32_t count_task_start = 0;

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
                        NULL,		// 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, NULL, 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, NULL);		// Start OCEOS
  return status;
}   // main

/*
 * Task 0 starting point
 */
void fun0(void *ptr) {
  timer_setup();
}   // fun0()
/**
 * Task 1 starting point;
 * Triggered from Timer IRQ handler
 */
void fun1(void *ptr) {
  printf("Task started : %u times \n", count_task_start);
  count_task_start++;
}   // 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:

tut5.h

/*
******************************************************************************
*                                   OCEOS
*                        Real-Time Operating System
*                               for ARM/SPARC
*                              Microcontroller
*
*                   Application Software Example Header File
*
*
*                    (c) Copyright 2021, O.C.E. Technology
*                             All Rights Reserved
*
* File :        asw.h
* Author:       Deniss Timofejevs <deniss.timofejevs@ocetechnology.com>
******************************************************************************
 */
#ifndef ASW_H
#define ASW_H
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "oceos_config.h"    // OCEOS header
#include "oceos_timer.h"     
#include "system_log.h"
#include "dataq.h"

#define N0 1  // dataq_size
#define N1 1  // dataq_size
#define JOBS0 1 // pending q size
#define JOBS1 1 // pending q size
#define TIME_OUT 1000000 // timeout

/*
 * APPLICATION FUNCTION DECLARATIONS
 */
enum TASK_NAME{
    t_consumer ,                     // will have task ID 0
    t_producer,                     // will have task ID 1
};
enum DATAQ_NAME{
  queue_0,                      // will have dataq ID 0
  queue_1,                      // will have dataq ID 1
};
void t_consumer_task(void);
void t_producer_task(void);

#endif /* ASW_H */

oceos_config.h

/*
 * app_config.h
 *
 *  Created on: 17 Feb 2020
 *      Author: Deniss Timofejevs <deniss.timofejevs@ocetechnology.com>
 */

#ifndef INCLUDE_OCEOS_CONFIG_H_
#define INCLUDE_OCEOS_CONFIG_H_

// 1: Includes OCEOS main header file
#include "oceos.h"
//----------------------------------------------------------------------------
// 2: Number of Log entries.
#define NUMBER_OF_LOG_ENTRIES                   16 // 16 to 1024, default 64
//----------------------------------------------------------------------------
// 3: Number of tasks
#define NUMBER_OF_TASKS                         2  // 1 to 255
//----------------------------------------------------------------------------
// 4: Number of ready queue entries, 0 to 254, see manual( MUST BE UPDATED BY USER);
//    Defaults to number of tasks, as each task should have aa least one job;
//    If Number of ready Q entries larger that number of total jobs => defaults to number of total jobs
#define NUMBER_OF_READYQ_ENTRIES                3
//----------------------------------------------------------------------------
// 5: Number of Mutexes
#define NUMBER_OF_MUTEXES                       0  // 0 to 63
//----------------------------------------------------------------------------
// 6: Number of Semaphores
#define NUMBER_OF_SEMAPHORES                    0  // 0 to 63
//----------------------------------------------------------------------------
// 7: Number of Data Qs
#define NUMBER_OF_DATAQS                        2  // 0 to 63
//----------------------------------------------------------------------------
// 8: LOG data array size
#define LOG_DATA_ARRAY_SIZE_U32S                0x28// Calculated value. Read manual
//----------------------------------------------------------------------------
// 9: FIXED data array size
#define FIXED_DATA_ARRAY_SIZE_U32S              0x34// Calculated value. Read manual
//----------------------------------------------------------------------------
// 10: DYNAMIC data array size
#define DYN_DATA_ARRAY_SIZE_U32S                0x46// Calculated value. Read manual
//----------------------------------------------------------------------------
// 11: Timed Actions
#define NUMBER_OF_ACTION_ENTRIES                0  // User-modify field
//----------------------------------------------------------------------------
// 12: Log entries base 2
#define CS_LOG_DEF_ENTRIES_BASE2                0
//----------------------------------------------------------------------------
// 13: OCEOS stack start Address
#define OCEOS_STACK_START_ADDRESS               0
//----------------------------------------------------------------------------
// 14: OCEOS stack end address
#define OCEOS_STACK_LOW_BOUND_ADDRESS           0
//----------------------------------------------------------------------------
/**
 * Target specific configurations
 */
#ifdef __SAM3X8E__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 84                                      // ARM target frequency in Mhz
#endif
#endif
#ifdef __SAMV71Q21__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 300                                     // ARM target frequency in Mhz
#endif
#endif
#ifdef __VA41620__
#ifndef BSP_SYSFREQ
#define BSP_SYSFREQ 100                                      // ARM target frequency in Mhz
#endif
#endif

// User defined function to deal with system errors
void oceos_on_error(void*);
//---------------------------------------------------------------------
// User defined function to deal with log 2/3 full
void oceos_on_full_log(void*);
//---------------------------------------------------------------------
extern U32_t log_data[];
extern U32_t fixed_data[];
extern U32_t dynamic_data[];
extern const unsigned int __oceos_bsp_sysfreq;
/**
 * Initialize OCEOS with user configurations
 */
int application_init(void);
#endif /* INCLUDE_OCEOS_CONFIG_H_ */

oceos_config.c

/*
 * app_config.c
 *
 *  Configuration Tamplate for OCEOS
 *
 *  Created on: 17 Feb 2020
 *      Author: Deniss Timofejevs <deniss.timofejevs@ocetechnology.com>
 */
#include <stdio.h>
#include <assert.h>
#include "oceos_config.h"

/*
 * OCEOS INTERNAL DATA STORAGE
 *
 * This application defines arrays to hold OCEOS internal data.
 * The array sizes are provided by DMON by running "oceos info" command:</br>
 *  *Set all three arrays to guessed max zise, run application for the first time and exit.</br>
 *  *Run DMON command "oceos info" to get size for each array.</br>
 *  *Update array sizes below
 */
U32_t log_data[LOG_DATA_ARRAY_SIZE_U32S];

U32_t fixed_data[FIXED_DATA_ARRAY_SIZE_U32S] = {0};     // will be in data segment

U32_t dynamic_data[DYN_DATA_ARRAY_SIZE_U32S];

const unsigned int __oceos_bsp_sysfreq = BSP_SYSFREQ * 1000 * 1000;// TODO

static BOOLE_t log_full_was_called = FALSE;

/*
 * Set up the application configuration structure and pass it to oceos_init
 * (done this way the memory used for the structure is returned automatically)
 */

int application_init(){

    /*
     * Create the application configuration structure
     */
    struct application_configuration           app_config = {0};

    /*
     * Fill in the application parameters
     */
    app_config.log_address                   = (adrs_t)log_data;              // required
    app_config.fixed_data_address            = (adrs_t)fixed_data;            // required
    app_config.dynamic_data_address          = (adrs_t)dynamic_data;          // required

    app_config.stack_start_address           = OCEOS_STACK_START_ADDRESS;     // 0 => no check
    app_config.stack_lower_bound_address     = OCEOS_STACK_LOW_BOUND_ADDRESS; // 0 => no check

    app_config.system_error_function         = &oceos_on_error;               // NULL => ignore
    app_config.log_full_function             = &oceos_on_full_log;            // NULL => ignore

    // used in setting up system log and fixed data array
    app_config.log_number_of_entries         = NUMBER_OF_LOG_ENTRIES;         // 0 => use default

    app_config.number_of_tasks               = NUMBER_OF_TASKS;               // >= 1
    app_config.number_of_readyQ_entries      = NUMBER_OF_READYQ_ENTRIES;      // 0 => calculate size

    app_config.number_of_mutexes             = NUMBER_OF_MUTEXES;
    app_config.number_of_counting_semaphores = NUMBER_OF_SEMAPHORES;
    app_config.number_of_data_queues         = NUMBER_OF_DATAQS;

    app_config.timed_actions_queue_size      = NUMBER_OF_ACTION_ENTRIES;
    app_config.CS_log_entries_base2          = CS_LOG_DEF_ENTRIES_BASE2;
    app_config.use_oceos_system_time         = TRUE;

    // initialise OCEOS
    enum DIRECTIVE_STATUS status;
    status = oceos_init(app_config);
    assert(SUCCESSFUL == status);

    if (SUCCESSFUL == status) {
        return 1;
    } else {
        printf("\n oceos_init failure\n");
        return -1;
    }   // else
}   // application_init()
/**
 * User to implement in case of system error;
 * Comment it out if not used and set field system_error_function in app_config to NULL
 */
void oceos_on_error(void* ptr) {
  return;
}
/**
 * User to implement in case of system log is 2/3 full;
 * Comment it out if not used and set field log_full_function in app_config to NULL
 */
void oceos_on_full_log(void* ptr){
  log_full_was_called = TRUE;
  return;
}

tut5.c

/*
******************************************************************************
*                                   OCEOS
*                        Real-Time Operating System
*                              for ARM/SPARC
*                             Microcontroller
*
*                       Application Software Example
*
*
*                    (c) Copyright 2022, O.C.E. Technology
*                             All Rights Reserved
*
* Author:       jfk
*
* Purpose                : The test here involves creating two tasks with different priorities, 
*						   and two data queues with timed action implimentation.
*
******************************************************************************
*/
/* N.B.  Application header is included first */
#include "tut5.h"                        // application header

struct data {
  int status;
  char *message;
} test_data = {
    1,
    "Test Data",
};
int main(void) {

    /*
     * 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
        printf("\nProblem\n");
        return -1;
    }

    enum DIRECTIVE_STATUS status;
    // 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
    status  = oceos_task_create(t_consumer, 10, 10, 1, 0, TASK_ENABLED,t_consumer_task, NULL, 0, 0);
      if(SUCCESSFUL != status){
        // LOG
        printf("\nAbandoning, problem creating task t_consumer, resulting return code: %u\n", status);
        return -1;
      }   // if
	
    // 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
    status  = oceos_task_create(t_producer, 254, 254, 1, 0, TASK_ENABLED,t_producer_task, NULL, 0, 0);
	  if(SUCCESSFUL != status){
        // LOG
        printf("\nAbandoning, problem creating task t_producer, resulting return code: %u\n", status);
        return -1;
      }   // if

    printf("\n Tasks created\n");
    // no counting semaphores, data queues or user defined traps

    // Creating Data 0, dataq_size 1, pen_q size 1, roll_over FALSE, use_timeout TRUE
     status = oceos_dataq_create(queue_0, N0, JOBS0, FALSE, TRUE);
     if(SUCCESSFUL != status){
        printf("\nProblem creating dataq queue_0, resulting return code: %u\n", status);
     }   // if
	
	// Creating Data 1, dataq_size 1, pen_q size 1, roll_over FALSE, use_timeout TRUE
      status = oceos_dataq_create(queue_1, N1, JOBS1, FALSE, TRUE);
      if(SUCCESSFUL != status){
       printf("\nProblem creating dataq queue_1, resulting return code: %u\n", status);
      }   // if
    /*
     * Finish initialising OCEOS and setting up the fixed data
     */
    status = oceos_init_finish();
    if(SUCCESSFUL != status){
     printf("\nAbandoning, problem ending OCEOS initialisation, resulting return code: %u\n", status);
     return -1;
    }   // if
    //1)  Action: Start OCEOS  with Task 1 as initial task, null input pointer
    status = oceos_start(fixed_data, t_producer, NULL);

    return status;                          // returned as an integer

}   // function waits for specific time interval
void test_wait(U32_t interval) {
  volatile U32_t start_time = oceos_time_sys_get32();
  volatile U32_t cur_time = 0;
  while(1) {
      cur_time = oceos_time_sys_get32();
      if ((cur_time - start_time) >= interval ) {
          break;
      }
  }
}
/*
 * Tasks
 */
void t_consumer_task() {
  static int case_number = 0;
  if (case_number == 0) {
      case_number++;
      // 2)  Action: Task 1 attempts to start Task 0
      // Check:  Task 0 has started, pre-empting Task 1
      // a.  Check: entry message from Task 0
      // b.  Check: queue_0 entries is 0
      // c.  Check: queue_1 entries is 0
      printf("t_consumer was started\n");
       if(oceos_dataq_get_size(queue_0)!= 0){
       printf("\nData queue_0 entries is not equal to 0\n");
       }   // if
	   if(oceos_dataq_get_size(queue_1)!= 0){
       printf("\nData queue_1 entries is not equal to 0\n");
       }   // if
  
      // 3) Action: Task 0 does read_restart on queue_0
      oceos_dataq_read_restart_timeout(queue_0, 0);
  } else if (case_number == 1){
      case_number++;
      // 5) Action: Task 1 writes pointer to struct to queue_0
      // Check:  Task 0 has started, pre-empting Task 1
      // a.  Check: entry message from Task 0
      // b.  Check: queue_0 entries count is 1
      // c.  Check: queue_1 entries count is 0
       printf("t_consumer was started\n");
	   if(oceos_dataq_get_size(queue_0)!= 1){
       printf("\nData queue_0 entries is not equal to 1\n");
       }   // if
	   if(oceos_dataq_get_size(queue_1)!= 0){
       printf("\nData queue_1 entries is not equal to 0\n");
       }   // if

      // 6) Action: Task 0 does read_restart on queue 0
      // Check:  Task 0 has succeeded
      // a.  Check: non-null pointer returned
      // b.  Check: queue_0 entries count is 0
      // c.  Check: queue_0 entries count is 0
	   if(oceos_dataq_read_restart_timeout(queue_0, 0) == NULL){
       printf("\nDataq read restart timeout returned null\n");
       }   // if
	   if(oceos_dataq_get_size(queue_0)!= 0){
       printf("\nData queue_0 entries is not equal to 0\n");
       }   // if
       if(oceos_dataq_get_size(queue_1)!= 0){
       printf("\nData queue_1 entries is not equal to 0\n");
       }   // if

      // 7)    Action: Task 0 writes this pointer to queue_1
      // Check:  Task 0 has succeeded
      // a.  Check: queue_0 entries count is 0
      // b.  Check: queue_1 entries count is 1
	   if(oceos_dataq_write(queue_1, &test_data) != SUCCESSFUL){
       printf("\nDataq write was not succesful\n");
       }   // if
       if(oceos_dataq_get_size(queue_0)!= 0){
       printf("\nData queue_0 entries is not equal to 0\n");
       }   // if
	   if(oceos_dataq_get_size(queue_1)!= 1){
       printf("\nData queue_1 entries is not equal to 1\n");
       }   // if

      // 8) Action: Task 0 does read_restart with timeout on queue_0
      // Check:  Task 0 exits as queues_0 is empty
	   if(oceos_dataq_read_restart_timeout(queue_0, TIME_OUT) != NULL){
       printf("\nDataq read restart timeout returned not null\n");
       }   // if
  } else {
      case_number++;
      // 10)   Action: Task 1 loops for at least twice timeout period T
      // Check:  Task 0 restarts on timeout, pre-empting Task 1
      // a.  Check: entry message from Task 0
      // b.  Check: queue_0 entries count is 0
      // c.  Check: queue_1 entries count is 0
       printf("t_consumer was started\n");
	   if(oceos_dataq_get_size(queue_0)!= 0){
       printf("\nData queue_0 entries is not equal to 0\n");
       }   // if
	   if(oceos_dataq_get_size(queue_1)!= 0){
       printf("\nData queue_1 entries is not equal to 0\n");
       }   // if

      // 11)    Action: Task 0 does read_continue on queue_0
      // Check:  Task 0 has succeeded
      // a.  Check: null pointer returned
      // b.  Check: queue_0 entries count is 0
      // c.  Check: queue_1 entries count is 0
	   if(oceos_dataq_read_continue(queue_0) != NULL){
       printf("\nDataq read continue returned not null\n");
       }   // if
       if(oceos_dataq_get_size(queue_0)!= 0){
       printf("\nData queue_0 entries is not equal to 0\n");
       }   // if
	   if(oceos_dataq_get_size(queue_1)!= 0){
       printf("\nData queue_1 entries is not equal to 0\n");
       }   // if

      // 12)   Action: Task 0 exits
      // Check:  Task 0 exit message
      // a.  Check: queue_0 entries count is 0
      // b.  Check: queue_1 entries count is 0
       printf("t_consumer is exiting\n");
       if(oceos_dataq_get_size(queue_0)!= 0){
       printf("\nData queue_0 entries is not equal to 0\n");
       }   // if
	   if(oceos_dataq_get_size(queue_1)!= 0){
       printf("\nData queue_1 entries is not equal to 0\n");
       }   // if
      return;
  }
}//END  t_consumer_task

void t_producer_task() {
  // 1)  Action: Start OCEOS  with Task 1 as initial task, null input pointer
  // Check: Task 1 has started
  // a.  Check: Starting message from Task 1
  // b.  Check: queue_0 entries count is 0
  // c.  Check: queue_0 capacity is as created
  // d.  Check: queue_1 entries count is 0
  // e.  Check: queue_1 capacity is as created
  printf("t_producer was started\n");
   if(oceos_dataq_get_size(queue_0)!= 0){
   printf("\nData queue_0 entries is not equal to 0\n");
   }   // if
   if(oceos_dataq_get_size(queue_1)!= 0){
   printf("\nData queue_1 entries is not equal to 0\n");
   }   // if

  // 2)  Action: Task 1 attempts to start Task 0
   if(oceos_task_start(t_consumer, NULL)!= SUCCESSFUL){
   printf("\nFailed starting task t_consumer\n");
   }   // if

  // 3) Action: Task 0 does read_restart on queue_0
  // Check:  Task 0 exits as queue_0 is empty
  // Check:  Task 1 continues
  // a.  Check: continue message from Task 1
  // b.  Check: queue_0 entries count is 0
  // c.  Check: queue_1 entries count is 0
   printf("t_producer continues \n");
   if(oceos_dataq_get_size(queue_0)!= 0){
   printf("\nData queue_0 entries is not equal to 0\n");
   }   // if
   if(oceos_dataq_get_size(queue_1)!= 0){
   printf("\nData queue_1 entries is not equal to 0\n");
   }   // if

  // 4) Action: Task 1 does read_continue on queue_1
  // Check:   null pointer returned
   if(oceos_dataq_read_continue(queue_1) != NULL){
   printf("\nDataq read continue returned not null\n");
   }   // if

  // 5) Action: Task 1 writes pointer to struct to queue_0
   if(oceos_dataq_write(queue_0, &test_data) != SUCCESSFUL){
   printf("\nDataq write failed\n");
   }   // if

  // 8) Action: Task 0 does read_restart with timeout on queue_0
  // Check:  Task 0 exits as queues_0 is empty
  // Check:  Task 1 continues
  // a.  Check: continue message from Task 1
  // b.  Check: queue_0 entries count is 0
  // c.  Check: queue_1 entries count is 1
   printf("t_producer continues \n");
   if(oceos_dataq_get_size(queue_0)!= 0){
   printf("\nData queue_0 entries is not equal to 0\n");
   }   // if
   if(oceos_dataq_get_size(queue_1)!= 1){
   printf("\nData queue_1 entries is not equal to 1\n");
   }   // if

  // 9) Action: Task 1 does read_continue on queue_1
  // Check:  Non-null pointer returned
  // a.  Check: pointer to same struct
  // b.  Check: queue_0 entries count is 0
  // c.  Check: queue_1 entries count is 0
   struct data *temp_data = oceos_dataq_read_continue(queue_1);
   if(temp_data == NULL){
   printf("\ntemp_data is null\n");
   }   // if
   if(test_data.message != temp_data->message){
   printf("\npointer not to same struct\n");
   }   // if
   if(oceos_dataq_get_size(queue_0)!= 0){
   printf("\nData queue_0 entries is not equal to 0\n");
   }   // if
   if(oceos_dataq_get_size(queue_1)!= 0){
   printf("\nData queue_1 entries is not equal to 0\n");
   }   // if

  // 10)   Action: Task 1 loops for at least three timeout period
  // Check:  Task 0 restarts on timeout, pre-empting Task 1
  test_wait(TIME_OUT * 3);

  //Task 1 writes pointer to struct on queue_1
   if(oceos_dataq_write(queue_1, &test_data) != SUCCESSFUL){
   printf("\nDataq write failed\n");
   }   // if
  // Data q size check
   if(oceos_dataq_get_size(queue_1)!= 1){
   printf("\nData queue_1 entries is not equal to 1\n");
   }   // if
  // Task 1 does read restart on queue_1
   if(oceos_dataq_read_restart(queue_1) == NULL){
   printf("\nDataq read restart failed\n");
   }   // if
  // Data q size check
   if(oceos_dataq_get_size(queue_1)!= 0){
   printf("\nData queue_1 entries is not equal to 0\n");
   }   // if
  //Task 1 writes pointer to struct on queue_1
   if(oceos_dataq_write(queue_1, &test_data) != SUCCESSFUL){
   printf("\nDataq write failed\n");
   }   // if
  // Data q size check
   if(oceos_dataq_get_size(queue_1)!= 1){
   printf("\nData queue_1 entries is not equal to 1\n");
   }   // if
  // Data q clear
   if(oceos_dataq_clear(queue_1)!= 0){
   printf("\nDataq clear failed\n");
   }   // if
  
  // Data q size check
   if(oceos_dataq_get_size(queue_1)!= 0){
   printf("\nData queue_1 entries is not equal to 0\n");
   }   // if
  // Data pending q size check
   if(oceos_dataq_penq_get_size(queue_1) != 0){
   printf("\nDataq pending queue not equal to 0\n");
   }   // if

  // 14)   Action: Task 1 terminates
   // Check:  Task 1 exit message
   printf("t_producer is exiting\n");

  // 15) Action: CPU placed in sleep mode
  // Check:  Sleep mode starting message
   if(oceos_exit() != SUCCESSFUL){
   printf("\nOceos exiting failed\n");
   }   // if
   
  return;
}