/****************************************************************************** * Function: void USBDriverService(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: This routine is the heart of this firmware. It manages * all USB interrupts. * * Note: Device state transitions through the following stages: * DETACHED -> ATTACHED -> POWERED -> DEFAULT -> * ADDRESS_PENDING -> ADDRESSED -> CONFIGURED -> READY *****************************************************************************/ void USBDriverService(void) { /* * Task A: Service USB Activity Interrupt */ if(UIRbits.ACTVIF && UIEbits.ACTVIE) { UCONbits.SUSPND = 0; UIEbits.ACTVIE = 0; UIRbits.ACTVIF = 0; }//end if /* * Task B: Service USB Bus Reset Interrupt. * When bus reset is received during suspend, ACTVIF will be set first, * once the UCONbits.SUSPND is clear, then the URSTIF bit will be asserted. * This is why URSTIF is checked after ACTVIF. * * The USB reset flag is masked when the USB state is in * DETACHED_STATE or ATTACHED_STATE, and therefore cannot * cause a USB reset event during these two states. */ if(UIRbits.URSTIF && UIEbits.URSTIE) USBProtocolResetHandler(); /* * Task C: Service other USB interrupts */ if(UIRbits.IDLEIF && UIEbits.IDLEIE) { UIEbits.ACTVIE = 1; // Enable bus activity interrupt UIRbits.IDLEIF = 0; UCONbits.SUSPND = 1; // Put USB module in power conserve // mode, SIE clock inactive /* Now, go into power saving */ PIE2bits.USBIE = 1; // Set wakeup source Sleep(); PIR2bits.USBIF = 0; }//end if if(UIRbits.STALLIF && UIEbits.STALLIE) { if(UEP0bits.EPSTALL == 1) { USBPrepareForNextSetupTrf(); // Firmware Work-Around UEP0bits.EPSTALL = 0; }//end if UIRbits.STALLIF = 0; }//end if /* * Pointless to continue servicing if the host has not sent a bus reset. * Once bus reset is received, the device transitions into the DEFAULT * state and is ready for communication. */ if(usb_device_state < DEFAULT_STATE) return; /* * Task D: Servicing USB Transaction Complete Interrupt */ if(UIRbits.TRNIF && UIEbits.TRNIE) { /* * USBCtrlEPService only services transactions over EP0. * It ignores all other EP transactions. */ USBCtrlEPService(); /* * Other EP can be serviced later by responsible device class firmware. * Each device driver knows when an OUT or IN transaction is ready by * checking the buffer ownership bit. * An OUT EP should always be owned by SIE until the data is ready. * An IN EP should always be owned by CPU until the data is ready. * * Because of this logic, it is not necessary to save the USTAT value * of non-EP0 transactions. */ UIRbits.TRNIF = 0; }//end if(UIRbits.TRNIF && UIEbits.TRNIE) }//end USBDriverService
/****************************************************************************** * Function: void USBDriverService(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: This routine is the heart of this firmware. It manages * all USB interrupts. * * Note: Device state transitions through the following stages: * DETACHED -> ATTACHED -> POWERED -> DEFAULT -> * ADDRESS_PENDING -> ADDRESSED -> CONFIGURED -> READY *****************************************************************************/ void USBDriverService(void) { /* * Pointless to continue servicing if USB cable is not even attached. */ if(usb_device_state == DETACHED_STATE) return; /* * Task A: Service USB Activity Interrupt */ if(UIRbits.ACTVIF && UIEbits.ACTVIE) USBWakeFromSuspend(); /* * Pointless to continue servicing if the device is in suspend mode. */ if(UCONbits.SUSPND==1) return; /* * Task B: Service USB Bus Reset Interrupt. * When bus reset is received during suspend, ACTVIF will be set first, * once the UCONbits.SUSPND is clear, then the URSTIF bit will be asserted. * This is why URSTIF is checked after ACTVIF. */ if(UIRbits.URSTIF && UIEbits.URSTIE) USBProtocolResetHandler(); /* * Task C: Service other USB interrupts */ if(UIRbits.IDLEIF && UIEbits.IDLEIE) USBSuspend(); if(UIRbits.SOFIF && UIEbits.SOFIE) USB_SOF_Handler(); if(UIRbits.STALLIF && UIEbits.STALLIE) USBStallHandler(); // if(UIRbits.UERRIF && UIEbits.UERRIE) USBErrorHandler(); /* * Pointless to continue servicing if the host has not sent a bus reset. * Once bus reset is received, the device transitions into the DEFAULT * state and is ready for communication. */ if(usb_device_state < DEFAULT_STATE) return; /* * Task D: Servicing USB Transaction Complete Interrupt */ for(bTRNIFCount = 0; bTRNIFCount < 4; bTRNIFCount++) { if(UIRbits.TRNIF && UIEbits.TRNIE) { /* * USBCtrlEPService only services transactions over EP0. * It ignores all other EP transactions. */ if(USBCtrlEPService() == 0) // If not an EP0 transaction, then clear TRNIF. { /* * Other EP can be serviced later by responsible device class firmware. * Each device driver knows when an OUT or IN transaction is ready by * checking the buffer ownership bit. * An OUT EP should always be owned by SIE until the data is ready. * An IN EP should always be owned by CPU until the data is ready. * * Because of this logic, it is not necessary to save the USTAT value * of non-EP0 transactions. */ UIRbits.TRNIF = 0; /* * At least six Tcy are needed in between clearing UIR<TRNIF> * and when it becomes reasserted when the USTAT FIFO has more * than one entry in it. * * No Nops are needed here because the number of instruction * cycles between clearing the TRNIF here to the next flag * check is longer than the required minimum of six Tcy due * to the for loop logic of bTRNIFCount. This is true even * when all optimization options in C18 are enabled. */ } }//end if(UIRbits.TRNIF && UIEbits.TRNIE) else break; }// end for(bTRNIFCount = 0; bTRNIFCount < 4; bTRNIFCount++) }//end USBDriverService
/****************************************************************************** * Function: void USBDriverService(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: This routine is the heart of this firmware. It manages * all USB interrupts. * * Note: Device state transitions through the following stages: * DETACHED -> ATTACHED -> POWERED -> DEFAULT -> * ADDRESS_PENDING -> ADDRESSED -> CONFIGURED -> READY *****************************************************************************/ void USBDriverService(void) { /* * Pointless to continue servicing if USB cable is not even attached. */ if(usb_device_state == DETACHED_STATE) return; /* * Task A: Service USB Activity Interrupt */ if(UIRbits.ACTVIF && UIEbits.ACTVIE) USBWakeFromSuspend(); /* * Pointless to continue servicing if the device is in suspend mode. */ if(UCONbits.SUSPND==1) return; /* * Task B: Service USB Bus Reset Interrupt. * When bus reset is received during suspend, ACTVIF will be set first, * once the UCONbits.SUSPND is clear, then the URSTIF bit will be asserted. * This is why URSTIF is checked after ACTVIF. */ if(UIRbits.URSTIF && UIEbits.URSTIE) USBProtocolResetHandler(); /* * Task C: Service other USB interrupts */ if(UIRbits.IDLEIF && UIEbits.IDLEIE) USBSuspend(); if(UIRbits.SOFIF && UIEbits.SOFIE) USB_SOF_Handler(); if(UIRbits.STALLIF && UIEbits.STALLIE) USBStallHandler(); if(UIRbits.UERRIF && UIEbits.UERRIE) USBErrorHandler(); /* * Pointless to continue servicing if the host has not sent a bus reset. * Once bus reset is received, the device transitions into the DEFAULT * state and is ready for communication. */ if(usb_device_state < DEFAULT_STATE) return; /* * Task D: Servicing USB Transaction Complete Interrupt */ if(UIRbits.TRNIF && UIEbits.TRNIE) { /* * USBCtrlEPService only services transactions over EP0. * It ignores all other EP transactions. */ USBCtrlEPService(); /* * Other EP can be serviced later by responsible device class firmware. * Each device driver knows when an OUT or IN transaction is ready by * checking the buffer ownership bit. * An OUT EP should always be owned by SIE until the data is ready. * An IN EP should always be owned by CPU until the data is ready. * * Because of this logic, it is not necessary to save the USTAT value * of non-EP0 transactions. */ UIRbits.TRNIF = 0; }//end if(UIRbits.TRNIF && UIEbits.TRNIE) }//end USBDriverService