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:
committed by
Antonio Borneo
parent
3b78b5c1db
commit
9c91ce8d24
189
contrib/firmware/angie/c/src/protocol.c
Normal file
189
contrib/firmware/angie/c/src/protocol.c
Normal 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user