several changes..
1 /*********************************************************************
3 * Microchip USB C18 Firmware Version 1.0
5 *********************************************************************
7 * Dependencies: See INCLUDES section below
9 * Compiler: C18 2.30.01+
10 * Company: Microchip Technology, Inc.
12 * Software License Agreement
14 * The software supplied herewith by Microchip Technology Incorporated
15 * (the “Company”) for its PICmicro® Microcontroller is intended and
16 * supplied to you, the Company’s customer, for use solely and
17 * exclusively on Microchip PICmicro Microcontroller products. The
18 * software is owned by the Company and/or its supplier, and is
19 * protected under applicable copyright laws. All rights are reserved.
20 * Any use in violation of the foregoing restrictions may subject the
21 * user to criminal sanctions under applicable laws, as well as to
22 * civil liability for the breach of the terms and conditions of this
25 * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES,
26 * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED
27 * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
28 * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT,
29 * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
30 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
33 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
34 * Rawin Rojvanit 11/19/04 Original.
35 ********************************************************************/
37 /** I N C L U D E S **********************************************************/
41 #include "io_cfg.h" // Required for USBCheckBusStatus()
43 /** V A R I A B L E S ********************************************************/
46 /** P R I V A T E P R O T O T Y P E S ***************************************/
47 void USBModuleEnable(void);
48 void USBModuleDisable(void);
50 void USBSuspend(void);
51 void USBWakeFromSuspend(void);
53 void USBProtocolResetHandler(void);
54 void USB_SOF_Handler(void);
55 void USBStallHandler(void);
56 void USBErrorHandler(void);
58 /** D E C L A R A T I O N S **************************************************/
60 /******************************************************************************
61 * Function: void USBCheckBusStatus(void)
71 * Overview: This routine enables/disables the USB module by monitoring
72 * the USB power signal.
75 *****************************************************************************/
76 void USBCheckBusStatus(void)
78 /**************************************************************************
79 * Bus Attachment & Detachment Detection
80 * usb_bus_sense is an i/o pin defined in io_cfg.h
81 *************************************************************************/
82 #define USB_BUS_ATTACHED 1
83 #define USB_BUS_DETACHED 0
85 if(usb_bus_sense == USB_BUS_ATTACHED) // Is USB bus attached?
87 if(UCONbits.USBEN == 0) // Is the module off?
88 USBModuleEnable(); // Is off, enable it
92 if(UCONbits.USBEN == 1) // Is the module on?
93 USBModuleDisable(); // Is on, disable it
94 }//end if(usb_bus_sense...)
97 * After enabling the USB module, it takes some time for the voltage
98 * on the D+ or D- line to rise high enough to get out of the SE0 condition.
99 * The USB Reset interrupt should not be unmasked until the SE0 condition is
100 * cleared. This helps preventing the firmware from misinterpreting this
101 * unique event as a USB bus reset from the USB host.
103 if(usb_device_state == ATTACHED_STATE)
107 UIR = 0; // Clear all USB interrupts
108 UIE = 0; // Mask all USB interrupts
109 UIEbits.URSTIE = 1; // Unmask RESET interrupt
110 UIEbits.IDLEIE = 1; // Unmask IDLE interrupt
111 usb_device_state = POWERED_STATE;
112 }//end if // else wait until SE0 is cleared
113 }//end if(usb_device_state == ATTACHED_STATE)
115 }//end USBCheckBusStatus
117 /******************************************************************************
118 * Function: void USBModuleEnable(void)
128 * Overview: This routine enables the USB module.
129 * An end designer should never have to call this routine
130 * manually. This routine should only be called from
131 * USBCheckBusStatus().
133 * Note: See USBCheckBusStatus() for more information.
134 *****************************************************************************/
135 void USBModuleEnable(void)
138 UIE = 0; // Mask all USB interrupts
139 UCONbits.USBEN = 1; // Enable module & attach to bus
140 usb_device_state = ATTACHED_STATE; // Defined in usbmmap.c & .h
141 }//end USBModuleEnable
143 /******************************************************************************
144 * Function: void USBModuleDisable(void)
154 * Overview: This routine disables the USB module.
155 * An end designer should never have to call this routine
156 * manually. This routine should only be called from
157 * USBCheckBusStatus().
159 * Note: See USBCheckBusStatus() for more information.
160 *****************************************************************************/
161 void USBModuleDisable(void)
163 UCON = 0; // Disable module & detach from bus
164 UIE = 0; // Mask all USB interrupts
165 usb_device_state = DETACHED_STATE; // Defined in usbmmap.c & .h
166 }//end USBModuleDisable
168 /******************************************************************************
169 * Function: void USBSoftDetach(void)
177 * Side Effects: The device will have to be re-enumerated to function again.
179 * Overview: USBSoftDetach electrically disconnects the device from
180 * the bus. This is done by stop supplying Vusb voltage to
181 * pull-up resistor. The pull-down resistors on the host
182 * side will pull both differential signal lines low and
183 * the host registers the event as a disconnect.
185 * Since the USB cable is not physically disconnected, the
186 * power supply through the cable can still be sensed by
187 * the device. The next time USBCheckBusStatus() function
188 * is called, it will reconnect the device back to the bus.
191 *****************************************************************************/
192 void USBSoftDetach(void)
197 /******************************************************************************
198 * Function: void USBDriverService(void)
208 * Overview: This routine is the heart of this firmware. It manages
209 * all USB interrupts.
211 * Note: Device state transitions through the following stages:
212 * DETACHED -> ATTACHED -> POWERED -> DEFAULT ->
213 * ADDRESS_PENDING -> ADDRESSED -> CONFIGURED -> READY
214 *****************************************************************************/
215 void USBDriverService(void)
218 * Pointless to continue servicing if USB cable is not even attached.
220 if(usb_device_state == DETACHED_STATE) return;
223 * Task A: Service USB Activity Interrupt
226 if(UIRbits.ACTVIF && UIEbits.ACTVIE) USBWakeFromSuspend();
229 * Pointless to continue servicing if the device is in suspend mode.
231 if(UCONbits.SUSPND==1) return;
234 * Task B: Service USB Bus Reset Interrupt.
235 * When bus reset is received during suspend, ACTVIF will be set first,
236 * once the UCONbits.SUSPND is clear, then the URSTIF bit will be asserted.
237 * This is why URSTIF is checked after ACTVIF.
239 if(UIRbits.URSTIF && UIEbits.URSTIE) USBProtocolResetHandler();
242 * Task C: Service other USB interrupts
244 if(UIRbits.IDLEIF && UIEbits.IDLEIE) USBSuspend();
245 if(UIRbits.SOFIF && UIEbits.SOFIE) USB_SOF_Handler();
246 if(UIRbits.STALLIF && UIEbits.STALLIE) USBStallHandler();
247 if(UIRbits.UERRIF && UIEbits.UERRIE) USBErrorHandler();
250 * Pointless to continue servicing if the host has not sent a bus reset.
251 * Once bus reset is received, the device transitions into the DEFAULT
252 * state and is ready for communication.
254 if(usb_device_state < DEFAULT_STATE) return;
257 * Task D: Servicing USB Transaction Complete Interrupt
259 if(UIRbits.TRNIF && UIEbits.TRNIE)
262 * USBCtrlEPService only services transactions over EP0.
263 * It ignores all other EP transactions.
268 * Other EP can be serviced later by responsible device class firmware.
269 * Each device driver knows when an OUT or IN transaction is ready by
270 * checking the buffer ownership bit.
271 * An OUT EP should always be owned by SIE until the data is ready.
272 * An IN EP should always be owned by CPU until the data is ready.
274 * Because of this logic, it is not necessary to save the USTAT value
275 * of non-EP0 transactions.
278 }//end if(UIRbits.TRNIF && UIEbits.TRNIE)
280 }//end USBDriverService
282 /******************************************************************************
283 * Function: void USBSuspend(void)
296 *****************************************************************************/
297 void USBSuspend(void)
300 * NOTE: Do not clear UIRbits.ACTVIF here!
302 * ACTVIF is only generated once an IDLEIF has been generated.
303 * This is a 1:1 ratio interrupt generation.
304 * For every IDLEIF, there will be only one ACTVIF regardless of
305 * the number of subsequent bus transitions.
307 * If the ACTIF is cleared here, a problem could occur when:
308 * [ IDLE ][bus activity ->
312 * # # # # (#=Program polling flags)
314 * This polling loop will see both
315 * IDLEIF=1 and ACTVIF=1.
316 * However, the program services IDLEIF first
318 * If this routine clears the only ACTIVIF,
319 * then it can never get out of the suspend
322 UIEbits.ACTVIE = 1; // Enable bus activity interrupt
324 UCONbits.SUSPND = 1; // Put USB module in power conserve
325 // mode, SIE clock inactive
327 * At this point the PIC can go into sleep,idle, or
328 * switch to a slower clock, etc.
331 /* Modifiable Section */
333 PIE2bits.USBIE = 1; // Set USB wakeup source
334 Sleep(); // Goto sleep
336 /* End Modifiable Section */
340 /******************************************************************************
341 * Function: void USBWakeFromSuspend(void)
354 *****************************************************************************/
355 void USBWakeFromSuspend(void)
358 * If using clock switching, this is the place to restore the
359 * original clock frequency.
364 }//end USBWakeFromSuspend
366 /******************************************************************************
367 * Function: void USBRemoteWakeup(void)
377 * Overview: This function should be called by user when the device
378 * is waken up by an external stimulus other than ACTIVIF.
379 * Please read the note below to understand the limitations.
381 * Note: The modifiable section in this routine should be changed
382 * to meet the application needs. Current implementation
383 * temporary blocks other functions from executing for a
384 * period of 1-13 ms depending on the core frequency.
386 * According to USB 2.0 specification section 7.1.7.7,
387 * "The remote wakeup device must hold the resume signaling
388 * for at lest 1 ms but for no more than 15 ms."
389 * The idea here is to use a delay counter loop, using a
390 * common value that would work over a wide range of core
392 * That value selected is 1800. See table below:
393 * ==========================================================
394 * Core Freq(MHz) MIP RESUME Signal Period (ms)
395 * ==========================================================
398 * ==========================================================
399 * * These timing could be incorrect when using code
400 * optimization or extended instruction mode,
401 * or when having other interrupts enabled.
402 * Make sure to verify using the MPLAB SIM's Stopwatch
403 *****************************************************************************/
404 void USBRemoteWakeup(void)
406 static word delay_count;
408 if(usb_stat.RemoteWakeup == 1) // Check if RemoteWakeup function
409 { // has been enabled by the host.
410 USBWakeFromSuspend(); // Unsuspend USB modue
411 UCONbits.RESUME = 1; // Start RESUME signaling
413 /* Modifiable Section */
415 delay_count = 1800U; // Set RESUME line for 1-13 ms
421 /* End Modifiable Section */
425 }//end USBRemoteWakeup
427 /******************************************************************************
428 * Function: void USB_SOF_Handler(void)
438 * Overview: The USB host sends out a SOF packet to full-speed devices
439 * every 1 ms. This interrupt may be useful for isochronous
440 * pipes. End designers should implement callback routine
444 *****************************************************************************/
445 void USB_SOF_Handler(void)
447 /* Callback routine here */
450 }//end USB_SOF_Handler
452 /******************************************************************************
453 * Function: void USBStallHandler(void)
455 * PreCondition: A STALL packet is sent to the host by the SIE.
463 * Overview: The STALLIF is set anytime the SIE sends out a STALL
464 * packet regardless of which endpoint causes it.
465 * A Setup transaction overrides the STALL function. A stalled
466 * endpoint stops stalling once it receives a setup packet.
467 * In this case, the SIE will accepts the Setup packet and
468 * set the TRNIF flag to notify the firmware. STALL function
469 * for that particular endpoint pipe will be automatically
470 * disabled (direction specific).
472 * There are a few reasons for an endpoint to be stalled.
473 * 1. When a non-supported USB request is received.
474 * Example: GET_DESCRIPTOR(DEVICE_QUALIFIER)
475 * 2. When an endpoint is currently halted.
476 * 3. When the device class specifies that an endpoint must
477 * stall in response to a specific event.
478 * Example: Mass Storage Device Class
479 * If the CBW is not valid, the device shall
480 * STALL the Bulk-In pipe.
481 * See USB Mass Storage Class Bulk-only Transport
482 * Specification for more details.
484 * Note: UEPn.EPSTALL can be scanned to see which endpoint causes
487 *****************************************************************************/
488 void USBStallHandler(void)
491 * Does not really have to do anything here,
492 * even for the control endpoint.
493 * All BDs of Endpoint 0 are owned by SIE right now,
494 * but once a Setup Transaction is received, the ownership
495 * for EP0_OUT will be returned to CPU.
496 * When the Setup Transaction is serviced, the ownership
497 * for EP0_IN will then be forced back to CPU by firmware.
499 if(UEP0bits.EPSTALL == 1)
501 USBPrepareForNextSetupTrf(); // Firmware work-around
502 UEP0bits.EPSTALL = 0;
505 }//end USBStallHandler
507 /******************************************************************************
508 * Function: void USBErrorHandler(void)
518 * Overview: The purpose of this interrupt is mainly for debugging
519 * during development. Check UEIR to see which error causes
523 *****************************************************************************/
524 void USBErrorHandler(void)
527 }//end USBErrorHandler
529 /******************************************************************************
530 * Function: void USBProtocolResetHandler(void)
532 * PreCondition: A USB bus reset is received from the host.
538 * Side Effects: Currently, this routine flushes any pending USB
539 * transactions. It empties out the USTAT FIFO. This action
540 * might not be desirable in some applications.
542 * Overview: Once a USB bus reset is received from the host, this
543 * routine should be called. It resets the device address to
544 * zero, disables all non-EP0 endpoints, initializes EP0 to
545 * be ready for default communication, clears all USB
546 * interrupt flags, unmasks applicable USB interrupts, and
547 * reinitializes internal state-machine variables.
550 *****************************************************************************/
551 void USBProtocolResetHandler(void)
553 UEIR = 0; // Clear all USB error flags
554 UIR = 0; // Clears all USB interrupts
555 UEIE = 0b10011111; // Unmask all USB error interrupts
556 UIE = 0b01111011; // Enable all interrupts except ACTVIE
558 UADDR = 0x00; // Reset to default address
559 mDisableEP1to15(); // Reset all non-EP0 UEPn registers
560 UEP0 = EP_CTRL|HSHK_EN; // Init EP0 as a Ctrl EP, see usbdrv.h
562 while(UIRbits.TRNIF == 1) // Flush any pending transactions
565 UCONbits.PKTDIS = 0; // Make sure packet processing is enabled
566 USBPrepareForNextSetupTrf(); // Declared in usbctrltrf.c
568 usb_stat.RemoteWakeup = 0; // Default status flag to disable
569 usb_active_cfg = 0; // Clear active configuration
570 usb_device_state = DEFAULT_STATE;
571 }//end USBProtocolResetHandler
574 /* Auxiliary Function */
575 void ClearArray(byte* startAdr,byte count)
587 /** EOF usbdrv.c *************************************************************/