📄 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.25
; Date: 23 April 2002
; Assembled using: MPASM 2.80
;################################################################################
;
; 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 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.
; Each function checks the UOWNs bit for the particular OUT endpoint,
; and copies the buffer if available. Upon completion of the function,
; the bank bits are restored to the state they were in when this
; function was entered.
;
; 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 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.
;
; Tests the UOWNs 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 UOWNs 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
return
#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
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 ; BANK 2
btfss USB_status_device, 1
return
bsf STATUS, RP0 ; BANK 3
bcf UCTRL, SUSPND
bsf UIE,UIDLE
bcf UIR,UIDLE
bcf UIE,ACTIVITY
bcf UIR,ACTIVITY
bsf UCTRL, 2 ; RESUME SIGNALING
bcf STATUS, RP0 ; BANK 2
clrf inner
movlw 0x80
movwf outer
pagesel RemoteLoop
RemoteLoop
decfsz inner, f
goto RemoteLoop
decfsz outer, f
goto RemoteLoop
bsf STATUS, RP0 ; BANK 3
bcf UCTRL, 2 ; Clear Resume bit
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
pagesel SoftDetachLoop
SoftDetachLoop
incfsz inner,f
goto SoftDetachLoop
incfsz outer,f
goto SoftDetachLoop
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
pagesel ExitServiceUSBInt
btfsc STATUS,Z ; is there any unmasked interrupts?
goto ExitServiceUSBInt ; no, bail out.
movwf USBMaskedInterrupts
pagesel TokenDone
btfsc USBMaskedInterrupts,ACTIVITY
call USBActivity
pagesel USBReset
btfsc USBMaskedInterrupts,USB_RST
call USBReset
pagesel USBStall
btfsc USBMaskedInterrupts,TOK_DNE ; was it a token done?
call TokenDone
pagesel USBActivity
btfsc USBMaskedInterrupts,STALL
call USBStall
pagesel USBError
btfsc USBMaskedInterrupts,UERR
call USBError
pagesel USBSleep
btfsc USBMaskedInterrupts,UIDLE
call USBSleep
pagesel ServiceUSBInt
goto ServiceUSBInt
ExitServiceUSBInt
banksel PIR1
bcf PIR1,USBIF
return
; ******************************************************************
; USB Reset interrupt triggered (SE0)
; initialize the Buffer Descriptor Table,
; Transition to the DEFAULT state,
; Set address to 0
; enable the USB
; ******************************************************************
USBReset ; START IN BANK2
clrf USB_Curr_Config
clrf IS_IDLE
bsf STATUS, RP0 ; bank 3
bcf UIR,TOK_DNE ; hit this 4 times to clear out the
bcf UIR,TOK_DNE ; USTAT FIFO
bcf UIR,TOK_DNE
bcf UIR,TOK_DNE
movlw 0x8
movwf BD0OBC
movlw USB_Buffer ; Endpoint 0 OUT gets a buffer
movwf BD0OAL ; set up buffer address
movlw 0x88 ; set owns bit (SIE can write)
movwf BD0OST
movlw USB_Buffer+8 ; Endpoint 0 IN gets a buffer
movwf BD0IAL ; set up buffer address
movlw 0x08 ; Clear owns bit (PIC can write)
movwf BD0IST
clrf UADDR ; set USB Address to 0
clrf UIR ; clear all the USB interrupt flags
banksel PIR1 ; switch to bank 0
bcf PIR1,USBIF
; Set up the Endpoint Control Registers. The following patterns are defined
; ENDPT_DISABLED - endpoint not used
; ENDPT_IN_ONLY - endpoint supports IN transactions only
; ENDPT_OUT_ONLY - endpoint supports OUT transactions only
; ENDPT_CONTROL - Supports IN, OUT and CONTROL transactions - Only use with EP0
; ENDPT_NON_CONTROL - Supports both IN and OUT transactions
banksel UEP0
movlw ENDPT_CONTROL
movwf UEP0 ; endpoint 0 is a control pipe and requires an ACK
movlw 0x3B ; enable all interrupts except activity
movwf UIE
movlw 0xFF ; enable all error interrupts
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -