Commits

Anonymous committed 72e31c0

Add debugdev example

EHCI defines a DEBUG device, which might be used for low level
hardware debugging. Lets add this as an example usage for fx2lib.

Signed-off-by: Sven Schnelle <svens@stackframe.org>

Comments (0)

Files changed (3)

examples/debugdevice/Makefile

+FX2LIBDIR=../../
+BASENAME = debugdev
+SOURCES=debugdev.c
+A51_SOURCES=dscr.a51
+PID=0x1004
+
+include $(FX2LIBDIR)lib/fx2.mk
+

examples/debugdevice/debugdev.c

+/**
+ * Copyright (C) 2009 Ubixum, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ **/
+#include <stdio.h>
+
+#include <fx2regs.h>
+#include <fx2macros.h>
+#include <serial.h>
+#include <delay.h>
+#include <autovector.h>
+#include <lights.h>
+#include <setupdat.h>
+#include <eputils.h>
+
+#define SYNCDELAY() SYNCDELAY4
+#define REARMVAL 0x80
+#define REARM() EP2BCL=REARMVAL
+
+volatile WORD bytes;
+volatile __bit gotbuf;
+volatile BYTE icount;
+volatile __bit got_sud;
+DWORD lcount;
+__bit on;
+
+extern code WORD debug_dscr;
+extern void _transchar(char c);
+void main()
+{
+	REVCTL=0; // not using advanced endpoint controls
+
+	d2off();
+	on=0;
+	lcount=0;
+	got_sud=FALSE;
+	icount=0;
+	gotbuf=FALSE;
+	bytes=0;
+
+	// renumerate
+	RENUMERATE_UNCOND();
+
+
+	SETCPUFREQ(CLK_48M);
+	SETIF48MHZ();
+	sio0_init(115200);
+
+
+	USE_USB_INTS();
+	ENABLE_SUDAV();
+	ENABLE_SOF();
+	ENABLE_HISPEED();
+	ENABLE_USBRESET();
+
+
+	// only valid endpoints are 2/6
+	EP2CFG = 0xA2; // 10100010
+	SYNCDELAY();
+	EP6CFG = 0xE2; // 11100010
+	SYNCDELAY();
+	EP1INCFG &= ~bmVALID;
+	SYNCDELAY();
+	EP1OUTCFG &= ~bmVALID;
+	SYNCDELAY();
+	EP4CFG &= ~bmVALID;
+	SYNCDELAY();
+	EP8CFG &= ~bmVALID;
+	SYNCDELAY();
+
+
+	// arm ep2
+	EP2BCL = 0x80; // write once
+	SYNCDELAY();
+	EP2BCL = 0x80; // do it again
+
+
+	// make it so we enumberate
+
+
+	EA=1; // global __interrupt enable
+	printf ( "USB DEBUG: Done initializing stuff\n" );
+
+
+	d3off();
+
+	while(TRUE) {
+
+		if ( got_sud ) {
+			handle_setupdata();
+			got_sud=FALSE;
+		}
+
+		if ( !(EP2468STAT & bmEP2EMPTY) ) {
+			if  ( !(EP2468STAT & bmEP6FULL) ) { // wait for at least one empty in buffer
+				WORD i;
+
+				bytes = MAKEWORD(EP2BCH,EP2BCL);
+
+				for (i=0;i<bytes;++i)
+					_transchar(EP2FIFOBUF[i]);
+				REARM();
+			}
+		}
+	}
+
+}
+
+// copied routines from setupdat.h
+
+// value (low byte) = ep
+#define VC_EPSTAT 0xB1
+
+
+BOOL handle_vendorcommand(BYTE cmd)
+{
+	__xdata BYTE* pep;
+	switch ( cmd ) {
+	case 6:
+		return TRUE;
+	case VC_EPSTAT:
+
+		pep = ep_addr(SETUPDAT[2]);
+		if (pep) {
+			EP0BUF[0] = *pep;
+			EP0BCH=0;
+			EP0BCL=1;
+			return TRUE;
+		}
+	default:
+		printf ( "Need to implement vendor command: %02x\n", cmd );
+	}
+	return FALSE;
+}
+
+// this firmware only supports 0,0
+BOOL handle_get_interface(BYTE ifc, BYTE* alt_ifc)
+{
+//	printf ( "Get Interface\n" );
+	if (ifc==0) {
+		*alt_ifc=0;
+		return TRUE;
+	} else {
+		return FALSE;
+	}
+}
+BOOL handle_set_interface(BYTE ifc, BYTE alt_ifc)
+{
+	if (ifc==0&&alt_ifc==0) {
+		// SEE TRM 2.3.7
+		// reset toggles
+		RESETTOGGLE(0x02);
+		RESETTOGGLE(0x86);
+		// restore endpoints to default condition
+		RESETFIFO(0x02);
+		EP2BCL=0x80;
+		SYNCDELAY();
+		EP2BCL=0X80;
+		SYNCDELAY();
+		RESETFIFO(0x86);
+		return TRUE;
+	} else
+		return FALSE;
+}
+
+// get/set configuration
+BYTE handle_get_configuration()
+{
+	return 1;
+}
+
+BOOL handle_get_descriptor(BYTE desc)
+{
+	if (desc != DSCR_DEBUG_TYPE)
+		return FALSE;
+
+	SUDPTRH = MSB((WORD)&debug_dscr);
+	SUDPTRL = LSB((WORD)&debug_dscr);
+	return TRUE;
+}
+
+BOOL handle_set_configuration(BYTE cfg)
+{
+
+	return cfg==1 ? TRUE : FALSE; // we only handle cfg 1
+}
+
+
+// copied usb jt routines from usbjt.h
+void sudav_isr() __interrupt SUDAV_ISR {
+
+	got_sud=TRUE;
+	CLEAR_SUDAV();
+}
+
+__bit on5;
+__xdata WORD sofct=0;
+void sof_isr () __interrupt SOF_ISR __using 1
+{
+	if(++sofct==8000) { // about 8000 sof __interrupts per second at high speed
+		on5 = !on5;
+		if (on5) {
+			d5on();
+		} else {
+			d5off();
+		}
+		sofct=0;
+	}
+	CLEAR_SOF();
+}
+
+void usbreset_isr() __interrupt USBRESET_ISR
+{
+	handle_hispeed(FALSE);
+	CLEAR_USBRESET();
+}
+void hispeed_isr() __interrupt HISPEED_ISR
+{
+	handle_hispeed(TRUE);
+	CLEAR_HISPEED();
+}
+

examples/debugdevice/dscr.a51

+; Copyright (C) 2009 Ubixum, Inc.
+;
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2.1 of the License, or (at your option) any later version.
+;
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+; this is a the default
+; full speed and high speed
+; descriptors found in the TRM
+; change however you want but leave
+; the descriptor pointers so the setupdat.c file works right
+
+
+.module DEV_DSCR
+
+; descriptor types
+; same as setupdat.h
+DSCR_DEVICE_TYPE=1
+DSCR_CONFIG_TYPE=2
+DSCR_STRING_TYPE=3
+DSCR_INTERFACE_TYPE=4
+DSCR_ENDPOINT_TYPE=5
+DSCR_DEVQUAL_TYPE=6
+
+; for the repeating interfaces
+DSCR_INTERFACE_LEN=9
+DSCR_ENDPOINT_LEN=7
+
+; endpoint types
+ENDPOINT_TYPE_CONTROL=0
+ENDPOINT_TYPE_ISO=1
+ENDPOINT_TYPE_BULK=2
+ENDPOINT_TYPE_INT=3
+
+    .globl	_dev_dscr, _dev_qual_dscr, _highspd_dscr, _fullspd_dscr, _debug_dscr, _dev_strings, _dev_strings_end
+; These need to be in code memory.  If
+; they aren't you'll have to manully copy them somewhere
+; in code memory otherwise SUDPTRH:L don't work right
+    .area	DSCR_AREA	(CODE)
+
+_dev_dscr:
+	.db	dev_dscr_end-_dev_dscr    ; len
+	.db	DSCR_DEVICE_TYPE		  ; type
+	.dw	0x0002					  ; usb 2.0
+	.db	0xff  					  ; class (vendor specific)
+	.db	0					  ; subclass (vendor specific)
+	.db	0					  ; protocol (vendor specific)
+	.db	64						  ; packet size (ep0)
+	.dw	0xb404					  ; vendor id
+	.dw	0x1386					  ; product id
+	.dw	0x0100					  ; version id
+	.db	1					  ; manufacturure str idx
+	.db	2				          ; product str idx
+	.db	0				          ; serial str idx
+	.db	1			              ; n configurations
+dev_dscr_end:
+
+_dev_qual_dscr:
+	.db	dev_qualdscr_end-_dev_qual_dscr
+	.db	DSCR_DEVQUAL_TYPE
+	.dw	0x0002                              ; usb 2.0
+	.db	0xff
+	.db	0x00
+	.db	0x0
+	.db	64                                  ; max packet
+	.db	1									; n configs
+	.db	0									; extra reserved byte
+dev_qualdscr_end:
+
+_debug_dscr:
+	.db	_debug_dscr_end - _debug_dscr
+	.db	10
+	.db	0x86
+	.db	0x02
+_debug_dscr_end:
+
+
+_highspd_dscr:
+	.db	highspd_dscr_end-_highspd_dscr      ; dscr len											;; Descriptor length
+	.db	DSCR_CONFIG_TYPE
+    ; can't use .dw because byte order is different
+	.db	(highspd_dscr_realend-_highspd_dscr) % 256 ; total length of config lsb
+	.db	(highspd_dscr_realend-_highspd_dscr) / 256 ; total length of config msb
+	.db	1								 ; n interfaces
+	.db	1								 ; config number
+	.db	0								 ; config string
+	.db	0x80                             ; attrs = bus powered, no wakeup
+	.db	0x32                             ; max power = 100ma
+highspd_dscr_end:
+
+; all the interfaces next
+; NOTE the default TRM actually has more alt interfaces
+; but you can add them back in if you need them.
+; here, we just use the default alt setting 1 from the trm
+	.db	DSCR_INTERFACE_LEN
+	.db	DSCR_INTERFACE_TYPE
+	.db	0				 ; index
+	.db	0				 ; alt setting idx
+	.db	2				 ; n endpoints
+	.db	0xff			 ; class
+	.db	0
+	.db	0
+	.db	3	             ; string index
+
+; endpoint 2 out
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x02				;  ep2 dir=OUT and address
+	.db	ENDPOINT_TYPE_BULK	; type
+	.db	0x00				; max packet LSB
+	.db	0x02				; max packet size=512 bytes
+	.db	0x00				; polling interval
+
+; endpoint 6 in
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x86				;  ep6 dir=in and address
+	.db	ENDPOINT_TYPE_BULK	; type
+	.db	0x00				; max packet LSB
+	.db	0x02				; max packet size=512 bytes
+	.db	0x00				; polling interval
+
+highspd_dscr_realend:
+
+    .even
+_fullspd_dscr:
+	.db	fullspd_dscr_end-_fullspd_dscr      ; dscr len
+	.db	DSCR_CONFIG_TYPE
+    ; can't use .dw because byte order is different
+	.db	(fullspd_dscr_realend-_fullspd_dscr) % 256 ; total length of config lsb
+	.db	(fullspd_dscr_realend-_fullspd_dscr) / 256 ; total length of config msb
+	.db	1								 ; n interfaces
+	.db	1								 ; config number
+	.db	0								 ; config string
+	.db	0x80                             ; attrs = bus powered, no wakeup
+	.db	0x32                             ; max power = 100ma
+fullspd_dscr_end:
+
+; all the interfaces next
+; NOTE the default TRM actually has more alt interfaces
+; but you can add them back in if you need them.
+; here, we just use the default alt setting 1 from the trm
+	.db	DSCR_INTERFACE_LEN
+	.db	DSCR_INTERFACE_TYPE
+	.db	0				 ; index
+	.db	0				 ; alt setting idx
+	.db	2				 ; n endpoints
+	.db	0xff			 ; class
+	.db	0xff
+	.db	0xff
+	.db	3	             ; string index
+
+; endpoint 2 out
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x02				;  ep2 dir=OUT and address
+	.db	ENDPOINT_TYPE_BULK	; type
+	.db	0x40				; max packet LSB
+	.db	0x00				; max packet size=64 bytes
+	.db	0x00				; polling interval
+
+; endpoint 6 in
+	.db	DSCR_ENDPOINT_LEN
+	.db	DSCR_ENDPOINT_TYPE
+	.db	0x86				;  ep6 dir=in and address
+	.db	ENDPOINT_TYPE_BULK	; type
+	.db	0x40				; max packet LSB
+	.db	0x00				; max packet size=64 bytes
+	.db	0x00				; polling interval
+
+fullspd_dscr_realend:
+
+.even
+_dev_strings:
+; sample string
+_string0:
+	.db	string0end-_string0 ; len
+	.db	DSCR_STRING_TYPE
+    .db 0x09, 0x04     ; who knows
+string0end:
+; add more strings here
+
+_string1:
+    .db string1end-_string1
+    .db DSCR_STRING_TYPE
+    .ascii 'N'
+    .db 0
+    .ascii 'o'
+    .db 0
+    .ascii 'n'
+    .db 0
+    .ascii 'e'
+    .db 0
+string1end:
+
+_string2:
+    .db string2end-_string2
+    .db DSCR_STRING_TYPE
+    .ascii 'E'
+    .db 0
+    .ascii 'H'
+    .db 0
+    .ascii 'C'
+    .db 0
+    .ascii 'I'
+    .db 0
+    .ascii ' '
+    .db 0
+    .ascii 'D'
+    .db 0
+    .ascii 'e'
+    .db 0
+    .ascii 'b'
+    .db 0
+    .ascii 'u'
+    .db 0
+    .ascii 'g'
+    .db 0
+    .ascii ' '
+    .db 0
+    .ascii 'c'
+    .db 0
+    .ascii 'a'
+    .db 0
+    .ascii 'b'
+    .db 0
+    .ascii 'l'
+    .db 0
+    .ascii 'e'
+    .db 0
+string2end:
+
+_string3:
+    .db string3end-_string3
+    .db DSCR_STRING_TYPE
+    .ascii 'i'
+    .db 0
+    .ascii 'F'
+    .db 0
+    .ascii 'a'
+    .db 0
+    .ascii 'c'
+    .db 0
+    .ascii 'e'
+    .db 0
+string3end:
+
+_dev_strings_end:
+    .dw 0x0000   ; just in case someone passes an index higher than the end to the firmware