event_handler()
Handle an interrupt
Synopsis
#include <hw/libcan.h>
CANDEV* event_handler( void* const hdl,
const int code );Arguments
- hdl
An arbitrary handle; passed in to the can_resmgr_attach_intr() function.
- code
Pulse code; passed in to the can_resmgr_attach_intr() function.
Description
The event_handler() function verifies that the pulse code is expected and, if so, handles the hardware interrupt and unmasks the interrupt. The interrupt doesn't fire again until it's unmasked. Depending on what triggered the interrupt, you can check if there's data available in the RX devices, verify that transmission has completed on the TX device, etc.
Once the interrupt is fully handled, event_handler() must call the InterruptUnmask() function and return NULL.
The libcan resource manager repeatedly calls event_handler() until the function returns NULL to indicate it's done servicing the interrupt.
Upon return from the event_handler() function, if the device pointer returned corresponds to a TX device, the resource manager immediately invokes the transmit() callback. If the pointer corresponds to a RX device, the resource manager unblocks the client that was blocked the longest.
Returns
A pointer to the CANDEV structure associated with the device that triggered the interrupt, or
NULL if the interrupt was fully handled or was ignored by event_handler().
Example
CANDEV *my_event_handler(void *const hdl, const int code)
{
if (code != MY_DRIVER_PULSE_CODE)
{
return NULL;
}
// my_get_active_device() function would be implementation-specific
// to determine which of the hardware devices handled by this driver is
// responsible for the interrupt. In this example, my_get_active_device()
// would only return a pointer to a structure representing a RX device.
my_device_t *mydev = my_get_active_device();
if (NULL == mydev) {
InterrupUnmask(0, my_driver_data.iid);
return NULL;
}
canmsg_t *msg = canmsg_dequeue_element(mydev->cdev->free_queue);
if (NULL == msg)
{
// Drop oldest message
msg = canmsg_dequeue_element(mydev->cdev->msg_queue);
if (NULL == msg)
{
// No message found - error.
InterrupUnmask(0, my_driver_data.iid);
return NULL;
}
}
memset(&msg->cmsg, 0, sizeof(msg->cmsg));
msg->cmsg.ext.timestamp = get_timestamp(mydev);
msg->cmsg.ext.is_extended_mid = mydev->extended;
msg->cmsg.ext.is_remote_frame = mydev->remote;
msg->cmsg.mid = mydev->mid;
memcpy(msg->cmsg.dat, mydev->data, mydev->datalen);
msg->cmsg.len = mydev->datalen;
canmsg_queue_element(mydev->cdev->msg_queue, msg);
return mydev->cdev;
}