Difference between revisions of "OCEOS/oceos use"
Okhoruzhyy (talk | contribs) |
Okhoruzhyy (talk | contribs) |
||
(33 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
=<span style="color:#0000ff">'''Introduction'''</span>= | =<span style="color:#0000ff">'''Introduction'''</span>= | ||
OCEOS is provided as an object library, documentation and example source code.<br> | |||
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.<br> | ||
<p>The OCEOS build and test environment requires the following:</p> | <p>The OCEOS build and test environment requires the following:</p> | ||
# SPARC Build environment (compiler, linker, libraries, etc.) [https://www.gaisler.com/index.php/downloads/compilers?task=view&id=161 Download here]. | # SPARC Build environment (compiler, linker, libraries, etc.) [https://www.gaisler.com/index.php/downloads/compilers?task=view&id=161 Download here]. | ||
# ARM Build environment [https://developer.arm.com/tools-and-software/embedded/arm-compiler Download here] and [https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm Download here] | # ARM Build environment [https://developer.arm.com/tools-and-software/embedded/arm-compiler Download here] and [https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm Download here] | ||
# Debug software tool e.g. OCE’s DMON. [http://ocetechnology.com/?page_id=306 Evaluation download]. | # Debug software tool e.g. OCE’s DMON. [http://ocetechnology.com/?page_id=306 Evaluation download]. | ||
====<span style="color:#0000ff">Content of Customer Release</span>==== | |||
'''Documentation'''/ | |||
OCEOS_User_Manual.pdf // OCEOS User Manual | |||
'''Examples'''/ | |||
AreaDisplay/ // OCEOS project to display sizes of data areas described [[OCEOS/oceos_introduction#OCEOS_Data_Area_Layouts|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 | |||
====<span style="color:#0000ff">OCEOS Normal operations</span>==== | |||
The scheduling is started after calling [[OCEOS/oceos kernel/initialisation#oceos_start()|oceos_start()]]. The main structure of application flow is described below: | |||
# [[OCEOS/oceos kernel/initialisation#oceos_init()|oceos_init()]] - Initialize fixed data and start system time and log | |||
# Create: | |||
#* [[OCEOS/oceos kernel/task#oceos_task_create()|oceos_task_create()]] - Create task, setting priority, no of jobs, ..etc. | |||
#* [[OCEOS/oceos inter-task communication/mutex#oceos_mutex_create()|oceos_mutex_create()]] - Create mutexes if require | |||
#* [[OCEOS/oceos inter-task communication/dataq#oceos_dataq_create()|oceos_dataq_create()]] - Create data queues if require | |||
#* [[OCEOS/oceos inter-task communication/semaphore#oceos_sem_create()|oceos_sem_create()]] - Create semaphores if require | |||
# [[OCEOS/oceos kernel/initialisation#oceos_init_finish()|oceos_init_finish()]] - Initialize dynamic data area | |||
# [[OCEOS/oceos kernel/initialisation#oceos_start()|oceos_start()]] - Start the scheduler and pass control to first task | |||
<blockquote style="background-color: #c6e2f7; border-left-style: solid; border-left-width: 3px; border-left-color: blue; "> '''Note'''<br> | |||
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. | |||
</blockquote> | |||
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 [[OCEOS/oceos_logging#Logging_Configuration|NUMBER_OF_LOG_ENTRIES]] 16 // ''16 to 1024, default 64'' | |||
//---------------------------------------------------------------------------- | |||
// ''3: Number of tasks'' | |||
#define [[OCEOS/oceos_kernel/task#Task_Configuration|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 [[OCEOS/oceos_kernel/task#Task_Configuration|NUMBER_OF_READYQ_ENTRIES]] 10 | |||
//---------------------------------------------------------------------------- | |||
// ''5: Number of Mutexes'' | |||
#define [[OCEOS/oceos_inter-task_communication/mutex#Mutex_Configuration|NUMBER_OF_MUTEXES]] 2 // ''0 to 63'' | |||
//---------------------------------------------------------------------------- | |||
// ''6: Number of Semaphores'' | |||
#define [[OCEOS/oceos_inter-task_communication/semaphore#Semaphore_Configuration|NUMBER_OF_SEMAPHORES]] 0 // ''0 to 63'' | |||
//---------------------------------------------------------------------------- | |||
// ''7: Number of Data Qs'' | |||
#define [[OCEOS/oceos_inter-task_communication/dataq#Data_Queue_Configuration|NUMBER_OF_DATAQS]] 0 // ''0 to 63'' | |||
//---------------------------------------------------------------------------- | |||
// ''8: LOG data array size'' | |||
#define [[OCEOS/oceos_logging#Logging_Configuration|LOG_DATA_ARRAY_SIZE_U32S]] 0x100 // ''Calculated value. Read manual'' | |||
//---------------------------------------------------------------------------- | |||
// ''9: FIXED data array size'' | |||
#define [[OCEOS/oceos_introduction#OCEOS_Data_Area_Layouts|FIXED_DATA_ARRAY_SIZE_U32S]] 0x100 // ''Calculated value. Read manual'' | |||
//---------------------------------------------------------------------------- | |||
// ''10: DYNAMIC data array size'' | |||
#define [[OCEOS/oceos_introduction#OCEOS_Data_Area_Layouts|DYN_DATA_ARRAY_SIZE_U32S]] 0x100 // ''Calculated value. Read manual'' | |||
//---------------------------------------------------------------------------- | |||
// ''11: Timed Actions'' | |||
#define [[OCEOS/oceos_timed_actions#Timed_Actions_Configuration|NUMBER_OF_ACTION_ENTRIES]] 0 // ''User-modify field'' | |||
//---------------------------------------------------------------------------- | |||
// ''12: Log entries base 2'' | |||
#define [[OCEOS/oceos_profiling#Configuration|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/oceos kernel/initialisation#oceos_init()|oceos_init()]]. | |||
<syntaxhighlight lang="C"> | |||
/* | |||
* 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() | |||
</syntaxhighlight> | |||
====<span style="color:#0000ff">Building the example application</span>==== | |||
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. | |||
<blockquote style="background-color: #c6e2f7; border-left-style: solid; border-left-width: 3px; border-left-color: blue; "> '''Note'''<br> | |||
User requires to modify make files to add own development board. | |||
</blockquote> | |||
Make file available parameters for ARM:<br> | |||
* 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:<br> | |||
* 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 | |||
====<span style="color:#0000ff">Troubleshooting</span>==== | |||
=====oceos_init_interrrupt_manager() is failing with data store error===== | |||
<blockquote style="background-color: #c6e2f7; border-left-style: solid; border-left-width: 3px; border-left-color: blue; "> '''Solution'''<br> | |||
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. | |||
</blockquote> | |||
=<span style="color:#0000ff">'''OCEOS Demo Tutorials'''</span>= | =<span style="color:#0000ff">'''OCEOS Demo Tutorials'''</span>= | ||
=<span style="color:#0000ff">''' | ===<span style="color:#0000ff">Tutorial 1 – Starting tasks</span>=== | ||
TODO | |||
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''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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_ */ | |||
</syntaxhighlight> | |||
'''''oceos_config.h''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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_ */ | |||
</syntaxhighlight> | |||
'''''oceos_config.c''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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; | |||
} | |||
</syntaxhighlight> | |||
'''''tut1.c''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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() | |||
</syntaxhighlight> | |||
===<span style="color:#0000ff">Tutorial 2 – Using a mutex</span>=== | |||
<p>This exercise will familiarise the developer with the use a mutexes.</p> | |||
# Two tasks as before. | |||
# One mutex. Note the priority ceiling of the mutex. | |||
# Both tasks output message when they get the mutex and when they return it | |||
# Start OCEOS with the low priority task | |||
# This grabs mutex, then starts high priority task | |||
# Low priority task returns mutex then exits | |||
# High priority task returns mutex, start low priority task and exits | |||
For code example see example below: | |||
'''''tut2.h''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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_ */ | |||
</syntaxhighlight> | |||
'''''oceos_config.h''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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_ */ | |||
</syntaxhighlight> | |||
'''''oceos_config.c''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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; | |||
} | |||
</syntaxhighlight> | |||
'''''tut2.c''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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() | |||
</syntaxhighlight> | |||
===<span style="color:#0000ff">Tutorial 3 – Using Semaphores</span>=== | |||
<p>Semaphores can be used to synchronise task actions as in this exercise.</p> | |||
<ol> | |||
<li>Three tasks this time, one high priority and the other two with the same lower priority</li> | |||
<li>Two counting semaphores, one initially 0, one initially 4, called ‘items’ and ‘spaces’</li> | |||
<li>First task starts second and third tasks</li> | |||
<li>Second task loops | |||
<ol style="list-style-type: lower-latin;"> | |||
<li>wait_restart spaces</li> | |||
<li>signal items</li> | |||
<li>Output ‘item done’ message</li> | |||
</li> | |||
</ol> | |||
<li>Third task loops | |||
<ol style="list-style-type: lower-latin;"> | |||
<li>wait_restart items</li> | |||
<li>Output ‘got item’ message</li> | |||
<li>signal spaces</li> | |||
</li> | |||
</ol> | |||
</li> | |||
</ol> | |||
For code example see below: | |||
'''''tut3.h''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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_ */ | |||
</syntaxhighlight> | |||
'''''oceos_config.h''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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_ */ | |||
</syntaxhighlight> | |||
'''''oceos_config.c''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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; | |||
} | |||
</syntaxhighlight> | |||
'''''tut3.c''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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() | |||
</syntaxhighlight> | |||
===<span style="color:#0000ff">Tutorial 4 – Timer interrupt starts task</span>=== | |||
<p>This exercise introduces the use of timer interrupts.</p> | |||
# 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''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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_ */ | |||
</syntaxhighlight> | |||
'''''oceos_config.h''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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_ */ | |||
</syntaxhighlight> | |||
'''''oceos_config.c''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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; | |||
} | |||
</syntaxhighlight> | |||
'''''arm_task_src.c''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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 | |||
} | |||
</syntaxhighlight> | |||
'''''tut4.c''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* 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() | |||
</syntaxhighlight> | |||
===<span style="color:#0000ff">Tutorial 5 – Using dataq with timed action</span>=== | |||
<p>This exercise introduces the use of data queue with timeouts.</p> | |||
# 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''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
****************************************************************************** | |||
* 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 */ | |||
</syntaxhighlight> | |||
'''''oceos_config.h''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
* 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_ */ | |||
</syntaxhighlight> | |||
'''''oceos_config.c''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
* 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; | |||
} | |||
</syntaxhighlight> | |||
'''''tut5.c''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
****************************************************************************** | |||
* 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; | |||
} | |||
</syntaxhighlight> | |||
<!-- =<span style="color:#0000ff">'''Drivers Porting Example'''</span>= | |||
In common situation embedded application would call list of functions in a while loop and interrupt service routines are used for critical operations.<br> | |||
Using RTOS for the same application would make developers life easier and would save power consumption. | |||
Each function in a list of while loop can represent the task and started only when something really happen. Most of RTOS available today would use priority controlled round-robin scheduling. Where the tasks require different response time developer could assigned different priorities for those tasks and scheduling according to those priorities. Tasks with the same priorities are scheduled using round-robin. | |||
This is where OCEOS is different. | |||
--> | |||
[[Category:backup]] | [[Category:backup]] |
Latest revision as of 13:48, 20 April 2022
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
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #ifndef TUT1_H_
19 #define TUT1_H_
20
21 /* Sample Task names - all here start with t_ to help avoid name confusion */
22 enum TASK_NAME{
23 t_0, // High priority task
24 t_1 // Low priority task
25 };
26
27 char* nullPtr = ""; // Need pointer to pass to oceos_start
28 void (*nullFun)(void *); // Null function
29
30 /*
31 * APPLICATION FUNCTION DECLARATIONS
32 */
33 void fun0(void *);
34 void fun1(void *);
35
36 #endif /* TUT1_H_ */
oceos_config.h
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #ifndef INCLUDE_OCEOS_CONFIG_H_
19 #define INCLUDE_OCEOS_CONFIG_H_
20
21 // 1: Includes OCEOS main header file
22 #include "oceos.h"
23 //----------------------------------------------------------------------------
24 // 2: Number of Log entries.
25 #define NUMBER_OF_LOG_ENTRIES 64 // 16 to 1024, default 64
26 //----------------------------------------------------------------------------
27 // 3: Number of tasks
28 #define NUMBER_OF_TASKS 2 // 1 to 255
29 //----------------------------------------------------------------------------
30 // 4: Number of ready queue entries, 0 to 254, see manual( MUST BE UPDATED BY USER);
31 // Defaults to number of tasks, as each task should have aa least one job;
32 // If Number of ready Q entries larger that number of total jobs => defaults to number of total jobs
33 #define NUMBER_OF_READYQ_ENTRIES NUMBER_OF_TASKS * 2
34 //----------------------------------------------------------------------------
35 // 5: Number of Mutexes
36 #define NUMBER_OF_MUTEXES 0 // 0 to 63
37 //----------------------------------------------------------------------------
38 // 6: Number of Semaphores
39 #define NUMBER_OF_SEMAPHORES 0 // 0 to 63
40 //----------------------------------------------------------------------------
41 // 7: Number of Data Qs
42 #define NUMBER_OF_DATAQS 0 // 0 to 63
43 //----------------------------------------------------------------------------
44 // 8: LOG data array size
45 #define LOG_DATA_ARRAY_SIZE_U32S 0x88// Calculated value. Read manual
46 //----------------------------------------------------------------------------
47 // 9: FIXED data array size
48 #define FIXED_DATA_ARRAY_SIZE_U32S 0x32// Calculated value. Read manual
49 //----------------------------------------------------------------------------
50 // 10: DYNAMIC data array size
51 #define DYN_DATA_ARRAY_SIZE_U32S 0x33// Calculated value. Read manual
52 //----------------------------------------------------------------------------
53 // 11: Timed Actions
54 #define NUMBER_OF_ACTION_ENTRIES 0 // User-modify field
55 //----------------------------------------------------------------------------
56 // 12: Log entries base 2
57 #define CS_LOG_DEF_ENTRIES_BASE2 0
58 //----------------------------------------------------------------------------
59 // 13: OCEOS stack start Address
60 #define OCEOS_STACK_START_ADDRESS 0
61 //----------------------------------------------------------------------------
62 // 14: OCEOS stack end address
63 #define OCEOS_STACK_LOW_BOUND_ADDRESS 0
64 //----------------------------------------------------------------------------
65 /**
66 * Target specific configurations
67 */
68 /*
69 * ARM specific configurations
70 */
71 #ifdef __SAM3X8E__
72 #ifndef BSP_SYSFREQ
73 #define BSP_SYSFREQ 84 // ARM target frequency in Mhz
74 #endif
75 #endif
76 #ifdef __SAMV71Q21__
77 #ifndef BSP_SYSFREQ
78 #define BSP_SYSFREQ 300 // ARM target frequency in Mhz
79 #endif
80 #endif
81 #ifdef __VA41620__
82 #ifndef BSP_SYSFREQ
83 #define BSP_SYSFREQ 100 // ARM target frequency in Mhz
84 #endif
85 #endif
86 //--------------------------------------------------------------------
87 // User defined function to deal with system errors
88 void oceos_on_error(void);
89 //---------------------------------------------------------------------
90 // User defined function to deal with log 2/3 full
91 void oceos_on_full_log(void);
92 //---------------------------------------------------------------------
93 extern U32_t log_data[];
94 extern U32_t fixed_data[];
95 extern U32_t dynamic_data[];
96 extern const unsigned int __oceos_bsp_sysfreq;
97 /**
98 * Initialize OCEOS with user configurations
99 */
100 int application_init(void);
101 #endif /* INCLUDE_OCEOS_CONFIG_H_ */
oceos_config.c
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #include <stdio.h>
19 #include "oceos_config.h"
20
21 /*
22 * OCEOS INTERNAL DATA STORAGE
23 *
24 * This application defines arrays to hold OCEOS internal data.
25 * The array sizes are provided by DMON by running "oceos info" command:</br>
26 * *Set all three arrays to guessed max zise, run application for the first time and exit.</br>
27 * *Run DMON command "oceos info" to get size for each array.</br>
28 * *Update array sizes below
29 */
30 U32_t log_data[LOG_DATA_ARRAY_SIZE_U32S];
31
32 U32_t fixed_data[FIXED_DATA_ARRAY_SIZE_U32S] = {0}; // will be in data segment
33
34 U32_t dynamic_data[DYN_DATA_ARRAY_SIZE_U32S];
35
36 const unsigned int __oceos_bsp_sysfreq = BSP_SYSFREQ * 1000 * 1000;// TODO
37
38 static BOOLE_t log_full_was_called = FALSE;
39
40 /**
41 * Must be defined if Application is using :
42 * Dataq with timeout
43 * Semaphore with timeout
44 * Timed Actions
45 */
46 /*
47 * Set up the application configuration structure and pass it to oceos_init
48 * (done this way the memory used for the structure is returned automatically)
49 */
50
51 int application_init(){
52
53 /*
54 * Create the application configuration structure
55 */
56 struct application_configuration app_config = {0};
57
58 /*
59 * Fill in the application parameters
60 */
61 app_config.log_address = (adrs_t)log_data; // required
62 app_config.fixed_data_address = (adrs_t)fixed_data; // required
63 app_config.dynamic_data_address = (adrs_t)dynamic_data; // required
64
65 app_config.stack_start_address = OCEOS_STACK_START_ADDRESS; // 0 => no check
66 app_config.stack_lower_bound_address = OCEOS_STACK_LOW_BOUND_ADDRESS; // 0 => no check
67
68 app_config.system_error_function = &oceos_on_error; // NULL => ignore
69 app_config.log_full_function = &oceos_on_full_log; // NULL => ignore
70 // used in setting up system log and fixed data array
71 app_config.log_number_of_entries = NUMBER_OF_LOG_ENTRIES; // 0 => use default
72
73 app_config.number_of_tasks = NUMBER_OF_TASKS; // >= 1
74 app_config.number_of_readyQ_entries = NUMBER_OF_READYQ_ENTRIES; // 0 => calculate size
75
76 app_config.number_of_mutexes = NUMBER_OF_MUTEXES;
77 app_config.number_of_counting_semaphores = NUMBER_OF_SEMAPHORES;
78 app_config.number_of_data_queues = NUMBER_OF_DATAQS;
79
80 app_config.timed_actions_queue_size = NUMBER_OF_ACTION_ENTRIES;
81 app_config.CS_log_entries_base2 = CS_LOG_DEF_ENTRIES_BASE2;
82 app_config.use_oceos_system_time = TRUE;
83
84 // initialise OCEOS
85 enum DIRECTIVE_STATUS status;
86 status = oceos_init(app_config);
87
88 if (SUCCESSFUL == status) {
89 return 1;
90 } else {
91 printf("\n oceos_init failure\n");
92 return -1;
93 } // else
94 } // application_init()
95 /**
96 * User to implement in case of system error;
97 * Comment it out if not used and set field system_error_function in app_config to NULL
98 */
99 void oceos_on_error() {
100 return;
101 }
102 /**
103 * User to implement in case of system log is 2/3 full;
104 * Comment it out if not used and set field log_full_function in app_config to NULL
105 */
106 void oceos_on_full_log(){
107 log_full_was_called = TRUE;
108 return;
109 }
tut1.c
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include "tut1.h" // application header
21 #include "oceos_config.h" // OCEOS header
22
23 int main(void) {
24 int status;
25
26 /*
27 * Initialise the application configuration and OCEOS
28 *
29 * This application function creates the application configuration
30 * and passes it to oceos_init(), which initialises the fixed data
31 * and enables the system log
32 */
33 if (!application_init()) {
34 //LOG
35 return -1;
36 }
37
38 // Create Main task to
39 if (oceos_task_create(t_0,// taskID, used as index, must be in range 0 to 254
40 100,// priority, must be in range 1 to 254, lower value is higher priority
41 100, // threshold, must be in range 1 to task priority
42 2, // jobs_max, must be in range 1 to 15
43 0,// FALSE -> floating point hardware not used by task
44 1, // FALSE -> task initially not enabled
45 fun0, // main body of task
46 nullFun, // task end function
47 0,// time_deadline, must finish no later than this after start, 0 => ignore
48 0 // minimum time expected between start requests, 0 => no restriction
49 ) != SUCCESSFUL)
50 return 1;
51
52 if (oceos_task_create(t_1, 200, 200, 2, 0, 1, fun1, nullFun, 0, 0)
53 != SUCCESSFUL)
54 return 2;
55
56 /*
57 * Finish initialising OCEOS and setting up the fixed data
58 */
59 status = oceos_init_finish();
60 if (SUCCESSFUL != status) {
61 return 3;
62 } // if
63
64 /*
65 * Start OCEOS scheduling
66 *
67 * The OCEOS fixed data provides all the information required.
68 *
69 * If a valid task is specified, it is started and passed the pointer.
70 * Otherwise the system is put in sleep mode
71 */
72 status = oceos_start(fixed_data, t_1, (void*) nullPtr); // Start OCEOS with lower prioroty task
73 return status;
74 } // main
75
76 /*
77 * Application code functions, functions declared in asw.h
78 */
79 void fun0(void *ptr) {
80 printf("Entered high priority task\n");
81 oceos_task_start(t_1, ptr);
82 printf("Leaving high priority task\n");
83 return;
84 } // fun0()
85
86 void fun1(void *ptr) {
87 printf("Entered low priority task\n");
88 oceos_task_start(t_0, ptr);
89 printf("Leaving low priority task\n");
90 return;
91 } // fun1()
Tutorial 2 – Using a mutex
This exercise will familiarise the developer with the use a mutexes.
- 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
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #ifndef TUT2_H_
19 #define TUT2_H_
20
21 /* Sample Task names - all here start with t_ to help avoid name confusion */
22 enum TASK_NAME{
23 t_0, // High priority task
24 t_1 // Low priority task
25 };
26 /* Sample Mutex names - all here start with m_ to help avoid name confusion */
27 enum MUTEX_NAME{
28 m_0
29 };
30 char* nullPtr = ""; // Need pointer to pass to oceos_start
31 void (*nullFun)(void *); // Null function
32
33 /*
34 * APPLICATION FUNCTION DECLARATIONS
35 */
36 void fun0(void *);
37 void fun1(void *);
38
39 #endif /* TUT2_H_ */
oceos_config.h
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #ifndef INCLUDE_OCEOS_CONFIG_H_
19 #define INCLUDE_OCEOS_CONFIG_H_
20
21 // 1: Includes OCEOS main header file
22 #include "oceos.h"
23 //----------------------------------------------------------------------------
24 // 2: Number of Log entries.
25 #define NUMBER_OF_LOG_ENTRIES 64 // 16 to 1024, default 64
26 //----------------------------------------------------------------------------
27 // 3: Number of tasks
28 #define NUMBER_OF_TASKS 2 // 1 to 255
29 //----------------------------------------------------------------------------
30 // 4: Number of ready queue entries, 0 to 254, see manual( MUST BE UPDATED BY USER);
31 // Defaults to number of tasks, as each task should have aa least one job;
32 // If Number of ready Q entries larger that number of total jobs => defaults to number of total jobs
33 #define NUMBER_OF_READYQ_ENTRIES NUMBER_OF_TASKS * 2
34 //----------------------------------------------------------------------------
35 // 5: Number of Mutexes
36 #define NUMBER_OF_MUTEXES 1 // 0 to 63
37 //----------------------------------------------------------------------------
38 // 6: Number of Semaphores
39 #define NUMBER_OF_SEMAPHORES 0 // 0 to 63
40 //----------------------------------------------------------------------------
41 // 7: Number of Data Qs
42 #define NUMBER_OF_DATAQS 0 // 0 to 63
43 //----------------------------------------------------------------------------
44 // 8: LOG data array size
45 #define LOG_DATA_ARRAY_SIZE_U32S 0x88// Calculated value. Read manual
46 //----------------------------------------------------------------------------
47 // 9: FIXED data array size
48 #define FIXED_DATA_ARRAY_SIZE_U32S 0x33// Calculated value. Read manual
49 //----------------------------------------------------------------------------
50 // 10: DYNAMIC data array size
51 #define DYN_DATA_ARRAY_SIZE_U32S 0x34// Calculated value. Read manual
52 //----------------------------------------------------------------------------
53 // 11: Timed Actions
54 #define NUMBER_OF_ACTION_ENTRIES 0 // User-modify field
55 //----------------------------------------------------------------------------
56 // 12: Log entries base 2
57 #define CS_LOG_DEF_ENTRIES_BASE2 0
58 //----------------------------------------------------------------------------
59 // 13: OCEOS stack start Address
60 #define OCEOS_STACK_START_ADDRESS 0
61 //----------------------------------------------------------------------------
62 // 14: OCEOS stack end address
63 #define OCEOS_STACK_LOW_BOUND_ADDRESS 0
64 //----------------------------------------------------------------------------
65 /**
66 * Target specific configurations
67 */
68 /*
69 * ARM specific configurations
70 */
71 #ifdef __SAM3X8E__
72 #ifndef BSP_SYSFREQ
73 #define BSP_SYSFREQ 84 // ARM target frequency in Mhz
74 #endif
75 #endif
76 #ifdef __SAMV71Q21__
77 #ifndef BSP_SYSFREQ
78 #define BSP_SYSFREQ 300 // ARM target frequency in Mhz
79 #endif
80 #endif
81 #ifdef __VA41620__
82 #ifndef BSP_SYSFREQ
83 #define BSP_SYSFREQ 100 // ARM target frequency in Mhz
84 #endif
85 #endif
86 //--------------------------------------------------------------------
87 // User defined function to deal with system errors
88 void oceos_on_error(void);
89 //---------------------------------------------------------------------
90 // User defined function to deal with log 2/3 full
91 void oceos_on_full_log(void);
92 //---------------------------------------------------------------------
93 extern U32_t log_data[];
94 extern U32_t fixed_data[];
95 extern U32_t dynamic_data[];
96 extern const unsigned int __oceos_bsp_sysfreq;
97 /**
98 * Initialize OCEOS with user configurations
99 */
100 int application_init(void);
101 #endif /* INCLUDE_OCEOS_CONFIG_H_ */
oceos_config.c
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #include <stdio.h>
19 #include "oceos_config.h"
20
21 /*
22 * OCEOS INTERNAL DATA STORAGE
23 *
24 * This application defines arrays to hold OCEOS internal data.
25 * The array sizes are provided by DMON by running "oceos info" command:</br>
26 * *Set all three arrays to guessed max zise, run application for the first time and exit.</br>
27 * *Run DMON command "oceos info" to get size for each array.</br>
28 * *Update array sizes below
29 */
30 U32_t log_data[LOG_DATA_ARRAY_SIZE_U32S];
31
32 U32_t fixed_data[FIXED_DATA_ARRAY_SIZE_U32S] = {0}; // will be in data segment
33
34 U32_t dynamic_data[DYN_DATA_ARRAY_SIZE_U32S];
35
36 const unsigned int __oceos_bsp_sysfreq = BSP_SYSFREQ * 1000 * 1000;// TODO
37
38 static BOOLE_t log_full_was_called = FALSE;
39
40 /**
41 * Must be defined if Application is using :
42 * Dataq with timeout
43 * Semaphore with timeout
44 * Timed Actions
45 */
46 /*
47 * Set up the application configuration structure and pass it to oceos_init
48 * (done this way the memory used for the structure is returned automatically)
49 */
50
51 int application_init(){
52
53 /*
54 * Create the application configuration structure
55 */
56 struct application_configuration app_config = {0};
57
58 /*
59 * Fill in the application parameters
60 */
61 app_config.log_address = (adrs_t)log_data; // required
62 app_config.fixed_data_address = (adrs_t)fixed_data; // required
63 app_config.dynamic_data_address = (adrs_t)dynamic_data; // required
64
65 app_config.stack_start_address = OCEOS_STACK_START_ADDRESS; // 0 => no check
66 app_config.stack_lower_bound_address = OCEOS_STACK_LOW_BOUND_ADDRESS; // 0 => no check
67
68 app_config.system_error_function = &oceos_on_error; // NULL => ignore
69 app_config.log_full_function = &oceos_on_full_log; // NULL => ignore
70 // used in setting up system log and fixed data array
71 app_config.log_number_of_entries = NUMBER_OF_LOG_ENTRIES; // 0 => use default
72
73 app_config.number_of_tasks = NUMBER_OF_TASKS; // >= 1
74 app_config.number_of_readyQ_entries = NUMBER_OF_READYQ_ENTRIES; // 0 => calculate size
75
76 app_config.number_of_mutexes = NUMBER_OF_MUTEXES;
77 app_config.number_of_counting_semaphores = NUMBER_OF_SEMAPHORES;
78 app_config.number_of_data_queues = NUMBER_OF_DATAQS;
79
80 app_config.timed_actions_queue_size = NUMBER_OF_ACTION_ENTRIES;
81 app_config.CS_log_entries_base2 = CS_LOG_DEF_ENTRIES_BASE2;
82 app_config.use_oceos_system_time = TRUE;
83
84 // initialise OCEOS
85 enum DIRECTIVE_STATUS status;
86 status = oceos_init(app_config);
87
88 if (SUCCESSFUL == status) {
89 return 1;
90 } else {
91 printf("\n oceos_init failure\n");
92 return -1;
93 } // else
94 } // application_init()
95 /**
96 * User to implement in case of system error;
97 * Comment it out if not used and set field system_error_function in app_config to NULL
98 */
99 void oceos_on_error() {
100 return;
101 }
102 /**
103 * User to implement in case of system log is 2/3 full;
104 * Comment it out if not used and set field log_full_function in app_config to NULL
105 */
106 void oceos_on_full_log(){
107 log_full_was_called = TRUE;
108 return;
109 }
tut2.c
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include "tut2.h" // application header
21
22 /* N.B. Application header is included first */
23 #include "oceos_config.h" // OCEOS header for this application
24 #include "mutex.h"
25
26 int main(void) {
27 int status;
28
29 /*
30 * Initialise the application configuration and OCEOS
31 *
32 * This application function creates the application configuration
33 * and passes it to oceos_init(), which initialises the fixed data
34 * and enables the system log
35 */
36 if (!application_init()) {
37 //LOG
38 return -1;
39 }
40
41 // Create Main task to
42 if (oceos_task_create(t_0,// taskID, used as index, must be in range 0 to 254
43 100,// priority, must be in range 1 to 254, lower value is higher priority
44 100, // threshold, must be in range 1 to task priority
45 2, // jobs_max, must be in range 1 to 15
46 0,// FALSE -> floating point hardware not used by task
47 1, // FALSE -> task initially not enabled
48 fun0, // main body of task
49 nullFun, // task end function
50 0,// time_deadline, must finish no later than this after start, 0 => ignore
51 0 // minimum time expected between start requests, 0 => no restriction
52 ) != SUCCESSFUL)
53 return 1;
54
55 if (oceos_task_create(t_1, 200, 200, 2, 0, 1, fun1, nullFun, 0, 0)
56 != SUCCESSFUL)
57 return 2;
58
59 if (oceos_mutex_create(m_0, 100) != SUCCESSFUL) // Create mutex with ceiling of highest priority task using it
60 return 3;
61
62 /*
63 * Finish initialising OCEOS and setting up the fixed data
64 */
65 status = oceos_init_finish();
66 if (SUCCESSFUL != status) {
67 return 4;
68 } // if
69
70 /*
71 * Start OCEOS scheduling
72 *
73 * The OCEOS fixed data provides all the information required.
74 *
75 * If a valid task is specified, it is started and passed the pointer.
76 * Otherwise the system is put in sleep mode
77 */
78 status = oceos_start(fixed_data, t_1, (void*) nullPtr); // Start OCEOS with lower prioroty task
79 return status;
80 } // main
81
82 /*
83 * Application code functions, functions declared in asw.h
84 */
85 void fun0(void *ptr) {
86 if (oceos_mutex_wait(m_0) != SUCCESSFUL) {
87 printf("Error from high priority task getting mutex\n");
88 } else {
89 printf("high priority task got mutex\n");
90 }
91 oceos_task_start(t_1, ptr); // Start lower priority task
92
93 if (oceos_mutex_signal(m_0) != SUCCESSFUL) {
94 printf("Error from high priority task releasing mutex\n");
95 } else {
96 printf("High priority task released mutex\n");
97 }
98 return;
99 } // fun0()
100
101 void fun1(void *ptr) {
102 if (oceos_mutex_wait(m_0) != SUCCESSFUL) {
103 printf("Error from low priority task getting mutex\n");
104 } else {
105 printf("Low priority task got mutex\n");
106 }
107 oceos_task_start(t_0, ptr); // Start higher priority task
108
109 if (oceos_mutex_signal(m_0) != SUCCESSFUL) {
110 printf("Error from low priority task releasing mutex\n");
111 } else {
112 printf("Low priority task released mutex\n");
113 }
114 return;
115 } // 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
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #ifndef TUT3_H_
19 #define TUT3_H_
20 /* Sample Task names - all here start with t_ to help avoid name confusion */
21 enum TASK_NAME{
22 t_0, // Task to start other two
23 t_1, // consumer task
24 t_2 // consumer task
25
26 };
27 /* Sample Counting Semaphore names - all here start with s_ to help avoid name confusion */
28 enum SEM_NAME{
29 items, // Semaphore called items
30 spaces // Semaphore called spaces
31 };
32 char* nullPtr = ""; // Need pointer to pass to oceos_start
33 void (*nullFun)(void *); // Null function
34
35 /*
36 * APPLICATION FUNCTION DECLARATIONS
37 */
38 void fun0(void *);
39 void fun1(void *);
40 void fun2(void *);
41
42 #endif /* TUT3_H_ */
oceos_config.h
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #ifndef INCLUDE_OCEOS_CONFIG_H_
19 #define INCLUDE_OCEOS_CONFIG_H_
20
21 // 1: Includes OCEOS main header file
22 #include "oceos.h"
23 //----------------------------------------------------------------------------
24 // 2: Number of Log entries.
25 #define NUMBER_OF_LOG_ENTRIES 64 // 16 to 1024, default 64
26 //----------------------------------------------------------------------------
27 // 3: Number of tasks
28 #define NUMBER_OF_TASKS 3 // 1 to 255
29 //----------------------------------------------------------------------------
30 // 4: Number of ready queue entries, 0 to 254, see manual( MUST BE UPDATED BY USER);
31 // Defaults to number of tasks, as each task should have aa least one job;
32 // If Number of ready Q entries larger that number of total jobs => defaults to number of total jobs
33 #define NUMBER_OF_READYQ_ENTRIES NUMBER_OF_TASKS * 2
34 //----------------------------------------------------------------------------
35 // 5: Number of Mutexes
36 #define NUMBER_OF_MUTEXES 0 // 0 to 63
37 //----------------------------------------------------------------------------
38 // 6: Number of Semaphores
39 #define NUMBER_OF_SEMAPHORES 2 // 0 to 63
40 //----------------------------------------------------------------------------
41 // 7: Number of Data Qs
42 #define NUMBER_OF_DATAQS 0 // 0 to 63
43 //----------------------------------------------------------------------------
44 // 8: LOG data array size
45 #define LOG_DATA_ARRAY_SIZE_U32S 0x88// Calculated value. Read manual
46 //----------------------------------------------------------------------------
47 // 9: FIXED data array size
48 #define FIXED_DATA_ARRAY_SIZE_U32S 0x3a// Calculated value. Read manual
49 //----------------------------------------------------------------------------
50 // 10: DYNAMIC data array size
51 #define DYN_DATA_ARRAY_SIZE_U32S 0x65// Calculated value. Read manual
52 //----------------------------------------------------------------------------
53 // 11: Timed Actions
54 #define NUMBER_OF_ACTION_ENTRIES 0 // User-modify field
55 //----------------------------------------------------------------------------
56 // 12: Log entries base 2
57 #define CS_LOG_DEF_ENTRIES_BASE2 0
58 //----------------------------------------------------------------------------
59 // 13: OCEOS stack start Address
60 #define OCEOS_STACK_START_ADDRESS 0
61 //----------------------------------------------------------------------------
62 // 14: OCEOS stack end address
63 #define OCEOS_STACK_LOW_BOUND_ADDRESS 0
64 //----------------------------------------------------------------------------
65 /**
66 * Target specific configurations
67 */
68 /*
69 * ARM specific configurations
70 */
71 #ifdef __SAM3X8E__
72 #ifndef BSP_SYSFREQ
73 #define BSP_SYSFREQ 84 // ARM target frequency in Mhz
74 #endif
75 #endif
76 #ifdef __SAMV71Q21__
77 #ifndef BSP_SYSFREQ
78 #define BSP_SYSFREQ 300 // ARM target frequency in Mhz
79 #endif
80 #endif
81 #ifdef __VA41620__
82 #ifndef BSP_SYSFREQ
83 #define BSP_SYSFREQ 100 // ARM target frequency in Mhz
84 #endif
85 #endif
86 //--------------------------------------------------------------------
87 // User defined function to deal with system errors
88 void oceos_on_error(void);
89 //---------------------------------------------------------------------
90 // User defined function to deal with log 2/3 full
91 void oceos_on_full_log(void);
92 //---------------------------------------------------------------------
93 extern U32_t log_data[];
94 extern U32_t fixed_data[];
95 extern U32_t dynamic_data[];
96 extern const unsigned int __oceos_bsp_sysfreq;
97 /**
98 * Initialize OCEOS with user configurations
99 */
100 int application_init(void);
101 #endif /* INCLUDE_OCEOS_CONFIG_H_ */
oceos_config.c
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #include <stdio.h>
19 #include "oceos_config.h"
20
21 /*
22 * OCEOS INTERNAL DATA STORAGE
23 *
24 * This application defines arrays to hold OCEOS internal data.
25 * The array sizes are provided by DMON by running "oceos info" command:</br>
26 * *Set all three arrays to guessed max zise, run application for the first time and exit.</br>
27 * *Run DMON command "oceos info" to get size for each array.</br>
28 * *Update array sizes below
29 */
30 U32_t log_data[LOG_DATA_ARRAY_SIZE_U32S];
31
32 U32_t fixed_data[FIXED_DATA_ARRAY_SIZE_U32S] = {0}; // will be in data segment
33
34 U32_t dynamic_data[DYN_DATA_ARRAY_SIZE_U32S];
35
36 const unsigned int __oceos_bsp_sysfreq = BSP_SYSFREQ * 1000 * 1000;// TODO
37
38 static BOOLE_t log_full_was_called = FALSE;
39
40 /**
41 * Must be defined if Application is using :
42 * Dataq with timeout
43 * Semaphore with timeout
44 * Timed Actions
45 */
46 /*
47 * Set up the application configuration structure and pass it to oceos_init
48 * (done this way the memory used for the structure is returned automatically)
49 */
50
51 int application_init(){
52
53 /*
54 * Create the application configuration structure
55 */
56 struct application_configuration app_config = {0};
57
58 /*
59 * Fill in the application parameters
60 */
61 app_config.log_address = (adrs_t)log_data; // required
62 app_config.fixed_data_address = (adrs_t)fixed_data; // required
63 app_config.dynamic_data_address = (adrs_t)dynamic_data; // required
64
65 app_config.stack_start_address = OCEOS_STACK_START_ADDRESS; // 0 => no check
66 app_config.stack_lower_bound_address = OCEOS_STACK_LOW_BOUND_ADDRESS; // 0 => no check
67
68 app_config.system_error_function = &oceos_on_error; // NULL => ignore
69 app_config.log_full_function = &oceos_on_full_log; // NULL => ignore
70 // used in setting up system log and fixed data array
71 app_config.log_number_of_entries = NUMBER_OF_LOG_ENTRIES; // 0 => use default
72
73 app_config.number_of_tasks = NUMBER_OF_TASKS; // >= 1
74 app_config.number_of_readyQ_entries = NUMBER_OF_READYQ_ENTRIES; // 0 => calculate size
75
76 app_config.number_of_mutexes = NUMBER_OF_MUTEXES;
77 app_config.number_of_counting_semaphores = NUMBER_OF_SEMAPHORES;
78 app_config.number_of_data_queues = NUMBER_OF_DATAQS;
79
80 app_config.timed_actions_queue_size = NUMBER_OF_ACTION_ENTRIES;
81 app_config.CS_log_entries_base2 = CS_LOG_DEF_ENTRIES_BASE2;
82 app_config.use_oceos_system_time = TRUE;
83
84 // initialise OCEOS
85 enum DIRECTIVE_STATUS status;
86 status = oceos_init(app_config);
87
88 if (SUCCESSFUL == status) {
89 return 1;
90 } else {
91 printf("\n oceos_init failure\n");
92 return -1;
93 } // else
94 } // application_init()
95 /**
96 * User to implement in case of system error;
97 * Comment it out if not used and set field system_error_function in app_config to NULL
98 */
99 void oceos_on_error() {
100 return;
101 }
102 /**
103 * User to implement in case of system log is 2/3 full;
104 * Comment it out if not used and set field log_full_function in app_config to NULL
105 */
106 void oceos_on_full_log(){
107 log_full_was_called = TRUE;
108 return;
109 }
tut3.c
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20
21 /* N.B. Application header is included first */
22 #include "oceos_config.h" // OCEOS header for this application
23 #include "tut3.h" // application header
24 #include "semaphore.h"
25
26 int main(void) {
27 int status;
28 /*
29 * Initialise the application configuration and OCEOS
30 *
31 * This application function creates the application configuration
32 * and passes it to oceos_init(), which initialises the fixed data
33 * and enables the system log
34 */
35 if (!application_init()) {
36 //LOG
37 return -1;
38 }
39 // Create Main task to
40 if (oceos_task_create(t_0,// taskID, used as index, must be in range 0 to 254
41 10, // priority, must be in range 1 to 254, lower value is higher priority
42 10, // threshold, must be in range 1 to task priority
43 1, // jobs_max, must be in range 1 to 15
44 0,// FALSE -> floating point hardware not used by task
45 1, // FALSE -> task initially not enabled
46 fun0, // main body of task
47 nullFun, // task end function
48 0,// time_deadline, must finish no later than this after start, 0 => ignore
49 0 // minimum time expected between start requests, 0 => no restriction
50 ) != SUCCESSFUL)
51 return 1;
52
53 if (oceos_task_create(t_1, 100, 100, 1, 0, 1, fun1, nullFun, 0, 0)
54 != SUCCESSFUL)
55 return 2;
56
57 if (oceos_task_create(t_2, 100, 100, 1, 0, 1, fun2, nullFun, 0, 0)
58 != SUCCESSFUL)
59 return 3;
60
61 if (oceos_sem_create(items, 10, 0, 2, FALSE) != SUCCESSFUL)// items semaphore with max permits of 10, initial permits of 0, max jobs 2
62 return 4;
63
64 if (oceos_sem_create(spaces, 10, 4, 2, FALSE) != SUCCESSFUL) // spaces semaphore with max permits of 10, initial permits of 4, max jobs 2
65 return 4;
66 /*
67 * Finish initialising OCEOS and setting up the fixed data
68 */
69 status = oceos_init_finish();
70 if (SUCCESSFUL != status) {
71 return 6;
72 } // if
73 /*
74 * Start OCEOS scheduling
75 *
76 * The OCEOS fixed data provides all the information required.
77 *
78 * If a valid task is specified, it is started and passed the pointer.
79 * Otherwise the system is put in sleep mode
80 */
81 status = oceos_start(fixed_data, t_0, (void*) nullPtr); // Start OCEOS with task to start other tasks
82 return status;
83 } // main
84
85 /*
86 * Application code functions, functions declared in asw.h
87 */
88 void fun0(void *ptr) {
89 oceos_task_start(t_1, ptr); // Start consumer task
90 oceos_task_start(t_2, ptr); // Start consumer task
91 } // fun0()
92
93 void fun1(void *ptr) {
94 while (1) { // loop forever
95 if (oceos_sem_wait_restart(items) != SUCCESSFUL) {
96 printf("Error from task t_0 task waiting items\n");
97 }
98 printf("Got item\n");
99 if (oceos_sem_signal(spaces) != SUCCESSFUL) {
100 printf("Error from task t_0 signalling spaces\n");
101 }
102 }
103 } // fun0()
104
105 void fun2(void *ptr) {
106 while (1) { // loop forever
107 if (oceos_sem_wait_restart(spaces) != SUCCESSFUL) {
108 printf("Error from task t_1 task waiting spaces\n");
109 }
110 if (oceos_sem_signal(items) != SUCCESSFUL) {
111 printf("Error from task t_1 signalling items\n");
112 } else {
113 printf("Item done\n");
114 }
115 }
116 return;
117 } // 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
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #ifndef TUT4_H_
19 #define TUT4_H_
20 /* Sample Task names - all here start with t_ to help avoid name confusion */
21 enum TASK_NAME{
22 t_0, // Task to setup interrupt
23 t_1 // Task to be executed by interrupt routine
24
25 };
26 /*
27 * APPLICATION FUNCTION DECLARATIONS
28 */
29 void fun0(void *);
30 void fun1(void *);
31 void start_task(void *arg, int source);
32 void timer_setup(void);
33
34 #endif /* TUT4_H_ */
oceos_config.h
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #ifndef INCLUDE_OCEOS_CONFIG_H_
19 #define INCLUDE_OCEOS_CONFIG_H_
20
21 // 1: Includes OCEOS main header file
22 #include "oceos.h"
23 //----------------------------------------------------------------------------
24 // 2: Number of Log entries.
25 #define NUMBER_OF_LOG_ENTRIES 64 // 16 to 1024, default 64
26 //----------------------------------------------------------------------------
27 // 3: Number of tasks
28 #define NUMBER_OF_TASKS 2 // 1 to 255
29 //----------------------------------------------------------------------------
30 // 4: Number of ready queue entries, 0 to 254, see manual( MUST BE UPDATED BY USER);
31 // Defaults to number of tasks, as each task should have aa least one job;
32 // If Number of ready Q entries larger that number of total jobs => defaults to number of total jobs
33 #define NUMBER_OF_READYQ_ENTRIES NUMBER_OF_TASKS + 1
34 //----------------------------------------------------------------------------
35 // 5: Number of Mutexes
36 #define NUMBER_OF_MUTEXES 0 // 0 to 63
37 //----------------------------------------------------------------------------
38 // 6: Number of Semaphores
39 #define NUMBER_OF_SEMAPHORES 0 // 0 to 63
40 //----------------------------------------------------------------------------
41 // 7: Number of Data Qs
42 #define NUMBER_OF_DATAQS 0 // 0 to 63
43 //----------------------------------------------------------------------------
44 // 8: LOG data array size
45 #define LOG_DATA_ARRAY_SIZE_U32S 0x88// Calculated value. Read manual
46 //----------------------------------------------------------------------------
47 // 9: FIXED data array size
48 #define FIXED_DATA_ARRAY_SIZE_U32S 0x32// Calculated value. Read manual
49 //----------------------------------------------------------------------------
50 // 10: DYNAMIC data array size
51 #define DYN_DATA_ARRAY_SIZE_U32S 0x29// Calculated value. Read manual
52 //----------------------------------------------------------------------------
53 // 11: Timed Actions
54 #define NUMBER_OF_ACTION_ENTRIES 0 // User-modify field
55 //----------------------------------------------------------------------------
56 // 12: Log entries base 2
57 #define CS_LOG_DEF_ENTRIES_BASE2 0
58 //----------------------------------------------------------------------------
59 // 13: OCEOS stack start Address
60 #define OCEOS_STACK_START_ADDRESS 0
61 //----------------------------------------------------------------------------
62 // 14: OCEOS stack end address
63 #define OCEOS_STACK_LOW_BOUND_ADDRESS 0
64 //----------------------------------------------------------------------------
65 /**
66 * Target specific configurations
67 */
68 /*
69 * ARM specific configurations
70 */
71 #ifdef __SAM3X8E__
72 #ifndef BSP_SYSFREQ
73 #define BSP_SYSFREQ 84 // ARM target frequency in Mhz
74 #endif
75 #endif
76 #ifdef __SAMV71Q21__
77 #ifndef BSP_SYSFREQ
78 #define BSP_SYSFREQ 300 // ARM target frequency in Mhz
79 #endif
80 #endif
81 #ifdef __VA41620__
82 #ifndef BSP_SYSFREQ
83 #define BSP_SYSFREQ 100 // ARM target frequency in Mhz
84 #endif
85 #endif
86 //--------------------------------------------------------------------
87 // User defined function to deal with system errors
88 void oceos_on_error(void);
89 //---------------------------------------------------------------------
90 // User defined function to deal with log 2/3 full
91 void oceos_on_full_log(void);
92 //---------------------------------------------------------------------
93 extern U32_t log_data[];
94 extern U32_t fixed_data[];
95 extern U32_t dynamic_data[];
96 extern const unsigned int __oceos_bsp_sysfreq;
97 /**
98 * Initialize OCEOS with user configurations
99 */
100 int application_init(void);
101 #endif /* INCLUDE_OCEOS_CONFIG_H_ */
oceos_config.c
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #include <stdio.h>
19 #include "oceos_config.h"
20
21 /*
22 * OCEOS INTERNAL DATA STORAGE
23 *
24 * This application defines arrays to hold OCEOS internal data.
25 * The array sizes are provided by DMON by running "oceos info" command:</br>
26 * *Set all three arrays to guessed max zise, run application for the first time and exit.</br>
27 * *Run DMON command "oceos info" to get size for each array.</br>
28 * *Update array sizes below
29 */
30 U32_t log_data[LOG_DATA_ARRAY_SIZE_U32S];
31
32 U32_t fixed_data[FIXED_DATA_ARRAY_SIZE_U32S] = {0}; // will be in data segment
33
34 U32_t dynamic_data[DYN_DATA_ARRAY_SIZE_U32S];
35
36 const unsigned int __oceos_bsp_sysfreq = BSP_SYSFREQ * 1000 * 1000;// TODO
37
38 static BOOLE_t log_full_was_called = FALSE;
39
40 /**
41 * Must be defined if Application is using :
42 * Dataq with timeout
43 * Semaphore with timeout
44 * Timed Actions
45 */
46 /*
47 * Set up the application configuration structure and pass it to oceos_init
48 * (done this way the memory used for the structure is returned automatically)
49 */
50
51 int application_init(){
52
53 /*
54 * Create the application configuration structure
55 */
56 struct application_configuration app_config = {0};
57
58 /*
59 * Fill in the application parameters
60 */
61 app_config.log_address = (adrs_t)log_data; // required
62 app_config.fixed_data_address = (adrs_t)fixed_data; // required
63 app_config.dynamic_data_address = (adrs_t)dynamic_data; // required
64
65 app_config.stack_start_address = OCEOS_STACK_START_ADDRESS; // 0 => no check
66 app_config.stack_lower_bound_address = OCEOS_STACK_LOW_BOUND_ADDRESS; // 0 => no check
67
68 app_config.system_error_function = &oceos_on_error; // NULL => ignore
69 app_config.log_full_function = &oceos_on_full_log; // NULL => ignore
70 // used in setting up system log and fixed data array
71 app_config.log_number_of_entries = NUMBER_OF_LOG_ENTRIES; // 0 => use default
72
73 app_config.number_of_tasks = NUMBER_OF_TASKS; // >= 1
74 app_config.number_of_readyQ_entries = NUMBER_OF_READYQ_ENTRIES; // 0 => calculate size
75
76 app_config.number_of_mutexes = NUMBER_OF_MUTEXES;
77 app_config.number_of_counting_semaphores = NUMBER_OF_SEMAPHORES;
78 app_config.number_of_data_queues = NUMBER_OF_DATAQS;
79
80 app_config.timed_actions_queue_size = NUMBER_OF_ACTION_ENTRIES;
81 app_config.CS_log_entries_base2 = CS_LOG_DEF_ENTRIES_BASE2;
82 app_config.use_oceos_system_time = TRUE;
83
84 // initialise OCEOS
85 enum DIRECTIVE_STATUS status;
86 status = oceos_init(app_config);
87
88 if (SUCCESSFUL == status) {
89 return 1;
90 } else {
91 printf("\n oceos_init failure\n");
92 return -1;
93 } // else
94 } // application_init()
95 /**
96 * User to implement in case of system error;
97 * Comment it out if not used and set field system_error_function in app_config to NULL
98 */
99 void oceos_on_error() {
100 return;
101 }
102 /**
103 * User to implement in case of system log is 2/3 full;
104 * Comment it out if not used and set field log_full_function in app_config to NULL
105 */
106 void oceos_on_full_log(){
107 log_full_was_called = TRUE;
108 return;
109 }
arm_task_src.c
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include "tut4.h"
21 #include "oceos_config.h"
22
23 #if defined(__SAM3X8E__) || defined(__SAMV71Q21__)
24 #include "sam.h"
25
26 #define ENABLE_WAVE_MODE (0x1 << TC_CMR_WAVE_Pos)
27 #define TC_CMR_WAVE_SEL_Pos 13
28 #define SET_WAVE_SELECT (~(0x3 << TC_CMR_WAVE_SEL_Pos)) //00
29 #define TC_CMR_CPCSTOP_Pos 6
30 #define TC_CMR_CPCSTOP (0x1 << TC_CMR_CPCSTOP_Pos)
31
32 static Tc *timer_regs;
33 static TcChannel *tc;
34
35 #endif
36
37 /*
38 * Set up timer and register handler
39 */
40 void timer_setup(){
41
42 #ifdef __SAM3X8E__
43 // Enabling Peripheral Clocks
44 // REmove write protect
45 int pmc_was_enabled = 0;
46 if (0 != (PMC->PMC_WPMR & PMC_WPMR_WPEN)) {
47 PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD;
48 pmc_was_enabled = 1;
49 }
50 // Enable Clock
51 PMC->PMC_PCER0 |= PMC_PCER0_PID28;
52 // Enable write protect
53 if (pmc_was_enabled) {
54 PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD | PMC_WPMR_WPEN;
55 }
56
57 timer_regs = (Tc *)TC0;
58 tc = &(timer_regs->TC_CHANNEL[1]);
59
60 // Enable Wave Mode
61 tc->TC_CMR |= ENABLE_WAVE_MODE;
62 // Set WAVESEL to 00
63 tc->TC_CMR &= (U32_t)SET_WAVE_SELECT;
64 // Set TC_CMR_CPCSTOP and Clock input
65 tc->TC_CMR |= (TC_CMR_CPCSTOP | TC_CMR_TCCLKS_TIMER_CLOCK1); // MCK/8
66
67
68 // Set Block Clock
69 timer_regs->TC_BMR &= (U32_t)(~(1 << 1));
70 // Interrupt Enable
71 // Enable Timer interrupt (RC Compare)
72 tc->TC_IER = TC_IER_CPCS;
73
74 NVIC_EnableIRQ(TC1_IRQn);
75 // Set Highest Priority for interrupt number
76 NVIC_SetPriority(TC1_IRQn, 1);
77 float base_scaler = (float)(__oceos_bsp_sysfreq / 2) / 1000000.0f;
78
79 //tc->TC_RC = base_scaler * 0x3DC6C0;
80 tc->TC_RC = base_scaler * 1349;
81 // Enable clock
82 tc->TC_CCR = TC_CCR_CLKEN;
83
84 // Start clock
85 tc->TC_CCR = TC_CCR_SWTRG;
86 #endif
87 #ifdef __SAMV71Q21__
88 // Enabling Peripheral Clocks
89 // REmove write protect
90 int pmc_was_enabled = 0;
91 if (0 != (PMC->PMC_WPMR & PMC_WPMR_WPEN)) {
92 PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD;
93 pmc_was_enabled = 1;
94 }
95 // Enable Clock
96 PMC->PMC_PCER0 |= PMC_PCER0_PID24;
97 // Enable write protect
98 if (pmc_was_enabled) {
99 PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD | PMC_WPMR_WPEN;
100 }
101 timer_regs = (Tc *)TC0;
102 tc = &(timer_regs->TC_CHANNEL[1]);
103
104 // Enable Wave Mode
105 tc->TC_CMR |= ENABLE_WAVE_MODE;
106 // Set WAVESEL to 00
107 tc->TC_CMR &= (U32_t)SET_WAVE_SELECT;
108 // Set TC_CMR_CPCSTOP and Clock input
109 tc->TC_CMR |= (TC_CMR_CPCSTOP | TC_CMR_TCCLKS_TIMER_CLOCK5_Val); //
110
111 // Set Block Clock
112 timer_regs->TC_BMR &= (U32_t)(~(1 << 1));
113 // Interrupt Enable
114 // Enable Timer interrupt (RC Compare)
115 tc->TC_IER = TC_IER_CPCS;
116
117 NVIC_EnableIRQ(TC1_IRQn);
118 // Set Highest Priority for interrupt number
119 NVIC_SetPriority(TC1_IRQn, 1);
120
121 tc->TC_RC = 0x61a8;// 1s
122
123 // Enable clock
124 tc->TC_CCR = TC_CCR_CLKEN;
125
126 // Start clock
127 tc->TC_CCR = TC_CCR_SWTRG;
128 #endif
129 } // setup_timer()
130
131 void TC1_IRQHandler() {
132 #if defined(__SAM3X8E__) || defined(__SAMV71Q21__)
133 tc->TC_SR;// Read to remove pending bit
134 #endif
135 // Start task
136 oceos_task_start(t_1, NULL);
137
138 #if defined(__SAM3X8E__) || defined(__SAMV71Q21__)
139 tc->TC_CCR = TC_CCR_SWTRG;
140 #endif
141 }
tut4.c
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * SPARC and ARM Microcontrollers
7 *
8 * Example implementation of OCEOS
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 *
15 * Author: jfk
16 ********************************************************************************************************
17 */
18 #include <stdio.h>
19 #include <stdlib.h>
20
21 /* N.B. Application header is included first */
22 #include "oceos_config.h" // OCEOS header for this application
23 #include "tut4.h" // application header
24
25 volatile U32_t count_task_start = 0;
26
27 int main(void) {
28 int status;
29 /*
30 * Initialise the application configuration and OCEOS
31 *
32 * This application function creates the application configuration
33 * and passes it to oceos_init(), which initialises the fixed data
34 * and enables the system log
35 */
36 if (!application_init()) {
37 //LOG
38 return -1;
39 }
40 // Create Main task to
41 if (oceos_task_create(t_0,// taskID, used as index, must be in range 0 to 254
42 10, // priority, must be in range 1 to 254, lower value is higher priority
43 10, // threshold, must be in range 1 to task priority
44 1, // jobs_max, must be in range 1 to 15
45 0,// FALSE -> floating point hardware not used by task
46 1, // FALSE -> task initially not enabled
47 fun0, // main body of task
48 NULL, // task end function
49 0,// time_deadline, must finish no later than this after start, 0 => ignore
50 0 // minimum time expected between start requests, 0 => no restriction
51 ) != SUCCESSFUL)
52 return 1;
53
54 if (oceos_task_create(t_1, 100, 100, 1, 0, 1, fun1, NULL, 0, 0)
55 != SUCCESSFUL)
56 return 2;
57 /*
58 * Finish initialising OCEOS and setting up the fixed data
59 */
60 status = oceos_init_finish();
61 if (SUCCESSFUL != status) {
62 return 3;
63 } // if
64 /*
65 * Start OCEOS scheduling
66 *
67 * The OCEOS fixed data provides all the information required.
68 *
69 * If a valid task is specified, it is started and passed the pointer.
70 * Otherwise the system is put in sleep mode
71 */
72 status = oceos_start(fixed_data, t_0, NULL); // Start OCEOS
73 return status;
74 } // main
75
76 /*
77 * Task 0 starting point
78 */
79 void fun0(void *ptr) {
80 timer_setup();
81 } // fun0()
82 /**
83 * Task 1 starting point;
84 * Triggered from Timer IRQ handler
85 */
86 void fun1(void *ptr) {
87 printf("Task started : %u times \n", count_task_start);
88 count_task_start++;
89 } // 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
1 /*
2 ******************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for ARM/SPARC
6 * Microcontroller
7 *
8 * Application Software Example Header File
9 *
10 *
11 * (c) Copyright 2021, O.C.E. Technology
12 * All Rights Reserved
13 *
14 * File : asw.h
15 * Author: Deniss Timofejevs <deniss.timofejevs@ocetechnology.com>
16 ******************************************************************************
17 */
18 #ifndef ASW_H
19 #define ASW_H
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <assert.h>
23 #include "oceos_config.h" // OCEOS header
24 #include "oceos_timer.h"
25 #include "system_log.h"
26 #include "dataq.h"
27
28 #define N0 1 // dataq_size
29 #define N1 1 // dataq_size
30 #define JOBS0 1 // pending q size
31 #define JOBS1 1 // pending q size
32 #define TIME_OUT 1000000 // timeout
33
34 /*
35 * APPLICATION FUNCTION DECLARATIONS
36 */
37 enum TASK_NAME{
38 t_consumer , // will have task ID 0
39 t_producer, // will have task ID 1
40 };
41 enum DATAQ_NAME{
42 queue_0, // will have dataq ID 0
43 queue_1, // will have dataq ID 1
44 };
45 void t_consumer_task(void);
46 void t_producer_task(void);
47
48 #endif /* ASW_H */
oceos_config.h
1 /*
2 * app_config.h
3 *
4 * Created on: 17 Feb 2020
5 * Author: Deniss Timofejevs <deniss.timofejevs@ocetechnology.com>
6 */
7
8 #ifndef INCLUDE_OCEOS_CONFIG_H_
9 #define INCLUDE_OCEOS_CONFIG_H_
10
11 // 1: Includes OCEOS main header file
12 #include "oceos.h"
13 //----------------------------------------------------------------------------
14 // 2: Number of Log entries.
15 #define NUMBER_OF_LOG_ENTRIES 16 // 16 to 1024, default 64
16 //----------------------------------------------------------------------------
17 // 3: Number of tasks
18 #define NUMBER_OF_TASKS 2 // 1 to 255
19 //----------------------------------------------------------------------------
20 // 4: Number of ready queue entries, 0 to 254, see manual( MUST BE UPDATED BY USER);
21 // Defaults to number of tasks, as each task should have aa least one job;
22 // If Number of ready Q entries larger that number of total jobs => defaults to number of total jobs
23 #define NUMBER_OF_READYQ_ENTRIES 3
24 //----------------------------------------------------------------------------
25 // 5: Number of Mutexes
26 #define NUMBER_OF_MUTEXES 0 // 0 to 63
27 //----------------------------------------------------------------------------
28 // 6: Number of Semaphores
29 #define NUMBER_OF_SEMAPHORES 0 // 0 to 63
30 //----------------------------------------------------------------------------
31 // 7: Number of Data Qs
32 #define NUMBER_OF_DATAQS 2 // 0 to 63
33 //----------------------------------------------------------------------------
34 // 8: LOG data array size
35 #define LOG_DATA_ARRAY_SIZE_U32S 0x28// Calculated value. Read manual
36 //----------------------------------------------------------------------------
37 // 9: FIXED data array size
38 #define FIXED_DATA_ARRAY_SIZE_U32S 0x34// Calculated value. Read manual
39 //----------------------------------------------------------------------------
40 // 10: DYNAMIC data array size
41 #define DYN_DATA_ARRAY_SIZE_U32S 0x46// Calculated value. Read manual
42 //----------------------------------------------------------------------------
43 // 11: Timed Actions
44 #define NUMBER_OF_ACTION_ENTRIES 0 // User-modify field
45 //----------------------------------------------------------------------------
46 // 12: Log entries base 2
47 #define CS_LOG_DEF_ENTRIES_BASE2 0
48 //----------------------------------------------------------------------------
49 // 13: OCEOS stack start Address
50 #define OCEOS_STACK_START_ADDRESS 0
51 //----------------------------------------------------------------------------
52 // 14: OCEOS stack end address
53 #define OCEOS_STACK_LOW_BOUND_ADDRESS 0
54 //----------------------------------------------------------------------------
55 /**
56 * Target specific configurations
57 */
58 #ifdef __SAM3X8E__
59 #ifndef BSP_SYSFREQ
60 #define BSP_SYSFREQ 84 // ARM target frequency in Mhz
61 #endif
62 #endif
63 #ifdef __SAMV71Q21__
64 #ifndef BSP_SYSFREQ
65 #define BSP_SYSFREQ 300 // ARM target frequency in Mhz
66 #endif
67 #endif
68 #ifdef __VA41620__
69 #ifndef BSP_SYSFREQ
70 #define BSP_SYSFREQ 100 // ARM target frequency in Mhz
71 #endif
72 #endif
73
74 // User defined function to deal with system errors
75 void oceos_on_error(void*);
76 //---------------------------------------------------------------------
77 // User defined function to deal with log 2/3 full
78 void oceos_on_full_log(void*);
79 //---------------------------------------------------------------------
80 extern U32_t log_data[];
81 extern U32_t fixed_data[];
82 extern U32_t dynamic_data[];
83 extern const unsigned int __oceos_bsp_sysfreq;
84 /**
85 * Initialize OCEOS with user configurations
86 */
87 int application_init(void);
88 #endif /* INCLUDE_OCEOS_CONFIG_H_ */
oceos_config.c
1 /*
2 * app_config.c
3 *
4 * Configuration Tamplate for OCEOS
5 *
6 * Created on: 17 Feb 2020
7 * Author: Deniss Timofejevs <deniss.timofejevs@ocetechnology.com>
8 */
9 #include <stdio.h>
10 #include <assert.h>
11 #include "oceos_config.h"
12
13 /*
14 * OCEOS INTERNAL DATA STORAGE
15 *
16 * This application defines arrays to hold OCEOS internal data.
17 * The array sizes are provided by DMON by running "oceos info" command:</br>
18 * *Set all three arrays to guessed max zise, run application for the first time and exit.</br>
19 * *Run DMON command "oceos info" to get size for each array.</br>
20 * *Update array sizes below
21 */
22 U32_t log_data[LOG_DATA_ARRAY_SIZE_U32S];
23
24 U32_t fixed_data[FIXED_DATA_ARRAY_SIZE_U32S] = {0}; // will be in data segment
25
26 U32_t dynamic_data[DYN_DATA_ARRAY_SIZE_U32S];
27
28 const unsigned int __oceos_bsp_sysfreq = BSP_SYSFREQ * 1000 * 1000;// TODO
29
30 static BOOLE_t log_full_was_called = FALSE;
31
32 /*
33 * Set up the application configuration structure and pass it to oceos_init
34 * (done this way the memory used for the structure is returned automatically)
35 */
36
37 int application_init(){
38
39 /*
40 * Create the application configuration structure
41 */
42 struct application_configuration app_config = {0};
43
44 /*
45 * Fill in the application parameters
46 */
47 app_config.log_address = (adrs_t)log_data; // required
48 app_config.fixed_data_address = (adrs_t)fixed_data; // required
49 app_config.dynamic_data_address = (adrs_t)dynamic_data; // required
50
51 app_config.stack_start_address = OCEOS_STACK_START_ADDRESS; // 0 => no check
52 app_config.stack_lower_bound_address = OCEOS_STACK_LOW_BOUND_ADDRESS; // 0 => no check
53
54 app_config.system_error_function = &oceos_on_error; // NULL => ignore
55 app_config.log_full_function = &oceos_on_full_log; // NULL => ignore
56
57 // used in setting up system log and fixed data array
58 app_config.log_number_of_entries = NUMBER_OF_LOG_ENTRIES; // 0 => use default
59
60 app_config.number_of_tasks = NUMBER_OF_TASKS; // >= 1
61 app_config.number_of_readyQ_entries = NUMBER_OF_READYQ_ENTRIES; // 0 => calculate size
62
63 app_config.number_of_mutexes = NUMBER_OF_MUTEXES;
64 app_config.number_of_counting_semaphores = NUMBER_OF_SEMAPHORES;
65 app_config.number_of_data_queues = NUMBER_OF_DATAQS;
66
67 app_config.timed_actions_queue_size = NUMBER_OF_ACTION_ENTRIES;
68 app_config.CS_log_entries_base2 = CS_LOG_DEF_ENTRIES_BASE2;
69 app_config.use_oceos_system_time = TRUE;
70
71 // initialise OCEOS
72 enum DIRECTIVE_STATUS status;
73 status = oceos_init(app_config);
74 assert(SUCCESSFUL == status);
75
76 if (SUCCESSFUL == status) {
77 return 1;
78 } else {
79 printf("\n oceos_init failure\n");
80 return -1;
81 } // else
82 } // application_init()
83 /**
84 * User to implement in case of system error;
85 * Comment it out if not used and set field system_error_function in app_config to NULL
86 */
87 void oceos_on_error(void* ptr) {
88 return;
89 }
90 /**
91 * User to implement in case of system log is 2/3 full;
92 * Comment it out if not used and set field log_full_function in app_config to NULL
93 */
94 void oceos_on_full_log(void* ptr){
95 log_full_was_called = TRUE;
96 return;
97 }
tut5.c
1 /*
2 ******************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for ARM/SPARC
6 * Microcontroller
7 *
8 * Application Software Example
9 *
10 *
11 * (c) Copyright 2022, O.C.E. Technology
12 * All Rights Reserved
13 *
14 * Author: jfk
15 *
16 * Purpose : The test here involves creating two tasks with different priorities,
17 * and two data queues with timed action implimentation.
18 *
19 ******************************************************************************
20 */
21 /* N.B. Application header is included first */
22 #include "tut5.h" // application header
23
24 struct data {
25 int status;
26 char *message;
27 } test_data = {
28 1,
29 "Test Data",
30 };
31 int main(void) {
32
33 /*
34 * Initialise the application configuration and OCEOS
35 *
36 * This application function creates the application configuration
37 * and passes it to oceos_init(), which initialises the fixed data
38 * and enables the system log
39 */
40 if ( !application_init()) {
41 //LOG
42 printf("\nProblem\n");
43 return -1;
44 }
45
46 enum DIRECTIVE_STATUS status;
47 // 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
48 status = oceos_task_create(t_consumer, 10, 10, 1, 0, TASK_ENABLED,t_consumer_task, NULL, 0, 0);
49 if(SUCCESSFUL != status){
50 // LOG
51 printf("\nAbandoning, problem creating task t_consumer, resulting return code: %u\n", status);
52 return -1;
53 } // if
54
55 // 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
56 status = oceos_task_create(t_producer, 254, 254, 1, 0, TASK_ENABLED,t_producer_task, NULL, 0, 0);
57 if(SUCCESSFUL != status){
58 // LOG
59 printf("\nAbandoning, problem creating task t_producer, resulting return code: %u\n", status);
60 return -1;
61 } // if
62
63 printf("\n Tasks created\n");
64 // no counting semaphores, data queues or user defined traps
65
66 // Creating Data 0, dataq_size 1, pen_q size 1, roll_over FALSE, use_timeout TRUE
67 status = oceos_dataq_create(queue_0, N0, JOBS0, FALSE, TRUE);
68 if(SUCCESSFUL != status){
69 printf("\nProblem creating dataq queue_0, resulting return code: %u\n", status);
70 } // if
71
72 // Creating Data 1, dataq_size 1, pen_q size 1, roll_over FALSE, use_timeout TRUE
73 status = oceos_dataq_create(queue_1, N1, JOBS1, FALSE, TRUE);
74 if(SUCCESSFUL != status){
75 printf("\nProblem creating dataq queue_1, resulting return code: %u\n", status);
76 } // if
77 /*
78 * Finish initialising OCEOS and setting up the fixed data
79 */
80 status = oceos_init_finish();
81 if(SUCCESSFUL != status){
82 printf("\nAbandoning, problem ending OCEOS initialisation, resulting return code: %u\n", status);
83 return -1;
84 } // if
85 //1) Action: Start OCEOS with Task 1 as initial task, null input pointer
86 status = oceos_start(fixed_data, t_producer, NULL);
87
88 return status; // returned as an integer
89
90 } // function waits for specific time interval
91 void test_wait(U32_t interval) {
92 volatile U32_t start_time = oceos_time_sys_get32();
93 volatile U32_t cur_time = 0;
94 while(1) {
95 cur_time = oceos_time_sys_get32();
96 if ((cur_time - start_time) >= interval ) {
97 break;
98 }
99 }
100 }
101 /*
102 * Tasks
103 */
104 void t_consumer_task() {
105 static int case_number = 0;
106 if (case_number == 0) {
107 case_number++;
108 // 2) Action: Task 1 attempts to start Task 0
109 // Check: Task 0 has started, pre-empting Task 1
110 // a. Check: entry message from Task 0
111 // b. Check: queue_0 entries is 0
112 // c. Check: queue_1 entries is 0
113 printf("t_consumer was started\n");
114 if(oceos_dataq_get_size(queue_0)!= 0){
115 printf("\nData queue_0 entries is not equal to 0\n");
116 } // if
117 if(oceos_dataq_get_size(queue_1)!= 0){
118 printf("\nData queue_1 entries is not equal to 0\n");
119 } // if
120
121 // 3) Action: Task 0 does read_restart on queue_0
122 oceos_dataq_read_restart_timeout(queue_0, 0);
123 } else if (case_number == 1){
124 case_number++;
125 // 5) Action: Task 1 writes pointer to struct to queue_0
126 // Check: Task 0 has started, pre-empting Task 1
127 // a. Check: entry message from Task 0
128 // b. Check: queue_0 entries count is 1
129 // c. Check: queue_1 entries count is 0
130 printf("t_consumer was started\n");
131 if(oceos_dataq_get_size(queue_0)!= 1){
132 printf("\nData queue_0 entries is not equal to 1\n");
133 } // if
134 if(oceos_dataq_get_size(queue_1)!= 0){
135 printf("\nData queue_1 entries is not equal to 0\n");
136 } // if
137
138 // 6) Action: Task 0 does read_restart on queue 0
139 // Check: Task 0 has succeeded
140 // a. Check: non-null pointer returned
141 // b. Check: queue_0 entries count is 0
142 // c. Check: queue_0 entries count is 0
143 if(oceos_dataq_read_restart_timeout(queue_0, 0) == NULL){
144 printf("\nDataq read restart timeout returned null\n");
145 } // if
146 if(oceos_dataq_get_size(queue_0)!= 0){
147 printf("\nData queue_0 entries is not equal to 0\n");
148 } // if
149 if(oceos_dataq_get_size(queue_1)!= 0){
150 printf("\nData queue_1 entries is not equal to 0\n");
151 } // if
152
153 // 7) Action: Task 0 writes this pointer to queue_1
154 // Check: Task 0 has succeeded
155 // a. Check: queue_0 entries count is 0
156 // b. Check: queue_1 entries count is 1
157 if(oceos_dataq_write(queue_1, &test_data) != SUCCESSFUL){
158 printf("\nDataq write was not succesful\n");
159 } // if
160 if(oceos_dataq_get_size(queue_0)!= 0){
161 printf("\nData queue_0 entries is not equal to 0\n");
162 } // if
163 if(oceos_dataq_get_size(queue_1)!= 1){
164 printf("\nData queue_1 entries is not equal to 1\n");
165 } // if
166
167 // 8) Action: Task 0 does read_restart with timeout on queue_0
168 // Check: Task 0 exits as queues_0 is empty
169 if(oceos_dataq_read_restart_timeout(queue_0, TIME_OUT) != NULL){
170 printf("\nDataq read restart timeout returned not null\n");
171 } // if
172 } else {
173 case_number++;
174 // 10) Action: Task 1 loops for at least twice timeout period T
175 // Check: Task 0 restarts on timeout, pre-empting Task 1
176 // a. Check: entry message from Task 0
177 // b. Check: queue_0 entries count is 0
178 // c. Check: queue_1 entries count is 0
179 printf("t_consumer was started\n");
180 if(oceos_dataq_get_size(queue_0)!= 0){
181 printf("\nData queue_0 entries is not equal to 0\n");
182 } // if
183 if(oceos_dataq_get_size(queue_1)!= 0){
184 printf("\nData queue_1 entries is not equal to 0\n");
185 } // if
186
187 // 11) Action: Task 0 does read_continue on queue_0
188 // Check: Task 0 has succeeded
189 // a. Check: null pointer returned
190 // b. Check: queue_0 entries count is 0
191 // c. Check: queue_1 entries count is 0
192 if(oceos_dataq_read_continue(queue_0) != NULL){
193 printf("\nDataq read continue returned not null\n");
194 } // if
195 if(oceos_dataq_get_size(queue_0)!= 0){
196 printf("\nData queue_0 entries is not equal to 0\n");
197 } // if
198 if(oceos_dataq_get_size(queue_1)!= 0){
199 printf("\nData queue_1 entries is not equal to 0\n");
200 } // if
201
202 // 12) Action: Task 0 exits
203 // Check: Task 0 exit message
204 // a. Check: queue_0 entries count is 0
205 // b. Check: queue_1 entries count is 0
206 printf("t_consumer is exiting\n");
207 if(oceos_dataq_get_size(queue_0)!= 0){
208 printf("\nData queue_0 entries is not equal to 0\n");
209 } // if
210 if(oceos_dataq_get_size(queue_1)!= 0){
211 printf("\nData queue_1 entries is not equal to 0\n");
212 } // if
213 return;
214 }
215 }//END t_consumer_task
216
217 void t_producer_task() {
218 // 1) Action: Start OCEOS with Task 1 as initial task, null input pointer
219 // Check: Task 1 has started
220 // a. Check: Starting message from Task 1
221 // b. Check: queue_0 entries count is 0
222 // c. Check: queue_0 capacity is as created
223 // d. Check: queue_1 entries count is 0
224 // e. Check: queue_1 capacity is as created
225 printf("t_producer was started\n");
226 if(oceos_dataq_get_size(queue_0)!= 0){
227 printf("\nData queue_0 entries is not equal to 0\n");
228 } // if
229 if(oceos_dataq_get_size(queue_1)!= 0){
230 printf("\nData queue_1 entries is not equal to 0\n");
231 } // if
232
233 // 2) Action: Task 1 attempts to start Task 0
234 if(oceos_task_start(t_consumer, NULL)!= SUCCESSFUL){
235 printf("\nFailed starting task t_consumer\n");
236 } // if
237
238 // 3) Action: Task 0 does read_restart on queue_0
239 // Check: Task 0 exits as queue_0 is empty
240 // Check: Task 1 continues
241 // a. Check: continue message from Task 1
242 // b. Check: queue_0 entries count is 0
243 // c. Check: queue_1 entries count is 0
244 printf("t_producer continues \n");
245 if(oceos_dataq_get_size(queue_0)!= 0){
246 printf("\nData queue_0 entries is not equal to 0\n");
247 } // if
248 if(oceos_dataq_get_size(queue_1)!= 0){
249 printf("\nData queue_1 entries is not equal to 0\n");
250 } // if
251
252 // 4) Action: Task 1 does read_continue on queue_1
253 // Check: null pointer returned
254 if(oceos_dataq_read_continue(queue_1) != NULL){
255 printf("\nDataq read continue returned not null\n");
256 } // if
257
258 // 5) Action: Task 1 writes pointer to struct to queue_0
259 if(oceos_dataq_write(queue_0, &test_data) != SUCCESSFUL){
260 printf("\nDataq write failed\n");
261 } // if
262
263 // 8) Action: Task 0 does read_restart with timeout on queue_0
264 // Check: Task 0 exits as queues_0 is empty
265 // Check: Task 1 continues
266 // a. Check: continue message from Task 1
267 // b. Check: queue_0 entries count is 0
268 // c. Check: queue_1 entries count is 1
269 printf("t_producer continues \n");
270 if(oceos_dataq_get_size(queue_0)!= 0){
271 printf("\nData queue_0 entries is not equal to 0\n");
272 } // if
273 if(oceos_dataq_get_size(queue_1)!= 1){
274 printf("\nData queue_1 entries is not equal to 1\n");
275 } // if
276
277 // 9) Action: Task 1 does read_continue on queue_1
278 // Check: Non-null pointer returned
279 // a. Check: pointer to same struct
280 // b. Check: queue_0 entries count is 0
281 // c. Check: queue_1 entries count is 0
282 struct data *temp_data = oceos_dataq_read_continue(queue_1);
283 if(temp_data == NULL){
284 printf("\ntemp_data is null\n");
285 } // if
286 if(test_data.message != temp_data->message){
287 printf("\npointer not to same struct\n");
288 } // if
289 if(oceos_dataq_get_size(queue_0)!= 0){
290 printf("\nData queue_0 entries is not equal to 0\n");
291 } // if
292 if(oceos_dataq_get_size(queue_1)!= 0){
293 printf("\nData queue_1 entries is not equal to 0\n");
294 } // if
295
296 // 10) Action: Task 1 loops for at least three timeout period
297 // Check: Task 0 restarts on timeout, pre-empting Task 1
298 test_wait(TIME_OUT * 3);
299
300 //Task 1 writes pointer to struct on queue_1
301 if(oceos_dataq_write(queue_1, &test_data) != SUCCESSFUL){
302 printf("\nDataq write failed\n");
303 } // if
304 // Data q size check
305 if(oceos_dataq_get_size(queue_1)!= 1){
306 printf("\nData queue_1 entries is not equal to 1\n");
307 } // if
308 // Task 1 does read restart on queue_1
309 if(oceos_dataq_read_restart(queue_1) == NULL){
310 printf("\nDataq read restart failed\n");
311 } // if
312 // Data q size check
313 if(oceos_dataq_get_size(queue_1)!= 0){
314 printf("\nData queue_1 entries is not equal to 0\n");
315 } // if
316 //Task 1 writes pointer to struct on queue_1
317 if(oceos_dataq_write(queue_1, &test_data) != SUCCESSFUL){
318 printf("\nDataq write failed\n");
319 } // if
320 // Data q size check
321 if(oceos_dataq_get_size(queue_1)!= 1){
322 printf("\nData queue_1 entries is not equal to 1\n");
323 } // if
324 // Data q clear
325 if(oceos_dataq_clear(queue_1)!= 0){
326 printf("\nDataq clear failed\n");
327 } // if
328
329 // Data q size check
330 if(oceos_dataq_get_size(queue_1)!= 0){
331 printf("\nData queue_1 entries is not equal to 0\n");
332 } // if
333 // Data pending q size check
334 if(oceos_dataq_penq_get_size(queue_1) != 0){
335 printf("\nDataq pending queue not equal to 0\n");
336 } // if
337
338 // 14) Action: Task 1 terminates
339 // Check: Task 1 exit message
340 printf("t_producer is exiting\n");
341
342 // 15) Action: CPU placed in sleep mode
343 // Check: Sleep mode starting message
344 if(oceos_exit() != SUCCESSFUL){
345 printf("\nOceos exiting failed\n");
346 } // if
347
348 return;
349 }