Difference between revisions of "OCEOS Tutorials"
Dtimofejevs (talk | contribs) |
Dtimofejevs (talk | contribs) Tag: Reverted |
||
Line 806: | Line 806: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<syntaxhighlight lang="C" line> | |||
/** | |||
* User has to implement this function to initialize external timer | |||
* to be used with timed actions,semaphores and data qs. | |||
*/ | |||
enum DIRECTIVE_STATUS oceos_external_timer_init() { | |||
// Remove write protect from PMC | |||
U32_t pmc_was_enabled = 0U; | |||
if (0 != (PMC->PMC_WPMR & PMC_WPMR_WPEN)) { | |||
PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD; | |||
pmc_was_enabled = 1U; | |||
} | |||
// Enable Clock | |||
PMC->PMC_PCER0 |= PMC_PCER0_PID23; | |||
// Enable write protect | |||
if (1U == pmc_was_enabled) { | |||
PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD | PMC_WPMR_WPEN; | |||
} | |||
timer_regs = (Tc *)TC0; | |||
tc = &(timer_regs->TC_CHANNEL[EXTERNAL_TIMER_INDEX]); | |||
// Remove Timer Unit protection | |||
U32_t tc_was_protected = 0U; | |||
if (0U != (timer_regs->TC_WPMR & TC_WPMR_WPEN)) { | |||
timer_regs->TC_WPMR = TC_WPMR_WPKEY_PASSWD; | |||
tc_was_protected = 1U; | |||
} | |||
// 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_CLOCK2_Val); // MCK/8 | |||
// Set Block Clock | |||
timer_regs->TC_BMR &= (U32_t)(~(1 << EXTERNAL_TIMER_INDEX)); | |||
// Enable Timer interrupt (RC Compare) | |||
tc->TC_IER = TC_IER_CPCS; | |||
// Enable Timer Interrupt in NVIC | |||
NVIC_EnableIRQ(TC0_IRQn); | |||
// Set Priority for interrupt number, should not be zero as this is the highest priority | |||
// and used by SysTick to update time counter | |||
NVIC_SetPriority(TC0_IRQn, EXTERNAL_TIMER_PRIORITY); | |||
//TC_CMR_TCCLKS_TIMER_CLOCK1 => MCK / 8 | |||
base_scaler = (float)(__oceos_bsp_sysfreq / 8.0f) / 1000000.0f; | |||
// Calculate max reload time in ns | |||
// Used in OCEOS internally | |||
OCEOS_MAX_TIMER_COUNTER_VALUE = EXTERNAL_TIMER_COUNER_MSK / base_scaler; | |||
// Enable clock | |||
tc->TC_CCR = TC_CCR_CLKEN; | |||
// Re-enable Timer Protection if was protected | |||
if (1U == tc_was_protected) { | |||
timer_regs->TC_WPMR = TC_WPMR_WPKEY_PASSWD | TC_WPMR_WPEN; | |||
} | |||
return SUCCESSFUL; | |||
} | |||
/** | |||
* User has to implement this function to start external timer | |||
* to be used with timed actions,semaphores and data qs. | |||
*/ | |||
enum DIRECTIVE_STATUS oceos_external_timer_start(U32_t act_time) { | |||
if (NULL == timer_regs || NULL == tc) { | |||
oceos_log_add_entry(LOG_TIMED_ACTION_NOT_INIT, 0x1); | |||
return NOT_CONFIGURED; | |||
} | |||
// Remove protection | |||
U32_t tc_was_protected = 0U; | |||
if (0 != (timer_regs->TC_WPMR & TC_WPMR_WPEN)) { | |||
timer_regs->TC_WPMR = TC_WPMR_WPKEY_PASSWD; | |||
tc_was_protected = 1U; | |||
} | |||
// Set Register C for compare | |||
tc->TC_RC = base_scaler * act_time; | |||
// Enable Protection | |||
if (1U == tc_was_protected) { | |||
timer_regs->TC_WPMR = TC_WPMR_WPKEY_PASSWD | TC_WPMR_WPEN; | |||
} | |||
// Enable clock | |||
tc->TC_CCR = TC_CCR_CLKEN; | |||
if (0 == (tc->TC_SR & TC_SR_CLKSTA)) {// check if set | |||
oceos_log_add_entry(LOG_TIMED_ACTION_NOT_INIT, 0x2); | |||
return NOT_CONFIGURED; | |||
} | |||
// Start clock | |||
tc->TC_CCR = TC_CCR_SWTRG; | |||
return SUCCESSFUL; | |||
} | |||
/** | |||
* User has to implement this function to stop external timer | |||
* to be used with timed actions,semaphores and data qs. | |||
*/ | |||
enum DIRECTIVE_STATUS oceos_external_timer_stop() { | |||
if (NULL == tc) { | |||
oceos_log_add_entry(LOG_TIMED_ACTION_NOT_INIT, 0x1); | |||
return NOT_CONFIGURED; | |||
} | |||
tc->TC_CCR = TC_CCR_CLKDIS; | |||
if (0 != (tc->TC_SR & TC_SR_CLKSTA)) { | |||
oceos_log_add_entry(LOG_TIMED_ACTION_TIMER_STOP_FAIL, 0x2); | |||
return FAILED_TO_SET_REGISTER; | |||
} | |||
return SUCCESSFUL; | |||
} | |||
/** | |||
* IRQ handler for timed action timer. | |||
* This function label should be present in Vector table | |||
*/ | |||
void oceos_TC0_IRQHandler() { | |||
// Clear timer interrupt Pending bit in register | |||
tc->TC_SR; | |||
// Call Timed action | |||
__oceos_timed_action_do(); | |||
} | |||
#endif | |||
</syntaxhighlight> | |||
[[Category:backup]] | [[Category:backup]] |
Revision as of 14:48, 1 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.
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:
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:
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:
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:
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 assert(SUCCESSFUL == status);
50 // 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
51 status = oceos_task_create(t_producer, 254, 254, 1, 0, TASK_ENABLED,t_producer_task, NULL, 0, 0);
52 assert(SUCCESSFUL == status);
53
54 printf("\n Tasks created\n");
55 // no counting semaphores, data queues or user defined traps
56
57 if(SUCCESSFUL != status){
58 // LOG
59 printf("\nAbandoning, problem creating task, resulting return code: %u\n", status);
60 return -1;
61 } // if
62 // Creating Data 0, dataq_size 1, pen_q size 1, roll_over FALSE, use_timeout TRUE
63 status = oceos_dataq_create(queue_0, N0, JOBS0, FALSE, TRUE);
64 assert(SUCCESSFUL == status);
65 // Creating Data 1, dataq_size 1, pen_q size 1, roll_over FALSE, use_timeout TRUE
66 status = oceos_dataq_create(queue_1, N1, JOBS1, FALSE, TRUE);
67 assert(SUCCESSFUL == status);
68 /*
69 * Finish initialising OCEOS and setting up the fixed data
70 */
71 status = oceos_init_finish();
72 assert(SUCCESSFUL == status);
73 if(SUCCESSFUL != status){
74 // LOG
75 printf("\nAbandoning, problem ending OCEOS initialisation, resulting return code: %u\n", status);
76 return -1;
77 } // if
78 //1) Action: Start OCEOS with Task 1 as initial task, null input pointer
79 status = oceos_start(fixed_data, t_producer, NULL);
80
81 return status; // returned as an integer
82
83 } // function waits for specific time interval
84 void test_wait(U32_t interval) {
85 volatile U32_t start_time = oceos_time_sys_get32();
86 volatile U32_t cur_time = 0;
87 while(1) {
88 cur_time = oceos_time_sys_get32();
89 if ((cur_time - start_time) >= interval ) {
90 break;
91 }
92 }
93 }
94 /*
95 * Tasks
96 */
97 void t_consumer_task() {
98 static int case_number = 0;
99 if (case_number == 0) {
100 case_number++;
101 // 2) Action: Task 1 attempts to start Task 0
102 // Check: Task 0 has started, pre-empting Task 1
103 // a. Check: entry message from Task 0
104 // b. Check: queue_0 entries is 0
105 // c. Check: queue_1 entries is 0
106 printf("t_consumer was started\n");
107 assert(0 == oceos_dataq_get_size(queue_0));
108 assert(0 == oceos_dataq_get_size(queue_1));
109
110 // 3) Action: Task 0 does read_restart on queue_0
111 oceos_dataq_read_restart_timeout(queue_0, 0);
112 } else if (case_number == 1){
113 case_number++;
114 // 5) Action: Task 1 writes pointer to struct to queue_0
115 // Check: Task 0 has started, pre-empting Task 1
116 // a. Check: entry message from Task 0
117 // b. Check: queue_0 entries count is 1
118 // c. Check: queue_1 entries count is 0
119 printf("t_consumer was started\n");
120 assert(1 == oceos_dataq_get_size(queue_0));
121 assert(0 == oceos_dataq_get_size(queue_1));
122
123 // 6) Action: Task 0 does read_restart on queue 0
124 // Check: Task 0 has succeeded
125 // a. Check: non-null pointer returned
126 // b. Check: queue_0 entries count is 0
127 // c. Check: queue_0 entries count is 0
128 assert(NULL != oceos_dataq_read_restart_timeout(queue_0, 0));
129 assert(0 == oceos_dataq_get_size(queue_0));
130 assert(0 == oceos_dataq_get_size(queue_1));
131
132 // 7) Action: Task 0 writes this pointer to queue_1
133 // Check: Task 0 has succeeded
134 // a. Check: queue_0 entries count is 0
135 // b. Check: queue_1 entries count is 1
136 assert(SUCCESSFUL == oceos_dataq_write(queue_1, &test_data));
137 assert(0 == oceos_dataq_get_size(queue_0));
138 assert(1 == oceos_dataq_get_size(queue_1));
139
140 // 8) Action: Task 0 does read_restart with timeout on queue_0
141 // Check: Task 0 exits as queues_0 is empty
142 assert(NULL == oceos_dataq_read_restart_timeout(queue_0, TIME_OUT));
143 } else {
144 case_number++;
145 // 10) Action: Task 1 loops for at least twice timeout period T
146 // Check: Task 0 restarts on timeout, pre-empting Task 1
147 // a. Check: entry message from Task 0
148 // b. Check: queue_0 entries count is 0
149 // c. Check: queue_1 entries count is 0
150 printf("t_consumer was started\n");
151 assert(0 == oceos_dataq_get_size(queue_0));
152 assert(0 == oceos_dataq_get_size(queue_1));
153
154 // 11) Action: Task 0 does read_continue on queue_0
155 // Check: Task 0 has succeeded
156 // a. Check: null pointer returned
157 // b. Check: queue_0 entries count is 0
158 // c. Check: queue_1 entries count is 0
159 assert(NULL == oceos_dataq_read_continue(queue_0));
160 assert(0 == oceos_dataq_get_size(queue_0));
161 assert(0 == oceos_dataq_get_size(queue_1));
162
163 // 12) Action: Task 0 exits
164 // Check: Task 0 exit message
165 // a. Check: queue_0 entries count is 0
166 // b. Check: queue_1 entries count is 0
167 printf("t_consumer is exiting\n");
168 assert(0 == oceos_dataq_get_size(queue_0));
169 assert(0 == oceos_dataq_get_size(queue_1));
170 return;
171 }
172 }//END t_consumer_task
173
174 void t_producer_task() {
175 // 1) Action: Start OCEOS with Task 1 as initial task, null input pointer
176 // Check: Task 1 has started
177 // a. Check: Starting message from Task 1
178 // b. Check: queue_0 entries count is 0
179 // c. Check: queue_0 capacity is as created
180 // d. Check: queue_1 entries count is 0
181 // e. Check: queue_1 capacity is as created
182 printf("t_producer was started\n");
183 assert(0 == oceos_dataq_get_size(queue_0));
184 assert(0 == oceos_dataq_get_size(queue_1));
185
186 // 2) Action: Task 1 attempts to start Task 0
187 assert(SUCCESSFUL == oceos_task_start(t_consumer, NULL));
188
189 // 3) Action: Task 0 does read_restart on queue_0
190 // Check: Task 0 exits as queue_0 is empty
191 // Check: Task 1 continues
192 // a. Check: continue message from Task 1
193 // b. Check: queue_0 entries count is 0
194 // c. Check: queue_1 entries count is 0
195 printf("t_producer continues \n");
196 assert(0 == oceos_dataq_get_size(queue_0));
197 assert(0 == oceos_dataq_get_size(queue_1));
198
199 // 4) Action: Task 1 does read_continue on queue_1
200 // Check: null pointer returned
201 assert(NULL == oceos_dataq_read_continue(queue_1));
202
203 // 5) Action: Task 1 writes pointer to struct to queue_0
204 assert(SUCCESSFUL == oceos_dataq_write(queue_0, &test_data));
205
206 // 8) Action: Task 0 does read_restart with timeout on queue_0
207 // Check: Task 0 exits as queues_0 is empty
208 // Check: Task 1 continues
209 // a. Check: continue message from Task 1
210 // b. Check: queue_0 entries count is 0
211 // c. Check: queue_1 entries count is 1
212 printf("t_producer continues \n");
213 assert(0 == oceos_dataq_get_size(queue_0));
214 assert(1 == oceos_dataq_get_size(queue_1));
215
216 // 9) Action: Task 1 does read_continue on queue_1
217 // Check: Non-null pointer returned
218 // a. Check: pointer to same struct
219 // b. Check: queue_0 entries count is 0
220 // c. Check: queue_1 entries count is 0
221 struct data *temp_data = oceos_dataq_read_continue(queue_1);
222 assert(NULL != temp_data);
223 assert(test_data.message == temp_data->message);
224 assert(0 == oceos_dataq_get_size(queue_0));
225 assert(0 == oceos_dataq_get_size(queue_1));
226
227 // 10) Action: Task 1 loops for at least three timeout period
228 // Check: Task 0 restarts on timeout, pre-empting Task 1
229 test_wait(TIME_OUT * 3);
230
231 // 13) Action: Task 1 loop resumes and terminates
232 // Check: Task 1 loop ended message
233 //assert(i == TIME_OUT * 100);
234
235 //Task 1 writes pointer to struct on queue_1
236 assert(SUCCESSFUL == oceos_dataq_write(queue_1, &test_data));
237 // Data q size check
238 assert(1 == oceos_dataq_get_size(queue_1));
239 // Task 1 does read restart on queue_1
240 assert(NULL != oceos_dataq_read_restart(queue_1));
241 // Data q size check
242 assert(0 == oceos_dataq_get_size(queue_1));
243 //Task 1 writes pointer to struct on queue_1
244 assert(SUCCESSFUL == oceos_dataq_write(queue_1, &test_data));
245 // Data q size check
246 assert(1 == oceos_dataq_get_size(queue_1));
247 // Data q clear
248 assert(0 == oceos_dataq_clear(queue_1));
249 // Data q size check
250 assert(0 == oceos_dataq_get_size(queue_1));
251 // Data pending q size check
252 assert(0 == oceos_dataq_penq_get_size(queue_1));
253
254 // 14) Action: Task 1 terminates
255 // Check: Task 1 exit message
256 printf("t_producer is exiting\n");
257
258
259
260 // 15) Action: CPU placed in sleep mode
261 // Check: Sleep mode starting message
262 assert(SUCCESSFUL == oceos_exit());
263 return;
264 }
1 /**
2 * User has to implement this function to initialize external timer
3 * to be used with timed actions,semaphores and data qs.
4 */
5 enum DIRECTIVE_STATUS oceos_external_timer_init() {
6
7 // Remove write protect from PMC
8 U32_t pmc_was_enabled = 0U;
9 if (0 != (PMC->PMC_WPMR & PMC_WPMR_WPEN)) {
10 PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD;
11 pmc_was_enabled = 1U;
12 }
13 // Enable Clock
14 PMC->PMC_PCER0 |= PMC_PCER0_PID23;
15
16 // Enable write protect
17 if (1U == pmc_was_enabled) {
18 PMC->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD | PMC_WPMR_WPEN;
19 }
20
21 timer_regs = (Tc *)TC0;
22 tc = &(timer_regs->TC_CHANNEL[EXTERNAL_TIMER_INDEX]);
23
24 // Remove Timer Unit protection
25 U32_t tc_was_protected = 0U;
26 if (0U != (timer_regs->TC_WPMR & TC_WPMR_WPEN)) {
27 timer_regs->TC_WPMR = TC_WPMR_WPKEY_PASSWD;
28 tc_was_protected = 1U;
29 }
30 // Enable Wave Mode
31 tc->TC_CMR |= ENABLE_WAVE_MODE;
32 // Set WAVESEL to 00
33 tc->TC_CMR &= (U32_t)SET_WAVE_SELECT;
34 // Set TC_CMR_CPCSTOP and Clock input
35 tc->TC_CMR |= (TC_CMR_CPCSTOP | TC_CMR_TCCLKS_TIMER_CLOCK2_Val); // MCK/8
36
37 // Set Block Clock
38 timer_regs->TC_BMR &= (U32_t)(~(1 << EXTERNAL_TIMER_INDEX));
39
40 // Enable Timer interrupt (RC Compare)
41 tc->TC_IER = TC_IER_CPCS;
42
43 // Enable Timer Interrupt in NVIC
44 NVIC_EnableIRQ(TC0_IRQn);
45
46 // Set Priority for interrupt number, should not be zero as this is the highest priority
47 // and used by SysTick to update time counter
48 NVIC_SetPriority(TC0_IRQn, EXTERNAL_TIMER_PRIORITY);
49
50 //TC_CMR_TCCLKS_TIMER_CLOCK1 => MCK / 8
51 base_scaler = (float)(__oceos_bsp_sysfreq / 8.0f) / 1000000.0f;
52
53 // Calculate max reload time in ns
54 // Used in OCEOS internally
55 OCEOS_MAX_TIMER_COUNTER_VALUE = EXTERNAL_TIMER_COUNER_MSK / base_scaler;
56
57 // Enable clock
58 tc->TC_CCR = TC_CCR_CLKEN;
59
60 // Re-enable Timer Protection if was protected
61 if (1U == tc_was_protected) {
62 timer_regs->TC_WPMR = TC_WPMR_WPKEY_PASSWD | TC_WPMR_WPEN;
63 }
64
65 return SUCCESSFUL;
66 }
67 /**
68 * User has to implement this function to start external timer
69 * to be used with timed actions,semaphores and data qs.
70 */
71 enum DIRECTIVE_STATUS oceos_external_timer_start(U32_t act_time) {
72 if (NULL == timer_regs || NULL == tc) {
73 oceos_log_add_entry(LOG_TIMED_ACTION_NOT_INIT, 0x1);
74 return NOT_CONFIGURED;
75 }
76 // Remove protection
77 U32_t tc_was_protected = 0U;
78 if (0 != (timer_regs->TC_WPMR & TC_WPMR_WPEN)) {
79 timer_regs->TC_WPMR = TC_WPMR_WPKEY_PASSWD;
80 tc_was_protected = 1U;
81 }
82 // Set Register C for compare
83 tc->TC_RC = base_scaler * act_time;
84
85 // Enable Protection
86 if (1U == tc_was_protected) {
87 timer_regs->TC_WPMR = TC_WPMR_WPKEY_PASSWD | TC_WPMR_WPEN;
88 }
89
90 // Enable clock
91 tc->TC_CCR = TC_CCR_CLKEN;
92 if (0 == (tc->TC_SR & TC_SR_CLKSTA)) {// check if set
93 oceos_log_add_entry(LOG_TIMED_ACTION_NOT_INIT, 0x2);
94 return NOT_CONFIGURED;
95 }
96 // Start clock
97 tc->TC_CCR = TC_CCR_SWTRG;
98 return SUCCESSFUL;
99 }
100 /**
101 * User has to implement this function to stop external timer
102 * to be used with timed actions,semaphores and data qs.
103 */
104 enum DIRECTIVE_STATUS oceos_external_timer_stop() {
105 if (NULL == tc) {
106 oceos_log_add_entry(LOG_TIMED_ACTION_NOT_INIT, 0x1);
107 return NOT_CONFIGURED;
108 }
109 tc->TC_CCR = TC_CCR_CLKDIS;
110 if (0 != (tc->TC_SR & TC_SR_CLKSTA)) {
111 oceos_log_add_entry(LOG_TIMED_ACTION_TIMER_STOP_FAIL, 0x2);
112 return FAILED_TO_SET_REGISTER;
113 }
114 return SUCCESSFUL;
115 }
116 /**
117 * IRQ handler for timed action timer.
118 * This function label should be present in Vector table
119 */
120 void oceos_TC0_IRQHandler() {
121 // Clear timer interrupt Pending bit in register
122 tc->TC_SR;
123
124 // Call Timed action
125 __oceos_timed_action_do();
126 }
127 #endif