diff options
Diffstat (limited to 'cpukit/libmisc/capture/capture.h')
-rw-r--r-- | cpukit/libmisc/capture/capture.h | 1042 |
1 files changed, 1042 insertions, 0 deletions
diff --git a/cpukit/libmisc/capture/capture.h b/cpukit/libmisc/capture/capture.h new file mode 100644 index 0000000000..48ba5ebec4 --- /dev/null +++ b/cpukit/libmisc/capture/capture.h @@ -0,0 +1,1042 @@ +/** + * @file rtems/capture.h + */ + +/* + ------------------------------------------------------------------------ + $Id$ + ------------------------------------------------------------------------ + + Copyright Objective Design Systems Pty Ltd, 2002 + All rights reserved Objective Design Systems Pty Ltd, 2002 + Chris Johns (ccj@acm.org) + + COPYRIGHT (c) 1989-1998. + On-Line Applications Research Corporation (OAR). + + The license and distribution terms for this file may be + found in the file LICENSE in this distribution. + + This software with is provided ``as is'' and with NO WARRANTY. + + ------------------------------------------------------------------------ + + RTEMS Performance Monitoring and Measurement Framework. + This is the Capture Engine component. + +*/ + +#ifndef __CAPTURE_H_ +#define __CAPTURE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rtems.h> + +/** + * The number of tasks in a trigger group. + */ +#define RTEMS_CAPTURE_TRIGGER_TASKS (32) + +/** + * rtems_capture_from_t + * + * DESCRIPTION: + * + * A from capture is a task id and a mask for the type of + * from trigger we are interested in. The mask uses the same + * bit maps as the flags field in the control structure. There + * will only be a from type trigger if the flags in the control + * structure has the specific *_BY bit set. + */ +typedef struct rtems_capture_from_s +{ + rtems_name name; + rtems_id id; + uint32_t trigger; +} rtems_capture_from_t; + +/** + * rtems_capture_control_t + * + * DESCRIPTION: + * + * RTEMS control holds the trigger and watch configuration for a group of + * tasks with the same name. The flags hold global control flags. + * + * The to_triggers fields holds triggers TO this task. The from_triggers holds + * triggers from this task. The by_triggers is an OR or triggers which are + * caused BY the task listed TO this task. The by_valid flag which entries + * in by are valid. + */ +typedef struct rtems_capture_control_s +{ + rtems_name name; + rtems_id id; + uint32_t flags; + uint32_t to_triggers; + uint32_t from_triggers; + uint32_t by_triggers; + uint32_t by_valid; + rtems_capture_from_t by[RTEMS_CAPTURE_TRIGGER_TASKS]; + struct rtems_capture_control_s* next; +} rtems_capture_control_t; + +/** + * The from_valid mask. + */ +#define RTEMS_CAPTURE_CONTROL_FROM_MASK(_s) \ + (UINT32_C(1) << (RTEMS_CAPTURE_TRIGGER_TASKS - ((_s) + 1))) + +/** + * Control flags. + */ +#define RTEMS_CAPTURE_WATCH (1 << 0) + +/** + * Control triggers. + */ +#define RTEMS_CAPTURE_SWITCH (1 << 0) +#define RTEMS_CAPTURE_CREATE (1 << 1) +#define RTEMS_CAPTURE_START (1 << 2) +#define RTEMS_CAPTURE_RESTART (1 << 3) +#define RTEMS_CAPTURE_DELETE (1 << 4) +#define RTEMS_CAPTURE_BEGIN (1 << 5) +#define RTEMS_CAPTURE_EXITTED (1 << 6) + +#define RTEMS_CAPTURE_FROM_TRIGS (RTEMS_CAPTURE_SWITCH | \ + RTEMS_CAPTURE_CREATE | \ + RTEMS_CAPTURE_START | \ + RTEMS_CAPTURE_RESTART | \ + RTEMS_CAPTURE_DELETE) + +#define RTEMS_CAPTURE_TO_TRIGS (RTEMS_CAPTURE_SWITCH | \ + RTEMS_CAPTURE_CREATE | \ + RTEMS_CAPTURE_START | \ + RTEMS_CAPTURE_RESTART | \ + RTEMS_CAPTURE_DELETE | \ + RTEMS_CAPTURE_BEGIN | \ + RTEMS_CAPTURE_EXITTED) + +/** + * rtems_capture_task_t + * + * DESCRIPTION: + * + * RTEMS capture control provdes the information about a task, along + * with its trigger state. The control is referenced by each + * capture record. This is information neeed by the decoder. The + * capture record cannot assume the task will exist when the record is + * dumped via the target interface so task info needed for tracing is + * copied and held here. Once the references in the trace buffer + * have been removed and the task is deleted this structure is + * released back to the heap. + * + * The inline helper functions provide more details about the info + * contained in this structure. + * + * Note, the tracer code exploits the fact an rtems_name is a + * 32bit value. + */ +typedef struct rtems_capture_task_s +{ + rtems_name name; + rtems_id id; + uint32_t flags; + uint32_t refcount; + rtems_tcb* tcb; + uint32_t in; + uint32_t out; + rtems_task_priority start_priority; + uint32_t stack_size; + uint32_t stack_clean; + uint32_t ticks; + uint32_t tick_offset; + uint32_t ticks_in; + uint32_t tick_offset_in; + uint32_t last_ticks; + uint32_t last_tick_offset; + rtems_capture_control_t* control; + struct rtems_capture_task_s* forw; + struct rtems_capture_task_s* back; +} rtems_capture_task_t; + +/** + * Task flags. + */ +#define RTEMS_CAPTURE_TRACED (1 << 0) + +/* + * rtems_capture_record_t + * + * DESCRIPTION: + * + * RTEMS capture record. This is a record that is written into + * the buffer. The events includes the priority of the task + * at the time of the context switch. + */ +typedef struct rtems_capture_record_s +{ + rtems_capture_task_t* task; + uint32_t events; + uint32_t ticks; + uint32_t tick_offset; +} rtems_capture_record_t; + +/** + * The capture record event flags. + */ +#define RTEMS_CAPTURE_REAL_PRI_EVENT_MASK UINT32_C (0x000000ff) +#define RTEMS_CAPTURE_CURR_PRI_EVENT_MASK UINT32_C (0x0000ff00) +#define RTEMS_CAPTURE_REAL_PRIORITY_EVENT (0) +#define RTEMS_CAPTURE_CURR_PRIORITY_EVENT (8) +#define RTEMS_CAPTURE_EVENT_START (16) +#define RTEMS_CAPTURE_CREATED_BY_EVENT UINT32_C (0x00010000) +#define RTEMS_CAPTURE_CREATED_EVENT UINT32_C (0x00020000) +#define RTEMS_CAPTURE_STARTED_BY_EVENT UINT32_C (0x00040000) +#define RTEMS_CAPTURE_STARTED_EVENT UINT32_C (0x00080000) +#define RTEMS_CAPTURE_RESTARTED_BY_EVENT UINT32_C (0x00100000) +#define RTEMS_CAPTURE_RESTARTED_EVENT UINT32_C (0x00200000) +#define RTEMS_CAPTURE_DELETED_BY_EVENT UINT32_C (0x00400000) +#define RTEMS_CAPTURE_DELETED_EVENT UINT32_C (0x00800000) +#define RTEMS_CAPTURE_BEGIN_EVENT UINT32_C (0x01000000) +#define RTEMS_CAPTURE_EXITTED_EVENT UINT32_C (0x02000000) +#define RTEMS_CAPTURE_SWITCHED_OUT_EVENT UINT32_C (0x04000000) +#define RTEMS_CAPTURE_SWITCHED_IN_EVENT UINT32_C (0x08000000) +#define RTEMS_CAPTURE_TIMESTAMP UINT32_C (0x10000000) +#define RTEMS_CAPTURE_EVENT_END (28) + +/** + * rtems_capture_trigger_mode_t + * + * DESCRIPTION: + * + * The types of trigger modes that exist. + */ +typedef enum rtems_capture_trigger_mode_e +{ + rtems_capture_to_any, + rtems_capture_from_any, + rtems_capture_from_to +} rtems_capture_trigger_mode_t; + +/** + * rtems_capture_trigger_t + * + * DESCRIPTION: + * + * The types of triggers that exist. + */ +typedef enum rtems_capture_trigger_e +{ + rtems_capture_switch, + rtems_capture_create, + rtems_capture_start, + rtems_capture_restart, + rtems_capture_delete, + rtems_capture_begin, + rtems_capture_exitted +} rtems_capture_trigger_t; + +/** + * rtems_capture_timestamp + * + * DESCRIPTION: + * + * This defines the callout handler to obtain a time stamp. The + * value returned is time count since the last read. + * + */ + +typedef void (*rtems_capture_timestamp) + (uint32_t* ticks, uint32_t* micro); + +/** + * rtems_capture_open + * + * DESCRIPTION: + * + * This function initialises the realtime trace manager allocating the + * capture buffer. It is assumed we have a working heap at stage of + * initialisation. + * + */ +rtems_status_code +rtems_capture_open (uint32_t size, + rtems_capture_timestamp timestamp); + +/** + * rtems_capture_close + * + * DESCRIPTION: + * + * This function shutdowns the tracer and release any claimed + * resources. + */ +rtems_status_code +rtems_capture_close (void); + +/** + * rtems_capture_control + * + * DESCRIPTION: + * + * This function allows control of tracing at a global level. + */ +rtems_status_code +rtems_capture_control (bool enable); + +/** + * rtems_capture_monitor + * + * DESCRIPTION: + * + * This function enable the monitor mode. When in the monitor mode + * the tasks are monitored but no data is saved. This can be used + * to profile the load on a system. + */ +rtems_status_code +rtems_capture_monitor (bool enable); + +/* + * rtems_capture_flush + * + * DESCRIPTION: + * + * This function flushes the trace buffer. The prime parameter allows the + * capture engine to also be primed again. + */ +rtems_status_code +rtems_capture_flush (bool prime); + +/** + * rtems_capture_watch_add + * + * DESCRIPTION: + * + * This function defines a watch for a specific task given a name. A watch + * causes it to be traced either in or out of context. The watch can be + * optionally enabled or disabled with the set routine. It is disabled by + * default. + */ +rtems_status_code +rtems_capture_watch_add (rtems_name name, rtems_id id); + +/** + * rtems_capture_watch_del + * + * DESCRIPTION: + * + * This function removes a watch for a specific task given a name. The task + * description will still exist if referenced by a trace record in the trace + * buffer or a global watch is defined. + */ +rtems_status_code +rtems_capture_watch_del (rtems_name name, rtems_id id); + +/** + * rtems_capture_watch_set + * + * DESCRIPTION: + * + * This function allows control of a watch. The watch can be enabled or + * disabled. + */ +rtems_status_code +rtems_capture_watch_ctrl (rtems_name name, + rtems_id id, + bool enable); + +/** + * rtems_capture_watch_global + * + * DESCRIPTION: + * + * This function allows control of a global watch. The watch can + * be enabled or disabled. A global watch configures all tasks below + * the ceiling and above the floor to be traced. + */ +rtems_status_code +rtems_capture_watch_global (bool enable); + +/** + * rtems_capture_watch_global_on + * + * DESCRIPTION: + * + * This function returns the global watch state. + */ +bool +rtems_capture_watch_global_on (void); + +/** + * rtems_capture_watch_ceiling + * + * DESCRIPTION: + * + * This function sets a watch ceiling. Tasks at or greating that the + * ceiling priority are not watched. This is a simple way to monitor + * an application and exclude system tasks running at a higher + * priority level. + */ +rtems_status_code +rtems_capture_watch_ceiling (rtems_task_priority ceiling); + +/** + * rtems_capture_watch_get_ceiling + * + * DESCRIPTION: + * + * This function gets the watch ceiling. + */ +rtems_task_priority +rtems_capture_watch_get_ceiling (void); + +/** + * rtems_capture_watch_floor + * + * DESCRIPTION: + * + * This function sets a watch floor. Tasks at or less that the + * floor priority are not watched. This is a simple way to monitor + * an application and exclude system tasks running at a lower + * priority level. + */ +rtems_status_code +rtems_capture_watch_floor (rtems_task_priority floor); + +/** + * rtems_capture_watch_get_floor + * + * DESCRIPTION: + * + * This function gets the watch floor. + */ +rtems_task_priority +rtems_capture_watch_get_floor (void); + +/** + * rtems_capture_set_trigger + * + * DESCRIPTION: + * + * This function sets a trigger. + * + * This set trigger routine will create a trace control for the + * target task. The task list is searched and any existing tasks + * are linked to the new control. + * + * We can have a number of tasks that have the same name so we + * search using names. This means a number of tasks can be + * linked to single control. + */ +rtems_status_code +rtems_capture_set_trigger (rtems_name from_name, + rtems_id from_id, + rtems_name to_name, + rtems_id to_id, + rtems_capture_trigger_mode_t mode, + rtems_capture_trigger_t trigger); + +/** + * rtems_capture_clear_trigger + * + * DESCRIPTION: + * + * This function clears a trigger. + * + * This clear trigger routine will not clear a watch. + */ +rtems_status_code +rtems_capture_clear_trigger (rtems_name from_name, + rtems_id from_id, + rtems_name to_name, + rtems_id to_id, + rtems_capture_trigger_mode_t mode, + rtems_capture_trigger_t trigger); + +/** + * rtems_capture_read + * + * DESCRIPTION: + * + * This function reads a number of records from the capture buffer. + * The user can optionally block and wait until the buffer as a + * specific number of records available or a specific time has + * elasped. + * + * The function returns the number of record that is has that are + * in a continous block of memory. If the number of available records + * wrap then only those records are provided. This removes the need for + * caller to be concerned about buffer wrappings. If the number of + * requested records cannot be met due to the wrapping of the records + * less than the specified number will be returned. + * + * The user must release the records. This is achieved with a call to + * rtems_capture_release. Calls this function without a release will + * result in at least the same number of records being released. + * + * The 'threshold' parameter is the number of records that must be + * captured before returning. If a timeout period is specified (non-0) + * any captured records will be returned. These parameters stop + * thrashing occuring for a small number of records, yet allows + * a user configured latiency to be applied for single events. + * + * The 'timeout' parameter is in micro-seconds. A value of 0 will + * disable the timeout. + * + */ +rtems_status_code +rtems_capture_read (uint32_t threshold, + uint32_t timeout, + uint32_t* read, + rtems_capture_record_t** recs); + +/** + * rtems_capture_release + * + * DESCRIPTION: + * + * This function releases the requested number of record slots back + * to the capture engine. The count must match the number read. + */ +rtems_status_code +rtems_capture_release (uint32_t count); + +/** + * rtems_capture_tick_time + * + * DESCRIPTION: + * + * This function returns the tick period in micro-seconds. + */ +uint32_t +rtems_capture_tick_time (void); + +/* + * rtems_capture_tick_time + * + * DESCRIPTION: + * + * This function returns the tick period in micro-seconds. + */ +uint32_t +rtems_capture_tick_time (void); + +/** + * rtems_capture_event_text + * + * DESCRIPTION: + * + * This function returns a string for an event based on the bit in the + * event. The functions takes the bit offset as a number not the bit + * set in a bit map. + */ +const char* +rtems_capture_event_text (int event); + +/** + * rtems_capture_get_task_list + * + * DESCRIPTION: + * + * This function returns the head of the list of tasks that the + * capture engine has detected. + */ +rtems_capture_task_t* +rtems_capture_get_task_list (void); + +/** + * rtems_capture_next_task + * + * DESCRIPTION: + * + * This function returns the pointer to the next task in the list. The + * pointer NULL terminates the list. + */ +static inline rtems_capture_task_t* +rtems_capture_next_task (rtems_capture_task_t* task) +{ + return task->forw; +} + +/** + * rtems_capture_task_valid + * + * DESCRIPTION: + * + * This function returns true if the task control block points to + * a valid task. + */ +static inline bool +rtems_capture_task_valid (rtems_capture_task_t* task) +{ + return task->tcb != NULL; +} + +/** + * rtems_capture_task_id + * + * DESCRIPTION: + * + * This function returns the task id. + */ +static inline rtems_id +rtems_capture_task_id (rtems_capture_task_t* task) +{ + return task->id; +} + +/** + * rtems_capture_task_state + * + * DESCRIPTION: + * + * This function returns the task state. + */ +static inline States_Control +rtems_capture_task_state (rtems_capture_task_t* task) +{ + if (rtems_capture_task_valid (task)) + return task->tcb->current_state; + return 0; +} + +/** + * rtems_capture_task_name + * + * DESCRIPTION: + * + * This function returns the task name. + */ +static inline rtems_name +rtems_capture_task_name (rtems_capture_task_t* task) +{ + return task->name; +} + +/** + * rtems_capture_task_flags + * + * DESCRIPTION: + * + * This function returns the task flags. + */ +static inline uint32_t +rtems_capture_task_flags (rtems_capture_task_t* task) +{ + return task->flags; +} + +/** + * rtems_capture_task_control + * + * DESCRIPTION: + * + * This function returns the task control if present. + */ +static inline rtems_capture_control_t* +rtems_capture_task_control (rtems_capture_task_t* task) +{ + return task->control; +} + +/** + * rtems_capture_task_control_flags + * + * DESCRIPTION: + * + * This function returns the task control flags if a control is present. + */ +static inline uint32_t +rtems_capture_task_control_flags (rtems_capture_task_t* task) +{ + if (!task->control) + return 0; + return task->control->flags; +} + +/** + * rtems_capture_task_switched_in + * + * DESCRIPTION: + * + * This function returns the number of times the task has + * been switched into context. + */ +static inline uint32_t +rtems_capture_task_switched_in (rtems_capture_task_t* task) +{ + return task->in; +} + +/** + * rtems_capture_task_switched_out + * + * DESCRIPTION: + * + * This function returns the number of times the task has + * been switched out of context. + */ +static inline uint32_t +rtems_capture_task_switched_out (rtems_capture_task_t* task) +{ + return task->out; +} + +/** + * rtems_capture_task_curr_priority + * + * DESCRIPTION: + * + * This function returns the tasks start priority. The tracer needs this + * to track where the task's priority goes. + */ +static inline rtems_task_priority +rtems_capture_task_start_priority (rtems_capture_task_t* task) +{ + return task->start_priority; +} + +/** + * rtems_capture_task_real_priority + * + * DESCRIPTION: + * + * This function returns the tasks real priority. + */ +static inline rtems_task_priority +rtems_capture_task_real_priority (rtems_capture_task_t* task) +{ + if (rtems_capture_task_valid (task)) + return task->tcb->real_priority; + return 0; +} + +/** + * rtems_capture_task_curr_priority + * + * DESCRIPTION: + * + * This function returns the tasks current priority. + */ +static inline rtems_task_priority +rtems_capture_task_curr_priority (rtems_capture_task_t* task) +{ + if (rtems_capture_task_valid (task)) + return task->tcb->current_priority; + return 0; +} + +/** + * rtems_capture_task_stack_usage + * + * DESCRIPTION: + * + * This function updates the stack usage. The task control block + * is updated. + */ +uint32_t +rtems_capture_task_stack_usage (rtems_capture_task_t* task); + +/** + * rtems_capture_task_stack_size + * + * DESCRIPTION: + * + * This function returns the task's stack size. + */ +static inline uint32_t +rtems_capture_task_stack_size (rtems_capture_task_t* task) +{ + return task->stack_size; +} + +/** + * rtems_capture_task_stack_used + * + * DESCRIPTION: + * + * This function returns the amount of stack used. + */ +static inline uint32_t +rtems_capture_task_stack_used (rtems_capture_task_t* task) +{ + return task->stack_size - task->stack_clean; +} + +/** + * rtems_capture_task_ticks + * + * DESCRIPTION: + * + * This function returns the current execution time as ticks. + */ +static inline uint32_t +rtems_capture_task_ticks (rtems_capture_task_t* task) +{ + return task->ticks; +} + +/** + * rtems_capture_task_tick_offset + * + * DESCRIPTION: + * + * This function returns the current execution time tick offset. + */ +static inline uint32_t +rtems_capture_task_tick_offset (rtems_capture_task_t* task) +{ + return task->tick_offset; +} + +/** + * rtems_capture_task_time + * + * DESCRIPTION: + * + * This function returns the current execution time. + */ +static inline unsigned long long +rtems_capture_task_time (rtems_capture_task_t* task) +{ + unsigned long long t = task->ticks; + return (t * rtems_capture_tick_time ()) + task->tick_offset;; +} + +/** + * rtems_capture_task_delta_time + * + * DESCRIPTION: + * + * This function returns the execution time as a different between the + * last time the detla time was and now. + */ +static inline unsigned long long +rtems_capture_task_delta_time (rtems_capture_task_t* task) +{ + unsigned long long t = task->ticks - task->last_ticks; + uint32_t o = task->tick_offset - task->last_tick_offset; + + task->last_ticks = task->ticks; + task->last_tick_offset = task->tick_offset; + + return (t * rtems_capture_tick_time ()) + o; +} + +/** + * rtems_capture_task_count + * + * DESCRIPTION: + * + * This function returns the number of tasks the capture + * engine knows about. + */ +static inline uint32_t +rtems_capture_task_count (void) +{ + rtems_capture_task_t* task = rtems_capture_get_task_list (); + uint32_t count = 0; + + while (task) + { + count++; + task = rtems_capture_next_task (task); + } + + return count; +} + +/** + * rtems_capture_get_control_list + * + * DESCRIPTION: + * + * This function returns the head of the list of controls in the + * capture engine. + */ +rtems_capture_control_t* +rtems_capture_get_control_list (void); + +/** + * rtems_capture_next_control + * + * DESCRIPTION: + * + * This function returns the pointer to the next control in the list. The + * pointer NULL terminates the list. + */ +static inline rtems_capture_control_t* +rtems_capture_next_control (rtems_capture_control_t* control) +{ + return control->next; +} + +/** + * rtems_capture_control_id + * + * DESCRIPTION: + * + * This function returns the control id. + */ +static inline rtems_id +rtems_capture_control_id (rtems_capture_control_t* control) +{ + return control->id; +} + +/** + * rtems_capture_control_name + * + * DESCRIPTION: + * + * This function returns the control name. + */ +static inline rtems_name +rtems_capture_control_name (rtems_capture_control_t* control) +{ + return control->name; +} + +/** + * rtems_capture_control_flags + * + * DESCRIPTION: + * + * This function returns the control flags. + */ +static inline uint32_t +rtems_capture_control_flags (rtems_capture_control_t* control) +{ + return control->flags; +} + +/** + * rtems_capture_control_to_triggers + * + * DESCRIPTION: + * + * This function returns the task control to triggers. + */ +static inline uint32_t +rtems_capture_control_to_triggers (rtems_capture_control_t* control) +{ + return control->to_triggers; +} + +/** + * rtems_capture_control_from_triggers + * + * DESCRIPTION: + * + * This function returns the task control from triggers. + */ +static inline uint32_t +rtems_capture_control_from_triggers (rtems_capture_control_t* control) +{ + return control->from_triggers; +} + +/** + * rtems_capture_control_all_by_triggers + * + * DESCRIPTION: + * + * This function returns the task control by triggers. + */ +static inline uint32_t +rtems_capture_control_all_by_triggers (rtems_capture_control_t* control) +{ + return control->by_triggers; +} + +/** + * rtems_capture_control_by_valid + * + * DESCRIPTION: + * + * This function returns the control valid BY flags. + */ +static inline int +rtems_capture_control_by_valid (rtems_capture_control_t* control, int slot) +{ + return control->by_valid & RTEMS_CAPTURE_CONTROL_FROM_MASK (slot); +} + +/** + * rtems_capture_control_by_name + * + * DESCRIPTION: + * + * This function returns the control BY task name. + */ +static inline rtems_name +rtems_capture_control_by_name (rtems_capture_control_t* control, int by) +{ + if (by < RTEMS_CAPTURE_TRIGGER_TASKS) + return control->by[by].name; + return control->by[0].name; +} + +/** + * rtems_capture_control_by_id + * + * DESCRIPTION: + * + * This function returns the control BY task id. + */ +static inline rtems_id +rtems_capture_control_by_id (rtems_capture_control_t* control, int by) +{ + if (by < RTEMS_CAPTURE_TRIGGER_TASKS) + return control->by[by].id; + return control->by[0].id; +} + +/** + * rtems_capture_control_by_triggers + * + * DESCRIPTION: + * + * This function returns the control BY task triggers. + */ +static inline uint32_t +rtems_capture_control_by_triggers (rtems_capture_control_t* control, + int by) +{ + if (by < RTEMS_CAPTURE_TRIGGER_TASKS) + return control->by[by].trigger; + return control->by[0].trigger; +} + +/** + * rtems_capture_control_count + * + * DESCRIPTION: + * + * This function returns the number of controls the capture + * engine has. + */ +static inline uint32_t +rtems_capture_control_count (void) +{ + rtems_capture_control_t* control = rtems_capture_get_control_list (); + uint32_t count = 0; + + while (control) + { + count++; + control = rtems_capture_next_control (control); + } + + return count; +} + +#ifdef __cplusplus +} +#endif + +#endif |