From 3c3f3c42472faa0414a8096133cb9b8a9ab37c86 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Martin=20Schm=C3=B6lzer?= Date: Mon, 20 Jun 2011 19:49:49 +0200 Subject: [PATCH] Add OpenULINK firmware Build requires SDCC, the Small Device C Compiler. --- src/jtag/drivers/OpenULINK/Makefile | 90 +++ src/jtag/drivers/OpenULINK/README | 34 + src/jtag/drivers/OpenULINK/include/common.h | 26 + src/jtag/drivers/OpenULINK/include/delay.h | 34 + src/jtag/drivers/OpenULINK/include/io.h | 125 +++ src/jtag/drivers/OpenULINK/include/jtag.h | 46 ++ src/jtag/drivers/OpenULINK/include/main.h | 26 + src/jtag/drivers/OpenULINK/include/msgtypes.h | 187 +++++ src/jtag/drivers/OpenULINK/include/protocol.h | 33 + .../drivers/OpenULINK/include/reg_ezusb.h | 742 ++++++++++++++++++ .../drivers/OpenULINK/include/shorttypes.h | 41 + src/jtag/drivers/OpenULINK/include/usb.h | 267 +++++++ src/jtag/drivers/OpenULINK/src/USBJmpTb.a51 | 83 ++ src/jtag/drivers/OpenULINK/src/delay.c | 51 ++ src/jtag/drivers/OpenULINK/src/jtag.c | 414 ++++++++++ src/jtag/drivers/OpenULINK/src/main.c | 92 +++ src/jtag/drivers/OpenULINK/src/protocol.c | 212 +++++ src/jtag/drivers/OpenULINK/src/usb.c | 543 +++++++++++++ src/jtag/drivers/OpenULINK/ulink_firmware.hex | 251 ++++++ 19 files changed, 3297 insertions(+) create mode 100644 src/jtag/drivers/OpenULINK/Makefile create mode 100644 src/jtag/drivers/OpenULINK/README create mode 100644 src/jtag/drivers/OpenULINK/include/common.h create mode 100644 src/jtag/drivers/OpenULINK/include/delay.h create mode 100644 src/jtag/drivers/OpenULINK/include/io.h create mode 100644 src/jtag/drivers/OpenULINK/include/jtag.h create mode 100644 src/jtag/drivers/OpenULINK/include/main.h create mode 100644 src/jtag/drivers/OpenULINK/include/msgtypes.h create mode 100644 src/jtag/drivers/OpenULINK/include/protocol.h create mode 100644 src/jtag/drivers/OpenULINK/include/reg_ezusb.h create mode 100644 src/jtag/drivers/OpenULINK/include/shorttypes.h create mode 100644 src/jtag/drivers/OpenULINK/include/usb.h create mode 100644 src/jtag/drivers/OpenULINK/src/USBJmpTb.a51 create mode 100644 src/jtag/drivers/OpenULINK/src/delay.c create mode 100644 src/jtag/drivers/OpenULINK/src/jtag.c create mode 100644 src/jtag/drivers/OpenULINK/src/main.c create mode 100644 src/jtag/drivers/OpenULINK/src/protocol.c create mode 100644 src/jtag/drivers/OpenULINK/src/usb.c create mode 100644 src/jtag/drivers/OpenULINK/ulink_firmware.hex diff --git a/src/jtag/drivers/OpenULINK/Makefile b/src/jtag/drivers/OpenULINK/Makefile new file mode 100644 index 00000000..c0e34350 --- /dev/null +++ b/src/jtag/drivers/OpenULINK/Makefile @@ -0,0 +1,90 @@ +############################################################################ +# Copyright (C) 2011 by Martin Schmoelzer # +# # +# # +# 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 index 00000000..445d7703 --- /dev/null +++ b/src/jtag/drivers/OpenULINK/README @@ -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 index 00000000..f4c966cd --- /dev/null +++ b/src/jtag/drivers/OpenULINK/include/common.h @@ -0,0 +1,26 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 index 00000000..3dfaf352 --- /dev/null +++ b/src/jtag/drivers/OpenULINK/include/delay.h @@ -0,0 +1,34 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 index 00000000..f7119b9a --- /dev/null +++ b/src/jtag/drivers/OpenULINK/include/io.h @@ -0,0 +1,125 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 index 00000000..93ecfb0a --- /dev/null +++ b/src/jtag/drivers/OpenULINK/include/jtag.h @@ -0,0 +1,46 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 index 00000000..08d748c1 --- /dev/null +++ b/src/jtag/drivers/OpenULINK/include/main.h @@ -0,0 +1,26 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 index 00000000..e3afb670 --- /dev/null +++ b/src/jtag/drivers/OpenULINK/include/msgtypes.h @@ -0,0 +1,187 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 index 00000000..2129fc84 --- /dev/null +++ b/src/jtag/drivers/OpenULINK/include/protocol.h @@ -0,0 +1,33 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 + +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 index 00000000..26ee0186 --- /dev/null +++ b/src/jtag/drivers/OpenULINK/include/reg_ezusb.h @@ -0,0 +1,742 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 + +/* 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 index 00000000..60b37df3 --- /dev/null +++ b/src/jtag/drivers/OpenULINK/include/shorttypes.h @@ -0,0 +1,41 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 + +/** + * @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 index 00000000..f70819ea --- /dev/null +++ b/src/jtag/drivers/OpenULINK/include/usb.h @@ -0,0 +1,267 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 + +#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 index 00000000..6f774dda --- /dev/null +++ b/src/jtag/drivers/OpenULINK/src/USBJmpTb.a51 @@ -0,0 +1,83 @@ +;--------------------------------------------------------------------------; +; Copyright (C) 2011 by Martin Schmoelzer ; +; ; +; ; +; 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 index 00000000..5b7d0eb4 --- /dev/null +++ b/src/jtag/drivers/OpenULINK/src/delay.c @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 index 00000000..cf126ed2 --- /dev/null +++ b/src/jtag/drivers/OpenULINK/src/jtag.c @@ -0,0 +1,414 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 + +/** 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 index 00000000..3ea3fff1 --- /dev/null +++ b/src/jtag/drivers/OpenULINK/src/main.c @@ -0,0 +1,92 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 index 00000000..05929d0f --- /dev/null +++ b/src/jtag/drivers/OpenULINK/src/protocol.c @@ -0,0 +1,212 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 index 00000000..b74b3a29 --- /dev/null +++ b/src/jtag/drivers/OpenULINK/src/usb.c @@ -0,0 +1,543 @@ +/*************************************************************************** + * Copyright (C) 2011 by Martin Schmoelzer * + * * + * * + * 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 index 00000000..9e744237 --- /dev/null +++ b/src/jtag/drivers/OpenULINK/ulink_firmware.hex @@ -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 -- 2.39.5