diff options
| -rw-r--r-- | ccload/Makefile.am | 4 | ||||
| -rw-r--r-- | configure.ac | 4 | ||||
| -rw-r--r-- | lib/Makefile.am | 5 | ||||
| -rw-r--r-- | lib/ccdbg-command.c | 2 | ||||
| -rw-r--r-- | lib/ccdbg-debug.h | 44 | ||||
| -rw-r--r-- | lib/ccdbg-io.c | 70 | ||||
| -rw-r--r-- | lib/ccdbg-manual.c | 2 | ||||
| -rw-r--r-- | lib/ccdbg.h | 48 | ||||
| -rw-r--r-- | lib/cp-usb-async.c | 176 | ||||
| -rw-r--r-- | lib/cp-usb-async.h | 38 | ||||
| -rw-r--r-- | s51/Makefile.am | 4 | 
11 files changed, 344 insertions, 53 deletions
| diff --git a/ccload/Makefile.am b/ccload/Makefile.am index f54f4aaa..3a754b23 100644 --- a/ccload/Makefile.am +++ b/ccload/Makefile.am @@ -1,10 +1,10 @@  bin_PROGRAMS=ccload -AM_CFLAGS=-I$(top_srcdir)/lib +AM_CFLAGS=-I$(top_srcdir)/lib $(LIBUSB_CFLAGS)  CCLOAD_LIBS=../lib/libcc.a  ccload_DEPENDENCIES = $(CCLOAD_LIBS) -ccload_LDADD=$(CCLOAD_LIBS) $(USB_LIBS) +ccload_LDADD=$(CCLOAD_LIBS) $(LIBUSB_LIBS)  ccload_SOURCES = ccload.c diff --git a/configure.ac b/configure.ac index a14c802b..3ae80522 100644 --- a/configure.ac +++ b/configure.ac @@ -30,7 +30,9 @@ AC_PROG_CC  AC_PROG_INSTALL  AC_PROG_LN_S  AC_PROG_RANLIB +PKG_PROG_PKG_CONFIG +CFLAGS="-g"  WARN_CFLAGS=""  if test "x$GCC" = "xyes"; then  	WARN_CFLAGS="-Wall -Wpointer-arith -Wstrict-prototypes \ @@ -57,6 +59,8 @@ fi  AC_MSG_RESULT([$CC_FOR_BUILD])  AC_SUBST(CC_FOR_BUILD) +PKG_CHECK_MODULES([LIBUSB], [libusb-1.0]) +  AC_MSG_CHECKING([for suffix of executable build tools])  if test $cross_compiling = yes; then    cat >conftest.c <<\_______EOF diff --git a/lib/Makefile.am b/lib/Makefile.am index a5e5932b..16f5b921 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -1,6 +1,6 @@  noinst_LIBRARIES = libcc.a -AM_CFLAGS=$(WARN_CFLAGS) +AM_CFLAGS=$(WARN_CFLAGS) $(LIBUSB_CFLAGS)  libcc_a_SOURCES = \  	ccdbg-command.c \ @@ -11,4 +11,5 @@ libcc_a_SOURCES = \  	ccdbg-io.c \  	ccdbg-manual.c \  	ccdbg-memory.c \ -	cp-usb.c +	cp-usb.c \ +	cp-usb-async.c diff --git a/lib/ccdbg-command.c b/lib/ccdbg-command.c index 30f5094d..2b29fdee 100644 --- a/lib/ccdbg-command.c +++ b/lib/ccdbg-command.c @@ -31,6 +31,7 @@ ccdbg_debug_mode(struct ccdbg *dbg)  	ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N,          CC_DATA           );  	ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA           );  	ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N,          CC_DATA|CC_RESET_N); +	ccdbg_sync_io(dbg);  }  void @@ -45,6 +46,7 @@ ccdbg_reset(struct ccdbg *dbg)  	ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA           );  	ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA           );  	ccdbg_send(dbg, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); +	ccdbg_sync_io(dbg);  }  uint8_t diff --git a/lib/ccdbg-debug.h b/lib/ccdbg-debug.h new file mode 100644 index 00000000..a09148d3 --- /dev/null +++ b/lib/ccdbg-debug.h @@ -0,0 +1,44 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _CCDBG_DEBUG_H_ +#define _CCDBG_DEBUG_H_ +/* Debug levels + */ +#define CC_DEBUG_BITBANG	0x00000001 +#define CC_DEBUG_COMMAND	0x00000002 +#define CC_DEBUG_INSTRUCTIONS	0x00000004 +#define CC_DEBUG_EXECUTE	0x00000008 +#define CC_DEBUG_FLASH		0x00000010 +#define CC_DEBUG_MEMORY		0x00000020 +#define CC_DEBUG_USB_ASYNC	0x00000040 + +/* ccdbg-debug.c */ +void +ccdbg_debug(int level, char *format, ...); + +void +ccdbg_add_debug(int level); + +void +ccdbg_clear_debug(int level); + +void +ccdbg_flush(void); + +#endif /* _CCDBG_DEBUG_H_ */ diff --git a/lib/ccdbg-io.c b/lib/ccdbg-io.c index 5ecea769..53ea7583 100644 --- a/lib/ccdbg-io.c +++ b/lib/ccdbg-io.c @@ -18,6 +18,11 @@  #include "ccdbg.h"  #include <time.h> +#ifdef CP_USB_ASYNC +#include "cp-usb-async.h" +#else +#include "cp-usb.h" +#endif  void  ccdbg_half_clock(struct ccdbg *dbg) @@ -38,32 +43,60 @@ ccdbg_open(void)  		perror("calloc");  		return NULL;  	} +#ifdef CP_USB_ASYNC +	dbg->cp_async = cp_usb_async_open(); +	if (!dbg->cp_async) { +		free (dbg); +		return NULL; +	} +#else  	dbg->cp = cp_usb_open ();  	if (!dbg->cp) {  		free (dbg);  		return NULL;  	} +#endif  	return dbg;  }  void  ccdbg_close(struct ccdbg *dbg)  { +#ifdef CP_USB_ASYNC +	cp_usb_async_close(dbg->cp_async); +#else  	cp_usb_close(dbg->cp); +#endif  	free (dbg);  }  int  ccdbg_write(struct ccdbg *dbg, uint8_t mask, uint8_t value)  { +#ifdef CP_USB_ASYNC +	cp_usb_async_write(dbg->cp_async, mask, value); +#else  	cp_usb_write(dbg->cp, mask, value); +#endif  	return 0;  } -uint8_t -ccdbg_read(struct ccdbg *dbg) +void +ccdbg_read(struct ccdbg *dbg, uint8_t *valuep) +{ +#ifdef CP_USB_ASYNC +	cp_usb_async_read(dbg->cp_async, valuep); +#else +	*valuep = cp_usb_read(dbg->cp); +#endif +} + +void +ccdbg_sync_io(struct ccdbg *dbg)  { -	return cp_usb_read(dbg->cp); +#ifdef CP_USB_ASYNC +	cp_usb_async_sync(dbg->cp_async); +#endif  }  static char @@ -112,6 +145,7 @@ ccdbg_send_byte(struct ccdbg *dbg, uint8_t byte)  		if (bit == 3)  			ccdbg_debug(CC_DEBUG_BITBANG, "\n");  	} +	ccdbg_sync_io(dbg);  }  void @@ -121,43 +155,47 @@ ccdbg_send_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes)  		ccdbg_send_byte(dbg, *bytes++);  } -uint8_t -ccdbg_recv_bit(struct ccdbg *dbg, int first) +void +ccdbg_recv_bit(struct ccdbg *dbg, int first, uint8_t *bit)  {  	uint8_t mask = first ? CC_DATA : 0; -	uint8_t read;  	ccdbg_send(dbg, CC_CLOCK|mask|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); -	read = ccdbg_read(dbg); -	ccdbg_print("#\t%c %c %c\n", CC_DATA, read); +	ccdbg_read(dbg, bit);  	ccdbg_send(dbg, CC_CLOCK|     CC_RESET_N,                  CC_RESET_N); -	return (read & CC_DATA) ? 1 : 0;  } -uint8_t -ccdbg_recv_byte(struct ccdbg *dbg, int first) +void +ccdbg_recv_byte(struct ccdbg *dbg, int first, uint8_t *bytep)  {  	uint8_t byte = 0; +	uint8_t bits[8];  	int	bit;  	ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Recv byte\n#\n");  	for (bit = 0; bit < 8; bit++) { +		ccdbg_recv_bit(dbg, first, &bits[bit]); +		first = 0; +	} +	ccdbg_sync_io(dbg); +	for (bit = 0; bit < 8; bit++) {  		byte = byte << 1; -		byte |= ccdbg_recv_bit(dbg, first); +		byte |= (bits[bit] & CC_DATA) ? 1 : 0; +		ccdbg_print("#\t%c %c %c\n", CC_DATA, bits[bit]);  		if (bit == 3)  			ccdbg_debug(CC_DEBUG_BITBANG, "\n"); -		first = 0;  	}  	ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Recv 0x%02x\n#\n", byte); -	return byte; +	*bytep = byte;  }  void  ccdbg_recv_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes)  { +	int i;  	int first = 1; -	while (nbytes--) { -		*bytes++ = ccdbg_recv_byte(dbg, first); +	for (i = 0; i < nbytes; i++) { +		ccdbg_recv_byte(dbg, first, &bytes[i]);  		first = 0;  	}  } diff --git a/lib/ccdbg-manual.c b/lib/ccdbg-manual.c index b83dc450..b48f8bb1 100644 --- a/lib/ccdbg-manual.c +++ b/lib/ccdbg-manual.c @@ -59,7 +59,7 @@ ccdbg_manual(struct ccdbg *dbg, FILE *input)  		get_bit(line, 4, 'R', CC_RESET_N, &set, &mask);  		if (mask != (CC_CLOCK|CC_DATA|CC_RESET_N)) {  			uint8_t	read; -			read = ccdbg_read(dbg); +			ccdbg_read(dbg, &read);  			ccdbg_print("\t%c %c %c", CC_CLOCK|CC_DATA|CC_RESET_N, read);  			if ((set & CC_CLOCK) == 0)  				printf ("\t%d", (read&CC_DATA) ? 1 : 0); diff --git a/lib/ccdbg.h b/lib/ccdbg.h index e0e58104..834092b2 100644 --- a/lib/ccdbg.h +++ b/lib/ccdbg.h @@ -30,11 +30,12 @@  #include <sys/types.h>  #include <sys/ioctl.h>  #include <sys/stat.h> -#include "cp-usb.h" +#include "ccdbg-debug.h" +  #define CC_CLOCK	0x1  #define CC_DATA		0x2  #define CC_RESET_N	0x4 -#define CC_CLOCK_US	(40) +#define CC_CLOCK_US	(0)  /* 8051 instructions   */ @@ -90,8 +91,14 @@  /* Bit-addressable accumulator */  #define ACC(bit)		(0xE0 | (bit)) +#define CP_USB_ASYNC +  struct ccdbg { +#ifdef CP_USB_ASYNC +	struct cp_usb_async *cp_async; +#else  	struct cp_usb *cp; +#endif  };  /* Intel hex file format data @@ -153,15 +160,6 @@ struct hex_image {  #define CC_STEP_REPLACE(n)	(0x64|(n))  #define CC_GET_CHIP_ID		0x68 -/* Debug levels - */ -#define CC_DEBUG_BITBANG	0x00000001 -#define CC_DEBUG_COMMAND	0x00000002 -#define CC_DEBUG_INSTRUCTIONS	0x00000004 -#define CC_DEBUG_EXECUTE	0x00000008 -#define CC_DEBUG_FLASH		0x00000010 -#define CC_DEBUG_MEMORY		0x00000020 -  /* ccdbg-command.c */  void  ccdbg_debug_mode(struct ccdbg *dbg); @@ -214,19 +212,6 @@ ccdbg_set_pc(struct ccdbg *dbg, uint16_t pc);  uint8_t  ccdbg_execute_hex_image(struct ccdbg *dbg, struct hex_image *image); -/* ccdbg-debug.c */ -void -ccdbg_debug(int level, char *format, ...); - -void -ccdbg_add_debug(int level); - -void -ccdbg_clear_debug(int level); - -void -ccdbg_flush(void); -  /* ccdbg-flash.c */  uint8_t  ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image); @@ -254,8 +239,8 @@ ccdbg_half_clock(struct ccdbg *dbg);  int  ccdbg_write(struct ccdbg *dbg, uint8_t mask, uint8_t value); -uint8_t -ccdbg_read(struct ccdbg *dbg); +void +ccdbg_read(struct ccdbg *dbg, uint8_t *valuep);  struct ccdbg *  ccdbg_open(void); @@ -302,16 +287,19 @@ ccdbg_send_byte(struct ccdbg *dbg, uint8_t byte);  void  ccdbg_send_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes); -uint8_t -ccdbg_recv_bit(struct ccdbg *dbg, int first); +void +ccdbg_recv_bit(struct ccdbg *dbg, int first, uint8_t *bit); -uint8_t -ccdbg_recv_byte(struct ccdbg *dbg, int first); +void +ccdbg_recv_byte(struct ccdbg *dbg, int first, uint8_t *byte);  void  ccdbg_recv_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes);  void +ccdbg_sync_io(struct ccdbg *dbg); + +void  ccdbg_print(char *format, uint8_t mask, uint8_t set);  /* ccdbg-manual.c */ diff --git a/lib/cp-usb-async.c b/lib/cp-usb-async.c new file mode 100644 index 00000000..3f5f76ab --- /dev/null +++ b/lib/cp-usb-async.c @@ -0,0 +1,176 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <unistd.h> +#include "cp-usb-async.h" +#include "ccdbg-debug.h" + +#define MAX_OUTSTANDING		256 +#define CP_TIMEOUT		1000	/* ms */ + +struct cp_usb_packet { +	struct libusb_transfer	*transfer; +	enum { packet_read, packet_write } direction; +	unsigned char		data[9]; +	uint8_t			*valuep; +}; + +struct cp_usb_async { +	libusb_context		*ctx; +	libusb_device_handle	*handle; +	struct cp_usb_packet	packet[MAX_OUTSTANDING]; +	int			p, ack; +}; + +struct cp_usb_async * +cp_usb_async_open(void) +{ +	struct cp_usb_async *cp; +	int ret; + +	cp = calloc(sizeof (struct cp_usb_async), 1); +	if (!cp) +		return NULL; +	ret = libusb_init(&cp->ctx); +	if (ret) { +		free(cp); +		return NULL; +	} +	cp->handle = libusb_open_device_with_vid_pid(cp->ctx, +						     0x10c4, 0xea60); +	if (!cp->handle) { +		libusb_exit(cp->ctx); +		free(cp); +		return NULL; +	} +	return cp; +} + +void +cp_usb_async_close(struct cp_usb_async *cp) +{ +	libusb_close(cp->handle); +	libusb_exit(cp->ctx); +	free(cp); +} + +static void +cp_usb_async_transfer_callback(struct libusb_transfer *transfer) +{ +	struct cp_usb_async *cp = transfer->user_data; +	int p; + +	for (p = 0; p < cp->p; p++) +		if (cp->packet[p].transfer == transfer) +			break; +	if (p == cp->p) { +		fprintf(stderr, "unknown transfer\n"); +		return; +	} +	switch (cp->packet[p].direction) { +	case packet_read: +		ccdbg_debug(CC_DEBUG_USB_ASYNC, "ack read %d 0x%02x\n", +			    p, cp->packet[p].data[8]); +		*cp->packet[p].valuep = cp->packet[p].data[8]; +		break; +	case packet_write: +		ccdbg_debug(CC_DEBUG_USB_ASYNC, "ack write %d\n", p); +		break; +	} +	if (p > cp->ack) +		cp->ack = p; +} + +void +cp_usb_async_write(struct cp_usb_async *cp, uint8_t mask, uint8_t value) +{ +	int	p; +	uint16_t gpio_set = ((uint16_t) value << 8) | mask; +	int	ret; + +	if (cp->p == MAX_OUTSTANDING) +		cp_usb_async_sync(cp); +	p = cp->p; +	if (!cp->packet[p].transfer) +		cp->packet[p].transfer = libusb_alloc_transfer(0); +	cp->packet[p].direction = packet_write; +	libusb_fill_control_setup(cp->packet[p].data, +				  0x40,			/* request */ +				  0xff,			/* request type */ +				  0x37e1,		/* value */ +				  gpio_set,		/* index */ +				  0);			/* length */ +	 +	libusb_fill_control_transfer(cp->packet[p].transfer, +				     cp->handle, +				     cp->packet[p].data, +				     cp_usb_async_transfer_callback, +				     cp, +				     CP_TIMEOUT); +	ccdbg_debug(CC_DEBUG_USB_ASYNC, "Write packet %d 0x%x 0x%x\n", p, mask, value); +	ret = libusb_submit_transfer(cp->packet[p].transfer); +	if (ret) +		fprintf(stderr, "libusb_submit_transfer failed %d\n", ret); +	cp->p++; +} + +void +cp_usb_async_read(struct cp_usb_async *cp, uint8_t *valuep) +{ +	int	p; +	int	ret; + +	if (cp->p == MAX_OUTSTANDING) +		cp_usb_async_sync(cp); +	p = cp->p; +	if (!cp->packet[p].transfer) +		cp->packet[p].transfer = libusb_alloc_transfer(0); +	cp->packet[p].valuep = valuep; +	cp->packet[p].direction = packet_read; +	libusb_fill_control_setup(cp->packet[p].data, +				  0xc0,			/* request */ +				  0xff,			/* request type */ +				  0x00c2,		/* value */ +				  0,			/* index */ +				  1);			/* length */ +	 +	libusb_fill_control_transfer(cp->packet[p].transfer, +				     cp->handle, +				     cp->packet[p].data, +				     cp_usb_async_transfer_callback, +				     cp, +				     CP_TIMEOUT); +	ccdbg_debug(CC_DEBUG_USB_ASYNC, "Read packet %d\n", p); +	ret = libusb_submit_transfer(cp->packet[p].transfer); +	if (ret) +		fprintf(stderr, "libusb_submit_transfer failed %d\n", ret); +	cp->p++; +} + +void +cp_usb_async_sync(struct cp_usb_async *cp) +{ +	while (cp->ack < cp->p - 1) { +		libusb_handle_events(cp->ctx); +	} +	cp->p = 0; +	cp->ack = 0; +} diff --git a/lib/cp-usb-async.h b/lib/cp-usb-async.h new file mode 100644 index 00000000..976a320e --- /dev/null +++ b/lib/cp-usb-async.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2008 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _CP_USB_ASYNC_H_ +#define _CP_USB_ASYNC_H_ +#include <libusb.h> + +struct cp_usb_async * +cp_usb_async_open(void); + +void +cp_usb_async_close(struct cp_usb_async *cp); + +void +cp_usb_async_write(struct cp_usb_async *cp, uint8_t mask, uint8_t value); + +void +cp_usb_async_read(struct cp_usb_async *cp, uint8_t *valuep); + +void +cp_usb_async_sync(struct cp_usb_async *cp); + +#endif diff --git a/s51/Makefile.am b/s51/Makefile.am index cfa183d4..fa6fc692 100644 --- a/s51/Makefile.am +++ b/s51/Makefile.am @@ -1,10 +1,10 @@  bin_PROGRAMS=s51 -AM_CFLAGS=-I$(top_srcdir)/lib +AM_CFLAGS=-I$(top_srcdir)/lib $(LIBUSB_CFLAGS)  S51_LIBS=../lib/libcc.a  s51_DEPENDENCIES = $(S51_LIBS) -s51_LDADD=$(S51_LIBS) $(USB_LIBS) +s51_LDADD=$(S51_LIBS) $(LIBUSB_LIBS)  s51_SOURCES = s51-parse.c s51-command.c s51-main.c | 
