📄 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: 2.00
; Date: 06 November 2002
; Assembled using: MPASM 2.80
;################################################################################
;
; include files:
; P16C745.inc Rev 1.00
; usb_defs.inc Rev 2.00
;
;################################################################################
#include <p16C745.inc>
#include "usb_defs.inc"
errorlevel -302 ; supress "register not in bank0, check page bits" message
;#define SHOW_ENUM_STATUS
;#define COUNTERRORS
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
USB_Curr_Config res 1
USB_status_device res 1 ; status of device
USB_dev_req res 1
USB_address_pending res 1
USB_Protocol 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
global USB_USTAT
global USB_Curr_Config
global USB_status_device
global USB_dev_req
global USB_Interface
global USB_Protocol
#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 String0
extern ClassSpecificRequest
extern Check_Class_Specific_IN
extern Get_Report_Descriptor
extern Get_HID_Descriptor
extern DeviceDescriptor
extern StringDescriptions
extern GetStringIndex
; **********************************************************************
; 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
; *********************************************************************
; 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
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
bcf STATUS,RP0 ; select bank 0
#ifdef SHOW_ENUM_STATUS
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
bcf STATUS,RP0
#ifdef SHOW_ENUM_STATUS
movlw 0x01
movwf PORTB ; clear all lights except powered
#endif
return
core code
; The functions below are the core functions
; ******************************************************************
; USB Reset interrupt triggered (SE0)
; initialize the Buffer Descriptor Table,
; Transition to the DEFAULT state,
; Set address to 0
; enable the USB
; ******************************************************************
USBReset
global USBReset
banksel USB_Curr_Config
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
; 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
movlw ENDPT_CONTROL
movwf UEP0 ; endpoint 0 is a control pipe and requires an ACK
movlw 0xFF ; Enable all error interrupts
movwf UEIE
movlw DEFAULT_STATE
movwf USWSTAT
bcf STATUS,RP0 ; select bank 2
movlw 0x01
movwf USB_status_device ; Self powered, remote wakeup disabled
bcf STATUS,RP1 ; bank 0
#ifdef SHOW_ENUM_STATUS
bsf PORTB,1 ; set bit one to indicate Reset status
#endif
return ; to keep straight with host controller tests
; ******************************************************************
; Enable Wakeup on interupt and Activity interrupt then put the
; device to sleep to save power. Activity on the D+/D- lines will
; set the ACTIVITY interrupt, waking up the part.
; ******************************************************************
USBSleep
global USBSleep
banksel UIR
bcf UIR,UIDLE
bsf UIE,ACTIVITY
bsf UCTRL, SUSPND
bcf STATUS, RP0 ; switch to bank 2
bsf IS_IDLE, 0
bcf STATUS, RP1 ; switch to bank 0
return
; ******************************************************************
; Service the Activity Interrupt. This is only enabled when the
; device is put to sleep as a result of inactivity on the bus. This
; code wakes up the part, disables the activity interrupt and reenables
; the idle interrupt.
; ******************************************************************
USBActivity
global USBActivity
banksel UCTRL
bcf UCTRL, SUSPND ; Bring the SIE back to life
bcf UIR,ACTIVITY ; clear activity flag
bcf UIE,ACTIVITY ; Disable activity interrupt
bcf STATUS,RP0 ; switch to bank 2
clrf IS_IDLE
bcf STATUS,RP1 ; switch to bank 0
return
; ******************************************************************
; This is activated by the STALL bit in the UIR register. It really
; just tells us that the SIE sent a STALL handshake. So far, Don't
; see that any action is required. Clear the bit and move on.
; ******************************************************************
USBStall
global USBStall
banksel UIR
bcf UIR, STALL ; clear STALL
banksel PIR1 ; switch to bank 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -