Difference between revisions of "OCEOS Tutorials"
| Line 576: | Line 576: | ||
<syntaxhighlight lang=" | <syntaxhighlight lang="C" line> | ||
void fun1(void * ptr){ | |||
printf ("Task started\n"); | |||
} // fun1() | |||
</syntaxhighlight> | </syntaxhighlight> | ||
[[Category:backup]] | [[Category:backup]] | ||
Revision as of 18:15, 30 September 2021
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.
/*
*********************************************************************************************************
* OCEOS
* Real-Time Operating System
* for
* GR716 Microcontroller
*
* User Manual Section 11 Example
*
* (c) Copyright 2020, O.C.E. Technology
* All Rights Reserved
*
* File : tut1.c
********************************************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include "tut1.h" // application header
/* N.B. Application header is included first */
#include "oceos_config.h" // OCEOS header for this application
/*
* Application specific
*
*/
extern U32_t fixed_data[]; // will be in data segment. Should this be in oceos.h
int main(void) {
int status;
/*
* Initialise the application configuration and OCEOS
*
* This application function creates the application configuration
* and passes it to oceos_init(), which initialises the fixed data
* and enables the system log
*/
if ( !application_init()) {
//LOG
return -1;
}
// Create Main task to
if ( oceos_task_create(
t_0, // taskID, used as index, must be in range 0 to 254
100, // priority, must be in range 1 to 254, lower value is higher priority
100, // threshold, must be in range 1 to task priority
2, // jobs_max, must be in range 1 to 15
0, // FALSE -> floating point hardware not used by task
1, // FALSE -> task initially not enabled
fun0, // main body of task
nullFun, // task end function
0, // time_deadline, must finish no later than this after start, 0 => ignore
0 // minimum time expected between start requests, 0 => no restriction
) != SUCCESSFUL )
return 1;
if ( oceos_task_create(t_1, 200, 200, 2, 0, 1, fun1, nullFun, 0, 0)!= SUCCESSFUL )
return 2;
/*
* Finish initialising OCEOS and setting up the fixed data
*/
status = oceos_init_finish();
if(SUCCESSFUL != status){
return 3;
} // if
/*
* Start OCEOS scheduling
*
* The OCEOS fixed data provides all the information required.
*
* If a valid task is specified, it is started and passed the pointer.
* Otherwise the system is put in sleep mode
*/
status = oceos_start(fixed_data, t_1, (void *)nullPtr); // Start OCEOS with lower prioroty task
return status;
} // main
/*
* Application code functions, functions declared in asw.h
*/
void fun0(void * ptr){
printf ("Entered high priority task\n");
oceos_task_start(t_1,ptr);
printf ("Leaving high priority task\n");
return;
} // fun0()
void fun1(void * ptr){
printf ("Entered low priority task\n");
oceos_task_start(t_0,ptr);
printf ("Leaving low priority task\n");
return;
} // fun1()
</<nowiki>
=== 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:
<nowiki>
/*
*********************************************************************************************************
* OCEOS
* Real-Time Operating System
* for
* GR716 Microcontroller
*
* User Manual Section 11 Example 2
*
* (c) Copyright 2020, O.C.E. Technology
* All Rights Reserved
*
* File : tut2.c
********************************************************************************************************
*/
#include "tut2.h" // application header
#include <stdio.h>
#include <stdlib.h>
/* N.B. Application header is included first */
#include "oceos_config.h" // OCEOS header for this application
/*
* Application specific
*
*/
extern U32_t fixed_data[]; // will be in data segment. Should this be in oceos.h
int main(void) {
int status;
/*
* Initialise the application configuration and OCEOS
*
* This application function creates the application configuration
* and passes it to oceos_init(), which initialises the fixed data
* and enables the system log
*/
if ( !application_init()) {
//LOG
return -1;
}
// Create Main task to
if ( oceos_task_create(
t_0, // taskID, used as index, must be in range 0 to 254
100, // priority, must be in range 1 to 254, lower value is higher priority
100, // threshold, must be in range 1 to task priority
2, // jobs_max, must be in range 1 to 15
0, // FALSE -> floating point hardware not used by task
1, // FALSE -> task initially not enabled
fun0, // main body of task
nullFun, // task end function
0, // time_deadline, must finish no later than this after start, 0 => ignore
0 // minimum time expected between start requests, 0 => no restriction
) != SUCCESSFUL )
return 1;
if ( oceos_task_create(t_1, 200, 200, 2, 0, 1, fun1, nullFun, 0, 0)!= SUCCESSFUL )
return 2;
if ( oceos_mutex_create(m_0, 100)!= SUCCESSFUL ) // Create mutex with ceiling of highest priority task using it
return 3;
/*
* Finish initialising OCEOS and setting up the fixed data
*/
status = oceos_init_finish();
if(SUCCESSFUL != status){
return 4;
} // if
/*
* Start OCEOS scheduling
*
* The OCEOS fixed data provides all the information required.
*
* If a valid task is specified, it is started and passed the pointer.
* Otherwise the system is put in sleep mode
*/
status = oceos_start(fixed_data, t_1, (void *)nullPtr); // Start OCEOS with lower prioroty task
return status;
} // main
/*
* Application code functions, functions declared in asw.h
*/
void fun0(void * ptr){
if (oceos_mutex_wait(m_0) != SUCCESSFUL) {
printf ("Error from high priority task getting mutex\n");
} else {
printf ("high priority task got mutex\n");
}
oceos_task_start(t_1,ptr); // Start lower priority task
if (oceos_mutex_signal(m_0) != SUCCESSFUL) {
printf ("Error from high priority task releasing mutex\n");
} else {
printf ("High priority task released mutex\n");
}
return;
} // fun0()
void fun1(void * ptr){
if (oceos_mutex_wait(m_0) != SUCCESSFUL) {
printf ("Error from low priority task getting mutex\n");
} else {
printf ("Low priority task got mutex\n");
}
oceos_task_start(t_0,ptr); // Start higher priority task
if (oceos_mutex_signal(m_0) != SUCCESSFUL) {
printf ("Error from low priority task releasing mutex\n");
} else {
printf ("Low priority task released mutex\n");
}
return;
} // fun1()
Tutorial 3 – Using Semaphores
Semaphores can be used to synchronise task actions as in this exercise.
- 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:
/*
*********************************************************************************************************
* OCEOS
* Real-Time Operating System
* for
* GR716 Microcontroller
*
* User Manual Section 11 Example 3
*
* (c) Copyright 2020, O.C.E. Technology
* All Rights Reserved
*
* File : tut3.c
********************************************************************************************************
*/
#include "tut3.h" // application header
#include <stdio.h>
#include <stdlib.h>
/* N.B. Application header is included first */
#include "oceos_config.h" // OCEOS header for this application
/*
* Application specific
*
*/
extern U32_t fixed_data[]; // will be in data segment. Should this be in oceos.h
int main(void) {
int status;
/*
* Initialise the application configuration and OCEOS
*
* This application function creates the application configuration
* and passes it to oceos_init(), which initialises the fixed data
* and enables the system log
*/
if ( !application_init()) {
//LOG
return -1;
}
// Create Main task to
if ( oceos_task_create(
t_0, // taskID, used as index, must be in range 0 to 254
10, // priority, must be in range 1 to 254, lower value is higher priority
10, // threshold, must be in range 1 to task priority
1, // jobs_max, must be in range 1 to 15
0, // FALSE -> floating point hardware not used by task
1, // FALSE -> task initially not enabled
fun0, // main body of task
nullFun, // task end function
0, // time_deadline, must finish no later than this after start, 0 => ignore
0 // minimum time expected between start requests, 0 => no restriction
) != SUCCESSFUL )
return 1;
if ( oceos_task_create(t_1, 100, 100, 1, 0, 1, fun1, nullFun, 0, 0)!= SUCCESSFUL )
return 2;
if ( oceos_task_create(t_2, 100, 100, 1, 0, 1, fun2, nullFun, 0, 0)!= SUCCESSFUL )
return 3;
if ( oceos_sem_create(items, 10, 0, 2, TRUE) != SUCCESSFUL ) // items semaphore with max permits of 10, initial permits of 0, max jobs 2
return 4;
if ( oceos_sem_create(spaces, 10, 4, 2, TRUE) != SUCCESSFUL ) // spaces semaphore with max permits of 10, initial permits of 4, max jobs 2
return 4;
/*
* Finish initialising OCEOS and setting up the fixed data
*/
status = oceos_init_finish();
if(SUCCESSFUL != status){
return 6;
} // if
/*
* Start OCEOS scheduling
*
* The OCEOS fixed data provides all the information required.
*
* If a valid task is specified, it is started and passed the pointer.
* Otherwise the system is put in sleep mode
*/
status = oceos_start(fixed_data, t_0, (void *)nullPtr); // Start OCEOS with task to start other tasks
return status;
} // main
/*
* Application code functions, functions declared in asw.h
*/
void fun0(void * ptr){
oceos_task_start(t_1,ptr); // Start consumer task
oceos_task_start(t_2,ptr); // Start consumer task
} // fun0()
void fun1(void * ptr){
while (1){ // loop forever
if (oceos_sem_wait_restart_timeout(items,0) != SUCCESSFUL) {
printf ("Error from task t_0 task waiting items\n");
}
printf ("Got item\n");
if (oceos_sem_signal(spaces) != SUCCESSFUL) {
printf ("Error from task t_0 signalling spaces\n");
}
}
} // fun0()
void fun2(void * ptr){
while (1){ // loop forever
if (oceos_sem_wait_restart_timeout(spaces,0) != SUCCESSFUL) {
printf ("Error from task t_1 task waiting spaces\n");
}
if (oceos_sem_signal(items) != SUCCESSFUL) {
printf ("Error from task t_1 signalling items\n");
} else {
printf ("Item done\n");
}
}
return;
} // fun1()
Tutorial 4 – Timer interrupt starts task
This exercise introduces the use of timer interrupts.
- 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:
/*
*********************************************************************************************************
* OCEOS
* Real-Time Operating System
* for
* GR716 Microcontroller
*
* User Manual Section 11 Example 4
*
* (c) Copyright 2020, O.C.E. Technology
* All Rights Reserved
*
* File : tut4.c
********************************************************************************************************
*/
#include "tut4.h" // application header
#include <stdio.h>
#include <stdlib.h>
/* N.B. Application header is included first */
#include "oceos_config.h" // OCEOS header for this application
#include <bcc/regs/gptimer.h>
#include "oceos_interrupt.h"
/*
* Application specific
*
*/
extern U32_t fixed_data[]; // will be in data segment. Should this be in oceos.h
struct gptimer_regs *timer_regs = (void *)OCEOS_TA_TIMER_ADDRESS;
struct gptimer_timer_regs *task_timer;
struct bcc_isr_node node;
int main(void) {
int status;
/*
* Initialise the application configuration and OCEOS
*
* This application function creates the application configuration
* and passes it to oceos_init(), which initialises the fixed data
* and enables the system log
*/
if ( !application_init()) {
//LOG
return -1;
}
// Create Main task to
if ( oceos_task_create(
t_0, // taskID, used as index, must be in range 0 to 254
10, // priority, must be in range 1 to 254, lower value is higher priority
10, // threshold, must be in range 1 to task priority
1, // jobs_max, must be in range 1 to 15
0, // FALSE -> floating point hardware not used by task
1, // FALSE -> task initially not enabled
fun0, // main body of task
nullFun, // task end function
0, // time_deadline, must finish no later than this after start, 0 => ignore
0 // minimum time expected between start requests, 0 => no restriction
) != SUCCESSFUL )
return 1;
if ( oceos_task_create(t_1, 100, 100, 1, 0, 1, fun1, nullFun, 0, 0)!= SUCCESSFUL )
return 2;
/*
* Finish initialising OCEOS and setting up the fixed data
*/
status = oceos_init_finish();
if(SUCCESSFUL != status){
return 3;
} // if
/*
* Start OCEOS scheduling
*
* The OCEOS fixed data provides all the information required.
*
* If a valid task is specified, it is started and passed the pointer.
* Otherwise the system is put in sleep mode
*/
status = oceos_start(fixed_data, t_0, (void *)nullPtr); // Start OCEOS
return status;
} // main
/*
* Application code functions, functions declared in asw.h
*/
void fun0(void * ptr){
//set up timer and add handle
task_timer = &timer_regs->timer[3];
task_timer->ctrl = 0x0;
enum DIRECTIVE_STATUS ret = 0;
#ifdef TARGET_PM
node.source = 9;
#endif
#ifdef TARGET_GR716
node.source = 12;
#endif
node.handler = start_task;
node.arg = ptr;
ret = oceos_interrupt_handle_register(&node);
if (SUCCESSFUL != ret) {
printf("ERROR :: Failed to add ISR handler\n");
}
#ifdef TARGET_PM
bcc_int_unmask(9);
#endif
#ifdef TARGET_GR716
bcc_int_unmask(12);
#endif
task_timer->reload = 0x2DC6C0; // 3 seconds
task_timer->counter = 0x2DC6C0; // 3 seconds
task_timer->ctrl = GPTIMER_CTRL_EN | GPTIMER_CTRL_RS | GPTIMER_CTRL_IE; // 0x1 | (1 << 1) | (1 << 3);
// The interrupt shoud keep starting t_1 so this task can exit
} // fun0()
/*
* Handler for timer interrupt
*/
void start_task(void *arg, int source){
oceos_task_start(t_1,arg);
}
void fun1(void * ptr){
printf ("Task started\n");
} // fun1()
1 void fun1(void * ptr){
2 printf ("Task started\n");
3 } // fun1()