📄 bwmeter.a51
字号:
;--------------------------------------------------------------------------
; BWmeter.A51 2-07-02 LTH
;
; A USB 2.0 High-Speed (480 Mbits/sec) bandwidth meter.
;
; Serves as endless, no-wait, source and sink of bulk packets. Measures the
; number of packets delivered/consumed by the host per microframe.
;
; Correct operation can be determined by glancing at the four FX2 Dev Board LEDs:
; L1 L2 L3 L4
; ON ON ON OFF
;
; L1 is ON for USB high-speed operation (off for full-speed). Indicates you're connected
; to a full-speed host, and the USB host driver is working.
; L2-L3 toggle once per SOF, proving that the code is running.
; L4 comes on only if the code causes any USB NAK's (was used for debug only).
;
; Endpoints used:
; EP1: Bulk IN 64 bytes (retrieves packet buffer history, displays in control panel)
; EP2, EP4: Bulk OUT, double-buffered 512 bytes (endless data sink)
; EP6, EP8: Bulk IN, double-buffered 512 bytes (endliss data source)
;
; NOTE: By using these FX2 default endpoints for Interface 0/Alt Setting 1,
; no USB enumeration code is required.
;
; Registers used:
; r0 is pointer to 64-byte buffer that holds packets-per-frame (ppf) history
; dptr used as a data transfer pointer
;
; Operating Instructions:
;
; 1. Plug in board, load Cypress USB EzMr application (Control Panel).
; 2. Check LED1 (D5) for ON, indicating high-speed operation. If not, go to 3a.
; 3. LED2 and LED3 (D4-D3) should both be on, indicating receipt of SOF packets.
; 3a. Check the port, driver, software, BIOS, etc.
; 4. Click 'Set Iface', then 'Get Pipes' buttons. (Sets the default Interface 0/AltSetting 1).
; 4a. If you don't see the 5 pipes, 0-5, go to 3a.
; 5. Set up a bulk transfer: EP8-IN (default), type 8192 in LENGTH box. [can also use EP6-IN]
; 6. Click BulkTrans. *** You should see the screen fill with blocks of 0's and 1's.
; NOTE: The 'ping' buffer has 0's, the 'pong' buffer has 1's. Last byte shows number of IN's.
; *** The 7-seg readout leaps to life, showing the max IN packets received in a microframe.
; 7. In Bulk Transfer Pipe dropdown menu, select '1: Endpoint 1 IN'. Leave length at 8192.
; 8. Click BulkTrans. This 64-byte record shows the results of the EP8-IN bulk transfer.
; Each byte is the number of IN packets received by the host in a microframe. '0' a microframe
; with no IN packets.
; NOTE: It's OK to leave the length at 8192 for the 64-byte EP1-IN. Since the default USB device
; reports EP1 MaxPacketSize=512, a 64 byte packet represents a short packet and terminates any IN
; transfer request of under 512 bytes. This saves repeatedly re-typing 64 for EP1 and 8192 for EP8.
; 9. An EP1-IN transfer clears the 7-seg readout and resets the analyzer for another try.
; 10. If at any time, LED4 (D2) lights, the analyzer has incurred wait states (NAK). Debug only.
; 11. Same instructions for EP4-OUT [can also use EP2-OUT], except send OUT packets instead of INS.
;
; EP8-IN packs its two buffers with data values 00 and 01; EP6-IN uses EF and FF.
; Note: Hitting the EP1-OUT button (by accident) does not hang the system since this program responds
; to an EP1-OUT request by re-arming the endpoint.
;--------------------------------------------------------------------------
$NOMOD51 ; disable predefined 8051 registers
;--------------------------------------------------------------------------
$include (fx2regs.inc)
$include (handy.mac) ; handy macros: LDREG, bit test, lights on/off
$list
NAME BWmeter
bHSM equ 7 ; in USBCS--High Speed Mode
bSOF equ 1 ; in USBIRQ register--an SOF has arrived
ISEG AT 90H ; stack
stack: ds 40
;
DSEG at 20H ; bit-addressable registers
flags: ds 1 ; NOTE: all flags in this byte initialze to 0
PKTbuf_full equ flags.0
F_LEDtog equ flags.1 ; alternate L2-L3 every SOF
blankflag equ flags.2 ; blank LED if 1
F_found_HS equ flags.3 ; found the high speed mode
F_gotPacket equ flags.4 ; got an IN or an OUT packet
did_once equ flags.5 ; to do stuff only once when PKTbuf just filled
;
DSEG at 30H ; gp registers
ppf: ds 1 ; packets per frame
InCnt: ds 1 ; number of IN-8 transfers
displaydigit: ds 1 ; hex digit to display
maxppf: ds 1 ; max packets in a microframe
PKTbuf: ds 64 ; 64-byte ppf-history buffer
;
CSEG AT 0
LJMP start ; jump over the interrupt vectors
; -------------------------------------------------
org 0080h
; -------------------------------------------------
digit_table: db 0C0h,0F9h,0A4h,0B0h,99h,92h,82h,0F8h,80h,98h,88h,83h,0C6h,0A1h,86h,08Eh
start: mov SP,#stack-1 ; set stack
LDREG USBCS,#0 ; clear RENUM bit and CONNECT (if disconnected)
;
; Comment out two of the following three statements to set 8051 clock speed
;
; LDREG CPUCS,#02h ; 12 MHz, CKOUT enabled (default)
; LDREG CPUCS,#0Ah ; 24 MHz, CKOUT enabled
LDREG CPUCS,#12H ; 48 MHz, CKOUT enabled
;
; initialize variables, buffers & pointers
;
init: call lites_out
call reset_FIFOS
call arm_EP24 ; arm the OUT endpoints
call fill_and_arm_EP8_buffers ; with 00's and 01's
call fill_and_arm_EP6_buffers ; with EF's and FF's
mov InCnt,#2 ; two packets are already posted-for-delivery
mov r0,#PKTbuf ; initialize packet buffer pointer
mov ppf,#0 ; IN packets per frame counter
mov maxppf,#0 ; max over long haul
mov flags,#0 ; all flags in this byte init to zero
setb blankflag ; blank the display
call display_hex
;********************************************************************************
; Main Loop. Poll flags
;********************************************************************************
mainloop: mov a,EP2468STAT ; *** Check for EP8 full flag
jb acc.7,m0 ; EP8 is full--don't need to update
call Update_EP8 ; got a free buffer--fill and arm it
sjmp m1 ; skip EP6 test
m0: jb acc.5,m1 ; EP6 is full--don't need to update
call Update_EP6 ; got a free buffer--fill and arm it
;
m1: mov a,EP2468STAT ; *** Check for EP4OUT-EMPTY
jb acc.2,m10 ; EP4OUT is empty--move on
call Update_EP4 ; it has OUT data--re-arm it
sjmp m2
m10: jb acc.0,m2 ; *** Check for EP2OUT empty
call Update_EP2 ; EP2OUT has OUT data--re-arm it
;
m2: RDREG USBIRQ ; *** Check for SOF
jnb acc.1,m3 ; USBIRQ.1=SOF: no SOF yet
mov a,#00000010b ; b1 is SOF IRQ flag
movx @dptr,a ; clear the request bit
call got_SOF
sjmp mainloop
;
m3: RDREG IBNIRQ ; *** Check for EP8 IBN (In-Bulk-NAK)
jnb acc.5,m3a ; IBNIRQ.5 is EP8-NAK
mov a,#00100000b ; EP4-IBN IRQ bit is bit 5
movx @dptr,a ; clear the bit
L4_ON ; turn on light #4
;
m3a: RDREG NAKIRQ ; *** Check for EP4 PING-NAK
jnb acc.5,m4 ; bit 5 is EP4
mov a,#00100000b
movx @dptr,a ; clear the bit
L4_ON ; turn on light #4
;
m4: RDREG EP1INCS ; *** Check for EP1-IN buffer free
jb acc.1,m4a ; bit 1 is BUSY bit
LDREG EP1INBC,#64 ; arm it for 64 byte transfer
jmp init ; *** START OVER
;
m4a: RDREG EP1OUTCS ; *** Did someone send EP1-OUT data?
jb acc.1,m5 ; busy--waiting for USB data
mov dptr,#EP1OUTBC ; any value in acc will do
movx @dptr,a ; Re-arm it so we don't hang the control panel
;
; *** Check for high-speed operation
;
m5: jb F_found_HS,m6 ; don't need to check for HS mode any more
JBL USBCS,bHSM,m6 ; check the HS operation bit
L1_ON ; found it ON
setb F_found_HS ; set flag so won't continue checking
;
; Do the following operations only once when the PKTbuffer fills (to 64).
;
m6: jb did_once,mainloop ; already displayed the max ppf & updated EP1-IN buffer
jnb PKTbuf_full,mainloop ; history buffer not full yet
setb did_once ; Do the stuff below only once
;
; *** Load EP1-IN with 64 bytes of ppf history
;
mov r7,#64 ; loop counter
mov r0,#PKTbuf ; r0 points to 64-byte ppf history buffer
mov dptr,#EP1INBUF ; dptr points to destination (endpoint FIFO)
xfr: mov a,@r0 ; get byte from PKTbuf
inc r0 ; bump source pointer
movx @dptr,a ; store byte in EP1INBUF
inc dptr ; bump dest pointer
djnz r7,xfr ; do it 64 times
;
clr blankflag ; (don't blank the display in 'display_hex' call)
mov displaydigit,maxppf ; display max packets per frame
call display_hex
jmp mainloop ; go again
; -----------------------------------------------------------------------------------------------
; An EP8 buffer is available. Update last byte in buffer, and dispatch another packet
; -----------------------------------------------------------------------------------------------
Update_EP8: inc InCnt ; total number of IN packets
setb F_gotPacket ; tell SOF service routine we're in business
LDREG EP8FIFOBUF+511,InCnt ; put IN count into last buffer byte
inc ppf ; bump the packets-per-frame count
LDREG EP8BCL,#0 ; re-arm (512 bytes)--NOTE: EP8BCH fixed at 2
ret ; back to loop
; -----------------------------------------------------------------------------------------------
; An EP6 buffer is available. Update last byte in buffer, and dispatch another packet
; -----------------------------------------------------------------------------------------------
Update_EP6: inc InCnt ; total number of IN packets
setb F_gotPacket ; tell SOF service routine we're in business
LDREG EP6FIFOBUF+511,InCnt ; put IN count into last buffer byte
inc ppf ; bump the packets-per-frame count
LDREG EP6BCL,#0 ; re-arm (512 bytes)--NOTE: EP6BCH fixed at 2
ret ; back to loop
; -----------------------------------------------------------------------------------------------
; An EP4 buffer has data. Re-arm the endpoint (drop the data)
; -----------------------------------------------------------------------------------------------
Update_EP4: setb F_gotPacket ; tell SOF service routine we're in business
inc ppf ; bump the packets-per-frame count
LDREG EP4BCL,#80h ; re-arm the endpoint (skip bit set)
ret ; back to loop
; -----------------------------------------------------------------------------------------------
; An EP2 buffer has data. Re-arm the endpoint (drop the data)
; -----------------------------------------------------------------------------------------------
Update_EP2: setb F_gotPacket ; tell SOF service routine we're in business
inc ppf ; bump the packets-per-frame count
LDREG EP2BCL,#80h ; re-arm the endpoint (skip bit set)
ret ; back to loop
; -----------------------------------------------------------------------------------------------
; Got an SOF. Toggle lights, store ppf in buffer, clear ppf, update max. Uses AUTOPTR1 -> PKTbuf
; -----------------------------------------------------------------------------------------------
got_SOF: cpl F_LEDtog ; *** Toggle the middle lights to indicate we're running
jnb F_LEDtog,gs0
L2_OFF
L3_ON
sjmp gs1
gs0: L2_ON
L3_OFF
gs1: jnb F_gotPacket,gs3 ; no INS or OUTS yet...bail out
gs2: jb PKTbuf_full,gs3 ; 64-byte ppf-history buffer is full...bail out
mov @r0,ppf ; not full--stash another ppf value,
inc r0 ; and bump the pointer
;
mov a,maxppf ; *** update maxppf
cjne a,ppf,$+3 ; just to set the cy bit
jnc notbigger ; maxppf-ppf: cy=1 if maxppf < ppf
mov maxppf,ppf ; found a higer one, update maxppf
notbigger: mov ppf,#0 ; reset packet count
;
mov a,r0 ; *** check for full PKTbuf (64 byte limit)
cjne a,#PKTbuf+64,gs3
setb PKTbuf_full ; set the 'full' (don't update any more) flag
gs3: ret
; -----------
; Subroutines
; -----------
; Reset the endpoint FIFOSto the power-on state. (Busy bits, pointers, etc.)
; This is done for repeated code load/debug cycles. Need to restore the part to the
; power-on state so logic that was set during last debug session does not carry over
; into the next debug session.
;
reset_FIFOS: mov dptr,#FIFORESET
mov a,#80h
movx @dptr,a ; first set this bit to NAK any traffic
mov a,#02h ; then clear individual FIFOS
nop ; Syncronization delay (TRM Sec 15.14)
movx @dptr,a ; EP2
mov a,#04h
nop
movx @dptr,a ; EP4
mov a,#06h
nop
movx @dptr,a ; EP6
mov a,#08h
nop
movx @dptr,a ; EP8
mov a,#0
nop
movx @dptr,a ; clear the NAK bit
ret
;
fill_and_arm_EP8_buffers:
mov a,#00h ; fill first buffer with 0's
mov dptr,#EP8FIFOBUF
call fill_EP68_IN
LDREG EP8FIFOBUF+511,#1 ; mark packet #1
LDREG EP8BCH,#2 ; Arm EP8-IN: 200h is 512 bytes
LDREG EP8BCL,#0 ; arm it
;
mov a,#01h ; fill second buffer with 1's
mov dptr,#EP8FIFOBUF
call fill_EP68_IN
LDREG EP8FIFOBUF+511,#2 ; mark packet #2
LDREG EP8BCH,#2
LDREG EP8BCL,#0 ; arm it
ret
;
fill_and_arm_EP6_buffers:
mov a,#0FEh ; fill first buffer with FE's
mov dptr,#EP6FIFOBUF
call fill_EP68_IN
LDREG EP6FIFOBUF+511,#1 ; mark packet #1
LDREG EP6BCH,#2 ; Arm EP6-IN: 200h is 512 bytes
LDREG EP6BCL,#0 ; arm it
;
mov a,#0FFh ; fill second buffer with 1's
mov dptr,#EP6FIFOBUF
call fill_EP68_IN
LDREG EP6FIFOBUF+511,#2 ; mark packet #2
LDREG EP6BCH,#2
LDREG EP6BCL,#0 ; arm it
ret
;
fill_EP68_IN: mov r5,#0
mov r6,#2 ; 2 times 256
fill: movx @dptr,a ; fill 512 byte buffer with value in a
inc dptr
djnz r5,fill
djnz r6,fill
ret
;
; Arm the OUT endpoints (EP2 & EP4). Unlike EZ-USB, the FX2 OUT endpoints come up unarmed.
; We need to write the byte count twice to account for the double-buffering
;
arm_EP24: LDREG EP2BCL,#80h ; set the 'skip' bit (b7) so OUT packets not
LDREG EP2BCL,#80h ; transferred to ext interface which would hang the
LDREG EP4BCL,#80h ; OUT transfers since there's nothing to re-arm the ep
LDREG EP4BCL,#80h
ret
;
lites_out: L1_OFF ; debug lights off
L2_OFF
L3_OFF
L4_OFF
ret
;-----------
display_hex:
;-----------
; Call with blankflag=0 to display digit in 'displaydigit', =1 to blank the display.
;
call stop_check ; make sure the last operation is not in progress
mov dptr,#I2CS ; set the START bit
mov a,#80h ; b7=start bit
movx @dptr,a
;
mov dptr,#I2DAT ; first data byte is address+direc
mov a,#42h ; IO expander address, bit b0=0 means write
movx @dptr,a
call wait_done ; wait for i2c transmit complete
;
jnb blankflag,show
mov a,#0FFh ; all off
sjmp dh2
show: mov dptr,#digit_table
mov a,displaydigit
movc a,@a+dptr
dh2: mov dptr,#I2DAT ; write the data byte
movx @dptr,a
call wait_done
;
mov dptr,#I2CS ; set the STOP bit
mov a,#01000000b
movx @dptr,a
ret
;
stop_check: mov dptr,#I2CS
stck: movx a,@dptr
jb acc.6,stck
ret
;
wait_done: mov dptr,#I2CS ; select DPTR1
cd1: movx a,@dptr
jnb acc.0,cd1
ret
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -