📄 usbdrv.c
字号:
* Note: None
*****************************************************************************/
void USBSuspend(void) //挂起
{
/*
* NOTE: Do not clear UIRbits.ACTVIF here!
* Reason:
* ACTVIF is only generated once an IDLEIF has been generated.
* This is a 1:1 ratio interrupt generation.
* For every IDLEIF, there will be only one ACTVIF regardless of
* the number of subsequent bus transitions.
*
* If the ACTIF is cleared here, a problem could occur when:
* [ IDLE ][bus activity ->
* <--- 3 ms -----> ^
* ^ ACTVIF=1
* IDLEIF=1
* # # # # (#=Program polling flags)
* ^
* This polling loop will see both
* IDLEIF=1 and ACTVIF=1.
* However, the program services IDLEIF first
* because ACTIVIE=0.
* If this routine clears the only ACTIVIF,
* then it can never get out of the suspend
* mode.
*/
UIEbits.ACTVIE = 1; // Enable bus activity interrupt
UIRbits.IDLEIF = 0;
UCONbits.SUSPND = 1; // Put USB module in power conserve
// mode, SIE clock inactive
/*
* At this point the PIC can go into sleep,idle, or
* switch to a slower clock, etc.
*/
/* Modifiable Section */
/* End Modifiable Section */
}//end USBSuspend
/******************************************************************************
* Function: void USBWakeFromSuspend(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview:
*
* Note: None
*****************************************************************************/
void USBWakeFromSuspend(void)
{
/*
* If using clock switching, this is the place to restore the
* original clock frequency.
*/
UCONbits.SUSPND = 0;
UIEbits.ACTVIE = 0;
UIRbits.ACTVIF = 0;
}//end USBWakeFromSuspend
/******************************************************************************
* Function: void USBRemoteWakeup(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: This function should be called by user when the device
* is waken up by an external stimulus other than ACTIVIF.
* Please read the note below to understand the limitations.
*
* Note: The modifiable section in this routine should be changed
* to meet the application needs. Current implementation
* temporary blocks other functions from executing for a
* period of 1-13 ms depending on the core frequency.
*
* According to USB 2.0 specification section 7.1.7.7,
* "The remote wakeup device must hold the resume signaling
* for at lest 1 ms but for no more than 15 ms."
* The idea here is to use a delay counter loop, using a
* common value that would work over a wide range of core
* frequencies.
* That value selected is 1800. See table below:
* ==========================================================
* Core Freq(MHz) MIP RESUME Signal Period (ms)
* ==========================================================
* 48 12 1.05
* 4 1 12.6
* ==========================================================
* * These timing could be incorrect when using code
* optimization or extended instruction mode,
* or when having other interrupts enabled.
* Make sure to verify using the MPLAB SIM's Stopwatch
*****************************************************************************/
void USBRemoteWakeup(void)
{
static word delay_count;
if(usb_stat.RemoteWakeup == 1) // Check if RemoteWakeup function
{ // has been enabled by the host.
USBWakeFromSuspend(); // Unsuspend USB modue
UCONbits.RESUME = 1; // Start RESUME signaling
/* Modifiable Section */
delay_count = 1800U; // Set RESUME line for 1-13 ms
do
{
delay_count--;
}while(delay_count);
/* End Modifiable Section */
UCONbits.RESUME = 0;
}//endif
}//end USBRemoteWakeup
/******************************************************************************
* Function: void USB_SOF_Handler(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: The USB host sends out a SOF packet to full-speed devices
* every 1 ms. This interrupt may be useful for isochronous
* pipes. End designers should implement callback routine
* as necessary.
*
* Note: None
*****************************************************************************/
void USB_SOF_Handler(void)
{
/* Callback routine here */
UIRbits.SOFIF = 0;
}//end USB_SOF_Handler
/******************************************************************************
* Function: void USBStallHandler(void)
*
* PreCondition: A STALL packet is sent to the host by the SIE.
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: The STALLIF is set anytime the SIE sends out a STALL
* packet regardless of which endpoint causes it.
* A Setup transaction overrides the STALL function. A stalled
* endpoint stops stalling once it receives a setup packet.
* In this case, the SIE will accepts the Setup packet and
* set the TRNIF flag to notify the firmware. STALL function
* for that particular endpoint pipe will be automatically
* disabled (direction specific).
*
* There are a few reasons for an endpoint to be stalled.
* 1. When a non-supported USB request is received.
* Example: GET_DESCRIPTOR(DEVICE_QUALIFIER)
* 2. When an endpoint is currently halted.
* 3. When the device class specifies that an endpoint must
* stall in response to a specific event.
* Example: Mass Storage Device Class
* If the CBW is not valid, the device shall
* STALL the Bulk-In pipe.
* See USB Mass Storage Class Bulk-only Transport
* Specification for more details.
*
* Note: UEPn.EPSTALL can be scanned to see which endpoint causes
* the stall event.
* If
*****************************************************************************/
void USBStallHandler(void)
{
/*
* Does not really have to do anything here,
* even for the control endpoint.
* All BDs of Endpoint 0 are owned by SIE right now,
* but once a Setup Transaction is received, the ownership
* for EP0_OUT will be returned to CPU.
* When the Setup Transaction is serviced, the ownership
* for EP0_IN will then be forced back to CPU by firmware.
*
* NOTE: Above description is not quite true at this point.
* It seems the SIE never returns the UOWN bit to CPU,
* and a TRNIF is never generated upon successful
* reception of a SETUP transaction.
* Firmware work-around is implemented below.
*/
if(UEP0bits.EPSTALL == 1)
{
USBPrepareForNextSetupTrf(); // Firmware Work-Around
UEP0bits.EPSTALL = 0;
}
UIRbits.STALLIF = 0;
}//end USBStallHandler
/******************************************************************************
* Function: void USBErrorHandler(void)
*
* PreCondition: None
*
* Input: None
*
* Output: None
*
* Side Effects: None
*
* Overview: The purpose of this interrupt is mainly for debugging
* during development. Check UEIR to see which error causes
* the interrupt.
*
* Note: None
*****************************************************************************/
void USBErrorHandler(void)
{
UIRbits.UERRIF = 0;
}//end USBErrorHandler
/******************************************************************************
* Function: void USBProtocolResetHandler(void)
*
* PreCondition: A USB bus reset is received from the host.
*
* Input: None
*
* Output: None
*
* Side Effects: Currently, this routine flushes any pending USB
* transactions. It empties out the USTAT FIFO. This action
* might not be desirable in some applications.
*
* Overview: Once a USB bus reset is received from the host, this
* routine should be called. It resets the device address to
* zero, disables all non-EP0 endpoints, initializes EP0 to
* be ready for default communication, clears all USB
* interrupt flags, unmasks applicable USB interrupts, and
* reinitializes internal state-machine variables.
*
* Note: None
*****************************************************************************/
void USBProtocolResetHandler(void)
{
UEIR = 0; // Clear all USB error flags
UIR = 0; // Clears all USB interrupts
UEIE = 0b10011111; // Unmask all USB error interrupts
UIE = 0b01111011; // Enable all interrupts except ACTVIE
UADDR = 0x00; // Reset to default address
mDisableEP1to15(); // Reset all non-EP0 UEPn registers
UEP0 = EP_CTRL|HSHK_EN; // Init EP0 as a Ctrl EP, see usbdrv.h
while(UIRbits.TRNIF == 1) // Flush any pending transactions
UIRbits.TRNIF = 0;
UCONbits.PKTDIS = 0; // Make sure packet processing is enabled
USBPrepareForNextSetupTrf(); // Declared in usbctrltrf.c
usb_stat.RemoteWakeup = 0; // Default status flag to disable
usb_active_cfg = 0; // Clear active configuration
usb_device_state = DEFAULT_STATE;
}//end USBProtocolResetHandler
/* Auxiliary Function */
void ClearArray(byte* startAdr,byte count)
{
*startAdr;
while(count)
{
_asm
clrf POSTINC0,0
_endasm
count--;
}//end while
}//end ClearArray
/** EOF usbdrv.c *************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -