From: Keith Packard Date: Thu, 4 Jun 2009 18:13:15 +0000 (-0700) Subject: Merge ccdbg and altos sources into one giant repository X-Git-Tag: 0.5~58 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=17d2432a8b9c15963cd3b821f025ad33972ef477;hp=-c Merge ccdbg and altos sources into one giant repository Keeping these separate isn't making things any easier. Signed-off-by: Keith Packard --- 17d2432a8b9c15963cd3b821f025ad33972ef477 diff --combined .gitignore index 190ba2fd,93d05b7f..71b0a614 --- a/.gitignore +++ b/.gitignore @@@ -1,32 -1,20 +1,44 @@@ -*.o + *.a +*.adb +*.asm - *.lst - *.ihx - *.rel - *.sym - *.rst +*.cdb ++*.ihx +*.lnk ++*.lst +*.map +*.mem - telemetrum - teleterra - tidongle - teledongle ++*.o ++*.rel ++*.rst ++*.sym + .deps -tags -Makefile -Makefile.in + aclocal.m4 +ao_flight_test ++ao-teledongle.h +ao-telemetrum.h +ao-teleterra.h - ao-teledongle.h +ao-tidongle.h - Makefile.in - aclocal.m4 - .deps ++aoload/aoload ++ccdump/ccdump ++ccmanual/ccmanual ++aoview/Makefile ++aoview/aoview autom4te.cache +config.* + config.h + config.h.in + config.h.in~ + config.log + config.status + configure depcomp install-sh ++Makefile + Makefile.in missing stamp-h1 - configure - Makefile - aoview/Makefile - ++tags ++teledongle ++telemetrum ++teleterra ++tidongle diff --combined INSTALL index c9fd2c0c,d3c5b40a..200806c5 --- a/INSTALL +++ b/INSTALL @@@ -2,15 -2,15 +2,15 @@@ Installation Instruction ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, - 2006, 2007, 2008 Free Software Foundation, Inc. + 2006, 2007 Free Software Foundation, Inc. - This file is free documentation; the Free Software Foundation gives + This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. Basic Installation ================== - Briefly, the shell commands `./configure; make; make install' should + Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. @@@ -73,9 -73,9 +73,9 @@@ The simplest way to compile this packag Compilers and Options ===================== - Some systems require unusual options for compilation or linking that - the `configure' script does not know about. Run `./configure --help' - for details on some of the pertinent environment variables. + Some systems require unusual options for compilation or linking that the + `configure' script does not know about. Run `./configure --help' for + details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here @@@ -88,7 -88,7 +88,7 @@@ is an example Compiling For Multiple Architectures ==================================== - You can compile the package for more than one kind of computer at the + You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run @@@ -100,24 -100,10 +100,10 @@@ architecture at a time in the source co installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. - On MacOS X 10.5 and later systems, you can create libraries and - executables that work on multiple system types--known as "fat" or - "universal" binaries--by specifying multiple `-arch' options to the - compiler but only a single `-arch' option to the preprocessor. Like - this: - - ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ - CPP="gcc -E" CXXCPP="g++ -E" - - This is not guaranteed to produce working output in all cases, you - may have to build one architecture at a time and combine the results - using the `lipo' tool if you have problems. - Installation Names ================== - By default, `make install' installs the package's commands under + By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX'. @@@ -140,7 -126,7 +126,7 @@@ option `--program-prefix=PREFIX' or `-- Optional Features ================= - Some packages pay attention to `--enable-FEATURE' options to + Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The @@@ -152,36 -138,14 +138,14 @@@ find the X include and library files au you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. - Particular systems - ================== - - On HP-UX, the default C compiler is not ANSI C compatible. If GNU - CC is not installed, it is recommended to use the following options in - order to use an ANSI C compiler: - - ./configure CC="cc -Ae" - - and if that doesn't work, install pre-built binaries of GCC for HP-UX. - - On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot - parse its `' header file. The option `-nodtk' can be used as - a workaround. If GNU CC is not installed, it is therefore recommended - to try - - ./configure CC="cc" - - and if that doesn't work, try - - ./configure CC="cc -nodtk" - Specifying the System Type ========================== - There may be some features `configure' cannot figure out - automatically, but needs to determine by the type of machine the package - will run on. Usually, assuming the package is built to be run on the - _same_ architectures, `configure' can figure that out, but if it prints - a message saying it cannot guess the machine type, give it the + There may be some features `configure' cannot figure out automatically, + but needs to determine by the type of machine the package will run on. + Usually, assuming the package is built to be run on the _same_ + architectures, `configure' can figure that out, but if it prints a + message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: @@@ -207,9 -171,9 +171,9 @@@ eventually be run) with `--host=TYPE' Sharing Defaults ================ - If you want to set default values for `configure' scripts to share, - you can create a site shell script called `config.site' that gives - default values for variables like `CC', `cache_file', and `prefix'. + If you want to set default values for `configure' scripts to share, you + can create a site shell script called `config.site' that gives default + values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. @@@ -218,7 -182,7 +182,7 @@@ A warning: not all `configure' scripts Defining Variables ================== - Variables not defined in a site shell script can be set in the + Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set @@@ -237,19 -201,11 +201,11 @@@ an Autoconf bug. Until the bug is fixe `configure' Invocation ====================== - `configure' recognizes the following options to control how it - operates. + `configure' recognizes the following options to control how it operates. `--help' `-h' - Print a summary of all of the options to `configure', and exit. - - `--help=short' - `--help=recursive' - Print a summary of the options unique to this package's - `configure', and exit. The `short' variant lists options used - only in the top level, while the `recursive' variant lists options - also present in any nested packages. + Print a summary of the options to `configure', and exit. `--version' `-V' @@@ -276,15 -232,6 +232,5 @@@ Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. - `--prefix=DIR' - Use DIR as the installation prefix. *Note Installation Names:: - for more details, including other options available for fine-tuning - the installation locations. - - `--no-create' - `-n' - Run the configure checks, but stop before creating any output - files. - `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. - diff --combined Makefile.am index e5c0c1e8,86f2fad5..b0d059ea --- a/Makefile.am +++ b/Makefile.am @@@ -1,1 -1,1 +1,1 @@@ - SUBDIRS=src aoview -SUBDIRS=lib ccload s51 ccmanual ccdump aoload ++SUBDIRS=src aoview lib ccload s51 ccmanual ccdump aoload diff --combined aoload/aoload.c index 00000000,a36ad375..b84a88a6 mode 000000,100644..100644 --- a/aoload/aoload.c +++ b/aoload/aoload.c @@@ -1,0 -1,231 +1,231 @@@ + /* + * 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 "ccdbg.h" + + #define AO_USB_DESC_STRING 3 + + void + usage(char *program) + { + fprintf(stderr, "usage: %s \n", program); + exit(1); + } + + struct sym { + unsigned addr; + char *name; + } serial_symbols[] = { + { 0, "_ao_serial_number" }, + #define AO_SERIAL_NUMBER (serial_symbols[0].addr) + { 0, "_ao_usb_descriptors" }, + #define AO_USB_DESCRIPTORS (serial_symbols[1].addr) + }; + + #define NUM_SERIAL_SYMBOLS (sizeof(serial_symbols)/sizeof(serial_symbols[0])) + + static int + find_symbols(FILE *map) + { + char line[2048]; + char *addr, *addr_end; + char *name; + char *save; + char *colon; + unsigned long a; + int s; + int found = 0; + + while (fgets(line, sizeof(line), map) != NULL) { + line[sizeof(line)-1] = '\0'; + addr = strtok_r(line, " \t\n", &save); + if (!addr) + continue; + name = strtok_r(NULL, " \t\n", &save); + if (!name) + continue; + colon = strchr (addr, ':'); + if (!colon) + continue; + a = strtoul(colon+1, &addr_end, 16); + if (a == ULONG_MAX || addr_end == addr) + continue; + for (s = 0; s < NUM_SERIAL_SYMBOLS; s++) + if (!strcmp(serial_symbols[s].name, name)) { + serial_symbols[s].addr = (unsigned) a; + ++found; + break; + } + } + return found == NUM_SERIAL_SYMBOLS; + } + + static int + rewrite(struct hex_image *image, unsigned addr, char *data, int len) + { + int i; + if (addr < image->address || image->address + image->length < addr + len) + return 0; + printf("rewrite %04x:", addr); + for (i = 0; i < len; i++) + printf (" %02x", image->data[addr - image->address + i]); + printf(" ->"); + for (i = 0; i < len; i++) + printf (" %02x", data[i]); + printf("\n"); + memcpy(image->data + addr - image->address, data, len); + } + + 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; + FILE *map; + char *serial_string; + unsigned int serial; + char *mapname, *dot; + char *serial_ucs2; + int serial_ucs2_len; + char serial_int[2]; + unsigned int s; + int i; + unsigned usb_descriptors; + int string_num; + + filename = argv[1]; + if (filename == NULL) + usage(argv[0]); + mapname = strdup(filename); + dot = strrchr(mapname, '.'); + if (!dot || strcmp(dot, ".ihx") != 0) + usage(argv[0]); + strcpy(dot, ".map"); + + serial_string = argv[2]; + if (serial_string == NULL) + usage(argv[0]); - ++ + file = fopen(filename, "r"); + if (!file) { + perror(filename); + exit(1); + } + map = fopen(mapname, "r"); + if (!map) { + perror(mapname); + exit(1); + } + if (!find_symbols(map)) { + fprintf(stderr, "Cannot find symbols in \"%s\"\n", mapname); + exit(1); + } + fclose(map); + + hex = ccdbg_hex_file_read(file, filename); + fclose(file); + if (!hex) { + perror(filename); + exit (1); + } + image = ccdbg_hex_image_create(hex); + if (!image) { + fprintf(stderr, "image create failed\n"); + exit (1); + } + ccdbg_hex_file_free(hex); + + serial = strtoul(serial_string, NULL, 0); + if (!serial) + usage(argv[0]); + + serial_int[0] = serial & 0xff; + serial_int[1] = (serial >> 8) & 0xff; + + if (!rewrite(image, AO_SERIAL_NUMBER, serial_int, sizeof (serial_int))) { + fprintf(stderr, "Cannot rewrite serial integer at %04x\n", + AO_SERIAL_NUMBER); + exit(1); + } - ++ + usb_descriptors = AO_USB_DESCRIPTORS - image->address; + string_num = 0; + while (image->data[usb_descriptors] != 0 && usb_descriptors < image->length) { + if (image->data[usb_descriptors+1] == AO_USB_DESC_STRING) { + ++string_num; + if (string_num == 4) + break; + } + usb_descriptors += image->data[usb_descriptors]; + } + if (usb_descriptors >= image->length || image->data[usb_descriptors] == 0 ) { + fprintf(stderr, "Cannot rewrite serial string at %04x\n", AO_USB_DESCRIPTORS); + exit(1); + } - ++ + serial_ucs2_len = image->data[usb_descriptors] - 2; + serial_ucs2 = malloc(serial_ucs2_len); + if (!serial_ucs2) { + fprintf(stderr, "Malloc(%d) failed\n", serial_ucs2_len); + exit(1); + } + s = serial; + for (i = serial_ucs2_len / 2; i; i--) { + serial_ucs2[i * 2 - 1] = 0; + serial_ucs2[i * 2 - 2] = (s % 10) + '0'; + s /= 10; + } + if (!rewrite(image, usb_descriptors + 2 + image->address, serial_ucs2, serial_ucs2_len)) + usage(argv[0]); - ++ + dbg = ccdbg_open(); + if (!dbg) + exit (1); - ++ + ccdbg_add_debug(CC_DEBUG_FLASH); + + 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); + } diff --combined aoview/Makefile.am index 9f67ac40,00000000..be3fbacf mode 100644,000000..100644 --- a/aoview/Makefile.am +++ b/aoview/Makefile.am @@@ -1,28 -1,0 +1,28 @@@ +VERSION=$(shell git describe) - AM_CFLAGS=$(AOVIEW_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\" ++AM_CFLAGS=$(GNOME_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\" + +bin_PROGRAMS=aoview + - aoview_LDADD=$(AOVIEW_LIBS) ++aoview_LDADD=$(GNOME_LIBS) + +aoview_SOURCES = \ + aoview_main.c \ + aoview_dev.c \ + aoview_dev_dialog.c \ + aoview_serial.c \ + aoview_monitor.c \ + aoview_state.c \ + aoview_convert.c \ + aoview_log.c \ + aoview_table.c \ + aoview_util.c \ + aoview_file.c \ + aoview_eeprom.c \ + aoview.h + +BUILT_SOURCES = aoview_glade.h + +CLEANFILES = aoview_glade.h + +aoview_glade.h: aoview.glade + sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/"/' $< > $@ diff --combined ccload/ccload.c index 00000000,3e220914..5f7708fd mode 000000,100644..100644 --- a/ccload/ccload.c +++ b/ccload/ccload.c @@@ -1,0 -1,80 +1,80 @@@ + /* + * 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_add_debug(CC_DEBUG_FLASH); + + 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); + } diff --combined ccmanual/ccmanual.c index 00000000,402d9b13..7090c9a3 mode 000000,100644..100644 --- a/ccmanual/ccmanual.c +++ b/ccmanual/ccmanual.c @@@ -1,0 -1,33 +1,33 @@@ + /* + * Copyright © 2009 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; + + dbg = ccdbg_open(); + if (!dbg) + exit (1); - ++ + ccdbg_add_debug(CC_DEBUG_BITBANG); + + ccdbg_manual(dbg, stdin); + } diff --combined configure.ac index 0419489a,6c8963c4..99511a6e --- a/configure.ac +++ b/configure.ac @@@ -1,25 -1,25 +1,25 @@@ -dnl -dnl Copyright © 2008 Keith Packard -dnl +dnl - dnl Copyright © 2008 Keith Packard ++dnl Copyright © 2008,2009 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 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 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(aoview) + AC_INIT(COPYING) - AM_INIT_AUTOMAKE(aoview, 0.1) -AM_INIT_AUTOMAKE(cctools, 0.1) ++AM_INIT_AUTOMAKE(altos, 0.1) AM_MAINTAINER_MODE dnl ========================================================================== @@@ -43,16 -43,61 +43,17 @@@ if test "x$GCC" = "xyes"; the 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) ++PKG_CHECK_MODULES([GNOME], [gtk+-2.0 libglade-2.0 gconf-2.0]) - PKG_CHECK_MODULES([AOVIEW], [gtk+-2.0 libglade-2.0 gconf-2.0]) + 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 -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 +Makefile +aoview/Makefile + lib/Makefile + ccload/Makefile + s51/Makefile + ccmanual/Makefile + ccdump/Makefile + aoload/Makefile ]) diff --combined lib/cc-bitbang.c index 00000000,a5d2d369..1d3ba476 mode 000000,100644..100644 --- a/lib/cc-bitbang.c +++ b/lib/cc-bitbang.c @@@ -1,0 -1,270 +1,269 @@@ + /* + * Copyright © 2009 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 "ccdbg-debug.h" + #include "cc-bitbang.h" + + #define CP_USB_ASYNC + + #ifdef CP_USB_ASYNC + #include "cp-usb-async.h" + #else + #include "cp-usb.h" + #endif + + struct cc_bitbang { + #ifdef CP_USB_ASYNC + struct cp_usb_async *cp_async; + #else + struct cp_usb *cp; + #endif + }; + + static uint32_t cc_clock_us = CC_CLOCK_US; + static uint32_t cc_reset_us = CC_RESET_US; + + void + cc_bitbang_set_clock(uint32_t us) + { + cc_clock_us = us; + } + + void + cc_bitbang_half_clock(struct cc_bitbang *bb) + { + struct timespec req, rem; + req.tv_sec = (cc_clock_us / 2) / 1000000; + req.tv_nsec = ((cc_clock_us / 2) % 1000000) * 1000; + nanosleep(&req, &rem); + } + + void + cc_bitbang_wait_reset(struct cc_bitbang *bb) + { + struct timespec req, rem; - ++ + cc_bitbang_sync(bb); + req.tv_sec = (cc_reset_us) / 1000000; + req.tv_nsec = ((cc_reset_us) % 1000000) * 1000; + nanosleep(&req, &rem); + } - ++ + struct cc_bitbang * + cc_bitbang_open(void) + { + struct cc_bitbang *bb; + + bb = calloc(sizeof (struct cc_bitbang), 1); + if (!bb) { + perror("calloc"); + return NULL; + } + #ifdef CP_USB_ASYNC + bb->cp_async = cp_usb_async_open(); + if (!bb->cp_async) { + free (bb); + return NULL; + } + #else + bb->cp = cp_usb_open (); + if (!bb->cp) { + free (bb); + return NULL; + } + #endif + return bb; + } + + void + cc_bitbang_close(struct cc_bitbang *bb) + { + #ifdef CP_USB_ASYNC + cp_usb_async_close(bb->cp_async); + #else + cp_usb_close(bb->cp); + #endif + free (bb); + } + + void + cc_bitbang_debug_mode(struct cc_bitbang *bb) + { + /* force two rising clocks while holding RESET_N low */ + ccdbg_debug(CC_DEBUG_COMMAND, "#\n"); + ccdbg_debug(CC_DEBUG_COMMAND, "# Debug mode\n"); + ccdbg_debug(CC_DEBUG_COMMAND, "#\n"); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_DATA ); + cc_bitbang_wait_reset(bb); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_DATA ); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_DATA|CC_RESET_N); + cc_bitbang_wait_reset(bb); + } + + void + cc_bitbang_reset(struct cc_bitbang *bb) + { + ccdbg_debug(CC_DEBUG_COMMAND, "#\n"); + ccdbg_debug(CC_DEBUG_COMMAND, "# Reset\n"); + ccdbg_debug(CC_DEBUG_COMMAND, "#\n"); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); + cc_bitbang_wait_reset(bb); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA ); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); + cc_bitbang_wait_reset(bb); + } + + int + cc_bitbang_write(struct cc_bitbang *bb, uint8_t mask, uint8_t value) + { + #ifdef CP_USB_ASYNC + cp_usb_async_write(bb->cp_async, mask, value); + #else + cp_usb_write(bb->cp, mask, value); + #endif + return 0; + } + + void + cc_bitbang_read(struct cc_bitbang *bb, uint8_t *valuep) + { + #ifdef CP_USB_ASYNC + cp_usb_async_read(bb->cp_async, valuep); + #else + *valuep = cp_usb_read(bb->cp); + #endif + } + + void + cc_bitbang_sync(struct cc_bitbang *bb) + { + #ifdef CP_USB_ASYNC + cp_usb_async_sync(bb->cp_async); + #endif + } + + static char + is_bit(uint8_t get, uint8_t mask, char on, uint8_t bit) + { + if (mask&bit) { + if (get&bit) + return on; + else + return '.'; + } else + return '-'; + } + + void + cc_bitbang_print(char *format, uint8_t mask, uint8_t set) + { + ccdbg_debug (CC_DEBUG_BITBANG, format, + is_bit(set, mask, 'C', CC_CLOCK), + is_bit(set, mask, 'D', CC_DATA), + is_bit(set, mask, 'R', CC_RESET_N)); + } + + void + cc_bitbang_send(struct cc_bitbang *bb, uint8_t mask, uint8_t set) + { + cc_bitbang_write(bb, mask, set); + cc_bitbang_print("%c %c %c\n", mask, set); + cc_bitbang_half_clock(bb); + } + + void + cc_bitbang_send_bit(struct cc_bitbang *bb, uint8_t bit) + { + if (bit) bit = CC_DATA; + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, CC_CLOCK|bit|CC_RESET_N); + cc_bitbang_send(bb, CC_CLOCK|CC_DATA|CC_RESET_N, bit|CC_RESET_N); + } + + void + cc_bitbang_send_byte(struct cc_bitbang *bb, uint8_t byte) + { + int bit; + ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Send Byte 0x%02x\n#\n", byte); + for (bit = 7; bit >= 0; bit--) { + cc_bitbang_send_bit(bb, (byte >> bit) & 1); + if (bit == 3) + ccdbg_debug(CC_DEBUG_BITBANG, "\n"); + } + cc_bitbang_sync(bb); + } + + void + cc_bitbang_send_bytes(struct cc_bitbang *bb, uint8_t *bytes, int nbytes) + { + while (nbytes--) + cc_bitbang_send_byte(bb, *bytes++); + } + + void + cc_bitbang_recv_bit(struct cc_bitbang *bb, int first, uint8_t *bit) + { + uint8_t mask = first ? CC_DATA : 0; + + cc_bitbang_send(bb, CC_CLOCK|mask|CC_RESET_N, CC_CLOCK|CC_DATA|CC_RESET_N); + cc_bitbang_read(bb, bit); + cc_bitbang_send(bb, CC_CLOCK| CC_RESET_N, CC_RESET_N); + } + + void + cc_bitbang_recv_byte(struct cc_bitbang *bb, 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++) { + cc_bitbang_recv_bit(bb, first, &bits[bit]); + first = 0; + } + cc_bitbang_sync(bb); + for (bit = 0; bit < 8; bit++) { + byte = byte << 1; + byte |= (bits[bit] & CC_DATA) ? 1 : 0; + cc_bitbang_print("#\t%c %c %c\n", CC_DATA, bits[bit]); + if (bit == 3) + ccdbg_debug(CC_DEBUG_BITBANG, "\n"); + } + ccdbg_debug(CC_DEBUG_BITBANG, "#\n# Recv 0x%02x\n#\n", byte); + *bytep = byte; + } + + void + cc_bitbang_recv_bytes(struct cc_bitbang *bb, uint8_t *bytes, int nbytes) + { + int i; + int first = 1; + for (i = 0; i < nbytes; i++) { + cc_bitbang_recv_byte(bb, first, &bytes[i]); + first = 0; + } + } - diff --combined lib/cc-usb.c index 00000000,2efe572e..dc764c24 mode 000000,100644..100644 --- a/lib/cc-usb.c +++ b/lib/cc-usb.c @@@ -1,0 -1,360 +1,359 @@@ + /* + * Copyright © 2009 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 + #include + #include + #include + #include + #include + #include "ccdbg-debug.h" + #include "cc-usb.h" + + + #define CC_NUM_READ 16 + /* + * AltOS has different buffer sizes for in/out packets + */ + #define CC_IN_BUF 256 + #define CC_OUT_BUF 64 + #define DEFAULT_TTY "/dev/ttyACM0" + + struct cc_read { + uint8_t *buf; + int len; + }; + + struct cc_usb { + int fd; + uint8_t in_buf[CC_IN_BUF]; + int in_count; + uint8_t out_buf[CC_OUT_BUF]; + int out_count; + struct cc_read read_buf[CC_NUM_READ]; + int read_count; + }; + + #define NOT_HEX 0xff + + static uint8_t + cc_hex_nibble(uint8_t c) + { + if ('0' <= c && c <= '9') + return c - '0'; + if ('a' <= c && c <= 'f') + return c - 'a' + 10; + if ('A' <= c && c <= 'F') + return c - 'A' + 10; + return NOT_HEX; + } + + /* + * Take raw input bytes, parse them as hex + * and write them to the waiting buffer + */ + static void + cc_handle_in(struct cc_usb *cc) + { + uint8_t h, l; + int in_pos; + int read_pos; - ++ + in_pos = 0; + read_pos = 0; + while (read_pos < cc->read_count && in_pos < cc->in_count) { + /* + * Skip to next hex character + */ - while (in_pos < cc->in_count && ++ while (in_pos < cc->in_count && + cc_hex_nibble(cc->in_buf[in_pos]) == NOT_HEX) + in_pos++; + /* + * Make sure we have two characters left + */ + if (cc->in_count - in_pos < 2) + break; + /* + * Parse hex number + */ + h = cc_hex_nibble(cc->in_buf[in_pos]); + l = cc_hex_nibble(cc->in_buf[in_pos+1]); + if (h == NOT_HEX || l == NOT_HEX) { + fprintf(stderr, "hex read error\n"); + break; + } + in_pos += 2; + /* + * Store hex number + */ + *cc->read_buf[read_pos].buf++ = (h << 4) | l; + if (--cc->read_buf[read_pos].len <= 0) + read_pos++; + } - ++ + /* Move remaining bytes to the start of the input buffer */ + if (in_pos) { + memmove(cc->in_buf, cc->in_buf + in_pos, + cc->in_count - in_pos); + cc->in_count -= in_pos; + } + + /* Move pending reads to the start of the array */ + if (read_pos) { + memmove(cc->read_buf, cc->read_buf + read_pos, + (cc->read_count - read_pos) * sizeof (cc->read_buf[0])); + cc->read_count -= read_pos; + } + + /* Once we're done reading, flush any pending input */ + if (cc->read_count == 0) + cc->in_count = 0; + } + + static void + cc_usb_dbg(int indent, uint8_t *bytes, int len) + { + int eol = 1; + int i; + uint8_t c; + while (len--) { + c = *bytes++; + if (eol) { + for (i = 0; i < indent; i++) + ccdbg_debug(CC_DEBUG_BITBANG, " "); + eol = 0; + } + switch (c) { + case '\r': + ccdbg_debug(CC_DEBUG_BITBANG, "^M"); + break; + case '\n': + eol = 1; + default: + ccdbg_debug(CC_DEBUG_BITBANG, "%c", c); + } + } + } + + /* + * Flush pending writes, fill pending reads + */ + void + cc_usb_sync(struct cc_usb *cc) + { + int ret; + struct pollfd fds; + int timeout; + + fds.fd = cc->fd; + for (;;) { + if (cc->read_count || cc->out_count) + timeout = -1; + else + timeout = 0; + fds.events = 0; + if (cc->in_count < CC_IN_BUF) + fds.events |= POLLIN; + if (cc->out_count) + fds.events |= POLLOUT; + ret = poll(&fds, 1, timeout); + if (ret == 0) + break; + if (ret < 0) { + perror("poll"); + break; + } + if (fds.revents & POLLIN) { + ret = read(cc->fd, cc->in_buf + cc->in_count, + CC_IN_BUF - cc->in_count); + if (ret > 0) { + cc_usb_dbg(24, cc->in_buf + cc->in_count, ret); + cc->in_count += ret; + cc_handle_in(cc); + } else if (ret < 0) + perror("read"); + } + if (fds.revents & POLLOUT) { + ret = write(cc->fd, cc->out_buf, + cc->out_count); + if (ret > 0) { + cc_usb_dbg(0, cc->out_buf, ret); + memmove(cc->out_buf, + cc->out_buf + ret, + cc->out_count - ret); + cc->out_count -= ret; + } else if (ret < 0) + perror("write"); + } + } + } + + void + cc_usb_printf(struct cc_usb *cc, char *format, ...) + { + char buf[1024], *b; + va_list ap; + int ret, this_time; - ++ + /* sprintf to a local buffer */ + va_start(ap, format); + ret = vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + if (ret > sizeof(buf)) { + fprintf(stderr, "printf overflow for format %s\n", + format); + } + + /* flush local buffer to the wire */ + b = buf; + while (ret > 0) { + this_time = ret; + if (this_time > CC_OUT_BUF - cc->out_count) + this_time = CC_OUT_BUF - cc->out_count; + memcpy(cc->out_buf + cc->out_count, b, this_time); + cc->out_count += this_time; + ret -= this_time; + b += this_time; + while (cc->out_count >= CC_OUT_BUF) + cc_usb_sync(cc); + } + } + + int + cc_usb_send_bytes(struct cc_usb *cc, uint8_t *bytes, int len) + { + int this_len; + int ret = len; - ++ + while (len) { + this_len = len; + if (this_len > 8) + this_len = 8; + len -= this_len; + cc_usb_printf(cc, "P"); + while (this_len--) + cc_usb_printf (cc, " %02x", (*bytes++) & 0xff); + cc_usb_printf(cc, "\n"); + } + return ret; + } + + void + cc_queue_read(struct cc_usb *cc, uint8_t *buf, int len) + { + struct cc_read *read_buf; + while (cc->read_count >= CC_NUM_READ) + cc_usb_sync(cc); + read_buf = &cc->read_buf[cc->read_count++]; + read_buf->buf = buf; + read_buf->len = len; + } + + int + cc_usb_recv_bytes(struct cc_usb *cc, uint8_t *buf, int len) + { + cc_queue_read(cc, buf, len); + cc_usb_printf(cc, "G %x\n", len); + return len; + } + + int + cc_usb_write_memory(struct cc_usb *cc, uint16_t addr, uint8_t *bytes, int len) + { + cc_usb_printf(cc, "O %x %x\n", len, addr); + while (len--) + cc_usb_printf(cc, "%02x", *bytes++); + return 0; + } + + int + cc_usb_read_memory(struct cc_usb *cc, uint16_t addr, uint8_t *bytes, int len) + { + int i; + cc_queue_read(cc, bytes, len); + cc_usb_printf(cc, "I %x %x\n", len, addr); + cc_usb_sync(cc); + for (i = 0; i < len; i++) { + if ((i & 15) == 0) { + if (i) + ccdbg_debug(CC_DEBUG_MEMORY, "\n"); + ccdbg_debug(CC_DEBUG_MEMORY, "\t%04x", addr + i); + } + ccdbg_debug(CC_DEBUG_MEMORY, " %02x", bytes[i]); + } + ccdbg_debug(CC_DEBUG_MEMORY, "\n"); + return 0; + } + + int + cc_usb_debug_mode(struct cc_usb *cc) + { + cc_usb_sync(cc); + cc_usb_printf(cc, "D\n"); + return 1; + } + + int + cc_usb_reset(struct cc_usb *cc) + { + cc_usb_sync(cc); + cc_usb_printf(cc, "R\n"); + return 1; + } + + static struct termios save_termios; + + struct cc_usb * + cc_usb_open(char *tty) + { + struct cc_usb *cc; + struct termios termios; - ++ + if (!tty) + tty = DEFAULT_TTY; + cc = calloc (sizeof (struct cc_usb), 1); + if (!cc) + return NULL; + cc->fd = open(tty, O_RDWR | O_NONBLOCK); + if (cc->fd < 0) { + perror(tty); + free (cc); + return NULL; + } + tcgetattr(cc->fd, &termios); + save_termios = termios; + cfmakeraw(&termios); + tcsetattr(cc->fd, TCSAFLUSH, &termios); + cc_usb_printf(cc, "E 0\n"); + cc_usb_sync(cc); + sleep(1); + cc_usb_sync(cc); + return cc; + } + + void + cc_usb_close(struct cc_usb *cc) + { + tcsetattr(cc->fd, TCSAFLUSH, &save_termios); + close (cc->fd); + free (cc); + } - diff --combined lib/ccdbg-command.c index 00000000,7d1ae067..a1002879 mode 000000,100644..100644 --- a/lib/ccdbg-command.c +++ b/lib/ccdbg-command.c @@@ -1,0 -1,177 +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 "ccdbg.h" + + uint8_t + ccdbg_chip_erase(struct ccdbg *dbg) + { + return ccdbg_cmd_write_read8(dbg, CC_CHIP_ERASE, NULL, 0); + } + + uint8_t + ccdbg_wr_config(struct ccdbg *dbg, uint8_t config) + { + return ccdbg_cmd_write_read8(dbg, CC_WR_CONFIG, &config, 1); + } + + uint8_t + ccdbg_rd_config(struct ccdbg *dbg) + { + return ccdbg_cmd_write_read8(dbg, CC_RD_CONFIG, NULL, 0); + } + + uint16_t + ccdbg_get_pc(struct ccdbg *dbg) + { + uint16_t pc1, pc2; + + pc1 = ccdbg_cmd_write_read16(dbg, CC_GET_PC, NULL, 0); + pc2 = ccdbg_cmd_write_read16(dbg, CC_GET_PC, NULL, 0); + if (pc1 != pc2) + fprintf (stderr, "Invalid pc %04x != %04x\n", + pc1, pc2); + return pc2; + } + + uint8_t + ccdbg_read_status(struct ccdbg *dbg) + { + return ccdbg_cmd_write_read8(dbg, CC_READ_STATUS, NULL, 0); + } + + uint8_t + ccdbg_set_hw_brkpnt(struct ccdbg *dbg, uint8_t number, uint8_t enable, uint16_t addr) + { + uint8_t data[3]; + + data[0] = (number << 3) | (enable << 2); + data[1] = (addr >> 8); + data[2] = addr; + return ccdbg_cmd_write_read8(dbg, CC_SET_HW_BRKPNT, data, 3); + } + + uint8_t + ccdbg_halt(struct ccdbg *dbg) + { + return ccdbg_cmd_write_read8(dbg, CC_HALT, NULL, 0); + } + + uint8_t + ccdbg_resume(struct ccdbg *dbg) + { + return ccdbg_cmd_write_read8(dbg, CC_RESUME, NULL, 0); + } + + uint8_t + ccdbg_debug_instr(struct ccdbg *dbg, uint8_t *instr, int nbytes) + { + return ccdbg_cmd_write_read8(dbg, CC_DEBUG_INSTR(nbytes), instr, nbytes); + } + + void + ccdbg_debug_instr_discard(struct ccdbg *dbg, uint8_t *instr, int nbytes) + { + static uint8_t discard; + ccdbg_cmd_write_queue8(dbg, CC_DEBUG_INSTR(nbytes), + instr, nbytes, &discard); + } + + void + ccdbg_debug_instr_queue(struct ccdbg *dbg, uint8_t *instr, int nbytes, + uint8_t *reply) + { + return ccdbg_cmd_write_queue8(dbg, CC_DEBUG_INSTR(nbytes), + instr, nbytes, reply); + } + + uint8_t + ccdbg_step_instr(struct ccdbg *dbg) + { + return ccdbg_cmd_write_read8(dbg, CC_STEP_INSTR, NULL, 0); + } + + uint8_t + ccdbg_step_replace(struct ccdbg *dbg, uint8_t *instr, int nbytes) + { + return ccdbg_cmd_write_read8(dbg, CC_STEP_REPLACE(nbytes), instr, nbytes); + } + + uint16_t + ccdbg_get_chip_id(struct ccdbg *dbg) + { + return ccdbg_cmd_write_read16(dbg, CC_GET_CHIP_ID, NULL, 0); + } + + /* + * Execute a sequence of instructions + */ + uint8_t + ccdbg_execute(struct ccdbg *dbg, uint8_t *inst) + { + uint8_t status = 0; + while(inst[0] != 0) { + uint8_t len = inst[0]; + int i; + ccdbg_debug(CC_DEBUG_INSTRUCTIONS, "\t%02x", inst[1]); + for (i = 0; i < len - 1; i++) + ccdbg_debug(CC_DEBUG_INSTRUCTIONS, " %02x", inst[i+2]); + ccdbg_debug_instr_queue(dbg, inst+1, len, &status); + for (; i < 3; i++) + ccdbg_debug(CC_DEBUG_INSTRUCTIONS, " "); + ccdbg_debug(CC_DEBUG_INSTRUCTIONS, " -> %02x\n", status); + inst += len + 1; + } + ccdbg_sync(dbg); + return status; + } + + static uint8_t jump_mem[] = { + 3, LJMP, 0xf0, 0x00, + #define PC_HIGH 2 + #define PC_LOW 3 + 0 + }; + + uint8_t + ccdbg_set_pc(struct ccdbg *dbg, uint16_t pc) + { + jump_mem[PC_HIGH] = pc >> 8; + jump_mem[PC_LOW] = pc & 0xff; + return ccdbg_execute(dbg, jump_mem); + } + + uint8_t + ccdbg_execute_hex_image(struct ccdbg *dbg, struct hex_image *image) + { + uint16_t pc; + uint8_t status; - ++ + if (image->address < 0xf000) { + fprintf(stderr, "Cannot execute program starting at 0x%04x\n", image->address); + return -1; + } + ccdbg_write_hex_image(dbg, image, 0); + ccdbg_set_pc(dbg, image->address); + pc = ccdbg_get_pc(dbg); + ccdbg_debug(CC_DEBUG_EXECUTE, "pc starts at 0x%04x\n", pc); + status = ccdbg_resume(dbg); + ccdbg_debug(CC_DEBUG_EXECUTE, "resume status: 0x%02x\n", status); + return 0; + } - diff --combined lib/ccdbg-flash.c index 00000000,8a586a21..3e672985 mode 000000,100644..100644 --- a/lib/ccdbg-flash.c +++ b/lib/ccdbg-flash.c @@@ -1,0 -1,356 +1,356 @@@ + /* + * 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" + + /* From SWRA124 section 3.1.6 */ + + static uint8_t flash_page[] = { + + MOV_direct_data, P1DIR, 0x02, + MOV_direct_data, P1, 0xFF, + + MOV_direct_data, FADDRH, 0, + #define FLASH_ADDR_HIGH 8 + + MOV_direct_data, FADDRL, 0, + #define FLASH_ADDR_LOW 11 + + MOV_DPTR_data16, 0, 0, + #define RAM_ADDR_HIGH 13 + #define RAM_ADDR_LOW 14 + + MOV_Rn_data(7), 0, + #define FLASH_WORDS_HIGH 16 - ++ + MOV_Rn_data(6), 0, + #define FLASH_WORDS_LOW 18 - ++ + MOV_direct_data, FWT, 0x20, + #define FLASH_TIMING 21 + + MOV_direct_data, FCTL, FCTL_ERASE, + /* eraseWaitLoop: */ + MOV_A_direct, FCTL, + JB, ACC(FCTL_BUSY_BIT), 0xfb, + + MOV_direct_data, P1, 0xfd, + + MOV_direct_data, FCTL, FCTL_WRITE, + /* writeLoop: */ + MOV_Rn_data(5), 2, + /* writeWordLoop: */ + MOVX_A_atDPTR, + INC_DPTR, + MOV_direct_A, FWDATA, + DJNZ_Rn_rel(5), 0xfa, /* writeWordLoop */ + /* writeWaitLoop: */ + MOV_A_direct, FCTL, + JB, ACC(FCTL_SWBSY_BIT), 0xfb, /* writeWaitLoop */ + DJNZ_Rn_rel(6), 0xf1, /* writeLoop */ + DJNZ_Rn_rel(7), 0xef, /* writeLoop */ + + MOV_direct_data, P1DIR, 0x00, + MOV_direct_data, P1, 0xFF, + TRAP, + }; + + #define FLASH_RAM 0xf000 + + #if 0 + static uint8_t flash_erase_page[] = { + 3, MOV_direct_data, FADDRH, 0, + #define ERASE_PAGE_HIGH 3 - ++ + 3, MOV_direct_data, FADDRL, 0, + #define ERASE_PAGE_LOW 7 + + 3, MOV_direct_data, FWT, 0x2A, + 3, MOV_direct_data, FCTL, FCTL_ERASE, + 0 + }; + + static uint8_t flash_read_control[] = { + 2, MOV_A_direct, FCTL, + 0 + }; + #endif + + #if 0 + static uint8_t flash_control_clear[] = { + 3, MOV_direct_data, FCTL, 0, + 2, MOV_A_direct, FCTL, + 0 + }; + #endif + + #if 0 + static uint8_t + ccdbg_flash_erase_page(struct ccdbg *dbg, uint16_t addr) + { + uint16_t page_addr = addr >> 1; + uint8_t status; + uint8_t old[0x10], new[0x10]; + int i; - ++ + ccdbg_read_memory(dbg, addr, old, 0x10); + flash_erase_page[ERASE_PAGE_HIGH] = page_addr >> 8; + flash_erase_page[ERASE_PAGE_LOW] = page_addr & 0xff; + status = ccdbg_execute(dbg, flash_erase_page); + ccdbg_debug(CC_DEBUG_FLASH, "erase status 0x%02x\n", status); + do { + status = ccdbg_execute(dbg, flash_read_control); + ccdbg_debug(CC_DEBUG_FLASH, "fctl 0x%02x\n", status); + } while (status & FCTL_BUSY); + ccdbg_read_memory(dbg, addr, new, 0x10); + for (i = 0; i < 0x10; i++) + ccdbg_debug(CC_DEBUG_FLASH, "0x%02x -> 0x%02x\n", old[i], new[i]); + status = ccdbg_execute(dbg, flash_control_clear); + ccdbg_debug(CC_DEBUG_FLASH, "clear fctl 0x%02x\n", status); + return 0; + } + #endif + + #if 0 + static uint8_t flash_write[] = { + MOV_direct_data, P1DIR, 0x02, + MOV_direct_data, P1, 0xFD, - ++ + MOV_A_direct, FCTL, + JB, ACC(FCTL_BUSY_BIT), 0xf1, + + MOV_direct_data, FCTL, 0x20, + + MOV_direct_data, FADDRH, 0, + #define WRITE_PAGE_HIGH 16 - ++ + MOV_direct_data, FADDRL, 0, + #define WRITE_PAGE_LOW 19 - ++ + MOV_direct_data, FCTL, FCTL_WRITE, + MOV_direct_data, FWDATA, 0, + #define WRITE_BYTE_0 25 + MOV_direct_data, FWDATA, 0, + #define WRITE_BYTE_1 28 + MOV_A_direct, FCTL, + JB, ACC(FCTL_SWBSY_BIT), 0xf1, + + MOV_direct_data, P1, 0xFF, + TRAP, + }; + #endif + + static uint8_t + ccdbg_clock_init(struct ccdbg *dbg) + { + static uint8_t set_clkcon_fast[] = { + 3, MOV_direct_data, CLKCON, 0x00, + 0 + }; + + static uint8_t get_sleep[] = { + 2, MOV_A_direct, SLEEP, + 0 + }; + + uint8_t status; + + ccdbg_execute(dbg, set_clkcon_fast); + do { + status = ccdbg_execute(dbg, get_sleep); + } while (!(status & 0x40)); + return 0; + } + + #if 0 + static uint8_t + ccdbg_flash_write_word(struct ccdbg *dbg, uint16_t addr, uint8_t data[2]) + { + uint16_t page_addr = addr >> 1; + uint8_t check[2]; + uint8_t status; + int i; + + flash_write[WRITE_PAGE_HIGH] = page_addr >> 8; + flash_write[WRITE_PAGE_LOW] = page_addr & 0xff; + flash_write[WRITE_BYTE_0] = data[0]; + flash_write[WRITE_BYTE_1] = data[1]; + ccdbg_debug(CC_DEBUG_FLASH, "upload flash write\n"); + ccdbg_write_memory(dbg, 0xf000, flash_write, sizeof(flash_write)); + ccdbg_set_pc(dbg, 0xf000); + ccdbg_resume(dbg); + for (;;) { + status = ccdbg_read_status(dbg); + ccdbg_debug(CC_DEBUG_FLASH, "waiting for write 0x%02x\n", status); + if ((status & CC_STATUS_CPU_HALTED) != 0) + break; + sleep (1); + } + status = ccdbg_execute(dbg, flash_control_clear); + ccdbg_debug(CC_DEBUG_FLASH, "clear fctl 0x%02x\n", status); + ccdbg_read_memory(dbg, addr, check, 2); + for (i = 0; i < 2; i++) + ccdbg_debug(CC_DEBUG_FLASH, "0x%02x : 0x%02x\n", data[i], check[i]); + return 0; + } + #endif + + #define TIMERS_OFF 0x08 + #define DMA_PAUSE 0x04 + #define TIMER_SUSPEND 0x02 + #define SEL_FLASH_INFO_PAGE 0x01 + + #if 0 + static uint8_t + ccdbg_flash_lock(struct ccdbg *dbg, uint8_t lock) + { + uint8_t config; + uint8_t bytes[2]; + uint8_t old[1], new[1]; + + config = ccdbg_rd_config(dbg); + ccdbg_wr_config(dbg, config|SEL_FLASH_INFO_PAGE); + bytes[0] = lock; + bytes[1] = 0; + ccdbg_flash_erase_page(dbg, 0); + ccdbg_read_memory(dbg, 0, old, 1); + ccdbg_flash_write_word(dbg, 0, bytes); + ccdbg_read_memory(dbg, 0, new, 1); + ccdbg_debug(CC_DEBUG_FLASH, "flash lock 0x%02x -> 0x%02x\n", old[0], new[0]); + ccdbg_wr_config(dbg, config & ~SEL_FLASH_INFO_PAGE); + return 0; + } + #endif + + uint8_t + ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image) + { + uint16_t offset; + 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) { + fprintf(stderr, "cannot flash image from 0x%04x to 0x%04x\n", + image->address, image->address + image->length); + return 1; + } + if (image->address & 0x3ff) { + fprintf(stderr, "flash image must start on page boundary\n"); + return 1; + } + ram_addr = 0xf000; + - ++ + flash_prog = 0xf400; + + fwt = 0x20; + + flash_page[FLASH_TIMING] = fwt; + ccdbg_debug(CC_DEBUG_FLASH, "Upload %d flash program bytes to 0x%04x\n", + sizeof (flash_page), flash_prog); + ccdbg_write_memory(dbg, flash_prog, flash_page, sizeof(flash_page)); - ++ + remain = image->length; + start = 0; + while (remain) { + this_time = remain; + if (this_time > 0x400) + this_time = 0x400; + + offset = ram_addr - (image->address + start); + + 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); + #if 0 + 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, "ram verify failed\n"); + return 1; + } + #endif - ++ + 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_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, "Flashing %d bytes at 0x%04x\n", + this_time, flash_addr); + status = ccdbg_resume(dbg); + for (times = 0; times < 10; times++) { + status = ccdbg_read_status(dbg); + ccdbg_debug(CC_DEBUG_FLASH, "."); + ccdbg_flush(CC_DEBUG_FLASH); + if ((status & CC_STATUS_CPU_HALTED) != 0) + break; + usleep(10000); + } + ccdbg_debug(CC_DEBUG_FLASH, "\n"); + 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; + } + return 0; + } diff --combined lib/ccdbg-hex.c index 00000000,86478da0..dfea9156 mode 000000,100644..100644 --- a/lib/ccdbg-hex.c +++ b/lib/ccdbg-hex.c @@@ -1,0 -1,330 +1,330 @@@ + /* + * 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" + #include + #include + + struct hex_input { + FILE *file; + int line; + char *name; + }; + + enum hex_read_state { + read_marker, + read_length, + read_address, + read_type, + read_data, + read_checksum, + read_newline, + read_white, + read_done, + }; + + + static void + ccdbg_hex_error(struct hex_input *input, char *format, ...) + { + va_list ap; + + va_start(ap, format); + fprintf(stderr, "Hex error %s:%d: ", input->name, input->line); + vfprintf(stderr, format, ap); + fprintf(stderr, "\n"); + va_end(ap); + } + + static void + ccdbg_hex_free(struct hex_record *record) + { + if (!record) return; + free(record); + } + + static struct hex_record * + ccdbg_hex_alloc(uint8_t length) + { + struct hex_record *record; + + record = calloc(1, sizeof(struct hex_record) + length); + record->length = length; + return record; + } + + static int + ishex(char c) + { + return isdigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'); + } + + static int + fromhex(char c) + { + if (isdigit(c)) + return c - '0'; + if ('a' <= c && c <= 'f') + return c - 'a' + 10; + if ('A' <= c && c <= 'F') + return c - 'A' + 10; + abort(); + return 0; + } + + static uint8_t + ccdbg_hex_checksum(struct hex_record *record) + { + uint8_t checksum = 0; + int i; + + checksum += record->length; + checksum += record->address >> 8; + checksum += record->address & 0xff; + checksum += record->type; + for (i = 0; i < record->length; i++) + checksum += record->data[i]; + return -checksum; + } + + static struct hex_record * + ccdbg_hex_read_record(struct hex_input *input) + { + struct hex_record *record = NULL; + enum hex_read_state state = read_marker; + char c; + int nhexbytes; + uint32_t hex; + uint32_t ndata; + uint8_t checksum; + + while (state != read_done) { + c = getc(input->file); + if (c == EOF && state != read_white) { + ccdbg_hex_error(input, "Unexpected EOF"); + goto bail; + } + if (c == ' ') + continue; + if (c == '\n') + input->line++; + switch (state) { + case read_marker: + if (c != ':') { + ccdbg_hex_error(input, "Missing ':'"); + goto bail; + } + state = read_length; + nhexbytes = 2; + hex = 0; + break; + case read_length: + case read_address: + case read_type: + case read_data: + case read_checksum: + if (!ishex(c)) { + ccdbg_hex_error(input, "Non-hex char '%c'", + c); + goto bail; + } + hex = hex << 4 | fromhex(c); + --nhexbytes; + if (nhexbytes != 0) + break; - ++ + switch (state) { + case read_length: + record = ccdbg_hex_alloc(hex); + if (!record) { + ccdbg_hex_error(input, "Out of memory"); + goto bail; + } + state = read_address; + nhexbytes = 4; + break; + case read_address: + record->address = hex; + state = read_type; + nhexbytes = 2; + break; + case read_type: + record->type = hex; + state = read_data; + nhexbytes = 2; + ndata = 0; + break; + case read_data: + record->data[ndata] = hex; + ndata++; + nhexbytes = 2; + break; + case read_checksum: + record->checksum = hex; + state = read_newline; + break; + default: + break; + } + if (state == read_data) + if (ndata == record->length) { + nhexbytes = 2; + state = read_checksum; + } + hex = 0; + break; + case read_newline: + if (c != '\n' && c != '\r') { + ccdbg_hex_error(input, "Missing newline"); + goto bail; + } + state = read_white; + break; + case read_white: + if (!isspace(c)) { + if (c == '\n') + input->line--; + if (c != EOF) + ungetc(c, input->file); + state = read_done; + } + break; + case read_done: + break; + } + } + checksum = ccdbg_hex_checksum(record); + if (checksum != record->checksum) { + ccdbg_hex_error(input, "Invalid checksum (read 0x%02x computed 0x%02x)\n", + record->checksum, checksum); + goto bail; + } + return record; + + bail: + ccdbg_hex_free(record); + return NULL; + } + + void + ccdbg_hex_file_free(struct hex_file *hex) + { + int i; + + if (!hex) + return; + for (i = 0; i < hex->nrecord; i++) + ccdbg_hex_free(hex->records[i]); + free(hex); + } + + static int + ccdbg_hex_record_compar(const void *av, const void *bv) + { + const struct hex_record *a = *(struct hex_record **) av; + const struct hex_record *b = *(struct hex_record **) bv; + + return (int) a->address - (int) b->address; + } + + struct hex_file * + ccdbg_hex_file_read(FILE *file, char *name) + { + struct hex_input input; + struct hex_file *hex = NULL, *newhex; + struct hex_record *record; + int srecord = 1; + int done = 0; + + hex = calloc(sizeof (struct hex_file) + sizeof (struct hex_record *), 1); + input.name = name; + input.line = 1; + input.file = file; + while (!done) { + record = ccdbg_hex_read_record(&input); + if (!record) + goto bail; + if (hex->nrecord == srecord) { + srecord *= 2; - newhex = realloc(hex, ++ newhex = realloc(hex, + sizeof (struct hex_file) + + srecord * sizeof (struct hex_record *)); + if (!newhex) + goto bail; + hex = newhex; + } + hex->records[hex->nrecord++] = record; + if (record->type == HEX_RECORD_EOF) + done = 1; + } + /* + * Sort them into increasing addresses, except for EOF + */ + qsort(hex->records, hex->nrecord - 1, sizeof (struct hex_record *), + ccdbg_hex_record_compar); + return hex; + + bail: + ccdbg_hex_file_free(hex); + return NULL; + } + + struct hex_image * + ccdbg_hex_image_create(struct hex_file *hex) + { + struct hex_image *image; + struct hex_record *first, *last, *record; + int i; + uint32_t base, bound; + uint32_t offset; + int length; + + first = hex->records[0]; + last = hex->records[hex->nrecord - 2]; /* skip EOF */ + base = (uint32_t) first->address; + bound = (uint32_t) last->address + (uint32_t) last->length; + length = bound - base; + image = calloc(sizeof(struct hex_image) + length, 1); + if (!image) + return NULL; + image->address = base; + image->length = length; + memset(image->data, 0xff, length); + for (i = 0; i < hex->nrecord - 1; i++) { + record = hex->records[i]; + offset = record->address - base; + memcpy(image->data + offset, record->data, record->length); + } + return image; + } + + void + ccdbg_hex_image_free(struct hex_image *image) + { + free(image); + } + + int + ccdbg_hex_image_equal(struct hex_image *a, struct hex_image *b) + { + if (a->length != b->length) + return 0; + if (memcmp(a->data, b->data, a->length) != 0) + return 0; + return 1; + } diff --combined lib/ccdbg-memory.c index 00000000,878c5f97..554ac637 mode 000000,100644..100644 --- a/lib/ccdbg-memory.c +++ b/lib/ccdbg-memory.c @@@ -1,0 -1,179 +1,179 @@@ + /* + * 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" + + /* + * Read and write arbitrary memory through the debug port + */ + + static uint8_t memory_init[] = { + 3, MOV_DPTR_data16, 0, 0, + #define HIGH_START 2 + #define LOW_START 3 + 0, + }; + + + static uint8_t write8[] = { + 2, MOV_A_data, 0, + #define DATA_BYTE 2 + 1, MOVX_atDPTR_A, + 1, INC_DPTR, + 0 + }; + + static uint8_t read8[] = { + 1, MOVX_A_atDPTR, + 1, INC_DPTR, + 0, + }; + + uint8_t + ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) + { + int i, nl = 0; + struct ccstate state; + + if (dbg->usb) + return cc_usb_write_memory(dbg->usb, addr, bytes, nbytes); + ccdbg_state_save(dbg, &state, CC_STATE_ACC | CC_STATE_PSW | CC_STATE_DP); + memory_init[HIGH_START] = addr >> 8; + memory_init[LOW_START] = addr; + (void) ccdbg_execute(dbg, memory_init); + for (i = 0; i < nbytes; i++) { + write8[DATA_BYTE] = *bytes++; + ccdbg_execute(dbg, write8); + if ((i & 0xf) == 0xf) { + ccdbg_debug(CC_DEBUG_MEMORY, "."); + ccdbg_flush(CC_DEBUG_MEMORY); + nl = 1; + } + if ((i & 0xff) == 0xff) { + ccdbg_debug(CC_DEBUG_MEMORY, "\n"); + nl = 0; + } + } + ccdbg_state_restore(dbg, &state); + if (nl) + ccdbg_debug(CC_DEBUG_MEMORY, "\n"); + return 0; + } + + uint8_t + ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes) + { + int i, nl = 0; + struct ccstate state; + + if (ccdbg_rom_contains(dbg, addr, nbytes)) { + ccdbg_rom_replace_xmem(dbg, addr, bytes, nbytes); + return 0; + } + if (dbg->usb) + return cc_usb_read_memory(dbg->usb, addr, bytes, nbytes); + ccdbg_state_save(dbg, &state, CC_STATE_ACC | CC_STATE_PSW | CC_STATE_DP); + memory_init[HIGH_START] = addr >> 8; + memory_init[LOW_START] = addr; + (void) ccdbg_execute(dbg, memory_init); + for (i = 0; i < nbytes; i++) { + *bytes++ = ccdbg_execute(dbg, read8); + if ((i & 0xf) == 0xf) { + ccdbg_debug(CC_DEBUG_MEMORY, "."); + ccdbg_flush(CC_DEBUG_MEMORY); + nl = 1; + } + if ((i & 0xff) == 0xff) { + ccdbg_debug(CC_DEBUG_MEMORY, "\n"); + nl = 0; + } + } + ccdbg_state_replace_xmem(dbg, &state, addr, bytes, nbytes); + ccdbg_state_restore(dbg, &state); + if (nl) + ccdbg_debug(CC_DEBUG_MEMORY, "\n"); + return 0; + } + + uint8_t + ccdbg_write_uint8(struct ccdbg *dbg, uint16_t addr, uint8_t byte) + { + return ccdbg_write_memory(dbg, addr, &byte, 1); + } + + uint8_t + ccdbg_write_hex_image(struct ccdbg *dbg, struct hex_image *image, uint16_t offset) + { + ccdbg_write_memory(dbg, image->address + offset, image->data, image->length); + return 0; + } + + struct hex_image * + ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length) + { + struct hex_image *image; - ++ + image = calloc(sizeof(struct hex_image) + length, 1); + image->address = address; + image->length = length; + memset(image->data, 0xff, length); + ccdbg_read_memory(dbg, address, image->data, length); + return image; + } + + static uint8_t sfr_read[] = { + 2, MOV_A_direct, 0, + #define SFR_READ_ADDR 2 + 0, + }; + + static uint8_t sfr_write[] = { + 3, MOV_direct_data, 0, 0, + #define SFR_WRITE_ADDR 2 + #define SFR_WRITE_DATA 3 + 0, + }; + + uint8_t + ccdbg_read_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes) + { + int i; + struct ccstate state; + + ccdbg_state_save(dbg, &state, CC_STATE_ACC); + for (i = 0; i < nbytes; i++) { + sfr_read[SFR_READ_ADDR] = addr + i; + *bytes++ = ccdbg_execute(dbg, sfr_read); + } + ccdbg_state_replace_sfr(dbg, &state, addr, bytes, nbytes); + ccdbg_state_restore(dbg, &state); + return 0; + } + + uint8_t + ccdbg_write_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes) + { + int i; - ++ + for (i = 0; i < nbytes; i++) { + sfr_write[SFR_WRITE_ADDR] = addr + i; + sfr_write[SFR_WRITE_DATA] = *bytes++; + ccdbg_execute(dbg, sfr_write); + } + return 0; + } diff --combined lib/ccdbg-rom.c index 00000000,4559b4e7..71bed220 mode 000000,100644..100644 --- a/lib/ccdbg-rom.c +++ b/lib/ccdbg-rom.c @@@ -1,0 -1,63 +1,63 @@@ + /* + * 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" + + uint8_t + ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom) + { + if (dbg->rom) + ccdbg_hex_image_free(dbg->rom); + dbg->rom = rom; + return 0; + } + + uint8_t + ccdbg_rom_contains(struct ccdbg *dbg, uint16_t addr, int nbytes) + { + struct hex_image *rom = dbg->rom; + if (!rom) + return 0; + if (addr < rom->address || rom->address + rom->length < addr + nbytes) + return 0; + return 1; + } + + uint8_t + ccdbg_rom_replace_xmem(struct ccdbg *dbg, + uint16_t addr, uint8_t *bytes, int nbytes) + { + struct hex_image *rom = dbg->rom; + if (!rom) + return 0; - ++ + if (rom->address < addr + nbytes && addr < rom->address + rom->length) { + int start, stop; + + start = addr; + if (addr < rom->address) + start = rom->address; + stop = addr + nbytes; + if (rom->address + rom->length < stop) + stop = rom->address + rom->length; + memcpy(bytes + start - addr, rom->data + start - rom->address, + stop - start); + return 1; + } + return 0; + } diff --combined lib/ccdbg.h index 00000000,fe0ea3a0..4a2e3b9f mode 000000,100644..100644 --- a/lib/ccdbg.h +++ b/lib/ccdbg.h @@@ -1,0 -1,341 +1,341 @@@ + /* + * 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_H_ + #define _CCDBG_H_ + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include "ccdbg-debug.h" + #include "cc-bitbang.h" + #include "cc-usb.h" + + /* 8051 instructions + */ + #define NOP 0x00 + #define MOV_direct_data 0x75 + #define LJMP 0x02 + #define MOV_Rn_data(n) (0x78 | (n)) + #define DJNZ_Rn_rel(n) (0xd8 | (n)) + #define MOV_A_direct 0xe5 + #define MOV_direct1_direct2 0x85 + #define MOV_direct_A 0xf5 + #define MOV_DPTR_data16 0x90 + #define MOV_A_data 0x74 + #define MOVX_atDPTR_A 0xf0 + #define MOVX_A_atDPTR 0xe0 + #define INC_DPTR 0xa3 + #define TRAP 0xa5 + #define SJMP 0x80 + #define JB 0x20 + + /* 8051 special function registers + */ + + #define SFR_P0 0x80 + #define SFR_SP 0x81 + #define SFR_DPL0 0x82 + #define SFR_DPH0 0x83 + #define SFR_DPL1 0x84 + #define SFR_DPH1 0x85 + + /* flash controller */ + #define FWT 0xAB + #define FADDRL 0xAC + #define FADDRH 0xAD + #define FCTL 0xAE + # define FCTL_BUSY 0x80 + # define FCTL_BUSY_BIT 7 + # define FCTL_SWBSY 0x40 + # define FCTL_SWBSY_BIT 6 + # define FCTL_CONTRD 0x10 + # define FCTL_WRITE 0x02 + # define FCTL_ERASE 0x01 + #define FWDATA 0xAF + + #define SLEEP 0xBE + + /* clock controller */ + #define CLKCON 0xC6 + #define CLKCON_OSC32K 0x80 + #define CLKCON_OSC 0x40 + #define CLKCON_TICKSPD 0x38 + #define CLKCON_CLKSPD 0x07 + + /* I/O pins */ + #define P0 0x80 + #define P1 0x90 + #define P2 0xA0 + #define P0DIR 0xFD + #define P1DIR 0xFE + #define P2DIR 0xFF + + /* Bit-addressable accumulator */ + #define ACC(bit) (0xE0 | (bit)) + + /* Bit-addressable status word */ + #define PSW(bit) (0xD0 | (bit)) + + struct ccdbg { + struct cc_bitbang *bb; + struct cc_usb *usb; + struct hex_image *rom; + }; + + /* Intel hex file format data + */ + struct hex_record { + uint8_t length; + uint16_t address; + uint8_t type; + uint8_t checksum; + uint8_t data[0]; + }; + + struct hex_file { + int nrecord; + struct hex_record *records[0]; + }; + + struct hex_image { + uint16_t address; + uint16_t length; + uint8_t data[0]; + }; + + #define CC_STATE_ACC 0x1 + #define CC_STATE_PSW 0x2 + #define CC_STATE_DP 0x4 + + #define CC_STATE_NSFR 5 + + struct ccstate { + uint16_t mask; + uint8_t acc; + uint8_t sfr[CC_STATE_NSFR]; + }; + + #define HEX_RECORD_NORMAL 0x00 + #define HEX_RECORD_EOF 0x01 + #define HEX_RECORD_EXTENDED_ADDRESS 0x02 + + /* CC1111 debug port commands + */ + #define CC_CHIP_ERASE 0x14 + + #define CC_WR_CONFIG 0x1d + #define CC_RD_CONFIG 0x24 + # define CC_CONFIG_TIMERS_OFF (1 << 3) + # define CC_CONFIG_DMA_PAUSE (1 << 2) + # define CC_CONFIG_TIMER_SUSPEND (1 << 1) + # define CC_SET_FLASH_INFO_PAGE (1 << 0) + + #define CC_GET_PC 0x28 + #define CC_READ_STATUS 0x34 + # define CC_STATUS_CHIP_ERASE_DONE (1 << 7) + # define CC_STATUS_PCON_IDLE (1 << 6) + # define CC_STATUS_CPU_HALTED (1 << 5) + # define CC_STATUS_POWER_MODE_0 (1 << 4) + # define CC_STATUS_HALT_STATUS (1 << 3) + # define CC_STATUS_DEBUG_LOCKED (1 << 2) + # define CC_STATUS_OSCILLATOR_STABLE (1 << 1) + # define CC_STATUS_STACK_OVERFLOW (1 << 0) + + #define CC_SET_HW_BRKPNT 0x3b + # define CC_HW_BRKPNT_N(n) ((n) << 3) + # define CC_HW_BRKPNT_N_MASK (0x3 << 3) + # define CC_HW_BRKPNT_ENABLE (1 << 2) + + #define CC_HALT 0x44 + #define CC_RESUME 0x4c + #define CC_DEBUG_INSTR(n) (0x54|(n)) + #define CC_STEP_INSTR 0x5c + #define CC_STEP_REPLACE(n) (0x64|(n)) + #define CC_GET_CHIP_ID 0x68 + + /* ccdbg-command.c */ + void + ccdbg_debug_mode(struct ccdbg *dbg); + + void + ccdbg_reset(struct ccdbg *dbg); + + uint8_t + ccdbg_chip_erase(struct ccdbg *dbg); + + uint8_t + ccdbg_wr_config(struct ccdbg *dbg, uint8_t config); + + uint8_t + ccdbg_rd_config(struct ccdbg *dbg); + + uint16_t + ccdbg_get_pc(struct ccdbg *dbg); + + uint8_t + ccdbg_read_status(struct ccdbg *dbg); + + uint8_t + ccdbg_set_hw_brkpnt(struct ccdbg *dbg, uint8_t number, uint8_t enable, uint16_t addr); + + uint8_t + ccdbg_halt(struct ccdbg *dbg); + + uint8_t + ccdbg_resume(struct ccdbg *dbg); + + uint8_t + ccdbg_debug_instr(struct ccdbg *dbg, uint8_t *instr, int nbytes); + + void + ccdbg_debug_instr_discard(struct ccdbg *dbg, uint8_t *instr, int nbytes); + + void + ccdbg_debug_instr_queue(struct ccdbg *dbg, uint8_t *instr, int nbytes, + uint8_t *reply); + + uint8_t + ccdbg_step_instr(struct ccdbg *dbg); + + uint8_t + ccdbg_step_replace(struct ccdbg *dbg, uint8_t *instr, int nbytes); + + uint16_t + ccdbg_get_chip_id(struct ccdbg *dbg); + + uint8_t + ccdbg_execute(struct ccdbg *dbg, uint8_t *inst); - ++ + uint8_t + ccdbg_set_pc(struct ccdbg *dbg, uint16_t pc); - ++ + uint8_t + ccdbg_execute_hex_image(struct ccdbg *dbg, struct hex_image *image); + + /* ccdbg-flash.c */ + uint8_t + ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image); + + /* ccdbg-hex.c */ + struct hex_file * + ccdbg_hex_file_read(FILE *file, char *name); + + void + ccdbg_hex_file_free(struct hex_file *hex); + + struct hex_image * + ccdbg_hex_image_create(struct hex_file *hex); + + void + ccdbg_hex_image_free(struct hex_image *image); + + int + ccdbg_hex_image_equal(struct hex_image *a, struct hex_image *b); + + /* ccdbg-io.c */ + struct ccdbg * + ccdbg_open(void); + + void + ccdbg_close(struct ccdbg *dbg); + + void + ccdbg_cmd_write(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len); + + uint8_t + ccdbg_cmd_write_read8(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len); + + void + ccdbg_cmd_write_queue8(struct ccdbg *dbg, uint8_t cmd, + uint8_t *data, int len, uint8_t *reply); + + uint16_t + ccdbg_cmd_write_read16(struct ccdbg *dbg, uint8_t cmd, uint8_t *data, int len); + + void + ccdbg_send_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes); + + void + ccdbg_recv_bytes(struct ccdbg *dbg, uint8_t *bytes, int nbytes); + + void + ccdbg_sync(struct ccdbg *dbg); + + /* ccdbg-manual.c */ + + void + ccdbg_manual(struct ccdbg *dbg, FILE *input); + + /* ccdbg-memory.c */ + uint8_t + ccdbg_write_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes); + + uint8_t + ccdbg_read_memory(struct ccdbg *dbg, uint16_t addr, uint8_t *bytes, int nbytes); + + uint8_t + ccdbg_write_uint8(struct ccdbg *dbg, uint16_t addr, uint8_t byte); + + uint8_t + ccdbg_write_hex_image(struct ccdbg *dbg, struct hex_image *image, uint16_t offset); + + struct hex_image * + ccdbg_read_hex_image(struct ccdbg *dbg, uint16_t address, uint16_t length); + + uint8_t + ccdbg_read_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes); + + uint8_t + ccdbg_write_sfr(struct ccdbg *dbg, uint8_t addr, uint8_t *bytes, int nbytes); + + /* ccdbg-rom.c */ + uint8_t + ccdbg_set_rom(struct ccdbg *dbg, struct hex_image *rom); + + uint8_t + ccdbg_rom_contains(struct ccdbg *dbg, uint16_t addr, int nbytes); + + uint8_t + ccdbg_rom_replace_xmem(struct ccdbg *dbg, + uint16_t addrp, uint8_t *bytesp, int nbytes); + + /* ccdbg-state.c */ + uint8_t + ccdbg_state_save(struct ccdbg *dbg, struct ccstate *state, unsigned int mask); + + uint8_t + ccdbg_state_restore(struct ccdbg *dbg, struct ccstate *state); + + void + ccdbg_state_replace_xmem(struct ccdbg *dbg, struct ccstate *state, + uint16_t addr, uint8_t *bytes, int nbytes); + + void + ccdbg_state_replace_sfr(struct ccdbg *dbg, struct ccstate *state, + uint8_t addr, uint8_t *bytes, int nbytes); + + #endif /* _CCDBG_H_ */ diff --combined lib/cp-usb-async.c index 00000000,1fe09aad..6539394b mode 000000,100644..100644 --- a/lib/cp-usb-async.c +++ b/lib/cp-usb-async.c @@@ -1,0 -1,188 +1,188 @@@ + /* + * 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; + uint8_t value; + uint8_t set; + }; + + 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); + cp->ack = -1; + if (!cp->handle) { + libusb_exit(cp->ctx); + free(cp); + return NULL; + } + cp->value = 0; + cp->set = 0; + 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; + int ret; + + if (cp->set) { + value = (cp->value & ~mask) | (value & mask); + mask = value ^ cp->value; + } + cp->set = 1; + cp->value = value; + gpio_set = ((uint16_t) value << 8) | mask; + 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 = -1; + } diff --combined lib/cp-usb.c index 00000000,d227b78c..530848db mode 000000,100644..100644 --- a/lib/cp-usb.c +++ b/lib/cp-usb.c @@@ -1,0 -1,157 +1,157 @@@ + /* + * 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. + */ + + /* + * libusb interface to the GPIO pins on a CP2103. + * + * Various magic constants came from the cp210x driver published by silabs. + */ + + #include "cp-usb.h" + #include + #include + #include + + struct cp_usb { + usb_dev_handle *usb_dev; + uint8_t gpio; + }; + + #define CP2101_UART 0x00 + #define UART_ENABLE 0x0001 + #define UART_DISABLE 0x0000 + #define REQTYPE_HOST_TO_DEVICE 0x41 + #define REQTYPE_DEVICE_TO_HOST 0xc1 + + static int + cp_usb_gpio_get(struct cp_usb *cp, uint8_t *gpio_get) + { + return usb_control_msg(cp->usb_dev, /* dev */ + 0xc0, /* request */ + 0xff, /* requesttype */ + 0x00c2, /* value */ + 0, /* index */ + (char *) gpio_get, /* bytes */ + 1, /* size */ + 300); /* timeout */ + } + + static int + cp_usb_gpio_set(struct cp_usb *cp, uint8_t mask, uint8_t value) + { + uint16_t gpio_set = ((uint16_t) value << 8) | mask; + + return usb_control_msg(cp->usb_dev, /* dev */ + 0x40, /* request */ + 0xff, /* requesttype */ + 0x37e1, /* value */ + gpio_set, /* index */ + NULL, /* bytes */ + 0, /* size */ + 300); /* timeout */ + } + + static int + cp_usb_uart_enable_disable(struct cp_usb *cp, uint16_t enable) + { + return usb_control_msg(cp->usb_dev, + CP2101_UART, + REQTYPE_HOST_TO_DEVICE, + enable, + 0, + NULL, + 0, + 300); + } + + struct cp_usb * + cp_usb_open(void) + { + struct cp_usb *cp; + usb_dev_handle *dev_handle; + struct usb_device *dev = NULL; + struct usb_bus *bus, *busses; + int interface; + int ret; + uint8_t gpio; - ++ + usb_init(); + usb_find_busses(); + usb_find_devices(); - ++ + busses = usb_get_busses(); + for (bus = busses; bus; bus = bus->next) { + for (dev = bus->devices; dev; dev = dev->next) { + if (dev->descriptor.idVendor == 0x10c4 && + dev->descriptor.idProduct == 0xea60) + break; + } + if (dev) + break; + } + if (!dev){ + perror("No CP2103 found"); + return NULL; + } + cp = calloc(sizeof(struct cp_usb), 1); + interface = 0; + dev_handle = usb_open(dev); + usb_detach_kernel_driver_np(dev_handle, interface); + usb_claim_interface(dev_handle, interface); + cp->usb_dev = dev_handle; + ret = cp_usb_uart_enable_disable(cp, UART_DISABLE); + cp->gpio = 0xf; + ret = cp_usb_gpio_set(cp, 0xf, cp->gpio); + ret = cp_usb_gpio_get(cp, &gpio); + return cp; + } + + void + cp_usb_close(struct cp_usb *cp) + { + cp_usb_uart_enable_disable(cp, UART_DISABLE); + usb_close(cp->usb_dev); + free(cp); + } + + void + cp_usb_write(struct cp_usb *cp, uint8_t mask, uint8_t value) + { + uint8_t new_gpio; + int ret; + + new_gpio = (cp->gpio & ~mask) | (value & mask); + if (new_gpio != cp->gpio) { + ret = cp_usb_gpio_set(cp, new_gpio ^ cp->gpio, new_gpio); + if (ret < 0) + perror("gpio_set"); + cp->gpio = new_gpio; + } + } + + uint8_t + cp_usb_read(struct cp_usb *cp) + { + int ret; + uint8_t gpio; + + ret = cp_usb_gpio_get(cp, &gpio); + if (ret < 0) + perror("gpio_get"); + return gpio; + } diff --combined s51/commands index 00000000,77a98493..aba65cd0 mode 000000,100644..100644 --- a/s51/commands +++ b/s51/commands @@@ -1,0 -1,61 +1,60 @@@ + Listens on port 9756 for a command stream. + + Dump commands: + di - dump imem + ds - dump sprs + dx - dump xaddr + + Returns a string of hex pairs, each preceded by a space, + with 8 pairs per line + + Memory access commands: + set mem + dump + + is one of: + + xram - external ram or external stack + rom - code space + iram - internal ram or stack + sfr - special function register + + + dump + set bit + + bit addressable space + + Set PC: + + pc + + Sets PC to specified address + + pc + + Returns current PC + + Breakpoints + + break + clear + + Load a file + + file "" + + Execution control: + + run - run starting at - run - set temporary bp at ++ run - set temporary bp at + run - continue + next - step over calls(?) + step - step one instruction - ++ + reset - reset the simulator + res - synonym? - ++ + Error messages: + + start with "Error:" - diff --combined s51/s51-command.c index 00000000,02ecdddd..4f803060 mode 000000,100644..100644 --- a/s51/s51-command.c +++ b/s51/s51-command.c @@@ -1,0 -1,655 +1,654 @@@ + /* + * 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 "s51.h" + + static uint16_t start_address; + + static enum command_result + parse_int(char *value, int *result) + { + char *endptr; + + *result = strtol(value, &endptr, 0); + if (endptr == value) + return command_syntax; + return command_success; + } + + static enum command_result + parse_uint16(char *value, uint16_t *uint16) + { + int v; + enum command_result result; + + result = parse_int(value, &v); + if (result != command_success) + return command_error; + if (v < 0 || v > 0xffff) + return command_error; + *uint16 = v; + return command_success; + } + + static enum command_result + parse_uint8(char *value, uint8_t *uint8) + { + int v; + enum command_result result; + + result = parse_int(value, &v); + if (result != command_success) + return command_error; + if (v < 0 || v > 0xff) + return command_error; + *uint8 = v; + return command_success; + } + + enum command_result + command_quit (int argc, char **argv) + { + ccdbg_reset(s51_dbg); + exit(0); + return command_error; + } + + static void + dump_bytes(uint8_t *memory, int length, uint16_t start, char *format) + { + int group, i; - ++ + for (group = 0; group < length; group += 8) { + s51_printf(format, start + group); + for (i = group; i < length && i < group + 8; i++) + s51_printf("%02x ", memory[i]); + for (; i < group + 8; i++) + s51_printf(" "); + for (i = group; i < length && i < group + 8; i++) { + if (isascii(memory[i]) && isprint(memory[i])) + s51_printf("%c", memory[i]); + else + s51_printf("."); + } + s51_printf("\n"); + } + } + + enum command_result + command_di (int argc, char **argv) + { + uint16_t start, end; + uint8_t memory[65536]; + uint8_t status; + int length; - ++ + if (argc != 3) + return command_error; + if (parse_uint16(argv[1], &start) != command_success) + return command_error; + if (parse_uint16(argv[2], &end) != command_success) + return command_error; + length = (int) end - (int) start + 1; + status = ccdbg_read_memory(s51_dbg, start + 0xff00, memory, length); + dump_bytes(memory, length, start, "0x%02x "); + return command_success; + } + + enum command_result + command_ds (int argc, char **argv) + { + uint8_t start, end; + uint8_t memory[0x100]; + uint8_t status; + int length; - ++ + if (argc != 3) + return command_error; + if (parse_uint8(argv[1], &start) != command_success) + return command_error; + if (parse_uint8(argv[2], &end) != command_success) + return command_error; + length = (int) end - (int) start + 1; + status = ccdbg_read_sfr(s51_dbg, start, memory, length); + dump_bytes(memory, length, start, "0x%02x "); + return command_success; + } + + enum command_result + command_dx (int argc, char **argv) + { + uint16_t start, end; + uint8_t memory[65536]; + uint8_t status; + int length; - ++ + if (argc != 3) + return command_error; + if (parse_uint16(argv[1], &start) != command_success) + return command_error; + if (parse_uint16(argv[2], &end) != command_success) + return command_error; + length = (int) end - (int) start + 1; + status = ccdbg_read_memory(s51_dbg, start, memory, length); + dump_bytes(memory, length, start, "0x%04x "); + return command_success; + } + + enum command_result + command_set (int argc, char **argv) + { + uint16_t address; + uint8_t *data; + int len = argc - 3; + int i; + enum command_result ret = command_success; + + if (len < 0) + return command_error; + if (parse_uint16(argv[2], &address) != command_success) + return command_error; + if (len == 0) + return command_success; + data = malloc(len); + if (!data) + return command_error; + for (i = 0; i < len; i++) + if (parse_uint8(argv[i+3], &data[i]) != command_success) + return command_error; - ++ + if (strcmp(argv[1], "xram") == 0) { + ccdbg_write_memory(s51_dbg, address, data, len); + } else if (strcmp(argv[1], "iram") == 0) { + ccdbg_write_memory(s51_dbg, address + 0xff00, data, len); + } else if (strcmp(argv[1], "sfr") == 0) { + ccdbg_write_sfr(s51_dbg, (uint8_t) address, data, len); + } else + ret = command_error; + free(data); + return ret; + } + + enum command_result + command_dump (int argc, char **argv) + { + if (argv[1]) { + if (strcmp(argv[1], "rom") == 0 || + strcmp(argv[1], "xram") == 0) + return command_dx(argc-1, argv+1); + if (strcmp(argv[1], "iram") == 0) + return command_di(argc-1, argv+1); + if (strcmp(argv[1], "sfr") == 0) + return command_ds(argc-1, argv+1); + } + return command_error; + } + + enum command_result + command_file (int argc, char **argv) + { + struct hex_file *hex; + struct hex_image *image; + FILE *file; - ++ + if (argc != 2) + return command_error; + file = fopen (argv[1], "r"); + if (!file) + return command_error; + hex = ccdbg_hex_file_read(file, argv[1]); + fclose(file); + if (!hex) + return command_error; + if (hex->nrecord == 0) { + ccdbg_hex_file_free(hex); + return command_error; + } + image = ccdbg_hex_image_create(hex); + ccdbg_hex_file_free(hex); + start_address = image->address; + ccdbg_set_rom(s51_dbg, image); + return command_success; + } + + enum command_result + command_pc (int argc, char **argv) + { + uint16_t pc; + if (argv[1]) { + enum command_result result; + result = parse_uint16(argv[1], &pc); + if (result != command_success) + return result; + ccdbg_set_pc(s51_dbg, pc); + } else { + pc = ccdbg_get_pc(s51_dbg); + s51_printf(" 0x%04x 00\n", pc); + } + return command_success; + } + + struct cc_break { + int enabled; + int temporary; + uint16_t address; + }; + + #define CC_NUM_BREAKPOINTS 4 + + static struct cc_break breakpoints[CC_NUM_BREAKPOINTS]; + + static void + disable_breakpoint(int b) + { + uint8_t status; - ++ + status = ccdbg_set_hw_brkpnt(s51_dbg, b, 0, breakpoints[b].address); + if (status != 0x00 && status != 0xff) + s51_printf("disable_breakpoint status 0x%02x\n", status); + } + + static void + enable_breakpoint(int b) + { + uint8_t status; - ++ + status = ccdbg_set_hw_brkpnt(s51_dbg, b, 1, breakpoints[b].address); + if (status != 0xff) + s51_printf("enable_breakpoint status 0x%02x\n", status); + } + + static void + enable_breakpoints(void) + { + int b; + for (b = 0; b < CC_NUM_BREAKPOINTS; b++) + if (breakpoints[b].enabled) + enable_breakpoint(b); + } + + enum command_result + set_breakpoint(uint16_t address, int temporary) + { + int b; + uint8_t status; + for (b = 0; b < CC_NUM_BREAKPOINTS; b++) { + if (breakpoints[b].enabled == 0) + break; + if (breakpoints[b].address == address) + break; + } + if (b == CC_NUM_BREAKPOINTS) { + s51_printf("Error: too many breakpoints requested\n"); + return command_success; + } + if (breakpoints[b].enabled == 0) { + breakpoints[b].address = address; + enable_breakpoint(b); + } + ++breakpoints[b].enabled; + s51_printf("Breakpoint %d at 0x%04x\n", b, address); + breakpoints[b].temporary += temporary; + return command_success; + } + + enum command_result + clear_breakpoint(uint16_t address, int temporary) + { + int b; + uint8_t status; + + for (b = 0; b < CC_NUM_BREAKPOINTS; b++) { + if (breakpoints[b].enabled != 0 && + ((breakpoints[b].temporary != 0) == (temporary != 0)) && + breakpoints[b].address == address) + break; + } + if (b == CC_NUM_BREAKPOINTS) { + s51_printf("Error: no matching breakpoint found\n"); + return command_success; + } + --breakpoints[b].enabled; + breakpoints[b].temporary -= temporary; + if (breakpoints[b].enabled == 0) { + disable_breakpoint(b); + breakpoints[b].address = -1; + } + return command_success; + } + + + int + find_breakpoint(uint16_t address) + { + int b; + + for (b = 0; b < CC_NUM_BREAKPOINTS; b++) + if (breakpoints[b].enabled && breakpoints[b].address == address) + break; + if (b == CC_NUM_BREAKPOINTS) + return -1; + return b; + } + + enum command_result + command_break (int argc, char **argv) + { + int b; + uint16_t address; + enum command_result result; + + if (argc == 1) { + for (b = 0; b < CC_NUM_BREAKPOINTS; b++) + if (breakpoints[b].enabled) + s51_printf("Breakpoint %d 0x%04x\n", + b, breakpoints[b].address); + return command_success; + } + if (argc != 2) + return command_error; + result = parse_uint16(argv[1], &address); + if (result != command_success) + return result; + + return set_breakpoint(address, 0); + } + + enum command_result + command_clear (int argc, char **argv) + { + int b; + uint16_t address; + enum command_result result; + + if (argc != 2) + return command_error; + result = parse_uint16(argv[1], &address); + if (result != command_success) + return result; + return clear_breakpoint(address, 0); + } + + void + cc_stopped(uint8_t status) + { + uint16_t pc; + int b; + int code; + char *reason; + + pc = ccdbg_get_pc(s51_dbg); + if (status & CC_STATUS_CPU_HALTED) { + if ((status & CC_STATUS_HALT_STATUS) != 0) { + pc = pc - 1; + code = 104; + reason = "Breakpoint"; + b = find_breakpoint(pc); + if (b != -1 && breakpoints[b].temporary) + clear_breakpoint(pc, 1); + ccdbg_set_pc(s51_dbg, pc); + } else { + code = 105; + reason = "Interrupt"; + } + s51_printf("Stop at 0x%04x: (%d) %s\n", + pc, code, reason); + } + } + + uint8_t + cc_step(uint16_t pc) + { + int b; + uint8_t status; + + b = find_breakpoint(pc); + if (b != -1) + disable_breakpoint(b); + status = ccdbg_step_instr(s51_dbg); + if (b != -1) + enable_breakpoint(b); + return status; + } + + enum command_result + command_run (int argc, char **argv) + { + uint16_t start, end; + enum command_result result; + uint16_t pc; + uint8_t status; + int b; - ++ + if (argv[1]) { + result = parse_uint16(argv[1], &start); + if (result != command_success) + return result; + if (argv[2]) { + result = parse_uint16(argv[2], &end); + if (result != command_success) + return result; + } + if (start_address && start == 0) { + start = start_address; + s51_printf("Starting at 0x%04x\n", start); + } + ccdbg_set_pc(s51_dbg, start); + } + else + start = ccdbg_get_pc(s51_dbg); + s51_printf("Resume at 0x%04x\n", start); + pc = start; + b = find_breakpoint(pc); + if (b != -1) { + cc_step(pc); + pc = ccdbg_get_pc(s51_dbg); + if (find_breakpoint(pc) != -1) { + status = ccdbg_read_status(s51_dbg); + cc_stopped(status); + return command_success; + } + } + ccdbg_resume(s51_dbg); + result = cc_wait(); + return result; + } + + enum command_result + command_next (int argc, char **argv) + { + return command_step(argc, argv); + } + + enum command_result + command_step (int argc, char **argv) + { + uint16_t pc; + uint8_t opcode; + uint8_t a; + + a = cc_step(ccdbg_get_pc(s51_dbg)); + s51_printf(" ACC= 0x%02x\n", a); + pc = ccdbg_get_pc(s51_dbg); + ccdbg_read_memory(s51_dbg, pc, &opcode, 1); + s51_printf(" ? 0x%04x %02x\n", pc, opcode); + return command_success; + } + + enum command_result + command_load (int argc, char **argv) + { + char *filename = argv[1]; + FILE *file; + struct hex_file *hex; + struct hex_image *image; - ++ + if (!filename) + return command_error; + file = fopen(filename, "r"); + if (!file) { + perror(filename); + return command_error; + } + hex = ccdbg_hex_file_read(file, filename); + fclose(file); + if (!hex) { + return command_error; + } + image = ccdbg_hex_image_create(hex); + ccdbg_hex_file_free(hex); + if (!image) { + fprintf(stderr, "image create failed\n"); + return command_error; + } + if (image->address >= 0xf000) { + printf("Loading %d bytes to RAM at 0x%04x\n", + image->length, image->address); + ccdbg_write_hex_image(s51_dbg, image, 0); + } else { + fprintf(stderr, "Can only load to RAM\n"); + } + ccdbg_hex_image_free(image); + return command_success; + } + + enum command_result + command_halt (int argc, char **argv) + { + uint16_t pc; + ccdbg_halt(s51_dbg); + pc = ccdbg_get_pc(s51_dbg); + s51_printf("Halted at 0x%04x\n", pc); + return command_success; + } + + enum command_result + command_stop (int argc, char **argv) + { + return command_success; + } + + enum command_result + command_reset (int argc, char **argv) + { + ccdbg_debug_mode(s51_dbg); + ccdbg_halt(s51_dbg); + enable_breakpoints(); + return command_success; + } + + enum command_result + command_status(int argc, char **argv) + { + uint8_t status; + + status = ccdbg_read_status(s51_dbg); + if ((status & CC_STATUS_CHIP_ERASE_DONE) == 0) + s51_printf("\tChip erase in progress\n"); + if (status & CC_STATUS_PCON_IDLE) + s51_printf("\tCPU is idle (clock gated)\n"); + if (status & CC_STATUS_CPU_HALTED) + s51_printf("\tCPU halted\n"); + else + s51_printf("\tCPU running\n"); + if ((status & CC_STATUS_POWER_MODE_0) == 0) + s51_printf("\tPower Mode 1-3 selected\n"); + if (status & CC_STATUS_HALT_STATUS) + s51_printf("\tHalted by software or hw breakpoint\n"); + else + s51_printf("\tHalted by debug command\n"); + if (status & CC_STATUS_DEBUG_LOCKED) + s51_printf("\tDebug interface is locked\n"); + if ((status & CC_STATUS_OSCILLATOR_STABLE) == 0) + s51_printf("\tOscillators are not stable\n"); + if (status & CC_STATUS_STACK_OVERFLOW) + s51_printf("\tStack overflow\n"); + return command_success; + } + + static enum command_result + info_breakpoints(int argc, char **argv) + { + int b; + uint16_t address; + enum command_result result; + + if (argc == 1) { + s51_printf("Num Type Disp Hit Cnt Address What\n"); + for (b = 0; b < CC_NUM_BREAKPOINTS; b++) + if (breakpoints[b].enabled) { + s51_printf("%-3d fetch %s 1 1 0x%04x uc::disass() unimplemented\n", + b, + breakpoints[b].temporary ? "del " : "keep", + breakpoints[b].address); + } + return command_success; + } - ++ + } + + static enum command_result + info_help(int argc, char **argv); + + static struct command_function infos[] = { + { "breakpoints", "b", info_breakpoints, "[b]reakpoints", + "List current breakpoints\n" }, + { "help", "?", info_help, "help", + "Print this list\n" }, - ++ + { NULL, NULL, NULL, NULL, NULL }, + }; + + static enum command_result + info_help(int argc, char **argv) + { + return command_function_help(infos, argc, argv); + } + + enum command_result + command_info(int argc, char **argv) + { + struct command_function *func; - ++ + if (argc < 2) + return command_error; + func = command_string_to_function(infos, argv[1]); + if (!func) + return command_syntax; + return (*func->func)(argc-1, argv+1); + } + + enum command_result + cc_wait(void) + { + for(;;) { + uint8_t status; + status = ccdbg_read_status(s51_dbg); + if (status & CC_STATUS_CPU_HALTED) { + cc_stopped(status); + return command_success; + } + if (s51_interrupted || s51_check_input()) { - ++ + ccdbg_halt(s51_dbg); + status = ccdbg_read_status(s51_dbg); + cc_stopped(status); + return command_interrupt; + } + } + } - diff --combined s51/s51-main.c index 00000000,46b97b0c..4dbd4c60 mode 000000,100644..100644 --- a/s51/s51-main.c +++ b/s51/s51-main.c @@@ -1,0 -1,240 +1,239 @@@ + /* + * 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 "s51.h" + #include + #include + #include + #include + #include + #include + #include + + static int s51_port = 0; + static char *cpu = "8051"; + static double freq = 11059200; + char *s51_prompt = "> "; + struct ccdbg *s51_dbg; + int s51_interrupted = 0; + int s51_monitor = 0; + + static FILE *s51_input; + static FILE *s51_output; + + static void + usage(void) + { + fprintf(stderr, "You're doing it wrong.\n"); + exit(1); + } + + void s51_sigint() + { + s51_interrupted = 1; + } + + int + main(int argc, char **argv) + { + int flags, opt; + char *endptr; + struct sigvec vec, ovec; + + while ((opt = getopt(argc, argv, "PVvHhmt:X:c:r:Z:s:S:p:")) != -1) { + switch (opt) { + case 't': + cpu = optarg; + break; + case 'X': + freq = strtod(optarg, &endptr); + if (endptr == optarg) + usage(); + if (endptr[0] != '\0') { + if (!strcmp(endptr, "k")) + freq *= 1000; + else if (!strcmp(endptr, "M") ) + freq *= 1000000; + else + usage (); + } + break; + case 'c': + break; + case 'r': + case 'Z': + s51_port = strtol(optarg, &endptr, 0); + if (endptr == optarg || strlen(endptr) != 0) + usage(); + break; + case 's': + break; + case 'S': + break; + case 'p': + s51_prompt = optarg; + break; + case 'P': + s51_prompt = NULL; + break; + case 'V': + break; + case 'v': + break; + case 'H': + exit (0); + break; + case 'h': + usage (); + break; + case 'm': + s51_monitor = 1; + break; + } + } + if (s51_port) { + int l, r, one = 1; + int s; + struct sockaddr_in in; + + l = socket(AF_INET, SOCK_STREAM, 0); + if (l < 0) { + perror ("socket"); + exit(1); + } + r = setsockopt(l, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (int)); + if (r) { + perror("setsockopt"); + exit(1); + } + in.sin_family = AF_INET; + in.sin_port = htons(s51_port); + in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + r = bind(l, (struct sockaddr *) &in, sizeof (in)); + if (r) { + perror("bind"); + exit(1); + } + r = listen(l, 5); + if (r) { + perror("listen"); + exit(1); + } + for (;;) { + struct sockaddr_in client_addr; + socklen_t client_len = sizeof (struct sockaddr_in); - ++ + s = accept(l, (struct sockaddr *) + &client_addr, &client_len); + if (s < 0) { + perror("accept"); + exit(1); + } + s51_input = fdopen(s, "r"); + s51_output = fdopen(s, "w"); + if (!s51_input || !s51_output) { + perror("fdopen"); + exit(1); + } + vec.sv_handler = SIG_IGN; + vec.sv_mask = 0; + vec.sv_flags = 0; + sigvec(SIGINT, &vec, &ovec); + command_read(); + sigvec(SIGINT, &ovec, NULL); + fclose(s51_input); + fclose(s51_output); + } + } else { + s51_input = stdin; + s51_output = stdout; + vec.sv_handler = s51_sigint; + vec.sv_mask = 0; + vec.sv_flags = 0; + sigvec(SIGINT, &vec, &ovec); + command_read(); + } + exit(0); + } + + void + s51_printf(char *format, ...) + { + va_list ap; + + va_start(ap, format); + vfprintf(s51_output, format, ap); + if (s51_monitor) + vfprintf(stdout, format, ap); + va_end(ap); + } + + void + s51_putc(int c) + { + putc(c, s51_output); + } + + #include + #include + + int + s51_read_line(char *line, int len) + { + int ret; + if (s51_output == stdout && s51_input == stdin && s51_prompt) { + char *r; + + r = readline(s51_prompt); + if (r == NULL) + return 0; + strncpy (line, r, len); + line[len-1] = '\0'; + add_history(r); + return 1; + } else { + if (s51_prompt) + s51_printf("%s", s51_prompt); + else + s51_putc('\0'); + fflush(s51_output); + ret = fgets(line, len, s51_input) != NULL; + if (s51_monitor) + printf("> %s", line); + fflush(stdout); + } + return ret; + } + + int + s51_check_input(void) + { + struct pollfd input; + int r; + int c; + + input.fd = fileno(s51_input); + input.events = POLLIN; + r = poll(&input, 1, 0); + if (r > 0) { + char line[256]; + (void) s51_read_line(line, sizeof (line)); - return 1; ++ return 1; + } + return 0; + } - diff --combined s51/s51-parse.c index 00000000,aba45485..170c979d mode 000000,100644..100644 --- a/s51/s51-parse.c +++ b/s51/s51-parse.c @@@ -1,0 -1,242 +1,241 @@@ + /* + * 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 "s51.h" + + static struct command_function functions[] = { + { "help", "?", command_help, "help", "Print this list\n" }, + { "quit", "q", command_quit, "[q]uit", "Quit\n" }, + { "di", "di", command_di, "di ", + "Dump imem\n" }, + { "ds", "ds", command_ds, "ds ", + "Dump sprs\n" }, + { "dx", "dx", command_dx, "dx ", + "Dump xaddr\n" }, + { "set", "t", command_set, "se[t] mem
...", + "Set mem {xram|rom|iram|sfr}\n" + "set bit \n" }, + { "dump", "d", command_dump, "[d]ump ", + "Dump {xram|rom|iram|sfr} \n" }, + { "file", "file", command_file, "file ", + "Pretend to load executable from \n" }, + { "pc", "p", command_pc, "[p]c [addr]", + "Get or set pc value\n" }, + { "break", "b", command_break,"[b]reak ", + "Set break point\n" }, + { "clear", "c", command_clear,"[c]lear ", + "Clear break point\n" }, + { "run", "r", command_run, "[r]un [start] [stop]", + "Run with optional start and temp breakpoint addresses\n" }, + { "go", "g", command_run, "[g]o [start] [stop]", + "Run with optional start and temp breakpoint addresses\n" }, + { "next", "n", command_next, "[n]ext", + "Step over one instruction, past any call\n" }, + { "step", "s", command_step, "[s]tep", + "Single step\n" }, + { "load", "l", command_load, "[l]oad ", + "Load a hex file into memory or flash" }, + { "halt", "h", command_halt, "[h]alt", + "Halt the processor\n" }, + { "reset","res",command_reset, "[res]et", + "Reset the CPU\n" }, + { "status","status",command_status, "status", + "Display CC1111 debug status\n" }, + { "info", "i", command_info, "[i]info", + "Get information\n" }, + { "stop", "stop", command_stop, "stop", + "Ignored\n" }, + { NULL, NULL, NULL, NULL, NULL }, + }; + + #ifndef FALSE + #define FALSE 0 + #define TRUE 1 + #endif + + static int + string_to_int(char *s, int *v) + { + char *endptr; + + if (isdigit(s[0]) || s[0] == '-' || s[0] == '+') { + *v = strtol(s, &endptr, 0); + if (endptr == s) + return FALSE; + } else if (*s == '\'') { + s++; + if (*s == '\\') { + s++; + switch (*s) { + case 'n': + *v = '\n'; + break; + case 't': + *v = '\t'; + break; + default: + *v = (int) *s; + break; + } + } else + *v = (int) *s; + s++; + if (*s != '\'') + return FALSE; + } + else + return FALSE; + return TRUE; + } + + struct command_function * + command_string_to_function(struct command_function *functions, char *name) + { + int i; + for (i = 0; functions[i].name; i++) + if (!strcmp(name, functions[i].name) || + !strcmp(name, functions[i].alias)) + return &functions[i]; + return NULL; -} ++} + + enum command_result + command_function_help(struct command_function *functions, int argc, char **argv) + { + int i; + struct command_function *func; + + if (argc == 1) { + for (i = 0; functions[i].name; i++) + s51_printf("%-10s%s\n", functions[i].name, + functions[i].usage); + } else { + for (i = 1; i < argc; i++) { + func = command_string_to_function(functions, argv[i]); + if (!func) { + s51_printf("%-10s unknown command\n", argv[i]); + return command_syntax; + } + s51_printf("%-10s %s\n%s", func->name, + func->usage, func->help); + } + } + return command_debug; + } + + static int + command_split_into_words(char *line, char **argv) + { + char quotechar; + int argc; + + argc = 0; + while (*line) { + while (isspace(*line)) + line++; + if (!*line) + break; + if (*line == '"') { + quotechar = *line++; + *argv++ = line; + argc++; + while (*line && *line != quotechar) + line++; + if (*line) + *line++ = '\0'; + } else { + *argv++ = line; + argc++; + while (*line && !isspace(*line)) + line++; + if (*line) + *line++ = '\0'; + } + } + *argv = 0; + return argc; + } + + enum command_result + command_help(int argc, char **argv) + { + return command_function_help(functions, argc, argv); + } - ++ + void + command_syntax_error(int argc, char **argv) + { + s51_printf("Syntax error in:"); + while (*argv) + s51_printf(" %s", *argv++); + s51_printf("\n"); + } + + void + command_read (void) + { + int argc; + char line[1024]; + char *argv[20]; + enum command_result result; + struct command_function *func; + + s51_dbg = ccdbg_open (); + if (!s51_dbg) { + perror("ccdbg_open"); + exit(1); + } + ccdbg_debug_mode(s51_dbg); + ccdbg_halt(s51_dbg); + s51_printf("Welcome to the non-simulated processor\n"); + for (;;) { + if (s51_read_line (line, sizeof line) == 0) + break; + s51_interrupted = 0; + argc = command_split_into_words(line, argv); + if (argc > 0) { + func = command_string_to_function(functions, argv[0]); + if (!func) + command_syntax_error(argc, argv); + else + { + result = (*func->func)(argc, argv); + if (s51_interrupted) + result = command_interrupt; + switch (result) { + case command_syntax: + command_syntax_error(argc, argv); + break; + case command_error: + s51_printf("Error\n"); + break; + case command_success: + break; + case command_interrupt: + ccdbg_halt(s51_dbg); + s51_printf("Interrupted\n"); + break; + default: + break; + } + } + } + } + ccdbg_close(s51_dbg); + s51_printf("...\n"); + } - diff --combined s51/s51.1 index 00000000,c283950e..f2f59a52 mode 000000,100644..100644 --- a/s51/s51.1 +++ b/s51/s51.1 @@@ -1,0 -1,211 +1,211 @@@ + .\" + .\" Copyright © 2009 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. + .\" + .\" + .TH S51 1 "s51" "" + .SH NAME + s51 \- hex debugger for cc1111 processors + .SH SYNOPSIS + .B "s51" + [\-t \fIcpu-type\fP] + [\-X \fIfrequency\fP] + [\-c] + [\-r \fIlisten-port\fP] + [\-Z \fIlisten-port\fP] + [\-s] + [\-S] + [\-p \fIprompt\fP] + [\-V] + [\-v] + [\-H] + [\-h] + [\-m] + .SH DESCRIPTION + .I s51 + connects to a cc1111 processor through a cp1203-based USB-to-serial + converter board, using the GPIO pins available on that chip. It provides an + interface compatible with the 8051 emulator of the same name (s51), but + communicating with the real chip instead of an emulation. Using a modified + version of the SDCC debugger (sdcdb), you can control program execution + on the target machine at source-level. + + .SH OPTIONS + The command line options are designed to be compatible with the 8051 + emulator so that it can be used with sdcdb. As such, they're all one letter + long. + .IP "\-t \fIcpu-type\fP" + The 8051 emulator can operate as one of several different chips. Oddly, the + real hardware cannot, so this option is ignored. + .IP "\-X \fIfrequency\fP" + Similarly, the emulator can pretend to run at an arbitrary frequency + which the real hardware cannot do. Ignored. + .IP "\-c" + .IP "\-s" + .IP "\-S" + .IP "\-v" + .IP "\-V" + All ignored. + .IP "\-r \fIlisten-port\fP, -Z \fIlisten-port\fP" + The emulator and sdcdb communicate through a network socket. This option + switches the debugger from communicating through stdin/stdout to listening + on a specific network port instead. Once a connection is made, the debugger + continues on, using that network port for command input and output. The + debugger uses port 9756, and attempts to connect before launching s51, so if + s51 is listening on this port before sdcdb is started, sdcdb will end up + talking to the existing s51 instance. That's often useful for debugging s51 + itself. + .IP "\-p \fIprompt\fP" + This sets the command prompt to the specified string. + .IP "\-P" + This sets the command prompt to a single NUL character. This is for use by + sdcdb. + .IP "\-h" + This should print a usage message, but does nothing useful currently. + .IP "\-m" + This option is not present in the original 8051 emulator, and causes s51 to + dump all commands and replies that are received from and sent to sdcdb. + .SH COMMANDS + Once started, s51 connects to the cc1111 via the CP2103 using libusb2 and + then reads and executes commands, either from stdin, or the nework + connection to sdcdb. + .PP + Unlike the command line, s51 contains built-in help for each of these + commands, via the 'help' command. Most of the commands are available in a + long form and a single character short form. Below, the short form follows + the long form after a comma. + .IP "help, ? {command}" + Without arguments, prints a list of available commands. With an argument + prints more detail about the specific command + .IP "quit, q" + Terminates the application, without changing the state of the target + processor. + .IP "di [start] [end]" + Dumps imem (256 bytes of "internal" memory) from start to end (inclusive). + .IP "ds [start] [end]" + Dumps sprs from start to end (inclusive). Note that while most sprs are + visible in the global address space, some are not, so use this command + instead of "dx" to read them. + .IP "dx [start] [end]" + Dump external (global) memory from start to end (inclusive). + .IP "set, t [start] {data ...}" + Store to the memory space specified by prefix where prefix is one of "xram", + "rom", "iram", or "sfr". Store bytes starting at start. + .IP "dump, d [start] [end]" + Dump from the memory space specified by prefix, where prefix is one of + "xram", "rom", "iram" or "sfr". Dumps from start to end (inclusive). + .IP "file [filename]" + Specifies an intel-format hex file (ihx) that contains the contents of the + rom area loaded into the cc1111. This is used to respond to requests to dump + rom memory contents without getting them from the cc1111 (which is slow). + .IP "pc, p {address}" + If the address argument is given, this sets the program counter to the + specified value. Otherwise, the current program counter value is displayed. + .IP "break, b [address]" + Sets a breakpoint at the specified address. This uses the built-in hardware + breakpoint support in the cc1111. As a result, it supports no more than four + breakpoints at once. You must therefore use a modified version of sdcdb which + changes how program execution is controlled to work within this limit. + .IP "clear, c [address]" + Clear a breakpoint from the specified address. + .IP "run, r, go, g {start} {stop}" + Resumes execution of the program. If the start argument is present, then it + begins at that address, otherwise it continues running at the current pc. If + a stop argument is present, then a temporary breakpoint is set at that + address. This temporary breakpoint will be removed when execution hits it. + .IP "next, n" + Step one instruction. In the original s51 program this would ignore + subroutines, but as sdcdb doesn't require this functionality, it's not + available here. + .IP "step, s" + Step one instruction. + .IP "load, l [filename]" + This is not implemented, but it is supposed to load a hex file into flash. + Use the ccload program instead. + .IP "halt, h" + Halt the processor. This is the only command which can be sent while the + program is running. It is ignored at other times. + .IP "reset, res" + Reset the processor. This pulls the reset pin low and re-enables debug mode. + Check the cc1111 documentation to see precisely what this does. + .IP "status" + This dumps the cc1111 debug status register. + .IP "info, i breakpoints, b" + List the current breakpoints. + .IP "info, i help, ?" + List the things you can get info on. + .IP "stop" + This doesn't do anything and is present only to retain compatibility with + the original 8051 emulator. + .SH "BOARD BRINGUP DEBUGGING" -.PP ++.PP + While the original purpose for this program was to connect the source + debugger with the hardware, it can also be used as a low-level hex debugger + all on its own. In particular, all of the cc1111 peripherals can be + manipulated directly from the s51 command line. + .IP "Starting s51" + If the CP2103 is plugged in, and the CC1111 is connected correctly, the -\'s51\' command itself should connect to the device without trouble. ++\'s51\' command itself should connect to the device without trouble. + Note that the CP2103 must have the GPIO pins configured correctly as well. + .IP + $ s51 + .br + Welcome to the non-simulated processor + .br + > status + .br + CPU halted + .br + Halted by debug command + .br + > + .IP "Turning on LEDs" + Two of the cc1111 GPIO pins, P1_0 and P1_1 are capable of driving external + LEDs. To control these, set the Port 1 direction bits to make these output + pins and then change the Port 1 data to set them high or low: + .IP + > set sfr 0xfe 0x02 # set P1DIR to 0x2 + .br + > set sfr 0x90 0x02 # set P1_1 to high + .br + > set sfr 0x90 0x00 # set P1_1 to low + .IP "Reading the A/D converters" + The six A/D converter inputs can each be connected to any of the P0 pins, + ground, the A/D voltage refernece, an internal temperature sensor or VDD/3. + To read one of these values, select an A/D converter to use then start the + conversion process. The cc1111 manual has the table for selecting the input + on page 144. + .IP + To configure one of the P0 pins for use by the A/D unit, we program the + ADCCFG register, setting the bits in that which match the pins desired: + .IP + > set sfr 0xf2 0x3f # enable all 6 A/D inputs + .IP + To trigger a single conversion, we ask the A/D unit to perform an 'extra' + conversion, which means to do a single conversion not a whole sequence of + conversions. This is controlled by the ADCCON3 register at 0xB6: + .IP + > set sfr 0xb6 0xb2 # sample P0_2 using 12 bits of precision + .br + > ds 0xba 0xbb # dump the ADC data low and high regs + .br + > set sfr 0xb6 0xbe # sample internal temperature sensor + .br + > ds 0xba 0xbb # dump the ADC data low and high regs + .SH "SEE ALSO" + sdcdb(1), ccload(1) + .SH AUTHOR + Keith Packard diff --combined target/adc-serial/adc_serial.c index 00000000,eba58744..1f7b6880 mode 000000,100644..100644 --- a/target/adc-serial/adc_serial.c +++ b/target/adc-serial/adc_serial.c @@@ -1,0 -1,578 +1,578 @@@ + /* + * 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 + + /* + * Test ADC in DMA mode + */ + + sfr at 0x80 P0; + sfr at 0x90 P1; + sfr at 0xA0 P2; + sfr at 0xC6 CLKCON; + sfr at 0xbe SLEEP; + + # define SLEEP_USB_EN (1 << 7) + # define SLEEP_XOSC_STB (1 << 6) + + sfr at 0xF1 PERCFG; + #define PERCFG_T1CFG_ALT_1 (0 << 6) + #define PERCFG_T1CFG_ALT_2 (1 << 6) + + #define PERCFG_T3CFG_ALT_1 (0 << 5) + #define PERCFG_T3CFG_ALT_2 (1 << 5) + + #define PERCFG_T4CFG_ALT_1 (0 << 4) + #define PERCFG_T4CFG_ALT_2 (1 << 4) + + #define PERCFG_U1CFG_ALT_1 (0 << 1) + #define PERCFG_U1CFG_ALT_2 (1 << 1) + + #define PERCFG_U0CFG_ALT_1 (0 << 0) + #define PERCFG_U0CFG_ALT_2 (1 << 0) + + sfr at 0xF2 ADCCFG; + sfr at 0xF3 P0SEL; + sfr at 0xF4 P1SEL; + sfr at 0xF5 P2SEL; + + sfr at 0xFD P0DIR; + sfr at 0xFE P1DIR; + sfr at 0xFF P2DIR; + sfr at 0x8F P0INP; + sfr at 0xF6 P1INP; + sfr at 0xF7 P2INP; + + sfr at 0x89 P0IFG; + sfr at 0x8A P1IFG; + sfr at 0x8B P2IFG; + + sbit at 0x90 P1_0; + sbit at 0x91 P1_1; + sbit at 0x92 P1_2; + sbit at 0x93 P1_3; + sbit at 0x94 P1_4; + sbit at 0x95 P1_5; + sbit at 0x96 P1_6; + sbit at 0x97 P1_7; + + /* + * UART registers + */ + + sfr at 0x86 U0CSR; + sfr at 0xF8 U1CSR; + + /* + * IRCON2 + */ + sfr at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ + + sbit at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ + sbit at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ + sbit at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ + sbit at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ + sbit at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ + sbit at 0xEB P1IF; /* Port1 interrupt flag */ + sbit at 0xEC WDTIF; /* Watchdog timer interrupt flag */ + + # define UxCSR_MODE_UART (1 << 7) + # define UxCSR_MODE_SPI (0 << 7) + # define UxCSR_RE (1 << 6) + # define UxCSR_SLAVE (1 << 5) + # define UxCSR_MASTER (0 << 5) + # define UxCSR_FE (1 << 4) + # define UxCSR_ERR (1 << 3) + # define UxCSR_RX_BYTE (1 << 2) + # define UxCSR_TX_BYTE (1 << 1) + # define UxCSR_ACTIVE (1 << 0) + + sfr at 0xc4 U0UCR; + sfr at 0xfb U1UCR; + + # define UxUCR_FLUSH (1 << 7) + # define UxUCR_FLOW_DISABLE (0 << 6) + # define UxUCR_FLOW_ENABLE (1 << 6) + # define UxUCR_D9_EVEN_PARITY (0 << 5) + # define UxUCR_D9_ODD_PARITY (1 << 5) + # define UxUCR_BIT9_8_BITS (0 << 4) + # define UxUCR_BIT9_9_BITS (1 << 4) + # define UxUCR_PARITY_DISABLE (0 << 3) + # define UxUCR_PARITY_ENABLE (1 << 3) + # define UxUCR_SPB_1_STOP_BIT (0 << 2) + # define UxUCR_SPB_2_STOP_BITS (1 << 2) + # define UxUCR_STOP_LOW (0 << 1) + # define UxUCR_STOP_HIGH (1 << 1) + # define UxUCR_START_LOW (0 << 0) + # define UxUCR_START_HIGH (1 << 0) + + sfr at 0xc5 U0GCR; + sfr at 0xfc U1GCR; + + # define UxGCR_CPOL_NEGATIVE (0 << 7) + # define UxGCR_CPOL_POSITIVE (1 << 7) + # define UxGCR_CPHA_FIRST_EDGE (0 << 6) + # define UxGCR_CPHA_SECOND_EDGE (1 << 6) + # define UxGCR_ORDER_LSB (0 << 5) + # define UxGCR_ORDER_MSB (1 << 5) + # define UxGCR_BAUD_E_MASK (0x1f) + # define UxGCR_BAUD_E_SHIFT 0 + + sfr at 0xc1 U0DBUF; + sfr at 0xf9 U1DBUF; + sfr at 0xc2 U0BAUD; + sfr at 0xfa U1BAUD; + + #define DEBUG P1_1 + + + # define DMA_LEN_HIGH_VLEN_MASK (7 << 5) + # define DMA_LEN_HIGH_VLEN_LEN (0 << 5) + # define DMA_LEN_HIGH_VLEN_PLUS_1 (1 << 5) + # define DMA_LEN_HIGH_VLEN (2 << 5) + # define DMA_LEN_HIGH_VLEN_PLUS_2 (3 << 5) + # define DMA_LEN_HIGH_VLEN_PLUS_3 (4 << 5) + # define DMA_LEN_HIGH_MASK (0x1f) + + # define DMA_CFG0_WORDSIZE_8 (0 << 7) + # define DMA_CFG0_WORDSIZE_16 (1 << 7) + # define DMA_CFG0_TMODE_MASK (3 << 5) + # define DMA_CFG0_TMODE_SINGLE (0 << 5) + # define DMA_CFG0_TMODE_BLOCK (1 << 5) + # define DMA_CFG0_TMODE_REPEATED_SINGLE (2 << 5) + # define DMA_CFG0_TMODE_REPEATED_BLOCK (3 << 5) + + /* + * DMA triggers + */ + # define DMA_CFG0_TRIGGER_NONE 0 + # define DMA_CFG0_TRIGGER_PREV 1 + # define DMA_CFG0_TRIGGER_T1_CH0 2 + # define DMA_CFG0_TRIGGER_T1_CH1 3 + # define DMA_CFG0_TRIGGER_T1_CH2 4 + # define DMA_CFG0_TRIGGER_T2_OVFL 6 + # define DMA_CFG0_TRIGGER_T3_CH0 7 + # define DMA_CFG0_TRIGGER_T3_CH1 8 + # define DMA_CFG0_TRIGGER_T4_CH0 9 + # define DMA_CFG0_TRIGGER_T4_CH1 10 + # define DMA_CFG0_TRIGGER_IOC_0 12 + # define DMA_CFG0_TRIGGER_IOC_1 13 + # define DMA_CFG0_TRIGGER_URX0 14 + # define DMA_CFG0_TRIGGER_UTX0 15 + # define DMA_CFG0_TRIGGER_URX1 16 + # define DMA_CFG0_TRIGGER_UTX1 17 + # define DMA_CFG0_TRIGGER_FLASH 18 + # define DMA_CFG0_TRIGGER_RADIO 19 + # define DMA_CFG0_TRIGGER_ADC_CHALL 20 + # define DMA_CFG0_TRIGGER_ADC_CH0 21 + # define DMA_CFG0_TRIGGER_ADC_CH1 22 + # define DMA_CFG0_TRIGGER_ADC_CH2 23 + # define DMA_CFG0_TRIGGER_ADC_CH3 24 + # define DMA_CFG0_TRIGGER_ADC_CH4 25 + # define DMA_CFG0_TRIGGER_ADC_CH5 26 + # define DMA_CFG0_TRIGGER_ADC_CH6 27 + # define DMA_CFG0_TRIGGER_I2SRX 27 + # define DMA_CFG0_TRIGGER_ADC_CH7 28 + # define DMA_CFG0_TRIGGER_I2STX 28 + # define DMA_CFG0_TRIGGER_ENC_DW 29 + # define DMA_CFG0_TRIGGER_DNC_UP 30 + + # define DMA_CFG1_SRCINC_MASK (3 << 6) + # define DMA_CFG1_SRCINC_0 (0 << 6) + # define DMA_CFG1_SRCINC_1 (1 << 6) + # define DMA_CFG1_SRCINC_2 (2 << 6) + # define DMA_CFG1_SRCINC_MINUS_1 (3 << 6) + + # define DMA_CFG1_DESTINC_MASK (3 << 4) + # define DMA_CFG1_DESTINC_0 (0 << 4) + # define DMA_CFG1_DESTINC_1 (1 << 4) + # define DMA_CFG1_DESTINC_2 (2 << 4) + # define DMA_CFG1_DESTINC_MINUS_1 (3 << 4) + + # define DMA_CFG1_IRQMASK (1 << 3) + # define DMA_CFG1_M8 (1 << 2) + + # define DMA_CFG1_PRIORITY_MASK (3 << 0) + # define DMA_CFG1_PRIORITY_LOW (0 << 0) + # define DMA_CFG1_PRIORITY_NORMAL (1 << 0) + # define DMA_CFG1_PRIORITY_HIGH (2 << 0) + + /* + * DMAARM - DMA Channel Arm + */ + + sfr at 0xD6 DMAARM; + + # define DMAARM_ABORT (1 << 7) + # define DMAARM_DMAARM4 (1 << 4) + # define DMAARM_DMAARM3 (1 << 3) + # define DMAARM_DMAARM2 (1 << 2) + # define DMAARM_DMAARM1 (1 << 1) + # define DMAARM_DMAARM0 (1 << 0) + + /* + * DMAREQ - DMA Channel Start Request and Status + */ + + sfr at 0xD7 DMAREQ; + + # define DMAREQ_DMAREQ4 (1 << 4) + # define DMAREQ_DMAREQ3 (1 << 3) + # define DMAREQ_DMAREQ2 (1 << 2) + # define DMAREQ_DMAREQ1 (1 << 1) + # define DMAREQ_DMAREQ0 (1 << 0) + + /* + * DMA configuration 0 address + */ + + sfr at 0xD5 DMA0CFGH; + sfr at 0xD4 DMA0CFGL; + + /* + * DMA configuration 1-4 address + */ + + sfr at 0xD3 DMA1CFGH; + sfr at 0xD2 DMA1CFGL; + + /* + * DMAIRQ - DMA Interrupt Flag + */ + + sfr at 0xD1 DMAIRQ; + + # define DMAIRQ_DMAIF4 (1 << 4) + # define DMAIRQ_DMAIF3 (1 << 3) + # define DMAIRQ_DMAIF2 (1 << 2) + # define DMAIRQ_DMAIF1 (1 << 1) + # define DMAIRQ_DMAIF0 (1 << 0) + + struct cc_dma_channel { + uint8_t src_high; + uint8_t src_low; + uint8_t dst_high; + uint8_t dst_low; + uint8_t len_high; + uint8_t len_low; + uint8_t cfg0; + uint8_t cfg1; + }; + + /* + * ADC Data register, low and high + */ + sfr at 0xBA ADCL; + sfr at 0xBB ADCH; + __xdata __at (0xDFBA) volatile uint16_t ADCXDATA; + + /* + * ADC Control Register 1 + */ + sfr at 0xB4 ADCCON1; + + # define ADCCON1_EOC (1 << 7) /* conversion complete */ + # define ADCCON1_ST (1 << 6) /* start conversion */ + + # define ADCCON1_STSEL_MASK (3 << 4) /* start select */ + # define ADCCON1_STSEL_EXTERNAL (0 << 4) /* P2_0 pin triggers */ + # define ADCCON1_STSEL_FULLSPEED (1 << 4) /* full speed, no waiting */ + # define ADCCON1_STSEL_TIMER1 (2 << 4) /* timer 1 channel 0 */ + # define ADCCON1_STSEL_START (3 << 4) /* set start bit */ + + # define ADCCON1_RCTRL_MASK (3 << 2) /* random number control */ + # define ADCCON1_RCTRL_COMPLETE (0 << 2) /* operation completed */ + # define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2) /* Clock the LFSR once */ + + /* + * ADC Control Register 2 + */ + sfr at 0xB5 ADCCON2; + + # define ADCCON2_SREF_MASK (3 << 6) /* reference voltage */ + # define ADCCON2_SREF_1_25V (0 << 6) /* internal 1.25V */ + # define ADCCON2_SREF_EXTERNAL (1 << 6) /* external on AIN7 cc1110 */ + # define ADCCON2_SREF_VDD (2 << 6) /* VDD on the AVDD pin */ + # define ADCCON2_SREF_EXTERNAL_DIFF (3 << 6) /* external on AIN6-7 cc1110 */ + + # define ADCCON2_SDIV_MASK (3 << 4) /* decimation rate */ + # define ADCCON2_SDIV_64 (0 << 4) /* 7 bits */ + # define ADCCON2_SDIV_128 (1 << 4) /* 9 bits */ + # define ADCCON2_SDIV_256 (2 << 4) /* 10 bits */ + # define ADCCON2_SDIV_512 (3 << 4) /* 12 bits */ + + # define ADCCON2_SCH_MASK (0xf << 0) /* Sequence channel select */ + # define ADCCON2_SCH_SHIFT 0 + # define ADCCON2_SCH_AIN0 (0 << 0) + # define ADCCON2_SCH_AIN1 (1 << 0) + # define ADCCON2_SCH_AIN2 (2 << 0) + # define ADCCON2_SCH_AIN3 (3 << 0) + # define ADCCON2_SCH_AIN4 (4 << 0) + # define ADCCON2_SCH_AIN5 (5 << 0) + # define ADCCON2_SCH_AIN6 (6 << 0) + # define ADCCON2_SCH_AIN7 (7 << 0) + # define ADCCON2_SCH_AIN0_AIN1 (8 << 0) + # define ADCCON2_SCH_AIN2_AIN3 (9 << 0) + # define ADCCON2_SCH_AIN4_AIN5 (0xa << 0) + # define ADCCON2_SCH_AIN6_AIN7 (0xb << 0) + # define ADCCON2_SCH_GND (0xc << 0) + # define ADCCON2_SCH_VREF (0xd << 0) + # define ADCCON2_SCH_TEMP (0xe << 0) + # define ADCCON2_SCH_VDD_3 (0xf << 0) + + + /* + * ADC Control Register 3 + */ + + sfr at 0xB6 ADCCON3; + + # define ADCCON3_EREF_MASK (3 << 6) /* extra conversion reference */ + # define ADCCON3_EREF_1_25 (0 << 6) /* internal 1.25V */ + # define ADCCON3_EREF_EXTERNAL (1 << 6) /* external AIN7 cc1110 */ + # define ADCCON3_EREF_VDD (2 << 6) /* VDD on the AVDD pin */ + # define ADCCON3_EREF_EXTERNAL_DIFF (3 << 6) /* external AIN6-7 cc1110 */ + # define ADCCON2_EDIV_MASK (3 << 4) /* extral decimation */ + # define ADCCON2_EDIV_64 (0 << 4) /* 7 bits */ + # define ADCCON2_EDIV_128 (1 << 4) /* 9 bits */ + # define ADCCON2_EDIV_256 (2 << 4) /* 10 bits */ + # define ADCCON2_EDIV_512 (3 << 4) /* 12 bits */ + # define ADCCON3_ECH_MASK (0xf << 0) /* Sequence channel select */ + # define ADCCON3_ECH_SHIFT 0 + # define ADCCON3_ECH_AIN0 (0 << 0) + # define ADCCON3_ECH_AIN1 (1 << 0) + # define ADCCON3_ECH_AIN2 (2 << 0) + # define ADCCON3_ECH_AIN3 (3 << 0) + # define ADCCON3_ECH_AIN4 (4 << 0) + # define ADCCON3_ECH_AIN5 (5 << 0) + # define ADCCON3_ECH_AIN6 (6 << 0) + # define ADCCON3_ECH_AIN7 (7 << 0) + # define ADCCON3_ECH_AIN0_AIN1 (8 << 0) + # define ADCCON3_ECH_AIN2_AIN3 (9 << 0) + # define ADCCON3_ECH_AIN4_AIN5 (0xa << 0) + # define ADCCON3_ECH_AIN6_AIN7 (0xb << 0) + # define ADCCON3_ECH_GND (0xc << 0) + # define ADCCON3_ECH_VREF (0xd << 0) + # define ADCCON3_ECH_TEMP (0xe << 0) + # define ADCCON3_ECH_VDD_3 (0xf << 0) + + sfr at 0xF2 ADCCFG; + + #define nop() _asm nop _endasm; + + void + delay (unsigned char n) + { + unsigned char i = 0; + unsigned char j = 0; + + n++; + while (--n != 0) + while (--i != 0) + while (--j != 0) + nop(); + } + + void + debug_byte(uint8_t byte) + { + uint8_t s; + + for (s = 0; s < 8; s++) { + DEBUG = byte & 1; + delay(5); + byte >>= 1; + } + } + + struct cc_dma_channel __xdata dma_config; + + #define ADC_LEN 6 + + /* The DMA engine writes to XDATA in MSB order */ + struct dma_xdata16 { + uint8_t high; + uint8_t low; + }; + + struct dma_xdata16 adc_output[ADC_LEN]; + + #define DMA_XDATA16(a,n) ((uint16_t) ((a)[n].high << 8) | (uint16_t) (a[n].low)) + + #define ADDRH(a) (((uint16_t) (a)) >> 8) + #define ADDRL(a) (((uint16_t) (a))) + + void + adc_init(void) + { + dma_config.cfg0 = (DMA_CFG0_WORDSIZE_16 | + DMA_CFG0_TMODE_REPEATED_SINGLE | + DMA_CFG0_TRIGGER_ADC_CHALL); + dma_config.cfg1 = (DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_NORMAL); - ++ + dma_config.src_high = ADDRH(&ADCXDATA); + dma_config.src_low = ADDRL(&ADCXDATA); + dma_config.dst_high = ADDRH(adc_output); + dma_config.dst_low = ADDRL(adc_output); + dma_config.len_high = 0; + dma_config.len_low = ADC_LEN; + DMA0CFGH = ADDRH(&dma_config); + DMA0CFGL = ADDRL(&dma_config); + ADCCFG = ((1 << 0) | /* acceleration */ + (1 << 1) | /* pressure */ + (1 << 2) | /* temperature */ + (1 << 3) | /* battery voltage */ + (1 << 4) | /* drogue sense */ + (1 << 5)); /* main sense */ - ++ + ADCCON1 = (ADCCON1_STSEL_START); /* ST bit triggers */ + ADCCON2 = (ADCCON2_SREF_VDD | /* reference voltage is VDD */ + ADCCON2_SDIV_512 | /* 12 bit ADC results */ + ADCCON2_SCH_AIN5); /* sample all 6 inputs */ + } + + void + adc_run(void) + { + DMAIRQ &= ~1; + DMAARM |= 1; + ADCCON1 |= ADCCON1_ST; + while ((DMAIRQ & 1) == 0) + ; + } + + /* + * This version uses the USART in UART mode + */ + void + usart_init(void) + { + P1DIR |= (1 << 2); + /* + * Configure the peripheral pin choices + * for both of the serial ports + * + * Note that telemetrum will use U1CFG_ALT_2 + * but that overlaps with SPI ALT_2, so until + * we can test that this works, we'll set this + * to ALT_1 + */ + PERCFG = (PERCFG_U1CFG_ALT_2 | + PERCFG_U0CFG_ALT_1); + + /* + * Make the UART pins controlled by the UART + * hardware + */ + P1SEL |= ((1 << 6) | (1 << 7)); + + /* + * UART mode with the receiver enabled + */ + U1CSR = (UxCSR_MODE_UART | + UxCSR_RE); + /* + * Pick a 38.4kbaud rate + */ + U1BAUD = 163; + U1GCR = 10 << UxGCR_BAUD_E_SHIFT; /* 38400 */ + // U1GCR = 3 << UxGCR_BAUD_E_SHIFT; /* 300 */ + /* + * Reasonable serial parameters + */ + U1UCR = (UxUCR_FLUSH | + UxUCR_FLOW_DISABLE | + UxUCR_D9_ODD_PARITY | + UxUCR_BIT9_8_BITS | + UxUCR_PARITY_DISABLE | + UxUCR_SPB_2_STOP_BITS | + UxUCR_STOP_HIGH | + UxUCR_START_LOW); + } + + void + usart_out_byte(uint8_t byte) + { + U1DBUF = byte; + while (!UTX1IF) + ; + UTX1IF = 0; + } + + void + usart_out_string(uint8_t *string) + { + uint8_t b; + + while (b = *string++) + usart_out_byte(b); + } + + #define NUM_LEN 6 + + uint8_t __xdata num_buffer[NUM_LEN]; + uint8_t __xdata * __xdata num_ptr; + + void + usart_out_number(uint16_t v) + { + + num_ptr = num_buffer + NUM_LEN; + *--num_ptr = '\0'; + do { + *--num_ptr = '0' + v % 10; + v /= 10; + } while (v); + while (num_ptr != num_buffer) + *--num_ptr = ' '; + usart_out_string(num_buffer); + } + + #define ADC(n) DMA_XDATA16(adc_output,n) + + main () + { + P1DIR = 3; + CLKCON = 0; + while (!(SLEEP & SLEEP_XOSC_STB)) + ; - ++ + adc_init(); + P1_0 = 1; + usart_init(); + for (;;) { + adc_run(); + usart_out_string("accel: "); + usart_out_number(ADC(0)); + usart_out_string(" pres: "); + usart_out_number(ADC(1)); + usart_out_string(" temp: "); + usart_out_number(ADC(2)); + usart_out_string(" batt: "); + usart_out_number(ADC(3)); + usart_out_string(" drogue: "); + usart_out_number(ADC(4)); + usart_out_string(" main: "); + usart_out_number(ADC(5)); + usart_out_string("\r\n"); + delay(10); + } + } diff --combined target/adc/adc.c index 00000000,bdc6c614..3a63a2c6 mode 000000,100644..100644 --- a/target/adc/adc.c +++ b/target/adc/adc.c @@@ -1,0 -1,470 +1,470 @@@ + /* + * 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 + + /* + * Test ADC in DMA mode + */ + + sfr at 0x80 P0; + sfr at 0x90 P1; + sfr at 0xA0 P2; + sfr at 0xC6 CLKCON; + sfr at 0xbe SLEEP; + + # define SLEEP_USB_EN (1 << 7) + # define SLEEP_XOSC_STB (1 << 6) + + sfr at 0xF1 PERCFG; + #define PERCFG_T1CFG_ALT_1 (0 << 6) + #define PERCFG_T1CFG_ALT_2 (1 << 6) + + #define PERCFG_T3CFG_ALT_1 (0 << 5) + #define PERCFG_T3CFG_ALT_2 (1 << 5) + + #define PERCFG_T4CFG_ALT_1 (0 << 4) + #define PERCFG_T4CFG_ALT_2 (1 << 4) + + #define PERCFG_U1CFG_ALT_1 (0 << 1) + #define PERCFG_U1CFG_ALT_2 (1 << 1) + + #define PERCFG_U0CFG_ALT_1 (0 << 0) + #define PERCFG_U0CFG_ALT_2 (1 << 0) + + sfr at 0xF2 ADCCFG; + sfr at 0xF3 P0SEL; + sfr at 0xF4 P1SEL; + sfr at 0xF5 P2SEL; + + sfr at 0xFD P0DIR; + sfr at 0xFE P1DIR; + sfr at 0xFF P2DIR; + sfr at 0x8F P0INP; + sfr at 0xF6 P1INP; + sfr at 0xF7 P2INP; + + sfr at 0x89 P0IFG; + sfr at 0x8A P1IFG; + sfr at 0x8B P2IFG; + + sbit at 0x90 P1_0; + sbit at 0x91 P1_1; + sbit at 0x92 P1_2; + sbit at 0x93 P1_3; + sbit at 0x94 P1_4; + sbit at 0x95 P1_5; + sbit at 0x96 P1_6; + sbit at 0x97 P1_7; + + /* + * UART registers + */ + + sfr at 0x86 U0CSR; + sfr at 0xF8 U1CSR; + + /* + * IRCON2 + */ + sfr at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ + + sbit at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ + sbit at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ + sbit at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ + sbit at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ + sbit at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ + sbit at 0xEB P1IF; /* Port1 interrupt flag */ + sbit at 0xEC WDTIF; /* Watchdog timer interrupt flag */ + + # define UxCSR_MODE_UART (1 << 7) + # define UxCSR_MODE_SPI (0 << 7) + # define UxCSR_RE (1 << 6) + # define UxCSR_SLAVE (1 << 5) + # define UxCSR_MASTER (0 << 5) + # define UxCSR_FE (1 << 4) + # define UxCSR_ERR (1 << 3) + # define UxCSR_RX_BYTE (1 << 2) + # define UxCSR_TX_BYTE (1 << 1) + # define UxCSR_ACTIVE (1 << 0) + + sfr at 0xc4 U0UCR; + sfr at 0xfb U1UCR; + + # define UxUCR_FLUSH (1 << 7) + # define UxUCR_FLOW_DISABLE (0 << 6) + # define UxUCR_FLOW_ENABLE (1 << 6) + # define UxUCR_D9_EVEN_PARITY (0 << 5) + # define UxUCR_D9_ODD_PARITY (1 << 5) + # define UxUCR_BIT9_8_BITS (0 << 4) + # define UxUCR_BIT9_9_BITS (1 << 4) + # define UxUCR_PARITY_DISABLE (0 << 3) + # define UxUCR_PARITY_ENABLE (1 << 3) + # define UxUCR_SPB_1_STOP_BIT (0 << 2) + # define UxUCR_SPB_2_STOP_BITS (1 << 2) + # define UxUCR_STOP_LOW (0 << 1) + # define UxUCR_STOP_HIGH (1 << 1) + # define UxUCR_START_LOW (0 << 0) + # define UxUCR_START_HIGH (1 << 0) + + sfr at 0xc5 U0GCR; + sfr at 0xfc U1GCR; + + # define UxGCR_CPOL_NEGATIVE (0 << 7) + # define UxGCR_CPOL_POSITIVE (1 << 7) + # define UxGCR_CPHA_FIRST_EDGE (0 << 6) + # define UxGCR_CPHA_SECOND_EDGE (1 << 6) + # define UxGCR_ORDER_LSB (0 << 5) + # define UxGCR_ORDER_MSB (1 << 5) + # define UxGCR_BAUD_E_MASK (0x1f) + # define UxGCR_BAUD_E_SHIFT 0 + + sfr at 0xc1 U0DBUF; + sfr at 0xf9 U1DBUF; + sfr at 0xc2 U0BAUD; + sfr at 0xfa U1BAUD; + + #define DEBUG P1_1 + + + # define DMA_LEN_HIGH_VLEN_MASK (7 << 5) + # define DMA_LEN_HIGH_VLEN_LEN (0 << 5) + # define DMA_LEN_HIGH_VLEN_PLUS_1 (1 << 5) + # define DMA_LEN_HIGH_VLEN (2 << 5) + # define DMA_LEN_HIGH_VLEN_PLUS_2 (3 << 5) + # define DMA_LEN_HIGH_VLEN_PLUS_3 (4 << 5) + # define DMA_LEN_HIGH_MASK (0x1f) + + # define DMA_CFG0_WORDSIZE_8 (0 << 7) + # define DMA_CFG0_WORDSIZE_16 (1 << 7) + # define DMA_CFG0_TMODE_MASK (3 << 5) + # define DMA_CFG0_TMODE_SINGLE (0 << 5) + # define DMA_CFG0_TMODE_BLOCK (1 << 5) + # define DMA_CFG0_TMODE_REPEATED_SINGLE (2 << 5) + # define DMA_CFG0_TMODE_REPEATED_BLOCK (3 << 5) + + /* + * DMA triggers + */ + # define DMA_CFG0_TRIGGER_NONE 0 + # define DMA_CFG0_TRIGGER_PREV 1 + # define DMA_CFG0_TRIGGER_T1_CH0 2 + # define DMA_CFG0_TRIGGER_T1_CH1 3 + # define DMA_CFG0_TRIGGER_T1_CH2 4 + # define DMA_CFG0_TRIGGER_T2_OVFL 6 + # define DMA_CFG0_TRIGGER_T3_CH0 7 + # define DMA_CFG0_TRIGGER_T3_CH1 8 + # define DMA_CFG0_TRIGGER_T4_CH0 9 + # define DMA_CFG0_TRIGGER_T4_CH1 10 + # define DMA_CFG0_TRIGGER_IOC_0 12 + # define DMA_CFG0_TRIGGER_IOC_1 13 + # define DMA_CFG0_TRIGGER_URX0 14 + # define DMA_CFG0_TRIGGER_UTX0 15 + # define DMA_CFG0_TRIGGER_URX1 16 + # define DMA_CFG0_TRIGGER_UTX1 17 + # define DMA_CFG0_TRIGGER_FLASH 18 + # define DMA_CFG0_TRIGGER_RADIO 19 + # define DMA_CFG0_TRIGGER_ADC_CHALL 20 + # define DMA_CFG0_TRIGGER_ADC_CH0 21 + # define DMA_CFG0_TRIGGER_ADC_CH1 22 + # define DMA_CFG0_TRIGGER_ADC_CH2 23 + # define DMA_CFG0_TRIGGER_ADC_CH3 24 + # define DMA_CFG0_TRIGGER_ADC_CH4 25 + # define DMA_CFG0_TRIGGER_ADC_CH5 26 + # define DMA_CFG0_TRIGGER_ADC_CH6 27 + # define DMA_CFG0_TRIGGER_I2SRX 27 + # define DMA_CFG0_TRIGGER_ADC_CH7 28 + # define DMA_CFG0_TRIGGER_I2STX 28 + # define DMA_CFG0_TRIGGER_ENC_DW 29 + # define DMA_CFG0_TRIGGER_DNC_UP 30 + + # define DMA_CFG1_SRCINC_MASK (3 << 6) + # define DMA_CFG1_SRCINC_0 (0 << 6) + # define DMA_CFG1_SRCINC_1 (1 << 6) + # define DMA_CFG1_SRCINC_2 (2 << 6) + # define DMA_CFG1_SRCINC_MINUS_1 (3 << 6) + + # define DMA_CFG1_DESTINC_MASK (3 << 4) + # define DMA_CFG1_DESTINC_0 (0 << 4) + # define DMA_CFG1_DESTINC_1 (1 << 4) + # define DMA_CFG1_DESTINC_2 (2 << 4) + # define DMA_CFG1_DESTINC_MINUS_1 (3 << 4) + + # define DMA_CFG1_IRQMASK (1 << 3) + # define DMA_CFG1_M8 (1 << 2) + + # define DMA_CFG1_PRIORITY_MASK (3 << 0) + # define DMA_CFG1_PRIORITY_LOW (0 << 0) + # define DMA_CFG1_PRIORITY_NORMAL (1 << 0) + # define DMA_CFG1_PRIORITY_HIGH (2 << 0) + + /* + * DMAARM - DMA Channel Arm + */ + + sfr at 0xD6 DMAARM; + + # define DMAARM_ABORT (1 << 7) + # define DMAARM_DMAARM4 (1 << 4) + # define DMAARM_DMAARM3 (1 << 3) + # define DMAARM_DMAARM2 (1 << 2) + # define DMAARM_DMAARM1 (1 << 1) + # define DMAARM_DMAARM0 (1 << 0) + + /* + * DMAREQ - DMA Channel Start Request and Status + */ + + sfr at 0xD7 DMAREQ; + + # define DMAREQ_DMAREQ4 (1 << 4) + # define DMAREQ_DMAREQ3 (1 << 3) + # define DMAREQ_DMAREQ2 (1 << 2) + # define DMAREQ_DMAREQ1 (1 << 1) + # define DMAREQ_DMAREQ0 (1 << 0) + + /* + * DMA configuration 0 address + */ + + sfr at 0xD5 DMA0CFGH; + sfr at 0xD4 DMA0CFGL; + + /* + * DMA configuration 1-4 address + */ + + sfr at 0xD3 DMA1CFGH; + sfr at 0xD2 DMA1CFGL; + + /* + * DMAIRQ - DMA Interrupt Flag + */ + + sfr at 0xD1 DMAIRQ; + + # define DMAIRQ_DMAIF4 (1 << 4) + # define DMAIRQ_DMAIF3 (1 << 3) + # define DMAIRQ_DMAIF2 (1 << 2) + # define DMAIRQ_DMAIF1 (1 << 1) + # define DMAIRQ_DMAIF0 (1 << 0) + + struct cc_dma_channel { + uint8_t src_high; + uint8_t src_low; + uint8_t dst_high; + uint8_t dst_low; + uint8_t len_high; + uint8_t len_low; + uint8_t cfg0; + uint8_t cfg1; + }; + + /* + * ADC Data register, low and high + */ + sfr at 0xBA ADCL; + sfr at 0xBB ADCH; + __xdata __at (0xDFBA) volatile uint16_t ADCXDATA; + + /* + * ADC Control Register 1 + */ + sfr at 0xB4 ADCCON1; + + # define ADCCON1_EOC (1 << 7) /* conversion complete */ + # define ADCCON1_ST (1 << 6) /* start conversion */ + + # define ADCCON1_STSEL_MASK (3 << 4) /* start select */ + # define ADCCON1_STSEL_EXTERNAL (0 << 4) /* P2_0 pin triggers */ + # define ADCCON1_STSEL_FULLSPEED (1 << 4) /* full speed, no waiting */ + # define ADCCON1_STSEL_TIMER1 (2 << 4) /* timer 1 channel 0 */ + # define ADCCON1_STSEL_START (3 << 4) /* set start bit */ + + # define ADCCON1_RCTRL_MASK (3 << 2) /* random number control */ + # define ADCCON1_RCTRL_COMPLETE (0 << 2) /* operation completed */ + # define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2) /* Clock the LFSR once */ + + /* + * ADC Control Register 2 + */ + sfr at 0xB5 ADCCON2; + + # define ADCCON2_SREF_MASK (3 << 6) /* reference voltage */ + # define ADCCON2_SREF_1_25V (0 << 6) /* internal 1.25V */ + # define ADCCON2_SREF_EXTERNAL (1 << 6) /* external on AIN7 cc1110 */ + # define ADCCON2_SREF_VDD (2 << 6) /* VDD on the AVDD pin */ + # define ADCCON2_SREF_EXTERNAL_DIFF (3 << 6) /* external on AIN6-7 cc1110 */ + + # define ADCCON2_SDIV_MASK (3 << 4) /* decimation rate */ + # define ADCCON2_SDIV_64 (0 << 4) /* 7 bits */ + # define ADCCON2_SDIV_128 (1 << 4) /* 9 bits */ + # define ADCCON2_SDIV_256 (2 << 4) /* 10 bits */ + # define ADCCON2_SDIV_512 (3 << 4) /* 12 bits */ + + # define ADCCON2_SCH_MASK (0xf << 0) /* Sequence channel select */ + # define ADCCON2_SCH_SHIFT 0 + # define ADCCON2_SCH_AIN0 (0 << 0) + # define ADCCON2_SCH_AIN1 (1 << 0) + # define ADCCON2_SCH_AIN2 (2 << 0) + # define ADCCON2_SCH_AIN3 (3 << 0) + # define ADCCON2_SCH_AIN4 (4 << 0) + # define ADCCON2_SCH_AIN5 (5 << 0) + # define ADCCON2_SCH_AIN6 (6 << 0) + # define ADCCON2_SCH_AIN7 (7 << 0) + # define ADCCON2_SCH_AIN0_AIN1 (8 << 0) + # define ADCCON2_SCH_AIN2_AIN3 (9 << 0) + # define ADCCON2_SCH_AIN4_AIN5 (0xa << 0) + # define ADCCON2_SCH_AIN6_AIN7 (0xb << 0) + # define ADCCON2_SCH_GND (0xc << 0) + # define ADCCON2_SCH_VREF (0xd << 0) + # define ADCCON2_SCH_TEMP (0xe << 0) + # define ADCCON2_SCH_VDD_3 (0xf << 0) + + + /* + * ADC Control Register 3 + */ + + sfr at 0xB6 ADCCON3; + + # define ADCCON3_EREF_MASK (3 << 6) /* extra conversion reference */ + # define ADCCON3_EREF_1_25 (0 << 6) /* internal 1.25V */ + # define ADCCON3_EREF_EXTERNAL (1 << 6) /* external AIN7 cc1110 */ + # define ADCCON3_EREF_VDD (2 << 6) /* VDD on the AVDD pin */ + # define ADCCON3_EREF_EXTERNAL_DIFF (3 << 6) /* external AIN6-7 cc1110 */ + # define ADCCON2_EDIV_MASK (3 << 4) /* extral decimation */ + # define ADCCON2_EDIV_64 (0 << 4) /* 7 bits */ + # define ADCCON2_EDIV_128 (1 << 4) /* 9 bits */ + # define ADCCON2_EDIV_256 (2 << 4) /* 10 bits */ + # define ADCCON2_EDIV_512 (3 << 4) /* 12 bits */ + # define ADCCON3_ECH_MASK (0xf << 0) /* Sequence channel select */ + # define ADCCON3_ECH_SHIFT 0 + # define ADCCON3_ECH_AIN0 (0 << 0) + # define ADCCON3_ECH_AIN1 (1 << 0) + # define ADCCON3_ECH_AIN2 (2 << 0) + # define ADCCON3_ECH_AIN3 (3 << 0) + # define ADCCON3_ECH_AIN4 (4 << 0) + # define ADCCON3_ECH_AIN5 (5 << 0) + # define ADCCON3_ECH_AIN6 (6 << 0) + # define ADCCON3_ECH_AIN7 (7 << 0) + # define ADCCON3_ECH_AIN0_AIN1 (8 << 0) + # define ADCCON3_ECH_AIN2_AIN3 (9 << 0) + # define ADCCON3_ECH_AIN4_AIN5 (0xa << 0) + # define ADCCON3_ECH_AIN6_AIN7 (0xb << 0) + # define ADCCON3_ECH_GND (0xc << 0) + # define ADCCON3_ECH_VREF (0xd << 0) + # define ADCCON3_ECH_TEMP (0xe << 0) + # define ADCCON3_ECH_VDD_3 (0xf << 0) + + sfr at 0xF2 ADCCFG; + + #define nop() _asm nop _endasm; + + void + delay (unsigned char n) + { + unsigned char i = 0; + unsigned char j = 0; + + n++; + while (--n != 0) + while (--i != 0) + while (--j != 0) + nop(); + } + + void + debug_byte(uint8_t byte) + { + uint8_t s; + + for (s = 0; s < 8; s++) { + DEBUG = byte & 1; + delay(5); + byte >>= 1; + } + } + + struct cc_dma_channel __xdata dma_config; + + #define ADC_LEN 6 + + uint16_t __xdata adc_output[ADC_LEN]; + + #define ADDRH(a) (((uint16_t) (a)) >> 8) + #define ADDRL(a) (((uint16_t) (a))) + + void + adc_init(void) + { + dma_config.cfg0 = (DMA_CFG0_WORDSIZE_16 | + DMA_CFG0_TMODE_REPEATED_SINGLE | + DMA_CFG0_TRIGGER_ADC_CHALL); + dma_config.cfg1 = (DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_NORMAL); - ++ + dma_config.src_high = ADDRH(&ADCXDATA); + dma_config.src_low = ADDRL(&ADCXDATA); + dma_config.dst_high = ADDRH(adc_output); + dma_config.dst_low = ADDRL(adc_output); + dma_config.len_high = 0; + dma_config.len_low = ADC_LEN; + DMA0CFGH = ADDRH(&dma_config); + DMA0CFGL = ADDRL(&dma_config); + ADCCFG = ((1 << 0) | /* acceleration */ + (1 << 1) | /* pressure */ + (1 << 2) | /* temperature */ + (1 << 3) | /* battery voltage */ + (1 << 4) | /* drogue sense */ + (1 << 5)); /* main sense */ - ++ + ADCCON1 = (ADCCON1_STSEL_START); /* ST bit triggers */ + ADCCON2 = (ADCCON2_SREF_VDD | /* reference voltage is VDD */ + ADCCON2_SDIV_512 | /* 12 bit ADC results */ + ADCCON2_SCH_AIN5); /* sample all 6 inputs */ + } + + void + adc_run(void) + { + DMAIRQ &= ~1; + DMAARM |= 1; + ADCCON1 |= ADCCON1_ST; + while ((DMAIRQ & 1) == 0) + ; + } + + main () + { + int i; + P1DIR |= 2; + CLKCON = 0; + while (!(SLEEP & SLEEP_XOSC_STB)) + ; + while (P1 & 0x4) + ; - ++ + adc_init(); + for (;;) { + adc_run(); + for (i = 0; i < ADC_LEN; i++) + debug_byte(adc_output[i]); + } + } diff --combined target/beep-timer/beep_timer.c index 00000000,53b95495..b3fa8754 mode 000000,100644..100644 --- a/target/beep-timer/beep_timer.c +++ b/target/beep-timer/beep_timer.c @@@ -1,0 -1,204 +1,204 @@@ + /* + * 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. + */ + + sfr at 0x80 P0; + sfr at 0x90 P1; + sfr at 0xA0 P2; + sfr at 0xC6 CLKCON; + sfr at 0xbe SLEEP; + + # define SLEEP_USB_EN (1 << 7) + # define SLEEP_XOSC_STB (1 << 6) + + sbit at 0x90 P1_0; + sbit at 0x91 P1_1; + sbit at 0x92 P1_2; + sbit at 0x93 P1_3; + sbit at 0x94 P1_4; + sbit at 0x95 P1_5; + sbit at 0x96 P1_6; + sbit at 0x97 P1_7; + + sfr at 0xF1 PERCFG; + sfr at 0xF2 ADCCFG; + sfr at 0xF3 P0SEL; + sfr at 0xF4 P1SEL; + sfr at 0xF5 P2SEL; + + #define P2SEL_PRI3P1_USART0 (0 << 6) + #define P2SEL_PRI3P1_USART1 (1 << 6) + #define P2SEL_PRI2P1_USART1 (0 << 5) + #define P2SEL_PRI2P1_TIMER3 (1 << 5) + #define P2SEL_PRI1P1_TIMER1 (0 << 4) + #define P2SEL_PRI1P1_TIMER4 (1 << 4) + #define P2SEL_PRI0P1_USART0 (0 << 3) + #define P2SEL_PRI0P1_TIMER1 (1 << 3) + #define P2SEL_SELP2_4_GPIO (0 << 2) + #define P2SEL_SELP2_4_PERIPHERAL (1 << 2) + #define P2SEL_SELP2_3_GPIO (0 << 1) + #define P2SEL_SELP2_3_PERIPHERAL (1 << 1) + #define P2SEL_SELP2_0_GPIO (0 << 0) + #define P2SEL_SELP2_0_PERIPHERAL (1 << 0) + + sfr at 0xFD P0DIR; + sfr at 0xFE P1DIR; + sfr at 0xFF P2DIR; + sfr at 0x8F P0INP; + sfr at 0xF6 P1INP; + sfr at 0xF7 P2INP; + + sfr at 0x89 P0IFG; + sfr at 0x8A P1IFG; + sfr at 0x8B P2IFG; + + sfr at 0xF1 PERCFG; + #define PERCFG_T1CFG_ALT_1 (0 << 6) + #define PERCFG_T1CFG_ALT_2 (1 << 6) + + #define PERCFG_T3CFG_ALT_1 (0 << 5) + #define PERCFG_T3CFG_ALT_2 (1 << 5) + + #define PERCFG_T4CFG_ALT_1 (0 << 4) + #define PERCFG_T4CFG_ALT_2 (1 << 4) + + #define PERCFG_U1CFG_ALT_1 (0 << 1) + #define PERCFG_U1CFG_ALT_2 (1 << 1) + + #define PERCFG_U0CFG_ALT_1 (0 << 0) + #define PERCFG_U0CFG_ALT_2 (1 << 0) + + /* Timer count */ + sfr at 0xCA T3CNT; + sfr at 0xEA T4CNT; + + /* Timer control */ - ++ + sfr at 0xCB T3CTL; + sfr at 0xEB T4CTL; + + #define TxCTL_DIV_1 (0 << 5) + #define TxCTL_DIV_2 (1 << 5) + #define TxCTL_DIV_4 (2 << 5) + #define TxCTL_DIV_8 (3 << 5) + #define TxCTL_DIV_16 (4 << 5) + #define TxCTL_DIV_32 (5 << 5) + #define TxCTL_DIV_64 (6 << 5) + #define TxCTL_DIV_128 (7 << 5) + #define TxCTL_START (1 << 4) + #define TxCTL_OVFIM (1 << 3) + #define TxCTL_CLR (1 << 2) + #define TxCTL_MODE_FREE (0 << 0) + #define TxCTL_MODE_DOWN (1 << 0) + #define TxCTL_MODE_MODULO (2 << 0) + #define TxCTL_MODE_UP_DOWN (3 << 0) + + /* Timer 4 channel 0 compare control */ + + sfr at 0xCC T3CCTL0; + sfr at 0xCE T3CCTL1; + sfr at 0xEC T4CCTL0; + sfr at 0xEE T4CCTL1; + + #define TxCCTLy_IM (1 << 6) + #define TxCCTLy_CMP_SET (0 << 3) + #define TxCCTLy_CMP_CLEAR (1 << 3) + #define TxCCTLy_CMP_TOGGLE (2 << 3) + #define TxCCTLy_CMP_SET_UP_CLEAR_DOWN (3 << 3) + #define TxCCTLy_CMP_CLEAR_UP_SET_DOWN (4 << 3) + #define TxCCTLy_CMP_SET_CLEAR_FF (5 << 3) + #define TxCCTLy_CMP_CLEAR_SET_00 (6 << 3) + #define TxCCTLy_CMP_MODE_ENABLE (1 << 2) + + /* Timer compare value */ + sfr at 0xCD T3CC0; + sfr at 0xCF T3CC1; + sfr at 0xED T4CC0; + sfr at 0xEF T4CC1; + + #define nop() _asm nop _endasm; + + void + delay (unsigned char n) + { + unsigned char i = 0, j = 0; + + n <<= 1; + while (--n != 0) + while (--j != 0) + while (--i != 0) + nop(); + } + + void + dit() { + T4CTL |= TxCTL_START; + delay(1); + T4CTL &= ~TxCTL_START; + delay(1); + } + + void + dah () { + T4CTL |= TxCTL_START; + delay(3); + T4CTL &= ~TxCTL_START; + delay(1); + } + + void + charspace () { + delay(2); + } + + void + wordspace () { + delay(8); + } + + #define _ dit(); + #define ___ dah(); + #define C charspace(); + #define W wordspace(); + + main () + { + CLKCON = 0; + while (!(SLEEP & SLEEP_XOSC_STB)) + ; + + /* Use timer 4 alternate config 2 */ + PERCFG = PERCFG_T4CFG_ALT_2; + /* Use P2_4 for timer 4 output */ + P2SEL = P2SEL_SELP2_0_PERIPHERAL; + + T4CCTL0 = TxCCTLy_CMP_TOGGLE|TxCCTLy_CMP_MODE_ENABLE; + T4CC0 = 125; + T4CTL = TxCTL_DIV_32 | TxCTL_MODE_MODULO; - ++ + for (;;) { + ___ _ ___ _ C ___ ___ _ ___ W /* cq */ + ___ _ _ C _ W /* de */ + ___ _ ___ C ___ _ _ C /* kd */ + ___ ___ _ _ _ C _ _ _ C /* 7s */ + ___ ___ _ ___ C ___ ___ _ W /* qg */ + if (T4CC0 == 94) + T4CC0 = 125; + else + T4CC0 = 94; + } + } diff --combined target/dma/dma.c index 00000000,c35c39f6..1762b658 mode 000000,100644..100644 --- a/target/dma/dma.c +++ b/target/dma/dma.c @@@ -1,0 -1,361 +1,361 @@@ + /* + * 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 + + /* + * Test DMA + */ + + sfr at 0x80 P0; + sfr at 0x90 P1; + sfr at 0xA0 P2; + sfr at 0xC6 CLKCON; + sfr at 0xbe SLEEP; + + # define SLEEP_USB_EN (1 << 7) + # define SLEEP_XOSC_STB (1 << 6) + + sfr at 0xF1 PERCFG; + #define PERCFG_T1CFG_ALT_1 (0 << 6) + #define PERCFG_T1CFG_ALT_2 (1 << 6) + + #define PERCFG_T3CFG_ALT_1 (0 << 5) + #define PERCFG_T3CFG_ALT_2 (1 << 5) + + #define PERCFG_T4CFG_ALT_1 (0 << 4) + #define PERCFG_T4CFG_ALT_2 (1 << 4) + + #define PERCFG_U1CFG_ALT_1 (0 << 1) + #define PERCFG_U1CFG_ALT_2 (1 << 1) + + #define PERCFG_U0CFG_ALT_1 (0 << 0) + #define PERCFG_U0CFG_ALT_2 (1 << 0) + + sfr at 0xF2 ADCCFG; + sfr at 0xF3 P0SEL; + sfr at 0xF4 P1SEL; + sfr at 0xF5 P2SEL; + + sfr at 0xFD P0DIR; + sfr at 0xFE P1DIR; + sfr at 0xFF P2DIR; + sfr at 0x8F P0INP; + sfr at 0xF6 P1INP; + sfr at 0xF7 P2INP; + + sfr at 0x89 P0IFG; + sfr at 0x8A P1IFG; + sfr at 0x8B P2IFG; + + sbit at 0x90 P1_0; + sbit at 0x91 P1_1; + sbit at 0x92 P1_2; + sbit at 0x93 P1_3; + sbit at 0x94 P1_4; + sbit at 0x95 P1_5; + sbit at 0x96 P1_6; + sbit at 0x97 P1_7; + + /* + * UART registers + */ + + sfr at 0x86 U0CSR; + sfr at 0xF8 U1CSR; + + /* + * IRCON2 + */ + sfr at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ + + sbit at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ + sbit at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ + sbit at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ + sbit at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ + sbit at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ + sbit at 0xEB P1IF; /* Port1 interrupt flag */ + sbit at 0xEC WDTIF; /* Watchdog timer interrupt flag */ + + # define UxCSR_MODE_UART (1 << 7) + # define UxCSR_MODE_SPI (0 << 7) + # define UxCSR_RE (1 << 6) + # define UxCSR_SLAVE (1 << 5) + # define UxCSR_MASTER (0 << 5) + # define UxCSR_FE (1 << 4) + # define UxCSR_ERR (1 << 3) + # define UxCSR_RX_BYTE (1 << 2) + # define UxCSR_TX_BYTE (1 << 1) + # define UxCSR_ACTIVE (1 << 0) + + sfr at 0xc4 U0UCR; + sfr at 0xfb U1UCR; + + # define UxUCR_FLUSH (1 << 7) + # define UxUCR_FLOW_DISABLE (0 << 6) + # define UxUCR_FLOW_ENABLE (1 << 6) + # define UxUCR_D9_EVEN_PARITY (0 << 5) + # define UxUCR_D9_ODD_PARITY (1 << 5) + # define UxUCR_BIT9_8_BITS (0 << 4) + # define UxUCR_BIT9_9_BITS (1 << 4) + # define UxUCR_PARITY_DISABLE (0 << 3) + # define UxUCR_PARITY_ENABLE (1 << 3) + # define UxUCR_SPB_1_STOP_BIT (0 << 2) + # define UxUCR_SPB_2_STOP_BITS (1 << 2) + # define UxUCR_STOP_LOW (0 << 1) + # define UxUCR_STOP_HIGH (1 << 1) + # define UxUCR_START_LOW (0 << 0) + # define UxUCR_START_HIGH (1 << 0) + + sfr at 0xc5 U0GCR; + sfr at 0xfc U1GCR; + + # define UxGCR_CPOL_NEGATIVE (0 << 7) + # define UxGCR_CPOL_POSITIVE (1 << 7) + # define UxGCR_CPHA_FIRST_EDGE (0 << 6) + # define UxGCR_CPHA_SECOND_EDGE (1 << 6) + # define UxGCR_ORDER_LSB (0 << 5) + # define UxGCR_ORDER_MSB (1 << 5) + # define UxGCR_BAUD_E_MASK (0x1f) + # define UxGCR_BAUD_E_SHIFT 0 + + sfr at 0xc1 U0DBUF; + sfr at 0xf9 U1DBUF; + sfr at 0xc2 U0BAUD; + sfr at 0xfa U1BAUD; + + #define DEBUG P1_1 + + + # define DMA_LEN_HIGH_VLEN_MASK (7 << 5) + # define DMA_LEN_HIGH_VLEN_LEN (0 << 5) + # define DMA_LEN_HIGH_VLEN_PLUS_1 (1 << 5) + # define DMA_LEN_HIGH_VLEN (2 << 5) + # define DMA_LEN_HIGH_VLEN_PLUS_2 (3 << 5) + # define DMA_LEN_HIGH_VLEN_PLUS_3 (4 << 5) + # define DMA_LEN_HIGH_MASK (0x1f) + + # define DMA_CFG0_WORDSIZE_8 (0 << 7) + # define DMA_CFG0_WORDSIZE_16 (1 << 7) + # define DMA_CFG0_TMODE_MASK (3 << 5) + # define DMA_CFG0_TMODE_SINGLE (0 << 5) + # define DMA_CFG0_TMODE_BLOCK (1 << 5) + # define DMA_CFG0_TMODE_REPEATED_SINGLE (2 << 5) + # define DMA_CFG0_TMODE_REPEATED_BLOCK (3 << 5) + + /* + * DMA triggers + */ + # define DMA_CFG0_TRIGGER_NONE 0 + # define DMA_CFG0_TRIGGER_PREV 1 + # define DMA_CFG0_TRIGGER_T1_CH0 2 + # define DMA_CFG0_TRIGGER_T1_CH1 3 + # define DMA_CFG0_TRIGGER_T1_CH2 4 + # define DMA_CFG0_TRIGGER_T2_OVFL 6 + # define DMA_CFG0_TRIGGER_T3_CH0 7 + # define DMA_CFG0_TRIGGER_T3_CH1 8 + # define DMA_CFG0_TRIGGER_T4_CH0 9 + # define DMA_CFG0_TRIGGER_T4_CH1 10 + # define DMA_CFG0_TRIGGER_IOC_0 12 + # define DMA_CFG0_TRIGGER_IOC_1 13 + # define DMA_CFG0_TRIGGER_URX0 14 + # define DMA_CFG0_TRIGGER_UTX0 15 + # define DMA_CFG0_TRIGGER_URX1 16 + # define DMA_CFG0_TRIGGER_UTX1 17 + # define DMA_CFG0_TRIGGER_FLASH 18 + # define DMA_CFG0_TRIGGER_RADIO 19 + # define DMA_CFG0_TRIGGER_ADC_CHALL 20 + # define DMA_CFG0_TRIGGER_ADC_CH0 21 + # define DMA_CFG0_TRIGGER_ADC_CH1 22 + # define DMA_CFG0_TRIGGER_ADC_CH2 23 + # define DMA_CFG0_TRIGGER_ADC_CH3 24 + # define DMA_CFG0_TRIGGER_ADC_CH4 25 + # define DMA_CFG0_TRIGGER_ADC_CH5 26 + # define DMA_CFG0_TRIGGER_ADC_CH6 27 + # define DMA_CFG0_TRIGGER_I2SRX 27 + # define DMA_CFG0_TRIGGER_ADC_CH7 28 + # define DMA_CFG0_TRIGGER_I2STX 28 + # define DMA_CFG0_TRIGGER_ENC_DW 29 + # define DMA_CFG0_TRIGGER_DNC_UP 30 + + # define DMA_CFG1_SRCINC_MASK (3 << 6) + # define DMA_CFG1_SRCINC_0 (0 << 6) + # define DMA_CFG1_SRCINC_1 (1 << 6) + # define DMA_CFG1_SRCINC_2 (2 << 6) + # define DMA_CFG1_SRCINC_MINUS_1 (3 << 6) + + # define DMA_CFG1_DESTINC_MASK (3 << 4) + # define DMA_CFG1_DESTINC_0 (0 << 4) + # define DMA_CFG1_DESTINC_1 (1 << 4) + # define DMA_CFG1_DESTINC_2 (2 << 4) + # define DMA_CFG1_DESTINC_MINUS_1 (3 << 4) + + # define DMA_CFG1_IRQMASK (1 << 3) + # define DMA_CFG1_M8 (1 << 2) + + # define DMA_CFG1_PRIORITY_MASK (3 << 0) + # define DMA_CFG1_PRIORITY_LOW (0 << 0) + # define DMA_CFG1_PRIORITY_NORMAL (1 << 0) + # define DMA_CFG1_PRIORITY_HIGH (2 << 0) + + /* + * DMAARM - DMA Channel Arm + */ + + sfr at 0xD6 DMAARM; + + # define DMAARM_ABORT (1 << 7) + # define DMAARM_DMAARM4 (1 << 4) + # define DMAARM_DMAARM3 (1 << 3) + # define DMAARM_DMAARM2 (1 << 2) + # define DMAARM_DMAARM1 (1 << 1) + # define DMAARM_DMAARM0 (1 << 0) + + /* + * DMAREQ - DMA Channel Start Request and Status + */ + + sfr at 0xD7 DMAREQ; + + # define DMAREQ_DMAREQ4 (1 << 4) + # define DMAREQ_DMAREQ3 (1 << 3) + # define DMAREQ_DMAREQ2 (1 << 2) + # define DMAREQ_DMAREQ1 (1 << 1) + # define DMAREQ_DMAREQ0 (1 << 0) + + /* + * DMA configuration 0 address + */ + + sfr at 0xD5 DMA0CFGH; + sfr at 0xD4 DMA0CFGL; + + /* + * DMA configuration 1-4 address + */ + + sfr at 0xD3 DMA1CFGH; + sfr at 0xD2 DMA1CFGL; + + /* + * DMAIRQ - DMA Interrupt Flag + */ + + sfr at 0xD1 DMAIRQ; + + # define DMAIRQ_DMAIF4 (1 << 4) + # define DMAIRQ_DMAIF3 (1 << 3) + # define DMAIRQ_DMAIF2 (1 << 2) + # define DMAIRQ_DMAIF1 (1 << 1) + # define DMAIRQ_DMAIF0 (1 << 0) + + struct cc_dma_channel { + uint8_t src_high; + uint8_t src_low; + uint8_t dst_high; + uint8_t dst_low; + uint8_t len_high; + uint8_t len_low; + uint8_t cfg0; + uint8_t cfg1; + }; + + #define nop() _asm nop _endasm; + + void + delay (unsigned char n) + { + unsigned char i = 0; + unsigned char j = 0; + + n++; + while (--n != 0) + while (--i != 0) + while (--j != 0) + nop(); + } + + void + debug_byte(uint8_t byte) + { + uint8_t s; + + for (s = 0; s < 8; s++) { + DEBUG = byte & 1; + delay(5); + byte >>= 1; + } + } + + struct cc_dma_channel __xdata config; + + #define DMA_LEN 8 + + uint8_t __xdata dma_input[DMA_LEN]; + uint8_t __xdata dma_output[DMA_LEN]; + + #define ADDRH(a) (((uint16_t) (a)) >> 8) + #define ADDRL(a) (((uint16_t) (a))) + + void + dma_init(void) + { + int i; + config.cfg0 = (DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_BLOCK | + DMA_CFG0_TRIGGER_NONE); + config.cfg1 = (DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_NORMAL); - ++ + config.src_high = ADDRH(dma_input); + config.src_low = ADDRL(dma_input); + config.dst_high = ADDRH(dma_output); + config.dst_low = ADDRL(dma_output); + config.len_high = 0; + config.len_low = DMA_LEN; + DMA0CFGH = ADDRH(&config); + DMA0CFGL = ADDRL(&config); + for (i = 0; i < DMA_LEN; i++) + dma_input[i] = i + 1; + } + + void + dma_run(void) + { + DMAREQ |= 1; + DMAARM |= 1; + while (DMAARM & 1) + ; + } + + main () + { + int i; + P1DIR |= 2; + CLKCON = 0; + while (!(SLEEP & SLEEP_XOSC_STB)) + ; - ++ + dma_init(); + dma_run(); + for (;;) { + for (i = 0; i < DMA_LEN; i++) + debug_byte(dma_output[i]); + } + } diff --combined target/ee/ee.c index 00000000,7cc47120..9ea22cdc mode 000000,100644..100644 --- a/target/ee/ee.c +++ b/target/ee/ee.c @@@ -1,0 -1,407 +1,407 @@@ + /* + * 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 + + /* + * Validate the SPI-connected EEPROM + */ + + sfr at 0x80 P0; + sfr at 0x90 P1; + sfr at 0xA0 P2; + sfr at 0xC6 CLKCON; + sfr at 0xbe SLEEP; + + # define SLEEP_USB_EN (1 << 7) + # define SLEEP_XOSC_STB (1 << 6) + + sfr at 0xF1 PERCFG; + #define PERCFG_T1CFG_ALT_1 (0 << 6) + #define PERCFG_T1CFG_ALT_2 (1 << 6) + + #define PERCFG_T3CFG_ALT_1 (0 << 5) + #define PERCFG_T3CFG_ALT_2 (1 << 5) + + #define PERCFG_T4CFG_ALT_1 (0 << 4) + #define PERCFG_T4CFG_ALT_2 (1 << 4) + + #define PERCFG_U1CFG_ALT_1 (0 << 1) + #define PERCFG_U1CFG_ALT_2 (1 << 1) + + #define PERCFG_U0CFG_ALT_1 (0 << 0) + #define PERCFG_U0CFG_ALT_2 (1 << 0) + + sfr at 0xF2 ADCCFG; + sfr at 0xF3 P0SEL; + sfr at 0xF4 P1SEL; + sfr at 0xF5 P2SEL; + + sfr at 0xFD P0DIR; + sfr at 0xFE P1DIR; + sfr at 0xFF P2DIR; + sfr at 0x8F P0INP; + sfr at 0xF6 P1INP; + sfr at 0xF7 P2INP; + + sfr at 0x89 P0IFG; + sfr at 0x8A P1IFG; + sfr at 0x8B P2IFG; + + sbit at 0x90 P1_0; + sbit at 0x91 P1_1; + sbit at 0x92 P1_2; + sbit at 0x93 P1_3; + sbit at 0x94 P1_4; + sbit at 0x95 P1_5; + sbit at 0x96 P1_6; + sbit at 0x97 P1_7; + + /* + * UART registers + */ + + sfr at 0x86 U0CSR; + sfr at 0xF8 U1CSR; + + # define UxCSR_MODE_UART (1 << 7) + # define UxCSR_MODE_SPI (0 << 7) + # define UxCSR_RE (1 << 6) + # define UxCSR_SLAVE (1 << 5) + # define UxCSR_MASTER (0 << 5) + # define UxCSR_FE (1 << 4) + # define UxCSR_ERR (1 << 3) + # define UxCSR_RX_BYTE (1 << 2) + # define UxCSR_TX_BYTE (1 << 1) + # define UxCSR_ACTIVE (1 << 0) + + sfr at 0xc4 U0UCR; + sfr at 0xfb U1UCR; + + sfr at 0xc5 U0GCR; + sfr at 0xfc U1GCR; + + # define UxGCR_CPOL_NEGATIVE (0 << 7) + # define UxGCR_CPOL_POSITIVE (1 << 7) + # define UxGCR_CPHA_FIRST_EDGE (0 << 6) + # define UxGCR_CPHA_SECOND_EDGE (1 << 6) + # define UxGCR_ORDER_LSB (0 << 5) + # define UxGCR_ORDER_MSB (1 << 5) + # define UxGCR_BAUD_E_MASK (0x1f) + # define UxGCR_BAUD_E_SHIFT 0 + + sfr at 0xc1 U0DBUF; + sfr at 0xf9 U1DBUF; + sfr at 0xc2 U0BAUD; + sfr at 0xfa U1BAUD; + + #define MOSI P1_5 + #define MISO P1_4 + #define SCK P1_3 + #define CS P1_2 + + #define DEBUG P1_1 + + #define BITBANG 0 + #define USART 1 + + #define nop() _asm nop _endasm; + + void + delay (unsigned char n) + { + unsigned char i = 0; + unsigned char j = 0; + + while (--n != 0) + while (--i != 0) + while (--j != 0) + nop(); + } + + #if BITBANG + + /* + * This version directly manipulates the GPIOs to synthesize SPI + */ + + void + bitbang_cs(uint8_t b) + { + SCK = 0; + CS = b; + delay(1); + } + + void + bitbang_out_bit(uint8_t b) + { + MOSI = b; + delay(1); + SCK = 1; + delay(1); + SCK = 0; + } + + void + bitbang_out_byte(uint8_t byte) + { + uint8_t s; + + for (s = 0; s < 8; s++) { + uint8_t b = (byte & 0x80) ? 1 : 0; + bitbang_out_bit(b); + byte <<= 1; + } + } + + uint8_t + bitbang_in_bit(void) + { + uint8_t b; - ++ + delay(1); + SCK = 1; + delay(1); + b = MISO; + SCK = 0; + return b; + } + + uint8_t + bitbang_in_byte(void) + { + uint8_t byte = 0; + uint8_t s; + uint8_t b; + + for (s = 0; s < 8; s++) { + b = bitbang_in_bit(); + byte = byte << 1; + byte |= b; + } + return byte; + } + + void + bit_bang_init(void) + { + CS = 1; + SCK = 0; + P1DIR = ((1 << 5) | + (0 << 4) | + (1 << 3) | + (1 << 2) | + (1 << 1)); + } + + #define spi_init() bitbang_init() + #define spi_out_byte(b) bitbang_out_byte(b) + #define spi_in_byte() bitbang_in_byte() + #define spi_cs(b) bitbang_cs(b) + #endif + + #if USART + + /* + * This version uses the USART in SPI mode + */ + void + usart_init(void) + { + /* + * Configure our chip select line + */ + CS = 1; + P1DIR |= (1 << 2); + /* + * Configure the peripheral pin choices + * for both of the serial ports + * + * Note that telemetrum will use U1CFG_ALT_2 + * but that overlaps with SPI ALT_2, so until + * we can test that this works, we'll set this + * to ALT_1 + */ + PERCFG = (PERCFG_U1CFG_ALT_1 | + PERCFG_U0CFG_ALT_2); + + /* + * Make the SPI pins controlled by the SPI + * hardware + */ + P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); + + /* + * SPI in master mode + */ + U0CSR = (UxCSR_MODE_SPI | + UxCSR_MASTER); + + /* + * The cc1111 is limited to a 24/8 MHz SPI clock, + * while the 25LC1024 is limited to 20MHz. So, + * use the 3MHz clock (BAUD_E 17, BAUD_M 0) + */ + U0BAUD = 0; + U0GCR = (UxGCR_CPOL_NEGATIVE | + UxGCR_CPHA_FIRST_EDGE | + UxGCR_ORDER_MSB | + (17 << UxGCR_BAUD_E_SHIFT)); + } + + void + usart_cs(uint8_t b) + { + CS = b; + } + + uint8_t + usart_in_out(uint8_t byte) + { + U0DBUF = byte; + while ((U0CSR & UxCSR_TX_BYTE) == 0) + ; + U0CSR &= ~UxCSR_TX_BYTE; + return U0DBUF; + } + + void + usart_out_byte(uint8_t byte) + { + (void) usart_in_out(byte); + } + + uint8_t + usart_in_byte(void) + { + return usart_in_out(0xff); + } + + #define spi_init() usart_init() + #define spi_out_byte(b) usart_out_byte(b) + #define spi_in_byte() usart_in_byte() + #define spi_cs(b) usart_cs(b) + + #endif + + uint8_t + rdsr(void) + { + uint8_t status; + spi_cs(0); + spi_out_byte(0x05); + status = spi_in_byte(); + spi_cs(1); + return status; + } + + void + wrsr(uint8_t status) + { + spi_cs(0); + spi_out_byte(0x01); + spi_out_byte(status); + spi_cs(1); + } - ++ + void + wren(void) + { + spi_cs(0); + spi_out_byte(0x06); + spi_cs(1); + } + + void + write(uint32_t addr, uint8_t *bytes, uint16_t len) + { + wren(); + spi_cs(0); + spi_out_byte(0x02); + spi_out_byte(addr >> 16); + spi_out_byte(addr >> 8); + spi_out_byte(addr); + while (len-- > 0) + spi_out_byte(*bytes++); + spi_cs(1); + for (;;) { + uint8_t status = rdsr(); + if ((status & (1 << 0)) == 0) + break; + } + } + + void + read(uint32_t addr, uint8_t *bytes, uint16_t len) + { + spi_cs(0); + spi_out_byte(0x03); + spi_out_byte(addr >> 16); + spi_out_byte(addr >> 8); + spi_out_byte(addr); + while (len-- > 0) + *bytes++ = spi_in_byte(); + spi_cs(1); + } + + void + debug_byte(uint8_t byte) + { + uint8_t s; + + for (s = 0; s < 8; s++) { + DEBUG = byte & 1; + delay(5); + byte >>= 1; + } + } + + #define STRING "\360\252" + #define LENGTH 2 + + main () + { + uint8_t status; + uint8_t buf[LENGTH]; + int i; + + P1DIR |= 2; + CLKCON = 0; + while (!(SLEEP & SLEEP_XOSC_STB)) + ; - ++ + spi_init(); + + status = rdsr(); + /* + * Turn off both block-protect bits + */ + status &= ~((1 << 3) | (1 << 2)); + /* + * Turn off write protect enable + */ + status &= ~(1 << 7); + wrsr(status); + write(0x0, STRING, LENGTH); + for (;;) { + read(0x0, buf, LENGTH); + for (i = 0; i < LENGTH; i++) + debug_byte(buf[i]); + } + } diff --combined target/isr.c index 00000000,43aedc29..ae4d04c5 mode 000000,100644..100644 --- a/target/isr.c +++ b/target/isr.c @@@ -1,0 -1,90 +1,89 @@@ + /* + * 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. + */ + + void rftxrx_isr (void) __interrupt(0) __using(1) + { + } + + void adc_isr (void) __interrupt(1) __using(1) + { + } + + void urx0_isr (void) __interrupt(2) __using(1) + { + } + + void urx1_isr (void) __interrupt(3) __using(1) + { + } + + void enc_isr (void) __interrupt(4) __using(1) + { + } + + void st_isr (void) __interrupt(5) __using(1) + { + } + + void usb_isr (void) __interrupt(6) __using(1) + { + } + + void utx0_isr (void) __interrupt(7) __using(1) + { + } + + void dma_isr (void) __interrupt(8) __using(1) + { + } + + void t1_isr (void) __interrupt(9) __using(1) + { + } + + void t2_isr (void) __interrupt(10) __using(1) + { + } + + void t3_isr (void) __interrupt(11) __using(1) + { + } + + void t4_isr (void) __interrupt(12) __using(1) + { + } + + void p0int_isr (void) __interrupt(13) __using(1) + { + } + + void utx1_isr (void) __interrupt(14) __using(1) + { + } + + void p1int_isr (void) __interrupt(15) __using(1) + { + } + + void rf_isr (void) __interrupt(16) __using(1) + { + } + + void wdt_isr (void) __interrupt(17) __using(1) + { + } - diff --combined target/radio/init.c index 00000000,c9b3d186..ea7c984c mode 000000,100644..100644 --- a/target/radio/init.c +++ b/target/radio/init.c @@@ -1,0 -1,207 +1,207 @@@ + /* + * Copyright © 2009 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; version 2 of the License. + * + * 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 "radio.h" + + /* Values from SmartRF® Studio for: + * + * Deviation: 20.507812 kHz + * Datarate: 38.360596 kBaud + * Modulation: GFSK + * RF Freq: 434.549927 MHz + * Channel: 99.975586 kHz + * Channel: 0 + * RX filter: 93.75 kHz + */ + + /* + * For 434.550MHz, the frequency value is: + * + * 434.550e6 / (24e6 / 2**16) = 1186611.2 + */ + + #define FREQ_CONTROL 1186611 + + /* + * For IF freq of 140.62kHz, the IF value is: + * + * 140.62e3 / (24e6 / 2**10) = 6 + */ + + #define IF_FREQ_CONTROL 6 + + /* + * For channel bandwidth of 93.75 kHz, the CHANBW_E and CHANBW_M values are + * + * BW = 24e6 / (8 * (4 + M) * 2 ** E) + * + * So, M = 0 and E = 3 + */ + + #define CHANBW_M 0 + #define CHANBW_E 3 + + /* + * For a symbol rate of 38360kBaud, the DRATE_E and DRATE_M values are: + * + * R = (256 + M) * 2** E * 24e6 / 2**28 + * + * So M is 163 and E is 10 + */ + + #define DRATE_E 10 + #define DRATE_M 163 + + /* + * For a channel deviation of 20.5kHz, the DEVIATION_E and DEVIATION_M values are: + * + * F = 24e6/2**17 * (8 + DEVIATION_M) * 2**DEVIATION_E + * + * So M is 6 and E is 3 + */ + + #define DEVIATION_M 6 + #define DEVIATION_E 3 + + #define PACKET_LEN 128 + + /* This are from the table for 433MHz */ + + #define RF_POWER_M30_DBM 0x12 + #define RF_POWER_M20_DBM 0x0e + #define RF_POWER_M15_DBM 0x1d + #define RF_POWER_M10_DBM 0x34 + #define RF_POWER_M5_DBM 0x2c + #define RF_POWER_0_DBM 0x60 + #define RF_POWER_5_DBM 0x84 + #define RF_POWER_7_DBM 0xc8 + #define RF_POWER_10_DBM 0xc0 + + #define RF_POWER RF_POWER_0_DBM + + static __code uint8_t radio_setup[] = { + RF_PA_TABLE7_OFF, RF_POWER, + RF_PA_TABLE6_OFF, RF_POWER, + RF_PA_TABLE5_OFF, RF_POWER, + RF_PA_TABLE4_OFF, RF_POWER, + RF_PA_TABLE3_OFF, RF_POWER, + RF_PA_TABLE2_OFF, RF_POWER, + RF_PA_TABLE1_OFF, RF_POWER, + RF_PA_TABLE0_OFF, RF_POWER, + + RF_FREQ2_OFF, FREQ_CONTROL >> 16, + RF_FREQ1_OFF, FREQ_CONTROL >> 8, + RF_FREQ0_OFF, FREQ_CONTROL >> 0, - ++ + RF_FSCTRL1_OFF, (IF_FREQ_CONTROL << RF_FSCTRL1_FREQ_IF_SHIFT), + RF_FSCTRL0_OFF, (0 << RF_FSCTRL0_FREQOFF_SHIFT), + + RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | + (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | + (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), + RF_MDMCFG3_OFF, (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), + RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | + RF_MDMCFG2_MOD_FORMAT_GFSK | + RF_MDMCFG2_SYNC_MODE_15_16_THRES), + RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_EN | + RF_MDMCFG1_NUM_PREAMBLE_4 | + (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), + RF_MDMCFG0_OFF, (17 << RF_MDMCFG0_CHANSPC_M_SHIFT), + + RF_CHANNR_OFF, 0, + + RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | + (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), + + /* SmartRF says set LODIV_BUF_CURRENT_TX to 0 + * And, we're not using power ramping, so use PA_POWER 0 + */ + RF_FREND0_OFF, ((1 << RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT) | + (0 << RF_FREND0_PA_POWER_SHIFT)), + + RF_FREND1_OFF, ((1 << RF_FREND1_LNA_CURRENT_SHIFT) | + (1 << RF_FREND1_LNA2MIX_CURRENT_SHIFT) | + (1 << RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT) | + (2 << RF_FREND1_MIX_CURRENT_SHIFT)), + + RF_FSCAL3_OFF, 0xE9, + RF_FSCAL2_OFF, 0x0A, + RF_FSCAL1_OFF, 0x00, + RF_FSCAL0_OFF, 0x1F, + + RF_TEST2_OFF, 0x88, + RF_TEST1_OFF, 0x31, + RF_TEST0_OFF, 0x09, + + /* default sync values */ + RF_SYNC1_OFF, 0xD3, + RF_SYNC0_OFF, 0x91, - ++ + /* max packet length */ + RF_PKTLEN_OFF, PACKET_LEN, + + RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| + PKTCTRL1_APPEND_STATUS| + PKTCTRL1_ADR_CHK_NONE), + RF_PKTCTRL0_OFF, (RF_PKTCTRL0_WHITE_DATA| + RF_PKTCTRL0_PKT_FORMAT_NORMAL| + RF_PKTCTRL0_CRC_EN| + RF_PKTCTRL0_LENGTH_CONFIG_FIXED), + RF_ADDR_OFF, 0x00, + RF_MCSM2_OFF, (RF_MCSM2_RX_TIME_END_OF_PACKET), + RF_MCSM1_OFF, (RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING| + RF_MCSM1_RXOFF_MODE_IDLE| + RF_MCSM1_TXOFF_MODE_IDLE), + RF_MCSM0_OFF, (RF_MCSM0_FS_AUTOCAL_FROM_IDLE| + RF_MCSM0_MAGIC_3| + RF_MCSM0_CLOSE_IN_RX_18DB), + RF_FOCCFG_OFF, (RF_FOCCFG_FOC_PRE_K_3K, + RF_FOCCFG_FOC_POST_K_PRE_K, + RF_FOCCFG_FOC_LIMIT_BW_OVER_4), + RF_BSCFG_OFF, (RF_BSCFG_BS_PRE_K_2K| + RF_BSCFG_BS_PRE_KP_3KP| + RF_BSCFG_BS_POST_KI_PRE_KI| + RF_BSCFG_BS_POST_KP_PRE_KP| + RF_BSCFG_BS_LIMIT_0), + RF_AGCCTRL2_OFF, 0x43, + RF_AGCCTRL1_OFF, 0x40, + RF_AGCCTRL0_OFF, 0x91, + + RF_IOCFG2_OFF, 0x00, + RF_IOCFG1_OFF, 0x00, + RF_IOCFG0_OFF, 0x00, + }; + + void + radio_init(void) { + uint8_t i; + for (i = 0; i < sizeof (radio_setup); i += 2) + RF[radio_setup[i]] = radio_setup[i+1]; + } + + #define nop() _asm nop _endasm; + + void + delay (unsigned char n) + { + unsigned char i = 0; + + n <<= 1; + while (--n != 0) + while (--i != 0) + nop(); + } diff --combined target/radio/recv.c index 00000000,1f50d8a9..c50c3205 mode 000000,100644..100644 --- a/target/radio/recv.c +++ b/target/radio/recv.c @@@ -1,0 -1,68 +1,68 @@@ + /* + * 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 "radio.h" + + main () + { + static uint8_t packet[PACKET_LEN + 2]; + CLKCON = 0; + while (!(SLEEP & SLEEP_XOSC_STB)) + ; + /* Set P2_0 to output */ + P1 = 0; + P1DIR = 0x02; + radio_init (); + delay(100); + + for (;;) { + uint8_t i; + RFST = RFST_SIDLE; + RFIF = 0; + delay(100); + RFST = RFST_SRX; + // while (!(RFIF & RFIF_IM_CS)); + // P1 = 2; + for (i = 0; i < PACKET_LEN + 2; i++) { + while (!RFTXRXIF) + ; + P1=2; + RFTXRXIF = 0; + packet[i] = RFD; + } + P1 = 0; - ++ + /* check packet contents */ + for (i = 0; i < PACKET_LEN; i++) + if (packet[i] != i) + break; + + /* get excited if the packet came through correctly */ + if (i == PACKET_LEN && + packet[PACKET_LEN+1] & PKT_APPEND_STATUS_1_CRC_OK) + { + for (i = 0; i < 5; i++){ + P1 = 2; + delay(100); + P1 = 0; + delay(100); + } + } + delay(100); + } + } diff --combined target/serial/serial.c index 00000000,29390426..63f6c6de mode 000000,100644..100644 --- a/target/serial/serial.c +++ b/target/serial/serial.c @@@ -1,0 -1,270 +1,270 @@@ + /* + * 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 + + /* + * Validate UART1 + */ + + sfr at 0x80 P0; + sfr at 0x90 P1; + sfr at 0xA0 P2; + sfr at 0xC6 CLKCON; + sfr at 0xbe SLEEP; + + # define SLEEP_USB_EN (1 << 7) + # define SLEEP_XOSC_STB (1 << 6) + + sfr at 0xF1 PERCFG; + #define PERCFG_T1CFG_ALT_1 (0 << 6) + #define PERCFG_T1CFG_ALT_2 (1 << 6) + + #define PERCFG_T3CFG_ALT_1 (0 << 5) + #define PERCFG_T3CFG_ALT_2 (1 << 5) + + #define PERCFG_T4CFG_ALT_1 (0 << 4) + #define PERCFG_T4CFG_ALT_2 (1 << 4) + + #define PERCFG_U1CFG_ALT_1 (0 << 1) + #define PERCFG_U1CFG_ALT_2 (1 << 1) + + #define PERCFG_U0CFG_ALT_1 (0 << 0) + #define PERCFG_U0CFG_ALT_2 (1 << 0) + + sfr at 0xF2 ADCCFG; + sfr at 0xF3 P0SEL; + sfr at 0xF4 P1SEL; + sfr at 0xF5 P2SEL; + + sfr at 0xFD P0DIR; + sfr at 0xFE P1DIR; + sfr at 0xFF P2DIR; + sfr at 0x8F P0INP; + sfr at 0xF6 P1INP; + sfr at 0xF7 P2INP; + + sfr at 0x89 P0IFG; + sfr at 0x8A P1IFG; + sfr at 0x8B P2IFG; + + sbit at 0x90 P1_0; + sbit at 0x91 P1_1; + sbit at 0x92 P1_2; + sbit at 0x93 P1_3; + sbit at 0x94 P1_4; + sbit at 0x95 P1_5; + sbit at 0x96 P1_6; + sbit at 0x97 P1_7; + + /* + * UART registers + */ + + sfr at 0x86 U0CSR; + sfr at 0xF8 U1CSR; + + /* + * IRCON2 + */ + sfr at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ + + sbit at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ + sbit at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ + sbit at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ + sbit at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ + sbit at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ + sbit at 0xEB P1IF; /* Port1 interrupt flag */ + sbit at 0xEC WDTIF; /* Watchdog timer interrupt flag */ + + # define UxCSR_MODE_UART (1 << 7) + # define UxCSR_MODE_SPI (0 << 7) + # define UxCSR_RE (1 << 6) + # define UxCSR_SLAVE (1 << 5) + # define UxCSR_MASTER (0 << 5) + # define UxCSR_FE (1 << 4) + # define UxCSR_ERR (1 << 3) + # define UxCSR_RX_BYTE (1 << 2) + # define UxCSR_TX_BYTE (1 << 1) + # define UxCSR_ACTIVE (1 << 0) + + sfr at 0xc4 U0UCR; + sfr at 0xfb U1UCR; + + # define UxUCR_FLUSH (1 << 7) + # define UxUCR_FLOW_DISABLE (0 << 6) + # define UxUCR_FLOW_ENABLE (1 << 6) + # define UxUCR_D9_EVEN_PARITY (0 << 5) + # define UxUCR_D9_ODD_PARITY (1 << 5) + # define UxUCR_BIT9_8_BITS (0 << 4) + # define UxUCR_BIT9_9_BITS (1 << 4) + # define UxUCR_PARITY_DISABLE (0 << 3) + # define UxUCR_PARITY_ENABLE (1 << 3) + # define UxUCR_SPB_1_STOP_BIT (0 << 2) + # define UxUCR_SPB_2_STOP_BITS (1 << 2) + # define UxUCR_STOP_LOW (0 << 1) + # define UxUCR_STOP_HIGH (1 << 1) + # define UxUCR_START_LOW (0 << 0) + # define UxUCR_START_HIGH (1 << 0) + + sfr at 0xc5 U0GCR; + sfr at 0xfc U1GCR; + + # define UxGCR_CPOL_NEGATIVE (0 << 7) + # define UxGCR_CPOL_POSITIVE (1 << 7) + # define UxGCR_CPHA_FIRST_EDGE (0 << 6) + # define UxGCR_CPHA_SECOND_EDGE (1 << 6) + # define UxGCR_ORDER_LSB (0 << 5) + # define UxGCR_ORDER_MSB (1 << 5) + # define UxGCR_BAUD_E_MASK (0x1f) + # define UxGCR_BAUD_E_SHIFT 0 + + sfr at 0xc1 U0DBUF; + sfr at 0xf9 U1DBUF; + sfr at 0xc2 U0BAUD; + sfr at 0xfa U1BAUD; + + #define MOSI P1_5 + #define MISO P1_4 + #define SCK P1_3 + #define CS P1_2 + + #define DEBUG P1_1 + + #define USART 1 + + #define nop() _asm nop _endasm; + + void + delay (unsigned char n) + { + unsigned char i = 0; + unsigned char j = 0; + + n++; + while (--n != 0) + while (--i != 0) + while (--j != 0) + nop(); + } + + /* + * This version uses the USART in SPI mode + */ + void + usart_init(void) + { + P1DIR |= (1 << 2); + /* + * Configure the peripheral pin choices + * for both of the serial ports + * + * Note that telemetrum will use U1CFG_ALT_2 + * but that overlaps with SPI ALT_2, so until + * we can test that this works, we'll set this + * to ALT_1 + */ + PERCFG = (PERCFG_U1CFG_ALT_2 | + PERCFG_U0CFG_ALT_1); + + /* + * Make the UART pins controlled by the UART + * hardware + */ + P1SEL |= ((1 << 6) | (1 << 7)); + + /* + * UART mode with the receiver enabled + */ + U1CSR = (UxCSR_MODE_UART | + UxCSR_RE); + /* + * Pick a 38.4kbaud rate + */ + U1BAUD = 163; + U1GCR = 10 << UxGCR_BAUD_E_SHIFT; /* 38400 */ + // U1GCR = 3 << UxGCR_BAUD_E_SHIFT; /* 300 */ + /* + * Reasonable serial parameters + */ + U1UCR = (UxUCR_FLUSH | + UxUCR_FLOW_DISABLE | + UxUCR_D9_ODD_PARITY | + UxUCR_BIT9_8_BITS | + UxUCR_PARITY_DISABLE | + UxUCR_SPB_2_STOP_BITS | + UxUCR_STOP_HIGH | + UxUCR_START_LOW); + } + + void + usart_out_byte(uint8_t byte) + { + U1DBUF = byte; + while (!UTX1IF) + ; + UTX1IF = 0; + } + + void + usart_out_string(uint8_t *string) + { + uint8_t b; + + while (b = *string++) + usart_out_byte(b); + } + + uint8_t + usart_in_byte(void) + { + uint8_t b; + while ((U1CSR & UxCSR_RX_BYTE) == 0) + ; + b = U1DBUF; + U1CSR &= ~UxCSR_RX_BYTE; + return b; + } + + void + debug_byte(uint8_t byte) + { + uint8_t s; + + for (s = 0; s < 8; s++) { + DEBUG = byte & 1; + delay(5); + byte >>= 1; + } + } + + main () + { + P1DIR |= 2; + CLKCON = 0; + while (!(SLEEP & SLEEP_XOSC_STB)) + ; - ++ + usart_init(); + + for (;;) { + usart_out_string("hello world\r\n"); + debug_byte(usart_in_byte()); + } - ++ + } diff --combined target/timer/cc1111.h index 00000000,7a531cc0..76c95c27 mode 000000,100644..100644 --- a/target/timer/cc1111.h +++ b/target/timer/cc1111.h @@@ -1,0 -1,294 +1,294 @@@ + /*------------------------------------------------------------------------- + Register Declarations for the ChipCon CC1111 Processor Range + + 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. + + Adapted from the Cygnal C8051F12x config file which is: - ++ + Copyright (C) 2003 - Maarten Brock, sourceforge.brock@dse.nl + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + -------------------------------------------------------------------------*/ + + #ifndef _CC1111_H_ + #define _CC1111_H_ + + + /* BYTE Registers */ + + sfr at 0x80 P0 ; /* PORT 0 */ + sfr at 0x81 SP ; /* STACK POINTER */ + sfr at 0x82 DPL ; /* DATA POINTER - LOW BYTE */ + sfr at 0x83 DPH ; /* DATA POINTER - HIGH BYTE */ + sfr at 0x84 DPL1 ; /* DATA POINTER 1 - LOW BYTE */ + sfr at 0x85 DPH1 ; /* DATA POINTER 1 - HIGH BYTE */ + sfr at 0x86 U0CSR ; /* USART 0 Control and status */ + sfr at 0x87 PCON ; /* POWER CONTROL */ + sfr at 0x88 TCON ; /* TIMER CONTROL */ + sfr at 0x89 P0IFG ; /* TIMER MODE */ + sfr at 0x8A P1IFG ; /* TIMER 0 - LOW BYTE */ + sfr at 0x8B P2IFG ; /* TIMER 1 - LOW BYTE */ + sfr at 0x8C PICTL ; /* TIMER 0 - HIGH BYTE */ + sfr at 0x8D P1IEN ; /* TIMER 1 - HIGH BYTE */ + + sfr at 0x8F P0INP ; /* FLASH WRITE/ERASE CONTROL */ + sfr at 0x90 P1 ; /* PORT 1 */ + sfr at 0x91 RFIM ; /* UART 0 STATUS */ + sfr at 0x92 DPS ; /* */ + sfr at 0x93 MPAGE ; /* */ + sfr at 0x94 _SFR94_ ; /* */ + sfr at 0x95 ENDIAN ; /* */ + sfr at 0x96 _SFR96_ ; /* */ + sfr at 0x97 _SFR97_ ; /* */ + sfr at 0x98 S0CON ; /* UART 0 CONTROL */ + sfr at 0x99 _SFR99_ ; /* UART 0 BUFFER */ + sfr at 0x9A IEN2 ; /* SPI 0 CONFIGURATION */ + sfr at 0x9B S1CON ; /* SPI 0 DATA */ + sfr at 0x9C T2CT ; /* SPI 0 DATA */ + sfr at 0x9D T2PR ; /* SPI 0 CLOCK RATE CONTROL */ + sfr at 0x9E T2CTL ; /* SPI 0 CLOCK RATE CONTROL */ + sfr at 0x9F _SFR9F_ ; /* SPI 0 CLOCK RATE CONTROL */ + sfr at 0xA0 P2 ; /* PORT 2 */ + sfr at 0xA1 WORIRQ ; /* EMIF TIMING CONTROL */ + sfr at 0xA2 WORCTRL ; /* EMIF CONTROL */ + sfr at 0xA3 WOREVT0 ; /* EMIF CONFIGURATION */ + sfr at 0xA4 WOREVT1 ; /* EMIF CONFIGURATION */ + sfr at 0xA5 WORTIME0 ; /* EMIF CONFIGURATION */ + sfr at 0xA6 WORTIME1 ; /* EMIF CONFIGURATION */ + sfr at 0xA7 _SFRA7_ ; /* EMIF CONFIGURATION */ + sfr at 0xA8 IEN0 ; /* INTERRUPT ENABLE */ + sfr at 0xA9 IP0 ; /* UART 0 SLAVE ADDRESS */ + sfr at 0xAA _SFRAA_ ; /* */ + sfr at 0xAB FWT ; /* */ + sfr at 0xAC FADDRL ; /* */ + sfr at 0xAD FADDRH ; /* */ + sfr at 0xAE FCTL ; /* */ + sfr at 0xAF FWDATA ; /* */ + sfr at 0xB0 _SFRB0_ ; /* */ + sfr at 0xB1 ENCDI ; /* FLASH BANK SELECT */ + sfr at 0xB2 ENCDO ; /* */ + sfr at 0xB3 ENCCS ; /* */ + sfr at 0xB4 ADCCON1 ; /* */ + sfr at 0xB5 ADCCON2 ; /* */ + sfr at 0xB6 ADCCON3 ; /* */ + sfr at 0xB8 IEN1 ; /* INTERRUPT PRIORITY */ + sfr at 0xB9 IP1 ; /* */ + sfr at 0xBA ADCL ; /* */ + sfr at 0xBB ADCH ; /* */ + sfr at 0xBC RNDL ; /* */ + sfr at 0xBD RNDH ; /* */ + sfr at 0xBE SLEEP ; /* */ + sfr at 0xC0 IRCON ; /* */ + sfr at 0xC1 U0DBUF ; /* */ + sfr at 0xC2 U0BAUD ; /* */ + sfr at 0xC4 U0UCR ; /* */ + sfr at 0xC5 U0GCR ; /* */ + sfr at 0xC6 CLKCON ; /* */ + sfr at 0xC7 MEMCTR ; /* */ + sfr at 0xC9 WDCTL ; /* */ + sfr at 0xCA T3CNT ; /* */ + sfr at 0xCB T3CTL ; /* */ + sfr at 0xCC T3CCTL0 ; /* */ + sfr at 0xCD T3CC0 ; /* */ + sfr at 0xCE T3CCTL1 ; /* */ + sfr at 0xCF T3CC1 ; /* */ + sfr at 0xD0 PSW ; /* */ + sfr at 0xD1 DMAIRQ ; /* */ + sfr at 0xD2 DMA1CFGL ; /* */ + sfr at 0xD3 DMA1CFGH ; /* */ + sfr at 0xD4 DMA0CFGL ; /* */ + sfr at 0xD5 DMA0CFGH ; /* */ + sfr at 0xD6 DMAARM ; /* */ + sfr at 0xD7 DMAREQ ; /* */ + sfr at 0xD8 TIMIF ; /* */ + sfr at 0xD9 RFD ; /* */ + sfr at 0xDA T1CC0L ; /* */ + sfr at 0xDB T1CC0H ; /* */ + sfr at 0xDC T1CC1L ; /* */ + sfr at 0xDD T1CC1H ; /* */ + sfr at 0xDE T1CC2L ; /* */ + sfr at 0xDF T1CC2H ; /* */ + sfr at 0xE0 ACC ; /* ACCUMULATOR */ -sfr at 0xE1 RFST ; /* */ -sfr at 0xE2 T1CNTL ; /* */ -sfr at 0xE3 T1CNTH ; /* */ -sfr at 0xE4 T1CTL ; /* */ -sfr at 0xE5 T1CCTL0 ; /* */ -sfr at 0xE6 T1CCTL1 ; /* */ -sfr at 0xE7 T1CCTL2 ; /* */ -sfr at 0xE8 IRCON2 ; /* */ -sfr at 0xE9 RFIF ; /* */ -sfr at 0xEA T4CNT ; /* */ -sfr at 0xEB T4CTL ; /* */ -sfr at 0xEC T4CCTL0 ; /* */ -sfr at 0xED T4CC0 ; /* */ -sfr at 0xEE T4CCTL1 ; /* */ -sfr at 0xEF T4CC1 ; /* */ -sfr at 0xF0 B ; /* */ -sfr at 0xF1 PERCFG ; /* */ -sfr at 0xF2 ADCCFG ; /* */ -sfr at 0xF3 P0SEL ; /* */ -sfr at 0xF4 P1SEL ; /* */ -sfr at 0xF5 P2SEL ; /* */ -sfr at 0xF6 P1INP ; /* */ -sfr at 0xF7 P2INP ; /* */ -sfr at 0xF8 U1CSR ; /* */ -sfr at 0xF9 U1DBUF ; /* */ -sfr at 0xFA U1BAUD ; /* */ -sfr at 0xFB U1UCR ; /* */ -sfr at 0xFC U1GCR ; /* */ -sfr at 0xFD P0DIR ; /* */ -sfr at 0xFE P1DIR ; /* */ -sfr at 0xFF P2DIR ; /* */ ++sfr at 0xE1 RFST ; /* */ ++sfr at 0xE2 T1CNTL ; /* */ ++sfr at 0xE3 T1CNTH ; /* */ ++sfr at 0xE4 T1CTL ; /* */ ++sfr at 0xE5 T1CCTL0 ; /* */ ++sfr at 0xE6 T1CCTL1 ; /* */ ++sfr at 0xE7 T1CCTL2 ; /* */ ++sfr at 0xE8 IRCON2 ; /* */ ++sfr at 0xE9 RFIF ; /* */ ++sfr at 0xEA T4CNT ; /* */ ++sfr at 0xEB T4CTL ; /* */ ++sfr at 0xEC T4CCTL0 ; /* */ ++sfr at 0xED T4CC0 ; /* */ ++sfr at 0xEE T4CCTL1 ; /* */ ++sfr at 0xEF T4CC1 ; /* */ ++sfr at 0xF0 B ; /* */ ++sfr at 0xF1 PERCFG ; /* */ ++sfr at 0xF2 ADCCFG ; /* */ ++sfr at 0xF3 P0SEL ; /* */ ++sfr at 0xF4 P1SEL ; /* */ ++sfr at 0xF5 P2SEL ; /* */ ++sfr at 0xF6 P1INP ; /* */ ++sfr at 0xF7 P2INP ; /* */ ++sfr at 0xF8 U1CSR ; /* */ ++sfr at 0xF9 U1DBUF ; /* */ ++sfr at 0xFA U1BAUD ; /* */ ++sfr at 0xFB U1UCR ; /* */ ++sfr at 0xFC U1GCR ; /* */ ++sfr at 0xFD P0DIR ; /* */ ++sfr at 0xFE P1DIR ; /* */ ++sfr at 0xFF P2DIR ; /* */ + + /* BIT Registers */ + + /* P0 0x80 */ + sbit at 0x80 P0_0 ; + sbit at 0x81 P0_1 ; + sbit at 0x82 P0_2 ; + sbit at 0x83 P0_3 ; + sbit at 0x84 P0_4 ; + sbit at 0x85 P0_5 ; + sbit at 0x86 P0_6 ; + sbit at 0x87 P0_7 ; + + /* TCON 0x88 */ + sbit at 0x89 RFTXRXIF; /* */ + sbit at 0x8B URX0IF ; /* */ + sbit at 0x8D ADCIF ; /* */ + sbit at 0x8F URX1IF ; /* */ + sbit at 0x8F I2SRXIF ; /* */ + + /* SCON0 0x98 */ + sbit at 0x98 ENCIF_0 ; /* UART 0 RX INTERRUPT FLAG */ + sbit at 0x99 ENCIF_1 ; /* UART 0 RX INTERRUPT FLAG */ + + /* IEN0 0xA8 */ + sbit at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */ + sbit at 0xA9 ADCIE ; /* ADC interrupt enable */ + sbit at 0xAA URX0IE ; /* USART0 RX interrupt enable */ + sbit at 0xAB URX1IE ; /* USART1 RX interrupt enable */ + sbit at 0xAB I2SRXIE ; /* I2S RX interrupt enable */ + sbit at 0xAC ENCIE ; /* AES interrupt enable */ + sbit at 0xAD STIE ; /* Sleep Timer interrupt enable */ + sbit at 0xAF EA ; /* GLOBAL INTERRUPT ENABLE */ + + /* IEN1 0xB8 */ + sbit at 0xB8 DMAIE ; /* DMA transfer interrupt enable */ + sbit at 0xB9 T1IE ; /* Timer 1 interrupt enable */ + sbit at 0xBA T2IE ; /* Timer 2 interrupt enable */ + sbit at 0xBB T3IE ; /* Timer 3 interrupt enable */ + sbit at 0xBC T4IE ; /* Timer 4 interrupt enable */ + sbit at 0xBD P0IE ; /* Port 0 interrupt enable */ + + /* IRCON 0xC0 */ + sbit at 0xC0 DMAIF ; /* */ + sbit at 0xC1 T1IF ; /* */ + sbit at 0xC2 T2IF ; /* */ + sbit at 0xC3 T3IF ; /* */ + sbit at 0xC4 T4IF ; /* */ + sbit at 0xC5 P0IF ; /* */ + sbit at 0xC7 STIF ; /* */ + + /* PSW 0xD0 */ + sbit at 0xD0 P ; /* ACCUMULATOR PARITY FLAG */ + sbit at 0xD1 F1 ; /* USER FLAG 1 */ + sbit at 0xD2 OV ; /* OVERFLOW FLAG */ + sbit at 0xD3 RS0 ; /* REGISTER BANK SELECT 0 */ + sbit at 0xD4 RS1 ; /* REGISTER BANK SELECT 1 */ + sbit at 0xD5 F0 ; /* USER FLAG 0 */ + sbit at 0xD6 AC ; /* AUXILIARY CARRY FLAG */ + sbit at 0xD7 CY ; /* CARRY FLAG */ + + /* TIMIF D8H */ + sbit at 0xD8 T3OVFIF ; /* */ + sbit at 0xD9 T3CH0IF ; /* */ + sbit at 0xDA T3CH1IF ; /* */ + sbit at 0xDB T4OVFIF ; /* */ + sbit at 0xDC T4CH0IF ; /* */ + sbit at 0xDD T4CH1IF ; /* */ + sbit at 0xDE OVFIM ; /* */ + + /* IRCON2 E8H */ + sbit at 0xE8 P2IF ; /* */ + sbit at 0xE8 USBIF ; /* */ + sbit at 0xE9 UTX0IF ; /* */ + sbit at 0xEA UTX1IF ; /* */ + sbit at 0xEA I2STXIF ; /* */ + sbit at 0xEB P1IF ; /* */ + sbit at 0xEC WDTIF ; /* */ + + /* U1CSR F8H */ + sbit at 0xF8 U1_ACTIVE ; /* */ + sbit at 0xF9 U1_TX_BYTE ; /* */ + sbit at 0xFA U1_RX_BYTE ; /* */ + sbit at 0xFB U1_ERR ; /* */ + sbit at 0xFC U1_FE ; /* */ + sbit at 0xFD U1_SLAVE ; /* */ + sbit at 0xFE U1_RE ; /* */ + sbit at 0xFF U1_MODE ; /* */ + + #define T1CTL_MODE_SUSPENDED (0 << 0) + #define T1CTL_MODE_FREE (1 << 0) + #define T1CTL_MODE_MODULO (2 << 0) + #define T1CTL_MODE_UP_DOWN (3 << 0) + #define T1CTL_MODE_MASK (3 << 0) + #define T1CTL_DIV_1 (0 << 2) + #define T1CTL_DIV_8 (1 << 2) + #define T1CTL_DIV_32 (2 << 2) + #define T1CTL_DIV_128 (3 << 2) + #define T1CTL_DIV_MASK (3 << 2) + #define T1CTL_OVFIF (1 << 4) + #define T1CTL_CH0IF (1 << 5) + #define T1CTL_CH1IF (1 << 6) + #define T1CTL_CH2IF (1 << 7) + + #define T1CCTL_NO_CAPTURE (0 << 0) + #define T1CCTL_CAPTURE_RISING (1 << 0) + #define T1CCTL_CAPTURE_FALLING (2 << 0) + #define T1CCTL_CAPTURE_BOTH (3 << 0) + #define T1CCTL_CAPTURE_MASK (3 << 0) + + #define T1CCTL_MODE_CAPTURE (0 << 2) + #define T1CCTL_MODE_COMPARE (1 << 2) + + #define T1CTL_CMP_SET (0 << 3) + #define T1CTL_CMP_CLEAR (1 << 3) + #define T1CTL_CMP_TOGGLE (2 << 3) + #define T1CTL_CMP_SET_CLEAR (3 << 3) + #define T1CTL_CMP_CLEAR_SET (4 << 3) + + #define T1CTL_IM_DISABLED (0 << 6) + #define T1CTL_IM_ENABLED (1 << 6) + + #define T1CTL_CPSEL_NORMAL (0 << 7) + #define T1CTL_CPSEL_RF (1 << 7) + + #endif diff --combined tests/debug_mode index 00000000,fe25bfef..2b5ec020 mode 000000,100644..100644 --- a/tests/debug_mode +++ b/tests/debug_mode @@@ -1,0 -1,11 +1,10 @@@ + # + # Debug mode - drive RESET_N low for two clock cycles + # + + C D R + . D . + C D . + . D . + C D . + . D R - diff --combined tests/get_status index 00000000,1d4ff03d..3e67a2e0 mode 000000,100644..100644 --- a/tests/get_status +++ b/tests/get_status @@@ -1,0 -1,329 +1,328 @@@ + # + # Debug mode - drive RESET_N low for two clock cycles + # + C D R + . D . + C D . + . D . + C D . + . D R + + # + # Halt 0x44 + # + + C . R 0 + . . R + C D R 1 + . D R + C . R 0 + . . R + C . R 0 + . . R + + C . R 0 + . . R + C D R 1 + . D R + C . R 0 + . . R + C . R 0 + . . R + + # status byte + + C D R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + C - R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + # Resume 0x4c + # + + C . R 0 + . . R + C D R 1 + . D R + C . R 0 + . . R + C . R 0 + . . R + + C D R 1 + . D R + C D R 1 + . D R + C . R 0 + . . R + C . R 0 + . . R + + # status byte + + C D R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + C - R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + # + # READ_STATUS + # + + C . R 0 + . . R + C . R 0 + . . R + C D R 1 + . D R + C D R 1 + . D R + + C . R 0 + . . R + C D R 1 + . D R + C . R 0 + . . R + C . R 0 + . . R + + # + # status + # + + C D R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + C - R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + # + # READ_STATUS + # + + C . R 0 + . . R + C . R 0 + . . R + C D R 1 + . D R + C D R 1 + . D R + + C . R 0 + . . R + C D R 1 + . D R + C . R 0 + . . R + C . R 0 + . . R + + # + # status + # + + C D R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + C - R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + # + # READ_STATUS + # + + C . R 0 + . . R + C . R 0 + . . R + C D R 1 + . D R + C D R 1 + . D R + + C . R 0 + . . R + C D R 1 + . D R + C . R 0 + . . R + C . R 0 + . . R + + # + # status + # + + C D R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + C - R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + # + # Halt 0x44 + # + + C . R 0 + . . R + C D R 1 + . D R + C . R 0 + . . R + C . R 0 + . . R + + C . R 0 + . . R + C D R 1 + . D R + C . R 0 + . . R + C . R 0 + . . R + + # status byte + + C D R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + C - R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + # + # READ_STATUS + # + + C . R 0 + . . R + C . R 0 + . . R + C D R 1 + . D R + C D R 1 + . D R + + C . R 0 + . . R + C D R 1 + . D R + C . R 0 + . . R + C . R 0 + . . R + + # + # status + # + + C D R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + C - R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + C - R + . - R + C - R + . - R + C - R + . - R + C - R + . - R + + C - R + . - R + C - R + . - R + C - R + . - R + C - R + . - R -