OCEOS/oceos use
Introduction
OCEOS is provided as an object library, documentation and example source code.
Setup for the use of OCEOS requires the user to prepare the development environment. At a minimum this requires the installation for compilers, debug tool, editors, …etc.
The OCEOS build and test environment requires the following:
- SPARC Build environment (compiler, linker, libraries, etc.) Download here.
- ARM Build environment Download here and Download here
- Debug software tool e.g. OCE’s DMON. Evaluation download.
Content of Customer Release
Documentation/
OCEOS_User_Manual.pdf // OCEOS User Manual
Examples/
AreaDisplay/ // OCEOS project to display sizes of data areas described HERE
arm_startup/ // Some start up files for Microchip Cortex-M3 and M7 developments boards, used in DEMO projects below
asw/ // DEMO project of main OCEOS features
SampleProject/ // Skeleton project that can be used to start development
tut1/ // This project demonstrates starting tasks with different priorities.
tut2/ // This project familiarize the developer with the use a mutexes.
tut3/ // This project demonstrates the use of semaphores for task synchronization.
tut4/ // This project introduces the use of timer interrupts to start the task.
tut5/ // This project introduces the use of data queue with timeouts.
include/ // OCEOS header files
OCEOS_GCC_LIB/
liboceos.lib // OCEOS library that can be linked with application
README.txt // Notes
OCEOS Normal operations
The scheduling is started after calling oceos_start(). The main structure of application flow is described below:
- oceos_init() - Initialize fixed data and start system time and log
- Create:
- oceos_task_create() - Create task, setting priority, no of jobs, ..etc.
- oceos_mutex_create() - Create mutexes if require
- oceos_dataq_create() - Create data queues if require
- oceos_sem_create() - Create semaphores if require
- oceos_init_finish() - Initialize dynamic data area
- oceos_start() - Start the scheduler and pass control to first task
Note
It is mandatory to create the number of tasks, mutexes, semaphores, and data queues declared in oceos_config.h otherwise oceos_init_finish() will return an error.
OCEOS configuration parameters are shown below. In provided demo projects these are oceos_config.h and oceos_config.c. More information can be found by clicking on the link for parameter that is of interest.
// 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 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 10 //---------------------------------------------------------------------------- // 5: Number of Mutexes #define NUMBER_OF_MUTEXES 2 // 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 0x100 // Calculated value. Read manual //---------------------------------------------------------------------------- // 9: FIXED data array size #define FIXED_DATA_ARRAY_SIZE_U32S 0x100 // Calculated value. Read manual //---------------------------------------------------------------------------- // 10: DYNAMIC data array size #define DYN_DATA_ARRAY_SIZE_U32S 0x100 // 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 // Used by DMON OCEOS profile to display stack usage //---------------------------------------------------------------------------- // 14: OCEOS stack end address #define OCEOS_STACK_LOW_BOUND_ADDRESS 0 // Used by DMON OCEOS profile to display stack usage
application_init() function shown below creates OCEOS configuration struct and sets configuration parameter that passed to oceos_init().
/*
* 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
#ifdef __sparc__
/**
* FOR SPARC TARGET ONLY.
* Not Used for ARM. Always Nested
*/
app_config.interrupt_nesting_enabled = TRUE; // Nesting Enabled
#endif
// 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;
#ifdef __sparc__
/**
* FOR SPARC TARGET ONLY.
* ARM SysTick is used for System Time
*/
app_config.sys_time_timer_index = SYS_TIME_TIMER_INDEX; // 0 => invalid index
#endif
app_config.timed_actions_queue_size = NUMBER_OF_ACTION_ENTRIES;
app_config.CS_log_entries_base2 = CS_LOG_DEF_ENTRIES_BASE2;
// System time is used by timed actions, semaphores with timeout, dataqs with timeout, logging and profiling.
// If all of above are not required then system time can be disabled. The system will not be interrupted by SysTick while CPU in sleep mode,
//but it is not the case for SPARC targets,
// as system time implemented by chaining two timers without interrupting.
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()
Building the example application
OCE Technology provides sample make files that can be used by application developer. Those files are located in demo projects of Examples folder. If make is called from one of the demo projects, than user requires only to modify variable TOOLCHAIN_PATH in tools_config_arm.mk to point to toolchain folder. User can use make files to build project for one of the supported development board.
Note
User requires to modify make files to add own development board.
Make file available parameters for ARM:
- Build target: all
- ARM_BUILD=1
- TOOLCHAIN=armclangv6|gcc|segger|iar
- RELEASE=0|1
- MCPU=cortex-m3|cortex-m7
- BOARD=ATSAM3X8E|ATSAMV71Q21
- FPU=0|1
- SAMV71_CONSOLE=0|1
Example: make all ARM_BUILD=1 FPU=1 TOOLCHAIN=gcc RELEASE=1 MCPU=cortex-m7 BOARD=ATSAMV71Q21
Make file available parameters for SPARC:
- Build target: all
- TOOLCHAIN=gcc|clang
- RELEASE=0|1
- MREX=1
- BSP=gr716|pm698|gr712rc|gr740|agga4|at697
Example: make all TOOLCHAIN=clang BSP=gr716 or make all TOOLCHAIN=clang BSP=gr716 MREX=1
Troubleshooting
oceos_init_interrrupt_manager() is failing with data store error
Solution
OCEOS is initializing interrupt trap table with OCEOS handler, replacing default handlers. If application is run from flash, than replacing interrupt trap table entries give data store error, as it cannot write to flash.
We would suggest you to move interrupt vector table __bcc_trap_table_svt_1 to SRAM. __bcc_trap_table_svt_1 is a weak symbol, so could be recreated and replaced by linker. If you are planning to add other trap handlers, you need to modify trap tables at compile time or move all trap tables to SRAM to use bcc_set_trap() at run time.
OCEOS Demo Tutorials
Tutorial 1 – Starting tasks
This exercise demonstrates starting tasks with different priorities.
- Two tasks, one higher priority (i.e. lower priority value), one lower priority (i.e. higher priority value. Each task allowed to have up to two concurrent jobs.
- Each task outputs a message when it starts, another message when it exits.
- Start OCEOS with the low priority task.
- This starts the high priority task and then exits.
- The high priority task starts the low priority tasks and exits.
For code example see below.
tut.h
/*
*********************************************************************************************************
* OCEOS
* Real-Time Operating System
* for
* SPARC and ARM Microcontrollers
*
* 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
* SPARC and ARM Microcontrollers
*
* 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
* SPARC and ARM Microcontrollers
*
* 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
* SPARC and ARM Microcontrollers
*
* 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.
- Two tasks as before.
- One mutex. Note the priority ceiling of the mutex.
- Both tasks output message when they get the mutex and when they return it
- Start OCEOS with the low priority task
- This grabs mutex, then starts high priority task
- Low priority task returns mutex then exits
- High priority task returns mutex, start low priority task and exits
For code example see example below:
tut2.h
/*
*********************************************************************************************************
* OCEOS
* Real-Time Operating System
* for
* SPARC and ARM Microcontrollers
*
* 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
* SPARC and ARM Microcontrollers
*
* 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
* SPARC and ARM Microcontrollers
*
* 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
* SPARC and ARM Microcontrollers
*
* 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.
- Three tasks this time, one high priority and the other two with the same lower priority
- Two counting semaphores, one initially 0, one initially 4, called ‘items’ and ‘spaces’
- First task starts second and third tasks
- Second task loops
- wait_restart spaces
- signal items
- Output ‘item done’ message
- Third task loops
- wait_restart items
- Output ‘got item’ message
- signal spaces
For code example see below:
tut3.h
/*
*********************************************************************************************************
* OCEOS
* Real-Time Operating System
* for
* SPARC and ARM Microcontrollers
*
* 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
* SPARC and ARM Microcontrollers
*
* 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
* SPARC and ARM Microcontrollers
*
* 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
* SPARC and ARM Microcontrollers
*
* 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.
- Create one task
- Set a timer to interrupt every 2 seconds
- Set timer handler to start task
- Task outputs message, then exits
For code example see below:
tut4.h
/*
*********************************************************************************************************
* OCEOS
* Real-Time Operating System
* for
* SPARC and ARM Microcontrollers
*
* 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
* SPARC and ARM Microcontrollers
*
* 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
* SPARC and ARM Microcontrollers
*
* 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
* SPARC and ARM Microcontrollers
*
* 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
* SPARC and ARM Microcontrollers
*
* 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 data queue with timeouts.
- Create functions to be used by tasks
- Create one struct – pointer to these will be placed on queues
- Set timeout period T
- Create configuration structure with above configuration values for fields
- Initialize OCEOS using oceos_init()
- Create two tasks
- 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;
}