📄 sn8_usb_module.lib
字号:
;**************************************************************************************
;
; <USB MODULE> USB SIE
;--------------------------------------------------------------------------------------
;EP0
;---
;Include 1. Control_Handler (For EP0 setup token)
; 2. Standard_Request (For USB standard command)
; 3. HID_Request (USB HID command)
; 4. Data_structure (EP0 SETUP, IN , OUT)
; 5. Bus Reset function
; 6. USB suspend function
; 7. Remote wakeup function
; 8. USB EP0~EP2's FIFO R/W function
;---------------------------------------------------------------------------------------
;Other Endpoints
;---------------
;EP1
;EP2
;***************************************************************************************
Bus_Reset:
;---------------------------------------------------------------
;NOTE!! Keep USB enable after Bus_reset and set USB address to 0
;---------------------------------------------------------------
mov a,#0x80 ;enable USB & and set USB address = 0
b0mov UDA,a
clr UDP0 ;set FIFO address to EP0
clr UDR0_R
clr UDR0_W
b0bclr bSetAddress ;bus reset clear bSet_address
b0bclr bAlreadySetAddr
b0bclr bSuspend
clr BSetConfiguration
clr UStatus
clr EP0OUT_CNT
mov a, #0x0
b0mov UE0R,a
b0mov UE1R,a
b0mov UE2R,a
jmp isr_90
// ---------------------- //
// USB Suspend function //
// ---------------------- //
USB_Suspend:
;------------------------------------------------------------------
;NOTE!! USER can define MCU's mode when USB suspend occur.
; This demo code set the MCU go into SLEEP.
;------------------------------------------------------------------
b0mov a, P0
b0mov Wakeup_IO_status,a
b0bclr bSuspend
b0bset FCLKMD ; Enter Slow Mode
b0bset FSTPHX
USB_Suspend_10:
@RST_WDT
b0bts1 FSUSPEND
jmp USB_Suspend_20
b0bts1 bRemote_Wakeup ; Check if support Remote wakeup
jmp USB_Suspend_10
b0mov a, P0 ; Check if P0 status changes
cmprs a, Wakeup_IO_status
jmp USB_Suspend_90
jmp USB_Suspend_10
USB_Suspend_20:
b0bclr FSTPHX
;------------------------------------------------------------------
; NOTE! From Slow to Normal Mode, the 6M X'tal stable time needs
; almost 7ms. The delay function below delays almost 8ms.
;------------------------------------------------------------------
mov a,#0x07
b0mov z,a
@@:
decms z
jmp @b
b0bclr FCLKMD
ret
USB_Suspend_90:
b0bclr FSTPHX
;------------------------------------------------------------------
; NOTE! From Slow to Normal Mode, the 6M X'tal stable time needs
; almost 7ms. The delay function below delays almost 8ms.
;------------------------------------------------------------------
mov a,#0x07
b0mov z,a
@@:
decms z
jmp @b
b0bclr FCLKMD
jmp Remote_Wakeup
// ------------------- //
// USB Remote_wakeup //
// ------------------- //
Remote_Wakeup:
mov a,#0x01
cmprs a,bSetConfiguration ; Check if Configured_State
jmp USB_Suspend_10
b0bclr FGIE
mov a, #11000110b ;j state ;Full speed D+ > 0, D- <0
b0mov upid, a
call delay_for_j_state
mov a, #11000101b ;k state
b0mov upid, a
call delay_for_k_state;SPEC require 1ms ~ 15ms
mov a, #11000010b ;recovery, disable driving USB BUS
b0mov upid,a
b0bclr INTRQ.0 ;clear Key wakeup
b0bclr INTRQ.6 ;clear USB interrupt request
b0bset FGIE
ret
;**************************************************************************************
; USB Delay function for remote wakeup control D+ D-
;======================================================================================
; User must define the parameter USB_REMOTE_WAKEUP_K_STATE_DELAY in SN8_USB_Setting.asm
;**************************************************************************************
delay_for_j_state:
mov a,#0ffh
b0mov z,a
mov a,#0X01
b0mov r,a
@@: DECMS Z
jmp @B
DECMS R
jmp @B
ret
delay_for_k_state:
mov a,#0ffh
b0mov z,a
mov a,#USB_REMOTE_WAKEUP_K_STATE_DELAY
b0mov r,a
@@: DECMS Z
jmp @B
DECMS R
jmp @B
ret
;***********************************************************************
; USB EP0 SETUP, IN, OUT
;***********************************************************************
;***********************************************************************
; Data Structure (contain 2 parts)
;-----------------------------------------------------------------------
; 1. Parse the setup token command
; <Parse the command and save the command to the relative RAM>
; a. bmRequestType
; b. bRequest
; c. wValue_H, wValue_L
; d. wIndex_H, wIndex_L
; e. wLength_H, wLength_L
;
; 2. Write DATA in to data and send it out to host (IN Token command)
; (If data > 8 bytes, the code will divide it automatically and
; write to the FIFO every 8 bytes)
;
;***********************************************************************
// ====================================================================== //
// EP1 & EP2 ACK transcation. //
// ====================================================================== //
EP1_ACK:
b0bclr EP_ACK.0
jmp isr_90
EP2_ACK:
b0bclr EP_ACK.1
jmp isr_90
// ====================================================================== //
// 1.Setup token & Parse the COMMAND //
// ====================================================================== //
EP0_Setup:
b0bclr UStatus.2 ;clear EP0_SETUP interrupt flag.
b0bclr UE0R.5 ;keep EP0 NAK state in the first place.
ReadEP0Buffer:
mov a, #0x0
CALL EP0_FIFO_RD_addr_set
CALL EP0_FIFO_RD_data
b0mov bmRequestType, a
mov a, #0x1
CALL EP0_FIFO_RD_addr_set
CALL EP0_FIFO_RD_data
b0mov bRequest, a
mov a, #0x2
CALL EP0_FIFO_RD_addr_set
CALL EP0_FIFO_RD_data
b0mov wValue_L, a
mov a, #0x3
CALL EP0_FIFO_RD_addr_set
CALL EP0_FIFO_RD_data
b0mov wValue_H, a
mov a, #0x4
CALL EP0_FIFO_RD_addr_set
CALL EP0_FIFO_RD_data
b0mov wIndex_L, a
mov a, #0x5
CALL EP0_FIFO_RD_addr_set
CALL EP0_FIFO_RD_data
b0mov wIndex_H, a
mov a, #0x6
CALL EP0_FIFO_RD_addr_set
CALL EP0_FIFO_RD_data
b0mov wLength_L, a
mov a, #0x7
CALL EP0_FIFO_RD_addr_set
CALL EP0_FIFO_RD_data
b0mov wLength_H, a
; call Control_Handler
; jmp isr_90
// ==================================================================================== //
// ==================================================================================== //
// USB Command request function
// ==================================================================================== //
// ==================================================================================== //
Control_Handler:
b0mov a, bmRequestType ; check Request Type
and a, #01100000b ; mask bits 5,6
cmprs a, #00100000b ; check the command
jmp Standard_Request
jmp HID_Request
;***********************************************************************
; Start standard request
;***********************************************************************
Standard_Request:
and a, #REQUEST_TYPE_MASK
b0bts1 FZ
jmp Request_Not_Support
b0mov a, bRequest ; find Request
and a, #0x0f
add PCL, a
jmp get_status ; 0x00
jmp clear_feature ; 0x01
jmp Request_Not_Support ; 0x02
jmp set_feature ; 0x03
jmp Request_Not_Support ; 0x04
jmp set_address ; 0x05
jmp get_descriptor ; 0x06
jmp set_descriptor ; 0x07
jmp get_configuration ; 0x08
jmp set_configuration ; 0x09
jmp get_interface ; 0x0a
jmp set_interface ; 0x0b
nop ; 0x0c
nop ; 0x0d
nop ; 0x0e
jmp Request_Not_Support
control_handler_90:
;ret
jmp isr_90
// ====================================================================== //
// EP0 IN token //
// ====================================================================== //
EP0_In:
b0bclr UStatus.1
b0bts0 bAlreadySetAddr
jmp EP0_In_10
b0bts1 bSetAddress
jmp EP0_In_10
b0mov a, bdevice_address ; Set Address
or a, #0x80
b0mov UDA, a
b0bset bAlreadySetAddr
EP0_In_10:
b0bts0 set_report_feature_arrival
jmp EP0_In_set_report_feature_done
b0mov a, wLength_H
or a, wLength_L
b0bts0 FZ
jmp isr_90 ; 0 in packet (stage status response)
b0bts0 bmRequestType.7 ; check if "IN" token require
jmp EP0_In_done ; EP0 in token
jmp isr_90
EP0_In_done: ; EP0 IN token start!
call table_transmit
jmp EP0_In_done_90
EP0_In_set_report_feature_done:
b0bclr set_report_feature_arrival
;b0bset set_report_feature_done
b0mov a,SET_REPORT_FEATURE_Buf[0]
cmprs a, #RETURN_KERNEL_0
jmp EP0_In_done_90
b0mov a,SET_REPORT_FEATURE_Buf[1]
cmprs a, #RETURN_KERNEL_1
jmp EP0_In_done_90
b0mov a,SET_REPORT_FEATURE_Buf[2]
cmprs a, #RETURN_KERNEL_2
jmp EP0_In_done_90
b0mov a,SET_REPORT_FEATURE_Buf[3]
cmprs a, #RETURN_KERNEL_3
jmp EP0_In_done_90
b0mov a,SET_REPORT_FEATURE_Buf[4]
cmprs a, #RETURN_KERNEL_4
jmp EP0_In_done_90
b0mov a,SET_REPORT_FEATURE_Buf[5]
cmprs a, #RETURN_KERNEL_5
jmp EP0_In_done_90
b0mov a,SET_REPORT_FEATURE_Buf[6]
cmprs a, #RETURN_KERNEL_6
jmp EP0_In_done_90
b0mov a,SET_REPORT_FEATURE_Buf[7]
cmprs a, #RETURN_KERNEL_7
jmp EP0_In_done_90
b0mov a, STKP
and a, #0x07
add a, #0x01
b0mov z,a
b0add z,a ; Use z for stack index
mov a, #0xF0
add a, z
b0mov z, a
b0mov y, #0x0
mov a, #_Back_To_Kernel_Mode$L
;mov a, #0x10
b0mov @yz, a
incms z
nop
;mov a, #0x20
mov a, #_Back_To_Kernel_Mode$M
b0mov @yz, a
ret
EP0_In_done_90:
jmp Isr_90
// ====================================================================== //
// EP0 OUT token //
// ====================================================================== //
EP0_OUT:
b0bclr UStatus.0 ;clear EP0 OUT interrupt flag
b0bts0 set_report_feature_flag
jmp _EP0_OUT_STATUS_set_report_feature
b0bts1 set_report_flag ;check "SET REPORT command"
jmp _EP0_OUT_STATUS_Stage
b0bclr set_report_flag
EP0_RD_RAM_addr_set #0x0 ;READ EP0 FIFO, START from 0x0
EP0_RD_RAM_to_A ;move data to A
mov SET_REPORT_BYTE_0,a ;save data to SET_REPORT_BYTE_0
jmp _EP0_OUT_STATUS_Stage
_EP0_OUT_STATUS_set_report_feature:
EP0_RD_RAM_addr_set #0x0 ;READ EP0 FIFO, START from 0x0
EP0_RD_RAM_to_A ;move data to A
mov SET_REPORT_FEATURE_Buf[0],a ;save data to SET_REPORT_BYTE_0
EP0_RD_RAM_addr_set #0x1
EP0_RD_RAM_to_A
mov SET_REPORT_FEATURE_Buf[1],a
EP0_RD_RAM_addr_set #0x2
EP0_RD_RAM_to_A
mov SET_REPORT_FEATURE_Buf[2],a
EP0_RD_RAM_addr_set #0x3
EP0_RD_RAM_to_A
mov SET_REPORT_FEATURE_Buf[3],a
EP0_RD_RAM_addr_set #0x4
EP0_RD_RAM_to_A
mov SET_REPORT_FEATURE_Buf[4],a
EP0_RD_RAM_addr_set #0x5
EP0_RD_RAM_to_A
mov SET_REPORT_FEATURE_Buf[5],a
EP0_RD_RAM_addr_set #0x6
EP0_RD_RAM_to_A
mov SET_REPORT_FEATURE_Buf[6],a
EP0_RD_RAM_addr_set #0x7
EP0_RD_RAM_to_A
mov SET_REPORT_FEATURE_Buf[7],a
b0bclr set_report_feature_flag
b0bset set_report_feature_arrival
;b0bset set_report_feature_done
_EP0_OUT_STATUS_Stage:
b0bset UE0R.5 ;ACK OUT status stage
jmp isr_90
// ====================================================================== //
// 2. Divide the data and Send to the FIFO //
// ====================================================================== //
/***************************************************************************
* NAME: decm_length
*----------------------------------------------------------------------------
* PURPOSE:
* subtract table_length[0] table_length[1]
* to solve problems about occur borrow
*----------------------------------------------------------------------------
*****************************************************************************/
decm_length:
mov a,table_length[0] ;length[0] - 1
sub a,#1h ; hubert
mov table_length[0],a
b0bts0 FC
jmp $+4
mov a,table_length[1] ;if occur borrow then length[1] - 1
sub a,#1h
mov table_length[1],a
b0bts1 FC
clr table_length[1] ;;if occur borrow then length[1] = 0
ret
/***************************************************************************
* NAME: check_length
*----------------------------------------------------------------------------
* PURPOSE:
*
* if table length > wLength
* then table length = wLength
*----------------------------------------------------------------------------
*****************************************************************************/
check_length:
mov a,wLength_H
sub a,table_length[1]
b0bts0 FC
jmp check_length_20 ;wLength_H >= table_length[1]
jmp check_length_30 ;wLength_H < table_length[1]
check_length_20:
mov a,wLength_H
cmprs a,table_length[1]
jmp check_length_90 ;wLength_H > table_length[1]
mov a,wLength_L
sub a,table_length[0]
b0bts0 FC
jmp check_length_90 ;if wLength_L >= table_length[0]
check_length_30:
mov a,wLength_H ;then table_length[0] = wLength_L
mov table_length[1],a
mov a,wLength_L ;then table_length[0] = wLength_L
mov table_length[0],a
check_length_90:
ret
/***************************************************************************
* NAME: table_transmit
*----------------------------------------------------------------------------
* PURPOSE:
* output data from lookup table to usb,
* Divide the data and Send to the FIFO
*----------------------------------------------------------------------------
*****************************************************************************/
table_transmit:
mov a,table_index[1]
mov y,a
mov a,table_index[0]
mov z,a
CALL check_length
mov a,#EP0_PACKET_SIZE ;Tmp_Cnt = 8
mov Tmp_Cnt,a
mov a,#0x0 ;set addr 0
CALL EP0_FIFO_WR_addr_set
mov a,table_length[1] ;if highbyte != 0
cmprs a,#0h
jmp table_transmit_20
mov a,table_length[0]
b0bts1 FZ
jmp table_transmit_05
mov a, #0xF0
and UE0R,a
jmp table_transmit_90
; mov a,table_length[0]
; b0bts0 FZ
; jmp table_transmit_90
table_transmit_05:
mov a,table_length[0] ;if lowbyte >= 8
sub a,#EP0_PACKET_SIZE
b0bts0 FC
jmp table_transmit_20
mov a,#0f0h
and UE0R,a
mov a,table_length[0]
or UE0R,a
table_transmit_10: ; < 8 byte transmit
movc
CALL EP0_FIFO_WR_data
mov a, #0x01
CALL EP0_FIFO_WR_addr_add
b0bts1 USB_Status.5 ;double byte transmit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -