Add OpenULINK firmware
authorMartin Schmölzer <martin.schmoelzer@student.tuwien.ac.at>
Mon, 20 Jun 2011 17:49:49 +0000 (19:49 +0200)
committerØyvind Harboe <oyvind.harboe@zylin.com>
Sun, 26 Jun 2011 15:43:51 +0000 (17:43 +0200)
Build requires SDCC, the Small Device C Compiler.

19 files changed:
src/jtag/drivers/OpenULINK/Makefile [new file with mode: 0644]
src/jtag/drivers/OpenULINK/README [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/common.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/delay.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/io.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/jtag.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/main.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/msgtypes.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/protocol.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/reg_ezusb.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/shorttypes.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/include/usb.h [new file with mode: 0644]
src/jtag/drivers/OpenULINK/src/USBJmpTb.a51 [new file with mode: 0644]
src/jtag/drivers/OpenULINK/src/delay.c [new file with mode: 0644]
src/jtag/drivers/OpenULINK/src/jtag.c [new file with mode: 0644]
src/jtag/drivers/OpenULINK/src/main.c [new file with mode: 0644]
src/jtag/drivers/OpenULINK/src/protocol.c [new file with mode: 0644]
src/jtag/drivers/OpenULINK/src/usb.c [new file with mode: 0644]
src/jtag/drivers/OpenULINK/ulink_firmware.hex [new file with mode: 0644]

diff --git a/src/jtag/drivers/OpenULINK/Makefile b/src/jtag/drivers/OpenULINK/Makefile
new file mode 100644 (file)
index 0000000..c0e3435
--- /dev/null
@@ -0,0 +1,90 @@
+############################################################################
+#    Copyright (C) 2011 by Martin Schmoelzer                               #
+#    <martin.schmoelzer@student.tuwien.ac.at>                              #
+#                                                                          #
+#    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.             #
+############################################################################
+
+# Define the name of our tools. Some distributions (e. g. Fedora) prefix
+# the SDCC executables, change this accordingly!
+PREFIX =
+
+# Small Device C Compiler: http://sdcc.sourceforge.net/
+CC = $(PREFIX)-sdcc
+
+# 8051 assembler, part of the SDCC software package.
+AS = $(PREFIX)-sdas8051
+
+# SDCC produces quite messy Intel HEX files. This tool is be used to re-format
+# those files. It is not required for the firmware download functionality in
+# the OpenOCD driver, but the resulting file is smaller.
+PACKIHX = $(PREFIX)-packihx
+
+# GNU binutils size. Used to print the size of the IHX file generated by SDCC.
+SIZE = size
+
+# Source and header directories.
+SRC_DIR     = src
+INCLUDE_DIR = include
+
+CODE_SIZE = 0x1B00
+
+# Starting address of __xdata variables. Since the OpenULINK firmware does not
+# use any of the isochronous interrupts, we can use the isochronous buffer space
+# as XDATA memory.
+XRAM_LOC  = 0x2000
+XRAM_SIZE = 0x0800
+
+CFLAGS  = --std-sdcc99 --opt-code-size --model-small
+LDFLAGS = --code-loc 0x0000 --code-size $(CODE_SIZE) --xram-loc $(XRAM_LOC) \
+          --xram-size $(XRAM_SIZE) --iram-size 256 --model-small
+
+# list of base object files
+OBJECTS = main.rel usb.rel protocol.rel jtag.rel delay.rel USBJmpTb.rel
+HEADERS = $(INCLUDE_DIR)/main.h         \
+          $(INCLUDE_DIR)/usb.h          \
+          $(INCLUDE_DIR)/protocol.h     \
+          $(INCLUDE_DIR)/jtag.h         \
+          $(INCLUDE_DIR)/delay.h        \
+          $(INCLUDE_DIR)/reg_ezusb.h    \
+          $(INCLUDE_DIR)/io.h           \
+          $(INCLUDE_DIR)/msgtypes.h     \
+          $(INCLUDE_DIR)/shorttypes.h
+
+# Disable all built-in rules.
+.SUFFIXES:
+
+# Targets which are executed even when identically named file is present.
+.PHONY: all, clean
+
+all: ulink_firmware.ihx
+       $(SIZE) ulink_firmware.ihx
+
+ulink_firmware.ihx: $(OBJECTS)
+       $(CC) -mmcs51 $(LDFLAGS) -o $@ $^
+
+# Rebuild every C module (there are only 5 of them) if any header changes.
+%.rel: $(SRC_DIR)/%.c $(HEADERS)
+       $(CC) -c $(CFLAGS) -mmcs51 -I$(INCLUDE_DIR) -o $@ $<
+
+%.rel: $(SRC_DIR)/%.a51
+       $(AS) -lsgo $@ $<
+
+clean:
+       rm -f *.asm *.lst *.rel *.rst *.sym *.ihx *.lnk *.map *.mem
+
+hex: ulink_firmware.ihx
+       $(PACKIHX) ulink_firmware.ihx > ulink_firmware.hex
diff --git a/src/jtag/drivers/OpenULINK/README b/src/jtag/drivers/OpenULINK/README
new file mode 100644 (file)
index 0000000..445d770
--- /dev/null
@@ -0,0 +1,34 @@
+This is the OpenULINK firmware for the Keil ULINK JTAG adapter.
+
+The main components of the Keil ULINK adapter are:
+- Cypress EZ-USB microcontroller: enhanced 8051 CPU + USB core (1.1 Full-Speed)
+- SRAM memory chip
+- Level shifters to support different JTAG signal voltage levels
+- Pin headers for various JTAG pin assignments
+
+This firmware can only be run on the ORIGINAL Keil ULINK adapter, not on the
+newer ULINK2, ULINK-ME or ULINK-PRO, as these adapters are based on different
+hardware.
+
+To compile the firmware, the SDCC compiler package is required. Most Linux
+distributions include SDCC in their official package repositories. The SDCC
+source code can be found at http://sdcc.sourceforge.net/
+Simply type "make hex" in the OpenULINK directory to compile the firmware.
+"make clean" will remove all generated files except the Intel HEX file required
+for downloading the firmware to the ULINK adapter.
+
+Note that the EZ-USB microcontroller does not have on-chip flash, nor does the
+Keil ULINK include on-board memory to store the firmware program of the EZ-USB.
+Instead, upon initial connection of the ULINK adapter to the host PC via USB,
+the EZ-USB core has enough intelligence to act as a stand-alone USB device,
+responding to USB control requests and allowing firmware download via a special
+VENDOR-type control request. Then, the EZ-USB microcontroller simulates a
+disconnect and re-connect to the USB bus. It may take up to two seconds for the
+host to recognize the newly connected device before OpenOCD can proceed to
+execute JTAG commands. This delay is only visible when OpenOCD first uses a
+blank (unconfigured) ULINK device.
+
+Once the user disconnects the ULINK adapter, all its memory contents are lost
+and the firmware download process has to be executed again. This also maintains
+compatibility with the original Keil uVision IDE, which will happily download
+its own firmware image to a blank ULINK adapter.
diff --git a/src/jtag/drivers/OpenULINK/include/common.h b/src/jtag/drivers/OpenULINK/include/common.h
new file mode 100644 (file)
index 0000000..f4c966c
--- /dev/null
@@ -0,0 +1,26 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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 __COMMON_H
+#define __COMMON_H
+
+#define DIV_ROUND_UP(m, n)  (((m) + (n) - 1) / (n))
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/delay.h b/src/jtag/drivers/OpenULINK/include/delay.h
new file mode 100644 (file)
index 0000000..3dfaf35
--- /dev/null
@@ -0,0 +1,34 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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 __DELAY_H
+#define __DELAY_H
+
+#include "shorttypes.h"
+
+#define NOP  {__asm nop __endasm;}
+
+void delay_5us(void);
+void delay_1ms(void);
+
+void delay_us(u16 delay);
+void delay_ms(u16 delay);
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/io.h b/src/jtag/drivers/OpenULINK/include/io.h
new file mode 100644 (file)
index 0000000..f7119b9
--- /dev/null
@@ -0,0 +1,125 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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 __IO_H
+#define __IO_H
+
+#include "reg_ezusb.h"
+
+/***************************************************************************
+ *  JTAG Signals:                                                          *
+ ***************************************************************************
+ * TMS ....... Test Mode Select                                            *
+ * TCK ....... Test Clock                                                  *
+ * TDI ....... Test Data Input  (from device point of view, not JTAG       *
+ *             adapter point of view!)                                     *
+ * TDO ....... Test Data Output (from device point of view, not JTAG       *
+ *             adapter point of view!)                                     *
+ * TRST ...... Test Reset: Used to reset the TAP Finite State Machine      *
+ *             into the Test Logic Reset state                             *
+ * RTCK ...... Return Test Clock                                           *
+ * OCDSE ..... Enable/Disable OCDS interface (Infineon specific) - shared  *
+ *             with /JEN                                                   *
+ * TRAP ...... Trap Condition (Infineon specific) - shared with TSTAT      *
+ * BRKIN ..... Hardware Break-In (Infineon specific)                       *
+ * BRKOUT .... Hardware Break-Out (Infineon specific)                      *
+ * /JEN ...... JTAG-Enable (STMicroelectronics specific) - shared          *
+ *             with OCDSE                                                  *
+ * TSTAT ..... JTAG ISP Status (STMicroelectronics specific) - shared      *
+ *             with TRAP                                                   *
+ * RESET ..... Chip Reset (STMicroelectronics specific)                    *
+ * /TERR ..... JTAG ISP Error (STMicroelectronics specific) - shared       *
+ *             with BRKOUT                                                 *
+ ***************************************************************************/
+
+/* PORT A */
+#define PIN_U_OE      OUTA0
+// PA1 Not Connected
+#define PIN_OE        OUTA2
+// PA3 Not Connected
+#define PIN_RUN_LED   OUTA4
+#define PIN_TDO       PINA5
+#define PIN_BRKOUT    PINA6
+#define PIN_COM_LED   OUTA7
+
+
+/* PORT B */
+#define PIN_TDI       OUTB0
+#define PIN_TMS       OUTB1
+#define PIN_TCK       OUTB2
+#define PIN_TRST      OUTB3
+#define PIN_BRKIN     OUTB4
+#define PIN_RESET     OUTB5
+#define PIN_OCDSE     OUTB6
+#define PIN_TRAP      PINB7
+
+/* JTAG Signals with direction 'OUT' on port B */
+#define MASK_PORTB_DIRECTION_OUT (PIN_TDI | PIN_TMS | PIN_TCK | PIN_TRST | PIN_BRKIN | PIN_RESET | PIN_OCDSE)
+
+/* PORT C */
+#define PIN_RXD0      PINC0
+#define PIN_TXD0      OUTC1
+#define PIN_RESET_2   PINC2
+// PC3 Not Connected
+// PC4 Not Connected
+#define PIN_RTCK      PINC5
+#define PIN_WR        OUTC6
+// PC7 Not Connected
+
+/* LED Macros */
+#define SET_RUN_LED()     OUTA &= ~PIN_RUN_LED
+#define CLEAR_RUN_LED()   OUTA |=  PIN_RUN_LED
+
+#define SET_COM_LED()     OUTA &= ~PIN_COM_LED
+#define CLEAR_COM_LED()   OUTA |=  PIN_COM_LED
+
+/* JTAG Pin Macros */
+#define GET_TMS()         (PINSB & PIN_TMS)
+#define GET_TCK()         (PINSB & PIN_TCK)
+
+#define GET_TDO()         (PINSA & PIN_TDO)
+#define GET_BRKOUT()      (PINSA & PIN_BRKOUT)
+#define GET_TRAP()        (PINSB & PIN_TRAP)
+#define GET_RTCK()        (PINSC & PIN_RTCK)
+
+#define SET_TMS_HIGH()    OUTB |=  PIN_TMS
+#define SET_TMS_LOW()     OUTB &= ~PIN_TMS
+
+#define SET_TCK_HIGH()    OUTB |=  PIN_TCK
+#define SET_TCK_LOW()     OUTB &= ~PIN_TCK
+
+#define SET_TDI_HIGH()    OUTB |=  PIN_TDI
+#define SET_TDI_LOW()     OUTB &= ~PIN_TDI
+
+/* TRST and RESET are low-active and inverted by hardware. SET_HIGH de-asserts
+ * the signal (enabling reset), SET_LOW asserts the signal (disabling reset) */
+#define SET_TRST_HIGH()   OUTB |=  PIN_TRST
+#define SET_TRST_LOW()    OUTB &= ~PIN_TRST
+
+#define SET_RESET_HIGH()  OUTB |=  PIN_RESET
+#define SET_RESET_LOW()   OUTB &= ~PIN_RESET
+
+#define SET_OCDSE_HIGH()  OUTB |=  PIN_OCDSE
+#define SET_OCDSE_LOW()   OUTB &= ~PIN_OCDSE
+
+#define SET_BRKIN_HIGH()  OUTB |=  PIN_BRKIN
+#define SET_BRKIN_LOW()   OUTB &= ~PIN_BRKIN
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/jtag.h b/src/jtag/drivers/OpenULINK/include/jtag.h
new file mode 100644 (file)
index 0000000..93ecfb0
--- /dev/null
@@ -0,0 +1,46 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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 __JTAG_H
+#define __JTAG_H
+
+#include "shorttypes.h"
+
+#define NOP {__asm nop __endasm;}
+
+void jtag_scan_in(u8 out_offset, u8 in_offset);
+void jtag_scan_out(u8 out_offset);
+void jtag_scan_io(u8 out_offset, u8 in_offset);
+
+void jtag_slow_scan_in(u8 scan_size_bytes, u8 tdo_index, u8 scan_options);
+void jtag_slow_scan_out(u8 scan_size_bytes, u8 tdi_index, u8 scan_options);
+void jtag_slow_scan_io(u8 scan_size_bytes, u8 tdi_index, u8 tdo_index,
+    u8 scan_options);
+
+void jtag_clock_tck(u16 count);
+void jtag_clock_tms(u8 count, u8 sequence);
+void jtag_slow_clock_tms(u8 count, u8 sequence);
+
+u16  jtag_get_signals(void);
+void jtag_set_signals(u8 low, u8 high);
+
+void jtag_configure_tck_delay(u8 scan, u8 tck, u8 tms);
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/main.h b/src/jtag/drivers/OpenULINK/include/main.h
new file mode 100644 (file)
index 0000000..08d748c
--- /dev/null
@@ -0,0 +1,26 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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 __MAIN_H
+#define __MAIN_H
+
+void io_init(void);
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/msgtypes.h b/src/jtag/drivers/OpenULINK/include/msgtypes.h
new file mode 100644 (file)
index 0000000..e3afb67
--- /dev/null
@@ -0,0 +1,187 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+/**
+ * @file Definition of the commands supported by the OpenULINK firmware.
+ *
+ * Basically, two types of commands can be distinguished:
+ *  - Commands with fixed payload size
+ *  - Commands with variable payload size
+ *
+ * SCAN commands (in all variations) carry payloads of variable size, all
+ * other commands carry payloads of fixed size.
+ *
+ * In the case of SCAN commands, the payload size (n) is calculated by
+ * dividing the scan_size_bits variable by 8, rounding up the result.
+ *
+ * Offset zero always contains the command ID.
+ *
+ ****************************************************************************
+ * CMD_SCAN_IN, CMD_SLOW_SCAN_IN:                                           *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: scan_size_bytes                                                *
+ * offset 2: bits_last_byte                                                 *
+ * offset 3: tms_count_start + tms_count_end                                *
+ * offset 4: tms_sequence_start                                             *
+ * offset 5: tms_sequence_end                                               *
+ *                                                                          *
+ * IN:                                                                      *
+ * offset 0..n: TDO data                                                    *
+ ****************************************************************************
+ * CMD_SCAN_OUT, CMD_SLOW_SCAN_OUT:                                         *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: scan_size_bytes                                                *
+ * offset 2: bits_last_byte                                                 *
+ * offset 3: tms_count_start + tms_count_end                                *
+ * offset 4: tms_sequence_start                                             *
+ * offset 5: tms_sequence_end                                               *
+ * offset 6..x: TDI data                                                    *
+ ****************************************************************************
+ * CMD_SCAN_IO, CMD_SLOW_SCAN_IO:                                           *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: scan_size_bytes                                                *
+ * offset 2: bits_last_byte                                                 *
+ * offset 3: tms_count_start + tms_count_end                                *
+ * offset 4: tms_sequence_start                                             *
+ * offset 5: tms_sequence_end                                               *
+ * offset 6..x: TDI data                                                    *
+ *                                                                          *
+ * IN:                                                                      *
+ * offset 0..n: TDO data                                                    *
+ ****************************************************************************
+ * CMD_CLOCK_TMS, CMD_SLOW_CLOCK_TMS:                                       *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: tms_count                                                      *
+ * offset 2: tms_sequence                                                   *
+ ****************************************************************************
+ * CMD_CLOCK_TCK:                                                           *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: low byte of tck_count                                          *
+ * offset 2: high byte of tck_count                                         *
+ ****************************************************************************
+ * CMD_CLOCK_SLEEP_US:                                                      *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: low byte of sleep_us                                           *
+ * offset 2: high byte of sleep_us                                          *
+ ****************************************************************************
+ * CMD_CLOCK_SLEEP_MS:                                                      *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: low byte of sleep_ms                                           *
+ * offset 2: high byte of sleep_ms                                          *
+ ****************************************************************************
+ * CMD_GET_SIGNALS:                                                         *
+ *                                                                          *
+ * IN:                                                                      *
+ * offset 0: current state of input signals                                 *
+ * offset 1: current state of output signals                                *
+ ****************************************************************************
+ * CMD_SET_SIGNALS:                                                         *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: signals that should be de-asserted                             *
+ * offset 2: signals that should be asserted                                *
+ ****************************************************************************
+ * CMD_CONFIGURE_TCK_FREQ:                                                  *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: delay value for scan functions                                 *
+ * offset 2: delay value for clock_tck function                             *
+ * offset 3: delay value for clock_tms function                             *
+ ****************************************************************************
+ * CMD_SET_LEDS:                                                            *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: LED states:                                                    *
+ *           Bit 0: turn COM LED on                                         *
+ *           Bit 1: turn RUN LED on                                         *
+ *           Bit 2: turn COM LED off                                        *
+ *           Bit 3: turn RUN LED off                                        *
+ *           Bits 7..4: Reserved                                            *
+ ****************************************************************************
+ * CMD_TEST:                                                                *
+ *                                                                          *
+ * OUT:                                                                     *
+ * offset 1: unused dummy value                                             *
+ ****************************************************************************
+ */
+
+#ifndef __MSGTYPES_H
+#define __MSGTYPES_H
+
+/*
+ * Command IDs:
+ *
+ * Bits 7..6: Reserved, should always be zero
+ * Bits 5..0: Command ID. There are 62 usable IDs. Of this 63 available IDs,
+ *            the IDs 0x00..0x1F are commands with variable payload size,
+ *            the IDs 0x20..0x3F are commands with fixed payload size.
+ */
+
+#define CMD_ID_MASK             0x3F
+
+/* Commands with variable payload size */
+#define CMD_SCAN_IN             0x00
+#define CMD_SLOW_SCAN_IN        0x01
+#define CMD_SCAN_OUT            0x02
+#define CMD_SLOW_SCAN_OUT       0x03
+#define CMD_SCAN_IO             0x04
+#define CMD_SLOW_SCAN_IO        0x05
+
+/* Commands with fixed payload size */
+#define CMD_CLOCK_TMS           0x20
+#define CMD_SLOW_CLOCK_TMS      0x21
+#define CMD_CLOCK_TCK           0x22
+#define CMD_SLEEP_US            0x23
+#define CMD_SLEEP_MS            0x24
+#define CMD_GET_SIGNALS         0x25
+#define CMD_SET_SIGNALS         0x26
+#define CMD_CONFIGURE_TCK_FREQ  0x27
+#define CMD_SET_LEDS            0x28
+#define CMD_TEST                0x29
+
+/* JTAG signal definition for jtag_get_signals() -- Input signals! */
+#define SIGNAL_TDO      (1<<0)
+#define SIGNAL_BRKOUT   (1<<1)
+#define SIGNAL_TRAP     (1<<2)
+#define SIGNAL_RTCK     (1<<3)
+
+/* JTAG signal definition for jtag_get_signals() -- Output signals! */
+#define SIGNAL_TDI      (1<<0)
+#define SIGNAL_TMS      (1<<1)
+#define SIGNAL_TCK      (1<<2)
+#define SIGNAL_TRST     (1<<3)
+#define SIGNAL_BRKIN    (1<<4)
+#define SIGNAL_RESET    (1<<5)
+#define SIGNAL_OCDSE    (1<<6)
+
+/* LED definitions for CMD_SET_LEDS and CMD_CLEAR_LEDS commands */
+#define COM_LED_ON      (1<<0)
+#define RUN_LED_ON      (1<<1)
+#define COM_LED_OFF     (1<<2)
+#define RUN_LED_OFF     (1<<3)
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/protocol.h b/src/jtag/drivers/OpenULINK/include/protocol.h
new file mode 100644 (file)
index 0000000..2129fc8
--- /dev/null
@@ -0,0 +1,33 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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 __PROTOCOL_H
+#define __PROTOCOL_H
+
+#include "shorttypes.h"
+#include "common.h"
+#include <stdbool.h>
+
+void execute_set_led_command(void);
+
+bool execute_command(void);
+void command_loop(void);
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/reg_ezusb.h b/src/jtag/drivers/OpenULINK/include/reg_ezusb.h
new file mode 100644 (file)
index 0000000..26ee018
--- /dev/null
@@ -0,0 +1,742 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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 REG_EZUSB_H
+#define REG_EZUSB_H
+
+/**
+ * @file All information in this file was taken from the EZ-USB Technical
+ * Reference Manual, Cypress Semiconductor, 3901 North First Street
+ * San Jose, CA 95134 (www.cypress.com).
+ *
+ * The EZ-USB Technical Reference Manual is called "EZ-USB TRM" hereafter.
+ *
+ * The following bit name  definitions differ from those in the EZ-USB TRM:
+ * - All lowercase characters in the EZ-USB TRM bit names have been converted
+ *   to capitals (e. g. "WakeSRC" converted to "WAKESRC").
+ * - CPUCS:  8051RES is named "RES8051".
+ * - ISOCTL: Two MBZ ("Must Be Zero") bits are named "MBZ0" and "MBZ1".
+ * - I2CS: STOP and START bits are preceded by "I2C_"
+ * - INxCS, OUTxCS: the busy and stall bits are named "EPBSY" and "EPSTALL".
+ * - TOGCTL: EZ-USB TRM bit names are preceded by "TOG_".
+ */
+
+/* Compiler-specific definitions of SBIT, SFR, SFRX, ... macros */
+#include <mcs51/compiler.h>
+
+/* Bit vectors */
+#define bmBit0      0x01
+#define bmBit1      0x02
+#define bmBit2      0x04
+#define bmBit3      0x08
+#define bmBit4      0x10
+#define bmBit5      0x20
+#define bmBit6      0x40
+#define bmBit7      0x80
+
+/***************************************************************************/
+/************************ Special Function Registers ***********************/
+/***************************************************************************/
+
+/* See EZ-USB TRM, pp. A-9 - A-10 */
+
+SFR(SP,             0x81);
+SFR(DPL0,           0x82);
+SFR(DPH0,           0x83);
+SFR(DPL1,           0x84);
+SFR(DPL2,           0x85);
+
+SFR(DPS,            0x86);
+  #define SEL       bmBit0
+  // Bit 1 read-only, always reads '0'
+  // Bit 2 read-only, always reads '0'
+  // Bit 3 read-only, always reads '0'
+  // Bit 4 read-only, always reads '0'
+  // Bit 5 read-only, always reads '0'
+  // Bit 6 read-only, always reads '0'
+  // Bit 7 read-only, always reads '0'
+
+SFR(PCON,           0x87);
+  #define IDLE      bmBit0
+  #define STOP      bmBit1
+  #define GF0       bmBit2
+  #define GF1       bmBit3
+  // Bit 4 read-only, always reads '1'
+  // Bit 5 read-only, always reads '1'
+  // Bit 6 unused
+  #define SMOD0     bmBit7
+
+SFR(TCON,           0x88);
+  SBIT(IT0,         0x88, 0);
+  SBIT(IE0,         0x88, 1);
+  SBIT(IT1,         0x88, 2);
+  SBIT(IE1,         0x88, 3);
+  SBIT(TR0,         0x88, 4);
+  SBIT(TF0,         0x88, 5);
+  SBIT(TR1,         0x88, 6);
+  SBIT(TF1,         0x88, 7);
+
+SFR(TMOD,           0x89);
+/* Some bits in this register share the same name in the EZ-USB TRM. Therefore,
+ * we add a '0'/'1' to distinguish them */
+  #define M00       bmBit0
+  #define M01       bmBit1
+  #define CT0       bmBit2
+  #define GATE0     bmBit3
+  #define M10       bmBit4
+  #define M11       bmBit5
+  #define CT1       bmBit6
+  #define GATE1     bmBit7
+
+SFR(TL0,            0x8A);
+SFR(TL1,            0x8B);
+SFR(TH0,            0x8C);
+SFR(TH1,            0x8D);
+
+SFR(CKCON,          0x8E);
+  #define MD0       bmBit0
+  #define MD1       bmBit1
+  #define MD2       bmBit2
+  #define T0M       bmBit3
+  #define T1M       bmBit4
+  #define T2M       bmBit5
+  // Bit 6 unused
+  // Bit 7 unused
+
+SFR(SPC_FNC,        0x8D);
+  #define bmWRS     bmBit0
+  // Bit 1 read-only, always reads '0'
+  // Bit 2 read-only, always reads '0'
+  // Bit 3 read-only, always reads '0'
+  // Bit 4 read-only, always reads '0'
+  // Bit 5 read-only, always reads '0'
+  // Bit 6 read-only, always reads '0'
+  // Bit 7 read-only, always reads '0'
+
+SFR(EXIF,           0x91);
+  // Bit 0 read-only, always reads '0'
+  // Bit 1 read-only, always reads '0'
+  // Bit 2 read-only, always reads '0'
+  // Bit 3 read-only, always reads '1'
+  #define USBINT    bmBit4
+  #define I2CINT    bmBit5
+  #define IE4       bmBit6
+  #define IE5       bmBit7
+
+/* Definition of the _XPAGE register, according to SDCC Compiler User Guide,
+ * Version 3.0.1, Chapter 4, p. 61. Also see EZ-USB TRM, p. 2-4. */
+SFR(MPAGE,          0x92);
+SFR(_XPAGE,         0x92);
+
+SFR(SCON0,          0x98);
+  SBIT(RI_0,        0x98, 0);
+  SBIT(TI_0,        0x98, 1);
+  SBIT(RB8_0,       0x98, 2);
+  SBIT(TB8_0,       0x98, 3);
+  SBIT(REN_0,       0x98, 4);
+  SBIT(SM2_0,       0x98, 5);
+  SBIT(SM1_0,       0x98, 6);
+  SBIT(SM0_0,       0x98, 7);
+
+SFR(SBUF0,          0x99);
+
+SFR(IE,             0xA8);
+  SBIT(EX0,         0xA8, 0);
+  SBIT(ET0,         0xA8, 1);
+  SBIT(EX1,         0xA8, 2);
+  SBIT(ET1,         0xA8, 3);
+  SBIT(ES0,         0xA8, 4);
+  SBIT(ET2,         0xA8, 5);
+  SBIT(ES1,         0xA8, 6);
+  SBIT(EA,          0xA8, 7);
+
+SFR(IP,             0xB8);
+  SBIT(PX0,         0xB8, 0);
+  SBIT(PT0,         0xB8, 1);
+  SBIT(PX1,         0xB8, 2);
+  SBIT(PT1,         0xB8, 3);
+  SBIT(PS0,         0xB8, 4);
+  SBIT(PT2,         0xB8, 5);
+  SBIT(PS1,         0xB8, 6);
+  // Bit 7 read-only, always reads '1'
+
+SFR(SCON1,          0xC0);
+  SBIT(RI_1,        0xC0, 0);
+  SBIT(TI_1,        0xC0, 1);
+  SBIT(RB8_1,       0xC0, 2);
+  SBIT(TB8_1,       0xC0, 3);
+  SBIT(REN_1,       0xC0, 4);
+  SBIT(SM2_1,       0xC0, 5);
+  SBIT(SM1_1,       0xC0, 6);
+  SBIT(SM0_1,       0xC0, 7);
+
+SFR(SBUF1,          0xC1);
+
+SFR(T2CON,          0xC8);
+  SBIT(CPRL2,       0xC8, 0);
+  SBIT(CT2,         0xC8, 1);
+  SBIT(TR2,         0xC8, 2);
+  SBIT(EXEN2,       0xC8, 3);
+  SBIT(TCLK,        0xC8, 4);
+  SBIT(RCLK,        0xC8, 5);
+  SBIT(EXF2,        0xC8, 6);
+  SBIT(TF2,         0xC8, 7);
+
+SFR(RCAP2L,         0xCA);
+SFR(RCAP2H,         0xCB);
+SFR(TL2,            0xCC);
+SFR(TH2,            0xCD);
+
+SFR(PSW,            0xD0);
+  SBIT(P,           0xD0, 0);
+  SBIT(F1,          0xD0, 1);
+  SBIT(OV,          0xD0, 2);
+  SBIT(RS0,         0xD0, 3);
+  SBIT(RS1,         0xD0, 4);
+  SBIT(F0,          0xD0, 5);
+  SBIT(AC,          0xD0, 6);
+  SBIT(CY,          0xD0, 7);
+
+SFR(EICON,          0xD8);
+  // Bit 0 read-only, always reads '0'
+  // Bit 1 read-only, always reads '0'
+  // Bit 2 read-only, always reads '0'
+  SBIT(INT6,        0xD8, 3);
+  SBIT(RESI,        0xD8, 4);
+  SBIT(ERESI,       0xD8, 5);
+  // Bit 6 read-only, always reads '1'
+  SBIT(SMOD1,       0xD8, 7);
+
+SFR(ACC,            0xE0);
+
+SFR(EIE,            0xE8);
+  SBIT(EUSB,        0xE8, 0);
+  SBIT(EI2C,        0xE8, 1);
+  SBIT(EX4,         0xE8, 2);
+  SBIT(EX5,         0xE8, 3);
+  SBIT(EWDI,        0xE8, 4);
+  // Bit 5 read-only, always reads '1'
+  // Bit 6 read-only, always reads '1'
+  // Bit 7 read-only, always reads '1'
+
+SFR(B,              0xF0);
+
+SFR(EIP,            0xF8);
+  SBIT(PUSB,        0xF8, 0);
+  SBIT(PI2C,        0xF8, 1);
+  SBIT(PX4,         0xF8, 2);
+  SBIT(PX5,         0xF8, 3);
+  SBIT(PX6,         0xF8, 4);
+  // Bit 5 read-only, always reads '1'
+  // Bit 6 read-only, always reads '1'
+  // Bit 7 read-only, always reads '1'
+
+/***************************************************************************/
+/***************************** XDATA Registers *****************************/
+/***************************************************************************/
+
+/************************ Endpoint 0-7 Data Buffers ************************/
+SFRX(OUT7BUF[64],   0x7B40);
+SFRX(IN7BUF[64],    0x7B80);
+SFRX(OUT6BUF[64],   0x7BC0);
+SFRX(IN6BUF[64],    0x7C00);
+SFRX(OUT5BUF[64],   0x7C40);
+SFRX(IN5BUF[64],    0x7C80);
+SFRX(OUT4BUF[64],   0x7CC0);
+SFRX(IN4BUF[64],    0x7D00);
+SFRX(OUT3BUF[64],   0x7D40);
+SFRX(IN3BUF[64],    0x7D80);
+SFRX(OUT2BUF[64],   0x7DC0);
+SFRX(IN2BUF[64],    0x7E00);
+SFRX(OUT1BUF[64],   0x7E40);
+SFRX(IN1BUF[64],    0x7E80);
+SFRX(OUT0BUF[64],   0x7EC0);
+SFRX(IN0BUF[64],    0x7F00);
+// 0x7F40 - 0x7F5F reserved
+
+/**************************** Isochronous Data *****************************/
+SFRX(OUT8DATA,      0x7F60);
+SFRX(OUT9DATA,      0x7F61);
+SFRX(OUT10DATA,     0x7F62);
+SFRX(OUT11DATA,     0x7F63);
+SFRX(OUT12DATA,     0x7F64);
+SFRX(OUT13DATA,     0x7F65);
+SFRX(OUT14DATA,     0x7F66);
+SFRX(OUT15DATA,     0x7F67);
+
+SFRX(IN8DATA,       0x7F68);
+SFRX(IN9DATA,       0x7F69);
+SFRX(IN10DATA,      0x7F6A);
+SFRX(IN11DATA,      0x7F6B);
+SFRX(IN12DATA,      0x7F6C);
+SFRX(IN13DATA,      0x7F6D);
+SFRX(IN14DATA,      0x7F6E);
+SFRX(IN15DATA,      0x7F6F);
+
+/************************* Isochronous Byte Counts *************************/
+SFRX(OUT8BCH,       0x7F70);
+SFRX(OUT8BCL,       0x7F71);
+SFRX(OUT9BCH,       0x7F72);
+SFRX(OUT9BCL,       0x7F73);
+SFRX(OUT10BCH,      0x7F74);
+SFRX(OUT10BCL,      0x7F75);
+SFRX(OUT11BCH,      0x7F76);
+SFRX(OUT11BCL,      0x7F77);
+SFRX(OUT12BCH,      0x7F78);
+SFRX(OUT12BCL,      0x7F79);
+SFRX(OUT13BCH,      0x7F7A);
+SFRX(OUT13BCL,      0x7F7B);
+SFRX(OUT14BCH,      0x7F7C);
+SFRX(OUT14BCL,      0x7F7D);
+SFRX(OUT15BCH,      0x7F7E);
+SFRX(OUT16BCL,      0x7F7F);
+
+/****************************** CPU Registers ******************************/
+SFRX(CPUCS,         0x7F92);
+  #define RES8051   bmBit0
+  #define CLK24OE   bmBit1
+  // Bit 2 read-only, always reads '0'
+  // Bit 3 read-only, always reads '0'
+  // Bits 4...7: Chip Revision
+
+SFRX(PORTACFG,      0x7F93);
+  #define T0OUT     bmBit0
+  #define T1OUT     bmBit1
+  #define OE        bmBit2
+  #define CS        bmBit3
+  #define FWR       bmBit4
+  #define FRD       bmBit5
+  #define RXD0OUT   bmBit6
+  #define RXD1OUT   bmBit7
+
+SFRX(PORTBCFG,      0x7F94);
+  #define T2        bmBit0
+  #define T2EX      bmBit1
+  #define RXD1      bmBit2
+  #define TXD1      bmBit3
+  #define INT4      bmBit4
+  #define INT5      bmBit5
+  #define INT6      bmBit6
+  #define T2OUT     bmBit7
+
+SFRX(PORTCCFG,      0x7F95);
+  #define RXD0      bmBit0
+  #define TXD0      bmBit1
+  #define INT0      bmBit2
+  #define INT1      bmBit3
+  #define T0        bmBit4
+  #define T1        bmBit5
+  #define WR        bmBit6
+  #define RD        bmBit7
+
+/*********************** Input-Output Port Registers ***********************/
+SFRX(OUTA,          0x7F96);
+  #define OUTA0     bmBit0
+  #define OUTA1     bmBit1
+  #define OUTA2     bmBit2
+  #define OUTA3     bmBit3
+  #define OUTA4     bmBit4
+  #define OUTA5     bmBit5
+  #define OUTA6     bmBit6
+  #define OUTA7     bmBit7
+
+SFRX(OUTB,          0x7F97);
+  #define OUTB0     bmBit0
+  #define OUTB1     bmBit1
+  #define OUTB2     bmBit2
+  #define OUTB3     bmBit3
+  #define OUTB4     bmBit4
+  #define OUTB5     bmBit5
+  #define OUTB6     bmBit6
+  #define OUTB7     bmBit7
+
+SFRX(OUTC,          0x7F98);
+  #define OUTC0     bmBit0
+  #define OUTC1     bmBit1
+  #define OUTC2     bmBit2
+  #define OUTC3     bmBit3
+  #define OUTC4     bmBit4
+  #define OUTC5     bmBit5
+  #define OUTC6     bmBit6
+  #define OUTC7     bmBit7
+
+SFRX(PINSA,         0x7F99);
+  #define PINA0     bmBit0
+  #define PINA1     bmBit1
+  #define PINA2     bmBit2
+  #define PINA3     bmBit3
+  #define PINA4     bmBit4
+  #define PINA5     bmBit5
+  #define PINA6     bmBit6
+  #define PINA7     bmBit7
+
+SFRX(PINSB,         0x7F9A);
+  #define PINB0     bmBit0
+  #define PINB1     bmBit1
+  #define PINB2     bmBit2
+  #define PINB3     bmBit3
+  #define PINB4     bmBit4
+  #define PINB5     bmBit5
+  #define PINB6     bmBit6
+  #define PINB7     bmBit7
+
+SFRX(PINSC,         0x7F9B);
+  #define PINC0     bmBit0
+  #define PINC1     bmBit1
+  #define PINC2     bmBit2
+  #define PINC3     bmBit3
+  #define PINC4     bmBit4
+  #define PINC5     bmBit5
+  #define PINC6     bmBit6
+  #define PINC7     bmBit7
+
+SFRX(OEA,           0x7F9C);
+  #define OEA0      bmBit0
+  #define OEA1      bmBit1
+  #define OEA2      bmBit2
+  #define OEA3      bmBit3
+  #define OEA4      bmBit4
+  #define OEA5      bmBit5
+  #define OEA6      bmBit6
+  #define OEA7      bmBit7
+
+SFRX(OEB,           0x7F9D);
+  #define OEB0      bmBit0
+  #define OEB1      bmBit1
+  #define OEB2      bmBit2
+  #define OEB3      bmBit3
+  #define OEB4      bmBit4
+  #define OEB5      bmBit5
+  #define OEB6      bmBit6
+  #define OEB7      bmBit7
+
+SFRX(OEC,           0x7F9E);
+  #define OEC0      bmBit0
+  #define OEC1      bmBit1
+  #define OEC2      bmBit2
+  #define OEC3      bmBit3
+  #define OEC4      bmBit4
+  #define OEC5      bmBit5
+  #define OEC6      bmBit6
+  #define OEC7      bmBit7
+
+// 0x7F9F reserved
+
+/****************** Isochronous Control/Status Registers *******************/
+SFRX(ISOERR,        0x7FA0);
+  #define ISO8ERR   bmBit0
+  #define ISO9ERR   bmBit1
+  #define ISO10ERR  bmBit2
+  #define ISO11ERR  bmBit3
+  #define ISO12ERR  bmBit4
+  #define ISO13ERR  bmBit5
+  #define ISO14ERR  bmBit6
+  #define ISO15ERR  bmBit7
+
+SFRX(ISOCTL,        0x7FA1);
+  #define ISODISAB  bmBit0
+  #define MBZ0      bmBit1
+  #define MBZ1      bmBit2
+  #define PPSTAT    bmBit3
+  // Bit 4 unused
+  // Bit 5 unused
+  // Bit 6 unused
+  // Bit 7 unused
+
+SFRX(ZBCOUT,        0x7FA2);
+  #define EP8       bmBit0
+  #define EP9       bmBit1
+  #define EP10      bmBit2
+  #define EP11      bmBit3
+  #define EP12      bmBit4
+  #define EP13      bmBit5
+  #define EP14      bmBit6
+  #define EP15      bmBit7
+
+// 0x7FA3 reserved
+// 0x7FA4 reserved
+
+/****************************** I2C Registers ******************************/
+SFRX(I2CS,          0x7FA5);
+  #define DONE      bmBit0
+  #define ACK       bmBit1
+  #define BERR      bmBit2
+  #define ID0       bmBit3
+  #define ID1       bmBit4
+  #define LASTRD    bmBit5
+  #define I2C_STOP  bmBit6
+  #define I2C_START bmBit7
+
+SFRX(I2DAT,         0x7FA6);
+// 0x7FA7 reserved
+
+/******************************* Interrupts ********************************/
+SFRX(IVEC,          0x7FA8);
+  // Bit 0 read-only, always reads '0'
+  // Bit 1 read-only, always reads '0'
+  #define IV0       bmBit2
+  #define IV1       bmBit3
+  #define IV2       bmBit4
+  #define IV3       bmBit5
+  #define IV4       bmBit6
+  // Bit 7 read-only, always reads '0'
+
+SFRX(IN07IRQ,       0x7FA9);
+  #define IN0IR     bmBit0
+  #define IN1IR     bmBit1
+  #define IN2IR     bmBit2
+  #define IN3IR     bmBit3
+  #define IN4IR     bmBit4
+  #define IN5IR     bmBit5
+  #define IN6IR     bmBit6
+  #define IN7IR     bmBit7
+
+SFRX(OUT07IRQ,      0x7FAA);
+  #define OUT0IR    bmBit0
+  #define OUT1IR    bmBit1
+  #define OUT2IR    bmBit2
+  #define OUT3IR    bmBit3
+  #define OUT4IR    bmBit4
+  #define OUT5IR    bmBit5
+  #define OUT6IR    bmBit6
+  #define OUT7IR    bmBit7
+
+SFRX(USBIRQ,        0x7FAB);
+  #define SUDAVIR   bmBit0
+  #define SOFIR     bmBit1
+  #define SUTOKIR   bmBit2
+  #define SUSPIR    bmBit3
+  #define URESIR    bmBit4
+  // Bit 5 unused
+  // Bit 6 unused
+  // Bit 7 unused
+
+SFRX(IN07IEN,       0x7FAC);
+  #define IN0IEN    bmBit0
+  #define IN1IEN    bmBit1
+  #define IN2IEN    bmBit2
+  #define IN3IEN    bmBit3
+  #define IN4IEN    bmBit4
+  #define IN5IEN    bmBit5
+  #define IN6IEN    bmBit6
+  #define IN7IEN    bmBit7
+
+SFRX(OUT07IEN,      0x7FAD);
+  #define OUT0IEN   bmBit0
+  #define OUT1IEN   bmBit1
+  #define OUT2IEN   bmBit2
+  #define OUT3IEN   bmBit3
+  #define OUT4IEN   bmBit4
+  #define OUT5IEN   bmBit5
+  #define OUT6IEN   bmBit6
+  #define OUT7IEN   bmBit7
+
+SFRX(USBIEN,        0x7FAE);
+  #define SUDAVIE   bmBit0
+  #define SOFIE     bmBit1
+  #define SUTOKIE   bmBit2
+  #define SUSPIE    bmBit3
+  #define URESIE    bmBit4
+  // Bit 5 unused
+  // Bit 6 unused
+  // Bit 7 unused
+
+SFRX(USBBAV,        0x7FAF);
+  #define AVEN      bmBit0
+  #define BPEN      bmBit1
+  #define BPPULSE   bmBit2
+  #define BREAK     bmBit3
+  // Bit 4 unused
+  // Bit 5 unused
+  // Bit 6 unused
+  // Bit 7 unused
+
+// 0x7FB0 reserved
+// 0x7FB1 reserved
+SFRX(BPADDRH,       0x7FB2);
+SFRX(BPADDRL,       0x7FB3);
+
+/****************************** Endpoints 0-7 ******************************/
+SFRX(EP0CS,         0x7FB4);
+  #define EP0STALL  bmBit0
+  #define HSNAK     bmBit1
+  #define IN0BSY    bmBit2
+  #define OUT0BSY   bmBit3
+  // Bit 4 unused
+  // Bit 5 unused
+  // Bit 6 unused
+  // Bit 7 unused
+
+SFRX(IN0BC,         0x7FB5);
+SFRX(IN1CS,         0x7FB6);
+SFRX(IN1BC,         0x7FB7);
+SFRX(IN2CS,         0x7FB8);
+SFRX(IN2BC,         0x7FB9);
+SFRX(IN3CS,         0x7FBA);
+SFRX(IN3BC,         0x7FBB);
+SFRX(IN4CS,         0x7FBC);
+SFRX(IN4BC,         0x7FBD);
+SFRX(IN5CS,         0x7FBE);
+SFRX(IN5BC,         0x7FBF);
+SFRX(IN6CS,         0x7FC0);
+SFRX(IN6BC,         0x7FC1);
+SFRX(IN7CS,         0x7FC2);
+SFRX(IN7BC,         0x7FC3);
+// 0x7FC4 reserved
+SFRX(OUT0BC,        0x7FC5);
+SFRX(OUT1CS,        0x7FC6);
+SFRX(OUT1BC,        0x7FC7);
+SFRX(OUT2CS,        0x7FC8);
+SFRX(OUT2BC,        0x7FC9);
+SFRX(OUT3CS,        0x7FCA);
+SFRX(OUT3BC,        0x7FCB);
+SFRX(OUT4CS,        0x7FCC);
+SFRX(OUT4BC,        0x7FCD);
+SFRX(OUT5CS,        0x7FCE);
+SFRX(OUT5BC,        0x7FCF);
+SFRX(OUT6CS,        0x7FD0);
+SFRX(OUT6BC,        0x7FD1);
+SFRX(OUT7CS,        0x7FD2);
+SFRX(OUT7BC,        0x7FD3);
+
+/* The INxSTALL, OUTxSTALL, INxBSY and OUTxBSY bits are the same for all
+ * INxCS/OUTxCS registers. For better readability, we define them only once */
+#define EPSTALL     bmBit0
+#define EPBSY       bmBit1
+
+/************************** Global USB Registers ***************************/
+SFRX(SUDPTRH,       0x7FD4);
+SFRX(SUDPTRL,       0x7FD5);
+
+SFRX(USBCS,         0x7FD6);
+  #define SIGRSUME  bmBit0
+  #define RENUM     bmBit1
+  #define DISCOE    bmBit2
+  #define DISCON    bmBit3
+  // Bit 4 unused
+  // Bit 5 unused
+  // Bit 6 unused
+  #define WAKESRC   bmBit7
+
+SFRX(TOGCTL,        0x7FD7);
+  #define TOG_EP0   bmBit0
+  #define TOG_EP1   bmBit1
+  #define TOG_EP2   bmBit2
+  // Bit 3 is read-only, always reads '0'
+  #define TOG_IO    bmBit4
+  #define TOG_R     bmBit5
+  #define TOG_S     bmBit6
+  #define TOG_Q     bmBit7
+
+SFRX(USBFRAMEL,     0x7FD8);
+SFRX(USBFRAMEH,     0x7FD9);
+// 0x7FDA reserved
+SFRX(FNADDR,        0x7FDB);
+// 0x7FDC reserved
+
+SFRX(USBPAIR,       0x7FDD);
+  #define PR2IN     bmBit0
+  #define PR4IN     bmBit1
+  #define PR6IN     bmBit2
+  #define PR2OUT    bmBit3
+  #define PR4OUT    bmBit4
+  #define PR6OUT    bmBit5
+  // Bit 6 unused
+  #define ISOSEND0  bmBit7
+
+SFRX(IN07VAL,       0x7FDE);
+  // Bit 0 is read-only, always reads '1'
+  #define IN1VAL    bmBit1
+  #define IN2VAL    bmBit2
+  #define IN3VAL    bmBit3
+  #define IN4VAL    bmBit4
+  #define IN5VAL    bmBit5
+  #define IN6VAL    bmBit6
+  #define IN7VAL    bmBit7
+
+SFRX(OUT07VAL,      0x7FDF);
+  // Bit 0 is read-only, always reads '1'
+  #define OUT1VAL   bmBit1
+  #define OUT2VAL   bmBit2
+  #define OUT3VAL   bmBit3
+  #define OUT4VAL   bmBit4
+  #define OUT5VAL   bmBit5
+  #define OUT6VAL   bmBit6
+  #define OUT7VAL   bmBit7
+
+SFRX(INISOVAL,      0x7FE0);
+  #define IN8VAL    bmBit0
+  #define IN9VAL    bmBit1
+  #define IN10VAL   bmBit2
+  #define IN11VAL   bmBit3
+  #define IN12VAL   bmBit4
+  #define IN13VAL   bmBit5
+  #define IN14VAL   bmBit6
+  #define IN15VAL   bmBit7
+
+SFRX(OUTISOVAL,     0x7FE1);
+  #define OUT8VAL   bmBit0
+  #define OUT9VAL   bmBit1
+  #define OUT10VAL  bmBit2
+  #define OUT11VAL  bmBit3
+  #define OUT12VAL  bmBit4
+  #define OUT13VAL  bmBit5
+  #define OUT14VAL  bmBit6
+  #define OUT15VAL  bmBit7
+
+SFRX(FASTXFR,       0x7FE2);
+  #define WMOD0     bmBit0
+  #define WMOD1     bmBit1
+  #define WPOL      bmBit2
+  #define RMOD0     bmBit3
+  #define RMOD1     bmBit4
+  #define RPOL      bmBit5
+  #define FBLK      bmBit6
+  #define FISO      bmBit7
+
+SFRX(AUTOPTRH,      0x7FE3);
+SFRX(AUTOPTRL,      0x7FE4);
+SFRX(AUTODATA,      0x7FE5);
+// 0x7FE6 reserved
+// 0x7FE7 reserved
+
+/******************************* Setup Data ********************************/
+SFRX(SETUPDAT[8],   0x7FE8);
+
+/************************* Isochronous FIFO sizes **************************/
+SFRX(OUT8ADDR,      0x7FF0);
+SFRX(OUT9ADDR,      0x7FF1);
+SFRX(OUT10ADDR,     0x7FF2);
+SFRX(OUT11ADDR,     0x7FF3);
+SFRX(OUT12ADDR,     0x7FF4);
+SFRX(OUT13ADDR,     0x7FF5);
+SFRX(OUT14ADDR,     0x7FF6);
+SFRX(OUT15ADDR,     0x7FF7);
+
+SFRX(IN8ADDR,       0x7FF8);
+SFRX(IN9ADDR,       0x7FF9);
+SFRX(IN10ADDR,      0x7FFA);
+SFRX(IN11ADDR,      0x7FFB);
+SFRX(IN12ADDR,      0x7FFC);
+SFRX(IN13ADDR,      0x7FFD);
+SFRX(IN14ADDR,      0x7FFE);
+SFRX(IN15ADDR,      0x7FFF);
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/shorttypes.h b/src/jtag/drivers/OpenULINK/include/shorttypes.h
new file mode 100644 (file)
index 0000000..60b37df
--- /dev/null
@@ -0,0 +1,41 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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 __SHORTTYPES_H
+#define __SHORTTYPES_H
+
+#include <stdint.h>
+
+/**
+ * @file Integer type definitions for shorter code (easier to stay within 80
+ * character maximum line length).
+ */
+
+/* Signed integers */
+typedef int8_t   s8;
+typedef int16_t  s16;
+typedef int32_t  s32;
+
+/* Unsigned integers */
+typedef uint8_t  u8;
+typedef uint16_t u16;
+typedef uint32_t u32;
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/include/usb.h b/src/jtag/drivers/OpenULINK/include/usb.h
new file mode 100644 (file)
index 0000000..f70819e
--- /dev/null
@@ -0,0 +1,267 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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 __USB_H
+#define __USB_H
+
+#include "shorttypes.h"
+#include "reg_ezusb.h"
+
+#include <stdbool.h>
+
+#define NULL        (void*)0;
+
+/* High and Low byte of a word (u16) */
+#define HI8(word)   (u8)(((u16)word >> 8) & 0xff)
+#define LO8(word)   (u8)((u16)word & 0xff)
+
+/* Convenience functions */
+#define STALL_EP0()   EP0CS |= EP0STALL
+#define CLEAR_IRQ()   EXIF &= ~USBINT
+
+/*********** USB descriptors. See section 9.5 of the USB 1.1 spec **********/
+
+/* USB Descriptor Types. See USB 1.1 spec, page 187, table 9-5 */
+#define DESCRIPTOR_TYPE_DEVICE         0x01
+#define DESCRIPTOR_TYPE_CONFIGURATION  0x02
+#define DESCRIPTOR_TYPE_STRING         0x03
+#define DESCRIPTOR_TYPE_INTERFACE      0x04
+#define DESCRIPTOR_TYPE_ENDPOINT       0x05
+
+#define STR_DESCR(len,...) { len*2+2, DESCRIPTOR_TYPE_STRING, { __VA_ARGS__ } }
+
+/** USB Device Descriptor. See USB 1.1 spec, pp. 196 - 198 */
+typedef struct {
+  u8  bLength;             ///< Size of this descriptor in bytes.
+  u8  bDescriptorType;     ///< DEVICE Descriptor Type.
+  u16 bcdUSB;              ///< USB specification release number (BCD).
+  u8  bDeviceClass;        ///< Class code.
+  u8  bDeviceSubClass;     ///< Subclass code.
+  u8  bDeviceProtocol;     ///< Protocol code.
+  u8  bMaxPacketSize0;     ///< Maximum packet size for EP0 (8, 16, 32, 64).
+  u16 idVendor;            ///< USB Vendor ID.
+  u16 idProduct;           ///< USB Product ID.
+  u16 bcdDevice;           ///< Device Release Number (BCD).
+  u8  iManufacturer;       ///< Index of manufacturer string descriptor.
+  u8  iProduct;            ///< Index of product string descriptor.
+  u8  iSerialNumber;       ///< Index of string descriptor containing serial #.
+  u8  bNumConfigurations;  ///< Number of possible configurations.
+} usb_device_descriptor_t;
+
+/** USB Configuration Descriptor. See USB 1.1 spec, pp. 199 - 200 */
+typedef struct {
+  u8  bLength;             ///< Size of this descriptor in bytes.
+  u8  bDescriptorType;     ///< CONFIGURATION descriptor type.
+  u16 wTotalLength;        ///< Combined total length of all descriptors.
+  u8  bNumInterfaces;      ///< Number of interfaces in this configuration.
+  u8  bConfigurationValue; ///< Value used to select this configuration.
+  u8  iConfiguration;      ///< Index of configuration string descriptor.
+  u8  bmAttributes;        ///< Configuration characteristics.
+  u8  MaxPower;            ///< Maximum power consumption in 2 mA units.
+} usb_config_descriptor_t;
+
+/** USB Interface Descriptor. See USB 1.1 spec, pp. 201 - 203 */
+typedef struct {
+  u8  bLength;             ///< Size of this descriptor in bytes.
+  u8  bDescriptorType;     ///< INTERFACE descriptor type.
+  u8  bInterfaceNumber;    ///< Interface number.
+  u8  bAlternateSetting;   ///< Value used to select alternate setting.
+  u8  bNumEndpoints;       ///< Number of endpoints used by this interface.
+  u8  bInterfaceClass;     ///< Class code.
+  u8  bInterfaceSubclass;  ///< Subclass code.
+  u8  bInterfaceProtocol;  ///< Protocol code.
+  u8  iInterface;          ///< Index of interface string descriptor.
+} usb_interface_descriptor_t;
+
+/** USB Endpoint Descriptor. See USB 1.1 spec, pp. 203 - 204 */
+typedef struct {
+  u8  bLength;             ///< Size of this descriptor in bytes.
+  u8  bDescriptorType;     ///< ENDPOINT descriptor type.
+  u8  bEndpointAddress;    ///< Endpoint Address: USB 1.1 spec, table 9-10.
+  u8  bmAttributes;        ///< Endpoint Attributes: USB 1.1 spec, table 9-10.
+  u16 wMaxPacketSize;      ///< Maximum packet size for this endpoint.
+  u8  bInterval;           ///< Polling interval (in ms) for this endpoint.
+} usb_endpoint_descriptor_t;
+
+/** USB Language Descriptor. See USB 1.1 spec, pp. 204 - 205 */
+typedef struct {
+  u8  bLength;             ///< Size of this descriptor in bytes.
+  u8  bDescriptorType;     ///< STRING descriptor type.
+  u16 wLANGID[];           ///< LANGID codes.
+} usb_language_descriptor_t;
+
+/** USB String Descriptor. See USB 1.1 spec, pp. 204 - 205 */
+typedef struct {
+  u8  bLength;             ///< Size of this descriptor in bytes.
+  u8  bDescriptorType;     ///< STRING descriptor type.
+  u16 bString[];           ///< UNICODE encoded string.
+} usb_string_descriptor_t;
+
+/********************** USB Control Endpoint 0 related *********************/
+
+/** USB Control Setup Data. See USB 1.1 spec, pp. 183 - 185 */
+typedef struct {
+  u8  bmRequestType;       ///< Characteristics of a request.
+  u8  bRequest;            ///< Specific request.
+  u16 wValue;              ///< Field that varies according to request.
+  u16 wIndex;              ///< Field that varies according to request.
+  u16 wLength;             ///< Number of bytes to transfer in data stage.
+} setup_data_t;
+
+/* External declarations for variables that need to be accessed outside of
+ * the USB module */
+extern volatile bool EP2_out;
+extern volatile bool EP2_in;
+extern volatile __xdata __at 0x7FE8 setup_data_t setup_data;
+
+/*
+ * USB Request Types (bmRequestType): See USB 1.1 spec, page 183, table 9-2
+ *
+ * Bit 7: Data transfer direction
+ *    0 = Host-to-device
+ *    1 = Device-to-host
+ * Bit 6...5: Type
+ *    0 = Standard
+ *    1 = Class
+ *    2 = Vendor
+ *    3 = Reserved
+ * Bit 4...0: Recipient
+ *    0 = Device
+ *    1 = Interface
+ *    2 = Endpoint
+ *    3 = Other
+ *    4...31 = Reserved
+ */
+
+#define USB_DIR_OUT             0x00
+#define USB_DIR_IN              0x80
+
+#define USB_REQ_TYPE_STANDARD   (0x00 << 5)
+#define USB_REQ_TYPE_CLASS      (0x01 << 5)
+#define USB_REQ_TYPE_VENDOR     (0x02 << 5)
+#define USB_REQ_TYPE_RESERVED   (0x03 << 5)
+
+#define USB_RECIP_DEVICE        0x00
+#define USB_RECIP_INTERFACE     0x01
+#define USB_RECIP_ENDPOINT      0x02
+#define USB_RECIP_OTHER         0x03
+
+/* bmRequestType for USB Standard Requests */
+
+/* Clear Interface Request */
+#define CF_DEVICE    (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+#define CF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+#define CF_ENDPOINT  (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+
+/* Get Configuration Request */
+#define GC_DEVICE    (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+
+/* Get Descriptor Request */
+#define GD_DEVICE    (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+
+/* Get Interface Request */
+#define GI_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+
+/* Get Status Request: See USB 1.1 spec, page 190 */
+#define GS_DEVICE    (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+#define GS_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+#define GS_ENDPOINT  (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+
+/* Set Address Request is handled by EZ-USB core */
+
+/* Set Configuration Request */
+#define SC_DEVICE    (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+
+/* Set Descriptor Request */
+#define SD_DEVICE    (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+
+/* Set Feature Request */
+#define SF_DEVICE    (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE)
+#define SF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+#define SF_ENDPOINT  (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+
+/* Set Interface Request */
+#define SI_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE)
+
+/* Synch Frame Request */
+#define SY_ENDPOINT  (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT)
+
+/* USB Requests (bRequest): See USB 1.1 spec, table 9-4 on page 187 */
+#define GET_STATUS               0
+#define CLEAR_FEATURE            1
+// Value '2' is reserved for future use
+#define SET_FEATURE              3
+// Value '4' is reserved for future use
+#define SET_ADDRESS              5
+#define GET_DESCRIPTOR           6
+#define SET_DESCRIPTOR           7
+#define GET_CONFIGURATION        8
+#define SET_CONFIGURATION        9
+#define GET_INTERFACE           10
+#define SET_INTERFACE           11
+#define SYNCH_FRAME             12
+
+/* Standard Feature Selectors: See USB 1.1 spec, table 9-6 on page 188 */
+#define DEVICE_REMOTE_WAKEUP     1
+#define ENDPOINT_HALT            0
+
+/************************** EZ-USB specific stuff **************************/
+
+/** USB Interrupts. See AN2131-TRM, page 9-4 for details */
+typedef enum {
+  SUDAV_ISR = 13,
+  SOF_ISR,
+  SUTOK_ISR,
+  SUSPEND_ISR,
+  USBRESET_ISR,
+  IBN_ISR,
+  EP0IN_ISR,
+  EP0OUT_ISR,
+  EP1IN_ISR,
+  EP1OUT_ISR,
+  EP2IN_ISR,
+  EP2OUT_ISR,
+  EP3IN_ISR,
+  EP3OUT_ISR,
+  EP4IN_ISR,
+  EP4OUT_ISR,
+  EP5IN_ISR,
+  EP5OUT_ISR,
+  EP6IN_ISR,
+  EP6OUT_ISR,
+  EP7IN_ISR,
+  EP7OUT_ISR
+} USB_ISR;
+
+/*************************** Function Prototypes ***************************/
+
+__xdata u8* usb_get_endpoint_cs_reg(u8 ep);
+void usb_reset_data_toggle(u8 ep);
+
+bool usb_handle_get_status(void);
+bool usb_handle_clear_feature(void);
+bool usb_handle_set_feature(void);
+bool usb_handle_get_descriptor(void);
+void usb_handle_set_interface(void);
+
+void usb_handle_setup_data(void);
+void usb_init(void);
+
+#endif
diff --git a/src/jtag/drivers/OpenULINK/src/USBJmpTb.a51 b/src/jtag/drivers/OpenULINK/src/USBJmpTb.a51
new file mode 100644 (file)
index 0000000..6f774dd
--- /dev/null
@@ -0,0 +1,83 @@
+;--------------------------------------------------------------------------;
+;    Copyright (C) 2011 by Martin Schmoelzer                               ;
+;    <martin.schmoelzer@student.tuwien.ac.at>                              ;
+;                                                                          ;
+;    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.             ;
+;--------------------------------------------------------------------------;
+
+.module JUMPTABLE
+.globl USB_AutoVector
+.globl USB_Jump_Table
+
+;--------------------------------------------------------------------------;
+; Interrupt Vectors                                                        ;
+;--------------------------------------------------------------------------;
+.area   USB_JV (ABS,OVR)   ; Absolute, Overlay
+.org    0x43               ; USB interrupt (INT2) jumps here
+USB_AutoVector = #. + 2
+    ljmp  USB_jump_table
+
+;--------------------------------------------------------------------------;
+; USB Jump Table                                                           ;
+;--------------------------------------------------------------------------;
+.area  USB_JT (ABS)        ; Absolute placement
+.org   0x1B00              ; Place jump table at 0x1B00
+
+USB_jump_table:            ; autovector jump table
+    ljmp  _sudav_isr       ; Setup Data Available
+    .db 0
+    ljmp  _sof_isr         ; Start of Frame
+    .db 0
+    ljmp  _sutok_isr       ; Setup Data Loading
+    .db 0
+    ljmp  _suspend_isr     ; Global Suspend
+    .db 0
+    ljmp  _usbreset_isr    ; USB Reset
+    .db 0
+    ljmp  _ibn_isr         ; IN Bulk NAK interrupt
+    .db 0
+    ljmp  _ep0in_isr       ; Endpoint 0 IN
+    .db 0
+    ljmp  _ep0out_isr      ; Endpoint 0 OUT
+    .db 0
+    ljmp  _ep1in_isr       ; Endpoint 1 IN
+    .db 0
+    ljmp  _ep1out_isr      ; Endpoint 1 OUT
+    .db 0
+    ljmp  _ep2in_isr       ; Endpoint 2 IN
+    .db 0
+    ljmp  _ep2out_isr      ; Endpoint 2 OUT
+    .db 0
+    ljmp  _ep3in_isr       ; Endpoint 3 IN
+    .db 0
+    ljmp  _ep3out_isr      ; Endpoint 3 OUT
+    .db 0
+    ljmp  _ep4in_isr       ; Endpoint 4 IN
+    .db 0
+    ljmp  _ep4out_isr      ; Endpoint 4 OUT
+    .db 0
+    ljmp  _ep5in_isr       ; Endpoint 5 IN
+    .db 0
+    ljmp  _ep5out_isr      ; Endpoint 5 OUT
+    .db 0
+    ljmp  _ep6in_isr       ; Endpoint 6 IN
+    .db 0
+    ljmp  _ep6out_isr      ; Endpoint 6 OUT
+    .db 0
+    ljmp  _ep7in_isr       ; Endpoint 7 IN
+    .db 0
+    ljmp  _ep7out_isr      ; Endpoint 7 OUT
+    .db 0
diff --git a/src/jtag/drivers/OpenULINK/src/delay.c b/src/jtag/drivers/OpenULINK/src/delay.c
new file mode 100644 (file)
index 0000000..5b7d0eb
--- /dev/null
@@ -0,0 +1,51 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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 "delay.h"
+
+void delay_5us(void)
+{
+  NOP;
+}
+
+void delay_1ms(void) {
+  u16 i;
+
+  for (i = 0; i < 598; i++);
+}
+
+void delay_us(u16 delay)
+{
+  u16 i;
+  u16 maxcount = (delay / 5);
+
+  for (i = 0; i < maxcount; i++) {
+    delay_5us();
+  }
+}
+
+void delay_ms(u16 delay)
+{
+  u16 i;
+
+  for (i = 0; i < delay; i++) {
+    delay_1ms();
+  }
+}
diff --git a/src/jtag/drivers/OpenULINK/src/jtag.c b/src/jtag/drivers/OpenULINK/src/jtag.c
new file mode 100644 (file)
index 0000000..cf126ed
--- /dev/null
@@ -0,0 +1,414 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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 "jtag.h"
+
+#include "io.h"
+#include "msgtypes.h"
+#include "common.h"
+
+#include <stdbool.h>
+
+/** Delay value for SCAN operations with less than maximum TCK frequency */
+u8 delay_scan = 0;
+
+/** Delay value for CLOCK_TCK operations */
+u8 delay_tck = 0;
+
+/** Delay value for CLOCK_TMS operations with less than maximum frequency */
+u8 delay_tms = 0;
+
+/**
+ * Perform JTAG SCAN-IN operation at maximum TCK frequency.
+ *
+ * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
+ * stored in the EP2 IN buffer.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_scan_in(u8 out_offset, u8 in_offset)
+{
+  u8 scan_size_bytes, bits_last_byte;
+  u8 tms_count_start, tms_count_end;
+  u8 tms_sequence_start, tms_sequence_end;
+  u8 tdo_data, i, j;
+
+  u8 outb_buffer;
+
+  /* Get parameters from OUT2BUF */
+  scan_size_bytes = OUT2BUF[out_offset];
+  bits_last_byte = OUT2BUF[out_offset + 1];
+  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+  tms_sequence_start = OUT2BUF[out_offset + 3];
+  tms_sequence_end = OUT2BUF[out_offset + 4];
+
+  if (tms_count_start > 0) {
+    jtag_clock_tms(tms_count_start, tms_sequence_start);
+  }
+
+  outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS);
+
+  /* Shift all bytes except the last byte */
+  for (i = 0; i < scan_size_bytes - 1; i++) {
+    tdo_data = 0;
+
+    for (j = 0; j < 8; j++) {
+      OUTB = outb_buffer; /* TCK changes here */
+      OUTB = (outb_buffer | PIN_TCK);
+      tdo_data = tdo_data >> 1;
+
+      if (GET_TDO()) {
+        tdo_data |= 0x80;
+      }
+    }
+
+    /* Copy TDO data to IN2BUF */
+    IN2BUF[i + in_offset] = tdo_data;
+  }
+
+  tdo_data = 0;
+
+  /* Shift the last byte */
+  for (j = 0; j < bits_last_byte; j++) {
+    /* Assert TMS signal if requested and this is the last bit */
+    if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+      outb_buffer |= PIN_TMS;
+      tms_count_end--;
+      tms_sequence_end = tms_sequence_end >> 1;
+    }
+
+    OUTB = outb_buffer; /* TCK change here */
+    OUTB = (outb_buffer | PIN_TCK);
+    tdo_data = tdo_data >> 1;
+
+    if (GET_TDO()) {
+      tdo_data |= 0x80;
+    }
+  }
+  tdo_data = tdo_data >> (8 - bits_last_byte);
+
+  /* Copy TDO data to IN2BUF */
+  IN2BUF[i + in_offset] = tdo_data;
+
+  /* Move to correct end state */
+  if (tms_count_end > 0) {
+    jtag_clock_tms(tms_count_end, tms_sequence_end);
+  }
+}
+
+/**
+ * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
+ *
+ * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
+ * data is not sampled.
+ * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_scan_out(u8 out_offset)
+{
+  u8 scan_size_bytes, bits_last_byte;
+  u8 tms_count_start, tms_count_end;
+  u8 tms_sequence_start, tms_sequence_end;
+  u8 tdi_data, i, j;
+
+  u8 outb_buffer;
+
+  /* Get parameters from OUT2BUF */
+  scan_size_bytes = OUT2BUF[out_offset];
+  bits_last_byte = OUT2BUF[out_offset + 1];
+  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+  tms_sequence_start = OUT2BUF[out_offset + 3];
+  tms_sequence_end = OUT2BUF[out_offset + 4];
+  
+  if (tms_count_start > 0) {
+    jtag_clock_tms(tms_count_start, tms_sequence_start);
+  }
+
+  outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
+
+  /* Shift all bytes except the last byte */
+  for (i = 0; i < scan_size_bytes - 1; i++) {
+    tdi_data = OUT2BUF[i + out_offset + 5];
+
+    for (j = 0; j < 8; j++) {
+      if (tdi_data & 0x01) {
+        outb_buffer |= PIN_TDI;
+      }
+      else {
+        outb_buffer &= ~PIN_TDI;
+      }
+
+      OUTB = outb_buffer; /* TDI and TCK change here */
+      tdi_data = tdi_data >> 1;
+      OUTB = (outb_buffer | PIN_TCK);
+    }
+  }
+
+  tdi_data = OUT2BUF[i + out_offset + 5];
+
+  /* Shift the last byte */
+  for (j = 0; j < bits_last_byte; j++) {
+    if (tdi_data & 0x01) {
+      outb_buffer |= PIN_TDI;
+    }
+    else {
+      outb_buffer &= ~PIN_TDI;
+    }
+
+    /* Assert TMS signal if requested and this is the last bit */
+    if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+      outb_buffer |= PIN_TMS;
+      tms_count_end--;
+      tms_sequence_end = tms_sequence_end >> 1;
+    }
+
+    OUTB = outb_buffer; /* TDI and TCK change here */
+    tdi_data = tdi_data >> 1;
+    OUTB = (outb_buffer | PIN_TCK);
+  }
+
+  /* Move to correct end state */
+  if (tms_count_end > 0) {
+    jtag_clock_tms(tms_count_end, tms_sequence_end);
+  }
+}
+
+/**
+ * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
+ *
+ * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
+ * data is sampled and stored in the EP2 IN buffer.
+ * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
+ *
+ * @param out_offset offset in OUT2BUF where payload data starts
+ */
+void jtag_scan_io(u8 out_offset, u8 in_offset)
+{
+  u8 scan_size_bytes, bits_last_byte;
+  u8 tms_count_start, tms_count_end;
+  u8 tms_sequence_start, tms_sequence_end;
+  u8 tdi_data, tdo_data, i, j;
+
+  u8 outb_buffer;
+
+  /* Get parameters from OUT2BUF */
+  scan_size_bytes = OUT2BUF[out_offset];
+  bits_last_byte = OUT2BUF[out_offset + 1];
+  tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
+  tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
+  tms_sequence_start = OUT2BUF[out_offset + 3];
+  tms_sequence_end = OUT2BUF[out_offset + 4];
+  
+  if (tms_count_start > 0) {
+    jtag_clock_tms(tms_count_start, tms_sequence_start);
+  }
+
+  outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
+
+  /* Shift all bytes except the last byte */
+  for (i = 0; i < scan_size_bytes - 1; i++) {
+    tdi_data = OUT2BUF[i + out_offset + 5];
+    tdo_data = 0;
+
+    for (j = 0; j < 8; j++) {
+      if (tdi_data & 0x01) {
+        outb_buffer |= PIN_TDI;
+      }
+      else {
+        outb_buffer &= ~PIN_TDI;
+      }
+
+      OUTB = outb_buffer; /* TDI and TCK change here */
+      tdi_data = tdi_data >> 1;
+      OUTB = (outb_buffer | PIN_TCK);
+      tdo_data = tdo_data >> 1;
+
+      if (GET_TDO()) {
+        tdo_data |= 0x80;
+      }
+    }
+
+    /* Copy TDO data to IN2BUF */
+    IN2BUF[i + in_offset] = tdo_data;
+  }
+
+  tdi_data = OUT2BUF[i + out_offset + 5];
+  tdo_data = 0;
+
+  /* Shift the last byte */
+  for (j = 0; j < bits_last_byte; j++) {
+    if (tdi_data & 0x01) {
+      outb_buffer |= PIN_TDI;
+    }
+    else {
+      outb_buffer &= ~PIN_TDI;
+    }
+
+    /* Assert TMS signal if requested and this is the last bit */
+    if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
+      outb_buffer |= PIN_TMS;
+      tms_count_end--;
+      tms_sequence_end = tms_sequence_end >> 1;
+    }
+
+    OUTB = outb_buffer; /* TDI and TCK change here */
+    tdi_data = tdi_data >> 1;
+    OUTB = (outb_buffer | PIN_TCK);
+    tdo_data = tdo_data >> 1;
+
+    if (GET_TDO()) {
+      tdo_data |= 0x80;
+    }
+  }
+  tdo_data = tdo_data >> (8 - bits_last_byte);
+
+  /* Copy TDO data to IN2BUF */
+  IN2BUF[i + in_offset] = tdo_data;
+  
+  /* Move to correct end state */
+  if (tms_count_end > 0) {
+    jtag_clock_tms(tms_count_end, tms_sequence_end);
+  }
+}
+
+/**
+ * Generate TCK clock cycles.
+ *
+ * @param count number of TCK clock cyclces to generate.
+ */
+void jtag_clock_tck(u16 count)
+{
+  u16 i;
+  u8 j;
+
+  for ( i = 0; i < count; i++ ) {
+    SET_TCK_LOW();
+    for(j = 0; j < delay_tck; j++);
+
+    SET_TCK_HIGH();
+    for(j = 0; j < delay_tck; j++);
+  }
+}
+
+/**
+ * Perform TAP-FSM state transitions at maximum TCK frequency.
+ *
+ * @param count the number of state transitions to perform.
+ * @param sequence the TMS pin levels for each state transition, starting with
+ *  the least-significant bit.
+ */
+void jtag_clock_tms(u8 count, u8 sequence)
+{
+  volatile u8 outb_buffer;
+  u8 i;
+
+  outb_buffer = OUTB & ~(PIN_TCK);
+
+  for ( i = 0; i < count; i++ ) {
+    /* Set TMS pin according to sequence parameter */
+    if ( sequence & 0x1 ) {
+      outb_buffer |= PIN_TMS;
+    }
+    else {
+      outb_buffer &= ~PIN_TMS;
+    }
+
+    OUTB = outb_buffer;
+    sequence = sequence >> 1;
+    OUTB = outb_buffer | PIN_TCK;
+  }
+}
+
+/**
+ * Perform TAP-FSM state transitions at less than maximum TCK frequency.
+ *
+ * @param count the number of state transitions to perform.
+ * @param sequence the TMS pin levels for each state transition, starting with
+ *  the least-significant bit.
+ */
+void jtag_slow_clock_tms(u8 count, u8 sequence)
+{
+
+}
+
+/**
+ * Get current JTAG signal states.
+ *
+ * @return a 16-bit integer where the most-significant byte contains the state
+ *  of the JTAG input signals and the least-significant byte cotains the state
+ *  of the JTAG output signals.
+ */
+u16 jtag_get_signals(void)
+{
+  u8 input_signal_state, output_signal_state;
+
+  input_signal_state = 0;
+  output_signal_state = 0;
+
+  /* Get states of input pins */
+  if (GET_TDO()) {
+    input_signal_state |= SIGNAL_TDO;
+  }
+  if (GET_BRKOUT()) {
+    input_signal_state |= SIGNAL_BRKOUT;
+  }
+  if (GET_TRAP()) {
+    input_signal_state |= SIGNAL_TRAP;
+  }
+  if (GET_RTCK()) {
+    /* Using RTCK this way would be extremely slow,
+     * implemented only for the sake of completeness */
+    input_signal_state |= SIGNAL_RTCK;
+  }
+
+  /* Get states of output pins */
+  output_signal_state = PINSB & MASK_PORTB_DIRECTION_OUT;
+
+  return ((u16)input_signal_state << 8) | ((u16)output_signal_state);
+}
+
+/**
+ * Set state of JTAG output signals.
+ *
+ * @param low signals which should be de-asserted.
+ * @param high signals which should be asserted.
+ */
+void jtag_set_signals(u8 low, u8 high)
+{
+  OUTB &= ~(low & MASK_PORTB_DIRECTION_OUT);
+  OUTB |= (high & MASK_PORTB_DIRECTION_OUT);
+}
+
+/**
+ * Configure TCK delay parameters.
+ *
+ * @param scan number of delay cycles in shift operations.
+ * @param tck number of delay cycles in clock_tck operations.
+ * @param tms number of delay cycles in clock_tms operations.
+ */
+void jtag_configure_tck_delay(u8 scan, u8 tck, u8 tms)
+{
+  delay_scan = scan;
+  delay_tck = tck;
+  delay_tms = tms;
+}
diff --git a/src/jtag/drivers/OpenULINK/src/main.c b/src/jtag/drivers/OpenULINK/src/main.c
new file mode 100644 (file)
index 0000000..3ea3fff
--- /dev/null
@@ -0,0 +1,92 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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 "main.h"
+
+#include "shorttypes.h"
+#include "io.h"
+#include "usb.h"
+#include "protocol.h"
+
+extern void sudav_isr(void)    __interrupt SUDAV_ISR;
+extern void sof_isr(void)      __interrupt;
+extern void sutok_isr(void)    __interrupt;
+extern void suspend_isr(void)  __interrupt;
+extern void usbreset_isr(void) __interrupt;
+extern void ibn_isr(void)      __interrupt;
+extern void ep0in_isr(void)    __interrupt;
+extern void ep0out_isr(void)   __interrupt;
+extern void ep1in_isr(void)    __interrupt;
+extern void ep1out_isr(void)   __interrupt;
+extern void ep2in_isr(void)    __interrupt;
+extern void ep2out_isr(void)   __interrupt;
+extern void ep3in_isr(void)    __interrupt;
+extern void ep3out_isr(void)   __interrupt;
+extern void ep4in_isr(void)    __interrupt;
+extern void ep4out_isr(void)   __interrupt;
+extern void ep5in_isr(void)    __interrupt;
+extern void ep5out_isr(void)   __interrupt;
+extern void ep6in_isr(void)    __interrupt;
+extern void ep6out_isr(void)   __interrupt;
+extern void ep7in_isr(void)    __interrupt;
+extern void ep7out_isr(void)   __interrupt;
+
+void io_init(void)
+{
+  /* PORTxCFG register bits select alternate functions (1 == alternate function,
+   *                                                    0 == standard I/O)
+   * OEx register bits turn on/off output buffer (1 == output, 0 == input)
+   * OUTx register bits determine pin state of output
+   * PINx register bits reflect pin state (high == 1, low == 0) */
+
+  /* PORT A */
+  PORTACFG = PIN_OE;
+  OEA = PIN_U_OE | PIN_OE | PIN_RUN_LED | PIN_COM_LED;
+  OUTA = PIN_RUN_LED | PIN_COM_LED;
+
+  /* PORT B */
+  PORTBCFG = 0x00;
+  OEB = PIN_TDI | PIN_TMS | PIN_TCK | PIN_TRST | PIN_BRKIN | PIN_RESET
+      | PIN_OCDSE;
+
+  /* TRST and RESET signals are low-active but inverted by hardware, so we clear
+   * these signals here! */
+  OUTB = 0x00;
+
+  /* PORT C */
+  PORTCCFG = PIN_WR;
+  OEC = PIN_TXD0 | PIN_WR;
+  OUTC = 0x00;
+}
+
+int main(void)
+{
+  io_init();
+  usb_init();
+
+  /* Enable Interrupts */
+  EA = 1;
+
+  /* Begin executing command(s). This function never returns. */
+  command_loop();
+
+  /* Never reached, but SDCC complains about missing return statement */
+  return 0;
+}
diff --git a/src/jtag/drivers/OpenULINK/src/protocol.c b/src/jtag/drivers/OpenULINK/src/protocol.c
new file mode 100644 (file)
index 0000000..05929d0
--- /dev/null
@@ -0,0 +1,212 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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 "protocol.h"
+#include "jtag.h"
+#include "delay.h"
+#include "usb.h"
+#include "io.h"
+#include "msgtypes.h"
+
+#include "reg_ezusb.h"
+
+/**
+ * @file Implementation of the OpenULINK communication protocol.
+ *
+ * The OpenULINK protocol uses one OUT and one IN endpoint. These two endpoints
+ * are configured to use the maximum packet size for full-speed transfers,
+ * 64 bytes. Commands always start with a command ID (see msgtypes.h for
+ * command ID definitions) and contain zero or more payload data bytes in both
+ * transfer directions (IN and OUT). The payload 
+ *
+ * Almost all commands contain a fixed number of payload data bytes. The number
+ * of payload data bytes for the IN and OUT direction does not need to be the
+ * same.
+ * 
+ * Multiple commands may be sent in one EP2 Bulk-OUT packet. Because the
+ * OpenULINK firmware does not perform bounds checking for EP2 Bulk-IN packets,
+ * the host MUST ensure that the commands sent in the OUT packet require a
+ * maximum of 64 bytes of IN data.
+ */
+
+/** Index in EP2 Bulk-OUT data buffer that contains the current command ID */
+volatile u8 cmd_id_index;
+
+/** Number of data bytes already in EP2 Bulk-IN buffer */
+volatile u8 payload_index_in;
+
+/**
+ * Execute a SET_LEDS command.
+ */
+void execute_set_led_command(void)
+{
+  u8 led_state = OUT2BUF[cmd_id_index + 1];
+
+  if (led_state & RUN_LED_ON) {
+    SET_RUN_LED();
+  }
+
+  if (led_state & COM_LED_ON) {
+    SET_COM_LED();
+  }
+
+  if (led_state & RUN_LED_OFF) {
+    CLEAR_RUN_LED();
+  }
+
+  if (led_state & COM_LED_OFF) {
+    CLEAR_COM_LED();
+  }
+}
+
+/**
+ * Executes one command and updates global command indexes.
+ *
+ * @param index the index of the Bulk EP2-OUT data buffer at which the
+ *  command ID is stored.
+ * @return true if this command was the last command.
+ * @return false if there are more commands within the current contents of the
+ *  Bulk EP2-OUT data buffer.
+ */
+bool execute_command(void)
+{
+  u8 usb_out_bytecount, usb_in_bytecount;
+  u16 signal_state;
+  u16 count;
+
+  /* Most commands do not transfer IN data. To save code space, we write 0 to
+   * usb_in_bytecount here, then modify it in the switch statement below where
+   * neccessary */
+  usb_in_bytecount = 0;
+
+  switch (OUT2BUF[cmd_id_index] /* Command ID */) {
+  case CMD_SCAN_IN:
+    usb_out_bytecount = 5;
+    usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
+    jtag_scan_in(cmd_id_index + 1, payload_index_in);
+    break;
+  case CMD_SCAN_OUT:
+    usb_out_bytecount = OUT2BUF[cmd_id_index + 1] + 5;
+    jtag_scan_out(cmd_id_index + 1);
+    break;
+  case CMD_SCAN_IO:
+    usb_in_bytecount = OUT2BUF[cmd_id_index + 1];
+    usb_out_bytecount = usb_in_bytecount + 5;
+    jtag_scan_io(cmd_id_index + 1, payload_index_in);
+    break;
+  case CMD_CLOCK_TMS:
+    usb_out_bytecount = 2;
+    jtag_clock_tms(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]);
+    break;
+  case CMD_CLOCK_TCK:
+    usb_out_bytecount = 2;
+    count = (u16)OUT2BUF[cmd_id_index + 1];
+    count |= ((u16)OUT2BUF[cmd_id_index + 2]) << 8;
+    jtag_clock_tck(count);
+    break;
+  case CMD_SLEEP_US:
+    usb_out_bytecount = 2;
+    count = (u16)OUT2BUF[cmd_id_index + 1];
+    count |= ((u16)OUT2BUF[cmd_id_index + 2]) << 8;
+    delay_us(count);
+    break;
+  case CMD_SLEEP_MS:
+    usb_out_bytecount = 2;
+    count = (u16)OUT2BUF[cmd_id_index + 1];
+    count |= ((u16)OUT2BUF[cmd_id_index + 2]) << 8;
+    delay_ms(count);
+    break;
+  case CMD_GET_SIGNALS:
+    usb_out_bytecount = 0;
+    usb_in_bytecount = 2;
+    signal_state = jtag_get_signals();
+    IN2BUF[payload_index_in] = (signal_state >> 8) & 0x00FF;
+    IN2BUF[payload_index_in + 1] = signal_state & 0x00FF;
+    break;
+  case CMD_SET_SIGNALS:
+    usb_out_bytecount = 2;
+    jtag_set_signals(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]);
+    break;
+  case CMD_SET_LEDS:
+    usb_out_bytecount = 1;
+    execute_set_led_command();
+    break;
+  case CMD_TEST:
+    usb_out_bytecount = 1;
+    /* Do nothing... This command is only used to test if the device is ready
+     * to accept new commands */
+    break;
+  default:
+    /* Should never be reached */
+    usb_out_bytecount = 0;
+    break;
+  }
+
+  /* Update EP2 Bulk-IN data byte count */
+  payload_index_in += usb_in_bytecount;
+
+  /* Determine if this was the last command */
+  if ((cmd_id_index + usb_out_bytecount + 1) >= OUT2BC) {
+    return true;
+  }
+  else {
+    /* Not the last command, update cmd_id_index */
+    cmd_id_index += (usb_out_bytecount + 1);
+    return false;
+  }
+}
+
+/**
+ * Forever wait for commands and execute them as they arrive.
+ */
+void command_loop(void)
+{
+  bool last_command;
+
+  while (1) {
+    cmd_id_index = 0;
+    payload_index_in = 0;
+
+    /* Wait until host sends EP2 Bulk-OUT packet */
+    while (!EP2_out);
+    EP2_out = 0;
+
+    /* Turn on COM LED to indicate command execution */
+    SET_COM_LED();
+
+    /* Execute the commands */
+    last_command = false;
+    while (last_command == false) {
+      last_command = execute_command();
+    }
+
+    CLEAR_COM_LED();
+    
+    /* Send back EP2 Bulk-IN packet if required */
+    if (payload_index_in > 0) {
+      IN2BC = payload_index_in;
+      while (!EP2_in);
+      EP2_in = 0;
+    }
+
+    /* Re-arm EP2-OUT after command execution */
+    OUT2BC = 0;
+  }
+}
diff --git a/src/jtag/drivers/OpenULINK/src/usb.c b/src/jtag/drivers/OpenULINK/src/usb.c
new file mode 100644 (file)
index 0000000..b74b3a2
--- /dev/null
@@ -0,0 +1,543 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Martin Schmoelzer                               *
+ *   <martin.schmoelzer@student.tuwien.ac.at>                              *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+
+/**
+ * @file Defines USB descriptors, interrupt routines and helper functions.
+ * To minimize code size, we make the following assumptions:
+ *  - The OpenULINK has exactly one configuration
+ *  - and exactly one alternate setting
+ *
+ * Therefore, we do not have to support the Set Configuration USB request.
+ */
+
+#include "usb.h"
+#include "delay.h"
+#include "io.h"
+
+/* Also update external declarations in "include/usb.h" if making changes to
+ * these variables! */
+volatile bool EP2_out = 0;
+volatile bool EP2_in  = 0;
+
+volatile __xdata __at 0x7FE8 setup_data_t setup_data;
+
+/* Define number of endpoints (except Control Endpoint 0) in a central place.
+ * Be sure to include the neccessary endpoint descriptors! */
+#define NUM_ENDPOINTS  2
+
+/*
+ * Normally, we would initialize the descriptor structures in C99 style:
+ *
+ * __code usb_device_descriptor_t device_descriptor = {
+ *   .bLength = foo,
+ *   .bDescriptorType = bar,
+ *   .bcdUSB = 0xABCD,
+ *   ...
+ * };
+ *
+ * But SDCC currently does not support this, so we have to do it the
+ * old-fashioned way...
+ */
+
+__code usb_device_descriptor_t device_descriptor = {
+  /* .bLength = */            sizeof(usb_device_descriptor_t),
+  /* .bDescriptorType = */     DESCRIPTOR_TYPE_DEVICE,
+  /* .bcdUSB = */              0x0110, /* BCD: 01.00 (Version 1.0 USB spec) */
+  /* .bDeviceClass = */        0xFF,   /* 0xFF = vendor-specific */
+  /* .bDeviceSubClass = */     0xFF,
+  /* .bDeviceProtocol = */     0xFF,
+  /* .bMaxPacketSize0 = */     64,
+  /* .idVendor = */            0xC251,
+  /* .idProduct = */           0x2710,
+  /* .bcdDevice = */           0x0100,
+  /* .iManufacturer = */       1,
+  /* .iProduct = */            2,
+  /* .iSerialNumber = */       3,
+  /* .bNumConfigurations = */  1
+};
+
+/* WARNING: ALL config, interface and endpoint descriptors MUST be adjacent! */
+
+__code usb_config_descriptor_t config_descriptor = {
+  /* .bLength = */             sizeof(usb_config_descriptor_t),
+  /* .bDescriptorType = */     DESCRIPTOR_TYPE_CONFIGURATION,
+  /* .wTotalLength = */        sizeof(usb_config_descriptor_t) +
+                               sizeof(usb_interface_descriptor_t) + 
+                               NUM_ENDPOINTS * sizeof(usb_endpoint_descriptor_t),
+  /* .bNumInterfaces = */      1,
+  /* .bConfigurationValue = */ 1,
+  /* .iConfiguration = */      4,     /* String describing this configuration */
+  /* .bmAttributes = */        0x80,  /* Only MSB set according to USB spec */
+  /* .MaxPower = */            50     /* 100 mA */
+};
+
+__code usb_interface_descriptor_t interface_descriptor00 = {
+  /* .bLength = */             sizeof(usb_interface_descriptor_t),
+  /* .bDescriptorType = */     DESCRIPTOR_TYPE_INTERFACE,
+  /* .bInterfaceNumber = */    0,
+  /* .bAlternateSetting = */   0,
+  /* .bNumEndpoints = */       NUM_ENDPOINTS,
+  /* .bInterfaceClass = */     0xFF,
+  /* .bInterfaceSubclass = */  0xFF,
+  /* .bInterfaceProtocol = */  0xFF,
+  /* .iInterface = */          0
+};
+
+__code usb_endpoint_descriptor_t Bulk_EP2_IN_Endpoint_Descriptor = {
+  /* .bLength = */             sizeof(usb_endpoint_descriptor_t),
+  /* .bDescriptorType = */     0x05,
+  /* .bEndpointAddress = */    2 | USB_DIR_IN,
+  /* .bmAttributes = */        0x02,
+  /* .wMaxPacketSize = */      64,
+  /* .bInterval = */           0
+};
+
+__code usb_endpoint_descriptor_t Bulk_EP2_OUT_Endpoint_Descriptor = {
+  /* .bLength = */             sizeof(usb_endpoint_descriptor_t),
+  /* .bDescriptorType = */     0x05,
+  /* .bEndpointAddress = */    2 | USB_DIR_OUT,
+  /* .bmAttributes = */        0x02,
+  /* .wMaxPacketSize = */      64,
+  /* .bInterval = */           0
+};
+
+__code usb_language_descriptor_t language_descriptor = {
+  /* .bLength =  */            4,
+  /* .bDescriptorType = */     DESCRIPTOR_TYPE_STRING,
+  /* .wLANGID = */             {0x0409 /* US English */}
+};
+
+__code usb_string_descriptor_t strManufacturer = STR_DESCR(9,'O','p','e','n','U','L','I','N','K');
+__code usb_string_descriptor_t strProduct      = STR_DESCR(9,'O','p','e','n','U','L','I','N','K');
+__code usb_string_descriptor_t strSerialNumber = STR_DESCR(6, '0','0','0','0','0','1');
+__code usb_string_descriptor_t strConfigDescr  = STR_DESCR(12, 'J','T','A','G',' ','A','d','a','p','t','e','r');
+
+/* Table containing pointers to string descriptors */
+__code usb_string_descriptor_t* __code en_string_descriptors[4] = {
+  &strManufacturer,
+  &strProduct,
+  &strSerialNumber,
+  &strConfigDescr
+};
+
+void sudav_isr(void) __interrupt SUDAV_ISR
+{
+  CLEAR_IRQ();
+
+  usb_handle_setup_data();
+
+  USBIRQ = SUDAVIR;
+  EP0CS |= HSNAK;
+}
+
+void sof_isr(void)      __interrupt SOF_ISR      { }
+void sutok_isr(void)    __interrupt SUTOK_ISR    { }
+void suspend_isr(void)  __interrupt SUSPEND_ISR  { }
+void usbreset_isr(void) __interrupt USBRESET_ISR { }
+void ibn_isr(void)      __interrupt IBN_ISR      { }
+
+void ep0in_isr(void)    __interrupt EP0IN_ISR    { }
+void ep0out_isr(void)   __interrupt EP0OUT_ISR   { }
+void ep1in_isr(void)    __interrupt EP1IN_ISR    { }
+void ep1out_isr(void)   __interrupt EP1OUT_ISR   { }
+
+/**
+ * EP2 IN: called after the transfer from uC->Host has finished: we sent data
+ */
+void ep2in_isr(void)    __interrupt EP2IN_ISR { 
+  EP2_in = 1;
+
+  CLEAR_IRQ();
+  IN07IRQ = IN2IR;     // Clear OUT2 IRQ
+}
+
+/**
+ * EP2 OUT: called after the transfer from Host->uC has finished: we got data
+ */
+void ep2out_isr(void)   __interrupt EP2OUT_ISR {
+  EP2_out = 1;
+
+  CLEAR_IRQ();
+  OUT07IRQ = OUT2IR;    // Clear OUT2 IRQ
+}
+
+void ep3in_isr(void)    __interrupt EP3IN_ISR    { }
+void ep3out_isr(void)   __interrupt EP3OUT_ISR   { }
+void ep4in_isr(void)    __interrupt EP4IN_ISR    { }
+void ep4out_isr(void)   __interrupt EP4OUT_ISR   { }
+void ep5in_isr(void)    __interrupt EP5IN_ISR    { }
+void ep5out_isr(void)   __interrupt EP5OUT_ISR   { }
+void ep6in_isr(void)    __interrupt EP6IN_ISR    { }
+void ep6out_isr(void)   __interrupt EP6OUT_ISR   { }
+void ep7in_isr(void)    __interrupt EP7IN_ISR    { }
+void ep7out_isr(void)   __interrupt EP7OUT_ISR   { }
+
+/**
+ * Return the control/status register for an endpoint
+ *
+ * @param ep endpoint address
+ * @return on success: pointer to Control & Status register for endpoint
+ *  specified in \a ep
+ * @return on failure: NULL
+ */
+__xdata u8* usb_get_endpoint_cs_reg(u8 ep)
+{
+  /* Mask direction bit */
+  u8 ep_num = ep & 0x7F;
+
+  switch (ep_num) {
+  case 0:
+    return &EP0CS;
+    break;
+  case 1:
+    return ep & 0x80 ? &IN1CS : &OUT1CS;
+    break;
+  case 2:
+    return ep & 0x80 ? &IN2CS : &OUT2CS;
+    break;
+  case 3:
+    return ep & 0x80 ? &IN3CS : &OUT3CS;
+    break;
+  case 4:
+    return ep & 0x80 ? &IN4CS : &OUT4CS;
+    break;
+  case 5:
+    return ep & 0x80 ? &IN5CS : &OUT5CS;
+    break;
+  case 6:
+    return ep & 0x80 ? &IN6CS : &OUT6CS;
+    break;
+  case 7:
+    return ep & 0x80 ? &IN7CS : &OUT7CS;
+    break;
+  }
+
+  return NULL;
+}
+
+void usb_reset_data_toggle(u8 ep)
+{
+  /* TOGCTL register:
+     +----+-----+-----+------+-----+-------+-------+-------+
+     | Q  |  S  |  R  |  IO  |  0  |  EP2  |  EP1  |  EP0  |
+     +----+-----+-----+------+-----+-------+-------+-------+
+
+     To reset data toggle bits, we have to write the endpoint direction (IN/OUT)
+     to the IO bit and the endpoint number to the EP2..EP0 bits. Then, in a
+     separate write cycle, the R bit needs to be set.
+  */
+  u8 togctl_value = (ep & 0x80 >> 3) | (ep & 0x7);
+
+  /* First step: Write EP number and direction bit */
+  TOGCTL = togctl_value;
+
+  /* Second step: Set R bit */
+  togctl_value |= TOG_R;
+  TOGCTL = togctl_value;
+}
+
+/**
+ * Handle GET_STATUS request.
+ *
+ * @return on success: true
+ * @return on failure: false
+ */
+bool usb_handle_get_status(void)
+{
+  u8 *ep_cs;
+
+  switch (setup_data.bmRequestType) {
+  case GS_DEVICE:
+    /* Two byte response: Byte 0, Bit 0 = self-powered, Bit 1 = remote wakeup.
+     *                    Byte 1: reserved, reset to zero */
+    IN0BUF[0] = 0;
+    IN0BUF[1] = 0;
+
+    /* Send response */
+    IN0BC = 2;
+    break;
+  case GS_INTERFACE:
+    /* Always return two zero bytes according to USB 1.1 spec, p. 191 */
+    IN0BUF[0] = 0;
+    IN0BUF[1] = 0;
+
+    /* Send response */
+    IN0BC = 2;
+    break;
+  case GS_ENDPOINT:
+    /* Get stall bit for endpoint specified in low byte of wIndex */
+    ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex & 0xff);
+
+    if (*ep_cs & EPSTALL) {
+      IN0BUF[0] = 0x01;
+    }
+    else {
+      IN0BUF[0] = 0x00;
+    }
+
+    /* Second byte sent has to be always zero */
+    IN0BUF[1] = 0;
+
+    /* Send response */
+    IN0BC = 2;
+    break;
+  default:
+    return false;
+    break;
+  }
+
+  return true;
+}
+
+/**
+ * Handle CLEAR_FEATURE request.
+ *
+ * @return on success: true
+ * @return on failure: false
+ */
+bool usb_handle_clear_feature(void)
+{
+  __xdata u8 *ep_cs;
+
+  switch (setup_data.bmRequestType) {
+  case CF_DEVICE:
+    /* Clear remote wakeup not supported: stall EP0 */
+    STALL_EP0();
+    break;
+  case CF_ENDPOINT:
+    if (setup_data.wValue == 0) {
+      /* Unstall the endpoint specified in wIndex */
+      ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex);
+      if (!ep_cs) {
+        return false;
+      }
+      *ep_cs &= ~EPSTALL;
+    }
+    else {
+      /* Unsupported feature, stall EP0 */
+      STALL_EP0();
+    }
+    break;
+  default:
+    /* Vendor commands... */
+  }
+
+  return true;
+}
+
+/**
+ * Handle SET_FEATURE request.
+ *
+ * @return on success: true
+ * @return on failure: false
+ */
+bool usb_handle_set_feature(void)
+{
+  __xdata u8 *ep_cs;
+
+  switch (setup_data.bmRequestType) {
+  case SF_DEVICE:
+    if (setup_data.wValue == 2) {
+      return true;
+    }
+    break;
+  case SF_ENDPOINT:
+    if (setup_data.wValue == 0) {
+      /* Stall the endpoint specified in wIndex */
+      ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex);
+      if (!ep_cs) {
+        return false;
+      }
+      *ep_cs |= EPSTALL;
+    }
+    else {
+      /* Unsupported endpoint feature */
+      return false;
+    }
+    break;
+  default:
+    /* Vendor commands... */
+    break;
+  }
+
+  return true;
+}
+
+/**
+ * Handle GET_DESCRIPTOR request.
+ *
+ * @return on success: true
+ * @return on failure: false
+ */
+bool usb_handle_get_descriptor(void)
+{
+  __xdata u8 descriptor_type;
+  __xdata u8 descriptor_index;
+
+  descriptor_type = (setup_data.wValue & 0xff00) >> 8;
+  descriptor_index = setup_data.wValue & 0x00ff;
+
+  switch (descriptor_type) {
+  case DESCRIPTOR_TYPE_DEVICE:
+    SUDPTRH = HI8(&device_descriptor);
+    SUDPTRL = LO8(&device_descriptor);
+    break;
+  case DESCRIPTOR_TYPE_CONFIGURATION:
+    SUDPTRH = HI8(&config_descriptor);
+    SUDPTRL = LO8(&config_descriptor);
+    break;
+  case DESCRIPTOR_TYPE_STRING:
+    if (setup_data.wIndex == 0) {
+      /* Supply language descriptor */
+      SUDPTRH = HI8(&language_descriptor);
+      SUDPTRL = LO8(&language_descriptor);
+    }
+    else if (setup_data.wIndex == 0x0409 /* US English */) {
+      /* Supply string descriptor */
+      SUDPTRH = HI8(en_string_descriptors[descriptor_index - 1]);
+      SUDPTRL = LO8(en_string_descriptors[descriptor_index - 1]);
+    }
+    else {
+      return false;
+    }
+    break;
+  default:
+    /* Unsupported descriptor type */
+    return false;
+    break;
+  }
+
+  return true;
+}
+
+/**
+ * Handle SET_INTERFACE request.
+ */
+void usb_handle_set_interface(void)
+{
+  /* Reset Data Toggle */
+  usb_reset_data_toggle(USB_DIR_IN  | 2);
+  usb_reset_data_toggle(USB_DIR_OUT | 2);
+
+  /* Unstall & clear busy flag of all valid IN endpoints */
+  IN2CS = 0 | EPBSY;
+  
+  /* Unstall all valid OUT endpoints, reset bytecounts */
+  OUT2CS = 0;
+  OUT2BC = 0;
+}
+
+/**
+ * Handle the arrival of a USB Control Setup Packet.
+ */
+void usb_handle_setup_data(void)
+{
+  switch (setup_data.bRequest) {
+    case GET_STATUS:
+      if (!usb_handle_get_status()) {
+        STALL_EP0();
+      }
+      break;
+    case CLEAR_FEATURE:
+      if (!usb_handle_clear_feature()) {
+        STALL_EP0();
+      }
+      break;
+    case 2: case 4:
+      /* Reserved values */
+      STALL_EP0();
+      break;
+    case SET_FEATURE:
+      if (!usb_handle_set_feature()) {
+        STALL_EP0();
+      }
+      break;
+    case SET_ADDRESS:
+      /* Handled by USB core */
+      break;
+    case SET_DESCRIPTOR:
+      /* Set Descriptor not supported. */
+      STALL_EP0();
+      break;
+    case GET_DESCRIPTOR:
+      if (!usb_handle_get_descriptor()) {
+        STALL_EP0();
+      }
+      break;
+    case GET_CONFIGURATION:
+      /* OpenULINK has only one configuration, return its index */
+      IN0BUF[0] = config_descriptor.bConfigurationValue;
+      IN0BC = 1;
+      break;
+    case SET_CONFIGURATION:
+      /* OpenULINK has only one configuration -> nothing to do */
+      break;
+    case GET_INTERFACE:
+      /* OpenULINK only has one interface, return its number */
+      IN0BUF[0] = interface_descriptor00.bInterfaceNumber;
+      IN0BC = 1;
+      break;
+    case SET_INTERFACE:
+      usb_handle_set_interface();
+      break;
+    case SYNCH_FRAME:
+      /* Isochronous endpoints not used -> nothing to do */
+      break;
+    default:
+      /* Any other requests: do nothing */
+      break;
+  }
+}
+
+/**
+ * USB initialization. Configures USB interrupts, endpoints and performs
+ * ReNumeration.
+ */
+void usb_init(void) {
+  /* Mark endpoint 2 IN & OUT as valid */
+  IN07VAL  = IN2VAL;
+  OUT07VAL = OUT2VAL;
+
+  /* Make sure no isochronous endpoints are marked valid */
+  INISOVAL  = 0;
+  OUTISOVAL = 0;
+
+  /* Disable isochronous endpoints. This makes the isochronous data buffers
+   * available as 8051 XDATA memory at address 0x2000 - 0x27FF */
+  ISOCTL = ISODISAB;
+
+  /* Enable USB Autovectoring */
+  USBBAV |= AVEN;
+  
+  /* Enable SUDAV interrupt */
+  USBIEN |= SUDAVIE;
+
+  /* Enable EP2 OUT & IN interrupts */
+  OUT07IEN = OUT2IEN;
+  IN07IEN  = IN2IEN;
+
+  /* Enable USB interrupt (EIE register) */
+  EUSB = 1;
+
+  /* Perform ReNumeration */
+  USBCS = DISCON | RENUM;
+  delay_ms(200);
+  USBCS = DISCOE | RENUM;
+}
diff --git a/src/jtag/drivers/OpenULINK/ulink_firmware.hex b/src/jtag/drivers/OpenULINK/ulink_firmware.hex
new file mode 100644 (file)
index 0000000..9e74423
--- /dev/null
@@ -0,0 +1,251 @@
+:040000000200733255
+:01000B0032C2
+:0100130032BA
+:01001B0032B2
+:0100230032AA
+:01002B0032A2
+:01003300329A
+:01003B003292
+:01004300328A
+:01004B003282
+:01005300327A
+:01005B003272
+:01006300326A
+:03006B0002011F70
+:0300D90002006EB4
+:05006E0012011080FEEC
+:1000DC00907F937404F0907F9C7495F0907F96744D
+:1000EC0090F0907F94E4F0907F9D747FF0907F97D8
+:1000FC00E4F0907F957440F0907F9E7442F0907F76
+:10010C0098E4F0221200DC1204FCD2AF1207C89063
+:03011C00000022BE
+:0400CC00C200C201AB
+:10011F00C021C0E0C0F0C082C083C002C003C004D1
+:10012F00C005C006C007C000C001C0D075D00053C5
+:10013F0091EF120455907FAB7401F0907FB4E044BF
+:10014F0002F0D0D0D001D000D007D006D005D00417
+:10015F00D003D002D083D082D0F0D0E0D021323281
+:10016F003232323232323232C0E0C082C083D201F8
+:10017F005391EF907FA97404F0D083D082D0E032F6
+:10018F00C0E0C082C083D2005391EF907FAA740465
+:10019F00F0D083D082D0E032323232323232323249
+:1001AF003232AA82747F5AFB7407B50300500302E0
+:1001BF000269EB2B2B9001C8730201E00201E402EC
+:1001CF0001F702020A02021D02023002024302027A
+:1001DF0056907FB422EA30E7067BB67C7F80047BA3
+:1001EF00C67C7F8B828C8322EA30E7067BB87C7FCC
+:1001FF0080047BC87C7F8B828C8322EA30E7067B6E
+:10020F00BA7C7F80047BCA7C7F8B828C8322EA300E
+:10021F00E7067BBC7C7F80047BCC7C7F8B828C83CE
+:10022F0022EA30E7067BBE7C7F80047BCE7C7F8B0F
+:10023F00828C8322EA30E7067BC07C7F80047BD0F0
+:10024F007C7F8B828C8322EA30E7067AC27B7F80A9
+:10025F00047AD27B7F8A828B832290000022AA822B
+:10026F0074105AFB74075A4203907FD7EBF0742037
+:10027F004BF022907FE8E0FABA8002800ABA81023E
+:10028F008016BA825D8022907F00E4F0907F01F0AB
+:10029F00907FB57402F0804C907F00E4F0907F0166
+:1002AF00F0907FB57402F0803B907FECE0FAA3E012
+:1002BF008A821201B1AA82AB837C008A828B838CE3
+:1002CF00F0120D90FA30E008907F007401F0800575
+:1002DF00907F00E4F0907F01E4F0907FB57402F01E
+:1002EF008002C322D322907FE8E0FA6005BA02466B
+:1002FF00800A907FB4E0FA4401F0803A907FEAE000
+:10030F00FAA3E0FB4A7027907FECE0FAA3E08A8221
+:10031F001201B1AA82AB83EA4B7002C3228A828B8D
+:10032F0083E0FC5304FE8A828B83ECF08008907F7D
+:10033F00B4E0FA4401F0D322907FE8E0FA6005BA06
+:10034F0002468010907FEAE0FAA3E0FBBA0239BBC5
+:10035F000036D322907FEAE0FAA3E0FB4A702790A1
+:10036F007FECE0FAA3E08A821201B1AA82AB83EAA2
+:10037F004B7002C3228A828B83E0FC4304018A8282
+:10038F008B83ECF08002C322D322907FEAE0A3E0BC
+:10039F00FA907FEAE0FBA3E07C00BA0102800CBA7E
+:1003AF000202801DBA0302802E807B7AB07C0D90F2
+:1003BF007FD4ECF07AB07C0D7C00907FD5EAF08092
+:1003CF00677AC27C0D907FD4ECF07AC27C0D7C00F2
+:1003DF00907FD5EAF08051907FECE0FAA3E0FC4AE1
+:1003EF0070167AE27C0D907FD4ECF07AE27C0D7C73
+:1003FF0000907FD5EAF08030907FECE0FAA3E0FC2C
+:10040F00BA0921BC041E1BEB2BFA900E3693CAA31C
+:10041F0093FB8A048B05907FD4EDF07B00907FD502
+:10042F00EAF08004C322C322D32275828212026DA6
+:10043F0075820212026D907FB87402F0907FC8E44B
+:10044F00F0907FC9F022907FE9E0FA740CB50200BA
+:10045F00500122EA2A2A9004697302049002049E32
+:10046F000204AC0204B40204AC0204C10204CA02C6
+:10047F0004C20204D70204E70204E80204F80204EB
+:10048F00FB120282500122907FB4E04401F022124D
+:10049F0002F5500122907FB4E04401F022907FB426
+:1004AF00E04401F0221203474042907FB4E0440140
+:1004BF00F02222907FB4E04401F022120399402CE5
+:1004CF00907FB4E04401F022900DC7E493907F0039
+:1004DF00F0907FB57401F02222900DCDE493907FC0
+:1004EF0000F0907FB57401F02212043922907FDE64
+:1004FF007404F0907FDF7404F0907FE0E4F0907F5D
+:10050F00E1F0907FA17401F0907FAFE04401F09093
+:10051F007FAEE04401F0907FAD7404F0907FAC7437
+:10052F0004F0D2E8907FD6740AF09000C8120D3D07
+:07053F00907FD67406F02244
+:100DB00012011001FFFFFF4051C210270001010284
+:100DC000030109022000010104803209040000022D
+:100DD000FFFFFF00070582024000000705020240F6
+:100DE00000000403090414034F00700065006E0046
+:100DF00055004C0049004E004B0014034F0070009A
+:100E000065006E0055004C0049004E004B000E037B
+:100E10003000300030003000300031001A034A004A
+:100E20005400410047002000410064006100700050
+:0E0E3000740065007200E60DFA0D0E0E1C0E29
+:10054600E5080424C0F582E4347DF583E0FA30E161
+:1005560008907F96E0FB54EFF0EA30E008907F9633
+:10056600E0FB547FF0EA30E308907F96E0FB44100E
+:10057600F0EA30E208907F96E0FA4480F0227A00B2
+:10058600E50824C0F582E4347DF583E0FB603EBBDC
+:100596000202805FBB040302061CBB200302064363
+:1005A600BB2203020673BB23030206ACBB24030271
+:1005B60006E5BB250302071DBB260302074CBB2825
+:1005C6000302077BBB290302078A02078E7B05E528
+:1005D600080424C0F582E4347DF583E0FAE50804D6
+:1005E600F58285090DC002C003120805D003D002AA
+:1005F600020790E5080424C0F582E4347DF583E023
+:100606002405FBE50804F582C002C003120951D097
+:1006160003D002020790E5080424C0F582E4347D85
+:10062600F583E0FA2405FBE50804F582850917C081
+:1006360002C003120A83D003D0020207907B02E5B0
+:10064600080424C0F582E4347DF583E0FC740225B9
+:100656000824C0F582E4347DF583E0F5228C82C05F
+:1006660002C003120C5BD003D0020207907B02E5A6
+:10067600080424C0F582E4347DF583E0FC7D007433
+:1006860002250824C0F582E4347DF583E0FFE442C8
+:1006960004EF42058C828D83C002C003120C20D069
+:1006A60003D0020207907B02E5080424C0F582E429
+:1006B600347DF583E0FC7D007402250824C0F582B4
+:1006C600E4347DF583E0FFE44204EF42058C828D3D
+:1006D60083C002C003120D0AD003D0020207907B2A
+:1006E60002E5080424C0F582E4347DF583E0FC7D50
+:1006F600007402250824C0F582E4347DF583E0FF0A
+:10070600E44204EF42058C828D83C002C003120DC1
+:100716003DD003D00280737B007A02C002C0031270
+:100726000C95AC82AD83D003D00285098275837E99
+:100736008D06EEF0E509042400F582E4347EF583A7
+:100746007D00ECF080447B02E5080424C0F582E4D9
+:10075600347DF583E0FC7402250824C0F582E43478
+:100766007DF583E0F5228C82C002C003120CD8D03E
+:1007760003D00280157B01C002C003120546D003D8
+:10078600D00280067B0180027B00EA2509F509AAD2
+:10079600087C008B057E00ED2AFAEE3CFC0ABA00C6
+:1007A600010C907FC9E0FD7E00C3EA9DEC64808E5B
+:1007B600F063F08095F04002D322EB042508F5089B
+:1007C600C32275080075090010000280FB907F9611
+:1007D600E0FA547FF0C202200207120584920280DA
+:1007E600F6907F96E0FA4480F0E509600B907FB9B9
+:0F07F600E509F010010280FB907FC9E4F080C399
+:0900D000750A00750B00750C00A7
+:10080500E582FA24C0F582E4347DF583E0F50EEA4D
+:100815000424C0F582E4347DF583E0F50F74022AE3
+:10082500FD24C0F582E4347DF583E0C4540FFE5306
+:10083500060FED24C0F582E4347DF583E0FD740FE9
+:100845005DF51074032A24C0F582E4347DF583E058
+:10085500FF74042A24C0F582E4347DF583E0F511A4
+:10086500EE60078F228E82120C5B907F97E0FE531D
+:1008750006F87F0074044EF87900AD0E7B001DBDAF
+:10088500FF011B89027C00C3EA9DEC64808BF06349
+:10089500F08095F050357A007B00BB080050199028
+:1008A5007F97EEF0E8F0EAC313FA907F99E0FC3009
+:1008B500E5034302800B80E2E50D292400F582E47F
+:1008C500347EF583EAF009890780AF89077A00ABA2
+:1008D50010751200E512B50F00503EAD0F78001DE2
+:1008E500BDFF0118A9127C00E9B50511ECB5000D95
+:1008F500EB600A4306021BE511C313F511907F97C0
+:10090500EEF074044EF0EAC313FA907F99E0FC30E0
+:10091500E503430280051280BBAC0F7D007408C35C
+:100925009CFCE49DFD8CF005F0EA8002C313D5F034
+:10093500FBFAE50D2F2400F582E4347EF583EAF019
+:10094500EB60088511228B82020C5B22E582FA247A
+:10095500C0F582E4347DF583E0F513EA0424C0F59F
+:1009650082E4347DF583E0F51474022AFD24C0F594
+:1009750082E4347DF583E0C4540FFE53060FED2465
+:10098500C0F582E4347DF583E0FD740F5DF51574E3
+:10099500032A24C0F582E4347DF583E0FF74042A3C
+:1009A50024C0F582E4347DF583E0F516EE600B8F07
+:1009B500228E82C002120C5BD002907F97E0FE531C
+:1009C50006F97F00A9137D0019B9FF011D8F037872
+:1009D50000C3EB99E864808DF063F08095F05038A2
+:1009E500EA2F240524C0F582E4347DF583E0FB7D00
+:1009F50000BD0800501FEB30E0054306018003539E
+:100A050006FE907F97EEF0EBC313FB907F9774047F
+:100A15004EF00D80DC0F80ACEA2F240524C0F58252
+:100A2500E4347DF583E0FBAA157D00EDB514005097
+:100A350041EB30E00543060180035306FEAF147811
+:100A4500001FBFFF01188D017C00E9B50711ECB54A
+:100A5500000DEA600A4306021AE516C313F516905F
+:100A65007F97EEF0EBC313FB907F9774044EF00D68
+:100A750080B9EA60088516228A82020C5B22E5822B
+:100A8500F51824C0F582E4347DF583E0F519E51801
+:100A95000424C0F582E4347DF583E0F51A7402255B
+:100AA50018FD24C0F582E4347DF583E0C4540FFEBF
+:100AB50053060FED24C0F582E4347DF583E0FD7423
+:100AC5000F5DF51B7403251824C0F582E4347DF50C
+:100AD50083E0FF7404251824C0F582E4347DF58392
+:100AE500E0F51CEE60078F228E82120C5B907F97DB
+:100AF500E0FE5306F97F007900AD197B001DBDFFAF
+:100B0500011B89007A00C3E89DEA64808BF063F0DD
+:100B15008095F0505EE51829240524C0F582E4345B
+:100B25007DF583E0F51D7B007D00BD08005031E5B6
+:100B35001D30E00543060180035306FE907F97EEC6
+:100B4500F0E51DC313F51D907F9774044EF0EBC3BC
+:100B550013FB907F99E0F830E5034303800D80CACD
+:100B6500E517292400F582E4347EF583EBF0098945
+:100B75000780868907E51829240524C0F582E43411
+:100B85007DF583E0F51D7B00AD1B751E00E51EB5EB
+:100B95001A005054E51D30E0054306018003530655
+:100BA500FEA91A7C0019B9FF011CA81E7A00E8B538
+:100BB5000111EAB5040DED600A4306021DE51CC3EB
+:100BC50013F51C907F97EEF0E51DC313F51D907F7F
+:100BD5009774044EF0EBC313FB907F99E0FA30E570
+:100BE50003430380051E80A5AC1A7A007408C39CD4
+:100BF500FCE49AFA8CF005F0EB8002C313D5F0FB08
+:100C0500FBE5172F2400F582E4347EF583EBF0ED48
+:100C15006008851C228D82020C5B22AA82AB837C34
+:100C2500007D00C3EC9AED9B502B907F97E054FB21
+:100C3500F07E00EEB50B0050030E80F7907F97E035
+:100C45004404F07E00EEB50B0050030E80F70CBC9B
+:100C550000D10D80CE22AA82907F97E0FB74FB5BCA
+:100C6500F5237B00EBB502005024E52230E0054377
+:100C7500230280035323FD907F97E523F0E522C3EC
+:100C850013F522907F9774044523F00B80D622221A
+:100C95007A00907F99E0FB30E5027A01907F99E038
+:100CA500FB30E603430202907F9AE0FB30E7034303
+:100CB5000204907F9BE0FB30E503430208907F9A96
+:100CC500E0FB53037F8A04E4FAFDEB4AF582ED4C21
+:100CD500F58322E582547FF4FA907F97E05AF07409
+:100CE5007F5522FA907F97E04AF02285820A852275
+:100CF5000B85230C2200227A567B021ABAFF011BB0
+:100D0500EA4B70F722752205752300120D67AA823A
+:100D1500AB837C007D00C3EC9AED9B501AC002C0EA
+:100D250003C004C005120CFAD005D004D003D002CC
+:100D35000CBC00E20D80DF22AA82AB837C007D0023
+:100D4500C3EC9AED9B501AC002C003C004C0051243
+:100D55000CFCD005D004D003D0020CBC00E20D8001
+:020D6500DF228B
+:03004300021B009D
+:101B000002011F0002016E0002016F00020170005D
+:101B100002017100020172000201730002017400EF
+:101B200002017500020176000201770002018F00B8
+:101B30000201A7000201A8000201A9000201AA00F7
+:101B40000201AB000201AC000201AD000201AE00D7
+:081B50000201AF000201B00028
+:100D67007A10E4FBFCE58225E0F582E58333F58321
+:100D7700EB33FBEC33FCEB9522F5F0EC95234006C7
+:090D8700FCABF0438201DADD222D
+:0600A200E478FFF6D8FD32
+:100080007900E94400601B7A00900E3E780075927A
+:1000900020E493F2A308B800020592D9F4DAF275CD
+:0200A00092FFCD
+:1000A8007800E84400600A7900759220E4F309D8E2
+:1000B800FC7800E84400600C7900902000E4F0A38C
+:0400C800D8FCD9FA8D
+:0D007300758123120DACE582600302006E62
+:100D900020F71430F6148883A88220F507E6A8838C
+:100DA00075830022E280F7E49322E022758200221C
+:00000001FF

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)