Difference between revisions of "OCEOS Tutorials"
Dtimofejevs (talk | contribs) Tag: Reverted |
Dtimofejevs (talk | contribs) |
||
(24 intermediate revisions by the same user not shown) | |||
Line 32: | Line 32: | ||
For code example see below. | For code example see below. | ||
<syntaxhighlight lang="C" line> | '''''tut.h''''' | ||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* OCEOS | |||
* Real-Time Operating System | |||
* for | |||
* ARM Microcontroller | |||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#ifndef TUT1_H_ | |||
#define TUT1_H_ | |||
/* Sample Task names - all here start with t_ to help avoid name confusion */ | |||
enum TASK_NAME{ | |||
t_0, // High priority task | |||
t_1 // Low priority task | |||
}; | |||
char* nullPtr = ""; // Need pointer to pass to oceos_start | |||
void (*nullFun)(void *); // Null function | |||
/* | |||
* APPLICATION FUNCTION DECLARATIONS | |||
*/ | |||
void fun0(void *); | |||
void fun1(void *); | |||
#endif /* TUT1_H_ */ | |||
</syntaxhighlight> | |||
'''''oceos_config.h''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* OCEOS | |||
* Real-Time Operating System | |||
* for | |||
* ARM Microcontroller | |||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#ifndef INCLUDE_OCEOS_CONFIG_H_ | |||
#define INCLUDE_OCEOS_CONFIG_H_ | |||
// 1: Includes OCEOS main header file | |||
#include "oceos.h" | |||
//---------------------------------------------------------------------------- | |||
// 2: Number of Log entries. | |||
#define NUMBER_OF_LOG_ENTRIES 64 // 16 to 1024, default 64 | |||
//---------------------------------------------------------------------------- | |||
// 3: Number of tasks | |||
#define NUMBER_OF_TASKS 2 // 1 to 255 | |||
//---------------------------------------------------------------------------- | |||
// 4: Number of ready queue entries, 0 to 254, see manual( MUST BE UPDATED BY USER); | |||
// Defaults to number of tasks, as each task should have aa least one job; | |||
// If Number of ready Q entries larger that number of total jobs => defaults to number of total jobs | |||
#define NUMBER_OF_READYQ_ENTRIES NUMBER_OF_TASKS * 2 | |||
//---------------------------------------------------------------------------- | |||
// 5: Number of Mutexes | |||
#define NUMBER_OF_MUTEXES 0 // 0 to 63 | |||
//---------------------------------------------------------------------------- | |||
// 6: Number of Semaphores | |||
#define NUMBER_OF_SEMAPHORES 0 // 0 to 63 | |||
//---------------------------------------------------------------------------- | |||
// 7: Number of Data Qs | |||
#define NUMBER_OF_DATAQS 0 // 0 to 63 | |||
//---------------------------------------------------------------------------- | |||
// 8: LOG data array size | |||
#define LOG_DATA_ARRAY_SIZE_U32S 0x88// Calculated value. Read manual | |||
//---------------------------------------------------------------------------- | |||
// 9: FIXED data array size | |||
#define FIXED_DATA_ARRAY_SIZE_U32S 0x32// Calculated value. Read manual | |||
//---------------------------------------------------------------------------- | |||
// 10: DYNAMIC data array size | |||
#define DYN_DATA_ARRAY_SIZE_U32S 0x33// Calculated value. Read manual | |||
//---------------------------------------------------------------------------- | |||
// 11: Timed Actions | |||
#define NUMBER_OF_ACTION_ENTRIES 0 // User-modify field | |||
//---------------------------------------------------------------------------- | |||
// 12: Log entries base 2 | |||
#define CS_LOG_DEF_ENTRIES_BASE2 0 | |||
//---------------------------------------------------------------------------- | |||
// 13: OCEOS stack start Address | |||
#define OCEOS_STACK_START_ADDRESS 0 | |||
//---------------------------------------------------------------------------- | |||
// 14: OCEOS stack end address | |||
#define OCEOS_STACK_LOW_BOUND_ADDRESS 0 | |||
//---------------------------------------------------------------------------- | |||
/** | |||
* Target specific configurations | |||
*/ | |||
/* | /* | ||
** | * ARM specific configurations | ||
*/ | |||
#ifdef __SAM3X8E__ | |||
#ifndef BSP_SYSFREQ | |||
#define BSP_SYSFREQ 84 // ARM target frequency in Mhz | |||
#endif | |||
#endif | |||
#ifdef __SAMV71Q21__ | |||
#ifndef BSP_SYSFREQ | |||
#define BSP_SYSFREQ 300 // ARM target frequency in Mhz | |||
#endif | |||
#endif | |||
*** | #ifdef __VA41620__ | ||
#ifndef BSP_SYSFREQ | |||
#define BSP_SYSFREQ 100 // ARM target frequency in Mhz | |||
#endif | |||
#endif | |||
//-------------------------------------------------------------------- | |||
// User defined function to deal with system errors | |||
void oceos_on_error(void); | |||
//--------------------------------------------------------------------- | |||
// User defined function to deal with log 2/3 full | |||
void oceos_on_full_log(void); | |||
//--------------------------------------------------------------------- | |||
extern U32_t log_data[]; | |||
extern U32_t fixed_data[]; | |||
extern U32_t dynamic_data[]; | |||
extern const unsigned int __oceos_bsp_sysfreq; | |||
/** | |||
* Initialize OCEOS with user configurations | |||
*/ | */ | ||
int application_init(void); | |||
#endif /* INCLUDE_OCEOS_CONFIG_H_ */ | |||
# | |||
/ | </syntaxhighlight> | ||
'''''oceos_config.c''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* OCEOS | |||
* Real-Time Operating System | |||
* for | |||
* ARM Microcontroller | |||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#include <stdio.h> | |||
#include "oceos_config.h" | |||
/* | /* | ||
* | * OCEOS INTERNAL DATA STORAGE | ||
* | * | ||
* This application defines arrays to hold OCEOS internal data. | |||
* The array sizes are provided by DMON by running "oceos info" command:</br> | |||
* *Set all three arrays to guessed max zise, run application for the first time and exit.</br> | |||
* *Run DMON command "oceos info" to get size for each array.</br> | |||
* *Update array sizes below | |||
*/ | */ | ||
U32_t log_data[LOG_DATA_ARRAY_SIZE_U32S]; | |||
U32_t fixed_data[FIXED_DATA_ARRAY_SIZE_U32S] = {0}; // will be in data segment | |||
U32_t dynamic_data[DYN_DATA_ARRAY_SIZE_U32S]; | |||
const unsigned int __oceos_bsp_sysfreq = BSP_SYSFREQ * 1000 * 1000;// TODO | |||
static BOOLE_t log_full_was_called = FALSE; | |||
/** | |||
* Must be defined if Application is using : | |||
* Dataq with timeout | |||
* Semaphore with timeout | |||
* Timed Actions | |||
*/ | |||
/* | |||
* Set up the application configuration structure and pass it to oceos_init | |||
* (done this way the memory used for the structure is returned automatically) | |||
*/ | |||
int application_init(){ | |||
/* | /* | ||
* | * Create the application configuration structure | ||
*/ | */ | ||
struct application_configuration app_config = {0}; | |||
/* | /* | ||
* | * Fill in the application parameters | ||
*/ | */ | ||
status = oceos_start(fixed_data, t_1, (void *)nullPtr); | 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 | |||
* ARM Microcontroller | |||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include "tut1.h" // application header | |||
#include "oceos_config.h" // OCEOS header | |||
int main(void) { | |||
int status; | |||
/* | |||
* Initialise the application configuration and OCEOS | |||
* | |||
* This application function creates the application configuration | |||
* and passes it to oceos_init(), which initialises the fixed data | |||
* and enables the system log | |||
*/ | |||
if (!application_init()) { | |||
//LOG | |||
return -1; | |||
} | |||
// Create Main task to | |||
if (oceos_task_create(t_0,// taskID, used as index, must be in range 0 to 254 | |||
100,// priority, must be in range 1 to 254, lower value is higher priority | |||
100, // threshold, must be in range 1 to task priority | |||
2, // jobs_max, must be in range 1 to 15 | |||
0,// FALSE -> floating point hardware not used by task | |||
1, // FALSE -> task initially not enabled | |||
fun0, // main body of task | |||
nullFun, // task end function | |||
0,// time_deadline, must finish no later than this after start, 0 => ignore | |||
0 // minimum time expected between start requests, 0 => no restriction | |||
) != SUCCESSFUL) | |||
return 1; | |||
if (oceos_task_create(t_1, 200, 200, 2, 0, 1, fun1, nullFun, 0, 0) | |||
!= SUCCESSFUL) | |||
return 2; | |||
/* | |||
* Finish initialising OCEOS and setting up the fixed data | |||
*/ | |||
status = oceos_init_finish(); | |||
if (SUCCESSFUL != status) { | |||
return 3; | |||
} // if | |||
/* | |||
* Start OCEOS scheduling | |||
* | |||
* The OCEOS fixed data provides all the information required. | |||
* | |||
* If a valid task is specified, it is started and passed the pointer. | |||
* Otherwise the system is put in sleep mode | |||
*/ | |||
status = oceos_start(fixed_data, t_1, (void*) nullPtr); // Start OCEOS with lower prioroty task | |||
return status; | |||
} // main | } // main | ||
/* | /* | ||
* Application code functions, functions declared in asw.h | * Application code functions, functions declared in asw.h | ||
*/ | */ | ||
void fun0(void * ptr){ | void fun0(void *ptr) { | ||
printf("Entered high priority task\n"); | |||
oceos_task_start(t_1, ptr); | |||
printf("Leaving high priority task\n"); | |||
return; | |||
} // fun0() | } // 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> | |||
=== Tutorial 2 – Using a mutex === | |||
<p>This exercise will familiarise the developer with the use a mutexes.</p> | |||
# Two tasks as before. | |||
# One mutex. Note the priority ceiling of the mutex. | |||
# Both tasks output message when they get the mutex and when they return it | |||
# Start OCEOS with the low priority task | |||
# This grabs mutex, then starts high priority task | |||
# Low priority task returns mutex then exits | |||
# High priority task returns mutex, start low priority task and exits | |||
For code example see example below: | |||
'''''tut2.h''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* OCEOS | |||
* Real-Time Operating System | |||
* for | |||
* ARM Microcontroller | |||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#ifndef TUT2_H_ | |||
#define TUT2_H_ | |||
/* Sample Task names - all here start with t_ to help avoid name confusion */ | |||
enum TASK_NAME{ | |||
t_0, // High priority task | |||
t_1 // Low priority task | |||
}; | |||
/* Sample Mutex names - all here start with m_ to help avoid name confusion */ | |||
enum MUTEX_NAME{ | |||
m_0 | |||
}; | |||
char* nullPtr = ""; // Need pointer to pass to oceos_start | |||
void (*nullFun)(void *); // Null function | |||
/* | |||
* APPLICATION FUNCTION DECLARATIONS | |||
*/ | |||
void fun0(void *); | |||
void fun1(void *); | |||
#endif /* TUT2_H_ */ | |||
</syntaxhighlight> | |||
'''''oceos_config.h''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* OCEOS | |||
* Real-Time Operating System | |||
* for | |||
* ARM Microcontroller | |||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#ifndef INCLUDE_OCEOS_CONFIG_H_ | |||
#define INCLUDE_OCEOS_CONFIG_H_ | |||
// 1: Includes OCEOS main header file | |||
#include "oceos.h" | |||
//---------------------------------------------------------------------------- | |||
// 2: Number of Log entries. | // 2: Number of Log entries. | ||
#define NUMBER_OF_LOG_ENTRIES | #define NUMBER_OF_LOG_ENTRIES 64 // 16 to 1024, default 64 | ||
//---------------------------------------------------------------------------- | //---------------------------------------------------------------------------- | ||
// 3: Number of tasks | // 3: Number of tasks | ||
#define 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); | // 4: Number of ready queue entries, 0 to 254, see manual( MUST BE UPDATED BY USER); | ||
Line 157: | Line 490: | ||
//---------------------------------------------------------------------------- | //---------------------------------------------------------------------------- | ||
// 6: Number of Semaphores | // 6: Number of Semaphores | ||
#define NUMBER_OF_SEMAPHORES | #define NUMBER_OF_SEMAPHORES 0 // 0 to 63 | ||
//---------------------------------------------------------------------------- | //---------------------------------------------------------------------------- | ||
// 7: Number of Data Qs | // 7: Number of Data Qs | ||
#define NUMBER_OF_DATAQS | #define NUMBER_OF_DATAQS 0 // 0 to 63 | ||
//---------------------------------------------------------------------------- | //---------------------------------------------------------------------------- | ||
// 8: LOG data array size | // 8: LOG data array size | ||
#define LOG_DATA_ARRAY_SIZE_U32S | #define LOG_DATA_ARRAY_SIZE_U32S 0x88// Calculated value. Read manual | ||
//---------------------------------------------------------------------------- | //---------------------------------------------------------------------------- | ||
// 9: FIXED data array size | // 9: FIXED data array size | ||
#define FIXED_DATA_ARRAY_SIZE_U32S | #define FIXED_DATA_ARRAY_SIZE_U32S 0x33// Calculated value. Read manual | ||
//---------------------------------------------------------------------------- | //---------------------------------------------------------------------------- | ||
// 10: DYNAMIC data array size | // 10: DYNAMIC data array size | ||
#define DYN_DATA_ARRAY_SIZE_U32S | #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 | |||
* ARM Microcontroller | |||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#include <stdio.h> | |||
#include "oceos_config.h" | |||
/* | |||
* OCEOS INTERNAL DATA STORAGE | |||
* | |||
* This application defines arrays to hold OCEOS internal data. | |||
* The array sizes are provided by DMON by running "oceos info" command:</br> | |||
* *Set all three arrays to guessed max zise, run application for the first time and exit.</br> | |||
* *Run DMON command "oceos info" to get size for each array.</br> | |||
* *Update array sizes below | |||
*/ | |||
U32_t log_data[LOG_DATA_ARRAY_SIZE_U32S]; | |||
U32_t fixed_data[FIXED_DATA_ARRAY_SIZE_U32S] = {0}; // will be in data segment | |||
U32_t dynamic_data[DYN_DATA_ARRAY_SIZE_U32S]; | |||
const unsigned int __oceos_bsp_sysfreq = BSP_SYSFREQ * 1000 * 1000;// TODO | |||
static BOOLE_t log_full_was_called = FALSE; | |||
/** | |||
* Must be defined if Application is using : | |||
* Dataq with timeout | |||
* Semaphore with timeout | |||
* Timed Actions | |||
*/ | |||
/* | |||
* Set up the application configuration structure and pass it to oceos_init | |||
* (done this way the memory used for the structure is returned automatically) | |||
*/ | |||
int application_init(){ | |||
/* | |||
* Create the application configuration structure | |||
*/ | |||
struct application_configuration app_config = {0}; | |||
/* | |||
* Fill in the application parameters | |||
*/ | |||
app_config.log_address = (adrs_t)log_data; // required | |||
app_config.fixed_data_address = (adrs_t)fixed_data; // required | |||
app_config.dynamic_data_address = (adrs_t)dynamic_data; // required | |||
app_config.stack_start_address = OCEOS_STACK_START_ADDRESS; // 0 => no check | |||
app_config.stack_lower_bound_address = OCEOS_STACK_LOW_BOUND_ADDRESS; // 0 => no check | |||
app_config.system_error_function = &oceos_on_error; // NULL => ignore | |||
app_config.log_full_function = &oceos_on_full_log; // NULL => ignore | |||
// used in setting up system log and fixed data array | |||
app_config.log_number_of_entries = NUMBER_OF_LOG_ENTRIES; // 0 => use default | |||
=== | app_config.number_of_tasks = NUMBER_OF_TASKS; // >= 1 | ||
app_config.number_of_readyQ_entries = NUMBER_OF_READYQ_ENTRIES; // 0 => calculate size | |||
app_config.number_of_mutexes = NUMBER_OF_MUTEXES; | |||
app_config.number_of_counting_semaphores = NUMBER_OF_SEMAPHORES; | |||
app_config.number_of_data_queues = NUMBER_OF_DATAQS; | |||
app_config.timed_actions_queue_size = NUMBER_OF_ACTION_ENTRIES; | |||
app_config.CS_log_entries_base2 = CS_LOG_DEF_ENTRIES_BASE2; | |||
app_config.use_oceos_system_time = TRUE; | |||
// initialise OCEOS | |||
enum DIRECTIVE_STATUS status; | |||
status = oceos_init(app_config); | |||
if (SUCCESSFUL == status) { | |||
return 1; | |||
} else { | |||
printf("\n oceos_init failure\n"); | |||
return -1; | |||
} // else | |||
} // application_init() | |||
/** | |||
* User to implement in case of system error; | |||
* Comment it out if not used and set field system_error_function in app_config to NULL | |||
*/ | |||
void oceos_on_error() { | |||
return; | |||
} | |||
/** | |||
* User to implement in case of system log is 2/3 full; | |||
* Comment it out if not used and set field log_full_function in app_config to NULL | |||
*/ | |||
void oceos_on_full_log(){ | |||
log_full_was_called = TRUE; | |||
return; | |||
} | |||
</syntaxhighlight> | |||
'''''tut2.c''''' | |||
<syntaxhighlight lang="C" line> | <syntaxhighlight lang="C" line> | ||
/* | /* | ||
********************************************************************************************************* | ********************************************************************************************************* | ||
* OCEOS | * OCEOS | ||
* Real-Time Operating System | * Real-Time Operating System | ||
* for | * for | ||
* | * ARM Microcontroller | ||
* | * | ||
* | * Example implementation of OCEOS | ||
* | * | ||
* (c) Copyright | * | ||
* All Rights Reserved | * (c) Copyright 2021, O.C.E. Technology | ||
* | * All Rights Reserved | ||
* | * | ||
******************************************************************************************************** | * | ||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | */ | ||
#include <stdio.h> | #include <stdio.h> | ||
#include <stdlib.h> | #include <stdlib.h> | ||
#include "tut2.h" // application header | |||
/* N.B. Application header is included first */ | /* N.B. Application header is included first */ | ||
#include "oceos_config.h" // OCEOS header for this application | #include "oceos_config.h" // OCEOS header for this application | ||
#include "mutex.h" | |||
int main(void) { | 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 | } // main | ||
/* | /* | ||
* Application code functions, functions declared in asw.h | * Application code functions, functions declared in asw.h | ||
*/ | */ | ||
void fun0(void * ptr){ | 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() | } // 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> | </syntaxhighlight> | ||
Line 343: | Line 817: | ||
For code example see below: | For code example see below: | ||
'''''tut3.h''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* OCEOS | |||
* Real-Time Operating System | |||
* for | |||
* ARM Microcontroller | |||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#ifndef TUT3_H_ | |||
#define TUT3_H_ | |||
/* Sample Task names - all here start with t_ to help avoid name confusion */ | |||
enum TASK_NAME{ | |||
t_0, // Task to start other two | |||
t_1, // consumer task | |||
t_2 // consumer task | |||
}; | |||
/* Sample Counting Semaphore names - all here start with s_ to help avoid name confusion */ | |||
enum SEM_NAME{ | |||
items, // Semaphore called items | |||
spaces // Semaphore called spaces | |||
}; | |||
char* nullPtr = ""; // Need pointer to pass to oceos_start | |||
void (*nullFun)(void *); // Null function | |||
/* | |||
* APPLICATION FUNCTION DECLARATIONS | |||
*/ | |||
void fun0(void *); | |||
void fun1(void *); | |||
void fun2(void *); | |||
#endif /* TUT3_H_ */ | |||
</syntaxhighlight> | |||
'''''oceos_config.h''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | /* | ||
********************************************************************************************************* | ********************************************************************************************************* | ||
* OCEOS | * OCEOS | ||
* Real-Time Operating System | * Real-Time Operating System | ||
* for | * for | ||
* | * ARM Microcontroller | ||
* | * | ||
* | * Example implementation of OCEOS | ||
* | * | ||
* (c) Copyright | * | ||
* All Rights Reserved | * (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 | |||
* ARM Microcontroller | |||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#include <stdio.h> | #include <stdio.h> | ||
#include "oceos_config.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]; | |||
int | 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 | ||
*/ | */ | ||
status = oceos_start(fixed_data, t_0, (void *)nullPtr); | 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 | |||
* ARM Microcontroller | |||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
/* N.B. Application header is included first */ | |||
#include "oceos_config.h" // OCEOS header for this application | |||
#include "tut3.h" // application header | |||
#include "semaphore.h" | |||
int main(void) { | |||
int status; | |||
/* | |||
* Initialise the application configuration and OCEOS | |||
* | |||
* This application function creates the application configuration | |||
* and passes it to oceos_init(), which initialises the fixed data | |||
* and enables the system log | |||
*/ | |||
if (!application_init()) { | |||
//LOG | |||
return -1; | |||
} | |||
// Create Main task to | |||
if (oceos_task_create(t_0,// taskID, used as index, must be in range 0 to 254 | |||
10, // priority, must be in range 1 to 254, lower value is higher priority | |||
10, // threshold, must be in range 1 to task priority | |||
1, // jobs_max, must be in range 1 to 15 | |||
0,// FALSE -> floating point hardware not used by task | |||
1, // FALSE -> task initially not enabled | |||
fun0, // main body of task | |||
nullFun, // task end function | |||
0,// time_deadline, must finish no later than this after start, 0 => ignore | |||
0 // minimum time expected between start requests, 0 => no restriction | |||
) != SUCCESSFUL) | |||
return 1; | |||
if (oceos_task_create(t_1, 100, 100, 1, 0, 1, fun1, nullFun, 0, 0) | |||
!= SUCCESSFUL) | |||
return 2; | |||
if (oceos_task_create(t_2, 100, 100, 1, 0, 1, fun2, nullFun, 0, 0) | |||
!= SUCCESSFUL) | |||
return 3; | |||
if (oceos_sem_create(items, 10, 0, 2, FALSE) != SUCCESSFUL)// items semaphore with max permits of 10, initial permits of 0, max jobs 2 | |||
return 4; | |||
if (oceos_sem_create(spaces, 10, 4, 2, FALSE) != SUCCESSFUL) // spaces semaphore with max permits of 10, initial permits of 4, max jobs 2 | |||
return 4; | |||
/* | |||
* Finish initialising OCEOS and setting up the fixed data | |||
*/ | |||
status = oceos_init_finish(); | |||
if (SUCCESSFUL != status) { | |||
return 6; | |||
} // if | |||
/* | |||
* Start OCEOS scheduling | |||
* | |||
* The OCEOS fixed data provides all the information required. | |||
* | |||
* If a valid task is specified, it is started and passed the pointer. | |||
* Otherwise the system is put in sleep mode | |||
*/ | |||
status = oceos_start(fixed_data, t_0, (void*) nullPtr); // Start OCEOS with task to start other tasks | |||
return status; | |||
} // main | } // main | ||
Line 435: | Line 1,171: | ||
* Application code functions, functions declared in asw.h | * Application code functions, functions declared in asw.h | ||
*/ | */ | ||
void fun0(void * ptr){ | void fun0(void *ptr) { | ||
oceos_task_start(t_1, ptr); // Start consumer task | |||
oceos_task_start(t_2, ptr); // Start consumer task | |||
} // fun0() | } // fun0() | ||
void fun1(void * ptr){ | 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() | } // fun0() | ||
void fun2(void * ptr){ | 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() | } // fun1() | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Line 478: | Line 1,215: | ||
For code example see below: | For code example see below: | ||
'''''tut4.h''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* OCEOS | |||
* Real-Time Operating System | |||
* for | |||
* ARM Microcontroller | |||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#ifndef TUT4_H_ | |||
#define TUT4_H_ | |||
/* Sample Task names - all here start with t_ to help avoid name confusion */ | |||
enum TASK_NAME{ | |||
t_0, // Task to setup interrupt | |||
t_1 // Task to be executed by interrupt routine | |||
}; | |||
/* | |||
* APPLICATION FUNCTION DECLARATIONS | |||
*/ | |||
void fun0(void *); | |||
void fun1(void *); | |||
void start_task(void *arg, int source); | |||
void timer_setup(void); | |||
#endif /* TUT4_H_ */ | |||
</syntaxhighlight> | |||
'''''oceos_config.h''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* OCEOS | |||
* Real-Time Operating System | |||
* for | |||
* ARM Microcontroller | |||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#ifndef INCLUDE_OCEOS_CONFIG_H_ | |||
#define INCLUDE_OCEOS_CONFIG_H_ | |||
// 1: Includes OCEOS main header file | |||
#include "oceos.h" | |||
//---------------------------------------------------------------------------- | |||
// 2: Number of Log entries. | |||
#define NUMBER_OF_LOG_ENTRIES 64 // 16 to 1024, default 64 | |||
//---------------------------------------------------------------------------- | |||
// 3: Number of tasks | |||
#define NUMBER_OF_TASKS 2 // 1 to 255 | |||
//---------------------------------------------------------------------------- | |||
// 4: Number of ready queue entries, 0 to 254, see manual( MUST BE UPDATED BY USER); | |||
// Defaults to number of tasks, as each task should have aa least one job; | |||
// If Number of ready Q entries larger that number of total jobs => defaults to number of total jobs | |||
#define NUMBER_OF_READYQ_ENTRIES NUMBER_OF_TASKS + 1 | |||
//---------------------------------------------------------------------------- | |||
// 5: Number of Mutexes | |||
#define NUMBER_OF_MUTEXES 0 // 0 to 63 | |||
//---------------------------------------------------------------------------- | |||
// 6: Number of Semaphores | |||
#define NUMBER_OF_SEMAPHORES 0 // 0 to 63 | |||
//---------------------------------------------------------------------------- | |||
// 7: Number of Data Qs | |||
#define NUMBER_OF_DATAQS 0 // 0 to 63 | |||
//---------------------------------------------------------------------------- | |||
// 8: LOG data array size | |||
#define LOG_DATA_ARRAY_SIZE_U32S 0x88// Calculated value. Read manual | |||
//---------------------------------------------------------------------------- | |||
// 9: FIXED data array size | |||
#define FIXED_DATA_ARRAY_SIZE_U32S 0x32// Calculated value. Read manual | |||
//---------------------------------------------------------------------------- | |||
// 10: DYNAMIC data array size | |||
#define DYN_DATA_ARRAY_SIZE_U32S 0x29// Calculated value. Read manual | |||
//---------------------------------------------------------------------------- | |||
// 11: Timed Actions | |||
#define NUMBER_OF_ACTION_ENTRIES 0 // User-modify field | |||
//---------------------------------------------------------------------------- | |||
// 12: Log entries base 2 | |||
#define CS_LOG_DEF_ENTRIES_BASE2 0 | |||
//---------------------------------------------------------------------------- | |||
// 13: OCEOS stack start Address | |||
#define OCEOS_STACK_START_ADDRESS 0 | |||
//---------------------------------------------------------------------------- | |||
// 14: OCEOS stack end address | |||
#define OCEOS_STACK_LOW_BOUND_ADDRESS 0 | |||
//---------------------------------------------------------------------------- | |||
/** | |||
* Target specific configurations | |||
*/ | |||
/* | |||
* ARM specific configurations | |||
*/ | |||
#ifdef __SAM3X8E__ | |||
#ifndef BSP_SYSFREQ | |||
#define BSP_SYSFREQ 84 // ARM target frequency in Mhz | |||
#endif | |||
#endif | |||
#ifdef __SAMV71Q21__ | |||
#ifndef BSP_SYSFREQ | |||
#define BSP_SYSFREQ 300 // ARM target frequency in Mhz | |||
#endif | |||
#endif | |||
#ifdef __VA41620__ | |||
#ifndef BSP_SYSFREQ | |||
#define BSP_SYSFREQ 100 // ARM target frequency in Mhz | |||
#endif | |||
#endif | |||
//-------------------------------------------------------------------- | |||
// User defined function to deal with system errors | |||
void oceos_on_error(void); | |||
//--------------------------------------------------------------------- | |||
// User defined function to deal with log 2/3 full | |||
void oceos_on_full_log(void); | |||
//--------------------------------------------------------------------- | |||
extern U32_t log_data[]; | |||
extern U32_t fixed_data[]; | |||
extern U32_t dynamic_data[]; | |||
extern const unsigned int __oceos_bsp_sysfreq; | |||
/** | |||
* Initialize OCEOS with user configurations | |||
*/ | |||
int application_init(void); | |||
#endif /* INCLUDE_OCEOS_CONFIG_H_ */ | |||
</syntaxhighlight> | |||
'''''oceos_config.c''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* OCEOS | |||
* Real-Time Operating System | |||
* for | |||
* ARM Microcontroller | |||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#include <stdio.h> | |||
#include "oceos_config.h" | |||
/* | |||
* OCEOS INTERNAL DATA STORAGE | |||
* | |||
* This application defines arrays to hold OCEOS internal data. | |||
* The array sizes are provided by DMON by running "oceos info" command:</br> | |||
* *Set all three arrays to guessed max zise, run application for the first time and exit.</br> | |||
* *Run DMON command "oceos info" to get size for each array.</br> | |||
* *Update array sizes below | |||
*/ | |||
U32_t log_data[LOG_DATA_ARRAY_SIZE_U32S]; | |||
U32_t fixed_data[FIXED_DATA_ARRAY_SIZE_U32S] = {0}; // will be in data segment | |||
U32_t dynamic_data[DYN_DATA_ARRAY_SIZE_U32S]; | |||
const unsigned int __oceos_bsp_sysfreq = BSP_SYSFREQ * 1000 * 1000;// TODO | |||
static BOOLE_t log_full_was_called = FALSE; | |||
/** | |||
* Must be defined if Application is using : | |||
* Dataq with timeout | |||
* Semaphore with timeout | |||
* Timed Actions | |||
*/ | |||
/* | |||
* Set up the application configuration structure and pass it to oceos_init | |||
* (done this way the memory used for the structure is returned automatically) | |||
*/ | |||
int application_init(){ | |||
/* | |||
* Create the application configuration structure | |||
*/ | |||
struct application_configuration app_config = {0}; | |||
/* | |||
* Fill in the application parameters | |||
*/ | |||
app_config.log_address = (adrs_t)log_data; // required | |||
app_config.fixed_data_address = (adrs_t)fixed_data; // required | |||
app_config.dynamic_data_address = (adrs_t)dynamic_data; // required | |||
app_config.stack_start_address = OCEOS_STACK_START_ADDRESS; // 0 => no check | |||
app_config.stack_lower_bound_address = OCEOS_STACK_LOW_BOUND_ADDRESS; // 0 => no check | |||
app_config.system_error_function = &oceos_on_error; // NULL => ignore | |||
app_config.log_full_function = &oceos_on_full_log; // NULL => ignore | |||
// used in setting up system log and fixed data array | |||
app_config.log_number_of_entries = NUMBER_OF_LOG_ENTRIES; // 0 => use default | |||
app_config.number_of_tasks = NUMBER_OF_TASKS; // >= 1 | |||
app_config.number_of_readyQ_entries = NUMBER_OF_READYQ_ENTRIES; // 0 => calculate size | |||
app_config.number_of_mutexes = NUMBER_OF_MUTEXES; | |||
app_config.number_of_counting_semaphores = NUMBER_OF_SEMAPHORES; | |||
app_config.number_of_data_queues = NUMBER_OF_DATAQS; | |||
app_config.timed_actions_queue_size = NUMBER_OF_ACTION_ENTRIES; | |||
app_config.CS_log_entries_base2 = CS_LOG_DEF_ENTRIES_BASE2; | |||
app_config.use_oceos_system_time = TRUE; | |||
// initialise OCEOS | |||
enum DIRECTIVE_STATUS status; | |||
status = oceos_init(app_config); | |||
if (SUCCESSFUL == status) { | |||
return 1; | |||
} else { | |||
printf("\n oceos_init failure\n"); | |||
return -1; | |||
} // else | |||
} // application_init() | |||
/** | |||
* User to implement in case of system error; | |||
* Comment it out if not used and set field system_error_function in app_config to NULL | |||
*/ | |||
void oceos_on_error() { | |||
return; | |||
} | |||
/** | |||
* User to implement in case of system log is 2/3 full; | |||
* Comment it out if not used and set field log_full_function in app_config to NULL | |||
*/ | |||
void oceos_on_full_log(){ | |||
log_full_was_called = TRUE; | |||
return; | |||
} | |||
</syntaxhighlight> | |||
'''''arm_task_src.c''''' | |||
<syntaxhighlight lang="C" line> | |||
/* | |||
********************************************************************************************************* | |||
* OCEOS | |||
* Real-Time Operating System | |||
* for | |||
* ARM Microcontroller | |||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include "tut4.h" | |||
#include "oceos_config.h" | |||
#if defined(__SAM3X8E__) || defined(__SAMV71Q21__) | |||
#include "sam.h" | |||
#define ENABLE_WAVE_MODE (0x1 << TC_CMR_WAVE_Pos) | |||
#define TC_CMR_WAVE_SEL_Pos 13 | |||
#define SET_WAVE_SELECT (~(0x3 << TC_CMR_WAVE_SEL_Pos)) //00 | |||
#define TC_CMR_CPCSTOP_Pos 6 | |||
#define TC_CMR_CPCSTOP (0x1 << TC_CMR_CPCSTOP_Pos) | |||
static Tc *timer_regs; | |||
static TcChannel *tc; | |||
#endif | |||
/* | |||
* Set up timer and register handler | |||
*/ | |||
void timer_setup(){ | |||
#ifdef __SAM3X8E__ | |||
// Enabling Peripheral Clocks | |||
// REmove write protect | |||
int pmc_was_enabled = 0; | |||
if (0 != (PMC->PMC_WPMR & PMC_WPMR_WPEN)) { | |||
PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD; | |||
pmc_was_enabled = 1; | |||
} | |||
// Enable Clock | |||
PMC->PMC_PCER0 |= PMC_PCER0_PID28; | |||
// Enable write protect | |||
if (pmc_was_enabled) { | |||
PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD | PMC_WPMR_WPEN; | |||
} | |||
timer_regs = (Tc *)TC0; | |||
tc = &(timer_regs->TC_CHANNEL[1]); | |||
// Enable Wave Mode | |||
tc->TC_CMR |= ENABLE_WAVE_MODE; | |||
// Set WAVESEL to 00 | |||
tc->TC_CMR &= (U32_t)SET_WAVE_SELECT; | |||
// Set TC_CMR_CPCSTOP and Clock input | |||
tc->TC_CMR |= (TC_CMR_CPCSTOP | TC_CMR_TCCLKS_TIMER_CLOCK1); // MCK/8 | |||
// Set Block Clock | |||
timer_regs->TC_BMR &= (U32_t)(~(1 << 1)); | |||
// Interrupt Enable | |||
// Enable Timer interrupt (RC Compare) | |||
tc->TC_IER = TC_IER_CPCS; | |||
NVIC_EnableIRQ(TC1_IRQn); | |||
// Set Highest Priority for interrupt number | |||
NVIC_SetPriority(TC1_IRQn, 1); | |||
float base_scaler = (float)(__oceos_bsp_sysfreq / 2) / 1000000.0f; | |||
//tc->TC_RC = base_scaler * 0x3DC6C0; | |||
tc->TC_RC = base_scaler * 1349; | |||
// Enable clock | |||
tc->TC_CCR = TC_CCR_CLKEN; | |||
// Start clock | |||
tc->TC_CCR = TC_CCR_SWTRG; | |||
#endif | |||
#ifdef __SAMV71Q21__ | |||
// Enabling Peripheral Clocks | |||
// REmove write protect | |||
int pmc_was_enabled = 0; | |||
if (0 != (PMC->PMC_WPMR & PMC_WPMR_WPEN)) { | |||
PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD; | |||
pmc_was_enabled = 1; | |||
} | |||
// Enable Clock | |||
PMC->PMC_PCER0 |= PMC_PCER0_PID24; | |||
// Enable write protect | |||
if (pmc_was_enabled) { | |||
PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD | PMC_WPMR_WPEN; | |||
} | |||
timer_regs = (Tc *)TC0; | |||
tc = &(timer_regs->TC_CHANNEL[1]); | |||
// Enable Wave Mode | |||
tc->TC_CMR |= ENABLE_WAVE_MODE; | |||
// Set WAVESEL to 00 | |||
tc->TC_CMR &= (U32_t)SET_WAVE_SELECT; | |||
// Set TC_CMR_CPCSTOP and Clock input | |||
tc->TC_CMR |= (TC_CMR_CPCSTOP | TC_CMR_TCCLKS_TIMER_CLOCK5_Val); // | |||
// Set Block Clock | |||
timer_regs->TC_BMR &= (U32_t)(~(1 << 1)); | |||
// Interrupt Enable | |||
// Enable Timer interrupt (RC Compare) | |||
tc->TC_IER = TC_IER_CPCS; | |||
NVIC_EnableIRQ(TC1_IRQn); | |||
// Set Highest Priority for interrupt number | |||
NVIC_SetPriority(TC1_IRQn, 1); | |||
tc->TC_RC = 0x61a8;// 1s | |||
// Enable clock | |||
tc->TC_CCR = TC_CCR_CLKEN; | |||
// Start clock | |||
tc->TC_CCR = TC_CCR_SWTRG; | |||
#endif | |||
} // setup_timer() | |||
void TC1_IRQHandler() { | |||
#if defined(__SAM3X8E__) || defined(__SAMV71Q21__) | |||
tc->TC_SR;// Read to remove pending bit | |||
#endif | |||
// Start task | |||
oceos_task_start(t_1, NULL); | |||
#if defined(__SAM3X8E__) || defined(__SAMV71Q21__) | |||
tc->TC_CCR = TC_CCR_SWTRG; | |||
#endif | |||
} | |||
</syntaxhighlight> | |||
'''''tut4.c''''' | |||
<syntaxhighlight lang="C" line> | <syntaxhighlight lang="C" line> | ||
/* | /* | ||
********************************************************************************************************* | ********************************************************************************************************* | ||
* OCEOS | * OCEOS | ||
* Real-Time Operating System | * Real-Time Operating System | ||
* for | * for | ||
* | * ARM Microcontroller | ||
* | |||
* Example implementation of OCEOS | |||
* | |||
* | |||
* (c) Copyright 2021, O.C.E. Technology | |||
* All Rights Reserved | |||
* | |||
* | |||
* Author: jfk | |||
******************************************************************************************************** | |||
*/ | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
/* N.B. Application header is included first */ | |||
#include "oceos_config.h" // OCEOS header for this application | |||
#include "tut4.h" // application header | |||
volatile U32_t count_task_start = 0; | |||
int main(void) { | |||
int status; | |||
/* | |||
* Initialise the application configuration and OCEOS | |||
* | |||
* This application function creates the application configuration | |||
* and passes it to oceos_init(), which initialises the fixed data | |||
* and enables the system log | |||
*/ | |||
if (!application_init()) { | |||
//LOG | |||
return -1; | |||
} | |||
// Create Main task to | |||
if (oceos_task_create(t_0,// taskID, used as index, must be in range 0 to 254 | |||
10, // priority, must be in range 1 to 254, lower value is higher priority | |||
10, // threshold, must be in range 1 to task priority | |||
1, // jobs_max, must be in range 1 to 15 | |||
0,// FALSE -> floating point hardware not used by task | |||
1, // FALSE -> task initially not enabled | |||
fun0, // main body of task | |||
NULL, // task end function | |||
0,// time_deadline, must finish no later than this after start, 0 => ignore | |||
0 // minimum time expected between start requests, 0 => no restriction | |||
) != SUCCESSFUL) | |||
return 1; | |||
if (oceos_task_create(t_1, 100, 100, 1, 0, 1, fun1, NULL, 0, 0) | |||
!= SUCCESSFUL) | |||
return 2; | |||
/* | |||
* Finish initialising OCEOS and setting up the fixed data | |||
*/ | |||
status = oceos_init_finish(); | |||
if (SUCCESSFUL != status) { | |||
return 3; | |||
} // if | |||
/* | |||
* Start OCEOS scheduling | |||
* | |||
* The OCEOS fixed data provides all the information required. | |||
* | |||
* If a valid task is specified, it is started and passed the pointer. | |||
* Otherwise the system is put in sleep mode | |||
*/ | |||
status = oceos_start(fixed_data, t_0, NULL); // Start OCEOS | |||
return status; | |||
} // main | |||
/* | |||
* Task 0 starting point | |||
*/ | |||
void fun0(void *ptr) { | |||
timer_setup(); | |||
} // fun0() | |||
/** | |||
* Task 1 starting point; | |||
* Triggered from Timer IRQ handler | |||
*/ | |||
void fun1(void *ptr) { | |||
printf("Task started : %u times \n", count_task_start); | |||
count_task_start++; | |||
} // fun1() | |||
</syntaxhighlight> | |||
=== Tutorial 5 – Using dataq with timed action === | |||
<p>This exercise introduces the use of dataq with timed action.</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 | ||
* | * | ||
* | * | ||
* 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 <stdio.h> | ||
#include <stdlib.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_ | ||
#include " | #define INCLUDE_OCEOS_CONFIG_H_ | ||
#include < | |||
// 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) { | int main(void) { | ||
/* | /* | ||
* Initialise the application configuration and OCEOS | * Initialise the application configuration and OCEOS | ||
Line 527: | Line 2,019: | ||
if ( !application_init()) { | if ( !application_init()) { | ||
//LOG | //LOG | ||
printf("\nProblem\n"); | |||
return -1; | return -1; | ||
} | } | ||
if ( oceos_task_create( | 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 | * Finish initialising OCEOS and setting up the fixed data | ||
Line 551: | Line 2,059: | ||
status = oceos_init_finish(); | status = oceos_init_finish(); | ||
if(SUCCESSFUL != status){ | if(SUCCESSFUL != status){ | ||
printf("\nAbandoning, problem ending OCEOS initialisation, resulting return code: %u\n", status); | |||
return -1; | |||
} // if | } // 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 | |||
status = oceos_start(fixed_data, | |||
return status; | |||
} // 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 | 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> | </syntaxhighlight> |
Latest revision as of 17:38, 7 March 2022
Tutorials
Introduction
This section presents some typical real-time tasks and how they can be addressed using OCEOS.
Getting started
Section 9.5 provides guidance on how to structure an OCEOS application. The file asw.c provided with OCEOS is a simple example.
The directives to initialise and start OCEOS are:
- application_init – Initialise fixed data and start system timer(s)
- oceos_task_create - Create task setting priority, no of jobs, ..etc.
- oceos_init_finish – Initilise dynamic data area
- oceos_start – Start the scheduler and pass control to first task
After steps 1 to 4 above tasks implement application functionality. If mutexes, semaphores, or dataqs are required they are also created at step 2.
Note: it is mandatory to create the number of mutexes, semaphores, and dataqs declared otherwise oceos_init_finish() will return an error.
Tutorials
Tutorial 1 – Starting tasks
This exercise demonstrates starting tasks with different priorities.
- Two tasks, one higher priority (i.e. lower priority value), one lower priority (i.e. higher priority value. Each task allowed to have up to two concurrent jobs.
- Each task outputs a message when it starts, another message when it exits.
- Start OCEOS with the low priority task.
- This starts the high priority task and then exits.
- The high priority task starts the low priority tasks and exits.
For code example see below.
tut.h
1 /*
2 *********************************************************************************************************
3 * OCEOS
4 * Real-Time Operating System
5 * for
6 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 * ARM Microcontroller
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 dataq with timed action.
- 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 }