drivers/ipm: Add IPM_CALLBACK_ASYNC mode

Some IPM devices support asynchronous command processing, where
acknowledgment of an IPM message can be delayed while handling
happens in a context other than the ISR that invoked the callback.
Expose this via a kconfig that can be selected by the driver, and add
a new "complete" call (a zero-overhead stub on non-supporting devices)
to signal the end of message handling.

Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
This commit is contained in:
Andy Ross 2022-02-14 11:46:49 -08:00 committed by Anas Nashif
parent 3da9c9213e
commit ebf48d7112
2 changed files with 47 additions and 0 deletions

View File

@ -129,6 +129,14 @@ config IPM_STM32_HSEM_CPU
help help
use to define the CPU ID used by HSEM use to define the CPU ID used by HSEM
config IPM_CALLBACK_ASYNC
bool "Deliver callbacks asynchronously"
help
When selected, the driver supports "asynchronous" command
delivery. Commands will stay active after the ISR returns,
until the application expressly "completes" the command
later.
module = IPM module = IPM
module-str = ipm module-str = ipm
source "subsys/logging/Kconfig.template.log_config" source "subsys/logging/Kconfig.template.log_config"

View File

@ -87,12 +87,23 @@ typedef void (*ipm_register_callback_t)(const struct device *port,
*/ */
typedef int (*ipm_set_enabled_t)(const struct device *ipmdev, int enable); typedef int (*ipm_set_enabled_t)(const struct device *ipmdev, int enable);
/**
* @typedef ipm_complete_t
* @brief Callback API upon command completion
*
* See @a ipm_complete() for argument definitions.
*/
typedef void (*ipm_complete_t)(const struct device *ipmdev);
__subsystem struct ipm_driver_api { __subsystem struct ipm_driver_api {
ipm_send_t send; ipm_send_t send;
ipm_register_callback_t register_callback; ipm_register_callback_t register_callback;
ipm_max_data_size_get_t max_data_size_get; ipm_max_data_size_get_t max_data_size_get;
ipm_max_id_val_get_t max_id_val_get; ipm_max_id_val_get_t max_id_val_get;
ipm_set_enabled_t set_enabled; ipm_set_enabled_t set_enabled;
#ifdef CONFIG_IPM_CALLBACK_ASYNC
ipm_complete_t complete;
#endif
}; };
/** /**
@ -221,6 +232,34 @@ static inline int z_impl_ipm_set_enabled(const struct device *ipmdev,
return api->set_enabled(ipmdev, enable); return api->set_enabled(ipmdev, enable);
} }
/**
* @brief Signal asynchronous command completion
*
* Some IPM backends have an ability to deliver a command
* asynchronously. The callback will be invoked in interrupt context,
* but the message (including the provided data pointer) will stay
* "active" and unacknowledged until later code (presumably in thread
* mode) calls ipm_complete().
*
* This function is, obviously, a noop on drivers without async
* support.
*
* @param ipmdev Driver instance pointer.
*/
__syscall void ipm_complete(const struct device *ipmdev);
static inline void z_impl_ipm_complete(const struct device *ipmdev)
{
#ifdef CONFIG_IPM_CALLBACK_ASYNC
const struct ipm_driver_api *api =
(const struct ipm_driver_api *)ipmdev->api;
if (api->complete != NULL) {
api->complete(ipmdev);
}
#endif
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif