From 9025eb792861930e6af918d2727c4f5d97a69936 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 19 Dec 2008 21:11:45 -0800 Subject: Autotools. Signed-off-by: Keith Packard --- ccload/Makefile.am | 10 +++++++ ccload/ccload.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 ccload/Makefile.am create mode 100644 ccload/ccload.c (limited to 'ccload') diff --git a/ccload/Makefile.am b/ccload/Makefile.am new file mode 100644 index 00000000..f54f4aaa --- /dev/null +++ b/ccload/Makefile.am @@ -0,0 +1,10 @@ +bin_PROGRAMS=ccload + +AM_CFLAGS=-I$(top_srcdir)/lib +CCLOAD_LIBS=../lib/libcc.a + +ccload_DEPENDENCIES = $(CCLOAD_LIBS) + +ccload_LDADD=$(CCLOAD_LIBS) $(USB_LIBS) + +ccload_SOURCES = ccload.c diff --git a/ccload/ccload.c b/ccload/ccload.c new file mode 100644 index 00000000..b4bb1443 --- /dev/null +++ b/ccload/ccload.c @@ -0,0 +1,78 @@ +/* + * Copyright © 2008 Keith Packard + * + * 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 "ccdbg.h" + +int +main (int argc, char **argv) +{ + struct ccdbg *dbg; + uint8_t status; + uint16_t pc; + struct hex_file *hex; + struct hex_image *image; + char *filename; + FILE *file; + + filename = argv[1]; + if (filename == NULL) { + fprintf(stderr, "usage: %s \n", argv[0]); + exit(1); + } + file = fopen(filename, "r"); + if (!file) { + perror(filename); + exit(1); + } + hex = ccdbg_hex_file_read(file, filename); + fclose(file); + if (!hex) + exit (1); + image = ccdbg_hex_image_create(hex); + if (!image) { + fprintf(stderr, "image create failed\n"); + exit (1); + } + + ccdbg_hex_file_free(hex); + dbg = ccdbg_open(); + if (!dbg) + exit (1); + + ccdbg_debug_mode(dbg); + ccdbg_halt(dbg); + if (image->address == 0xf000) { + printf("Loading %d bytes to execute from RAM\n", + image->length); + ccdbg_write_hex_image(dbg, image, 0); + } else if (image->address == 0x0000) { + printf("Loading %d bytes to execute from FLASH\n", + image->length); + ccdbg_flash_hex_image(dbg, image); + } else { + printf("Cannot load code to 0x%04x\n", + image->address); + ccdbg_hex_image_free(image); + ccdbg_close(dbg); + exit(1); + } + ccdbg_set_pc(dbg, image->address); + ccdbg_resume(dbg); + ccdbg_close(dbg); + exit (0); +} -- cgit v1.2.3 From 30f23f23a6db3d12fdc9c088cf6ab47c5e5077fb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 19 Dec 2008 21:13:04 -0800 Subject: Clean up autotools stuff. Signed-off-by: Keith Packard --- .gitignore | 32 +++++++++-------- ccload/.gitignore | 1 + configure.ac | 95 +++++++++++++++++++++++++++++++++++++++++++++++++ target/blink/.gitignore | 13 +++++++ 4 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 ccload/.gitignore create mode 100644 configure.ac create mode 100644 target/blink/.gitignore (limited to 'ccload') diff --git a/.gitignore b/.gitignore index 4db91cd2..93d05b7f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,20 @@ -ccdbg -*.ihx -blink-flash -blink-ram *.o +*.a +.deps tags -*.adb -*.asm -*.cdb -*.lnk -*.lst -*.map -*.mem -*.rel -*.rst -*.sym +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +config.h +config.h.in +config.h.in~ +config.log +config.status +configure +depcomp +install-sh +Makefile.in +missing +stamp-h1 + diff --git a/ccload/.gitignore b/ccload/.gitignore new file mode 100644 index 00000000..3899747a --- /dev/null +++ b/ccload/.gitignore @@ -0,0 +1 @@ +ccload diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..6182d71c --- /dev/null +++ b/configure.ac @@ -0,0 +1,95 @@ +dnl +dnl Copyright © 2008 Keith Packard +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License along +dnl with this program; if not, write to the Free Software Foundation, Inc., +dnl 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +dnl +dnl Process this file with autoconf to create configure. + +AC_INIT(COPYING) + +AM_INIT_AUTOMAKE(cctools, 0.1) +AM_MAINTAINER_MODE + +dnl ========================================================================== + +AM_CONFIG_HEADER(config.h) + +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_RANLIB + +WARN_CFLAGS="" +if test "x$GCC" = "xyes"; then + WARN_CFLAGS="-Wall -Wpointer-arith -Wstrict-prototypes \ + -Wmissing-prototypes -Wmissing-declarations \ + -Wnested-externs -fno-strict-aliasing" + AC_DEFINE_UNQUOTED(HAVE_WARNING_CPP_DIRECTIVE,1, + [Can use #warning in C files]) +fi +AC_SUBST(WARN_CFLAGS) + +dnl ========================================================================== + +AM_CONDITIONAL(CROSS_COMPILING, test $cross_compiling = yes) + +dnl ========================================================================== + +# Setup for compiling build tools (fc-glyphname, etc) +AC_MSG_CHECKING([for a C compiler for build tools]) +if test $cross_compiling = yes; then + AC_CHECK_PROGS(CC_FOR_BUILD, gcc cc) +else + CC_FOR_BUILD=$CC +fi +AC_MSG_RESULT([$CC_FOR_BUILD]) +AC_SUBST(CC_FOR_BUILD) + +AC_MSG_CHECKING([for suffix of executable build tools]) +if test $cross_compiling = yes; then + cat >conftest.c <<\_______EOF +int +main () +{ + exit (0); +} +_______EOF + for i in .exe ""; do + compile="$CC_FOR_BUILD conftest.c -o conftest$i" + if AC_TRY_EVAL(compile); then + if (./conftest) 2>&AC_FD_CC; then + EXEEXT_FOR_BUILD=$i + break + fi + fi + done + rm -f conftest* + if test "${EXEEXT_FOR_BUILD+set}" != set; then + AC_MSG_ERROR([Cannot determine suffix of executable build tools]) + fi +else + EXEEXT_FOR_BUILD=$EXEEXT +fi +AC_MSG_RESULT([$EXEEXT_FOR_BUILD]) +AC_SUBST(EXEEXT_FOR_BUILD) + +USB_LIBS="-lusb" +AC_SUBST(USB_LIBS) + +AC_OUTPUT([ +Makefile +lib/Makefile +ccload/Makefile +]) diff --git a/target/blink/.gitignore b/target/blink/.gitignore new file mode 100644 index 00000000..40f72de9 --- /dev/null +++ b/target/blink/.gitignore @@ -0,0 +1,13 @@ +*.ihx +*.adb +*.asm +*.cdb +*.lnk +*.lst +*.map +*.mem +*.rel +*.rst +*.sym +blink-flash +blink-ram -- cgit v1.2.3 From 1264c3676e95427bba5d01e05c303d036a7f9eca Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 26 Dec 2008 23:05:04 -0800 Subject: Switch to libusb-1.0 and use async interface. The async libusb interface offers substantial performance benefits by not making each command wait for the reply. This makes talking over this interface almost reasonable. Signed-off-by: Keith Packard --- ccload/Makefile.am | 4 +- configure.ac | 4 ++ lib/Makefile.am | 5 +- lib/ccdbg-command.c | 2 + lib/ccdbg-debug.h | 44 +++++++++++++ lib/ccdbg-io.c | 70 ++++++++++++++++----- lib/ccdbg-manual.c | 2 +- lib/ccdbg.h | 48 ++++++-------- lib/cp-usb-async.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/cp-usb-async.h | 38 ++++++++++++ s51/Makefile.am | 4 +- 11 files changed, 344 insertions(+), 53 deletions(-) create mode 100644 lib/ccdbg-debug.h create mode 100644 lib/cp-usb-async.c create mode 100644 lib/cp-usb-async.h (limited to 'ccload') 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 + * + * 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 +#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 #include #include -#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,15 +287,18 @@ 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); 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 + * + * 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 +#include +#include +#include +#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 + * + * 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 + +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 -- cgit v1.2.3 From ea366058aa467a8a7caf17e7014758f3741ea7f7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 29 Dec 2008 12:35:11 -0800 Subject: Fix flashing less than a full page of data. Verify page at a time. The 8051 flashing code requires special help with counts with non-zero low byte. Also, instead of verifying the entire flash contents at the end, verify each page as it goes. Signed-off-by: Keith Packard --- ccload/ccload.c | 2 ++ lib/ccdbg-flash.c | 61 ++++++++++++++++++++++++++++++++------------------- target/blink/Makefile | 2 ++ 3 files changed, 42 insertions(+), 23 deletions(-) (limited to 'ccload') diff --git a/ccload/ccload.c b/ccload/ccload.c index b4bb1443..3e220914 100644 --- a/ccload/ccload.c +++ b/ccload/ccload.c @@ -54,6 +54,8 @@ main (int argc, char **argv) if (!dbg) exit (1); + ccdbg_add_debug(CC_DEBUG_FLASH); + ccdbg_debug_mode(dbg); ccdbg_halt(dbg); if (image->address == 0xf000) { diff --git a/lib/ccdbg-flash.c b/lib/ccdbg-flash.c index f950dd1b..8b3390c7 100644 --- a/lib/ccdbg-flash.c +++ b/lib/ccdbg-flash.c @@ -244,13 +244,16 @@ ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image) uint16_t flash_prog; uint16_t flash_len; uint8_t fwt; + uint16_t flash_addr; uint16_t flash_word_addr; uint16_t flash_words; + uint8_t flash_words_high, flash_words_low; uint16_t ram_addr; uint16_t pc; uint8_t status; uint16_t remain, this_time, start; uint8_t verify[0x400]; + int times; ccdbg_clock_init(dbg); if (image->address + image->length > 0x8000) { @@ -286,52 +289,64 @@ ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image) ccdbg_debug(CC_DEBUG_FLASH, "Upload %d bytes at 0x%04x\n", this_time, ram_addr); ccdbg_write_memory(dbg, ram_addr, image->data + start, this_time); - ccdbg_debug(CC_DEBUG_FLASH, "Verify %d bytes\n", image->length); + ccdbg_debug(CC_DEBUG_FLASH, "Verify %d bytes in ram\n", this_time); ccdbg_read_memory(dbg, ram_addr, verify, this_time); if (memcmp (image->data + start, verify, this_time) != 0) { - fprintf(stderr, "image verify failed\n"); + fprintf(stderr, "ram verify failed\n"); return 1; } - flash_word_addr = (image->address + start) >> 1; + flash_addr = image->address + start; + flash_word_addr = flash_addr >> 1; flash_len = this_time + (this_time & 1); flash_words = flash_len >> 1; + flash_words_low = flash_words & 0xff; + flash_words_high = flash_words >> 8; + + /* The flash code above is lame */ + if (flash_words_low) + flash_words_high++; + ccdbg_write_uint8(dbg, flash_prog + FLASH_ADDR_HIGH, flash_word_addr >> 8); ccdbg_write_uint8(dbg, flash_prog + FLASH_ADDR_LOW, flash_word_addr & 0xff); ccdbg_write_uint8(dbg, flash_prog + RAM_ADDR_HIGH, ram_addr >> 8); ccdbg_write_uint8(dbg, flash_prog + RAM_ADDR_LOW, ram_addr & 0xff); - ccdbg_write_uint8(dbg, flash_prog + FLASH_WORDS_HIGH, flash_words >> 8); - ccdbg_write_uint8(dbg, flash_prog + FLASH_WORDS_LOW, flash_words & 0xff); + ccdbg_write_uint8(dbg, flash_prog + FLASH_WORDS_HIGH, flash_words_high); + ccdbg_write_uint8(dbg, flash_prog + FLASH_WORDS_LOW, flash_words_low); ccdbg_set_pc(dbg, flash_prog); pc = ccdbg_get_pc(dbg); - ccdbg_debug(CC_DEBUG_FLASH, "Starting flash program at 0x%04x\n", pc); + ccdbg_debug(CC_DEBUG_FLASH, "Flashing %d bytes at 0x%04x\n", + this_time, flash_addr); status = ccdbg_resume(dbg); - ccdbg_debug(CC_DEBUG_FLASH, "resume status is 0x%02x\n", status); - do { + for (times = 0; times < 10; times++) { status = ccdbg_read_status(dbg); ccdbg_debug(CC_DEBUG_FLASH, "chip status is 0x%02x\n", status); - sleep(1); - } while ((status & CC_STATUS_CPU_HALTED) == 0); + if ((status & CC_STATUS_CPU_HALTED) != 0) + break; + } + if (times == 10) { + fprintf(stderr, "flash page timed out\n"); + return 1; + } + ccdbg_debug(CC_DEBUG_FLASH, "Verify %d bytes in flash\n", this_time); + ccdbg_read_memory(dbg, flash_addr, verify, this_time); + if (memcmp (image->data + start, verify, this_time) != 0) { + int i; + fprintf(stderr, "flash verify failed\n"); + for (i = 0; i < this_time; i++) { + if (image->data[start + i] != verify[i]) + fprintf(stderr, "0x%04x: 0x%02x != 0x%02x\n", + start + i, image->data[start+i], verify[i]); + } + return 1; + } remain -= this_time; start += this_time; } -#if 1 - ccdbg_debug(CC_DEBUG_FLASH, "Downloading flash to check\n"); - struct hex_image *test_image; - test_image = ccdbg_read_hex_image(dbg, image->address, image->length); - if (!ccdbg_hex_image_equal(image, test_image)) { - int i; - fprintf(stderr, "Image not loaded\n"); - for (i = 0;i < 0x10; i++) - ccdbg_debug(CC_DEBUG_FLASH, "0x%02x : 0x%02x\n", image->data[i], test_image->data[i]); - return 1; - } - return 0; -#endif return 0; } diff --git a/target/blink/Makefile b/target/blink/Makefile index 1f18f529..4c9b4102 100644 --- a/target/blink/Makefile +++ b/target/blink/Makefile @@ -42,3 +42,5 @@ blink-flash.ihx: blink-ram.ihx clean: rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + +install: -- cgit v1.2.3