Build requires SDCC, the Small Device C Compiler.tags/v0.5.0-rc1
@@ -0,0 +1,90 @@ | |||
############################################################################ | |||
# Copyright (C) 2011 by Martin Schmoelzer # | |||
# <martin.schmoelzer@student.tuwien.ac.at> # | |||
# # | |||
# This program is free software; you can redistribute it and/or modify # | |||
# it under the terms of the GNU General Public License as published by # | |||
# the Free Software Foundation; either version 2 of the License, or # | |||
# (at your option) any later version. # | |||
# # | |||
# This program is distributed in the hope that it will be useful, # | |||
# but WITHOUT ANY WARRANTY; without even the implied warranty of # | |||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |||
# GNU General Public License for more details. # | |||
# # | |||
# You should have received a copy of the GNU General Public License # | |||
# along with this program; if not, write to the # | |||
# Free Software Foundation, Inc., # | |||
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # | |||
############################################################################ | |||
# Define the name of our tools. Some distributions (e. g. Fedora) prefix | |||
# the SDCC executables, change this accordingly! | |||
PREFIX = | |||
# Small Device C Compiler: http://sdcc.sourceforge.net/ | |||
CC = $(PREFIX)-sdcc | |||
# 8051 assembler, part of the SDCC software package. | |||
AS = $(PREFIX)-sdas8051 | |||
# SDCC produces quite messy Intel HEX files. This tool is be used to re-format | |||
# those files. It is not required for the firmware download functionality in | |||
# the OpenOCD driver, but the resulting file is smaller. | |||
PACKIHX = $(PREFIX)-packihx | |||
# GNU binutils size. Used to print the size of the IHX file generated by SDCC. | |||
SIZE = size | |||
# Source and header directories. | |||
SRC_DIR = src | |||
INCLUDE_DIR = include | |||
CODE_SIZE = 0x1B00 | |||
# Starting address of __xdata variables. Since the OpenULINK firmware does not | |||
# use any of the isochronous interrupts, we can use the isochronous buffer space | |||
# as XDATA memory. | |||
XRAM_LOC = 0x2000 | |||
XRAM_SIZE = 0x0800 | |||
CFLAGS = --std-sdcc99 --opt-code-size --model-small | |||
LDFLAGS = --code-loc 0x0000 --code-size $(CODE_SIZE) --xram-loc $(XRAM_LOC) \ | |||
--xram-size $(XRAM_SIZE) --iram-size 256 --model-small | |||
# list of base object files | |||
OBJECTS = main.rel usb.rel protocol.rel jtag.rel delay.rel USBJmpTb.rel | |||
HEADERS = $(INCLUDE_DIR)/main.h \ | |||
$(INCLUDE_DIR)/usb.h \ | |||
$(INCLUDE_DIR)/protocol.h \ | |||
$(INCLUDE_DIR)/jtag.h \ | |||
$(INCLUDE_DIR)/delay.h \ | |||
$(INCLUDE_DIR)/reg_ezusb.h \ | |||
$(INCLUDE_DIR)/io.h \ | |||
$(INCLUDE_DIR)/msgtypes.h \ | |||
$(INCLUDE_DIR)/shorttypes.h | |||
# Disable all built-in rules. | |||
.SUFFIXES: | |||
# Targets which are executed even when identically named file is present. | |||
.PHONY: all, clean | |||
all: ulink_firmware.ihx | |||
$(SIZE) ulink_firmware.ihx | |||
ulink_firmware.ihx: $(OBJECTS) | |||
$(CC) -mmcs51 $(LDFLAGS) -o $@ $^ | |||
# Rebuild every C module (there are only 5 of them) if any header changes. | |||
%.rel: $(SRC_DIR)/%.c $(HEADERS) | |||
$(CC) -c $(CFLAGS) -mmcs51 -I$(INCLUDE_DIR) -o $@ $< | |||
%.rel: $(SRC_DIR)/%.a51 | |||
$(AS) -lsgo $@ $< | |||
clean: | |||
rm -f *.asm *.lst *.rel *.rst *.sym *.ihx *.lnk *.map *.mem | |||
hex: ulink_firmware.ihx | |||
$(PACKIHX) ulink_firmware.ihx > ulink_firmware.hex |
@@ -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. |
@@ -0,0 +1,26 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef __COMMON_H | |||
#define __COMMON_H | |||
#define DIV_ROUND_UP(m, n) (((m) + (n) - 1) / (n)) | |||
#endif |
@@ -0,0 +1,34 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef __DELAY_H | |||
#define __DELAY_H | |||
#include "shorttypes.h" | |||
#define NOP {__asm nop __endasm;} | |||
void delay_5us(void); | |||
void delay_1ms(void); | |||
void delay_us(u16 delay); | |||
void delay_ms(u16 delay); | |||
#endif |
@@ -0,0 +1,125 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef __IO_H | |||
#define __IO_H | |||
#include "reg_ezusb.h" | |||
/*************************************************************************** | |||
* JTAG Signals: * | |||
*************************************************************************** | |||
* TMS ....... Test Mode Select * | |||
* TCK ....... Test Clock * | |||
* TDI ....... Test Data Input (from device point of view, not JTAG * | |||
* adapter point of view!) * | |||
* TDO ....... Test Data Output (from device point of view, not JTAG * | |||
* adapter point of view!) * | |||
* TRST ...... Test Reset: Used to reset the TAP Finite State Machine * | |||
* into the Test Logic Reset state * | |||
* RTCK ...... Return Test Clock * | |||
* OCDSE ..... Enable/Disable OCDS interface (Infineon specific) - shared * | |||
* with /JEN * | |||
* TRAP ...... Trap Condition (Infineon specific) - shared with TSTAT * | |||
* BRKIN ..... Hardware Break-In (Infineon specific) * | |||
* BRKOUT .... Hardware Break-Out (Infineon specific) * | |||
* /JEN ...... JTAG-Enable (STMicroelectronics specific) - shared * | |||
* with OCDSE * | |||
* TSTAT ..... JTAG ISP Status (STMicroelectronics specific) - shared * | |||
* with TRAP * | |||
* RESET ..... Chip Reset (STMicroelectronics specific) * | |||
* /TERR ..... JTAG ISP Error (STMicroelectronics specific) - shared * | |||
* with BRKOUT * | |||
***************************************************************************/ | |||
/* PORT A */ | |||
#define PIN_U_OE OUTA0 | |||
// PA1 Not Connected | |||
#define PIN_OE OUTA2 | |||
// PA3 Not Connected | |||
#define PIN_RUN_LED OUTA4 | |||
#define PIN_TDO PINA5 | |||
#define PIN_BRKOUT PINA6 | |||
#define PIN_COM_LED OUTA7 | |||
/* PORT B */ | |||
#define PIN_TDI OUTB0 | |||
#define PIN_TMS OUTB1 | |||
#define PIN_TCK OUTB2 | |||
#define PIN_TRST OUTB3 | |||
#define PIN_BRKIN OUTB4 | |||
#define PIN_RESET OUTB5 | |||
#define PIN_OCDSE OUTB6 | |||
#define PIN_TRAP PINB7 | |||
/* JTAG Signals with direction 'OUT' on port B */ | |||
#define MASK_PORTB_DIRECTION_OUT (PIN_TDI | PIN_TMS | PIN_TCK | PIN_TRST | PIN_BRKIN | PIN_RESET | PIN_OCDSE) | |||
/* PORT C */ | |||
#define PIN_RXD0 PINC0 | |||
#define PIN_TXD0 OUTC1 | |||
#define PIN_RESET_2 PINC2 | |||
// PC3 Not Connected | |||
// PC4 Not Connected | |||
#define PIN_RTCK PINC5 | |||
#define PIN_WR OUTC6 | |||
// PC7 Not Connected | |||
/* LED Macros */ | |||
#define SET_RUN_LED() OUTA &= ~PIN_RUN_LED | |||
#define CLEAR_RUN_LED() OUTA |= PIN_RUN_LED | |||
#define SET_COM_LED() OUTA &= ~PIN_COM_LED | |||
#define CLEAR_COM_LED() OUTA |= PIN_COM_LED | |||
/* JTAG Pin Macros */ | |||
#define GET_TMS() (PINSB & PIN_TMS) | |||
#define GET_TCK() (PINSB & PIN_TCK) | |||
#define GET_TDO() (PINSA & PIN_TDO) | |||
#define GET_BRKOUT() (PINSA & PIN_BRKOUT) | |||
#define GET_TRAP() (PINSB & PIN_TRAP) | |||
#define GET_RTCK() (PINSC & PIN_RTCK) | |||
#define SET_TMS_HIGH() OUTB |= PIN_TMS | |||
#define SET_TMS_LOW() OUTB &= ~PIN_TMS | |||
#define SET_TCK_HIGH() OUTB |= PIN_TCK | |||
#define SET_TCK_LOW() OUTB &= ~PIN_TCK | |||
#define SET_TDI_HIGH() OUTB |= PIN_TDI | |||
#define SET_TDI_LOW() OUTB &= ~PIN_TDI | |||
/* TRST and RESET are low-active and inverted by hardware. SET_HIGH de-asserts | |||
* the signal (enabling reset), SET_LOW asserts the signal (disabling reset) */ | |||
#define SET_TRST_HIGH() OUTB |= PIN_TRST | |||
#define SET_TRST_LOW() OUTB &= ~PIN_TRST | |||
#define SET_RESET_HIGH() OUTB |= PIN_RESET | |||
#define SET_RESET_LOW() OUTB &= ~PIN_RESET | |||
#define SET_OCDSE_HIGH() OUTB |= PIN_OCDSE | |||
#define SET_OCDSE_LOW() OUTB &= ~PIN_OCDSE | |||
#define SET_BRKIN_HIGH() OUTB |= PIN_BRKIN | |||
#define SET_BRKIN_LOW() OUTB &= ~PIN_BRKIN | |||
#endif |
@@ -0,0 +1,46 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef __JTAG_H | |||
#define __JTAG_H | |||
#include "shorttypes.h" | |||
#define NOP {__asm nop __endasm;} | |||
void jtag_scan_in(u8 out_offset, u8 in_offset); | |||
void jtag_scan_out(u8 out_offset); | |||
void jtag_scan_io(u8 out_offset, u8 in_offset); | |||
void jtag_slow_scan_in(u8 scan_size_bytes, u8 tdo_index, u8 scan_options); | |||
void jtag_slow_scan_out(u8 scan_size_bytes, u8 tdi_index, u8 scan_options); | |||
void jtag_slow_scan_io(u8 scan_size_bytes, u8 tdi_index, u8 tdo_index, | |||
u8 scan_options); | |||
void jtag_clock_tck(u16 count); | |||
void jtag_clock_tms(u8 count, u8 sequence); | |||
void jtag_slow_clock_tms(u8 count, u8 sequence); | |||
u16 jtag_get_signals(void); | |||
void jtag_set_signals(u8 low, u8 high); | |||
void jtag_configure_tck_delay(u8 scan, u8 tck, u8 tms); | |||
#endif |
@@ -0,0 +1,26 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef __MAIN_H | |||
#define __MAIN_H | |||
void io_init(void); | |||
#endif |
@@ -0,0 +1,187 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
/** | |||
* @file Definition of the commands supported by the OpenULINK firmware. | |||
* | |||
* Basically, two types of commands can be distinguished: | |||
* - Commands with fixed payload size | |||
* - Commands with variable payload size | |||
* | |||
* SCAN commands (in all variations) carry payloads of variable size, all | |||
* other commands carry payloads of fixed size. | |||
* | |||
* In the case of SCAN commands, the payload size (n) is calculated by | |||
* dividing the scan_size_bits variable by 8, rounding up the result. | |||
* | |||
* Offset zero always contains the command ID. | |||
* | |||
**************************************************************************** | |||
* CMD_SCAN_IN, CMD_SLOW_SCAN_IN: * | |||
* * | |||
* OUT: * | |||
* offset 1: scan_size_bytes * | |||
* offset 2: bits_last_byte * | |||
* offset 3: tms_count_start + tms_count_end * | |||
* offset 4: tms_sequence_start * | |||
* offset 5: tms_sequence_end * | |||
* * | |||
* IN: * | |||
* offset 0..n: TDO data * | |||
**************************************************************************** | |||
* CMD_SCAN_OUT, CMD_SLOW_SCAN_OUT: * | |||
* * | |||
* OUT: * | |||
* offset 1: scan_size_bytes * | |||
* offset 2: bits_last_byte * | |||
* offset 3: tms_count_start + tms_count_end * | |||
* offset 4: tms_sequence_start * | |||
* offset 5: tms_sequence_end * | |||
* offset 6..x: TDI data * | |||
**************************************************************************** | |||
* CMD_SCAN_IO, CMD_SLOW_SCAN_IO: * | |||
* * | |||
* OUT: * | |||
* offset 1: scan_size_bytes * | |||
* offset 2: bits_last_byte * | |||
* offset 3: tms_count_start + tms_count_end * | |||
* offset 4: tms_sequence_start * | |||
* offset 5: tms_sequence_end * | |||
* offset 6..x: TDI data * | |||
* * | |||
* IN: * | |||
* offset 0..n: TDO data * | |||
**************************************************************************** | |||
* CMD_CLOCK_TMS, CMD_SLOW_CLOCK_TMS: * | |||
* * | |||
* OUT: * | |||
* offset 1: tms_count * | |||
* offset 2: tms_sequence * | |||
**************************************************************************** | |||
* CMD_CLOCK_TCK: * | |||
* * | |||
* OUT: * | |||
* offset 1: low byte of tck_count * | |||
* offset 2: high byte of tck_count * | |||
**************************************************************************** | |||
* CMD_CLOCK_SLEEP_US: * | |||
* * | |||
* OUT: * | |||
* offset 1: low byte of sleep_us * | |||
* offset 2: high byte of sleep_us * | |||
**************************************************************************** | |||
* CMD_CLOCK_SLEEP_MS: * | |||
* * | |||
* OUT: * | |||
* offset 1: low byte of sleep_ms * | |||
* offset 2: high byte of sleep_ms * | |||
**************************************************************************** | |||
* CMD_GET_SIGNALS: * | |||
* * | |||
* IN: * | |||
* offset 0: current state of input signals * | |||
* offset 1: current state of output signals * | |||
**************************************************************************** | |||
* CMD_SET_SIGNALS: * | |||
* * | |||
* OUT: * | |||
* offset 1: signals that should be de-asserted * | |||
* offset 2: signals that should be asserted * | |||
**************************************************************************** | |||
* CMD_CONFIGURE_TCK_FREQ: * | |||
* * | |||
* OUT: * | |||
* offset 1: delay value for scan functions * | |||
* offset 2: delay value for clock_tck function * | |||
* offset 3: delay value for clock_tms function * | |||
**************************************************************************** | |||
* CMD_SET_LEDS: * | |||
* * | |||
* OUT: * | |||
* offset 1: LED states: * | |||
* Bit 0: turn COM LED on * | |||
* Bit 1: turn RUN LED on * | |||
* Bit 2: turn COM LED off * | |||
* Bit 3: turn RUN LED off * | |||
* Bits 7..4: Reserved * | |||
**************************************************************************** | |||
* CMD_TEST: * | |||
* * | |||
* OUT: * | |||
* offset 1: unused dummy value * | |||
**************************************************************************** | |||
*/ | |||
#ifndef __MSGTYPES_H | |||
#define __MSGTYPES_H | |||
/* | |||
* Command IDs: | |||
* | |||
* Bits 7..6: Reserved, should always be zero | |||
* Bits 5..0: Command ID. There are 62 usable IDs. Of this 63 available IDs, | |||
* the IDs 0x00..0x1F are commands with variable payload size, | |||
* the IDs 0x20..0x3F are commands with fixed payload size. | |||
*/ | |||
#define CMD_ID_MASK 0x3F | |||
/* Commands with variable payload size */ | |||
#define CMD_SCAN_IN 0x00 | |||
#define CMD_SLOW_SCAN_IN 0x01 | |||
#define CMD_SCAN_OUT 0x02 | |||
#define CMD_SLOW_SCAN_OUT 0x03 | |||
#define CMD_SCAN_IO 0x04 | |||
#define CMD_SLOW_SCAN_IO 0x05 | |||
/* Commands with fixed payload size */ | |||
#define CMD_CLOCK_TMS 0x20 | |||
#define CMD_SLOW_CLOCK_TMS 0x21 | |||
#define CMD_CLOCK_TCK 0x22 | |||
#define CMD_SLEEP_US 0x23 | |||
#define CMD_SLEEP_MS 0x24 | |||
#define CMD_GET_SIGNALS 0x25 | |||
#define CMD_SET_SIGNALS 0x26 | |||
#define CMD_CONFIGURE_TCK_FREQ 0x27 | |||
#define CMD_SET_LEDS 0x28 | |||
#define CMD_TEST 0x29 | |||
/* JTAG signal definition for jtag_get_signals() -- Input signals! */ | |||
#define SIGNAL_TDO (1<<0) | |||
#define SIGNAL_BRKOUT (1<<1) | |||
#define SIGNAL_TRAP (1<<2) | |||
#define SIGNAL_RTCK (1<<3) | |||
/* JTAG signal definition for jtag_get_signals() -- Output signals! */ | |||
#define SIGNAL_TDI (1<<0) | |||
#define SIGNAL_TMS (1<<1) | |||
#define SIGNAL_TCK (1<<2) | |||
#define SIGNAL_TRST (1<<3) | |||
#define SIGNAL_BRKIN (1<<4) | |||
#define SIGNAL_RESET (1<<5) | |||
#define SIGNAL_OCDSE (1<<6) | |||
/* LED definitions for CMD_SET_LEDS and CMD_CLEAR_LEDS commands */ | |||
#define COM_LED_ON (1<<0) | |||
#define RUN_LED_ON (1<<1) | |||
#define COM_LED_OFF (1<<2) | |||
#define RUN_LED_OFF (1<<3) | |||
#endif |
@@ -0,0 +1,33 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef __PROTOCOL_H | |||
#define __PROTOCOL_H | |||
#include "shorttypes.h" | |||
#include "common.h" | |||
#include <stdbool.h> | |||
void execute_set_led_command(void); | |||
bool execute_command(void); | |||
void command_loop(void); | |||
#endif |
@@ -0,0 +1,742 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef REG_EZUSB_H | |||
#define REG_EZUSB_H | |||
/** | |||
* @file All information in this file was taken from the EZ-USB Technical | |||
* Reference Manual, Cypress Semiconductor, 3901 North First Street | |||
* San Jose, CA 95134 (www.cypress.com). | |||
* | |||
* The EZ-USB Technical Reference Manual is called "EZ-USB TRM" hereafter. | |||
* | |||
* The following bit name definitions differ from those in the EZ-USB TRM: | |||
* - All lowercase characters in the EZ-USB TRM bit names have been converted | |||
* to capitals (e. g. "WakeSRC" converted to "WAKESRC"). | |||
* - CPUCS: 8051RES is named "RES8051". | |||
* - ISOCTL: Two MBZ ("Must Be Zero") bits are named "MBZ0" and "MBZ1". | |||
* - I2CS: STOP and START bits are preceded by "I2C_" | |||
* - INxCS, OUTxCS: the busy and stall bits are named "EPBSY" and "EPSTALL". | |||
* - TOGCTL: EZ-USB TRM bit names are preceded by "TOG_". | |||
*/ | |||
/* Compiler-specific definitions of SBIT, SFR, SFRX, ... macros */ | |||
#include <mcs51/compiler.h> | |||
/* Bit vectors */ | |||
#define bmBit0 0x01 | |||
#define bmBit1 0x02 | |||
#define bmBit2 0x04 | |||
#define bmBit3 0x08 | |||
#define bmBit4 0x10 | |||
#define bmBit5 0x20 | |||
#define bmBit6 0x40 | |||
#define bmBit7 0x80 | |||
/***************************************************************************/ | |||
/************************ Special Function Registers ***********************/ | |||
/***************************************************************************/ | |||
/* See EZ-USB TRM, pp. A-9 - A-10 */ | |||
SFR(SP, 0x81); | |||
SFR(DPL0, 0x82); | |||
SFR(DPH0, 0x83); | |||
SFR(DPL1, 0x84); | |||
SFR(DPL2, 0x85); | |||
SFR(DPS, 0x86); | |||
#define SEL bmBit0 | |||
// Bit 1 read-only, always reads '0' | |||
// Bit 2 read-only, always reads '0' | |||
// Bit 3 read-only, always reads '0' | |||
// Bit 4 read-only, always reads '0' | |||
// Bit 5 read-only, always reads '0' | |||
// Bit 6 read-only, always reads '0' | |||
// Bit 7 read-only, always reads '0' | |||
SFR(PCON, 0x87); | |||
#define IDLE bmBit0 | |||
#define STOP bmBit1 | |||
#define GF0 bmBit2 | |||
#define GF1 bmBit3 | |||
// Bit 4 read-only, always reads '1' | |||
// Bit 5 read-only, always reads '1' | |||
// Bit 6 unused | |||
#define SMOD0 bmBit7 | |||
SFR(TCON, 0x88); | |||
SBIT(IT0, 0x88, 0); | |||
SBIT(IE0, 0x88, 1); | |||
SBIT(IT1, 0x88, 2); | |||
SBIT(IE1, 0x88, 3); | |||
SBIT(TR0, 0x88, 4); | |||
SBIT(TF0, 0x88, 5); | |||
SBIT(TR1, 0x88, 6); | |||
SBIT(TF1, 0x88, 7); | |||
SFR(TMOD, 0x89); | |||
/* Some bits in this register share the same name in the EZ-USB TRM. Therefore, | |||
* we add a '0'/'1' to distinguish them */ | |||
#define M00 bmBit0 | |||
#define M01 bmBit1 | |||
#define CT0 bmBit2 | |||
#define GATE0 bmBit3 | |||
#define M10 bmBit4 | |||
#define M11 bmBit5 | |||
#define CT1 bmBit6 | |||
#define GATE1 bmBit7 | |||
SFR(TL0, 0x8A); | |||
SFR(TL1, 0x8B); | |||
SFR(TH0, 0x8C); | |||
SFR(TH1, 0x8D); | |||
SFR(CKCON, 0x8E); | |||
#define MD0 bmBit0 | |||
#define MD1 bmBit1 | |||
#define MD2 bmBit2 | |||
#define T0M bmBit3 | |||
#define T1M bmBit4 | |||
#define T2M bmBit5 | |||
// Bit 6 unused | |||
// Bit 7 unused | |||
SFR(SPC_FNC, 0x8D); | |||
#define bmWRS bmBit0 | |||
// Bit 1 read-only, always reads '0' | |||
// Bit 2 read-only, always reads '0' | |||
// Bit 3 read-only, always reads '0' | |||
// Bit 4 read-only, always reads '0' | |||
// Bit 5 read-only, always reads '0' | |||
// Bit 6 read-only, always reads '0' | |||
// Bit 7 read-only, always reads '0' | |||
SFR(EXIF, 0x91); | |||
// Bit 0 read-only, always reads '0' | |||
// Bit 1 read-only, always reads '0' | |||
// Bit 2 read-only, always reads '0' | |||
// Bit 3 read-only, always reads '1' | |||
#define USBINT bmBit4 | |||
#define I2CINT bmBit5 | |||
#define IE4 bmBit6 | |||
#define IE5 bmBit7 | |||
/* Definition of the _XPAGE register, according to SDCC Compiler User Guide, | |||
* Version 3.0.1, Chapter 4, p. 61. Also see EZ-USB TRM, p. 2-4. */ | |||
SFR(MPAGE, 0x92); | |||
SFR(_XPAGE, 0x92); | |||
SFR(SCON0, 0x98); | |||
SBIT(RI_0, 0x98, 0); | |||
SBIT(TI_0, 0x98, 1); | |||
SBIT(RB8_0, 0x98, 2); | |||
SBIT(TB8_0, 0x98, 3); | |||
SBIT(REN_0, 0x98, 4); | |||
SBIT(SM2_0, 0x98, 5); | |||
SBIT(SM1_0, 0x98, 6); | |||
SBIT(SM0_0, 0x98, 7); | |||
SFR(SBUF0, 0x99); | |||
SFR(IE, 0xA8); | |||
SBIT(EX0, 0xA8, 0); | |||
SBIT(ET0, 0xA8, 1); | |||
SBIT(EX1, 0xA8, 2); | |||
SBIT(ET1, 0xA8, 3); | |||
SBIT(ES0, 0xA8, 4); | |||
SBIT(ET2, 0xA8, 5); | |||
SBIT(ES1, 0xA8, 6); | |||
SBIT(EA, 0xA8, 7); | |||
SFR(IP, 0xB8); | |||
SBIT(PX0, 0xB8, 0); | |||
SBIT(PT0, 0xB8, 1); | |||
SBIT(PX1, 0xB8, 2); | |||
SBIT(PT1, 0xB8, 3); | |||
SBIT(PS0, 0xB8, 4); | |||
SBIT(PT2, 0xB8, 5); | |||
SBIT(PS1, 0xB8, 6); | |||
// Bit 7 read-only, always reads '1' | |||
SFR(SCON1, 0xC0); | |||
SBIT(RI_1, 0xC0, 0); | |||
SBIT(TI_1, 0xC0, 1); | |||
SBIT(RB8_1, 0xC0, 2); | |||
SBIT(TB8_1, 0xC0, 3); | |||
SBIT(REN_1, 0xC0, 4); | |||
SBIT(SM2_1, 0xC0, 5); | |||
SBIT(SM1_1, 0xC0, 6); | |||
SBIT(SM0_1, 0xC0, 7); | |||
SFR(SBUF1, 0xC1); | |||
SFR(T2CON, 0xC8); | |||
SBIT(CPRL2, 0xC8, 0); | |||
SBIT(CT2, 0xC8, 1); | |||
SBIT(TR2, 0xC8, 2); | |||
SBIT(EXEN2, 0xC8, 3); | |||
SBIT(TCLK, 0xC8, 4); | |||
SBIT(RCLK, 0xC8, 5); | |||
SBIT(EXF2, 0xC8, 6); | |||
SBIT(TF2, 0xC8, 7); | |||
SFR(RCAP2L, 0xCA); | |||
SFR(RCAP2H, 0xCB); | |||
SFR(TL2, 0xCC); | |||
SFR(TH2, 0xCD); | |||
SFR(PSW, 0xD0); | |||
SBIT(P, 0xD0, 0); | |||
SBIT(F1, 0xD0, 1); | |||
SBIT(OV, 0xD0, 2); | |||
SBIT(RS0, 0xD0, 3); | |||
SBIT(RS1, 0xD0, 4); | |||
SBIT(F0, 0xD0, 5); | |||
SBIT(AC, 0xD0, 6); | |||
SBIT(CY, 0xD0, 7); | |||
SFR(EICON, 0xD8); | |||
// Bit 0 read-only, always reads '0' | |||
// Bit 1 read-only, always reads '0' | |||
// Bit 2 read-only, always reads '0' | |||
SBIT(INT6, 0xD8, 3); | |||
SBIT(RESI, 0xD8, 4); | |||
SBIT(ERESI, 0xD8, 5); | |||
// Bit 6 read-only, always reads '1' | |||
SBIT(SMOD1, 0xD8, 7); | |||
SFR(ACC, 0xE0); | |||
SFR(EIE, 0xE8); | |||
SBIT(EUSB, 0xE8, 0); | |||
SBIT(EI2C, 0xE8, 1); | |||
SBIT(EX4, 0xE8, 2); | |||
SBIT(EX5, 0xE8, 3); | |||
SBIT(EWDI, 0xE8, 4); | |||
// Bit 5 read-only, always reads '1' | |||
// Bit 6 read-only, always reads '1' | |||
// Bit 7 read-only, always reads '1' | |||
SFR(B, 0xF0); | |||
SFR(EIP, 0xF8); | |||
SBIT(PUSB, 0xF8, 0); | |||
SBIT(PI2C, 0xF8, 1); | |||
SBIT(PX4, 0xF8, 2); | |||
SBIT(PX5, 0xF8, 3); | |||
SBIT(PX6, 0xF8, 4); | |||
// Bit 5 read-only, always reads '1' | |||
// Bit 6 read-only, always reads '1' | |||
// Bit 7 read-only, always reads '1' | |||
/***************************************************************************/ | |||
/***************************** XDATA Registers *****************************/ | |||
/***************************************************************************/ | |||
/************************ Endpoint 0-7 Data Buffers ************************/ | |||
SFRX(OUT7BUF[64], 0x7B40); | |||
SFRX(IN7BUF[64], 0x7B80); | |||
SFRX(OUT6BUF[64], 0x7BC0); | |||
SFRX(IN6BUF[64], 0x7C00); | |||
SFRX(OUT5BUF[64], 0x7C40); | |||
SFRX(IN5BUF[64], 0x7C80); | |||
SFRX(OUT4BUF[64], 0x7CC0); | |||
SFRX(IN4BUF[64], 0x7D00); | |||
SFRX(OUT3BUF[64], 0x7D40); | |||
SFRX(IN3BUF[64], 0x7D80); | |||
SFRX(OUT2BUF[64], 0x7DC0); | |||
SFRX(IN2BUF[64], 0x7E00); | |||
SFRX(OUT1BUF[64], 0x7E40); | |||
SFRX(IN1BUF[64], 0x7E80); | |||
SFRX(OUT0BUF[64], 0x7EC0); | |||
SFRX(IN0BUF[64], 0x7F00); | |||
// 0x7F40 - 0x7F5F reserved | |||
/**************************** Isochronous Data *****************************/ | |||
SFRX(OUT8DATA, 0x7F60); | |||
SFRX(OUT9DATA, 0x7F61); | |||
SFRX(OUT10DATA, 0x7F62); | |||
SFRX(OUT11DATA, 0x7F63); | |||
SFRX(OUT12DATA, 0x7F64); | |||
SFRX(OUT13DATA, 0x7F65); | |||
SFRX(OUT14DATA, 0x7F66); | |||
SFRX(OUT15DATA, 0x7F67); | |||
SFRX(IN8DATA, 0x7F68); | |||
SFRX(IN9DATA, 0x7F69); | |||
SFRX(IN10DATA, 0x7F6A); | |||
SFRX(IN11DATA, 0x7F6B); | |||
SFRX(IN12DATA, 0x7F6C); | |||
SFRX(IN13DATA, 0x7F6D); | |||
SFRX(IN14DATA, 0x7F6E); | |||
SFRX(IN15DATA, 0x7F6F); | |||
/************************* Isochronous Byte Counts *************************/ | |||
SFRX(OUT8BCH, 0x7F70); | |||
SFRX(OUT8BCL, 0x7F71); | |||
SFRX(OUT9BCH, 0x7F72); | |||
SFRX(OUT9BCL, 0x7F73); | |||
SFRX(OUT10BCH, 0x7F74); | |||
SFRX(OUT10BCL, 0x7F75); | |||
SFRX(OUT11BCH, 0x7F76); | |||
SFRX(OUT11BCL, 0x7F77); | |||
SFRX(OUT12BCH, 0x7F78); | |||
SFRX(OUT12BCL, 0x7F79); | |||
SFRX(OUT13BCH, 0x7F7A); | |||
SFRX(OUT13BCL, 0x7F7B); | |||
SFRX(OUT14BCH, 0x7F7C); | |||
SFRX(OUT14BCL, 0x7F7D); | |||
SFRX(OUT15BCH, 0x7F7E); | |||
SFRX(OUT16BCL, 0x7F7F); | |||
/****************************** CPU Registers ******************************/ | |||
SFRX(CPUCS, 0x7F92); | |||
#define RES8051 bmBit0 | |||
#define CLK24OE bmBit1 | |||
// Bit 2 read-only, always reads '0' | |||
// Bit 3 read-only, always reads '0' | |||
// Bits 4...7: Chip Revision | |||
SFRX(PORTACFG, 0x7F93); | |||
#define T0OUT bmBit0 | |||
#define T1OUT bmBit1 | |||
#define OE bmBit2 | |||
#define CS bmBit3 | |||
#define FWR bmBit4 | |||
#define FRD bmBit5 | |||
#define RXD0OUT bmBit6 | |||
#define RXD1OUT bmBit7 | |||
SFRX(PORTBCFG, 0x7F94); | |||
#define T2 bmBit0 | |||
#define T2EX bmBit1 | |||
#define RXD1 bmBit2 | |||
#define TXD1 bmBit3 | |||
#define INT4 bmBit4 | |||
#define INT5 bmBit5 | |||
#define INT6 bmBit6 | |||
#define T2OUT bmBit7 | |||
SFRX(PORTCCFG, 0x7F95); | |||
#define RXD0 bmBit0 | |||
#define TXD0 bmBit1 | |||
#define INT0 bmBit2 | |||
#define INT1 bmBit3 | |||
#define T0 bmBit4 | |||
#define T1 bmBit5 | |||
#define WR bmBit6 | |||
#define RD bmBit7 | |||
/*********************** Input-Output Port Registers ***********************/ | |||
SFRX(OUTA, 0x7F96); | |||
#define OUTA0 bmBit0 | |||
#define OUTA1 bmBit1 | |||
#define OUTA2 bmBit2 | |||
#define OUTA3 bmBit3 | |||
#define OUTA4 bmBit4 | |||
#define OUTA5 bmBit5 | |||
#define OUTA6 bmBit6 | |||
#define OUTA7 bmBit7 | |||
SFRX(OUTB, 0x7F97); | |||
#define OUTB0 bmBit0 | |||
#define OUTB1 bmBit1 | |||
#define OUTB2 bmBit2 | |||
#define OUTB3 bmBit3 | |||
#define OUTB4 bmBit4 | |||
#define OUTB5 bmBit5 | |||
#define OUTB6 bmBit6 | |||
#define OUTB7 bmBit7 | |||
SFRX(OUTC, 0x7F98); | |||
#define OUTC0 bmBit0 | |||
#define OUTC1 bmBit1 | |||
#define OUTC2 bmBit2 | |||
#define OUTC3 bmBit3 | |||
#define OUTC4 bmBit4 | |||
#define OUTC5 bmBit5 | |||
#define OUTC6 bmBit6 | |||
#define OUTC7 bmBit7 | |||
SFRX(PINSA, 0x7F99); | |||
#define PINA0 bmBit0 | |||
#define PINA1 bmBit1 | |||
#define PINA2 bmBit2 | |||
#define PINA3 bmBit3 | |||
#define PINA4 bmBit4 | |||
#define PINA5 bmBit5 | |||
#define PINA6 bmBit6 | |||
#define PINA7 bmBit7 | |||
SFRX(PINSB, 0x7F9A); | |||
#define PINB0 bmBit0 | |||
#define PINB1 bmBit1 | |||
#define PINB2 bmBit2 | |||
#define PINB3 bmBit3 | |||
#define PINB4 bmBit4 | |||
#define PINB5 bmBit5 | |||
#define PINB6 bmBit6 | |||
#define PINB7 bmBit7 | |||
SFRX(PINSC, 0x7F9B); | |||
#define PINC0 bmBit0 | |||
#define PINC1 bmBit1 | |||
#define PINC2 bmBit2 | |||
#define PINC3 bmBit3 | |||
#define PINC4 bmBit4 | |||
#define PINC5 bmBit5 | |||
#define PINC6 bmBit6 | |||
#define PINC7 bmBit7 | |||
SFRX(OEA, 0x7F9C); | |||
#define OEA0 bmBit0 | |||
#define OEA1 bmBit1 | |||
#define OEA2 bmBit2 | |||
#define OEA3 bmBit3 | |||
#define OEA4 bmBit4 | |||
#define OEA5 bmBit5 | |||
#define OEA6 bmBit6 | |||
#define OEA7 bmBit7 | |||
SFRX(OEB, 0x7F9D); | |||
#define OEB0 bmBit0 | |||
#define OEB1 bmBit1 | |||
#define OEB2 bmBit2 | |||
#define OEB3 bmBit3 | |||
#define OEB4 bmBit4 | |||
#define OEB5 bmBit5 | |||
#define OEB6 bmBit6 | |||
#define OEB7 bmBit7 | |||
SFRX(OEC, 0x7F9E); | |||
#define OEC0 bmBit0 | |||
#define OEC1 bmBit1 | |||
#define OEC2 bmBit2 | |||
#define OEC3 bmBit3 | |||
#define OEC4 bmBit4 | |||
#define OEC5 bmBit5 | |||
#define OEC6 bmBit6 | |||
#define OEC7 bmBit7 | |||
// 0x7F9F reserved | |||
/****************** Isochronous Control/Status Registers *******************/ | |||
SFRX(ISOERR, 0x7FA0); | |||
#define ISO8ERR bmBit0 | |||
#define ISO9ERR bmBit1 | |||
#define ISO10ERR bmBit2 | |||
#define ISO11ERR bmBit3 | |||
#define ISO12ERR bmBit4 | |||
#define ISO13ERR bmBit5 | |||
#define ISO14ERR bmBit6 | |||
#define ISO15ERR bmBit7 | |||
SFRX(ISOCTL, 0x7FA1); | |||
#define ISODISAB bmBit0 | |||
#define MBZ0 bmBit1 | |||
#define MBZ1 bmBit2 | |||
#define PPSTAT bmBit3 | |||
// Bit 4 unused | |||
// Bit 5 unused | |||
// Bit 6 unused | |||
// Bit 7 unused | |||
SFRX(ZBCOUT, 0x7FA2); | |||
#define EP8 bmBit0 | |||
#define EP9 bmBit1 | |||
#define EP10 bmBit2 | |||
#define EP11 bmBit3 | |||
#define EP12 bmBit4 | |||
#define EP13 bmBit5 | |||
#define EP14 bmBit6 | |||
#define EP15 bmBit7 | |||
// 0x7FA3 reserved | |||
// 0x7FA4 reserved | |||
/****************************** I2C Registers ******************************/ | |||
SFRX(I2CS, 0x7FA5); | |||
#define DONE bmBit0 | |||
#define ACK bmBit1 | |||
#define BERR bmBit2 | |||
#define ID0 bmBit3 | |||
#define ID1 bmBit4 | |||
#define LASTRD bmBit5 | |||
#define I2C_STOP bmBit6 | |||
#define I2C_START bmBit7 | |||
SFRX(I2DAT, 0x7FA6); | |||
// 0x7FA7 reserved | |||
/******************************* Interrupts ********************************/ | |||
SFRX(IVEC, 0x7FA8); | |||
// Bit 0 read-only, always reads '0' | |||
// Bit 1 read-only, always reads '0' | |||
#define IV0 bmBit2 | |||
#define IV1 bmBit3 | |||
#define IV2 bmBit4 | |||
#define IV3 bmBit5 | |||
#define IV4 bmBit6 | |||
// Bit 7 read-only, always reads '0' | |||
SFRX(IN07IRQ, 0x7FA9); | |||
#define IN0IR bmBit0 | |||
#define IN1IR bmBit1 | |||
#define IN2IR bmBit2 | |||
#define IN3IR bmBit3 | |||
#define IN4IR bmBit4 | |||
#define IN5IR bmBit5 | |||
#define IN6IR bmBit6 | |||
#define IN7IR bmBit7 | |||
SFRX(OUT07IRQ, 0x7FAA); | |||
#define OUT0IR bmBit0 | |||
#define OUT1IR bmBit1 | |||
#define OUT2IR bmBit2 | |||
#define OUT3IR bmBit3 | |||
#define OUT4IR bmBit4 | |||
#define OUT5IR bmBit5 | |||
#define OUT6IR bmBit6 | |||
#define OUT7IR bmBit7 | |||
SFRX(USBIRQ, 0x7FAB); | |||
#define SUDAVIR bmBit0 | |||
#define SOFIR bmBit1 | |||
#define SUTOKIR bmBit2 | |||
#define SUSPIR bmBit3 | |||
#define URESIR bmBit4 | |||
// Bit 5 unused | |||
// Bit 6 unused | |||
// Bit 7 unused | |||
SFRX(IN07IEN, 0x7FAC); | |||
#define IN0IEN bmBit0 | |||
#define IN1IEN bmBit1 | |||
#define IN2IEN bmBit2 | |||
#define IN3IEN bmBit3 | |||
#define IN4IEN bmBit4 | |||
#define IN5IEN bmBit5 | |||
#define IN6IEN bmBit6 | |||
#define IN7IEN bmBit7 | |||
SFRX(OUT07IEN, 0x7FAD); | |||
#define OUT0IEN bmBit0 | |||
#define OUT1IEN bmBit1 | |||
#define OUT2IEN bmBit2 | |||
#define OUT3IEN bmBit3 | |||
#define OUT4IEN bmBit4 | |||
#define OUT5IEN bmBit5 | |||
#define OUT6IEN bmBit6 | |||
#define OUT7IEN bmBit7 | |||
SFRX(USBIEN, 0x7FAE); | |||
#define SUDAVIE bmBit0 | |||
#define SOFIE bmBit1 | |||
#define SUTOKIE bmBit2 | |||
#define SUSPIE bmBit3 | |||
#define URESIE bmBit4 | |||
// Bit 5 unused | |||
// Bit 6 unused | |||
// Bit 7 unused | |||
SFRX(USBBAV, 0x7FAF); | |||
#define AVEN bmBit0 | |||
#define BPEN bmBit1 | |||
#define BPPULSE bmBit2 | |||
#define BREAK bmBit3 | |||
// Bit 4 unused | |||
// Bit 5 unused | |||
// Bit 6 unused | |||
// Bit 7 unused | |||
// 0x7FB0 reserved | |||
// 0x7FB1 reserved | |||
SFRX(BPADDRH, 0x7FB2); | |||
SFRX(BPADDRL, 0x7FB3); | |||
/****************************** Endpoints 0-7 ******************************/ | |||
SFRX(EP0CS, 0x7FB4); | |||
#define EP0STALL bmBit0 | |||
#define HSNAK bmBit1 | |||
#define IN0BSY bmBit2 | |||
#define OUT0BSY bmBit3 | |||
// Bit 4 unused | |||
// Bit 5 unused | |||
// Bit 6 unused | |||
// Bit 7 unused | |||
SFRX(IN0BC, 0x7FB5); | |||
SFRX(IN1CS, 0x7FB6); | |||
SFRX(IN1BC, 0x7FB7); | |||
SFRX(IN2CS, 0x7FB8); | |||
SFRX(IN2BC, 0x7FB9); | |||
SFRX(IN3CS, 0x7FBA); | |||
SFRX(IN3BC, 0x7FBB); | |||
SFRX(IN4CS, 0x7FBC); | |||
SFRX(IN4BC, 0x7FBD); | |||
SFRX(IN5CS, 0x7FBE); | |||
SFRX(IN5BC, 0x7FBF); | |||
SFRX(IN6CS, 0x7FC0); | |||
SFRX(IN6BC, 0x7FC1); | |||
SFRX(IN7CS, 0x7FC2); | |||
SFRX(IN7BC, 0x7FC3); | |||
// 0x7FC4 reserved | |||
SFRX(OUT0BC, 0x7FC5); | |||
SFRX(OUT1CS, 0x7FC6); | |||
SFRX(OUT1BC, 0x7FC7); | |||
SFRX(OUT2CS, 0x7FC8); | |||
SFRX(OUT2BC, 0x7FC9); | |||
SFRX(OUT3CS, 0x7FCA); | |||
SFRX(OUT3BC, 0x7FCB); | |||
SFRX(OUT4CS, 0x7FCC); | |||
SFRX(OUT4BC, 0x7FCD); | |||
SFRX(OUT5CS, 0x7FCE); | |||
SFRX(OUT5BC, 0x7FCF); | |||
SFRX(OUT6CS, 0x7FD0); | |||
SFRX(OUT6BC, 0x7FD1); | |||
SFRX(OUT7CS, 0x7FD2); | |||
SFRX(OUT7BC, 0x7FD3); | |||
/* The INxSTALL, OUTxSTALL, INxBSY and OUTxBSY bits are the same for all | |||
* INxCS/OUTxCS registers. For better readability, we define them only once */ | |||
#define EPSTALL bmBit0 | |||
#define EPBSY bmBit1 | |||
/************************** Global USB Registers ***************************/ | |||
SFRX(SUDPTRH, 0x7FD4); | |||
SFRX(SUDPTRL, 0x7FD5); | |||
SFRX(USBCS, 0x7FD6); | |||
#define SIGRSUME bmBit0 | |||
#define RENUM bmBit1 | |||
#define DISCOE bmBit2 | |||
#define DISCON bmBit3 | |||
// Bit 4 unused | |||
// Bit 5 unused | |||
// Bit 6 unused | |||
#define WAKESRC bmBit7 | |||
SFRX(TOGCTL, 0x7FD7); | |||
#define TOG_EP0 bmBit0 | |||
#define TOG_EP1 bmBit1 | |||
#define TOG_EP2 bmBit2 | |||
// Bit 3 is read-only, always reads '0' | |||
#define TOG_IO bmBit4 | |||
#define TOG_R bmBit5 | |||
#define TOG_S bmBit6 | |||
#define TOG_Q bmBit7 | |||
SFRX(USBFRAMEL, 0x7FD8); | |||
SFRX(USBFRAMEH, 0x7FD9); | |||
// 0x7FDA reserved | |||
SFRX(FNADDR, 0x7FDB); | |||
// 0x7FDC reserved | |||
SFRX(USBPAIR, 0x7FDD); | |||
#define PR2IN bmBit0 | |||
#define PR4IN bmBit1 | |||
#define PR6IN bmBit2 | |||
#define PR2OUT bmBit3 | |||
#define PR4OUT bmBit4 | |||
#define PR6OUT bmBit5 | |||
// Bit 6 unused | |||
#define ISOSEND0 bmBit7 | |||
SFRX(IN07VAL, 0x7FDE); | |||
// Bit 0 is read-only, always reads '1' | |||
#define IN1VAL bmBit1 | |||
#define IN2VAL bmBit2 | |||
#define IN3VAL bmBit3 | |||
#define IN4VAL bmBit4 | |||
#define IN5VAL bmBit5 | |||
#define IN6VAL bmBit6 | |||
#define IN7VAL bmBit7 | |||
SFRX(OUT07VAL, 0x7FDF); | |||
// Bit 0 is read-only, always reads '1' | |||
#define OUT1VAL bmBit1 | |||
#define OUT2VAL bmBit2 | |||
#define OUT3VAL bmBit3 | |||
#define OUT4VAL bmBit4 | |||
#define OUT5VAL bmBit5 | |||
#define OUT6VAL bmBit6 | |||
#define OUT7VAL bmBit7 | |||
SFRX(INISOVAL, 0x7FE0); | |||
#define IN8VAL bmBit0 | |||
#define IN9VAL bmBit1 | |||
#define IN10VAL bmBit2 | |||
#define IN11VAL bmBit3 | |||
#define IN12VAL bmBit4 | |||
#define IN13VAL bmBit5 | |||
#define IN14VAL bmBit6 | |||
#define IN15VAL bmBit7 | |||
SFRX(OUTISOVAL, 0x7FE1); | |||
#define OUT8VAL bmBit0 | |||
#define OUT9VAL bmBit1 | |||
#define OUT10VAL bmBit2 | |||
#define OUT11VAL bmBit3 | |||
#define OUT12VAL bmBit4 | |||
#define OUT13VAL bmBit5 | |||
#define OUT14VAL bmBit6 | |||
#define OUT15VAL bmBit7 | |||
SFRX(FASTXFR, 0x7FE2); | |||
#define WMOD0 bmBit0 | |||
#define WMOD1 bmBit1 | |||
#define WPOL bmBit2 | |||
#define RMOD0 bmBit3 | |||
#define RMOD1 bmBit4 | |||
#define RPOL bmBit5 | |||
#define FBLK bmBit6 | |||
#define FISO bmBit7 | |||
SFRX(AUTOPTRH, 0x7FE3); | |||
SFRX(AUTOPTRL, 0x7FE4); | |||
SFRX(AUTODATA, 0x7FE5); | |||
// 0x7FE6 reserved | |||
// 0x7FE7 reserved | |||
/******************************* Setup Data ********************************/ | |||
SFRX(SETUPDAT[8], 0x7FE8); | |||
/************************* Isochronous FIFO sizes **************************/ | |||
SFRX(OUT8ADDR, 0x7FF0); | |||
SFRX(OUT9ADDR, 0x7FF1); | |||
SFRX(OUT10ADDR, 0x7FF2); | |||
SFRX(OUT11ADDR, 0x7FF3); | |||
SFRX(OUT12ADDR, 0x7FF4); | |||
SFRX(OUT13ADDR, 0x7FF5); | |||
SFRX(OUT14ADDR, 0x7FF6); | |||
SFRX(OUT15ADDR, 0x7FF7); | |||
SFRX(IN8ADDR, 0x7FF8); | |||
SFRX(IN9ADDR, 0x7FF9); | |||
SFRX(IN10ADDR, 0x7FFA); | |||
SFRX(IN11ADDR, 0x7FFB); | |||
SFRX(IN12ADDR, 0x7FFC); | |||
SFRX(IN13ADDR, 0x7FFD); | |||
SFRX(IN14ADDR, 0x7FFE); | |||
SFRX(IN15ADDR, 0x7FFF); | |||
#endif |
@@ -0,0 +1,41 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef __SHORTTYPES_H | |||
#define __SHORTTYPES_H | |||
#include <stdint.h> | |||
/** | |||
* @file Integer type definitions for shorter code (easier to stay within 80 | |||
* character maximum line length). | |||
*/ | |||
/* Signed integers */ | |||
typedef int8_t s8; | |||
typedef int16_t s16; | |||
typedef int32_t s32; | |||
/* Unsigned integers */ | |||
typedef uint8_t u8; | |||
typedef uint16_t u16; | |||
typedef uint32_t u32; | |||
#endif |
@@ -0,0 +1,267 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#ifndef __USB_H | |||
#define __USB_H | |||
#include "shorttypes.h" | |||
#include "reg_ezusb.h" | |||
#include <stdbool.h> | |||
#define NULL (void*)0; | |||
/* High and Low byte of a word (u16) */ | |||
#define HI8(word) (u8)(((u16)word >> 8) & 0xff) | |||
#define LO8(word) (u8)((u16)word & 0xff) | |||
/* Convenience functions */ | |||
#define STALL_EP0() EP0CS |= EP0STALL | |||
#define CLEAR_IRQ() EXIF &= ~USBINT | |||
/*********** USB descriptors. See section 9.5 of the USB 1.1 spec **********/ | |||
/* USB Descriptor Types. See USB 1.1 spec, page 187, table 9-5 */ | |||
#define DESCRIPTOR_TYPE_DEVICE 0x01 | |||
#define DESCRIPTOR_TYPE_CONFIGURATION 0x02 | |||
#define DESCRIPTOR_TYPE_STRING 0x03 | |||
#define DESCRIPTOR_TYPE_INTERFACE 0x04 | |||
#define DESCRIPTOR_TYPE_ENDPOINT 0x05 | |||
#define STR_DESCR(len,...) { len*2+2, DESCRIPTOR_TYPE_STRING, { __VA_ARGS__ } } | |||
/** USB Device Descriptor. See USB 1.1 spec, pp. 196 - 198 */ | |||
typedef struct { | |||
u8 bLength; ///< Size of this descriptor in bytes. | |||
u8 bDescriptorType; ///< DEVICE Descriptor Type. | |||
u16 bcdUSB; ///< USB specification release number (BCD). | |||
u8 bDeviceClass; ///< Class code. | |||
u8 bDeviceSubClass; ///< Subclass code. | |||
u8 bDeviceProtocol; ///< Protocol code. | |||
u8 bMaxPacketSize0; ///< Maximum packet size for EP0 (8, 16, 32, 64). | |||
u16 idVendor; ///< USB Vendor ID. | |||
u16 idProduct; ///< USB Product ID. | |||
u16 bcdDevice; ///< Device Release Number (BCD). | |||
u8 iManufacturer; ///< Index of manufacturer string descriptor. | |||
u8 iProduct; ///< Index of product string descriptor. | |||
u8 iSerialNumber; ///< Index of string descriptor containing serial #. | |||
u8 bNumConfigurations; ///< Number of possible configurations. | |||
} usb_device_descriptor_t; | |||
/** USB Configuration Descriptor. See USB 1.1 spec, pp. 199 - 200 */ | |||
typedef struct { | |||
u8 bLength; ///< Size of this descriptor in bytes. | |||
u8 bDescriptorType; ///< CONFIGURATION descriptor type. | |||
u16 wTotalLength; ///< Combined total length of all descriptors. | |||
u8 bNumInterfaces; ///< Number of interfaces in this configuration. | |||
u8 bConfigurationValue; ///< Value used to select this configuration. | |||
u8 iConfiguration; ///< Index of configuration string descriptor. | |||
u8 bmAttributes; ///< Configuration characteristics. | |||
u8 MaxPower; ///< Maximum power consumption in 2 mA units. | |||
} usb_config_descriptor_t; | |||
/** USB Interface Descriptor. See USB 1.1 spec, pp. 201 - 203 */ | |||
typedef struct { | |||
u8 bLength; ///< Size of this descriptor in bytes. | |||
u8 bDescriptorType; ///< INTERFACE descriptor type. | |||
u8 bInterfaceNumber; ///< Interface number. | |||
u8 bAlternateSetting; ///< Value used to select alternate setting. | |||
u8 bNumEndpoints; ///< Number of endpoints used by this interface. | |||
u8 bInterfaceClass; ///< Class code. | |||
u8 bInterfaceSubclass; ///< Subclass code. | |||
u8 bInterfaceProtocol; ///< Protocol code. | |||
u8 iInterface; ///< Index of interface string descriptor. | |||
} usb_interface_descriptor_t; | |||
/** USB Endpoint Descriptor. See USB 1.1 spec, pp. 203 - 204 */ | |||
typedef struct { | |||
u8 bLength; ///< Size of this descriptor in bytes. | |||
u8 bDescriptorType; ///< ENDPOINT descriptor type. | |||
u8 bEndpointAddress; ///< Endpoint Address: USB 1.1 spec, table 9-10. | |||
u8 bmAttributes; ///< Endpoint Attributes: USB 1.1 spec, table 9-10. | |||
u16 wMaxPacketSize; ///< Maximum packet size for this endpoint. | |||
u8 bInterval; ///< Polling interval (in ms) for this endpoint. | |||
} usb_endpoint_descriptor_t; | |||
/** USB Language Descriptor. See USB 1.1 spec, pp. 204 - 205 */ | |||
typedef struct { | |||
u8 bLength; ///< Size of this descriptor in bytes. | |||
u8 bDescriptorType; ///< STRING descriptor type. | |||
u16 wLANGID[]; ///< LANGID codes. | |||
} usb_language_descriptor_t; | |||
/** USB String Descriptor. See USB 1.1 spec, pp. 204 - 205 */ | |||
typedef struct { | |||
u8 bLength; ///< Size of this descriptor in bytes. | |||
u8 bDescriptorType; ///< STRING descriptor type. | |||
u16 bString[]; ///< UNICODE encoded string. | |||
} usb_string_descriptor_t; | |||
/********************** USB Control Endpoint 0 related *********************/ | |||
/** USB Control Setup Data. See USB 1.1 spec, pp. 183 - 185 */ | |||
typedef struct { | |||
u8 bmRequestType; ///< Characteristics of a request. | |||
u8 bRequest; ///< Specific request. | |||
u16 wValue; ///< Field that varies according to request. | |||
u16 wIndex; ///< Field that varies according to request. | |||
u16 wLength; ///< Number of bytes to transfer in data stage. | |||
} setup_data_t; | |||
/* External declarations for variables that need to be accessed outside of | |||
* the USB module */ | |||
extern volatile bool EP2_out; | |||
extern volatile bool EP2_in; | |||
extern volatile __xdata __at 0x7FE8 setup_data_t setup_data; | |||
/* | |||
* USB Request Types (bmRequestType): See USB 1.1 spec, page 183, table 9-2 | |||
* | |||
* Bit 7: Data transfer direction | |||
* 0 = Host-to-device | |||
* 1 = Device-to-host | |||
* Bit 6...5: Type | |||
* 0 = Standard | |||
* 1 = Class | |||
* 2 = Vendor | |||
* 3 = Reserved | |||
* Bit 4...0: Recipient | |||
* 0 = Device | |||
* 1 = Interface | |||
* 2 = Endpoint | |||
* 3 = Other | |||
* 4...31 = Reserved | |||
*/ | |||
#define USB_DIR_OUT 0x00 | |||
#define USB_DIR_IN 0x80 | |||
#define USB_REQ_TYPE_STANDARD (0x00 << 5) | |||
#define USB_REQ_TYPE_CLASS (0x01 << 5) | |||
#define USB_REQ_TYPE_VENDOR (0x02 << 5) | |||
#define USB_REQ_TYPE_RESERVED (0x03 << 5) | |||
#define USB_RECIP_DEVICE 0x00 | |||
#define USB_RECIP_INTERFACE 0x01 | |||
#define USB_RECIP_ENDPOINT 0x02 | |||
#define USB_RECIP_OTHER 0x03 | |||
/* bmRequestType for USB Standard Requests */ | |||
/* Clear Interface Request */ | |||
#define CF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) | |||
#define CF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) | |||
#define CF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) | |||
/* Get Configuration Request */ | |||
#define GC_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) | |||
/* Get Descriptor Request */ | |||
#define GD_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) | |||
/* Get Interface Request */ | |||
#define GI_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) | |||
/* Get Status Request: See USB 1.1 spec, page 190 */ | |||
#define GS_DEVICE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) | |||
#define GS_INTERFACE (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) | |||
#define GS_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) | |||
/* Set Address Request is handled by EZ-USB core */ | |||
/* Set Configuration Request */ | |||
#define SC_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) | |||
/* Set Descriptor Request */ | |||
#define SD_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) | |||
/* Set Feature Request */ | |||
#define SF_DEVICE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_DEVICE) | |||
#define SF_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) | |||
#define SF_ENDPOINT (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) | |||
/* Set Interface Request */ | |||
#define SI_INTERFACE (USB_DIR_OUT | USB_REQ_TYPE_STANDARD | USB_RECIP_INTERFACE) | |||
/* Synch Frame Request */ | |||
#define SY_ENDPOINT (USB_DIR_IN | USB_REQ_TYPE_STANDARD | USB_RECIP_ENDPOINT) | |||
/* USB Requests (bRequest): See USB 1.1 spec, table 9-4 on page 187 */ | |||
#define GET_STATUS 0 | |||
#define CLEAR_FEATURE 1 | |||
// Value '2' is reserved for future use | |||
#define SET_FEATURE 3 | |||
// Value '4' is reserved for future use | |||
#define SET_ADDRESS 5 | |||
#define GET_DESCRIPTOR 6 | |||
#define SET_DESCRIPTOR 7 | |||
#define GET_CONFIGURATION 8 | |||
#define SET_CONFIGURATION 9 | |||
#define GET_INTERFACE 10 | |||
#define SET_INTERFACE 11 | |||
#define SYNCH_FRAME 12 | |||
/* Standard Feature Selectors: See USB 1.1 spec, table 9-6 on page 188 */ | |||
#define DEVICE_REMOTE_WAKEUP 1 | |||
#define ENDPOINT_HALT 0 | |||
/************************** EZ-USB specific stuff **************************/ | |||
/** USB Interrupts. See AN2131-TRM, page 9-4 for details */ | |||
typedef enum { | |||
SUDAV_ISR = 13, | |||
SOF_ISR, | |||
SUTOK_ISR, | |||
SUSPEND_ISR, | |||
USBRESET_ISR, | |||
IBN_ISR, | |||
EP0IN_ISR, | |||
EP0OUT_ISR, | |||
EP1IN_ISR, | |||
EP1OUT_ISR, | |||
EP2IN_ISR, | |||
EP2OUT_ISR, | |||
EP3IN_ISR, | |||
EP3OUT_ISR, | |||
EP4IN_ISR, | |||
EP4OUT_ISR, | |||
EP5IN_ISR, | |||
EP5OUT_ISR, | |||
EP6IN_ISR, | |||
EP6OUT_ISR, | |||
EP7IN_ISR, | |||
EP7OUT_ISR | |||
} USB_ISR; | |||
/*************************** Function Prototypes ***************************/ | |||
__xdata u8* usb_get_endpoint_cs_reg(u8 ep); | |||
void usb_reset_data_toggle(u8 ep); | |||
bool usb_handle_get_status(void); | |||
bool usb_handle_clear_feature(void); | |||
bool usb_handle_set_feature(void); | |||
bool usb_handle_get_descriptor(void); | |||
void usb_handle_set_interface(void); | |||
void usb_handle_setup_data(void); | |||
void usb_init(void); | |||
#endif |
@@ -0,0 +1,83 @@ | |||
;--------------------------------------------------------------------------; | |||
; Copyright (C) 2011 by Martin Schmoelzer ; | |||
; <martin.schmoelzer@student.tuwien.ac.at> ; | |||
; ; | |||
; This program is free software; you can redistribute it and/or modify ; | |||
; it under the terms of the GNU General Public License as published by ; | |||
; the Free Software Foundation; either version 2 of the License, or ; | |||
; (at your option) any later version. ; | |||
; ; | |||
; This program is distributed in the hope that it will be useful, ; | |||
; but WITHOUT ANY WARRANTY; without even the implied warranty of ; | |||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; | |||
; GNU General Public License for more details. ; | |||
; ; | |||
; You should have received a copy of the GNU General Public License ; | |||
; along with this program; if not, write to the ; | |||
; Free Software Foundation, Inc., ; | |||
; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ; | |||
;--------------------------------------------------------------------------; | |||
.module JUMPTABLE | |||
.globl USB_AutoVector | |||
.globl USB_Jump_Table | |||
;--------------------------------------------------------------------------; | |||
; Interrupt Vectors ; | |||
;--------------------------------------------------------------------------; | |||
.area USB_JV (ABS,OVR) ; Absolute, Overlay | |||
.org 0x43 ; USB interrupt (INT2) jumps here | |||
USB_AutoVector = #. + 2 | |||
ljmp USB_jump_table | |||
;--------------------------------------------------------------------------; | |||
; USB Jump Table ; | |||
;--------------------------------------------------------------------------; | |||
.area USB_JT (ABS) ; Absolute placement | |||
.org 0x1B00 ; Place jump table at 0x1B00 | |||
USB_jump_table: ; autovector jump table | |||
ljmp _sudav_isr ; Setup Data Available | |||
.db 0 | |||
ljmp _sof_isr ; Start of Frame | |||
.db 0 | |||
ljmp _sutok_isr ; Setup Data Loading | |||
.db 0 | |||
ljmp _suspend_isr ; Global Suspend | |||
.db 0 | |||
ljmp _usbreset_isr ; USB Reset | |||
.db 0 | |||
ljmp _ibn_isr ; IN Bulk NAK interrupt | |||
.db 0 | |||
ljmp _ep0in_isr ; Endpoint 0 IN | |||
.db 0 | |||
ljmp _ep0out_isr ; Endpoint 0 OUT | |||
.db 0 | |||
ljmp _ep1in_isr ; Endpoint 1 IN | |||
.db 0 | |||
ljmp _ep1out_isr ; Endpoint 1 OUT | |||
.db 0 | |||
ljmp _ep2in_isr ; Endpoint 2 IN | |||
.db 0 | |||
ljmp _ep2out_isr ; Endpoint 2 OUT | |||
.db 0 | |||
ljmp _ep3in_isr ; Endpoint 3 IN | |||
.db 0 | |||
ljmp _ep3out_isr ; Endpoint 3 OUT | |||
.db 0 | |||
ljmp _ep4in_isr ; Endpoint 4 IN | |||
.db 0 | |||
ljmp _ep4out_isr ; Endpoint 4 OUT | |||
.db 0 | |||
ljmp _ep5in_isr ; Endpoint 5 IN | |||
.db 0 | |||
ljmp _ep5out_isr ; Endpoint 5 OUT | |||
.db 0 | |||
ljmp _ep6in_isr ; Endpoint 6 IN | |||
.db 0 | |||
ljmp _ep6out_isr ; Endpoint 6 OUT | |||
.db 0 | |||
ljmp _ep7in_isr ; Endpoint 7 IN | |||
.db 0 | |||
ljmp _ep7out_isr ; Endpoint 7 OUT | |||
.db 0 |
@@ -0,0 +1,51 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#include "delay.h" | |||
void delay_5us(void) | |||
{ | |||
NOP; | |||
} | |||
void delay_1ms(void) { | |||
u16 i; | |||
for (i = 0; i < 598; i++); | |||
} | |||
void delay_us(u16 delay) | |||
{ | |||
u16 i; | |||
u16 maxcount = (delay / 5); | |||
for (i = 0; i < maxcount; i++) { | |||
delay_5us(); | |||
} | |||
} | |||
void delay_ms(u16 delay) | |||
{ | |||
u16 i; | |||
for (i = 0; i < delay; i++) { | |||
delay_1ms(); | |||
} | |||
} |
@@ -0,0 +1,414 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#include "jtag.h" | |||
#include "io.h" | |||
#include "msgtypes.h" | |||
#include "common.h" | |||
#include <stdbool.h> | |||
/** Delay value for SCAN operations with less than maximum TCK frequency */ | |||
u8 delay_scan = 0; | |||
/** Delay value for CLOCK_TCK operations */ | |||
u8 delay_tck = 0; | |||
/** Delay value for CLOCK_TMS operations with less than maximum frequency */ | |||
u8 delay_tms = 0; | |||
/** | |||
* Perform JTAG SCAN-IN operation at maximum TCK frequency. | |||
* | |||
* Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and | |||
* stored in the EP2 IN buffer. | |||
* | |||
* @param out_offset offset in OUT2BUF where payload data starts | |||
*/ | |||
void jtag_scan_in(u8 out_offset, u8 in_offset) | |||
{ | |||
u8 scan_size_bytes, bits_last_byte; | |||
u8 tms_count_start, tms_count_end; | |||
u8 tms_sequence_start, tms_sequence_end; | |||
u8 tdo_data, i, j; | |||
u8 outb_buffer; | |||
/* Get parameters from OUT2BUF */ | |||
scan_size_bytes = OUT2BUF[out_offset]; | |||
bits_last_byte = OUT2BUF[out_offset + 1]; | |||
tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F; | |||
tms_count_end = OUT2BUF[out_offset + 2] & 0x0F; | |||
tms_sequence_start = OUT2BUF[out_offset + 3]; | |||
tms_sequence_end = OUT2BUF[out_offset + 4]; | |||
if (tms_count_start > 0) { | |||
jtag_clock_tms(tms_count_start, tms_sequence_start); | |||
} | |||
outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS); | |||
/* Shift all bytes except the last byte */ | |||
for (i = 0; i < scan_size_bytes - 1; i++) { | |||
tdo_data = 0; | |||
for (j = 0; j < 8; j++) { | |||
OUTB = outb_buffer; /* TCK changes here */ | |||
OUTB = (outb_buffer | PIN_TCK); | |||
tdo_data = tdo_data >> 1; | |||
if (GET_TDO()) { | |||
tdo_data |= 0x80; | |||
} | |||
} | |||
/* Copy TDO data to IN2BUF */ | |||
IN2BUF[i + in_offset] = tdo_data; | |||
} | |||
tdo_data = 0; | |||
/* Shift the last byte */ | |||
for (j = 0; j < bits_last_byte; j++) { | |||
/* Assert TMS signal if requested and this is the last bit */ | |||
if ((j == bits_last_byte - 1) && (tms_count_end > 0)) { | |||
outb_buffer |= PIN_TMS; | |||
tms_count_end--; | |||
tms_sequence_end = tms_sequence_end >> 1; | |||
} | |||
OUTB = outb_buffer; /* TCK change here */ | |||
OUTB = (outb_buffer | PIN_TCK); | |||
tdo_data = tdo_data >> 1; | |||
if (GET_TDO()) { | |||
tdo_data |= 0x80; | |||
} | |||
} | |||
tdo_data = tdo_data >> (8 - bits_last_byte); | |||
/* Copy TDO data to IN2BUF */ | |||
IN2BUF[i + in_offset] = tdo_data; | |||
/* Move to correct end state */ | |||
if (tms_count_end > 0) { | |||
jtag_clock_tms(tms_count_end, tms_sequence_end); | |||
} | |||
} | |||
/** | |||
* Perform JTAG SCAN-OUT operation at maximum TCK frequency. | |||
* | |||
* Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO | |||
* data is not sampled. | |||
* The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state. | |||
* | |||
* @param out_offset offset in OUT2BUF where payload data starts | |||
*/ | |||
void jtag_scan_out(u8 out_offset) | |||
{ | |||
u8 scan_size_bytes, bits_last_byte; | |||
u8 tms_count_start, tms_count_end; | |||
u8 tms_sequence_start, tms_sequence_end; | |||
u8 tdi_data, i, j; | |||
u8 outb_buffer; | |||
/* Get parameters from OUT2BUF */ | |||
scan_size_bytes = OUT2BUF[out_offset]; | |||
bits_last_byte = OUT2BUF[out_offset + 1]; | |||
tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F; | |||
tms_count_end = OUT2BUF[out_offset + 2] & 0x0F; | |||
tms_sequence_start = OUT2BUF[out_offset + 3]; | |||
tms_sequence_end = OUT2BUF[out_offset + 4]; | |||
if (tms_count_start > 0) { | |||
jtag_clock_tms(tms_count_start, tms_sequence_start); | |||
} | |||
outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS); | |||
/* Shift all bytes except the last byte */ | |||
for (i = 0; i < scan_size_bytes - 1; i++) { | |||
tdi_data = OUT2BUF[i + out_offset + 5]; | |||
for (j = 0; j < 8; j++) { | |||
if (tdi_data & 0x01) { | |||
outb_buffer |= PIN_TDI; | |||
} | |||
else { | |||
outb_buffer &= ~PIN_TDI; | |||
} | |||
OUTB = outb_buffer; /* TDI and TCK change here */ | |||
tdi_data = tdi_data >> 1; | |||
OUTB = (outb_buffer | PIN_TCK); | |||
} | |||
} | |||
tdi_data = OUT2BUF[i + out_offset + 5]; | |||
/* Shift the last byte */ | |||
for (j = 0; j < bits_last_byte; j++) { | |||
if (tdi_data & 0x01) { | |||
outb_buffer |= PIN_TDI; | |||
} | |||
else { | |||
outb_buffer &= ~PIN_TDI; | |||
} | |||
/* Assert TMS signal if requested and this is the last bit */ | |||
if ((j == bits_last_byte - 1) && (tms_count_end > 0)) { | |||
outb_buffer |= PIN_TMS; | |||
tms_count_end--; | |||
tms_sequence_end = tms_sequence_end >> 1; | |||
} | |||
OUTB = outb_buffer; /* TDI and TCK change here */ | |||
tdi_data = tdi_data >> 1; | |||
OUTB = (outb_buffer | PIN_TCK); | |||
} | |||
/* Move to correct end state */ | |||
if (tms_count_end > 0) { | |||
jtag_clock_tms(tms_count_end, tms_sequence_end); | |||
} | |||
} | |||
/** | |||
* Perform bidirectional JTAG SCAN operation at maximum TCK frequency. | |||
* | |||
* Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO | |||
* data is sampled and stored in the EP2 IN buffer. | |||
* The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state. | |||
* | |||
* @param out_offset offset in OUT2BUF where payload data starts | |||
*/ | |||
void jtag_scan_io(u8 out_offset, u8 in_offset) | |||
{ | |||
u8 scan_size_bytes, bits_last_byte; | |||
u8 tms_count_start, tms_count_end; | |||
u8 tms_sequence_start, tms_sequence_end; | |||
u8 tdi_data, tdo_data, i, j; | |||
u8 outb_buffer; | |||
/* Get parameters from OUT2BUF */ | |||
scan_size_bytes = OUT2BUF[out_offset]; | |||
bits_last_byte = OUT2BUF[out_offset + 1]; | |||
tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F; | |||
tms_count_end = OUT2BUF[out_offset + 2] & 0x0F; | |||
tms_sequence_start = OUT2BUF[out_offset + 3]; | |||
tms_sequence_end = OUT2BUF[out_offset + 4]; | |||
if (tms_count_start > 0) { | |||
jtag_clock_tms(tms_count_start, tms_sequence_start); | |||
} | |||
outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS); | |||
/* Shift all bytes except the last byte */ | |||
for (i = 0; i < scan_size_bytes - 1; i++) { | |||
tdi_data = OUT2BUF[i + out_offset + 5]; | |||
tdo_data = 0; | |||
for (j = 0; j < 8; j++) { | |||
if (tdi_data & 0x01) { | |||
outb_buffer |= PIN_TDI; | |||
} | |||
else { | |||
outb_buffer &= ~PIN_TDI; | |||
} | |||
OUTB = outb_buffer; /* TDI and TCK change here */ | |||
tdi_data = tdi_data >> 1; | |||
OUTB = (outb_buffer | PIN_TCK); | |||
tdo_data = tdo_data >> 1; | |||
if (GET_TDO()) { | |||
tdo_data |= 0x80; | |||
} | |||
} | |||
/* Copy TDO data to IN2BUF */ | |||
IN2BUF[i + in_offset] = tdo_data; | |||
} | |||
tdi_data = OUT2BUF[i + out_offset + 5]; | |||
tdo_data = 0; | |||
/* Shift the last byte */ | |||
for (j = 0; j < bits_last_byte; j++) { | |||
if (tdi_data & 0x01) { | |||
outb_buffer |= PIN_TDI; | |||
} | |||
else { | |||
outb_buffer &= ~PIN_TDI; | |||
} | |||
/* Assert TMS signal if requested and this is the last bit */ | |||
if ((j == bits_last_byte - 1) && (tms_count_end > 0)) { | |||
outb_buffer |= PIN_TMS; | |||
tms_count_end--; | |||
tms_sequence_end = tms_sequence_end >> 1; | |||
} | |||
OUTB = outb_buffer; /* TDI and TCK change here */ | |||
tdi_data = tdi_data >> 1; | |||
OUTB = (outb_buffer | PIN_TCK); | |||
tdo_data = tdo_data >> 1; | |||
if (GET_TDO()) { | |||
tdo_data |= 0x80; | |||
} | |||
} | |||
tdo_data = tdo_data >> (8 - bits_last_byte); | |||
/* Copy TDO data to IN2BUF */ | |||
IN2BUF[i + in_offset] = tdo_data; | |||
/* Move to correct end state */ | |||
if (tms_count_end > 0) { | |||
jtag_clock_tms(tms_count_end, tms_sequence_end); | |||
} | |||
} | |||
/** | |||
* Generate TCK clock cycles. | |||
* | |||
* @param count number of TCK clock cyclces to generate. | |||
*/ | |||
void jtag_clock_tck(u16 count) | |||
{ | |||
u16 i; | |||
u8 j; | |||
for ( i = 0; i < count; i++ ) { | |||
SET_TCK_LOW(); | |||
for(j = 0; j < delay_tck; j++); | |||
SET_TCK_HIGH(); | |||
for(j = 0; j < delay_tck; j++); | |||
} | |||
} | |||
/** | |||
* Perform TAP-FSM state transitions at maximum TCK frequency. | |||
* | |||
* @param count the number of state transitions to perform. | |||
* @param sequence the TMS pin levels for each state transition, starting with | |||
* the least-significant bit. | |||
*/ | |||
void jtag_clock_tms(u8 count, u8 sequence) | |||
{ | |||
volatile u8 outb_buffer; | |||
u8 i; | |||
outb_buffer = OUTB & ~(PIN_TCK); | |||
for ( i = 0; i < count; i++ ) { | |||
/* Set TMS pin according to sequence parameter */ | |||
if ( sequence & 0x1 ) { | |||
outb_buffer |= PIN_TMS; | |||
} | |||
else { | |||
outb_buffer &= ~PIN_TMS; | |||
} | |||
OUTB = outb_buffer; | |||
sequence = sequence >> 1; | |||
OUTB = outb_buffer | PIN_TCK; | |||
} | |||
} | |||
/** | |||
* Perform TAP-FSM state transitions at less than maximum TCK frequency. | |||
* | |||
* @param count the number of state transitions to perform. | |||
* @param sequence the TMS pin levels for each state transition, starting with | |||
* the least-significant bit. | |||
*/ | |||
void jtag_slow_clock_tms(u8 count, u8 sequence) | |||
{ | |||
} | |||
/** | |||
* Get current JTAG signal states. | |||
* | |||
* @return a 16-bit integer where the most-significant byte contains the state | |||
* of the JTAG input signals and the least-significant byte cotains the state | |||
* of the JTAG output signals. | |||
*/ | |||
u16 jtag_get_signals(void) | |||
{ | |||
u8 input_signal_state, output_signal_state; | |||
input_signal_state = 0; | |||
output_signal_state = 0; | |||
/* Get states of input pins */ | |||
if (GET_TDO()) { | |||
input_signal_state |= SIGNAL_TDO; | |||
} | |||
if (GET_BRKOUT()) { | |||
input_signal_state |= SIGNAL_BRKOUT; | |||
} | |||
if (GET_TRAP()) { | |||
input_signal_state |= SIGNAL_TRAP; | |||
} | |||
if (GET_RTCK()) { | |||
/* Using RTCK this way would be extremely slow, | |||
* implemented only for the sake of completeness */ | |||
input_signal_state |= SIGNAL_RTCK; | |||
} | |||
/* Get states of output pins */ | |||
output_signal_state = PINSB & MASK_PORTB_DIRECTION_OUT; | |||
return ((u16)input_signal_state << 8) | ((u16)output_signal_state); | |||
} | |||
/** | |||
* Set state of JTAG output signals. | |||
* | |||
* @param low signals which should be de-asserted. | |||
* @param high signals which should be asserted. | |||
*/ | |||
void jtag_set_signals(u8 low, u8 high) | |||
{ | |||
OUTB &= ~(low & MASK_PORTB_DIRECTION_OUT); | |||
OUTB |= (high & MASK_PORTB_DIRECTION_OUT); | |||
} | |||
/** | |||
* Configure TCK delay parameters. | |||
* | |||
* @param scan number of delay cycles in shift operations. | |||
* @param tck number of delay cycles in clock_tck operations. | |||
* @param tms number of delay cycles in clock_tms operations. | |||
*/ | |||
void jtag_configure_tck_delay(u8 scan, u8 tck, u8 tms) | |||
{ | |||
delay_scan = scan; | |||
delay_tck = tck; | |||
delay_tms = tms; | |||
} |
@@ -0,0 +1,92 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#include "main.h" | |||
#include "shorttypes.h" | |||
#include "io.h" | |||
#include "usb.h" | |||
#include "protocol.h" | |||
extern void sudav_isr(void) __interrupt SUDAV_ISR; | |||
extern void sof_isr(void) __interrupt; | |||
extern void sutok_isr(void) __interrupt; | |||
extern void suspend_isr(void) __interrupt; | |||
extern void usbreset_isr(void) __interrupt; | |||
extern void ibn_isr(void) __interrupt; | |||
extern void ep0in_isr(void) __interrupt; | |||
extern void ep0out_isr(void) __interrupt; | |||
extern void ep1in_isr(void) __interrupt; | |||
extern void ep1out_isr(void) __interrupt; | |||
extern void ep2in_isr(void) __interrupt; | |||
extern void ep2out_isr(void) __interrupt; | |||
extern void ep3in_isr(void) __interrupt; | |||
extern void ep3out_isr(void) __interrupt; | |||
extern void ep4in_isr(void) __interrupt; | |||
extern void ep4out_isr(void) __interrupt; | |||
extern void ep5in_isr(void) __interrupt; | |||
extern void ep5out_isr(void) __interrupt; | |||
extern void ep6in_isr(void) __interrupt; | |||
extern void ep6out_isr(void) __interrupt; | |||
extern void ep7in_isr(void) __interrupt; | |||
extern void ep7out_isr(void) __interrupt; | |||
void io_init(void) | |||
{ | |||
/* PORTxCFG register bits select alternate functions (1 == alternate function, | |||
* 0 == standard I/O) | |||
* OEx register bits turn on/off output buffer (1 == output, 0 == input) | |||
* OUTx register bits determine pin state of output | |||
* PINx register bits reflect pin state (high == 1, low == 0) */ | |||
/* PORT A */ | |||
PORTACFG = PIN_OE; | |||
OEA = PIN_U_OE | PIN_OE | PIN_RUN_LED | PIN_COM_LED; | |||
OUTA = PIN_RUN_LED | PIN_COM_LED; | |||
/* PORT B */ | |||
PORTBCFG = 0x00; | |||
OEB = PIN_TDI | PIN_TMS | PIN_TCK | PIN_TRST | PIN_BRKIN | PIN_RESET | |||
| PIN_OCDSE; | |||
/* TRST and RESET signals are low-active but inverted by hardware, so we clear | |||
* these signals here! */ | |||
OUTB = 0x00; | |||
/* PORT C */ | |||
PORTCCFG = PIN_WR; | |||
OEC = PIN_TXD0 | PIN_WR; | |||
OUTC = 0x00; | |||
} | |||
int main(void) | |||
{ | |||
io_init(); | |||
usb_init(); | |||
/* Enable Interrupts */ | |||
EA = 1; | |||
/* Begin executing command(s). This function never returns. */ | |||
command_loop(); | |||
/* Never reached, but SDCC complains about missing return statement */ | |||
return 0; | |||
} |
@@ -0,0 +1,212 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
#include "protocol.h" | |||
#include "jtag.h" | |||
#include "delay.h" | |||
#include "usb.h" | |||
#include "io.h" | |||
#include "msgtypes.h" | |||
#include "reg_ezusb.h" | |||
/** | |||
* @file Implementation of the OpenULINK communication protocol. | |||
* | |||
* The OpenULINK protocol uses one OUT and one IN endpoint. These two endpoints | |||
* are configured to use the maximum packet size for full-speed transfers, | |||
* 64 bytes. Commands always start with a command ID (see msgtypes.h for | |||
* command ID definitions) and contain zero or more payload data bytes in both | |||
* transfer directions (IN and OUT). The payload | |||
* | |||
* Almost all commands contain a fixed number of payload data bytes. The number | |||
* of payload data bytes for the IN and OUT direction does not need to be the | |||
* same. | |||
* | |||
* Multiple commands may be sent in one EP2 Bulk-OUT packet. Because the | |||
* OpenULINK firmware does not perform bounds checking for EP2 Bulk-IN packets, | |||
* the host MUST ensure that the commands sent in the OUT packet require a | |||
* maximum of 64 bytes of IN data. | |||
*/ | |||
/** Index in EP2 Bulk-OUT data buffer that contains the current command ID */ | |||
volatile u8 cmd_id_index; | |||
/** Number of data bytes already in EP2 Bulk-IN buffer */ | |||
volatile u8 payload_index_in; | |||
/** | |||
* Execute a SET_LEDS command. | |||
*/ | |||
void execute_set_led_command(void) | |||
{ | |||
u8 led_state = OUT2BUF[cmd_id_index + 1]; | |||
if (led_state & RUN_LED_ON) { | |||
SET_RUN_LED(); | |||
} | |||
if (led_state & COM_LED_ON) { | |||
SET_COM_LED(); | |||
} | |||
if (led_state & RUN_LED_OFF) { | |||
CLEAR_RUN_LED(); | |||
} | |||
if (led_state & COM_LED_OFF) { | |||
CLEAR_COM_LED(); | |||
} | |||
} | |||
/** | |||
* Executes one command and updates global command indexes. | |||
* | |||
* @param index the index of the Bulk EP2-OUT data buffer at which the | |||
* command ID is stored. | |||
* @return true if this command was the last command. | |||
* @return false if there are more commands within the current contents of the | |||
* Bulk EP2-OUT data buffer. | |||
*/ | |||
bool execute_command(void) | |||
{ | |||
u8 usb_out_bytecount, usb_in_bytecount; | |||
u16 signal_state; | |||
u16 count; | |||
/* Most commands do not transfer IN data. To save code space, we write 0 to | |||
* usb_in_bytecount here, then modify it in the switch statement below where | |||
* neccessary */ | |||
usb_in_bytecount = 0; | |||
switch (OUT2BUF[cmd_id_index] /* Command ID */) { | |||
case CMD_SCAN_IN: | |||
usb_out_bytecount = 5; | |||
usb_in_bytecount = OUT2BUF[cmd_id_index + 1]; | |||
jtag_scan_in(cmd_id_index + 1, payload_index_in); | |||
break; | |||
case CMD_SCAN_OUT: | |||
usb_out_bytecount = OUT2BUF[cmd_id_index + 1] + 5; | |||
jtag_scan_out(cmd_id_index + 1); | |||
break; | |||
case CMD_SCAN_IO: | |||
usb_in_bytecount = OUT2BUF[cmd_id_index + 1]; | |||
usb_out_bytecount = usb_in_bytecount + 5; | |||
jtag_scan_io(cmd_id_index + 1, payload_index_in); | |||
break; | |||
case CMD_CLOCK_TMS: | |||
usb_out_bytecount = 2; | |||
jtag_clock_tms(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]); | |||
break; | |||
case CMD_CLOCK_TCK: | |||
usb_out_bytecount = 2; | |||
count = (u16)OUT2BUF[cmd_id_index + 1]; | |||
count |= ((u16)OUT2BUF[cmd_id_index + 2]) << 8; | |||
jtag_clock_tck(count); | |||
break; | |||
case CMD_SLEEP_US: | |||
usb_out_bytecount = 2; | |||
count = (u16)OUT2BUF[cmd_id_index + 1]; | |||
count |= ((u16)OUT2BUF[cmd_id_index + 2]) << 8; | |||
delay_us(count); | |||
break; | |||
case CMD_SLEEP_MS: | |||
usb_out_bytecount = 2; | |||
count = (u16)OUT2BUF[cmd_id_index + 1]; | |||
count |= ((u16)OUT2BUF[cmd_id_index + 2]) << 8; | |||
delay_ms(count); | |||
break; | |||
case CMD_GET_SIGNALS: | |||
usb_out_bytecount = 0; | |||
usb_in_bytecount = 2; | |||
signal_state = jtag_get_signals(); | |||
IN2BUF[payload_index_in] = (signal_state >> 8) & 0x00FF; | |||
IN2BUF[payload_index_in + 1] = signal_state & 0x00FF; | |||
break; | |||
case CMD_SET_SIGNALS: | |||
usb_out_bytecount = 2; | |||
jtag_set_signals(OUT2BUF[cmd_id_index + 1], OUT2BUF[cmd_id_index + 2]); | |||
break; | |||
case CMD_SET_LEDS: | |||
usb_out_bytecount = 1; | |||
execute_set_led_command(); | |||
break; | |||
case CMD_TEST: | |||
usb_out_bytecount = 1; | |||
/* Do nothing... This command is only used to test if the device is ready | |||
* to accept new commands */ | |||
break; | |||
default: | |||
/* Should never be reached */ | |||
usb_out_bytecount = 0; | |||
break; | |||
} | |||
/* Update EP2 Bulk-IN data byte count */ | |||
payload_index_in += usb_in_bytecount; | |||
/* Determine if this was the last command */ | |||
if ((cmd_id_index + usb_out_bytecount + 1) >= OUT2BC) { | |||
return true; | |||
} | |||
else { | |||
/* Not the last command, update cmd_id_index */ | |||
cmd_id_index += (usb_out_bytecount + 1); | |||
return false; | |||
} | |||
} | |||
/** | |||
* Forever wait for commands and execute them as they arrive. | |||
*/ | |||
void command_loop(void) | |||
{ | |||
bool last_command; | |||
while (1) { | |||
cmd_id_index = 0; | |||
payload_index_in = 0; | |||
/* Wait until host sends EP2 Bulk-OUT packet */ | |||
while (!EP2_out); | |||
EP2_out = 0; | |||
/* Turn on COM LED to indicate command execution */ | |||
SET_COM_LED(); | |||
/* Execute the commands */ | |||
last_command = false; | |||
while (last_command == false) { | |||
last_command = execute_command(); | |||
} | |||
CLEAR_COM_LED(); | |||
/* Send back EP2 Bulk-IN packet if required */ | |||
if (payload_index_in > 0) { | |||
IN2BC = payload_index_in; | |||
while (!EP2_in); | |||
EP2_in = 0; | |||
} | |||
/* Re-arm EP2-OUT after command execution */ | |||
OUT2BC = 0; | |||
} | |||
} |
@@ -0,0 +1,543 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2011 by Martin Schmoelzer * | |||
* <martin.schmoelzer@student.tuwien.ac.at> * | |||
* * | |||
* This program is free software; you can redistribute it and/or modify * | |||
* it under the terms of the GNU General Public License as published by * | |||
* the Free Software Foundation; either version 2 of the License, or * | |||
* (at your option) any later version. * | |||
* * | |||
* This program is distributed in the hope that it will be useful, * | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of * | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |||
* GNU General Public License for more details. * | |||
* * | |||
* You should have received a copy of the GNU General Public License * | |||
* along with this program; if not, write to the * | |||
* Free Software Foundation, Inc., * | |||
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * | |||
***************************************************************************/ | |||
/** | |||
* @file Defines USB descriptors, interrupt routines and helper functions. | |||
* To minimize code size, we make the following assumptions: | |||
* - The OpenULINK has exactly one configuration | |||
* - and exactly one alternate setting | |||
* | |||
* Therefore, we do not have to support the Set Configuration USB request. | |||
*/ | |||
#include "usb.h" | |||
#include "delay.h" | |||
#include "io.h" | |||
/* Also update external declarations in "include/usb.h" if making changes to | |||
* these variables! */ | |||
volatile bool EP2_out = 0; | |||
volatile bool EP2_in = 0; | |||
volatile __xdata __at 0x7FE8 setup_data_t setup_data; | |||
/* Define number of endpoints (except Control Endpoint 0) in a central place. | |||
* Be sure to include the neccessary endpoint descriptors! */ | |||
#define NUM_ENDPOINTS 2 | |||
/* | |||
* Normally, we would initialize the descriptor structures in C99 style: | |||
* | |||
* __code usb_device_descriptor_t device_descriptor = { | |||
* .bLength = foo, | |||
* .bDescriptorType = bar, | |||
* .bcdUSB = 0xABCD, | |||
* ... | |||
* }; | |||
* | |||
* But SDCC currently does not support this, so we have to do it the | |||
* old-fashioned way... | |||
*/ | |||
__code usb_device_descriptor_t device_descriptor = { | |||
/* .bLength = */ sizeof(usb_device_descriptor_t), | |||
/* .bDescriptorType = */ DESCRIPTOR_TYPE_DEVICE, | |||
/* .bcdUSB = */ 0x0110, /* BCD: 01.00 (Version 1.0 USB spec) */ | |||
/* .bDeviceClass = */ 0xFF, /* 0xFF = vendor-specific */ | |||
/* .bDeviceSubClass = */ 0xFF, | |||
/* .bDeviceProtocol = */ 0xFF, | |||
/* .bMaxPacketSize0 = */ 64, | |||
/* .idVendor = */ 0xC251, | |||
/* .idProduct = */ 0x2710, | |||
/* .bcdDevice = */ 0x0100, | |||
/* .iManufacturer = */ 1, | |||
/* .iProduct = */ 2, | |||
/* .iSerialNumber = */ 3, | |||
/* .bNumConfigurations = */ 1 | |||
}; | |||
/* WARNING: ALL config, interface and endpoint descriptors MUST be adjacent! */ | |||
__code usb_config_descriptor_t config_descriptor = { | |||
/* .bLength = */ sizeof(usb_config_descriptor_t), | |||
/* .bDescriptorType = */ DESCRIPTOR_TYPE_CONFIGURATION, | |||
/* .wTotalLength = */ sizeof(usb_config_descriptor_t) + | |||
sizeof(usb_interface_descriptor_t) + | |||
NUM_ENDPOINTS * sizeof(usb_endpoint_descriptor_t), | |||
/* .bNumInterfaces = */ 1, | |||
/* .bConfigurationValue = */ 1, | |||
/* .iConfiguration = */ 4, /* String describing this configuration */ | |||
/* .bmAttributes = */ 0x80, /* Only MSB set according to USB spec */ | |||
/* .MaxPower = */ 50 /* 100 mA */ | |||
}; | |||
__code usb_interface_descriptor_t interface_descriptor00 = { | |||
/* .bLength = */ sizeof(usb_interface_descriptor_t), | |||
/* .bDescriptorType = */ DESCRIPTOR_TYPE_INTERFACE, | |||
/* .bInterfaceNumber = */ 0, | |||
/* .bAlternateSetting = */ 0, | |||
/* .bNumEndpoints = */ NUM_ENDPOINTS, | |||
/* .bInterfaceClass = */ 0xFF, | |||
/* .bInterfaceSubclass = */ 0xFF, | |||
/* .bInterfaceProtocol = */ 0xFF, | |||
/* .iInterface = */ 0 | |||
}; | |||
__code usb_endpoint_descriptor_t Bulk_EP2_IN_Endpoint_Descriptor = { | |||
/* .bLength = */ sizeof(usb_endpoint_descriptor_t), | |||
/* .bDescriptorType = */ 0x05, | |||
/* .bEndpointAddress = */ 2 | USB_DIR_IN, | |||
/* .bmAttributes = */ 0x02, | |||
/* .wMaxPacketSize = */ 64, | |||
/* .bInterval = */ 0 | |||
}; | |||
__code usb_endpoint_descriptor_t Bulk_EP2_OUT_Endpoint_Descriptor = { | |||
/* .bLength = */ sizeof(usb_endpoint_descriptor_t), | |||
/* .bDescriptorType = */ 0x05, | |||
/* .bEndpointAddress = */ 2 | USB_DIR_OUT, | |||
/* .bmAttributes = */ 0x02, | |||
/* .wMaxPacketSize = */ 64, | |||
/* .bInterval = */ 0 | |||
}; | |||
__code usb_language_descriptor_t language_descriptor = { | |||
/* .bLength = */ 4, | |||
/* .bDescriptorType = */ DESCRIPTOR_TYPE_STRING, | |||
/* .wLANGID = */ {0x0409 /* US English */} | |||
}; | |||
__code usb_string_descriptor_t strManufacturer = STR_DESCR(9,'O','p','e','n','U','L','I','N','K'); | |||
__code usb_string_descriptor_t strProduct = STR_DESCR(9,'O','p','e','n','U','L','I','N','K'); | |||
__code usb_string_descriptor_t strSerialNumber = STR_DESCR(6, '0','0','0','0','0','1'); | |||
__code usb_string_descriptor_t strConfigDescr = STR_DESCR(12, 'J','T','A','G',' ','A','d','a','p','t','e','r'); | |||
/* Table containing pointers to string descriptors */ | |||
__code usb_string_descriptor_t* __code en_string_descriptors[4] = { | |||
&strManufacturer, | |||
&strProduct, | |||
&strSerialNumber, | |||
&strConfigDescr | |||
}; | |||
void sudav_isr(void) __interrupt SUDAV_ISR | |||
{ | |||
CLEAR_IRQ(); | |||
usb_handle_setup_data(); | |||
USBIRQ = SUDAVIR; | |||
EP0CS |= HSNAK; | |||
} | |||
void sof_isr(void) __interrupt SOF_ISR { } | |||
void sutok_isr(void) __interrupt SUTOK_ISR { } | |||
void suspend_isr(void) __interrupt SUSPEND_ISR { } | |||
void usbreset_isr(void) __interrupt USBRESET_ISR { } | |||
void ibn_isr(void) __interrupt IBN_ISR { } | |||
void ep0in_isr(void) __interrupt EP0IN_ISR { } | |||
void ep0out_isr(void) __interrupt EP0OUT_ISR { } | |||
void ep1in_isr(void) __interrupt EP1IN_ISR { } | |||
void ep1out_isr(void) __interrupt EP1OUT_ISR { } | |||
/** | |||
* EP2 IN: called after the transfer from uC->Host has finished: we sent data | |||
*/ | |||
void ep2in_isr(void) __interrupt EP2IN_ISR { | |||
EP2_in = 1; | |||
CLEAR_IRQ(); | |||
IN07IRQ = IN2IR; // Clear OUT2 IRQ | |||
} | |||
/** | |||
* EP2 OUT: called after the transfer from Host->uC has finished: we got data | |||
*/ | |||
void ep2out_isr(void) __interrupt EP2OUT_ISR { | |||
EP2_out = 1; | |||
CLEAR_IRQ(); | |||
OUT07IRQ = OUT2IR; // Clear OUT2 IRQ | |||
} | |||
void ep3in_isr(void) __interrupt EP3IN_ISR { } | |||
void ep3out_isr(void) __interrupt EP3OUT_ISR { } | |||
void ep4in_isr(void) __interrupt EP4IN_ISR { } | |||
void ep4out_isr(void) __interrupt EP4OUT_ISR { } | |||
void ep5in_isr(void) __interrupt EP5IN_ISR { } | |||
void ep5out_isr(void) __interrupt EP5OUT_ISR { } | |||
void ep6in_isr(void) __interrupt EP6IN_ISR { } | |||
void ep6out_isr(void) __interrupt EP6OUT_ISR { } | |||
void ep7in_isr(void) __interrupt EP7IN_ISR { } | |||
void ep7out_isr(void) __interrupt EP7OUT_ISR { } | |||
/** | |||
* Return the control/status register for an endpoint | |||
* | |||
* @param ep endpoint address | |||
* @return on success: pointer to Control & Status register for endpoint | |||
* specified in \a ep | |||
* @return on failure: NULL | |||
*/ | |||
__xdata u8* usb_get_endpoint_cs_reg(u8 ep) | |||
{ | |||
/* Mask direction bit */ | |||
u8 ep_num = ep & 0x7F; | |||
switch (ep_num) { | |||
case 0: | |||
return &EP0CS; | |||
break; | |||
case 1: | |||
return ep & 0x80 ? &IN1CS : &OUT1CS; | |||
break; | |||
case 2: | |||
return ep & 0x80 ? &IN2CS : &OUT2CS; | |||
break; | |||
case 3: | |||
return ep & 0x80 ? &IN3CS : &OUT3CS; | |||
break; | |||
case 4: | |||
return ep & 0x80 ? &IN4CS : &OUT4CS; | |||
break; | |||
case 5: | |||
return ep & 0x80 ? &IN5CS : &OUT5CS; | |||
break; | |||
case 6: | |||
return ep & 0x80 ? &IN6CS : &OUT6CS; | |||
break; | |||
case 7: | |||
return ep & 0x80 ? &IN7CS : &OUT7CS; | |||
break; | |||
} | |||
return NULL; | |||
} | |||
void usb_reset_data_toggle(u8 ep) | |||
{ | |||
/* TOGCTL register: | |||
+----+-----+-----+------+-----+-------+-------+-------+ | |||
| Q | S | R | IO | 0 | EP2 | EP1 | EP0 | | |||
+----+-----+-----+------+-----+-------+-------+-------+ | |||
To reset data toggle bits, we have to write the endpoint direction (IN/OUT) | |||
to the IO bit and the endpoint number to the EP2..EP0 bits. Then, in a | |||
separate write cycle, the R bit needs to be set. | |||
*/ | |||
u8 togctl_value = (ep & 0x80 >> 3) | (ep & 0x7); | |||
/* First step: Write EP number and direction bit */ | |||
TOGCTL = togctl_value; | |||
/* Second step: Set R bit */ | |||
togctl_value |= TOG_R; | |||
TOGCTL = togctl_value; | |||
} | |||
/** | |||
* Handle GET_STATUS request. | |||
* | |||
* @return on success: true | |||
* @return on failure: false | |||
*/ | |||
bool usb_handle_get_status(void) | |||
{ | |||
u8 *ep_cs; | |||
switch (setup_data.bmRequestType) { | |||
case GS_DEVICE: | |||
/* Two byte response: Byte 0, Bit 0 = self-powered, Bit 1 = remote wakeup. | |||
* Byte 1: reserved, reset to zero */ | |||
IN0BUF[0] = 0; | |||
IN0BUF[1] = 0; | |||
/* Send response */ | |||
IN0BC = 2; | |||
break; | |||
case GS_INTERFACE: | |||
/* Always return two zero bytes according to USB 1.1 spec, p. 191 */ | |||
IN0BUF[0] = 0; | |||
IN0BUF[1] = 0; | |||
/* Send response */ | |||
IN0BC = 2; | |||
break; | |||
case GS_ENDPOINT: | |||
/* Get stall bit for endpoint specified in low byte of wIndex */ | |||
ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex & 0xff); | |||
if (*ep_cs & EPSTALL) { | |||
IN0BUF[0] = 0x01; | |||
} | |||
else { | |||
IN0BUF[0] = 0x00; | |||
} | |||
/* Second byte sent has to be always zero */ | |||
IN0BUF[1] = 0; | |||
/* Send response */ | |||
IN0BC = 2; | |||
break; | |||
default: | |||
return false; | |||
break; | |||
} | |||
return true; | |||
} | |||
/** | |||
* Handle CLEAR_FEATURE request. | |||
* | |||
* @return on success: true | |||
* @return on failure: false | |||
*/ | |||
bool usb_handle_clear_feature(void) | |||
{ | |||
__xdata u8 *ep_cs; | |||
switch (setup_data.bmRequestType) { | |||
case CF_DEVICE: | |||
/* Clear remote wakeup not supported: stall EP0 */ | |||
STALL_EP0(); | |||
break; | |||
case CF_ENDPOINT: | |||
if (setup_data.wValue == 0) { | |||
/* Unstall the endpoint specified in wIndex */ | |||
ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex); | |||
if (!ep_cs) { | |||
return false; | |||
} | |||
*ep_cs &= ~EPSTALL; | |||
} | |||
else { | |||
/* Unsupported feature, stall EP0 */ | |||
STALL_EP0(); | |||
} | |||
break; | |||
default: | |||
/* Vendor commands... */ | |||
} | |||
return true; | |||
} | |||
/** | |||
* Handle SET_FEATURE request. | |||
* | |||
* @return on success: true | |||
* @return on failure: false | |||
*/ | |||
bool usb_handle_set_feature(void) | |||
{ | |||
__xdata u8 *ep_cs; | |||
switch (setup_data.bmRequestType) { | |||
case SF_DEVICE: | |||
if (setup_data.wValue == 2) { | |||
return true; | |||
} | |||
break; | |||
case SF_ENDPOINT: | |||
if (setup_data.wValue == 0) { | |||
/* Stall the endpoint specified in wIndex */ | |||
ep_cs = usb_get_endpoint_cs_reg(setup_data.wIndex); | |||
if (!ep_cs) { | |||
return false; | |||
} | |||
*ep_cs |= EPSTALL; | |||
} | |||
else { | |||
/* Unsupported endpoint feature */ | |||
return false; | |||
} | |||
break; | |||
default: | |||
/* Vendor commands... */ | |||
break; | |||
} | |||
return true; | |||
} | |||
/** | |||
* Handle GET_DESCRIPTOR request. | |||
* | |||
* @return on success: true | |||
* @return on failure: false | |||
*/ | |||
bool usb_handle_get_descriptor(void) | |||
{ | |||
__xdata u8 descriptor_type; | |||
__xdata u8 descriptor_index; | |||
descriptor_type = (setup_data.wValue & 0xff00) >> 8; | |||
descriptor_index = setup_data.wValue & 0x00ff; | |||
switch (descriptor_type) { | |||
case DESCRIPTOR_TYPE_DEVICE: | |||
SUDPTRH = HI8(&device_descriptor); | |||
SUDPTRL = LO8(&device_descriptor); | |||
break; | |||
case DESCRIPTOR_TYPE_CONFIGURATION: | |||
SUDPTRH = HI8(&config_descriptor); | |||
SUDPTRL = LO8(&config_descriptor); | |||
break; | |||
case DESCRIPTOR_TYPE_STRING: | |||
if (setup_data.wIndex == 0) { | |||
/* Supply language descriptor */ | |||
SUDPTRH = HI8(&language_descriptor); | |||
SUDPTRL = LO8(&language_descriptor); | |||
} | |||
else if (setup_data.wIndex == 0x0409 /* US English */) { | |||
/* Supply string descriptor */ | |||
SUDPTRH = HI8(en_string_descriptors[descriptor_index - 1]); | |||
SUDPTRL = LO8(en_string_descriptors[descriptor_index - 1]); | |||
} | |||
else { | |||
return false; | |||
} | |||
break; | |||
default: | |||
/* Unsupported descriptor type */ | |||
return false; | |||
break; | |||
} | |||
return true; | |||
} | |||
/** | |||
* Handle SET_INTERFACE request. | |||
*/ | |||
void usb_handle_set_interface(void) | |||
{ | |||
/* Reset Data Toggle */ | |||
usb_reset_data_toggle(USB_DIR_IN | 2); | |||
usb_reset_data_toggle(USB_DIR_OUT | 2); | |||
/* Unstall & clear busy flag of all valid IN endpoints */ | |||
IN2CS = 0 | EPBSY; | |||
/* Unstall all valid OUT endpoints, reset bytecounts */ | |||
OUT2CS = 0; | |||
OUT2BC = 0; | |||
} | |||
/** | |||
* Handle the arrival of a USB Control Setup Packet. | |||
*/ | |||
void usb_handle_setup_data(void) | |||
{ | |||
switch (setup_data.bRequest) { | |||
case GET_STATUS: | |||
if (!usb_handle_get_status()) { | |||
STALL_EP0(); | |||
} | |||
break; | |||
case CLEAR_FEATURE: | |||
if (!usb_handle_clear_feature()) { | |||
STALL_EP0(); | |||
} | |||
break; | |||
case 2: case 4: | |||
/* Reserved values */ | |||
STALL_EP0(); | |||
break; | |||
case SET_FEATURE: | |||
if (!usb_handle_set_feature()) { | |||
STALL_EP0(); | |||
} | |||
break; | |||
case SET_ADDRESS: | |||
/* Handled by USB core */ | |||
break; | |||
case SET_DESCRIPTOR: | |||
/* Set Descriptor not supported. */ | |||
STALL_EP0(); | |||
break; | |||
case GET_DESCRIPTOR: | |||
if (!usb_handle_get_descriptor()) { | |||
STALL_EP0(); | |||
} | |||
break; | |||
case GET_CONFIGURATION: | |||
/* OpenULINK has only one configuration, return its index */ | |||
IN0BUF[0] = config_descriptor.bConfigurationValue; | |||
IN0BC = 1; | |||
break; | |||
case SET_CONFIGURATION: | |||
/* OpenULINK has only one configuration -> nothing to do */ | |||
break; | |||
case GET_INTERFACE: | |||
/* OpenULINK only has one interface, return its number */ | |||
IN0BUF[0] = interface_descriptor00.bInterfaceNumber; | |||
IN0BC = 1; | |||
break; | |||
case SET_INTERFACE: | |||
usb_handle_set_interface(); | |||
break; | |||
case SYNCH_FRAME: | |||
/* Isochronous endpoints not used -> nothing to do */ | |||
break; | |||
default: | |||
/* Any other requests: do nothing */ | |||
break; | |||
} | |||
} | |||
/** | |||
* USB initialization. Configures USB interrupts, endpoints and performs | |||
* ReNumeration. | |||
*/ | |||
void usb_init(void) { | |||
/* Mark endpoint 2 IN & OUT as valid */ | |||
IN07VAL = IN2VAL; | |||
OUT07VAL = OUT2VAL; | |||
/* Make sure no isochronous endpoints are marked valid */ | |||
INISOVAL = 0; | |||
OUTISOVAL = 0; | |||
/* Disable isochronous endpoints. This makes the isochronous data buffers | |||
* available as 8051 XDATA memory at address 0x2000 - 0x27FF */ | |||
ISOCTL = ISODISAB; | |||
/* Enable USB Autovectoring */ | |||
USBBAV |= AVEN; | |||
/* Enable SUDAV interrupt */ | |||
USBIEN |= SUDAVIE; | |||
/* Enable EP2 OUT & IN interrupts */ | |||
OUT07IEN = OUT2IEN; | |||
IN07IEN = IN2IEN; | |||
/* Enable USB interrupt (EIE register) */ | |||
EUSB = 1; | |||
/* Perform ReNumeration */ | |||
USBCS = DISCON | RENUM; | |||
delay_ms(200); | |||
USBCS = DISCOE | RENUM; | |||
} |
@@ -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 |