contrib/firmware: add new adapter ANGIE's firmware/bitstream code

This is ANGIE's firmware and bitstream code.
The 'Embeded C' code is based on the openULINK project.
The hdl bitstream source code is for the spartan-6 FPGA included in
ANGIE.

Since ANGIE has a different microcontroller (EZ-USB FX2) than openULINK
(EZ-USB AN2131), the registers file (reg_ezusb.h) has been changed
completely, so are the descriptors, interruptions and the endpoints
configuration.

Change-Id: I70590c7c58bac6f1939c5ffba57e87d86850664d
Signed-off-by: Ahmed BOUDJELIDA <aboudjelida@nanoxplore.com>
Reviewed-on: https://review.openocd.org/c/openocd/+/7701
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
Ahmed BOUDJELIDA 2023-06-16 23:19:05 +02:00 committed by Antonio Borneo
parent 3b78b5c1db
commit 9c91ce8d24
25 changed files with 3847 additions and 0 deletions

View File

@ -0,0 +1,75 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#****************************************************************************
# File : Makefile *
# Contents : Code for NanoXplore USB-JTAG ANGIE adapter hardware. *
# Based on openULINK project by: Martin Schmoelzer. *
# Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
# <aboudjelida@nanoxplore.com> *
# <ahmederrachedbjld@gmail.com> *
# ***************************************************************************/
# Define the name of tools.
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 = 0x3C00
XRAM_LOC = 0x3C00
XRAM_SIZE = 0x0400
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 serial.rel gpif.rel
HEADERS = $(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)/serial.h \
$(INCLUDE_DIR)/fx2macros.h \
$(INCLUDE_DIR)/msgtypes.h
# Disable all built-in rules.
.SUFFIXES:
# Targets which are executed even when identically named file is present.
.PHONY: all, clean
all: angie_firmware.ihx
$(SIZE) angie_firmware.ihx
angie_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 *.lk *.map *.mem
bin: angie_firmware.ihx
makebin -p angie_firmware.ihx angie_firmware.bin

View File

@ -0,0 +1,37 @@
#SPDX-License-Identifier: GPL-2.0-or-later
This is the ANGIE firmware for ANGIE USB-JTAG adapter.
The main components of ANGIE adapter are:
- Cypress EZ-USB FX2 microcontroller
- Spartan-6 FPGA
- SRAM memory chip
- Pin headers for various JTAG pin assignments
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 ANGIE directory to compile the firmware.
"make clean" will remove all generated files except the Intel HEX file
required for downloading the firmware to ANGIE.
Note that the EZ-USB FX2 microcontroller does not have on-chip flash,
ANGIE include on-board EEPROM memory to store the firmware program of
the FX2, but we are not going to use this method.
Instead, upon initial connection of the ANGIE adapter to the host PC
via USB, the EZ-USB FX2 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) ANGIE device.
Once the firmware downloaded, the FX2 microcontroller activate its GPIF mode,
download the Spartan-6 FPGA's bitstream, program the FPGA rapidly, and switch
back to default io mode.
Once the user disconnects the ANGIE adapter, all its memory contents are lost
and the firmware & bitstream download process has to be executed again.

View File

@ -0,0 +1,50 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/****************************************************************
File : delay.h *
Contents : Delays handling header file for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************/
#ifndef __DELAY_H
#define __DELAY_H
#include <stdint.h>
void syncdelay(uint8_t count);
void delay_5us(void);
void delay_1ms(void);
void delay_us(uint16_t delay);
void delay_ms(uint16_t delay);
#ifndef _IFREQ
#define _IFREQ 48000 /* IFCLK frequency in kHz */
#endif
/* CFREQ can be any one of: 48000, 24000, or 12000 */
#ifndef _CFREQ
#define _CFREQ 48000 /* CLKOUT frequency in kHz */
#endif
#if (_IFREQ < 5000)
#error "_IFREQ too small! Valid Range: 5000 to 48000..."
#endif
#if (_IFREQ > 48000)
#error "_IFREQ too large! Valid Range: 5000 to 48000..."
#endif
#if (_CFREQ != 48000)
#if (_CFREQ != 24000)
#if (_CFREQ != 12000)
#error "_CFREQ invalid! Valid values: 48000, 24000, 12000..."
#endif
#endif
#endif
/* Synchronization Delay formula: see TRM section 15-14 */
#define _SCYCL (3 * (_CFREQ) + 5 * (_IFREQ) - 1) / (2 * (_IFREQ))
#endif

View File

@ -0,0 +1,31 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* This code was taken from the fx2lib project from this link:
* https://github.com/djmuhlestein/fx2lib
*
* Copyright (C) 2009 Ubixum, Inc.
*/
/*! \file
* Macros for simple common tasks in fx2 firmware.
* */
#ifndef FX2MACROS_H
#define FX2MACROS_H
#include "reg_ezusb.h"
typedef enum {FALSE = 0, TRUE} BOOL_VALS;
/**
* \brief Used for getting and setting the CPU clock speed.
**/
typedef enum {CLK_12M = 0, CLK_24M, CLK_48M} CLK_SPD;
/**
* \brief Evaluates to a CLK_SPD enum.
**/
#define CPUFREQ (CLK_SPD)((CPUCS & bmclkspd) >> 3)
#endif

View File

@ -0,0 +1,65 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/****************************************************************************
File : io.h *
Contents : input/output declaration header file for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#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 *
* SRST ..... Chip Reset *
***************************************************************************/
/* PORT A */
/* PA0 Not Connected */
/* PA1 Not Connected */
#define PIN_RDWR_B IOA2
#define PIN_CSI_B IOA3
#define PIN_INIT_B IOA4
#define PIN_PROGRAM_B IOA5
/* PA6 Not Connected */
/* PA7 Not Connected */
/* PORT B */
#define PIN_TRST IOB0
#define PIN_TMS IOB1
#define PIN_TCK IOB2
#define PIN_TDI IOB3
#define PIN_TDO IOB4
#define PIN_SRST IOB5
/* PA6 Not Connected */
/* PA7 Not Connected */
/* JTAG Signals with direction 'OUT' on port B */
/* PIN_TDI - PIN_TCK - PIN_TMS - PIN_TRST - PIN_SRST */
#define MASK_PORTB_DIRECTION_OUT (bmbit0 | bmbit1 | bmbit2 | bmbit3 | bmbit5)
/* PORT C */ // Debug:
#define PIN_T0 IOC0
#define PIN_T1 IOC1
#define PIN_T2 IOC2
#define PIN_T3 IOC3
#define PIN_T4 IOC4
/* PC5 Not Connected */
/* PC6 Not Connected */
/* PC7 Not Connected */
#endif

View File

@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/****************************************************************************
File : jtag.h *
Contents : Jtag handling functions header file for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#ifndef __JTAG_H
#define __JTAG_H
#include <stdint.h>
uint16_t jtag_get_signals(void);
void jtag_configure_tck_delay(uint8_t scan_in, uint8_t scan_out,
uint8_t scan_io, uint8_t tck, uint8_t tms);
void jtag_clock_tms(uint8_t count, uint8_t sequence);
void jtag_slow_clock_tms(uint8_t count, uint8_t sequence);
void jtag_set_signals(uint8_t low, uint8_t high);
void jtag_clock_tck(uint16_t count);
void jtag_slow_clock_tck(uint16_t count);
void jtag_scan_in(uint8_t out_offset, uint8_t in_offset);
void jtag_scan_out(uint8_t out_offset);
void jtag_scan_io(uint8_t out_offset, uint8_t in_offset);
void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset);
void jtag_slow_scan_out(uint8_t out_offset);
void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset);
#endif

View File

@ -0,0 +1,171 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/****************************************************************************
File : msgtypes.h *
Contents : Definition of the commands supported by NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
/**
* @file
* Definition of the commands supported by the ANGIE 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, CMD_SLOW_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_in function *
* offset 2: delay value for scan_out function *
* offset 3: delay value for scan_io function *
* offset 4: delay value for clock_tck function *
* offset 5: 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_SLOW_CLOCK_TCK 0x23
#define CMD_SLEEP_US 0x24
#define CMD_SLEEP_MS 0x25
#define CMD_GET_SIGNALS 0x26
#define CMD_SET_SIGNALS 0x27
#define CMD_CONFIGURE_TCK_FREQ 0x28
#define CMD_SET_LEDS 0x29
#define CMD_TEST 0x2A
/* JTAG signal definition for jtag_get_signals() -- Input signals! */
#define SIGNAL_TDO 1
/* JTAG signal definition for jtag_get_signals() -- Output signals! */
#define SIGNAL_TDI 8
#define SIGNAL_TMS 2
#define SIGNAL_TCK 4
#define SIGNAL_TRST 1
#define SIGNAL_SRST 32
#endif

View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/****************************************************************************
File : protocol.h *
Contents : Jtag commands handling protocol header file for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#ifndef __PROTOCOL_H
#define __PROTOCOL_H
#include <stdbool.h>
bool execute_command(void);
void command_loop(void);
#endif

View File

@ -0,0 +1,656 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/****************************************************************************
File : reg_ezusb.h *
Contents : FX2 microcontroller registers file for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#ifndef REG_EZUSB_H
#define REG_EZUSB_H
/**
* @file
* All information in this file was taken from the EZ-USB FX2 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 FX2 TRM" hereafter.
*/
/* 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 **********************
***************************************************************************/
SFR(IOA, 0x80);
SBIT(IOA0, 0x80, 0);
SBIT(IOA1, 0x80, 1);
SBIT(IOA2, 0x80, 2);
SBIT(IOA3, 0x80, 3);
SBIT(IOA4, 0x80, 4);
SBIT(IOA5, 0x80, 5);
SBIT(IOA6, 0x80, 6);
SBIT(IOA7, 0x80, 7);
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);
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, 0x8F);
#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(IOB, 0x90);
SBIT(IOB0, 0x90, 0);
SBIT(IOB1, 0x90, 1);
SBIT(IOB2, 0x90, 2);
SBIT(IOB3, 0x90, 3);
SBIT(IOB4, 0x90, 4);
SBIT(IOB5, 0x90, 5);
SBIT(IOB6, 0x90, 6);
SBIT(IOB7, 0x90, 7);
SFR(EXIF, 0x91);
SBIT(USBINT, 0x91, 4);
SBIT(I2CINT, 0x91, 5);
SBIT(IE4, 0x91, 6);
SBIT(IE5, 0x91, 7);
SFR(MPAGE, 0x92);
SFR(SCON0, 0x98);
SBIT(RI, 0x98, 0);
SBIT(TI, 0x98, 1);
SBIT(RB8, 0x98, 2);
SBIT(TB8, 0x98, 3);
SBIT(REN, 0x98, 4);
SBIT(SM2, 0x98, 5);
SBIT(SM1, 0x98, 6);
SBIT(SM0, 0x98, 7);
SFR(SBUF0, 0x99);
SFR(AUTOPTRH1, 0x9A);
SFR(AUTOPTRL1, 0x9B);
SFR(AUTOPTRH2, 0x9D);
SFR(AUTOPTRL2, 0x9E);
#define AUTOPTR1H AUTOPTRH1 /* for backwards compatibility with examples */
#define AUTOPTR1L AUTOPTRL1 /* for backwards compatibility with examples */
#define APTR1H AUTOPTRH1 /* for backwards compatibility with examples */
#define APTR1L AUTOPTRL1 /* for backwards compatibility with examples */
SFR(IOC, 0xA0);
SBIT(IOC0, 0xA0, 0);
SBIT(IOC1, 0xA0, 1);
SBIT(IOC2, 0xA0, 2);
SBIT(IOC3, 0xA0, 3);
SBIT(IOC4, 0xA0, 4);
SBIT(IOC5, 0xA0, 5);
SBIT(IOC6, 0xA0, 6);
SBIT(IOC7, 0xA0, 7);
SFR(INT2CLR, 0xA1);
SFR(INT4CLR, 0xA2);
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(EP2468STAT, 0xAA);
#define EP8F bmbit7
#define EP8E bmbit6
#define EP6F bmbit5
#define EP6E bmbit4
#define EP4F bmbit3
#define EP4E bmbit2
#define EP2F bmbit1
#define EP2E bmbit0
SFR(EP24FIFOFLGS, 0xAB);
SFR(EP68FIFOFLGS, 0xAC);
SFR(AUTOPTRSETUP, 0xAF);
SFR(IOD, 0xB0);
SBIT(IOD0, 0xB0, 0);
SBIT(IOD1, 0xB0, 1);
SBIT(IOD2, 0xB0, 2);
SBIT(IOD3, 0xB0, 3);
SBIT(IOD4, 0xB0, 4);
SBIT(IOD5, 0xB0, 5);
SBIT(IOD6, 0xB0, 6);
SBIT(IOD7, 0xB0, 7);
SFR(IOE, 0xB1);
SFR(OEA, 0xB2);
SFR(OEB, 0xB3);
SFR(OEC, 0xB4);
SFR(OED, 0xB5);
SFR(OEE, 0xB6);
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(EP01STAT, 0xBA);
SFR(GPIFTRIG, 0xBB);
#define BMGPIFDONE bmbit7
#define BMGPIFREAD bmbit2
#define GPIF_EP2 0
#define GPIF_EP4 1
#define GPIF_EP6 2
#define GPIF_EP8 3
SFR(GPIFSGLDATH, 0xBD);
SFR(GPIFSGLDATLX, 0xBE);
SFR(GPIFSGLDATLNOX, 0xBF);
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(C_T2, 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 ****************************
***************************************************************************/
SFRX(GPIF_WAVE_DATA, 0xE400);
SFRX(RES_WAVEDATA_END, 0xE480);
/* General Configuration */
SFRX(CPUCS, 0xE600);
#define RES8051 bmbit0
#define CLKOE bmbit1
#define BMCLKINV bmbit2
#define bmclkspd0 bmbit3
#define bmclkspd1 bmbit4
#define bmclkspd (bmbit4 | bmbit3)
#define BMPRTCSTB bmbit5
/* PCON register */
#define BMSMOD0 bmbit7
SFRX(IFCONFIG, 0xE601);
#define BMIFCLKSRC bmbit7
#define BM3048MHZ bmbit6
#define BMIFCLKOE bmbit5
#define BMIFCLKPOL bmbit4
#define BMASYNC bmbit3
#define BMGSTATE bmbit2
#define BMIFCFG1 bmbit1
#define BMIFCFG0 bmbit0
#define BMIFCFGMASK (BMIFCFG0 | BMIFCFG1)
#define BMIFGPIF BMIFCFG1
SFRX(PINFLAGSAB, 0xE602);
SFRX(PINFLAGSCD, 0xE603);
SFRX(FIFORESET, 0xE604);
#define BMNAKALL bmbit7
SFRX(BREAKPT, 0xE605);
#define BMBREAK bmbit3
#define BMBPPULSE bmbit2
#define BMBPEN bmbit1
SFRX(BPADDRH, 0xE606);
SFRX(BPADDRL, 0xE607);
SFRX(UART230, 0xE608);
SFRX(FIFOPINPOLAR, 0xE609);
SFRX(REVID, 0xE60A);
SFRX(REVCTL, 0xE60B);
#define BMNOAUTOARM bmbit1
#define BMSKIPCOMMIT bmbit0
/* Endpoint Configuration */
SFRX(EP1OUTCFG, 0xE610);
SFRX(EP1INCFG, 0xE611);
SFRX(EP2CFG, 0xE612);
SFRX(EP4CFG, 0xE613);
SFRX(EP6CFG, 0xE614);
SFRX(EP8CFG, 0xE615);
SFRX(EP2FIFOCFG, 0xE618);
SFRX(EP4FIFOCFG, 0xE619);
SFRX(EP6FIFOCFG, 0xE61A);
SFRX(EP8FIFOCFG, 0xE61B);
#define BMINFM bmbit6
#define BMOEP bmbit5
#define BMAUTOOUT bmbit4
#define BMAUTOIN bmbit3
#define BMZEROLENIN bmbit2
#define BMWORDWIDE bmbit0
SFRX(EP2AUTOINLENH, 0xE620);
SFRX(EP2AUTOINLENL, 0xE621);
SFRX(EP4AUTOINLENH, 0xE622);
SFRX(EP4AUTOINLENL, 0xE623);
SFRX(EP6AUTOINLENH, 0xE612);
SFRX(EP6AUTOINLENL, 0xE613);
SFRX(EP8AUTOINLENH, 0xE614);
SFRX(EP8AUTOINLENL, 0xE615);
SFRX(EP2FIFOPFH, 0xE630);
SFRX(EP2FIFOPFL, 0xE631);
SFRX(EP4FIFOPFH, 0xE632);
SFRX(EP4FIFOPFL, 0xE633);
SFRX(EP6FIFOPFH, 0xE634);
SFRX(EP6FIFOPFL, 0xE635);
SFRX(EP8FIFOPFH, 0xE636);
SFRX(EP8FIFOPFL, 0xE637);
SFRX(EP2ISOINPKTS, 0xE640);
SFRX(EP4ISOINPKTS, 0xE641);
SFRX(EP6ISOINPKTS, 0xE642);
SFRX(EP8ISOINPKTS, 0xE643);
SFRX(INPKTEND, 0xE648);
SFRX(OUTPKTEND, 0xE649);
/* Interrupts */
SFRX(EP2FIFOIE, 0xE650);
SFRX(EP2FIFOIRQ, 0xE651);
SFRX(EP4FIFOIE, 0xE652);
SFRX(EP4FIFOIRQ, 0xE653);
SFRX(EP6FIFOIE, 0xE654);
SFRX(EP6FIFOIRQ, 0xE655);
SFRX(EP8FIFOIE, 0xE656);
SFRX(EP8FIFOIRQ, 0xE657);
SFRX(IBNIE, 0xE658);
SFRX(IBNIRQ, 0xE659);
#define EP0IBN bmbit0
#define EP1IBN bmbit1
#define EP2IBN bmbit2
#define EP4IBN bmbit3
#define EP6IBN bmbit4
#define EP8IBN bmbit5
SFRX(NAKIE, 0xE65A);
SFRX(NAKIRQ, 0xE65B);
#define EP8PING bmbit7
#define EP6PING bmbit6
#define EP4PING bmbit5
#define EP2PING bmbit4
#define EP1PING bmbit3
#define EP0PING bmbit2
#define IBN bmbit0
SFRX(USBIEN, 0xE65C);
SFRX(USBIRQ, 0xE65D);
#define SUDAVI bmbit0
#define SOFI bmbit1
#define SUTOKI bmbit2
#define SUSPI bmbit3
#define URESI bmbit4
#define HSGRANT bmbit5
#define EP0ACK bmbit6
SFRX(EPIE, 0xE65E);
SFRX(EPIRQ, 0xE65F);
SFRX(GPIFIE, 0xE660);
SFRX(GPIFIRQ, 0xE661);
SFRX(USBERRIE, 0xE662);
SFRX(USBERRIRQ, 0xE663);
SFRX(ERRCNTLIM, 0xE664);
SFRX(CLRERRCNT, 0xE665);
SFRX(INT2IVEC, 0xE666);
#define I2V0 bmbit2
#define I2V1 bmbit3
#define I2V2 bmbit4
#define I2V3 bmbit5
#define I2V4 bmbit6
SFRX(INT4IVEC, 0xE667);
SFRX(INTSETUP, 0xE668);
#define AV4EN bmbit0
#define INT4IN bmbit1
#define AV2EN bmbit3
/* Input/Output */
SFRX(PORTACFG, 0xE670);
#define BMINT0 bmbit0
#define BMINT1 bmbit1
#define BMFLAGD bmbit7
SFRX(PORTCCFG, 0xE671);
#define BMGPIFA0 bmbit0
#define BMGPIFA1 bmbit1
#define BMGPIFA2 bmbit2
#define BMGPIFA3 bmbit3
#define BMGPIFA4 bmbit4
#define BMGPIFA5 bmbit5
#define BMGPIFA6 bmbit6
#define BMGPIFA7 bmbit7
SFRX(PORTECFG, 0xE672);
#define BMT0OUT bmbit0
#define BMT1OUT bmbit1
#define BMT2OUT bmbit2
#define BMRXD0OUT bmbit3
#define BMRXD1OUT bmbit4
#define BMINT6 bmbit5
#define BMT2EX bmbit6
#define BMGPIFA8 bmbit7
SFRX(I2CS, 0xE678);
#define BMDONE bmbit0
#define BMACK bmbit1
#define BMBERR bmbit2
#define BMID (bmbit4 | bmbit3)
#define BMLASTRD bmbit5
#define BMSTOP bmbit6
#define BMSTART bmbit7
SFRX(I2DAT, 0xE679);
SFRX(I2CTL, 0xE67A);
#define BMSTOPIE bmbit1
#define BM400KHZ bmbit0
SFRX(XAUTODAT1, 0xE67B);
SFRX(XAUTODAT2, 0xE67C);
#define EXTAUTODAT1 XAUTODAT1
#define EXTAUTODAT2 XAUTODAT2
/* USB Control */
SFRX(USBCS, 0xE680);
#define SIGRSUME bmbit0
#define RENUM bmbit1
#define NOSYNSOF bmbit2
#define DISCON bmbit3
#define HSM bmbit7
SFRX(SUSPEND, 0xE681);
SFRX(WAKEUPCS, 0xE682);
#define BMWU2 bmbit7
#define BMWU bmbit6
#define BMWU2POL bmbit5
#define BMWUPOL bmbit4
#define BMDPEN bmbit2
#define BMWU2EN bmbit1
#define BMWUEN bmbit0
SFRX(TOGCTL, 0xE683);
#define BMTOGCTLEPMASK bmbit3 | bmbit2 | bmbit1 | bmbit0
#define BMRESETTOGGLE bmbit5
#define BMSETTOGGLE bmbit6
#define BMQUERYTOGGLE bmbit7
SFRX(USBFRAMEH, 0xE684);
SFRX(USBFRAMEL, 0xE685);
SFRX(MICROFRAME, 0xE686);
SFRX(FNADDR, 0xE687);
/* Endpoints */
SFRX(EP0BCH, 0xE68A);
SFRX(EP0BCL, 0xE68B);
SFRX(EP1OUTBC, 0xE68D);
SFRX(EP1INBC, 0xE68F);
SFRX(EP2BCH, 0xE690);
SFRX(EP2BCL, 0xE691);
SFRX(EP4BCH, 0xE694);
SFRX(EP4BCL, 0xE695);
SFRX(EP6BCH, 0xE698);
SFRX(EP6BCL, 0xE699);
SFRX(EP8BCH, 0xE69C);
SFRX(EP8BCL, 0xE69D);
SFRX(EP0CS, 0xE6A0);
#define HSNAK bmbit7
SFRX(EP1INCS, 0xE6A2);
SFRX(EP1OUTCS, 0xE6A1);
#define EPSTALL bmbit0
#define EPBSY bmbit1
SFRX(EP2CS, 0xE6A3);
SFRX(EP4CS, 0xE6A4);
SFRX(EP6CS, 0xE6A5);
SFRX(EP8CS, 0xE6A6);
#define BMEPEMPTY bmbit2
#define BMEPFULL bmbit3
#define BMNPAK (bmbit6 | bmbit5 | bmbit4)
SFRX(EP2FIFOFLGS, 0xE6A7);
SFRX(EP4FIFOFLGS, 0xE6A8);
SFRX(EP6FIFOFLGS, 0xE6A9);
SFRX(EP8FIFOFLGS, 0xE6AA);
SFRX(EP2FIFOBCH, 0xE6AB);
SFRX(EP2FIFOBCL, 0xE6AC);
SFRX(EP4FIFOBCH, 0xE6AD);
SFRX(EP4FIFOBCL, 0xE6AE);
SFRX(EP6FIFOBCH, 0xE6AF);
SFRX(EP6FIFOBCL, 0xE6B0);
SFRX(EP8FIFOBCH, 0xE6B1);
SFRX(EP8FIFOBCL, 0xE6B2);
SFRX(SUDPTRH, 0xE6B3);
SFRX(SUDPTRL, 0xE6B4);
SFRX(SUDPTRCTL, 0xE6B5);
#define BMSDPAUTO bmbit0
SFRX(SETUPDAT[8], 0xE6B8);
/* GPIF */
SFRX(GPIFWFSELECT, 0xE6C0);
SFRX(GPIFIDLECS, 0xE6C1);
SFRX(GPIFIDLECTL, 0xE6C2);
SFRX(GPIFCTLCFG, 0xE6C3);
SFRX(GPIFADRH, 0xE6C4);
SFRX(GPIFADRL, 0xE6C5);
SFRX(GPIFTCB3, 0xE6CE);
SFRX(GPIFTCB2, 0xE6CF);
SFRX(GPIFTCB1, 0xE6D0);
SFRX(GPIFTCB0, 0xE6D1);
#define EP2GPIFTCH GPIFTCB1 /* these are here for backwards compatibility */
#define EP2GPIFTCL GPIFTCB0
#define EP4GPIFTCH GPIFTCB1 /* these are here for backwards compatibility */
#define EP4GPIFTCL GPIFTCB0
#define EP6GPIFTCH GPIFTCB1 /* these are here for backwards compatibility */
#define EP6GPIFTCL GPIFTCB0
#define EP8GPIFTCH GPIFTCB1 /* these are here for backwards compatibility */
#define EP8GPIFTCL GPIFTCB0
SFRX(EP2GPIFFLGSEL, 0xE6D2);
SFRX(EP2GPIFPFSTOP, 0xE6D3);
SFRX(EP2GPIFTRIG, 0xE6D4);
SFRX(EP4GPIFFLGSEL, 0xE6DA);
SFRX(EP4GPIFPFSTOP, 0xE6DB);
SFRX(EP4GPIFTRIG, 0xE6DC);
SFRX(EP6GPIFFLGSEL, 0xE6E2);
SFRX(EP6GPIFPFSTOP, 0xE6E3);
SFRX(EP6GPIFTRIG, 0xE6E4);
SFRX(EP8GPIFFLGSEL, 0xE6EA);
SFRX(EP8GPIFPFSTOP, 0xE6EB);
SFRX(EP8GPIFTRIG, 0xE6EC);
SFRX(XGPIFSGLDATH, 0xE6F0);
SFRX(XGPIFSGLDATLX, 0xE6F1);
SFRX(XGPIFSGLDATLNOX, 0xE6F2);
SFRX(GPIFREADYCFG, 0xE6F3);
SFRX(GPIFREADYSTAT, 0xE6F4);
SFRX(GPIFABORT, 0xE6F5);
// UDMA
SFRX(FLOWSTATE, 0xE6C6);
SFRX(FLOWLOGIC, 0xE6C7);
SFRX(FLOWEQ0CTL, 0xE6C8);
SFRX(FLOWEQ1CTL, 0xE6C9);
SFRX(FLOWHOLDOFF, 0xE6CA);
SFRX(FLOWSTB, 0xE6CB);
SFRX(FLOWSTBEDGE, 0xE6CC);
SFRX(FLOWSTBHPERIOD, 0xE6CD);
SFRX(GPIFHOLDAMOUNT, 0xE60C);
SFRX(UDMACRCH, 0xE67D);
SFRX(UDMACRCL, 0xE67E);
SFRX(UDMACRCQUAL, 0xE67F);
/* Debug/Test
* The following registers are for Cypress's internal testing purposes only.
* These registers are not documented in the datasheet or the Technical Reference
* Manual as they were not designed for end user application usage
*/
SFRX(DBUG, 0xE6F8);
SFRX(TESTCFG, 0xE6F9);
SFRX(USBTEST, 0xE6FA);
SFRX(CT1, 0xE6FB);
SFRX(CT2, 0xE6FC);
SFRX(CT3, 0xE6FD);
SFRX(CT4, 0xE6FE);
/* Endpoint Buffers */
SFRX(EP0BUF[64], 0xE740);
SFRX(EP1INBUF[64], 0xE7C0);
SFRX(EP1OUTBUF[64], 0xE780);
SFRX(EP2FIFOBUF[512], 0xF000);
SFRX(EP4FIFOBUF[512], 0xF400);
SFRX(EP6FIFOBUF[512], 0xF800);
SFRX(EP8FIFOBUF[512], 0xFC00);
/* Error Correction Code (ECC) Registers (FX2LP/FX1 only) */
SFRX(ECCCFG, 0xE628);
SFRX(ECCRESET, 0xE629);
SFRX(ECC1B0, 0xE62A);
SFRX(ECC1B1, 0xE62B);
SFRX(ECC1B2, 0xE62C);
SFRX(ECC2B0, 0xE62D);
SFRX(ECC2B1, 0xE62E);
SFRX(ECC2B2, 0xE62F);
/* Feature Registers (FX2LP/FX1 only) */
SFRX(GPCR2, 0xE50D);
#define BMFULLSPEEDONLY bmbit4
#endif

View File

@ -0,0 +1,47 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
/**
* This code was taken from the fx2lib project from this link:
* https://github.com/djmuhlestein/fx2lib
*
* Copyright (C) 2009 Ubixum, Inc.
**/
/** \file serial.h
* defines functions to print to a serial console with SIO0
**/
#include "fx2macros.h"
#include <stdint.h>
/**
* This function inits sio0 to use T2CON (timer 2)
* See TRM 14.3.4.1 (Table 14-16)
* Certain baud rates have too high an error rate to work. All baud rates are .16%
* except:
*
* 12MHZ 24MHZ
* \li 57600 -6.99%
* \li 38400 -2.34% -2.34%
* \li 19200 -2.34%
*
* Possible Baud rates:
* \li 2400
* \li 4800
* \li 9600
* \li 19200
* \li 28800
* \li 38400
* \li 57600
*
* Any of these rates should work except 57600 at 12mhz. -2.34% is pushing
* most hardware specs for working. All rates at 48mhz work at .16%
**/
void sio0_init(uint32_t baud_rate) __critical; /* baud_rate max should be 57600 since int=2 bytes */
/**
* putchar('\\n') or putchar('\\r') both transmit \\r\\n
* Just use one or the other. (This makes terminal echo easy)
**/
int putchar(char c);
int getchar(void);

View File

@ -0,0 +1,273 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/****************************************************************************
File : usb.h *
Contents : usb communication handling header file for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#ifndef __USB_H
#define __USB_H
#include "reg_ezusb.h"
#include <stdint.h>
#include <stdbool.h>
/* High and Low byte of a word (uint16_t) */
#define HI8(word) (uint8_t)(((uint16_t)(word) >> 8) & 0xff)
#define LO8(word) (uint8_t)((uint16_t)(word) & 0xff)
/* Convenience functions */
#define STALL_EP0() (EP0CS |= EPSTALL)
#define CLEAR_IRQ() (USBINT = 0)
/*********** 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 */
struct usb_device_descriptor {
uint8_t blength; /**< Size of this descriptor in bytes. */
uint8_t bdescriptortype; /**< DEVICE Descriptor Type. */
uint16_t bcdusb; /**< USB specification release number (BCD). */
uint8_t bdeviceclass; /**< Class code. */
uint8_t bdevicesubclass; /**< Subclass code. */
uint8_t bdeviceprotocol; /**< Protocol code. */
uint8_t bmaxpacketsize0; /**< Maximum packet size for EP0 (8, 16, 32, 64). */
uint16_t idvendor; /**< USB Vendor ID. */
uint16_t idproduct; /**< USB Product ID. */
uint16_t bcddevice; /**< Device Release Number (BCD). */
uint8_t imanufacturer; /**< Index of manufacturer string descriptor. */
uint8_t iproduct; /**< Index of product string descriptor. */
uint8_t iserialnumber; /**< Index of string descriptor containing serial #. */
uint8_t bnumconfigurations; /**< Number of possible configurations. */
};
/** USB Configuration Descriptor. See USB 1.1 spec, pp. 199 - 200 */
struct usb_config_descriptor {
uint8_t blength; /**< Size of this descriptor in bytes. */
uint8_t bdescriptortype; /**< CONFIGURATION descriptor type. */
uint16_t wtotallength; /**< Combined total length of all descriptors. */
uint8_t bnuminterfaces; /**< Number of interfaces in this configuration. */
uint8_t bconfigurationvalue; /**< Value used to select this configuration. */
uint8_t iconfiguration; /**< Index of configuration string descriptor. */
uint8_t bmattributes; /**< Configuration characteristics. */
uint8_t maxpower; /**< Maximum power consumption in 2 mA units. */
};
/** USB Interface Descriptor. See USB 1.1 spec, pp. 201 - 203 */
struct usb_interface_descriptor {
uint8_t blength; /**< Size of this descriptor in bytes. */
uint8_t bdescriptortype; /**< INTERFACE descriptor type. */
uint8_t binterfacenumber; /**< Interface number. */
uint8_t balternatesetting; /**< Value used to select alternate setting. */
uint8_t bnumendpoints; /**< Number of endpoints used by this interface. */
uint8_t binterfaceclass; /**< Class code. */
uint8_t binterfacesubclass; /**< Subclass code. */
uint8_t binterfaceprotocol; /**< Protocol code. */
uint8_t iinterface; /**< Index of interface string descriptor. */
};
/** USB Endpoint Descriptor. See USB 1.1 spec, pp. 203 - 204 */
struct usb_endpoint_descriptor {
uint8_t blength; /**< Size of this descriptor in bytes. */
uint8_t bdescriptortype; /**< ENDPOINT descriptor type. */
uint8_t bendpointaddress; /**< Endpoint Address: IN/OUT + EP number. */
uint8_t bmattributes; /**< Endpoint Attributes: BULK/INTR/ISO/CTRL. */
uint16_t wmaxpacketsize; /**< Maximum packet size for this endpoint. */
uint8_t binterval; /**< Polling interval (in ms) for this endpoint. */
};
/** USB Language Descriptor. See USB 1.1 spec, pp. 204 - 205 */
struct usb_language_descriptor {
uint8_t blength; /**< Size of this descriptor in bytes. */
uint8_t bdescriptortype; /**< STRING descriptor type. */
uint16_t wlangid[]; /**< LANGID codes. */
};
/** USB String Descriptor. See USB 1.1 spec, pp. 204 - 205 */
struct usb_string_descriptor {
uint8_t blength; /**< Size of this descriptor in bytes. */
uint8_t bdescriptortype; /**< STRING descriptor type. */
uint16_t bstring[]; /**< UNICODE encoded string. */
};
/********************** USB Control Endpoint 0 related *********************/
/** USB Control Setup Data. See USB 1.1 spec, pp. 183 - 185 */
struct setup_data {
uint8_t bmrequesttype; /**< Characteristics of a request. */
uint8_t brequest; /**< Specific request. */
uint16_t wvalue; /**< Field that varies according to request. */
uint16_t windex; /**< Field that varies according to request. */
uint16_t wlength; /**< Number of bytes to transfer in data stage. */
};
/* External declarations for variables that need to be accessed outside of
* the USB module */
extern volatile bool ep1_out;
extern volatile bool ep1_in;
extern volatile __xdata __at 0xE6B8 struct setup_data 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
/* 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 */
enum usb_isr {
SUDAV_ISR = 13,
SOF_ISR,
SUTOK_ISR,
SUSPEND_ISR,
USBRESET_ISR,
HIGHSPEED_ISR,
EP0ACK_ISR,
STUB_ISR,
EP0IN_ISR,
EP0OUT_ISR,
EP1IN_ISR,
EP1OUT_ISR,
EP2_ISR,
EP4_ISR,
EP6_ISR,
EP8_ISR,
IBN_ISR,
EP0PINGNAK_ISR,
EP1PINGNAK_ISR,
EP2PINGNAK_ISR,
EP4PINGNAK_ISR,
EP6PINGNAK_ISR,
EP8PINGNAK_ISR,
ERRORLIMIT_ISR,
EP2PIDERROR_ISR,
EP4PIDERROR_ISR,
EP6PIDERROR_ISR,
EP8PIDERROR_ISR,
EP2PFLAG_ISR,
EP4PFLAG_ISR,
EP6PFLAG_ISR,
EP8PFLAG_ISR,
EP2EFLAG_ISR,
EP4EFLAG_ISR,
EP6EFLAG_ISR,
EP8EFLAG_ISR,
EP2FFLAG_ISR,
EP4FFLAG_ISR,
EP6FFLAG_ISR,
EP8FFLAG_ISR,
GPIFCOMPLETE_ISR,
GPIFWAVEFORM_ISR
};
/*************************** Function Prototypes ***************************/
__xdata uint8_t *usb_get_endpoint_cs_reg(uint8_t ep);
void usb_reset_data_toggle(uint8_t 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 ep_init(void);
void interrupt_init(void);
void io_init(void);
#endif

View File

@ -0,0 +1,125 @@
; SPDX-License-Identifier: GPL-2.0-or-later
;****************************************************************************
; File : USBJmpTb.a51 *
; Contents : Interruptions vector configuration. *
; Based on openULINK project code by: Martin Schmoelzer. *
; Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
; <aboudjelida@nanoxplore.com> *
; <ahmederrachedbjld@gmail.com> *
;****************************************************************************
.module JUMPTABLE
.globl USB_AutoVector
.globl USB_Jump_Table
.globl _sudav_isr, _sof_isr, _sutok_isr, _suspend_isr, _usbreset_isr, _highspeed_isr, _ep0ack_isr, _stub_isr, _ep0in_isr, _ep0out_isr, _ep1in_isr, _ep1out_isr, _ep2_isr, _ep4_isr, _ep6_isr, _ep8_isr, _ibn_isr
.globl _ep0pingnak_isr, _ep1pingnak_isr, _ep2pingnak_isr, _ep4pingnak_isr, _ep6pingnak_isr, _ep8pingnak_isr, _errorlimit_isr, _stub_isr, _stub_isr, _stub_isr, _ep2piderror_isr, _ep4piderror_isr, _ep6piderror_isr, _ep8piderror_isr
.globl _ep2pflag_isr, _ep4pflag_isr, _ep6pflag_isr, _ep8pflag_isr, _ep2eflag_isr, _ep4eflag_isr, _ep6eflag_isr, _ep8eflag_isr, _ep2fflag_isr, _ep4fflag_isr, _ep6fflag_isr, _ep8fflag_isr, _gpifcomplete_isr, _gpifwaveform_isr
;--------------------------------------------------------------------------;
; Interrupt Vectors ;
;--------------------------------------------------------------------------;
.area USB_JV (ABS,OVR) ; Absolute, Overlay
.org 0x43 ; USB interrupt (INT2) jumps here
USB_AutoVector = #. + 2
ljmp USB_Jump_Table ; Autovector will replace byte 45
;--------------------------------------------------------------------------;
; USB Jump Table ;
;--------------------------------------------------------------------------;
.area USB_JT (ABS) ; Absolute placement
.org 0x0200 ; Place jump table at 0x0200
USB_Jump_Table: ; autovector jump table
ljmp _sudav_isr ; (00) Setup Data Available
.db 0
ljmp _sof_isr ; (04) Start of Frame
.db 0
ljmp _sutok_isr ; (08) Setup Data Loading
.db 0
ljmp _suspend_isr ; (0C) Global Suspend
.db 0
ljmp _usbreset_isr ; (10) USB Reset
.db 0
ljmp _highspeed_isr ; (14) Entered High Speed
.db 0
ljmp _ep0ack_isr ; (18) EP0ACK
.db 0
ljmp _stub_isr ; (1C) Reserved
.db 0
ljmp _ep0in_isr ; (20) EP0 In
.db 0
ljmp _ep0out_isr ; (24) EP0 Out
.db 0
ljmp _ep1in_isr ; (28) EP1 In
.db 0
ljmp _ep1out_isr ; (2C) EP1 Out
.db 0
ljmp _ep2_isr ; (30) EP2 In/Out
.db 0
ljmp _ep4_isr ; (34) EP4 In/Out
.db 0
ljmp _ep6_isr ; (38) EP6 In/Out
.db 0
ljmp _ep8_isr ; (3C) EP8 In/Out
.db 0
ljmp _ibn_isr ; (40) IBN
.db 0
ljmp _stub_isr ; (44) Reserved
.db 0
ljmp _ep0pingnak_isr ; (48) EP0 PING NAK
.db 0
ljmp _ep1pingnak_isr ; (4C) EP1 PING NAK
.db 0
ljmp _ep2pingnak_isr ; (50) EP2 PING NAK
.db 0
ljmp _ep4pingnak_isr ; (54) EP4 PING NAK
.db 0
ljmp _ep6pingnak_isr ; (58) EP6 PING NAK
.db 0
ljmp _ep8pingnak_isr ; (5C) EP8 PING NAK
.db 0
ljmp _errorlimit_isr ; (60) Error Limit
.db 0
ljmp _stub_isr ; (64) Reserved
.db 0
ljmp _stub_isr ; (68) Reserved
.db 0
ljmp _stub_isr ; (6C) Reserved
.db 0
ljmp _ep2piderror_isr ; (70) EP2 ISO Pid Sequence Error
.db 0
ljmp _ep4piderror_isr ; (74) EP4 ISO Pid Sequence Error
.db 0
ljmp _ep6piderror_isr ; (78) EP6 ISO Pid Sequence Error
.db 0
ljmp _ep8piderror_isr ; (7C) EP8 ISO Pid Sequence Error
.db 0
ljmp _ep2pflag_isr ; (80) EP2 Programmable Flag
.db 0
ljmp _ep4pflag_isr ; (84) EP4 Programmable Flag
.db 0
ljmp _ep6pflag_isr ; (88) EP6 Programmable Flag
.db 0
ljmp _ep8pflag_isr ; (8C) EP8 Programmable Flag
.db 0
ljmp _ep2eflag_isr ; (90) EP2 Empty Flag
.db 0
ljmp _ep4eflag_isr ; (94) EP4 Empty Flag
.db 0
ljmp _ep6eflag_isr ; (98) EP6 Empty Flag
.db 0
ljmp _ep8eflag_isr ; (9C) EP8 Empty Flag
.db 0
ljmp _ep2fflag_isr ; (A0) EP2 Full Flag
.db 0
ljmp _ep4fflag_isr ; (A4) EP4 Full Flag
.db 0
ljmp _ep6fflag_isr ; (A8) EP6 Full Flag
.db 0
ljmp _ep8fflag_isr ; (AC) EP8 Full Flag
.db 0
ljmp _gpifcomplete_isr ; (B0) GPIF Operation Complete
.db 0
ljmp _gpifwaveform_isr ; (B4) GPIF Waveform
.db 0

View File

@ -0,0 +1,49 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/****************************************************************************
File : delay.c *
Contents : Delays handling fucntions code for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#include "delay.h"
#include <mcs51/compiler.h>
void syncdelay(uint8_t count)
{
for (uint8_t i = 0; i < count; i++)
NOP();
}
void delay_5us(void)
{
NOP();
}
void delay_1ms(void)
{
uint16_t i;
for (i = 0; i < 598; i++)
;
}
void delay_us(uint16_t delay)
{
uint16_t i;
uint16_t maxcount = (delay / 5);
for (i = 0; i < maxcount; i++)
delay_5us();
}
void delay_ms(uint16_t delay)
{
uint16_t i;
for (i = 0; i < delay; i++)
delay_1ms();
}

View File

@ -0,0 +1,98 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
This program configures the General Programmable Interface (GPIF) for FX2.
Please do not modify sections of text which are marked as "DO NOT EDIT ...".
*/
/* GPIF Program Code */
#include "reg_ezusb.h"
#include "delay.h"
/****************************** GPIF PROGRAM CODE ********************************/
/* DO NOT EDIT ... */
const char wavedata[128] = {
/* Wave 0 */
/* LenBr */ 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
/* Opcode*/ 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00,
/* Output*/ 0x04, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
/* LFun */ 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
/* Wave 1 */
/* LenBr */ 0x88, 0x01, 0x3F, 0x01, 0x01, 0x01, 0x01, 0x07,
/* Opcode*/ 0x01, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Output*/ 0x07, 0x05, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
/* LFun */ 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x3F,
/* Wave 2 */
/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Output*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
/* Wave 3 */
/* LenBr */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07,
/* Opcode*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Output*/ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
/* LFun */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
};
/* END DO NOT EDIT */
/* DO NOT EDIT ... */
const char flowstates[36] = {
/* Wave 0 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Wave 1 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Wave 2 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* Wave 3 flowstates */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
/* END DO NOT EDIT */
/* DO NOT EDIT ... */
const char initdata[7] = {
/* Regs */ 0xE0, 0x00, 0x00, 0x07, 0xEE, 0xF2, 0x00
};
/* END DO NOT EDIT */
void gpif_init(void)
{
uint8_t i;
IFCONFIG = 0xEE;
GPIFABORT = 0xFF; /* abort any waveforms pending */
GPIFREADYCFG = initdata[0];
GPIFCTLCFG = initdata[1];
GPIFIDLECS = initdata[2];
GPIFIDLECTL = initdata[3];
GPIFWFSELECT = initdata[5];
GPIFREADYSTAT = initdata[6];
/* use dual autopointer feature... */
AUTOPTRSETUP = 0x07;
/* source */
AUTOPTRH1 = (uint8_t)(((uint16_t)(&wavedata) >> 8) & 0xff);
AUTOPTRL1 = (uint8_t)((uint16_t)(&wavedata) & 0xff);
/* destination */
AUTOPTRH2 = 0xE4;
AUTOPTRL2 = 0x00;
/* transfer */
for (i = 0x00; i < 128; i++)
EXTAUTODAT2 = EXTAUTODAT1;
/* GPIF address pins update when GPIFADRH/L written */
syncdelay(3);
GPIFADRH = 0x00; /* bits[7:1] always 0 */
syncdelay(3);
GPIFADRL = 0x00; /* point to PERIPHERAL address 0x0000 */
/* Configure GPIF flowstates registers for Wave 0 of wavedata */
FLOWSTATE = flowstates[0];
FLOWLOGIC = flowstates[1];
FLOWEQ0CTL = flowstates[2];
FLOWEQ1CTL = flowstates[3];
FLOWHOLDOFF = flowstates[4];
FLOWSTB = flowstates[5];
FLOWSTBEDGE = flowstates[6];
FLOWSTBHPERIOD = flowstates[7];
}

View File

@ -0,0 +1,674 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/****************************************************************************
File : jtag.c *
Contents : Jtag handling functions code for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#include "jtag.h"
#include "io.h"
#include "msgtypes.h"
#include "reg_ezusb.h"
#include <stdbool.h>
#include <serial.h>
#include <stdio.h>
/** Delay value for SCAN_IN operations with less than maximum TCK frequency */
uint8_t delay_scan_in;
/** Delay value for SCAN_OUT operations with less than maximum TCK frequency */
uint8_t delay_scan_out;
/** Delay value for SCAN_IO operations with less than maximum TCK frequency */
uint8_t delay_scan_io;
/** Delay value for CLOCK_TCK operations with less than maximum frequency */
uint8_t delay_tck;
/** Delay value for CLOCK_TMS operations with less than maximum frequency */
uint8_t delay_tms;
/**
* 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.
*
* Maximum achievable TCK frequency is 182 kHz for ANGIE clocked at 24 MHz.
*
* @param out_offset offset in EP1OUTBUF where payload data starts
* @param in_offset
*/
void jtag_scan_in(uint8_t out_offset, uint8_t in_offset)
{
uint8_t scan_size_bytes, bits_last_byte;
uint8_t tms_count_start, tms_count_end;
uint8_t tms_sequence_start, tms_sequence_end;
uint8_t tdo_data, i, j;
uint8_t outb_buffer;
/* Get parameters from EP1OUTBUF */
scan_size_bytes = EP1OUTBUF[out_offset];
bits_last_byte = EP1OUTBUF[out_offset + 1];
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
tms_sequence_start = EP1OUTBUF[out_offset + 3];
tms_sequence_end = EP1OUTBUF[out_offset + 4];
if (tms_count_start > 0)
jtag_clock_tms(tms_count_start, tms_sequence_start);
outb_buffer = IOB & ~(bmbit1 | bmbit2 | bmbit3);
/* 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++) {
IOB = outb_buffer; /* TCK changes here */
tdo_data = tdo_data >> 1;
IOB = (outb_buffer | bmbit2);
if (PIN_TDO)
tdo_data |= 0x80;
}
/* Copy TDO data to EP1INBUF */
EP1INBUF[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 |= bmbit1;
tms_count_end--;
tms_sequence_end = tms_sequence_end >> 1;
}
IOB = outb_buffer; /* TCK changes here */
tdo_data = tdo_data >> 1;
IOB = (outb_buffer | bmbit2);
if (PIN_TDO)
tdo_data |= 0x80;
}
tdo_data = tdo_data >> (8 - bits_last_byte);
/* Copy TDO data to EP1INBUF */
EP1INBUF[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-IN operation at variable TCK frequency.
*
* Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
* stored in the EP2 IN buffer.
*
* Maximum achievable TCK frequency is 113 kHz for ANGIE clocked at 24 MHz.
*
* @param out_offset offset in EP1OUTBUF where payload data starts
* @param in_offset
*/
void jtag_slow_scan_in(uint8_t out_offset, uint8_t in_offset)
{
uint8_t scan_size_bytes, bits_last_byte;
uint8_t tms_count_start, tms_count_end;
uint8_t tms_sequence_start, tms_sequence_end;
uint8_t tdo_data, i, j, k;
uint8_t outb_buffer;
/* Get parameters from EP1OUTBUF */
scan_size_bytes = EP1OUTBUF[out_offset];
bits_last_byte = EP1OUTBUF[out_offset + 1];
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
tms_sequence_start = EP1OUTBUF[out_offset + 3];
tms_sequence_end = EP1OUTBUF[out_offset + 4];
if (tms_count_start > 0)
jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
outb_buffer = IOB & ~(bmbit3 | bmbit2 | bmbit1);
/* 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++) {
IOB = outb_buffer; /* TCK changes here */
for (k = 0; k < delay_scan_in; k++)
;
tdo_data = tdo_data >> 1;
IOB = (outb_buffer | bmbit2);
for (k = 0; k < delay_scan_in; k++)
;
if (PIN_TDO)
tdo_data |= 0x80;
}
/* Copy TDO data to EP1INBUF */
EP1INBUF[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 |= bmbit1;
tms_count_end--;
tms_sequence_end = tms_sequence_end >> 1;
}
IOB = outb_buffer; /* TCK changes here */
for (k = 0; k < delay_scan_in; k++)
;
tdo_data = tdo_data >> 1;
IOB = (outb_buffer | bmbit2);
for (k = 0; k < delay_scan_in; k++)
;
if (PIN_TDO)
tdo_data |= 0x80;
}
tdo_data = tdo_data >> (8 - bits_last_byte);
/* Copy TDO data to EP1INBUF */
EP1INBUF[i + in_offset] = tdo_data;
/* Move to correct end state */
if (tms_count_end > 0)
jtag_slow_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 always left in the PAUSE-DR/PAUSE-IR state.
*
* Maximum achievable TCK frequency is 142 kHz for ANGIE clocked at 24 MHz.
*
* @param out_offset offset in EP1OUTBUF where payload data starts
*/
void jtag_scan_out(uint8_t out_offset)
{
uint8_t scan_size_bytes, bits_last_byte;
uint8_t tms_count_start, tms_count_end;
uint8_t tms_sequence_start, tms_sequence_end;
uint8_t tdi_data, i, j;
uint8_t outb_buffer;
/* Get parameters from EP1OUTBUF */
scan_size_bytes = EP1OUTBUF[out_offset];
bits_last_byte = EP1OUTBUF[out_offset + 1];
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
tms_sequence_start = EP1OUTBUF[out_offset + 3];
tms_sequence_end = EP1OUTBUF[out_offset + 4];
if (tms_count_start > 0)
jtag_clock_tms(tms_count_start, tms_sequence_start);
outb_buffer = IOB & ~(bmbit2 | bmbit1);
/* Shift all bytes except the last byte */
for (i = 0; i < scan_size_bytes - 1; i++) {
tdi_data = EP1OUTBUF[i + out_offset + 5];
for (j = 0; j < 8; j++) {
if (tdi_data & 0x01)
outb_buffer |= bmbit3;
else
outb_buffer &= ~bmbit3;
IOB = outb_buffer; /* TDI and TCK change here */
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
}
}
tdi_data = EP1OUTBUF[i + out_offset + 5];
/* Shift the last byte */
for (j = 0; j < bits_last_byte; j++) {
if (tdi_data & 0x01)
outb_buffer |= bmbit3;
else
outb_buffer &= ~bmbit3;
/* Assert TMS signal if requested and this is the last bit */
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
outb_buffer |= bmbit1;
tms_count_end--;
tms_sequence_end = tms_sequence_end >> 1;
}
IOB = outb_buffer; /* TDI and TCK change here */
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
}
/* 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 always left in the PAUSE-DR/PAUSE-IR state.
*
* Maximum achievable TCK frequency is 97 kHz for ANGIE clocked at 24 MHz.
*
* @param out_offset offset in EP1OUTBUF where payload data starts
*/
void jtag_slow_scan_out(uint8_t out_offset)
{
uint8_t scan_size_bytes, bits_last_byte;
uint8_t tms_count_start, tms_count_end;
uint8_t tms_sequence_start, tms_sequence_end;
uint8_t tdi_data, i, j, k;
uint8_t outb_buffer;
/* Get parameters from EP1OUTBUF */
scan_size_bytes = EP1OUTBUF[out_offset];
bits_last_byte = EP1OUTBUF[out_offset + 1];
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
tms_sequence_start = EP1OUTBUF[out_offset + 3];
tms_sequence_end = EP1OUTBUF[out_offset + 4];
if (tms_count_start > 0)
jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
outb_buffer = IOB & ~(bmbit2 | bmbit1);
/* Shift all bytes except the last byte */
for (i = 0; i < scan_size_bytes - 1; i++) {
tdi_data = EP1OUTBUF[i + out_offset + 5];
for (j = 0; j < 8; j++) {
if (tdi_data & 0x01)
outb_buffer |= bmbit3;
else
outb_buffer &= ~bmbit3;
IOB = outb_buffer; /* TDI and TCK change here */
for (k = 0; k < delay_scan_out; k++)
;
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
for (k = 0; k < delay_scan_out; k++)
;
}
}
tdi_data = EP1OUTBUF[i + out_offset + 5];
/* Shift the last byte */
for (j = 0; j < bits_last_byte; j++) {
if (tdi_data & 0x01)
outb_buffer |= bmbit3;
else
outb_buffer &= ~bmbit3;
/* Assert TMS signal if requested and this is the last bit */
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
outb_buffer |= bmbit1;
tms_count_end--;
tms_sequence_end = tms_sequence_end >> 1;
}
IOB = outb_buffer; /* TDI and TCK change here */
for (k = 0; k < delay_scan_out; k++)
;
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
for (k = 0; k < delay_scan_out; k++)
;
}
/* Move to correct end state */
if (tms_count_end > 0)
jtag_slow_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 always left in the PAUSE-DR/PAUSE-IR state.
*
* Maximum achievable TCK frequency is 100 kHz for ANGIE clocked at 24 MHz.
*
* @param out_offset offset in EP1OUTBUF where payload data starts
* @param in_offset
*/
int it;
void jtag_scan_io(uint8_t out_offset, uint8_t in_offset)
{
uint8_t scan_size_bytes, bits_last_byte;
uint8_t tms_count_start, tms_count_end;
uint8_t tms_sequence_start, tms_sequence_end;
uint8_t tdi_data, tdo_data, i, j;
uint8_t outb_buffer;
it++;
/* Get parameters from EP1OUTBUF */
scan_size_bytes = EP1OUTBUF[out_offset];
bits_last_byte = EP1OUTBUF[out_offset + 1];
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
tms_sequence_start = EP1OUTBUF[out_offset + 3];
tms_sequence_end = EP1OUTBUF[out_offset + 4];
if (tms_count_start > 0)
jtag_clock_tms(tms_count_start, tms_sequence_start);
outb_buffer = IOB & ~(bmbit2 | bmbit1);
/* Shift all bytes except the last byte */
for (i = 0; i < scan_size_bytes - 1; i++) {
tdi_data = EP1OUTBUF[i + out_offset + 5];
tdo_data = 0;
for (j = 0; j < 8; j++) {
if (tdi_data & 0x01)
outb_buffer |= bmbit3;
else
outb_buffer &= ~bmbit3;
IOB = outb_buffer; /* TDI and TCK change here */
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
tdo_data = tdo_data >> 1;
if (PIN_TDO)
tdo_data |= 0x80;
}
/* Copy TDO data to EP1INBUF */
EP1INBUF[i + in_offset] = tdo_data;
}
tdi_data = EP1OUTBUF[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 |= bmbit3;
else
outb_buffer &= ~bmbit3;
/* Assert TMS signal if requested and this is the last bit */
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
outb_buffer |= bmbit1;
tms_count_end--;
tms_sequence_end = tms_sequence_end >> 1;
}
IOB = outb_buffer; /* TDI and TCK change here */
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
tdo_data = tdo_data >> 1;
if (PIN_TDO)
tdo_data |= 0x80;
}
tdo_data = tdo_data >> (8 - bits_last_byte);
/* Copy TDO data to EP1INBUF */
EP1INBUF[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 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 always left in the PAUSE-DR/PAUSE-IR state.
*
* Maximum achievable TCK frequency is 78 kHz for ANGIE clocked at 24 MHz.
*
* @param out_offset offset in EP1OUTBUF where payload data starts
* @param in_offset
*/
void jtag_slow_scan_io(uint8_t out_offset, uint8_t in_offset)
{
uint8_t scan_size_bytes, bits_last_byte;
uint8_t tms_count_start, tms_count_end;
uint8_t tms_sequence_start, tms_sequence_end;
uint8_t tdi_data, tdo_data, i, j, k;
uint8_t outb_buffer;
/* Get parameters from EP1OUTBUF */
scan_size_bytes = EP1OUTBUF[out_offset];
bits_last_byte = EP1OUTBUF[out_offset + 1];
tms_count_start = (EP1OUTBUF[out_offset + 2] >> 4) & 0x0F;
tms_count_end = EP1OUTBUF[out_offset + 2] & 0x0F;
tms_sequence_start = EP1OUTBUF[out_offset + 3];
tms_sequence_end = EP1OUTBUF[out_offset + 4];
if (tms_count_start > 0)
jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
outb_buffer = IOB & ~(bmbit2 | bmbit1);
/* Shift all bytes except the last byte */
for (i = 0; i < scan_size_bytes - 1; i++) {
tdi_data = EP1OUTBUF[i + out_offset + 5];
tdo_data = 0;
for (j = 0; j < 8; j++) {
if (tdi_data & 0x01)
outb_buffer |= bmbit3;
else
outb_buffer &= ~bmbit3;
IOB = outb_buffer; /* TDI and TCK change here */
for (k = 0; k < delay_scan_io; k++)
;
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
for (k = 0; k < delay_scan_io; k++)
;
tdo_data = tdo_data >> 1;
if (PIN_TDO)
tdo_data |= 0x80;
}
/* Copy TDO data to EP1INBUF */
EP1INBUF[i + in_offset] = tdo_data;
}
tdi_data = EP1OUTBUF[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 |= bmbit3;
else
outb_buffer &= ~bmbit3;
/* Assert TMS signal if requested and this is the last bit */
if (j == (bits_last_byte - 1) && tms_count_end > 0) {
outb_buffer |= bmbit1;
tms_count_end--;
tms_sequence_end = tms_sequence_end >> 1;
}
IOB = outb_buffer; /* TDI and TCK change here */
for (k = 0; k < delay_scan_io; k++)
;
tdi_data = tdi_data >> 1;
IOB = (outb_buffer | bmbit2);
for (k = 0; k < delay_scan_io; k++)
;
tdo_data = tdo_data >> 1;
if (PIN_TDO)
tdo_data |= 0x80;
}
tdo_data = tdo_data >> (8 - bits_last_byte);
/* Copy TDO data to EP1INBUF */
EP1INBUF[i + in_offset] = tdo_data;
/* Move to correct end state */
if (tms_count_end > 0)
jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
}
/**
* Generate TCK clock cycles.
*
* Maximum achievable TCK frequency is 375 kHz for ANGIE clocked at 24 MHz.
*
* @param count number of TCK clock cycles to generate.
*/
void jtag_clock_tck(uint16_t count)
{
uint16_t i;
uint8_t outb_buffer = IOB & ~(bmbit2);
for (i = 0; i < count; i++) {
IOB = outb_buffer;
IOB = outb_buffer | bmbit2;
}
}
/**
* Generate TCK clock cycles at variable frequency.
*
* Maximum achievable TCK frequency is 166.6 kHz for ANGIE clocked at 24 MHz.
*
* @param count number of TCK clock cycles to generate.
*/
void jtag_slow_clock_tck(uint16_t count)
{
uint16_t i;
uint8_t j;
uint8_t outb_buffer = IOB & ~(bmbit2);
for (i = 0; i < count; i++) {
IOB = outb_buffer;
for (j = 0; j < delay_tck; j++)
;
IOB = outb_buffer | bmbit2;
for (j = 0; j < delay_tck; j++)
;
}
}
/**
* Perform TAP FSM state transitions at maximum TCK frequency.
*
* Maximum achievable TCK frequency is 176 kHz for ANGIE clocked at 24 MHz.
*
* @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(uint8_t count, uint8_t sequence)
{
uint8_t outb_buffer = IOB & ~(bmbit2);
uint8_t i;
for (i = 0; i < count; i++) {
/* Set TMS pin according to sequence parameter */
if (sequence & 0x1)
outb_buffer |= bmbit1;
else
outb_buffer &= ~bmbit1;
IOB = outb_buffer;
sequence = sequence >> 1;
IOB = outb_buffer | bmbit2;
}
}
/**
* Perform TAP-FSM state transitions at less than maximum TCK frequency.
*
* Maximum achievable TCK frequency is 117 kHz for ANGIE clocked at 24 MHz.
*
* @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(uint8_t count, uint8_t sequence)
{
uint8_t outb_buffer = IOB & ~(bmbit2);
uint8_t i, j;
for (i = 0; i < count; i++) {
/* Set TMS pin according to sequence parameter */
if (sequence & 0x1)
outb_buffer |= bmbit1;
else
outb_buffer &= ~bmbit1;
IOB = outb_buffer;
for (j = 0; j < delay_tms; j++)
;
sequence = sequence >> 1;
IOB = outb_buffer | bmbit2;
for (j = 0; j < delay_tms; j++)
;
}
}
uint16_t jtag_get_signals(void)
{
uint8_t input_signal_state, output_signal_state;
input_signal_state = 0;
output_signal_state = 0;
/* Get states of input pins */
if (PIN_TDO)
input_signal_state |= SIGNAL_TDO;
/* Get states of output pins */
output_signal_state = IOB & MASK_PORTB_DIRECTION_OUT;
return ((uint16_t)input_signal_state << 8) | ((uint16_t)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(uint8_t low, uint8_t high)
{
IOB &= ~(low & MASK_PORTB_DIRECTION_OUT);
IOB |= (high & MASK_PORTB_DIRECTION_OUT);
}
/**
* Configure TCK delay parameters.
*
* @param scan_in number of delay cycles in scan_in operations.
* @param scan_out number of delay cycles in scan_out operations.
* @param scan_io number of delay cycles in scan_io 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(uint8_t scan_in, uint8_t scan_out,
uint8_t scan_io, uint8_t tck, uint8_t tms)
{
delay_scan_in = scan_in;
delay_scan_out = scan_out;
delay_scan_io = scan_io;
delay_tck = tck;
delay_tms = tms;
}

View File

@ -0,0 +1,85 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/****************************************************************************
File : main.c *
Contents : main code for NanoXplore USB-JTAG ANGIE adapter *
hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#include "usb.h"
#include "delay.h"
#include "protocol.h"
#include "reg_ezusb.h"
#include <serial.h>
#include <stdio.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 highspeed_isr(void)__interrupt;
extern void ep0ack_isr(void)__interrupt;
extern void stub_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 ep2_isr(void)__interrupt;
extern void ep4_isr(void)__interrupt;
extern void ep6_isr(void)__interrupt;
extern void ep8_isr(void)__interrupt;
extern void ibn_isr(void)__interrupt;
extern void ep0pingnak_isr(void)__interrupt;
extern void ep1pingnak_isr(void)__interrupt;
extern void ep2pingnak_isr(void)__interrupt;
extern void ep4pingnak_isr(void)__interrupt;
extern void ep6pingnak_isr(void)__interrupt;
extern void ep8pingnak_isr(void)__interrupt;
extern void errorlimit_isr(void)__interrupt;
extern void ep2piderror_isr(void)__interrupt;
extern void ep4piderror_isr(void)__interrupt;
extern void ep6piderror_isr(void)__interrupt;
extern void ep8piderror_isr(void)__interrupt;
extern void ep2pflag_isr(void)__interrupt;
extern void ep4pflag_isr(void)__interrupt;
extern void ep6pflag_isr(void)__interrupt;
extern void ep8pflag_isr(void)__interrupt;
extern void ep2eflag_isr(void)__interrupt;
extern void ep4eflag_isr(void)__interrupt;
extern void ep6eflag_isr(void)__interrupt;
extern void ep8eflag_isr(void)__interrupt;
extern void ep2fflag_isr(void)__interrupt;
extern void ep4fflag_isr(void)__interrupt;
extern void ep6fflag_isr(void)__interrupt;
extern void ep8fflag_isr(void)__interrupt;
extern void gpifcomplete_isr(void)__interrupt;
extern void gpifwaveform_isr(void)__interrupt;
void gpif_init(void);
int main(void)
{
CPUCS = ((CPUCS & ~bmclkspd) | (CLK_48M << 3) | CLKOE); /* required for sio0_init */
sio0_init(57600); /* needed for printf */
ep_init();
gpif_init();
interrupt_init();
io_init();
/* Perform ReNumeration */
USBCS |= (DISCON | RENUM);
delay_ms(250);
USBCS &= ~DISCON;
/* Begin executing command(s). This function never returns. */
command_loop();
/* Never reached, but SDCC complains about missing return statement */
return 0;
}

View File

@ -0,0 +1,189 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/****************************************************************************
File : protocol.c *
Contents : Jtag commands handling protocol code for NanoXplore *
USB-JTAG ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#include "usb.h"
#include "protocol.h"
#include "jtag.h"
#include "delay.h"
#include "io.h"
#include "msgtypes.h"
#include "reg_ezusb.h"
#include <serial.h>
#include <stdio.h>
/** Index in EP1 Bulk-OUT data buffer that contains the current command ID */
volatile uint8_t cmd_id_index;
/** Number of data bytes already in EP1 Bulk-IN buffer */
volatile uint8_t payload_index_in;
/**
* Executes one command and updates global command indexes.
*
* @return true if this command was the last command.
* @return false if there are more commands within the current contents of the
* Bulk EP1-OUT data buffer.
*/
bool execute_command(void)
{
uint8_t usb_out_bytecount, usb_in_bytecount;
uint16_t signal_state = 0;
uint16_t 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
* necessary */
usb_in_bytecount = 0;
switch (EP1OUTBUF[cmd_id_index] /* Command ID */) {
case CMD_SCAN_IN:
usb_out_bytecount = 5;
usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
jtag_scan_in((cmd_id_index + 1), payload_index_in);
break;
case CMD_SCAN_OUT:
usb_out_bytecount = EP1OUTBUF[cmd_id_index + 1] + 5;
jtag_scan_out(cmd_id_index + 1);
break;
case CMD_SCAN_IO:
usb_in_bytecount = EP1OUTBUF[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(EP1OUTBUF[cmd_id_index + 1], EP1OUTBUF[cmd_id_index + 2]);
break;
case CMD_CLOCK_TCK:
usb_out_bytecount = 2;
count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
jtag_clock_tck(count);
break;
case CMD_SLOW_SCAN_IN:
usb_out_bytecount = 5;
usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
jtag_slow_scan_in(cmd_id_index + 1, payload_index_in);
break;
case CMD_SLOW_SCAN_OUT:
usb_out_bytecount = EP1OUTBUF[cmd_id_index + 1] + 5;
jtag_slow_scan_out(cmd_id_index + 1);
break;
case CMD_SLOW_SCAN_IO:
usb_in_bytecount = EP1OUTBUF[cmd_id_index + 1];
usb_out_bytecount = usb_in_bytecount + 5;
jtag_slow_scan_io(cmd_id_index + 1, payload_index_in);
break;
case CMD_SLOW_CLOCK_TMS:
usb_out_bytecount = 2;
jtag_slow_clock_tms(EP1OUTBUF[cmd_id_index + 1], EP1OUTBUF[cmd_id_index + 2]);
break;
case CMD_SLOW_CLOCK_TCK:
usb_out_bytecount = 2;
count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
jtag_slow_clock_tck(count);
break;
case CMD_SLEEP_US:
usb_out_bytecount = 2;
count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
count |= ((uint16_t)EP1OUTBUF[cmd_id_index + 2]) << 8;
delay_us(count);
break;
case CMD_SLEEP_MS:
usb_out_bytecount = 2;
count = (uint16_t)EP1OUTBUF[cmd_id_index + 1];
count |= ((uint16_t)EP1OUTBUF[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();
EP1INBUF[payload_index_in] = (signal_state >> 8);
EP1INBUF[payload_index_in + 1] = (signal_state & 0xFF);
break;
case CMD_SET_SIGNALS:
usb_out_bytecount = 2;
jtag_set_signals(EP1OUTBUF[cmd_id_index + 1], EP1OUTBUF[cmd_id_index + 2]);
break;
case CMD_CONFIGURE_TCK_FREQ:
usb_out_bytecount = 5;
jtag_configure_tck_delay(EP1OUTBUF[cmd_id_index + 1], /* scan_in */
EP1OUTBUF[cmd_id_index + 2], /* scan_out */
EP1OUTBUF[cmd_id_index + 3], /* scan_io */
EP1OUTBUF[cmd_id_index + 4], /* clock_tck */
EP1OUTBUF[cmd_id_index + 5]); /* clock_tms */
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 EP1 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) >= EP1OUTBC) {
return true;
/* Line between return and else required by checkpatch: */
uint8_t a = 0;
} 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 EP1 Bulk-OUT packet */
while (!ep1_out)
;
ep1_out = false;
/* Execute the commands */
last_command = false;
while (!last_command)
last_command = execute_command();
/* Send back EP6 Bulk-IN packet if required */
if (payload_index_in > 0) {
EP1INBC = payload_index_in;
syncdelay(3);
while (!ep1_in)
;
ep1_in = false;
}
/* Re-arm EP1-OUT after command execution */
EP1OUTBC = 0;
syncdelay(3);
EP1OUTBC = 0;
syncdelay(3);
}
}

View File

@ -0,0 +1,77 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* This code was taken from the fx2lib project from this link:
* https://github.com/djmuhlestein/fx2lib
*
* Copyright (C) 2009 Ubixum, Inc.
*/
#include <reg_ezusb.h>
#include <fx2macros.h>
#include <serial.h>
#include <stdint.h>
/**
* using the comp port implies that timer 2 will be used as
* a baud rate generator. (Don't use timer 2)
**/
void sio0_init(uint32_t baud_rate) __critical
{
uint16_t hl; /* hl value for reload */
uint8_t mult; /* multiplier for clock speed */
uint32_t tmp; /* scratch for mult/divide */
mult = (CPUFREQ == CLK_12M) ? 1 : ((CPUFREQ == CLK_24M) ? 2 : 4);
/* set the clock rate */
/* use clock 2 */
RCLK = 1; TCLK = 1;
tmp = mult * 375000L * 2;
tmp /= baud_rate;
tmp += 1;
tmp /= 2;
hl = 0xFFFF - (uint16_t)tmp;
RCAP2H = (uint8_t)(((uint16_t)(hl) >> 8) & 0xff);
/* seems that the 24/48mhz calculations are always one less than suggested values */
/* trm table 14-16 */
RCAP2L = ((uint8_t)((uint16_t)(hl) & 0xff)) + (mult > 0 ? 1 : 0);
/* start the timer */
TR2 = 1;
/* set up the serial port */
SM0 = 0; SM1 = 1; /* serial mode 1 (asyncronous) */
SM2 = 0 ; /* has to do with receiving */
REN = 1 ; /* to enable receiving */
PCON |= 0x80; /* SET SMOD0, baud rate doubler */
TI = 1; /* we send initial byte */
}
int getchar(void)
{
char c;
while (!RI)
;
c = SBUF0;
RI = 0;
return c;
}
void _transchar(char c)
{
while (!TI)
; /* wait for TI=1 */
TI = 0;
SBUF0 = c;
}
int putchar (char c)
{
if (c == '\n')
_transchar('\r'); /* transmit \r\n */
_transchar(c);
if (c == '\r')
_transchar('\n'); /* transmit \r\n */
return c;
}

View File

@ -0,0 +1,784 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/****************************************************************************
File : usb.c *
Contents : usb communication handling code for NanoXplore USB-JTAG *
ANGIE adapter hardware. *
Based on openULINK project code by: Martin Schmoelzer. *
Copyright 2023, Ahmed Errached BOUDJELIDA, NanoXplore SAS. *
<aboudjelida@nanoxplore.com> *
<ahmederrachedbjld@gmail.com> *
*****************************************************************************/
#include "usb.h"
#include "stdint.h"
#include "delay.h"
#include "io.h"
#include "reg_ezusb.h"
#include <fx2macros.h>
#include <serial.h>
#include <stdio.h>
/* Also update external declarations in "include/usb.h" if making changes to
* these variables!
*/
volatile bool ep1_out;
volatile bool ep1_in;
volatile __xdata __at 0xE6B8 struct setup_data setup_data;
/* Define number of endpoints (except Control Endpoint 0) in a central place.
* Be sure to include the necessary endpoint descriptors!
*/
#define NUM_ENDPOINTS 3
__code struct usb_device_descriptor device_descriptor = {
.blength = sizeof(struct usb_device_descriptor),
.bdescriptortype = DESCRIPTOR_TYPE_DEVICE,
.bcdusb = 0x0200, /* BCD: 02.00 (Version 2.0 USB spec) */
.bdeviceclass = 0xFF, /* 0xFF = vendor-specific */
.bdevicesubclass = 0xFF,
.bdeviceprotocol = 0xFF,
.bmaxpacketsize0 = 64,
.idvendor = 0x584e,
.idproduct = 0x424e,
.bcddevice = 0x0000,
.imanufacturer = 1,
.iproduct = 2,
.iserialnumber = 3,
.bnumconfigurations = 1
};
/* WARNING: ALL config, interface and endpoint descriptors MUST be adjacent! */
__code struct usb_config_descriptor config_descriptor = {
.blength = sizeof(struct usb_config_descriptor),
.bdescriptortype = DESCRIPTOR_TYPE_CONFIGURATION,
.wtotallength = sizeof(struct usb_config_descriptor) +
sizeof(struct usb_interface_descriptor) +
(NUM_ENDPOINTS * sizeof(struct usb_endpoint_descriptor)),
.bnuminterfaces = 1,
.bconfigurationvalue = 1,
.iconfiguration = 4, /* String describing this configuration */
.bmattributes = 0x80, /* Only MSB set according to USB spec */
.maxpower = 50 /* 100 mA */
};
__code struct usb_interface_descriptor interface_descriptor00 = {
.blength = sizeof(struct usb_interface_descriptor),
.bdescriptortype = DESCRIPTOR_TYPE_INTERFACE,
.binterfacenumber = 0,
.balternatesetting = 0,
.bnumendpoints = NUM_ENDPOINTS,
.binterfaceclass = 0xFF,
.binterfacesubclass = 0xFF,
.binterfaceprotocol = 0xFF,
.iinterface = 0
};
__code struct usb_endpoint_descriptor bulk_ep1_out_endpoint_descriptor = {
.blength = sizeof(struct usb_endpoint_descriptor),
.bdescriptortype = 0x05,
.bendpointaddress = (1 | USB_DIR_OUT),
.bmattributes = 0x02,
.wmaxpacketsize = 64,
.binterval = 0
};
__code struct usb_endpoint_descriptor bulk_ep1_in_endpoint_descriptor = {
.blength = sizeof(struct usb_endpoint_descriptor),
.bdescriptortype = 0x05,
.bendpointaddress = (1 | USB_DIR_IN),
.bmattributes = 0x02,
.wmaxpacketsize = 64,
.binterval = 0
};
__code struct usb_endpoint_descriptor bulk_ep2_endpoint_descriptor = {
.blength = sizeof(struct usb_endpoint_descriptor),
.bdescriptortype = 0x05,
.bendpointaddress = (2 | USB_DIR_OUT),
.bmattributes = 0x02,
.wmaxpacketsize = 512,
.binterval = 0
};
__code struct usb_endpoint_descriptor bulk_ep4_endpoint_descriptor = {
.blength = sizeof(struct usb_endpoint_descriptor),
.bdescriptortype = 0x05,
.bendpointaddress = (4 | USB_DIR_IN),
.bmattributes = 0x02,
.wmaxpacketsize = 512,
.binterval = 0
};
__code struct usb_endpoint_descriptor bulk_ep6_endpoint_descriptor = {
.blength = sizeof(struct usb_endpoint_descriptor),
.bdescriptortype = 0x05,
.bendpointaddress = (6 | USB_DIR_OUT),
.bmattributes = 0x02,
.wmaxpacketsize = 512,
.binterval = 0
};
__code struct usb_endpoint_descriptor bulk_ep8_endpoint_descriptor = {
.blength = sizeof(struct usb_endpoint_descriptor),
.bdescriptortype = 0x05,
.bendpointaddress = (8 | USB_DIR_OUT),
.bmattributes = 0x02,
.wmaxpacketsize = 512,
.binterval = 0
};
__code struct usb_language_descriptor language_descriptor = {
.blength = 4,
.bdescriptortype = DESCRIPTOR_TYPE_STRING,
.wlangid = {0x0409 /* US English */}
};
__code struct usb_string_descriptor strmanufacturer =
STR_DESCR(16, 'N', 'a', 'n', 'o', 'X', 'p', 'l', 'o', 'r', 'e', ',', ' ', 'S', 'A', 'S', '.');
__code struct usb_string_descriptor strproduct =
STR_DESCR(13, 'A', 'N', 'G', 'I', 'E', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r');
__code struct usb_string_descriptor strserialnumber =
STR_DESCR(6, '0', '0', '0', '0', '0', '1');
__code struct usb_string_descriptor strconfigdescr =
STR_DESCR(12, 'J', 'T', 'A', 'G', ' ', 'A', 'd', 'a', 'p', 't', 'e', 'r');
/* Table containing pointers to string descriptors */
__code struct usb_string_descriptor *__code en_string_descriptors[4] = {
&strmanufacturer,
&strproduct,
&strserialnumber,
&strconfigdescr
};
void sudav_isr(void)__interrupt SUDAV_ISR
{
EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */
USBIRQ = SUDAVI;
EP0CS |= HSNAK;
usb_handle_setup_data();
}
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 highspeed_isr(void)__interrupt HIGHSPEED_ISR
{
}
void ep0ack_isr(void)__interrupt EP0ACK_ISR
{
}
void stub_isr(void)__interrupt STUB_ISR
{
}
void ep0in_isr(void)__interrupt EP0IN_ISR
{
}
void ep0out_isr(void)__interrupt EP0OUT_ISR
{
}
void ep1in_isr(void)__interrupt EP1IN_ISR
{
ep1_in = true;
EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */
EPIRQ = 0x04; /* Clear individual EP1IN IRQ */
}
void ep1out_isr(void)__interrupt EP1OUT_ISR
{
ep1_out = true;
EXIF &= ~0x10; /* Clear USBINT: Main global interrupt */
EPIRQ = 0x08; /* Clear individual EP1OUT IRQ */
}
void ep2_isr(void)__interrupt EP2_ISR
{
ep1_out = false; /* Does nothing but required by the compiler */
}
void ep4_isr(void)__interrupt EP4_ISR
{
}
void ep6_isr(void)__interrupt EP6_ISR
{
}
void ep8_isr(void)__interrupt EP8_ISR
{
}
void ibn_isr(void)__interrupt IBN_ISR
{
}
void ep0pingnak_isr(void)__interrupt EP0PINGNAK_ISR
{
}
void ep1pingnak_isr(void)__interrupt EP1PINGNAK_ISR
{
}
void ep2pingnak_isr(void)__interrupt EP2PINGNAK_ISR
{
}
void ep4pingnak_isr(void)__interrupt EP4PINGNAK_ISR
{
}
void ep6pingnak_isr(void)__interrupt EP6PINGNAK_ISR
{
}
void ep8pingnak_isr(void)__interrupt EP8PINGNAK_ISR
{
}
void errorlimit_isr(void)__interrupt ERRORLIMIT_ISR
{
}
void ep2piderror_isr(void)__interrupt EP2PIDERROR_ISR
{
}
void ep4piderror_isr(void)__interrupt EP4PIDERROR_ISR
{
}
void ep6piderror_isr(void)__interrupt EP6PIDERROR_ISR
{
}
void ep8piderror_isr(void)__interrupt EP8PIDERROR_ISR
{
}
void ep2pflag_isr(void)__interrupt EP2PFLAG_ISR
{
}
void ep4pflag_isr(void)__interrupt EP4PFLAG_ISR
{
}
void ep6pflag_isr(void)__interrupt EP6PFLAG_ISR
{
}
void ep8pflag_isr(void)__interrupt EP8PFLAG_ISR
{
}
void ep2eflag_isr(void)__interrupt EP2EFLAG_ISR
{
}
void ep4eflag_isr(void)__interrupt EP4EFLAG_ISR
{
}
void ep6eflag_isr(void)__interrupt EP6EFLAG_ISR
{
}
void ep8eflag_isr(void)__interrupt EP8EFLAG_ISR
{
}
void ep2fflag_isr(void)__interrupt EP2FFLAG_ISR
{
}
void ep4fflag_isr(void)__interrupt EP4FFLAG_ISR
{
}
void ep6fflag_isr(void)__interrupt EP6FFLAG_ISR
{
}
void ep8fflag_isr(void)__interrupt EP8FFLAG_ISR
{
}
void gpifcomplete_isr(void)__interrupt GPIFCOMPLETE_ISR
{
}
void gpifwaveform_isr(void)__interrupt GPIFWAVEFORM_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 uint8_t *usb_get_endpoint_cs_reg(uint8_t ep)
{
/* Mask direction bit */
uint8_t ep_num = ep & ~0x80;
switch (ep_num) {
case 0:
return &EP0CS;
case 1:
return ep & 0x80 ? &EP1INCS : &EP1OUTCS;
case 2:
return &EP2CS;
case 4:
return &EP4CS;
case 6:
return &EP6CS;
case 8:
return &EP8CS;
default:
return NULL;
}
}
void usb_reset_data_toggle(uint8_t ep)
{
/* TOGCTL register:
+----+-----+-----+------+-----+-------+-------+-------+
| Q | S | R | IO | EP3 | 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.
*/
TOGCTL = (((ep & 0x80) >> 3) + (ep & 0x0F));
TOGCTL |= BMRESETTOGGLE;
}
/**
* Handle GET_STATUS request.
*
* @return on success: true
* @return on failure: false
*/
bool usb_handle_get_status(void)
{
uint8_t *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 */
EP0BUF[0] = 0;
EP0BUF[1] = 0;
/* Send response */
EP0BCH = 0;
syncdelay(3);
EP0BCL = 2;
syncdelay(3);
break;
case GS_INTERFACE:
/* Always return two zero bytes according to USB 1.1 spec, p. 191 */
EP0BUF[0] = 0;
EP0BUF[1] = 0;
/* Send response */
EP0BCH = 0;
syncdelay(3);
EP0BCL = 2;
syncdelay(3);
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)
EP0BUF[0] = 0x01;
else
EP0BUF[0] = 0x00;
/* Second byte sent has to be always zero */
EP0BUF[1] = 0;
/* Send response */
EP0BCH = 0;
syncdelay(3);
EP0BCL = 2;
syncdelay(3);
break;
default:
return false;
}
return true;
}
/**
* Handle CLEAR_FEATURE request.
*
* @return on success: true
* @return on failure: false
*/
bool usb_handle_clear_feature(void)
{
__xdata uint8_t *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... */
break;
}
return true;
}
/**
* Handle SET_FEATURE request.
*
* @return on success: true
* @return on failure: false
*/
bool usb_handle_set_feature(void)
{
__xdata uint8_t *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 uint8_t descriptor_type;
__xdata uint8_t 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;
}
return true;
}
/**
* Handle SET_INTERFACE request.
*/
void usb_handle_set_interface(void)
{
/* Reset Data Toggle */
usb_reset_data_toggle(USB_DIR_IN | 4);
usb_reset_data_toggle(USB_DIR_OUT | 2);
/* Unstall & clear busy flag of all valid IN endpoints */
EP1INCS = 0 | EPBSY;
/* Unstall all valid OUT endpoints, reset bytecounts */
EP1OUTCS = 0;
EP1OUTBC = 0;
syncdelay(3);
}
/* Initialize GPIF interface transfer count */
void set_gpif_cnt(uint32_t count)
{
GPIFTCB3 = (uint8_t)(((uint32_t)(count) >> 24) & 0x000000ff);
syncdelay(3);
GPIFTCB2 = (uint8_t)(((uint32_t)(count) >> 16) & 0x000000ff);
syncdelay(3);
GPIFTCB1 = (uint8_t)(((uint32_t)(count) >> 8) & 0x000000ff);
syncdelay(3);
GPIFTCB0 = (uint8_t)((uint32_t)(count) & 0x000000ff);
}
/*
* Vendor commands handling:
*/
#define VR_CFGOPEN 0xB0
#define VR_CFGCLOSE 0xB1
uint8_t ix;
uint8_t bcnt;
uint8_t __xdata *eptr;
uint16_t wcnt;
uint32_t __xdata gcnt;
bool usb_handle_send_bitstream(void)
{
eptr = EP0BUF; /* points to EP0BUF 64-byte register */
wcnt = setup_data.wlength; /* total transfer count */
/* Clear EP0BUF for OUT requests */
if (setup_data.bmrequesttype & 0x80) {
bcnt = ((wcnt > 64) ? 64 : wcnt);
for (ix = 0; ix < bcnt; ix++)
eptr[ix] = 0;
}
switch (setup_data.brequest) {
case VR_CFGOPEN:
/* Clear bytecount / to allow new data in / to stops NAKing */
EP0BCH = 0;
EP0BCL = 0;
while (EP0CS & EPBSY)
; /* wait to finish transferring in EP0BUF, until not busy */
gcnt = ((uint32_t)(eptr[0]) << 24) | ((uint32_t)(eptr[1]) << 16)
| ((uint32_t)(eptr[2]) << 8) | (uint32_t)(eptr[3]);
/* Angie board FPGA bitstream download */
switch ((setup_data.wvalue) & 0x00C0) {
case 0x00:
PIN_PROGRAM_B = 0; /* Apply RPGM- pulse */
GPIFWFSELECT = 0xF2; /* Restore Config mode waveforms select */
syncdelay(3);
EP2FIFOCFG = BMAUTOOUT; /* and Automatic 8-bit GPIF OUT mode */
syncdelay(3);
PIN_PROGRAM_B = 1; /* Negate RPGM- pulse */
delay_ms(10); /* FPGA init time < 10mS */
set_gpif_cnt(gcnt); /* Initialize GPIF interface transfer count */
PIN_RDWR_B = 0;
PIN_CSI_B = 0;
GPIFTRIG = GPIF_EP2; /* Trigger GPIF OUT transfer on EP2 */
syncdelay(3);
break;
default:
break;
}
break;
case VR_CFGCLOSE:
ix = 10;
/* wait until GPIF transaction has been completed */
while ((GPIFTRIG & BMGPIFDONE) == 0) {
if (ix-- == 0) {
printf("GPIF done time out\n");
break;
}
delay_ms(1);
}
switch ((setup_data.wvalue) & 0x00C0) {
case 0x00:
PIN_CSI_B = 1;
PIN_RDWR_B = 1;
IFCONFIG &= 0xFC; /* Exit gpif mode */
break;
default:
break;
}
EP0BCH = 0;
EP0BCL = (uint8_t)(setup_data.wlength); /* Signal buffer is filled */
break;
default:
return true; /* Error: unknown VR command */
}
return false; /* no error; command handled OK */
}
/**
* 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:
/* ANGIE has only one configuration, return its index */
EP0BUF[0] = config_descriptor.bconfigurationvalue;
EP0BCH = 0;
EP0BCL = 1;
syncdelay(3);
break;
case SET_CONFIGURATION:
/* ANGIE has only one configuration -> nothing to do */
break;
case GET_INTERFACE:
/* ANGIE only has one interface, return its number */
EP0BUF[0] = interface_descriptor00.binterfacenumber;
EP0BCH = 0;
EP0BCL = 1;
syncdelay(3);
break;
case SET_INTERFACE:
usb_handle_set_interface();
break;
case SYNCH_FRAME:
/* Isochronous endpoints not used -> nothing to do */
break;
default:
/* if not Vendor command, Stall EndPoint 0 */
if (usb_handle_send_bitstream())
STALL_EP0();
break;
}
}
/**
* Handle the initialization of endpoints.
*/
void ep_init(void)
{
EP1INCFG = 0xA0;
syncdelay(3);
EP1OUTCFG = 0xA0;
syncdelay(3);
EP2CFG = 0xA0;
syncdelay(3);
EP4CFG = 0x00;
syncdelay(3);
EP6CFG = 0x00;
syncdelay(3);
EP8CFG = 0x00;
syncdelay(3);
/* arm EP1-OUT */
EP1OUTBC = 0;
syncdelay(3);
EP1OUTBC = 0;
syncdelay(3);
/* arm EP1-IN */
EP1INBC = 0;
syncdelay(3);
EP1INBC = 0;
syncdelay(3);
/* Standard procedure to reset FIFOs */
FIFORESET = BMNAKALL; /* NAK all transfers during the reset */
syncdelay(3);
FIFORESET = 0x02; /* reset EP2 FIFO */
syncdelay(3);
FIFORESET = 0x00; /* deactivate the NAK all */
syncdelay(3);
EP2FIFOCFG = 0x00;
syncdelay(3);
EP2FIFOCFG = BMAUTOOUT; /* Automatic 8-bit GPIF OUT mode */
syncdelay(3);
}
/**
* Interrupt initialization. Configures USB interrupts.
*/
void interrupt_init(void)
{
/* Enable Interrupts */
EA = 1;
/* Enable USB interrupt (EIE register) */
EUSB = 1;
EICON |= 0x20;
/* Enable INT 2 & 4 Autovectoring */
INTSETUP |= (AV2EN | AV4EN);
/* Enable individual EP1OUT&IN interrupts */
EPIE |= 0x0C;
/* Clear individual USB interrupt IRQ */
EPIRQ = 0x0C;
/* Enable SUDAV interrupt */
USBIEN |= SUDAVI;
/* Clear SUDAV interrupt */
USBIRQ = SUDAVI;
}
/**
* Handle the initialization of io ports.
*/
void io_init(void)
{
/* PORT A */
PORTACFG = 0x01; /* 0: normal ou 1: alternate function (each bit) */
OEA = 0xEF; /* all OUT exept INIT_B IN */
IOA = 0xFF;
PIN_RDWR_B = 1;
PIN_CSI_B = 1;
PIN_PROGRAM_B = 1;
/* PORT B */
OEB = 0xEF; /* all OUT exept TDO */
IOB = 0xFF;
PIN_TRST = 1;
PIN_TMS = 0;
PIN_TCK = 0;
PIN_TDI = 0;
PIN_SRST = 1;
/* PORT C */
PORTCCFG = 0x00; /* 0: normal ou 1: alternate function (each bit) */
OEC = 0xEF;
IOC = 0xFF;
}

View File

@ -0,0 +1,109 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (C) 2023 by NanoXplore, France - all rights reserved
# Needed by timing test
export PROJECT := angie_openocd
TARGET_PART := xc6slx9-2tqg144
export TOPLEVEL := S609
# Detects the ROOT dir from the .git marker
sp :=
sp +=
_walk = $(if $1,$(wildcard /$(subst $(sp),/,$1)/$2) $(call _walk,$(wordlist 2,$(words $1),x $1),$2))
_find = $(firstword $(call _walk,$(strip $(subst /, ,$1)),$2))
_ROOT := $(patsubst %/.git,%,$(call _find,$(CURDIR),.git))
SHELL := /bin/bash
TOP_DIR := $(realpath $(_ROOT))
HDL_DIR := $(CURDIR)
SRC_DIR := $(HDL_DIR)/src
TOOLS_DIR := $(TOP_DIR)/tools/build
COMMON_DIR := $(TOP_DIR)/common/hdl
COMMON_HDL_DIR := $(COMMON_DIR)/src
COMMON_LIBS := $(COMMON_DIR)/libs
HDL_BUILD_DIR := $(HDL_DIR)/build
OUTPUT_DIR ?= $(HDL_BUILD_DIR)/output
FINAL_OUTPUT_DIR := $(OUTPUT_DIR)/$(PROJECT)
# Tools
MKDIR := mkdir -p
CP := cp -f
HDL_SRC_PATH := $(addprefix $(COMMON_DIR)/ips/, $(HDL_IPS)) $(HDL_DIR)
VHDSOURCE += $(foreach ip,$(HDL_SRC_PATH),$(wildcard $(ip)/src/*.vhd))
VSOURCE += $(foreach ip,$(HDL_SRC_PATH),$(wildcard $(ip)/src/*.v))
VSOURCE += $(foreach ip,$(HDL_SRC_PATH),$(wildcard $(ip)/src/*.vh))
CONSTRAINTS ?= $(SRC_DIR)/$(PROJECT).ucf
COMMON_OPTS := -intstyle xflow
XST_OPTS :=
NGDBUILD_OPTS :=
MAP_OPTS := -mt 2
PAR_OPTS := -mt 4
BITGEN_OPTS := -g Binary:Yes
XILINX_PLATFORM := lin64
PATH := $(PATH):$(XILINX_HOME)/bin/$(XILINX_PLATFORM)
RUN = @echo -ne "\n\n\e[1;33m======== $(1) ========\e[m\n\n"; \
cd $(HDL_BUILD_DIR) && $(XILINX_HOME)/bin/$(XILINX_PLATFORM)/$(1)
compile: $(HDL_BUILD_DIR)/$(PROJECT).bin
install: $(HDL_BUILD_DIR)/$(PROJECT).bin
$(MKDIR) $(FINAL_OUTPUT_DIR)
$(CP) $(HDL_BUILD_DIR)/$(PROJECT).bin $(FINAL_OUTPUT_DIR)
clean:
rm -rf $(HDL_BUILD_DIR)
$(HDL_BUILD_DIR)/$(PROJECT).bin: $(HDL_BUILD_DIR)/$(PROJECT).ncd
$(call RUN,bitgen) $(COMMON_OPTS) $(BITGEN_OPTS) \
-w $(PROJECT).ncd $(PROJECT).bit
$(HDL_BUILD_DIR)/$(PROJECT).ncd: $(HDL_BUILD_DIR)/$(PROJECT).map.ncd
$(call RUN,par) $(COMMON_OPTS) $(PAR_OPTS) \
-w $(PROJECT).map.ncd $(PROJECT).ncd $(PROJECT).pcf
$(HDL_BUILD_DIR)/$(PROJECT).map.ncd: $(HDL_BUILD_DIR)/$(PROJECT).ngd
$(call RUN,map) $(COMMON_OPTS) $(MAP_OPTS) \
-p $(TARGET_PART) \
-w $(PROJECT).ngd -o $(PROJECT).map.ncd $(PROJECT).pcf
$(HDL_BUILD_DIR)/$(PROJECT).ngd: $(HDL_BUILD_DIR)/$(PROJECT).ngc
$(call RUN,ngdbuild) $(COMMON_OPTS) $(NGDBUILD_OPTS) \
-p $(TARGET_PART) -uc $(CONSTRAINTS) \
$(PROJECT).ngc $(PROJECT).ngd
$(HDL_BUILD_DIR)/$(PROJECT).ngc: $(HDL_BUILD_DIR)/$(PROJECT).prj $(HDL_BUILD_DIR)/$(PROJECT).scr
$(call RUN,xst) $(COMMON_OPTS) -ifn $(PROJECT).scr
$(HDL_BUILD_DIR)/$(PROJECT).scr: | $(HDL_BUILD_DIR)
@echo "Updating $@"
@mkdir -p $(HDL_BUILD_DIR)
@rm -f $@
@echo "run" \
"-ifn $(PROJECT).prj" \
"-ofn $(PROJECT).ngc" \
"-ifmt mixed" \
"$(XST_OPTS)" \
"-top $(TOPLEVEL)" \
"-ofmt NGC" \
"-p $(TARGET_PART)" \
> $(HDL_BUILD_DIR)/$(PROJECT).scr
$(HDL_BUILD_DIR)/$(PROJECT).prj: | $(HDL_BUILD_DIR)
@echo "Updating $@"
@rm -f $@
@$(foreach file,$(VSOURCE),echo "verilog work \"$(file)\"" >> $@;)
@$(foreach file,$(VHDSOURCE),echo "vhdl work \"$(file)\"" >> $@;)
@$(foreach lib,$(HDL_LIBS),$(foreach file,$(wildcard $(COMMON_LIBS)/$(lib)/src/*.vhd),echo "vhdl $(lib) \"$(file)\"" >> $@;))
@$(foreach lib,$(HDL_LIBS),$(foreach file,$(wildcard $(COMMON_LIBS)/$(lib)/src/*.v),echo "verilog $(lib) \"$(file)\"" >> $@;))
@$(foreach lib,$(HDL_LIBS),$(foreach file,$(wildcard $(COMMON_LIBS)/$(lib)/src/*.vh),echo "verilog $(lib) \"$(file)\"" >> $@;))
$(HDL_BUILD_DIR):
$(MKDIR) $(HDL_BUILD_DIR)
.PHONY: clean compile install

View File

@ -0,0 +1,18 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (C) 2023 by NanoXplore, France - all rights reserved
This is the source code of Nanoxplore USB-JTAG Adapter Angie's bitstream.
This bitstream is for the "xc6slx9-2tqg144" Spartan-6 Xilinx FPGA.
To generate this bitstream, you need to install Xilinx ISE Webpack 14.7
You will need to give the ISE software path : export XILINX_HOME=path/to/ise/sw
Please set the enviromnent first by executing the ". ./set_env.sh"
All you have to do now is to write your vhd and constrains codes.
One all is setup, you can use the make commands:
make compile : to compile your (.vhd & .ucf) files in the "src" directory
A directory named "build" will be created, which contains all the generated
files including the bitstream file.
make clean : to delete the build directory.

View File

@ -0,0 +1,14 @@
#!/bin/bash
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (C) 2023 by NanoXplore, France - all rights reserved
[ -z "${XILINX_HOME}" ] && export XILINX_HOME=/home/software/Xilinx/ISE/14.7/ISE_DS/ISE
export PATH="$XILINX_HOME:$PATH"
echo "SET XILINX_HOME to ${XILINX_HOME}"
# This is needed for isim
XILINX_HOME_BASE=${XILINX_HOME}/..
for part in common EDK PlanAhead ISE
do
el=${XILINX_HOME_BASE}/${part}
. ${el}/.settings64.sh ${el}
done

View File

@ -0,0 +1,35 @@
## SPDX-License-Identifier: BSD-3-Clause
##--------------------------------------------------------------------------
## Project Context: nanoXplore USB-JTAG Adapter Board, Spartan6
## Design Name: NJTAG USB-JTAG Adapter FPGA source code
## Module Name: _angie_openocd.ucf
## Target Device: XC6SLX9-2 TQ144
## Tool versions: ISE Webpack 13.2 -> 14.2
## Author: Ahmed BOUDJELIDA nanoXplore SAS
##--------------------------------------------------------------------------
# WARNING: PullUps on JTAG inputs should be enabled after configuration
# (bitgen option) since the pins are not connected.
net TRST LOC = 'P48' ;
net TMS LOC = 'P43' ;
net TCK LOC = 'P44' ;
net TDI LOC = 'P45' ;
net TDO LOC = 'P46' ;
net SRST LOC = 'P61' ;
net SI_TDO LOC = 'P16' ;
net SO_TRST LOC = 'P32' ;
net SO_TMS LOC = 'P27' ;
net SO_TCK LOC = 'P30' ;
net SO_TDI LOC = 'P26' ;
net SO_SRST LOC = 'P12' ;
net ST_0 LOC = 'P29' ;
net ST_1 LOC = 'P21' ;
net ST_2 LOC = 'P11' ;
net FTP<0> LOC = 'P121' ;
net FTP<1> LOC = 'P120' ;
net FTP<2> LOC = 'P119' ;
net FTP<3> LOC = 'P116' ;
net FTP<4> LOC = 'P111' ;
net FTP<5> LOC = 'P112' ;
net FTP<6> LOC = 'P115' ;
net FTP<7> LOC = 'P114' ;

View File

@ -0,0 +1,66 @@
-- SPDX-License-Identifier: BSD-3-Clause
----------------------------------------------------------------------------
-- Project Context: nanoXplore USB-JTAG Adapter Board, Spartan6
-- Design Name: NJTAG USB-JTAG Adapter FPGA source code
-- Module Name: _angie_openocd.vhd
-- Target Device: XC6SLX9-2 TQ144
-- Tool versions: ISE Webpack 13.2 -> 14.2
-- Author: Ahmed BOUDJELIDA nanoXplore SAS
----------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library UNISIM;
use UNISIM.VComponents.all;
entity S609 is port(
TRST : in std_logic;
TMS : in std_logic;
TCK : in std_logic;
TDI : in std_logic;
TDO : out std_logic;
SRST : in std_logic;
FTP : out std_logic_vector(7 downto 0); -- Test points
SI_TDO : in std_logic;
ST_0 : out std_logic;
ST_1 : out std_logic;
ST_2 : out std_logic;
SO_TRST : out std_logic;
SO_TMS : out std_logic;
SO_TCK : out std_logic;
SO_TDI : out std_logic;
SO_SRST :out std_logic
);
end S609;
architecture A_S609 of S609 is
begin
--Directions:
ST_0 <= '0';
ST_1 <= '1';
--TDO:
TDO <= not SI_TDO;
--TRST - TCK - TMS - TDI:
SO_TRST <= TRST;
SO_TMS <= TMS;
SO_TCK <= TCK;
SO_TDI <= TDI;
ST_2 <= SRST;
SO_SRST <= '0';
--Points de test:
FTP(0) <= TRST;
FTP(1) <= TMS;
FTP(2) <= TCK;
FTP(3) <= TDI;
FTP(5) <= SRST;
FTP(4) <= SI_TDO;
FTP(6) <= '1';
FTP(7) <= '1';
end A_S609;

View File

@ -0,0 +1,68 @@
# SPDX-License-Identifier: GPL-2.0-or-later OR GFDL-1.2-no-invariants-or-later
Bus 001 Device 056: ID 584e:424e NanoXplore, SAS. ANGIE Adapter
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 255 Vendor Specific Class
bDeviceSubClass 255 Vendor Specific Subclass
bDeviceProtocol 255 Vendor Specific Protocol
bMaxPacketSize0 64
idVendor 0x584e
idProduct 0x424e
bcdDevice 0.00
iManufacturer 1 NanoXplore, SAS.
iProduct 2 ANGIE Adapter
iSerial 3 000001
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 0x0027
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 4 (error)
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 3
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 255 Vendor Specific Protocol
iInterface 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0