📄 usb_ch9.asm
字号:
; Software License Agreement
;
; The software supplied herewith by Microchip Technology Incorporated (the "Company")
; for its PICmicro(r) Microcontroller is intended and supplied to you, the Company's
; customer, for use solely and exclusively on Microchip PICmicro Microcontroller
; products.
;
; The software is owned by the Company and/or its supplier, and is protected under
; applicable copyright laws. All rights are reserved. Any use in violation of the
; foregoing restrictions may subject the user to criminal sanctions under applicable
; laws, as well as to civil liability for the breach of the terms and conditions of
; this license.
;
; THIS SOFTWARE IS PROVIDED IN AN "AS IS" CONDITION. NO WARRANTIES, WHETHER EXPRESS,
; IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
; MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE
; COMPANY SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR
; CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
;
; ###############################################################################
; filename: USB_CH9.ASM
;
; Implements the chapter 9 enumeration commands for Microchip's
; PIC16C7x5 parts.
;
; ###############################################################################
;
; Author(s): Dan Butler and Reston Condit
; Company: Microchip Technology Inc
;
; Revision: 1.21
; Date: 08 August 2001
; Assembled using MPASM 2.61
; Revision History:
; 23 August 2000 DZB Changed descriptor pointers to 16 bits.
; 24 August 2000 DZB Moved EP1 & 2 configuration from USBReset
; to Set_Configuration to implement requirement in
; USB V1.1 spec paragraph 5.3.1.2
; 28 August 2000 DZB Force data toggle on OUT packets in PutUSB
; 20 March 2001 DZB Reduced use of common RAM
; 20 March 2001 DZB Put and Get use their own temp variable (GPtemp) to
; avoid collisions with the ISR's use of temp.
; 29 March 2001 DZB Fixed saving of bank bits in GetUSB
; 02 May 2001 DZB Implemented SHOW_ENUM_STATUS to show enumeration
; status on the PORTB LEDs: 0- Powered, 1- Default,
; 2- addressed, 3- configured, 4- sleep,
; 5- EP0 Activity, 6- EP1 Activity, 7- EP2 Activity
; 03 August 2001 RAC Made distinct GetEP and PutEP macros for endpoints 1
; and 2. These functions are GetEP1, GetEP2, PutEP1, and
; PutEP2. Instances of the these macros are created in
; usb_ch9.asm.
; 08 August 2001 RAC Corrected various banking and paging issues.
; 15 August RAC Added Report_desc_index function in descript.asm.
; This function allows more than one report descriptor
; to be used.
;
;################################################################################
;
; include files:
; P16C765.inc Rev 1.00
; usb_defs.inc Rev 1.00
;
;################################################################################
#include <p16C765.inc>
#include "usb_defs.inc"
errorlevel -302 ; supress "register not in bank0, check page bits" message
#define SHOW_ENUM_STATUS
unbanked udata_shr ; these will get assigned to unbanked RAM (0x70-0x7F)
temp res 1 ; short term temp register used in Get Interface
GPtemp res 1 ; temporary storage location used in Get and PutEPn
global BufferDescriptor
global BufferData
global temp
global temp2
global EP0_maxLength
global EP0_start
global EP0_end
bank2 udata
BufferDescriptor res 3
BufferData res 8
USBMaskedInterrupts res 1
USB_Curr_Config res 1
USB_status_device res 1 ; status of device
USB_dev_req res 1
USB_address_pending res 1
USBMaskedErrors res 1
PIDs res 1
EP0_start res 2 ; pointer to first byte of data to send
EP0_end res 1 ; pointer to last byte of data to send
EP0_maxLength res 1
temp2 res 1
bufindex res 1
USB_Interface res 3 ; allow 3 interfaces to have alternate endpoints
inner res 1
outer res 1
dest_ptr res 1 ; used in buffer copies for Get and
source_ptr res 1 ; Put USB calls
hid_dest_ptr res 1 ; used in buffer copies for HIDSetReport
hid_source_ptr res 1 ;
counter res 1
bytecounter res 1 ; saved copy that will be returned in W
RP_save res 1 ; save bank bits while copying buffers
IS_IDLE res 1
USB_USTAT res 1 ; copy of the USTAT register before clearing TOK_DNE
global USB_Curr_Config
global USB_status_device
global USB_dev_req
global USB_Interface
#ifdef COUNTERRORS
USB_PID_ERR res 2 ; 16 bit counters for each error condition
USB_CRC5_ERR res 2
USB_CRC16_ERR res 2
USB_DFN8_ERR res 2
USB_BTO_ERR res 2
USB_WRT_ERR res 2
USB_OWN_ERR res 2
USB_BTS_ERR res 2
#endif
extern Config_desc_index
extern Descriptions
extern string_index
extern String0
extern String0_end
extern ClassSpecificRequest
extern Check_Class_Specific_IN
extern Get_Report_Descriptor
extern Get_HID_Descriptor
extern DeviceDescriptor
extern StringDescriptions
; **********************************************************************
; This section contains the functions to interface with the main
; application.
; **********************************************************************
interface code
; **********************************************************************
; GETEP1 and GETEP2
;
; Note: These functions are, in reality, macros defined in usb_defs.inc.
; To save ROM, delete the instances below that you will not need.
;
; Enter with buffer pointer in IRP+FSR.
; Checks the semaphore for the OUT endpoint, and copies the buffer
; if available. Restores the bank bits as we found them.
;
; Returns the bytecount in the W register and return status in the carry
; bit as follows:
; 0 - no buffer available,
; 1 - Buffer copied and buffer made available for next transfer.
;
; The number of bytes moved is returned in W reg.
; **********************************************************************
GETEP1 ; create instance of GETEP1
GETEP2 ; create instance of GETEP2
; **********************************************************************
; PUTEP1 and PUTEP2
;
; Note: These functions are, in reality, macros defined in usb_defs.inc.
; To save ROM, delete the instances below that you will not need.
;
; Enter with bytecount in W and buffer pointer in IRP+FSR.
; the bytecount is encoded in the lower nybble of W.
;
; Tests the owns bit for the IN side of the specified Endpoint.
; If we own the buffer, the buffer pointed to by the FSR is copied
; to the EPn In buffer, then the owns bit is set so the data will be
; TX'd next time polled.
;
; Returns the status in the carry bit as follows:
; 1 - buffer available and copied.
; 0 - buffer not available (try again later)
; **********************************************************************
PUTEP1 ; create instance of PUTEP1
PUTEP2 ; create instance of PUTEP2
; *********************************************************************
; Stall Endpoint.
; Sets the stall bit in the Endpoint Control Register. For the control
; Endpoint, this implements a Protocol stall and is used when the request
; is invalid for the current device state. For non-control Endpoints,
; this is a Functional Stall, meaning that the device needs outside
; intervention and trying again later won't help until it's been serviced.
; enter with endpoint # to stall in Wreg.
; *********************************************************************
StallUSBEP
bsf STATUS,IRP ; select banks 2/3
andlw 0x03 ; try to keep things under control
addlw low UEP0 ; add address of endpoint control reg
movwf FSR
bsf INDF,EP_STALL ; set stall bit
return
; *********************************************************************
; Unstall Endpoint.
; Sets the stall bit in the Endpoint Control Register. For the control
; Endpoint, this implements a Protocol stall and is used when the request
; is invalid for the current device state. For non-control Endpoints,
; this is a Functional Stall, meaning that the device needs outside
; intervention and trying again later won't help until it's been serviced.
; enter with endpoint # to stall in Wreg.
; *********************************************************************
UnstallUSBEP
bsf STATUS,IRP ; select banks 2/3
andlw 0x03 ; try to keep things under control
addlw low UEP0 ; add address of endpoint control reg
movwf FSR
bcf INDF,EP_STALL ; clear stall bit
return
; *********************************************************************
; CheckSleep
; Checks the USB Sleep bit. If the bit is set, the
; Endpoint, this implements a Protocol stall and is used when the request
; is invalid for the current device state. For non-control Endpoints,
; this is a Functional Stall, meaning that the device needs outside
; intervention and trying again later won't help until it's been serviced.
; enter with endpoint # to stall in Wreg.
; *********************************************************************
CheckSleep
global CheckSleep
banksel IS_IDLE
btfss IS_IDLE,0 ; test the bus idle bit
goto nosleeptoday
#ifdef SHOW_ENUM_STATUS
banksel PORTB
bsf PORTB,4 ; turn on LED 4 to indicate we've gone to sleep
banksel UIR
#endif
bsf STATUS,RP0 ; point to bank 3
bcf UIR,ACTIVITY
bsf UIE,ACTIVITY ; enable the USB activity interrupt
bsf UCTRL,SUSPND ; put USB regulator and transciever in low power state
sleep ; and go to sleep
nop
bcf UCTRL,SUSPND
bcf UIR,UIDLE
bsf UIE,UIDLE
bcf UIR,ACTIVITY
bcf UIE,ACTIVITY
#ifdef SHOW_ENUM_STATUS
banksel PORTB
bcf PORTB,4 ; turn off LED 4 to indicate we're back.
#endif
nosleeptoday
return
; *********************************************************************
; Remote Wakeup
; Checks USB_status_device to see if the host enabled Remote Wakeup
; If so, perform Remote wakeup and disable remote wakeup feature
; It is called by PortBChange
; *********************************************************************
RemoteWakeup
global RemoteWakeup
banksel USB_status_device
btfss USB_status_device, 1
goto RemoteEnd
clrf inner
movlw 0xB0
movwf outer
bsf STATUS, RP0 ; BANK 3
bsf UCTRL, 2 ; RESUME SIGNALING
bcf STATUS, RP0 ; BANK 2
incfsz inner,f ; DELAY over 10mS
goto $-1
incfsz outer,f
goto $-3
bsf STATUS,RP0
bcf UCTRL, 2 ; Clear Resume bit
bcf STATUS,RP0
bcf USB_status_device, 1 ; Disable Remote Wakeup
RemoteEnd
return
; *********************************************************************
; USB Soft Detach
; Clears the DEV_ATT bit, electrically disconnecting the device to the bus.
; This removes the device from the bus, then reconnects so it can be
; re-enumerated by the host. This is envisioned as a last ditch effort
; by the software.
; *********************************************************************
SoftDetachUSB
global SoftDetachUSB
banksel UCTRL
bcf UCTRL,DEV_ATT ; clear attach bit
bcf STATUS, RP0 ; bank 2
clrf outer
clrf inner
incfsz inner,f
goto $-1
incfsz outer,f
goto $-3
pagesel InitUSB
call InitUSB ; reinitialize the USB peripheral
return
; ******************************************************************
; Init USB
; Initializes the USB peripheral, sets up the interrupts
; ******************************************************************
InitUSB
global InitUSB
banksel USWSTAT
clrf USWSTAT ; default to powered state
movlw 0x01 ; mask all USB interrupts except reset
movwf UIE
clrf UIR ; clear all USB Interrupt flags
movlw 0x08 ; Device attached
movwf UCTRL
bcf STATUS, RP0 ; bank 2
clrf USB_Curr_Config
movlw 1
movwf USB_status_device
clrf USB_Interface
clrf USB_Interface+1
clrf USB_Interface+2
movlw 0xFF
movwf USB_dev_req ; no device requests in process
#ifdef COUNTERRORS
clrf USB_PID_ERR
clrf USB_PID_ERR+1
clrf USB_CRC5_ERR
clrf USB_CRC5_ERR+1
clrf USB_CRC16_ERR
clrf USB_CRC16_ERR+1
clrf USB_DFN8_ERR
clrf USB_DFN8_ERR+1
clrf USB_BTO_ERR
clrf USB_BTO_ERR+1
clrf USB_WRT_ERR
clrf USB_WRT_ERR+1
clrf USB_OWN_ERR
clrf USB_OWN_ERR+1
clrf USB_BTS_ERR
clrf USB_BTS_ERR+1
#endif
banksel PIR1 ; bank 0
bcf PIR1,USBIF ; clear the USB flag
bsf STATUS,RP0 ; bank 1
bsf PIE1,USBIE ; enable usb interrupt
bsf INTCON, 6 ; enable global and peripheral interrupts
bsf INTCON, 7
#ifdef SHOW_ENUM_STATUS
bcf STATUS,RP0 ; select bank 0
bsf PORTB,0 ; set bit zero to indicate Powered status
#endif
return
; ******************************************************************
; DeInit USB
; Shuts down the USB peripheral, clears the interrupt enable.
; ******************************************************************
DeInitUSB
global DeInitUSB
banksel UCTRL
bcf UCTRL,DEV_ATT ; D+/D- go high Z
bsf UCTRL,SUSPND ; Place USB module in low power mode.
clrf USWSTAT ; set device state to powered.
bcf STATUS,RP1 ; select bank 1
bcf PIE1,USBIE ; clear USB interrupt enable
#ifdef SHOW_ENUM_STATUS
bcf STATUS,RP0
movlw 0x01
movwf PORTB ; clear all lights except powered
bsf STATUS,RP0
#endif
return
core code
; The functions below are the core functions
; ******************************************************************
; USB interrupt triggered, Why?
; Poll the USB interrupt flags to find the cause.
; ******************************************************************
ServiceUSBInt
global ServiceUSBInt
banksel UIR
movf UIR,w ; get the USB interrupt register
andwf UIE,w ; mask off the disabled interrupts
bcf STATUS, RP0 ; BANK 2
btfsc STATUS,Z ; is there any unmasked interrupts?
goto ExitServiceUSBInt ; no, bail out.
pagesel TokenDone
movwf USBMaskedInterrupts
btfsc USBMaskedInterrupts,TOK_DNE ; was it a token done?
call TokenDone
banksel USBMaskedInterrupts
btfsc USBMaskedInterrupts,USB_RST
call USBReset
btfsc USBMaskedInterrupts,STALL
call USBStall
btfsc USBMaskedInterrupts,UERR
call USBError
btfsc USBMaskedInterrupts,UIDLE
call USBSleep
btfsc USBMaskedInterrupts,ACTIVITY
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -