Difference between revisions of "OCEOS/oceos timed actions"

From wiki
Jump to navigation Jump to search
Line 278: Line 278:


<span style="color:#1b7ac2">'''Description'''</span><br>
<span style="color:#1b7ac2">'''Description'''</span><br>
 
Remove all jobs (requests to start a task) from timed actions queue. These jobs were added by [[OCEOS/oceos kernel/task#oceos_task_timed_start()|oceos_task_timed_start()]] or [[OCEOS/oceos inter-task communication/dataq#oceos_dataq_read_restart_timeout()|oceos_dataq_read_restart_timeout()]] when data is not available (NULL) or [[OCEOS/oceos inter-task communication/semaphore#oceos_sem_wait_restart_timeout()|oceos_sem_wait_restart_timeout()]] when counting semaphore is 0.<br>
<span style="color:#1b7ac2">'''Prototype'''</span><br>
<span style="color:#1b7ac2">'''Prototype'''</span><br>
<syntaxhighlight lang="C">
<syntaxhighlight lang="C">
 
enum DIRECTIVE_STATUS  oceos_timed_jobs_reset(void);
</syntaxhighlight>
</syntaxhighlight>
<span style="color:#1b7ac2">'''Parameters'''</span><br>
<span style="color:#1b7ac2">'''Parameters'''</span><br>
Line 296: Line 296:
! enum DIRECTIVE_STATUS !! Description
! enum DIRECTIVE_STATUS !! Description
|-
|-
| INCORRECT_STATE || If system Meta pointer is NULL or
|NOT_CONFIGURED  || Timed actions manager is not initialized
                    Init pointer is NULL or
                    Start up phase check fail or
                    Fixed data checksum failed (check log)
|-
|-
| INVALID_NAME    || If Start Sentinel for fixed area is corrupt or
|UNSATISFIED    || Failed to stop timer
                    Start Sentinel for dynamic area is corrupt
|-
|-
| INVALID_NUMBER  || If Configuration and actual parameters do not match
|INCORRECT_STATE || Timed queue is empty
                    (In configuration file was defined 5 tasks, but created less)
|-
|-
| SUCCESSFUL     || If All OK
|SUCCESSFUL     || All OK
|}
|}
<span style="color:#1b7ac2">'''Example Usage'''</span><br>
<span style="color:#1b7ac2">'''Example Usage'''</span><br>
<syntaxhighlight lang="C">
<syntaxhighlight lang="C">
      
enum DIRECTIVE_STATUS status;
</syntaxhighlight>
status = oceos_timed_jobs_reset();
if (SUCCESSFUL != status) {
  // Handle ERROR
}      
</syntaxhighlight>
</blockquote>
</blockquote>
===<span style="color:#0000ff">oceos_timed_output_add()</span>===
===<span style="color:#0000ff">oceos_timed_output_add()</span>===
<blockquote style="border-left-style: none;">
<blockquote style="border-left-style: none;">

Revision as of 11:44, 25 March 2022

Timed Actions (Software Timers)

Timed Actions Introduction

Timed actions (Software timers) provide directives to perform actions at a precise time in the future. The currently supported action types are:

The action types implemented in OCEOS are listed in the enumerated type below. The action types required by the user for oceos_timed_output_add() are WRITE_ACTION and RMW_ACTION. Other action types are provided for information only and are not available to the user.

 enum ACTION_TYPE {
  INVALID_ACION,
  START_JOB_ACTION,         // The job was created with start in future. Put job on ready Q
  DATA_Q_WAIT_ACTION,       // The job is on data_Q pending Q with timeout
  SEM_Q_WAIT_ACTION,        // The job is on semaphore_Q pending Q with timeout
  WRITE_ACTION,             // Write value to address
  RMW_ACTION,               // Read-modify-write Action
 };

OCEOS uses the timed actions system to allow output of a value to an address be scheduled to occur independently of scheduling at a precise system time in microseconds.
Each output action involves (output address, value, type, mask, forward tolerance, backward tolerance, time).
When the timed action interrupt occurs this output and any other actions whose forward timing tolerances include the current time are performed. The backward tolerance allows the output be performed if the current time is later than the requested time by no more than this amount. If set to zero late outputs are not performed. Provision is made for error reporting if the current time is greater than the requested time by more than the allowed tolerance.

The output type and mask allow read-modify-write operations and single bit modifications.

Note

Timed outputs use the timed action subsystem which requires the user to provide some hardware specific timer initialization and handling.

All timed actions are put on timed action queue. This is a priority queue of pending actions and their associated times, with queue priority based on these times. It is linked to a high priority hardware timer which is set to interrupt at the time of the first action on the priority queue. When this interrupt occurs, actions on the queue within a timing tolerance of the current time are carried out and the timer is reset to interrupt at the start time of the earliest remaining action.

If the action is a task start request then at the set time the associated job is transferred to the ready queue, its origin set to timeout, and it is also removed from the pending list of any counting semaphore or data queue on which it is present. If the job is now the highest priority job on the ready queue it is started immediately, otherwise it must wait until that is the case.

If the action is a data output then at the set time it is performed immediately.

Timed Actions Configuration

In order to activate timed actions user must define NUMBER_OF_ACTION_ENTRIES or create data queue oceos_dataq_create() or counting semaphore oceos_sem_create() where use_timeout parameter is set to TRUE. If NUMBER_OF_ACTION_ENTRIES is zero, timed actions are not used, unless data queues and semaphores are not used with timeout. The example can be found in OCEOS demo projects.
NUMBER_OF_ACTION_ENTRIES defines how many timed outputs and jobs waiting to be started can be on timed actions queue at the same time. Timed outputs can be created by oceos_timed_output_add() and timed jobs start with oceos_task_timed_start().
The MAX value of NUMBER_OF_ACTION_ENTRIES can be 255. It means that timed action queue is limited to 255 entries.

Note

Timed action queue is shared between all timed actions (timed outputs, timed jobs, data queue and semaphore with timeouts).

If user is using data queues and counting semaphores with timeouts, OCEOS updates the number of entries in timed action queue by number of allowed pending jobs for that data queue or counting semaphore.

As described above, timed action queue can accommodate only 255 entries. User by defining NUMBER_OF_ACTION_ENTRIES should take in consideration how many pending jobs for data queue or counting semaphore that is using timeouts.
If application requires to use 10 timed outputs and to start 12 tasks in future NUMBER_OF_ACTION_ENTRIES must be defined to 22 and size of timed action queue is 22 entries. But if it needs to use one data queue oceos_read_restart_timeout() and one counting semaphore oceos_sem_wait_restart_timeout() with timeouts and when data queue is created with oceos_dataq_create() with pen_q_size = 5, and when counting semaphore is created with oceos_sem_create() with pending_q_size = 6, timed action queue is 22+5+6=33 =< 255.

    #define NUMBER_OF_ACTION_ENTRIES  2
    /*
     * Create the application configuration structure
     */
    struct application_configuration           app_config = {0};
   app_config.timed_actions_queue_size      = NUMBER_OF_ACTION_ENTRIES;

SPARC

SPARC Timed Actions Configuration

As described above, timed action functionality requires dedicated timer unit, that user has to provide. User must fill configuration struct, pointer to which is used by OCEOS. The example can be found in OCEOS demo projects.
User must provide start address of timer unit OCEOS_TA_TIMER_ADDRESS.
User must provide index of a timer in timer unit OCEOS_TA_TIMER_INDEX. OCEOS checks if this index is not used by system time already, if the same timer unit is selected SPARC System Time Configurations.
User must provide timer interrupt number OCEOS_TA_INTERRUPT_NUMBER for selected timer.
OCEOS sets __oceos_timed_action_do to handle timer interrupt. This is internal OCEOS function which defined in header file timed_action.h and must be present as shown below.
OCEOS initializes the timer and starts when it is required.

   #define OCEOS_TA_TIMER_ADDRESS                  0x80003000  // GPTIMER 0 (GR716)
   #define OCEOS_TA_TIMER_INDEX                    6           // Must be a timer with highest priority(GR716)
   #define OCEOS_TA_INTERRUPT_NUMBER               14          // Interrupt number for timed action timer(GR716)
   ...
   OCEOS_TA_TIMER_CONF oceos_ta_timer_config = {
  .oceos_ta_timer_device_address    = OCEOS_TA_TIMER_ADDRESS,    // Timer Module Start address SPARC
  .oceos_ta_timer_index             = OCEOS_TA_TIMER_INDEX,      // Timer Index within timer module [1...n] 
  .oceos_ta_timer_interrupt_number  = OCEOS_TA_INTERRUPT_NUMBER, // Timer Interrupt number used to enable interrupt in Interrupt Controller 
  .oceos_ta_isr_handler             = &__oceos_timed_action_do,  // DO NOT CHANGE. Must be __oceos_timed_action_do;
};
OCEOS_TA_TIMER_CONF *oceos_ta_timer_configurations = &oceos_ta_timer_config;

ARM

ARM Timed Actions Configuration

As described above, timed action functionality requires dedicated timer unit, that user has to provide.
ARM has many different timer implementations. It would be impossible for OCEOS to accommodate all different timer variations to be initialized, started and stopped.

OCEOS provides weak function oceos_external_timer_init() for timer initialization that called from OCEOS and must be implemented by user.

#define EXTERNAL_TIMER_COUNER_MSK  0xFFFF    // Timer implementation dependent  
extern const unsigned int __oceos_bsp_sysfreq;
/**
 * Used in OCEOS internally, max counter value in microseconds
 */
extern unsigned int OCEOS_MAX_TIMER_COUNTER_VALUE;
volatile float base_scaler = 0.0f;

enum DIRECTIVE_STATUS oceos_external_timer_init() {
 ... User code
 // Used in OCEOS internally
 //TC_CMR_TCCLKS_TIMER_CLOCK1 => MCK / 8
 base_scaler        = (float)(__oceos_bsp_sysfreq / 8.0f) / 1000000.0f;
 OCEOS_MAX_TIMER_COUNTER_VALUE = EXTERNAL_TIMER_COUNER_MSK / base_scaler;
 return SUCCESSFUL;
}

This function is called by OCEOS during timed action's initialization. The example of timer initialization code for ARM Cortex-M7 SAMV71Q21 is oceos_port_external_timer.c.

OCEOS_MAX_TIMER_COUNTER_VALUE is used internally by OCEOS and must be implemented.

OCEOS provides weak function oceos_external_timer_start(U32_t act_time) for timer start that called from OCEOS and must be implemented by user. act_time parameter is in microseconds.

enum DIRECTIVE_STATUS oceos_external_timer_start(U32_t act_time) {
  ... User Code
  return SUCCESSFUL;
}

This function is called by OCEOS when it is required to start a timer. The example of timer start code for ARM Cortex-M7 SAMV71Q21 is oceos_port_external_timer.c.

OCEOS provides weak function oceos_external_timer_stop() for timer stop that called from OCEOS and must be implemented by user.

enum DIRECTIVE_STATUS oceos_external_timer_stop() {
  ... User Code
  return SUCCESSFUL;
}

This function is called by OCEOS when it is required to stop a timer. The example of timer stop code for ARM Cortex-M7 SAMV71Q21 is oceos_port_external_timer.c.

User must add timer IRQ handler to Vector table.

	.extern oceos_SysTick_Handler
	.extern oceos_PendSV_Handler
	.extern oceos_TC0_IRQHandler

	.section .isr_vector
	.align	2
	.globl	__isr_vector
__isr_vector:
    .long	__StackTop           /*0: Top of Stack        */
	.long Reset_Handler          /*1: Reset Handler       */
	.long NMI_Handler            /*2: NMI Handler         */
	.long HardFault_Handler      /*3: Hard Fault Handler  */
	.long MemManage_Handler      /*4: MPU Fault Handler   */
	.long BusFault_Handler       /*5: Bus Fault Handler   */
	.long UsageFault_Handler     /*6: Usage Fault Handler */
	.long 0 /* Reserved */       /*7: Reserved            */
	.long 0 /* Reserved */       /*8: Reserved            */
	.long 0 /* Reserved */       /*9: Reserved            */
	.long 0 /* Reserved */       /*10: Reserved           */
	.long SVC_Handler  	         /*11: SVCall Handler     */
	.long 0 /* Reserved */       /*12: Debug Monitor Handler */
	.long 0 /* Reserved */       /*13: Reserved           */
	.long oceos_PendSV_Handler   /*14: PendSV Handler     */
	.long oceos_SysTick_Handler  /*15: SysTick Handler    */
    ...	
	.long oceos_TC0_IRQHandler   /* 23 Timer/Counter 0 */
	.long TC1_IRQHandler	     /* 24 Timer/Counter 1 */
void oceos_TC0_IRQHandler() {
  // User code to clear timer interrupt Pending bit in registers
  ...
  // Call Timed action. Must not modify below lines
  __oceos_timed_action_do();
}

The example of timer IRQ handler for ARM Cortex-M7 SAMV71Q21 is oceos_port_external_timer.c.

API Functions

API Functions
Directive Description main task IRQ handler
oceos_timed_jobs_number() Get number of Jobs waiting on timed action queue * *
oceos_timed_jobs_remove() Remove job from timed action queue * *
oceos_timed_jobs_reset() Remove all jobs * *
oceos_timed_output_add() Add output action to timed actions queue * *
oceos_timed_output_number() Get number of timed output actions * *
oceos_timed_output_remove() Remove timed output action from timed actions queue * *
oceos_timed_output_reset() Remove all timed output actions * *

oceos_timed_jobs_number()

Header File
timed_action.h

Description
Get number of Jobs (requests to start the task) waiting on timed action queue. These jobs are added by oceos_task_timed_start() or oceos_dataq_read_restart_timeout() when data is not available (NULL) or oceos_sem_wait_restart_timeout() when counting semaphore is 0.
Prototype

int oceos_timed_jobs_number(void);        // number of jobs on timed actions queue

Parameters

Parameter Description

Returns
This function returns int.

int Description
-1 Timed actions manager is not initialized
>= 0 Number of jobs on timed action queue

Example Usage

int count;
count = oceos_timed_jobs_number();
if (-1 == count) {
  // Handle ERROR
}

oceos_timed_jobs_remove()

Header File
timed_action.h

Description
Remove job from timed action queue when task started using oceos_task_timed_start(), this directive requires pointer to store ID of job that put on the timed action queue. This job can be removed later using this directive and stored job ID.
Prototype

enum DIRECTIVE_STATUS   oceos_timed_jobs_remove(
    U32_t job_id                             // Job ID
);

Parameters

Parameter Description
job_id Job ID

Returns
This function returns enum DIRECTIVE_STATUS.

enum DIRECTIVE_STATUS Description
NOT_CONFIGURED Timed actions manager is not initialized
INVALID_ID Job ID is not valid
UNSATISFIED Failed to stop timer
INTERNAL_ERROR Failed to restart timed actions
SUCCESSFUL All OK

Example Usage

enum DIRECTIVE_STATUS status;
status = oceos_timed_jobs_remove(12);
if (SUCCESSFUL != status) {
  // Handle ERROR
}

oceos_timed_jobs_reset()

Header File
timed_action.h

Description
Remove all jobs (requests to start a task) from timed actions queue. These jobs were added by oceos_task_timed_start() or oceos_dataq_read_restart_timeout() when data is not available (NULL) or oceos_sem_wait_restart_timeout() when counting semaphore is 0.
Prototype

enum DIRECTIVE_STATUS   oceos_timed_jobs_reset(void);

Parameters

Parameter Description

Returns
This function returns enum DIRECTIVE_STATUS.

enum DIRECTIVE_STATUS Description
NOT_CONFIGURED Timed actions manager is not initialized
UNSATISFIED Failed to stop timer
INCORRECT_STATE Timed queue is empty
SUCCESSFUL All OK

Example Usage

enum DIRECTIVE_STATUS status;
status = oceos_timed_jobs_reset();
if (SUCCESSFUL != status) {
  // Handle ERROR
}

oceos_timed_output_add()

Header File
timed_action.h

Description

Prototype

Parameters

Parameter Description

Returns
This function returns enum DIRECTIVE_STATUS.

enum DIRECTIVE_STATUS Description
INCORRECT_STATE If system Meta pointer is NULL or

Init pointer is NULL or Start up phase check fail or Fixed data checksum failed (check log)

INVALID_NAME If Start Sentinel for fixed area is corrupt or

Start Sentinel for dynamic area is corrupt

INVALID_NUMBER If Configuration and actual parameters do not match

(In configuration file was defined 5 tasks, but created less)

SUCCESSFUL If All OK

Example Usage

oceos_timed_output_number()

Header File
timed_action.h

Description

Prototype

Parameters

Parameter Description

Returns
This function returns enum DIRECTIVE_STATUS.

enum DIRECTIVE_STATUS Description
INCORRECT_STATE If system Meta pointer is NULL or

Init pointer is NULL or Start up phase check fail or Fixed data checksum failed (check log)

INVALID_NAME If Start Sentinel for fixed area is corrupt or

Start Sentinel for dynamic area is corrupt

INVALID_NUMBER If Configuration and actual parameters do not match

(In configuration file was defined 5 tasks, but created less)

SUCCESSFUL If All OK

Example Usage

oceos_timed_output_remove()

Header File
timed_action.h

Description

Prototype

Parameters

Parameter Description

Returns
This function returns enum DIRECTIVE_STATUS.

enum DIRECTIVE_STATUS Description
INCORRECT_STATE If system Meta pointer is NULL or

Init pointer is NULL or Start up phase check fail or Fixed data checksum failed (check log)

INVALID_NAME If Start Sentinel for fixed area is corrupt or

Start Sentinel for dynamic area is corrupt

INVALID_NUMBER If Configuration and actual parameters do not match

(In configuration file was defined 5 tasks, but created less)

SUCCESSFUL If All OK

Example Usage

oceos_timed_output_reset()

Header File
timed_action.h

Description

Prototype

Parameters

Parameter Description

Returns
This function returns enum DIRECTIVE_STATUS.

enum DIRECTIVE_STATUS Description
INCORRECT_STATE If system Meta pointer is NULL or

Init pointer is NULL or Start up phase check fail or Fixed data checksum failed (check log)

INVALID_NAME If Start Sentinel for fixed area is corrupt or

Start Sentinel for dynamic area is corrupt

INVALID_NUMBER If Configuration and actual parameters do not match

(In configuration file was defined 5 tasks, but created less)

SUCCESSFUL If All OK

Example Usage