Interrupt Handling
Interrupt handling is accomplished using the following multi-level scheme.
- Processor level kernel-aware interrupt handler
- Device driver interrupt handler
During initialization, the device driver registers all necessary interrupt sources with the BSP interrupt management code. You can also accomplish this by plugging an interrupt vector table during compile time. Once the global interrupt vector sources are configured and an interrupt occurs, the system will call the first-level interrupt handler. The first-level interrupt handler is responsible for performing all kernel required steps prior to calling the USB device driver interrupt handler: USBD_DrvISR_Handler()
. Depending on the platform architecture (that is the way the kernel handles interrupts) and the USB device controller interrupt vectors, the device driver interrupt handler implementation may follow the models below.
Single USB ISR Vector with ISR Handler Argument
If the platform architecture allows parameters to be passed to ISR handlers and the USB device controller has a single interrupt vector for the USB device, the first-level interrupt handler may be defined as:
Prototype
void USBD_BSP_<controller>_IntHandler (void *p_arg);
Arguments
p_arg
Pointer to USB device driver structure that must be typecast to a pointer to USBD_DRV
.
Notes / Warnings
None.
Single USB ISR Vector
If the platform architecture does not allow parameters to be passed to ISR handlers and the USB device controller has a single interrupt vector for the USB device, the first-level interrupt handler may be defined as:
Prototype
void USBD_BSP_<controller>_IntHandler (void);
Arguments
None.
Notes / Warnings
In this configuration, the pointer to the USB device driver structure must be stored globally in the driver. Since the pointer to the USB device structure is never modified, the BSP initialization function, USBD_BSP_Init()
, can save its address for later use.
Multiple USB ISR Vectors with ISR Handler Arguments
If the platform architecture allows parameters to be passed to ISR handlers and the USB device controller has multiple interrupt vectors for the USB device (e.g., USB events, DMA transfers), the first-level interrupt handler may need to be split into multiple sub-handlers. Each sub-handler would be responsible for managing the status reported to the different vectors. For example, the first-level interrupt handlers for a USB device controller that redirects USB events to one interrupt vector and the status of DMA transfers to a second interrupt vector may be defined as:
Prototype
void USBD_BSP_<controller>_EventIntHandler (void *p_arg); void USBD_BSP_<controller>_DMA_IntHandler (void *p_arg);
Arguments
p_arg
Pointer to USB device driver structure that must be typecast to a pointer to USBD_DRV
.
Notes / Warnings
None.
Multiple USB ISR Vectors
If the platform architecture does not allow parameters to be passed to ISR handlers and the USB device controller has multiple interrupt vectors for the USB device (e.g., USB events, DMA transfers), the first-level interrupt handler may need to be split into multiple sub-handlers. Each sub-handler would be responsible for managing the status reported to the different vectors. For example, the first-level interrupt handlers for a USB device controller that redirects USB events to one interrupt vector and the status of DMA transfers to a second interrupt vector may be defined as:
Prototype
void USBD_BSP_<controller>_EventIntHandler (void); void USBD_BSP_<controller>_DMA_IntHandler (void);
Arguments
None.
Notes / Warnings
In this configuration, the pointer to the USB device driver structure must be stored globally in the driver. Since the pointer to the USB device structure is never modified, the BSP initialization function, USBD_BSP_Init()
, can save its address for later use.
Using USBD_DrvISR_Handler()
The device driver interrupt handler must notify the USB device stack of various status changes. The Table - Status Notification API shows each type of status change and the corresponding notification function.
USB Event | Function associated |
---|---|
Connect Event | USBD_EventConn() |
Disconnect Event | USBD_EventDisconn() |
Reset Event | USBD_EventReset() |
Suspend Event | USBD_EventSuspend() |
Resume Event | USBD_EventResume() |
High-Speed Handshake Event | USBD_EventHS() |
Setup Packet | USBD_EventSetup() |
Receive Packet Completed | USBD_EP_RxCmpl() |
Transmit Packet Completed | USBD_EP_TxCmpl() |
Each status notification API queues the event type to be processed by the USB stack’s event processing task. Upon reception of a USB event, the interrupt service routine may perform some operations associated to the event before notifying the stack. For example, the USB device controller driver must perform the proper actions for the bus reset when an interrupt request for that event is triggered. Additionally, it must also notify the USB device stack about the bus reset event by invoking the proper status notification API. In general, the device driver interrupt handler must perform the following functions:
- Determine which type of interrupt event occurred by reading an interrupt status register.
- If a receive event has occurred, the driver must post the successful completion or the error status to the USB device stack by calling
USBD_EP_RxCmpl()
for each transfer received. - If a transmit complete event has occurred, the driver must post the successful completion or the error status to the USB device stack by calling
USBD_EP_TxCmpl()
for each transfer transmitted. - If a setup packet event has occurred, the driver must post the setup packet data in little-endian format to the USB device stack by calling
USBD_EventSetup()
. - All other events must be posted to the USB device stack by a call to their corresponding status notification API from Table - Status Notification API. This allows the USB device stack to broadcast these event notifications to the classes.
- Clear local interrupt flags.