/**
* @file
*
* @ingroup rtems_interrupt_extension
*
* @brief Header file for the Interrupt Manager Extension.
*/
/*
* Based on concepts of Pavel Pisa, Till Straumann and Eric Valette.
*
* Copyright (c) 2008, 2017 embedded brains GmbH.
*
* embedded brains GmbH
* Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#ifndef RTEMS_IRQ_EXTENSION_H
#define RTEMS_IRQ_EXTENSION_H
#include <rtems.h>
#include <rtems/chain.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/**
* @defgroup rtems_interrupt_extension Interrupt Manager Extension
*
* @ingroup ClassicINTR
*
* In addition to the Classic API interrupt handler with a handle are
* supported. You can also install multiple shared handler for one interrupt
* vector.
*/
/**@{**/
/**
* @brief Makes the interrupt handler unique. Prevents other handler from
* using the same interrupt vector.
*/
#define RTEMS_INTERRUPT_UNIQUE ((rtems_option) 0x00000001)
/**
* @brief Allows that this interrupt handler may share a common interrupt
* vector with other handler.
*/
#define RTEMS_INTERRUPT_SHARED ((rtems_option) 0x00000000)
/**
* @brief Forces that this interrupt handler replaces the first handler with
* the same argument.
*/
#define RTEMS_INTERRUPT_REPLACE ((rtems_option) 0x00000002)
/**
* @brief Returns true if the interrupt handler unique option is set.
*/
#define RTEMS_INTERRUPT_IS_UNIQUE( options) \
((options) & RTEMS_INTERRUPT_UNIQUE)
/**
* @brief Returns true if the interrupt handler shared option is set.
*/
#define RTEMS_INTERRUPT_IS_SHARED( options) \
(!RTEMS_INTERRUPT_IS_UNIQUE( options))
/**
* @brief Returns true if the interrupt handler replace option is set.
*/
#define RTEMS_INTERRUPT_IS_REPLACE( options) \
((options) & RTEMS_INTERRUPT_REPLACE)
/**
* @brief Interrupt handler routine type.
*/
typedef void (*rtems_interrupt_handler)(void *);
/**
* @brief Installs the interrupt handler routine @a handler for the interrupt
* vector with number @a vector.
*
* You can set one of the mutually exclusive options
*
* - @ref RTEMS_INTERRUPT_UNIQUE
* - @ref RTEMS_INTERRUPT_SHARED
* - @ref RTEMS_INTERRUPT_REPLACE
*
* with the @a options parameter for the interrupt handler.
*
* The handler routine shall be called with argument @a arg when dispatched.
* The order in which the shared interrupt handlers are dispatched for one
* vector is BSP dependent.
*
* If the option @ref RTEMS_INTERRUPT_UNIQUE is set then it shall be ensured
* that this handler will be the only one for this vector.
*
* If the option @ref RTEMS_INTERRUPT_REPLACE is set then it shall be ensured
* that this handler will replace the first handler with the same argument for
* this vector if it exists, otherwise an error status shall be returned. A
* second handler with the same argument for this vector shall remain
* unchanged. The new handler will inherit the unique or shared option from
* the replaced handler.
*
* You can provide an informative description @a info. This may be used for
* system debugging and status tools. The string has to be persistent during
* the handler life time.
*
* This function may block.
*
* @retval RTEMS_SUCCESSFUL Successful operation.
* @retval RTEMS_CALLED_FROM_ISR If this function is called from interrupt
* context this shall be returned.
* @retval RTEMS_INVALID_ADDRESS If the handler address is NULL this shall be
* returned.
* @retval RTEMS_INVALID_ID If the vector number is out of range this shall be
* returned.
* @retval RTEMS_INVALID_NUMBER If an option is not applicable this shall be
* returned.
* @retval RTEMS_RESOURCE_IN_USE If the vector is already occupied with a
* unique handler this shall be returned. If a unique handler should be
* installed and there is already a handler installed this shall be returned.
* @retval RTEMS_TOO_MANY If a handler with this argument is already installed
* for the vector this shall be returned.
* @retval RTEMS_UNSATISFIED If no handler exists to replace with the specified
* argument and vector this shall be returned.
* @retval RTEMS_IO_ERROR Reserved for board support package specific error
* conditions.
*/
rtems_status_code rtems_interrupt_handler_install(
rtems_vector_number vector,
const char *info,
rtems_option options,
rtems_interrupt_handler handler,
void *arg
);
/**
* @brief Removes the interrupt handler routine @a handler with argument @a arg
* for the interrupt vector with number @a vector.
*
* This function may block.
*
* @retval RTEMS_SUCCESSFUL Successful operation.
* @retval RTEMS_CALLED_FROM_ISR If this function is called from interrupt
* context this shall be returned.
* @retval RTEMS_INVALID_ADDRESS If the handler address is NULL this shall be
* returned.
* @retval RTEMS_INVALID_ID If the vector number is out of range this shall be
* returned.
* @retval RTEMS_UNSATISFIED If the handler with its argument is not installed
* for the vector this shall be returned.
* @retval RTEMS_IO_ERROR Reserved for board support package specific error
* conditions.
*/
rtems_status_code rtems_interrupt_handler_remove(
rtems_vector_number vector,
rtems_interrupt_handler handler,
void *arg
);
/**
* @brief Interrupt handler iteration routine type.
*
* @see rtems_interrupt_handler_iterate()
*/
typedef void (*rtems_interrupt_per_handler_routine)(
void *, const char *, rtems_option, rtems_interrupt_handler, void *
);
/**
* @brief Iterates over all installed interrupt handler of the interrupt vector
* with number @a vector.
*
* For each installed handler of the vector the function @a routine will be
* called with the supplied argument @a arg and the handler information,
* options, routine and argument.
*
* This function is intended for system information and diagnostics.
*
* This function may block. Never install or remove an interrupt handler
* within the iteration routine. This may result in a deadlock.
*
* @retval RTEMS_SUCCESSFUL Successful operation.
* @retval RTEMS_CALLED_FROM_ISR If this function is called from interrupt
* context this shall be returned.
* @retval RTEMS_INVALID_ID If the vector number is out of range this shall be
* returned.
* @retval RTEMS_IO_ERROR Reserved for board support package specific error
* conditions.
*/
rtems_status_code rtems_interrupt_handler_iterate(
rtems_vector_number vector,
rtems_interrupt_per_handler_routine routine,
void *arg
);
/**
* @brief Sets the processor affinity set of an interrupt vector.
*
* @param[in] vector The interrupt vector number.
* @param[in] affinity_size The storage size of the affinity set.
* @param[in] affinity_set The new processor affinity set for the interrupt
* vector. This pointer must not be @c NULL.
*
* @retval RTEMS_SUCCESSFUL Successful operation.
* @retval RTEMS_INVALID_ID The vector number is invalid.
* @retval RTEMS_INVALID_SIZE Invalid affinity set size.
* @retval RTEMS_INVALID_NUMBER Invalid processor affinity set.
*/
rtems_status_code rtems_interrupt_set_affinity(
rtems_vector_number vector,
size_t affinity_size,
const cpu_set_t *affinity
);
/**
* @brief Gets the processor affinity set of an interrupt vector.
*
* @param[in] vector The interrupt vector number.
* @param[in] affinity_size The storage size of the affinity set.
* @param[out] affinity_set The current processor affinity set for the
* interrupt vector. This pointer must not be @c NULL.
*
* @retval RTEMS_SUCCESSFUL Successful operation.
* @retval RTEMS_INVALID_ID The vector number is invalid.
* @retval RTEMS_INVALID_SIZE Invalid affinity set size.
*/
rtems_status_code rtems_interrupt_get_affinity(
rtems_vector_number vector,
size_t affinity_size,
cpu_set_t *affinity
);
/**
* @brief An interrupt server action.
*
* This structure must be treated as an opaque data type. Members must not be
* accessed directly.
*
* @see rtems_interrupt_server_action_prepend().
*/
typedef struct rtems_interrupt_server_action {
struct rtems_interrupt_server_action *next;
rtems_interrupt_handler handler;
void *arg;
} rtems_interrupt_server_action;
/**
* @brief The interrupt server index of the default interrupt server.
*/
#define RTEMS_INTERRUPT_SERVER_DEFAULT 0
/**
* @brief An interrupt server entry.
*
* This structure must be treated as an opaque data type. Members must not be
* accessed directly.
*
* @see rtems_interrupt_server_entry_initialize(),
* rtems_interrupt_server_action_prepend(),
* rtems_interrupt_server_entry_submit(), and
* rtems_interrupt_server_entry_destroy().
*/
typedef struct {
rtems_chain_node node;
void *server;
rtems_vector_number vector;
rtems_interrupt_server_action *actions;
} rtems_interrupt_server_entry;
/**
* @brief An interrupt server request.
*
* This structure must be treated as an opaque data type. Members must not be
* accessed directly.
*
* @see rtems_interrupt_server_request_initialize(),
* rtems_interrupt_server_request_submit(), and
* rtems_interrupt_server_request_destroy().
*/
typedef struct {
rtems_interrupt_server_entry entry;
rtems_interrupt_server_action action;
} rtems_interrupt_server_request;
/**
* @brief Initializes the interrupt server tasks.
*
* This function tries to create an interrupt server task for each processor in
* the system. The tasks will have the priority @a priority, the stack size @a
* stack_size, the modes @a modes and the attributes @a attributes. The count
* of server tasks will be returned in @a server_count. Interrupt handlers can
* be installed on an interrupt server with
* rtems_interrupt_server_handler_install() and removed with
* rtems_interrupt_server_handler_remove() using a server index. In case of an
* interrupt, the request will be forwarded to the interrupt server. The
* handlers are executed within the interrupt server context. If one handler
* blocks on something this may delay the processing of other handlers.
*
* The server count pointer @a server_count may be @a NULL.
*
* This function may block.
*
* @see rtems_task_create().
*
* @retval RTEMS_SUCCESSFUL Successful operation.
* @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized.
* @retval RTEMS_NO_MEMORY Not enough memory.
* @retval RTEMS_TOO_MANY No free task available to create at least one server task.
* @retval RTEMS_UNSATISFIED Task stack size too large.
* @retval RTEMS_INVALID_PRIORITY Invalid task priority.
*/
rtems_status_code rtems_interrupt_server_initialize(
rtems_task_priority priority,
size_t stack_size,
rtems_mode modes,
rtems_attribute attributes,
uint32_t *server_count
);
/**
* @brief Installs the interrupt handler routine @a handler for the interrupt
* vector with number @a vector on the server @a server.
*
* The handler routine will be executed on the corresponding interrupt server
* task. A server index @a server_index of @c RTEMS_INTERRUPT_SERVER_DEFAULT
* may be used to install the handler on the default server.
*
* This function may block.
*
* @see rtems_interrupt_handler_install().
*
* @retval RTEMS_SUCCESSFUL Successful operation.
* @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized.
* @retval RTEMS_INVALID_ID If the interrupt server index is invalid.
* @retval * For other errors see rtems_interrupt_handler_install().
*/
rtems_status_code rtems_interrupt_server_handler_install(
uint32_t server_index,
rtems_vector_number vector,
const char *info,
rtems_option options,
rtems_interrupt_handler handler,
void *arg
);
/**
* @brief Removes the interrupt handler routine @a handler with argument @a arg
* for the interrupt vector with number @a vector from the server @a server.
*
* A server index @a server_index of @c RTEMS_INTERRUPT_SERVER_DEFAULT may be
* used to remove the handler from the default server.
*
* This function may block.
*
* @see rtems_interrupt_handler_remove().
*
* @retval RTEMS_SUCCESSFUL Successful operation.
* @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized.
* @retval RTEMS_INVALID_ID If the interrupt server index is invalid.
* @retval * For other errors see rtems_interrupt_handler_remove().
*/
rtems_status_code rtems_interrupt_server_handler_remove(
uint32_t server_index,
rtems_vector_number vector,
rtems_interrupt_handler handler,
void *arg
);
/**
* @brief Iterates over all interrupt handler of the interrupt vector with
* number @a vector which are installed on the interrupt server specified by
* @a server.
*
* A server index @a server_index of @c RTEMS_INTERRUPT_SERVER_DEFAULT may be
* used to specify the default server.
*
* @see rtems_interrupt_handler_iterate()
*
* @retval RTEMS_SUCCESSFUL Successful operation.
* @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized.
* @retval RTEMS_INVALID_ID If the interrupt server index is invalid.
* @retval * For other errors see rtems_interrupt_handler_iterate().
*/
rtems_status_code rtems_interrupt_server_handler_iterate(
uint32_t server_index,
rtems_vector_number vector,
rtems_interrupt_per_handler_routine routine,
void *arg
);
/**
* @brief Moves the interrupt handlers installed on the specified source
* interrupt server to the destination interrupt server.
*
* This function must be called from thread context. It may block. Calling
* this function within the context of an interrupt server is undefined
* behaviour.
*
* @param[in] source_server_index The source interrupt server index. Use
* @c RTEMS_INTERRUPT_SERVER_DEFAULT to specify the default server.
* @param[in] vector The interrupt vector number.
* @param[in] destination_server_index The destination interrupt server index.
* Use @c RTEMS_INTERRUPT_SERVER_DEFAULT to specify the default server.
*
* @retval RTEMS_SUCCESSFUL Successful operation
* @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized.
* @retval RTEMS_INVALID_ID The destination interrupt server index is invalid.
* @retval RTEMS_INVALID_ID The vector number is invalid.
* @retval RTEMS_INVALID_ID The destination interrupt server index is invalid.
*/
rtems_status_code rtems_interrupt_server_move(
uint32_t source_server_index,
rtems_vector_number vector,
uint32_t destination_server_index
);
/**
* @brief Suspends the specified interrupt server.
*
* A suspend request is sent to the specified interrupt server. This function
* waits for an acknowledgment from the specified interrupt server.
*
* This function must be called from thread context. It may block. Calling
* this function within the context of an interrupt server is undefined
* behaviour.
*
* @param[in] server_index The interrupt server index. Use
* @c RTEMS_INTERRUPT_SERVER_DEFAULT to specify the default server.
*
* @see rtems_interrupt_server_resume().
*
* @retval RTEMS_SUCCESSFUL Successful operation
* @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized.
* @retval RTEMS_INVALID_ID If the interrupt server index is invalid.
*/
rtems_status_code rtems_interrupt_server_suspend( uint32_t server_index );
/**
* @brief Resumes the specified interrupt server.
*
* This function must be called from thread context. It may block. Calling
* this function within the context of an interrupt server is undefined
* behaviour.
*
* @param[in] server_index The interrupt server index. Use
* @c RTEMS_INTERRUPT_SERVER_DEFAULT to specify the default server.
*
* @see rtems_interrupt_server_suspend().
*
* @retval RTEMS_SUCCESSFUL Successful operation
* @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized.
* @retval RTEMS_INVALID_ID If the interrupt server index is invalid.
*/
rtems_status_code rtems_interrupt_server_resume( uint32_t server_index );
/**
* @brief Sets the processor affinity of the specified interrupt server.
*
* The scheduler is set determined by the highest numbered processor in the
* specified affinity set.
*
* This operation is only reliable in case the specified interrupt was
* suspended via rtems_interrupt_server_suspend().
*
* @param[in] server_index The interrupt server index. Use
* @c RTEMS_INTERRUPT_SERVER_DEFAULT to specify the default server.
* @param[in] affinity_size The storage size of the affinity set.
* @param[in] affinity The desired processor affinity set for the specified
* interrupt server.
* @param[in] priority The task priority with respect to the corresponding
* scheduler instance.
*
* @retval RTEMS_SUCCESSFUL Successful operation
* @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized.
* @retval RTEMS_INVALID_ID If the interrupt server index is invalid.
* @retval RTEMS_INVALID_SIZE Invalid affinity set size.
* @retval RTEMS_INVALID_NAME The affinity set contains no online processor.
* @retval RTEMS_INCORRECT_STATE The highest numbered online processor in the
* specified affinity set is not owned by a scheduler.
* @retval RTEMS_INVALID_PRIORITY Invalid priority.
* @retval RTEMS_RESOURCE_IN_USE The interrupt server owns resources which deny
* a scheduler change.
* @retval RTEMS_INVALID_NUMBER Invalid processor affinity set.
*/
rtems_status_code rtems_interrupt_server_set_affinity(
uint32_t server_index,
size_t affinity_size,
const cpu_set_t *affinity,
rtems_task_priority priority
);
/**
* @brief Initializes the specified interrupt server entry.
*
* @param[in] server_index The interrupt server index. Use
* @c RTEMS_INTERRUPT_SERVER_DEFAULT to specify the default server.
* @param[in] entry The interrupt server entry to initialize.
*
* @see rtems_interrupt_server_action_prepend().
*
* @retval RTEMS_SUCCESSFUL Successful operation.
* @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized.
* @retval RTEMS_INVALID_ID If the interrupt server index is invalid.
*/
rtems_status_code rtems_interrupt_server_entry_initialize(
uint32_t server_index,
rtems_interrupt_server_entry *entry
);
/**
* @brief Prepends the specified interrupt server action to the list of actions
* of the specified interrupt server entry.
*
* No error checking is performed.
*
* @param[in] entry The interrupt server entry to prepend the interrupt server
* action. It must have been initialized via
* rtems_interrupt_server_entry_initialize().
* @param[in] action The interrupt server action to prepend the list of actions
* of the entry.
* @param[in] handler The interrupt handler for the action.
* @param[in] arg The interrupt handler argument for the action.
*/
void rtems_interrupt_server_action_prepend(
rtems_interrupt_server_entry *entry,
rtems_interrupt_server_action *action,
rtems_interrupt_handler handler,
void *arg
);
/**
* @brief Submits the specified interrupt server entry so that its interrupt
* server actions can be invoked by the specified interrupt server.
*
* This function may be used to do a two-step interrupt processing. The first
* step is done in interrupt context which calls this function. The second
* step is then done in the context of the interrupt server.
*
* This function may be called from thread or interrupt context. It does not
* block. No error checking is performed.
*
* @param[in] entry The interrupt server entry must be initialized before the
* first call to this function via rtems_interrupt_server_entry_initialize()
* and rtems_interrupt_server_action_prepend(). The entry and its actions
* must not be modified between calls to this function. Use
* rtems_interrupt_server_entry_destroy() to destroy an entry in use.
*/
void rtems_interrupt_server_entry_submit(
rtems_interrupt_server_entry *entry
);
/**
* @brief Destroys the specified interrupt server entry.
*
* This function must be called from thread context. It may block. Calling
* this function within the context of an interrupt server is undefined
* behaviour. No error checking is performed.
*
* @param[in] server_index The interrupt server index. Use
* @c RTEMS_INTERRUPT_SERVER_DEFAULT to specify the default server.
* @param[in] entry The interrupt server entry to destroy. It must have been
* initialized via rtems_interrupt_server_entry_initialize().
*/
void rtems_interrupt_server_entry_destroy(
rtems_interrupt_server_entry *entry
);
/**
* @brief Initializes the specified interrupt server request.
*
* @param[in] server_index The interrupt server index. Use
* @c RTEMS_INTERRUPT_SERVER_DEFAULT to specify the default server.
* @param[in] request The interrupt server request to initialize.
* @param[in] handler The interrupt handler for the request action.
* @param[in] arg The interrupt handler argument for the request action.
*
* @retval RTEMS_SUCCESSFUL Successful operation.
* @retval RTEMS_INCORRECT_STATE The interrupt servers are not initialized.
* @retval RTEMS_INVALID_ID If the interrupt server index is invalid.
*/
rtems_status_code rtems_interrupt_server_request_initialize(
uint32_t server_index,
rtems_interrupt_server_request *request,
rtems_interrupt_handler handler,
void *arg
);
/**
* @brief Submits the specified interrupt server request so that its interrupt
* server action can be invoked by the specified interrupt server.
*
* This function may be used to do a two-step interrupt processing. The first
* step is done in interrupt context which calls this function. The second
* step is then done in the context of the interrupt server.
*
* This function may be called from thread or interrupt context. It does not
* block. No error checking is performed.
*
* @param[in] request The interrupt server request must be initialized before the
* first call to this function via
* rtems_interrupt_server_request_initialize(). The request must not be
* modified between calls to this function. Use
* rtems_interrupt_server_request_destroy() to destroy a request in use.
*/
RTEMS_INLINE_ROUTINE void rtems_interrupt_server_request_submit(
rtems_interrupt_server_request *request
)
{
rtems_interrupt_server_entry_submit( &request->entry );
}
/**
* @brief Destroys the specified interrupt server request.
*
* This function must be called from thread context. It may block. Calling
* this function within the context of an interrupt server is undefined
* behaviour. No error checking is performed.
*
* @param[in] request The interrupt server request to destroy. It must have
* been initialized via rtems_interrupt_server_request_initialize().
*/
RTEMS_INLINE_ROUTINE void rtems_interrupt_server_request_destroy(
rtems_interrupt_server_request *request
)
{
rtems_interrupt_server_entry_destroy( &request->entry );
}
/** @} */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* RTEMS_IRQ_EXTENSION_H */