aice: add Andes AICE support

Andes AICE uses USB to transfer packets between OpenOCD and AICE.
It uses high-level USB commands to control targets instead of using
JTAG signals. I define an interface as aice_port_api_s. It contains
all basic operations needed by target-dependent code.

Change-Id: I117bc4f938fab2732e44c509ea68b30172d6fdb9
Signed-off-by: Hsiangkai Wang <hsiangkai@gmail.com>
Reviewed-on: http://openocd.zylin.com/1256
Tested-by: jenkins
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
This commit is contained in:
Hsiangkai Wang
2013-02-05 09:34:18 +08:00
committed by Spencer Oliver
parent 8890ce3469
commit ceb402dc9e
21 changed files with 7182 additions and 2 deletions

27
src/jtag/aice/Makefile.am Normal file
View File

@@ -0,0 +1,27 @@
include $(top_srcdir)/common.mk
AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers
noinst_LTLIBRARIES = libocdaice.la
libocdaice_la_SOURCES = \
$(AICEFILES)
AICEFILES =
if AICE
AICEFILES += aice_transport.c
AICEFILES += aice_interface.c
AICEFILES += aice_port.c
AICEFILES += aice_usb.c
AICEFILES += aice_pipe.c
endif
noinst_HEADERS = \
aice_transport.h \
aice_interface.h \
aice_port.h \
aice_usb.h \
aice_pipe.h
MAINTAINERCLEANFILES = $(srcdir)/Makefile.in

View File

@@ -0,0 +1,500 @@
/***************************************************************************
* Copyright (C) 2013 by Andes Technology *
* Hsiangkai Wang <hkwang@andestech.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <jtag/interface.h>
#include <jtag/commands.h>
#include <transport/transport.h>
#include <target/target.h>
#include <jtag/aice/aice_transport.h>
#include <jtag/drivers/libusb_common.h>
#include "aice_usb.h"
#define AICE_KHZ_TO_SPEED_MAP_SIZE 16
static int aice_khz_to_speed_map[AICE_KHZ_TO_SPEED_MAP_SIZE] = {
30000,
15000,
7500,
3750,
1875,
937,
468,
234,
48000,
24000,
12000,
6000,
3000,
1500,
750,
375,
};
static struct aice_port_s aice;
/***************************************************************************/
/* External interface implementation */
#define AICE_MAX_TARGET_ID_CODES 0x10
static uint32_t aice_target_id_codes[AICE_MAX_TARGET_ID_CODES];
static uint8_t aice_num_of_target_id_codes;
/***************************************************************************/
/* AICE operations */
int aice_init_target(struct target *t)
{
int res;
LOG_DEBUG("aice_init_target");
if (aice_num_of_target_id_codes == 0) {
res = aice.port->api->idcode(aice_target_id_codes, &aice_num_of_target_id_codes);
if (res != ERROR_OK) {
LOG_ERROR("<-- TARGET ERROR! Failed to identify AndesCore "
"JTAG Manufacture ID in the JTAG scan chain. "
"Failed to access EDM registers. -->");
return res;
}
}
t->tap->idcode = aice_target_id_codes[t->tap->abs_chain_position];
unsigned ii, limit = t->tap->expected_ids_cnt;
int found = 0;
for (ii = 0; ii < limit; ii++) {
uint32_t expected = t->tap->expected_ids[ii];
/* treat "-expected-id 0" as a "don't-warn" wildcard */
if (!expected || (t->tap->idcode == expected)) {
found = 1;
break;
}
}
if (found == 0) {
LOG_ERROR
("aice_init_target: target not found: idcode: %x ",
t->tap->idcode);
return ERROR_FAIL;
}
t->tap->priv = &aice;
t->tap->hasidcode = 1;
return ERROR_OK;
}
/***************************************************************************/
/* End of External interface implementation */
/* initial aice
* 1. open usb
* 2. get/show version number
* 3. reset
*/
static int aice_init(void)
{
if (ERROR_OK != aice.port->api->open(&(aice.param))) {
LOG_ERROR("Cannot find AICE Interface! Please check "
"connection and permissions.");
return ERROR_JTAG_INIT_FAILED;
}
aice.port->api->set_retry_times(aice.retry_times);
aice.port->api->set_count_to_check_dbger(aice.count_to_check_dbger);
LOG_INFO("AICE JTAG Interface ready");
return ERROR_OK;
}
/* cleanup aice resource
* close usb
*/
static int aice_quit(void)
{
aice.port->api->close();
return ERROR_OK;
}
static int aice_execute_reset(struct jtag_command *cmd)
{
static int last_trst;
int retval = ERROR_OK;
DEBUG_JTAG_IO("reset trst: %i", cmd->cmd.reset->trst);
if (cmd->cmd.reset->trst != last_trst) {
if (cmd->cmd.reset->trst)
retval = aice.port->api->reset();
last_trst = cmd->cmd.reset->trst;
}
return retval;
}
static int aice_execute_command(struct jtag_command *cmd)
{
int retval;
switch (cmd->type) {
case JTAG_RESET:
retval = aice_execute_reset(cmd);
break;
default:
retval = ERROR_OK;
break;
}
return retval;
}
/* aice has no need to implement jtag execution model
*/
static int aice_execute_queue(void)
{
struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
int retval;
retval = ERROR_OK;
while (cmd) {
if (aice_execute_command(cmd) != ERROR_OK)
retval = ERROR_JTAG_QUEUE_FAILED;
cmd = cmd->next;
}
return retval;
}
/* set jtag frequency(base frequency/frequency divider) to your jtag adapter */
static int aice_speed(int speed)
{
return aice.port->api->set_jtag_clock(speed);
}
/* convert jtag adapter frequency(base frequency/frequency divider) to
* human readable KHz value */
static int aice_speed_div(int speed, int *khz)
{
*khz = aice_khz_to_speed_map[speed];
return ERROR_OK;
}
/* convert human readable KHz value to jtag adapter frequency
* (base frequency/frequency divider) */
static int aice_khz(int khz, int *jtag_speed)
{
int i;
for (i = 0 ; i < AICE_KHZ_TO_SPEED_MAP_SIZE ; i++) {
if (khz == aice_khz_to_speed_map[i]) {
if (8 <= i)
*jtag_speed = i | AICE_TCK_CONTROL_TCK3048;
else
*jtag_speed = i;
break;
}
}
if (i == AICE_KHZ_TO_SPEED_MAP_SIZE) {
LOG_INFO("No support the jtag clock: %d", khz);
LOG_INFO("Supported jtag clocks are:");
for (i = 0 ; i < AICE_KHZ_TO_SPEED_MAP_SIZE ; i++)
LOG_INFO("* %d", aice_khz_to_speed_map[i]);
return ERROR_FAIL;
}
return ERROR_OK;
}
/***************************************************************************/
/* Command handlers */
COMMAND_HANDLER(aice_handle_aice_info_command)
{
LOG_DEBUG("aice_handle_aice_info_command");
command_print(CMD_CTX, "Description: %s", aice.param.device_desc);
command_print(CMD_CTX, "Serial number: %s", aice.param.serial);
if (strncmp(aice.port->name, "aice_pipe", 9) == 0)
command_print(CMD_CTX, "Adapter: %s", aice.param.adapter_name);
return ERROR_OK;
}
COMMAND_HANDLER(aice_handle_aice_port_command)
{
LOG_DEBUG("aice_handle_aice_port_command");
if (CMD_ARGC != 1) {
LOG_ERROR("Need exactly one argument to 'aice port'");
return ERROR_COMMAND_SYNTAX_ERROR;
}
for (const struct aice_port *l = aice_port_get_list(); l->name; l++) {
if (strcmp(l->name, CMD_ARGV[0]) == 0) {
aice.port = l;
return ERROR_OK;
}
}
LOG_ERROR("No AICE port '%s' found", CMD_ARGV[0]);
return ERROR_FAIL;
}
COMMAND_HANDLER(aice_handle_aice_desc_command)
{
LOG_DEBUG("aice_handle_aice_desc_command");
if (CMD_ARGC == 1)
aice.param.device_desc = strdup(CMD_ARGV[0]);
else
LOG_ERROR("expected exactly one argument to aice desc <description>");
return ERROR_OK;
}
COMMAND_HANDLER(aice_handle_aice_serial_command)
{
LOG_DEBUG("aice_handle_aice_serial_command");
if (CMD_ARGC == 1)
aice.param.serial = strdup(CMD_ARGV[0]);
else
LOG_ERROR("expected exactly one argument to aice serial <serial-number>");
return ERROR_OK;
}
COMMAND_HANDLER(aice_handle_aice_vid_pid_command)
{
LOG_DEBUG("aice_handle_aice_vid_pid_command");
if (CMD_ARGC != 2) {
LOG_WARNING("ignoring extra IDs in aice vid_pid (maximum is 1 pair)");
return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], aice.param.vid);
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], aice.param.pid);
return ERROR_OK;
}
COMMAND_HANDLER(aice_handle_aice_adapter_command)
{
LOG_DEBUG("aice_handle_aice_adapter_command");
if (CMD_ARGC == 1)
aice.param.adapter_name = strdup(CMD_ARGV[0]);
else
LOG_ERROR("expected exactly one argument to aice adapter <adapter-name>");
return ERROR_OK;
}
COMMAND_HANDLER(aice_handle_aice_retry_times_command)
{
LOG_DEBUG("aice_handle_aice_retry_times_command");
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], aice.retry_times);
else
LOG_ERROR("expected exactly one argument to aice retry_times <num_of_retry>");
return ERROR_OK;
}
COMMAND_HANDLER(aice_handle_aice_count_to_check_dbger_command)
{
LOG_DEBUG("aice_handle_aice_count_to_check_dbger_command");
if (CMD_ARGC == 1)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], aice.count_to_check_dbger);
else
LOG_ERROR("expected exactly one argument to aice count_to_check_dbger "
"<count_of_checking>");
return ERROR_OK;
}
COMMAND_HANDLER(aice_handle_aice_custom_srst_script_command)
{
LOG_DEBUG("aice_handle_aice_custom_srst_script_command");
if (CMD_ARGC > 0) {
aice.port->api->set_custom_srst_script(CMD_ARGV[0]);
return ERROR_OK;
}
return ERROR_FAIL;
}
COMMAND_HANDLER(aice_handle_aice_custom_trst_script_command)
{
LOG_DEBUG("aice_handle_aice_custom_trst_script_command");
if (CMD_ARGC > 0) {
aice.port->api->set_custom_trst_script(CMD_ARGV[0]);
return ERROR_OK;
}
return ERROR_FAIL;
}
COMMAND_HANDLER(aice_handle_aice_custom_restart_script_command)
{
LOG_DEBUG("aice_handle_aice_custom_restart_script_command");
if (CMD_ARGC > 0) {
aice.port->api->set_custom_restart_script(CMD_ARGV[0]);
return ERROR_OK;
}
return ERROR_FAIL;
}
COMMAND_HANDLER(aice_handle_aice_reset_command)
{
LOG_DEBUG("aice_handle_aice_reset_command");
return aice.port->api->reset();
}
static const struct command_registration aice_subcommand_handlers[] = {
{
.name = "info",
.handler = &aice_handle_aice_info_command,
.mode = COMMAND_EXEC,
.help = "show aice info",
.usage = "aice info",
},
{
.name = "port",
.handler = &aice_handle_aice_port_command,
.mode = COMMAND_CONFIG,
.help = "set the port of the AICE",
.usage = "aice port ['aice_pipe'|'aice_usb']",
},
{
.name = "desc",
.handler = &aice_handle_aice_desc_command,
.mode = COMMAND_CONFIG,
.help = "set the aice device description",
.usage = "aice desc [desciption string]",
},
{
.name = "serial",
.handler = &aice_handle_aice_serial_command,
.mode = COMMAND_CONFIG,
.help = "set the serial number of the AICE device",
.usage = "aice serial [serial string]",
},
{
.name = "vid_pid",
.handler = &aice_handle_aice_vid_pid_command,
.mode = COMMAND_CONFIG,
.help = "the vendor and product ID of the AICE device",
.usage = "aice vid_pid (vid pid)*",
},
{
.name = "adapter",
.handler = &aice_handle_aice_adapter_command,
.mode = COMMAND_CONFIG,
.help = "set the file name of adapter",
.usage = "aice adapter [adapter name]",
},
{
.name = "retry_times",
.handler = &aice_handle_aice_retry_times_command,
.mode = COMMAND_CONFIG,
.help = "set retry times as AICE timeout",
.usage = "aice retry_times num_of_retry",
},
{
.name = "count_to_check_dbger",
.handler = &aice_handle_aice_count_to_check_dbger_command,
.mode = COMMAND_CONFIG,
.help = "set retry times as checking $DBGER status",
.usage = "aice count_to_check_dbger count_of_checking",
},
{
.name = "custom_srst_script",
.handler = &aice_handle_aice_custom_srst_script_command,
.mode = COMMAND_CONFIG,
.usage = "custom_srst_script script_file_name",
.help = "set custom srst script",
},
{
.name = "custom_trst_script",
.handler = &aice_handle_aice_custom_trst_script_command,
.mode = COMMAND_CONFIG,
.usage = "custom_trst_script script_file_name",
.help = "set custom trst script",
},
{
.name = "custom_restart_script",
.handler = &aice_handle_aice_custom_restart_script_command,
.mode = COMMAND_CONFIG,
.usage = "custom_restart_script script_file_name",
.help = "set custom restart script",
},
{
.name = "reset",
.handler = &aice_handle_aice_reset_command,
.mode = COMMAND_EXEC,
.usage = "aice reset",
.help = "reset AICE",
},
COMMAND_REGISTRATION_DONE
};
static const struct command_registration aice_command_handlers[] = {
{
.name = "aice",
.mode = COMMAND_ANY,
.help = "perform aice management",
.usage = "aice [subcommand]",
.chain = aice_subcommand_handlers,
},
COMMAND_REGISTRATION_DONE
};
/***************************************************************************/
/* End of Command handlers */
struct jtag_interface aice_interface = {
.name = "aice",
.commands = aice_command_handlers,
.transports = aice_transports,
.init = aice_init,
.quit = aice_quit,
.execute_queue = aice_execute_queue,
.speed = aice_speed, /* set interface speed */
.speed_div = aice_speed_div, /* return readable value */
.khz = aice_khz, /* convert khz to interface speed value */
};

View File

@@ -0,0 +1,36 @@
/***************************************************************************
* Copyright (C) 2013 by Andes Technology *
* Hsiangkai Wang <hkwang@andestech.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
#ifndef __AICE_INTERFACE_H__
#define __AICE_INTERFACE_H__
struct aice_interface_param_s {
/** */
char *device_desc;
/** */
char *serial;
/** */
uint16_t vid;
/** */
uint16_t pid;
};
int aice_init_target(struct target *t);
#endif

915
src/jtag/aice/aice_pipe.c Normal file
View File

@@ -0,0 +1,915 @@
/***************************************************************************
* Copyright (C) 2013 by Andes Technology *
* Hsiangkai Wang <hkwang@andestech.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef _WIN32
#include <windows.h>
#else
#include <signal.h>
#endif
#include <helper/log.h>
#include <helper/time_support.h>
#include "aice_port.h"
#include "aice_pipe.h"
#define AICE_PIPE_MAXLINE 8192
#ifdef _WIN32
PROCESS_INFORMATION proc_info;
HANDLE aice_pipe_output[2];
HANDLE aice_pipe_input[2];
static int aice_pipe_write(const void *buffer, int count)
{
BOOL success;
DWORD written;
success = WriteFile(aice_pipe_output[1], buffer, count, &written, NULL);
if (!success) {
LOG_ERROR("(WIN32) write to pipe failed, error code: 0x%08lx", GetLastError());
return -1;
}
return written;
}
static int aice_pipe_read(void *buffer, int count)
{
BOOL success;
DWORD has_read;
success = ReadFile(aice_pipe_input[0], buffer, count, &has_read, NULL);
if (!success || (has_read == 0)) {
LOG_ERROR("(WIN32) read from pipe failed, error code: 0x%08lx", GetLastError());
return -1;
}
return has_read;
}
static int aice_pipe_child_init(struct aice_port_param_s *param)
{
STARTUPINFO start_info;
BOOL success;
ZeroMemory(&proc_info, sizeof(PROCESS_INFORMATION));
ZeroMemory(&start_info, sizeof(STARTUPINFO));
start_info.cb = sizeof(STARTUPINFO);
start_info.hStdError = aice_pipe_input[1];
start_info.hStdOutput = aice_pipe_input[1];
start_info.hStdInput = aice_pipe_output[0];
start_info.dwFlags |= STARTF_USESTDHANDLES;
success = CreateProcess(NULL,
param->adapter_name,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&start_info,
&proc_info);
if (!success) {
LOG_ERROR("Create new process failed");
return ERROR_FAIL;
}
return ERROR_OK;
}
static int aice_pipe_parent_init(struct aice_port_param_s *param)
{
/* send open to adapter */
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_OPEN;
set_u16(command + 1, param->vid);
set_u16(command + 3, param->pid);
if (aice_pipe_write(command, 5) != 5) {
LOG_ERROR("write failed\n");
return ERROR_FAIL;
}
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) {
LOG_ERROR("read failed\n");
return ERROR_FAIL;
}
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_open(struct aice_port_param_s *param)
{
SECURITY_ATTRIBUTES attribute;
attribute.nLength = sizeof(SECURITY_ATTRIBUTES);
attribute.bInheritHandle = TRUE;
attribute.lpSecurityDescriptor = NULL;
if (!CreatePipe(&aice_pipe_output[0], &aice_pipe_output[1],
&attribute, AICE_PIPE_MAXLINE)) {
LOG_ERROR("Create pipes failed");
return ERROR_FAIL;
}
if (!CreatePipe(&aice_pipe_input[0], &aice_pipe_input[1],
&attribute, AICE_PIPE_MAXLINE)) {
LOG_ERROR("Create pipes failed");
return ERROR_FAIL;
}
/* do not inherit aice_pipe_output[1] & aice_pipe_input[0] to child process */
if (!SetHandleInformation(aice_pipe_output[1], HANDLE_FLAG_INHERIT, 0))
return ERROR_FAIL;
if (!SetHandleInformation(aice_pipe_input[0], HANDLE_FLAG_INHERIT, 0))
return ERROR_FAIL;
aice_pipe_child_init(param);
aice_pipe_parent_init(param);
return ERROR_OK;
}
#else
int aice_pipe_output[2];
int aice_pipe_input[2];
static int aice_pipe_write(const void *buffer, int count)
{
if (write(aice_pipe_output[1], buffer, count) != count) {
LOG_ERROR("write to pipe failed");
return -1;
}
return count;
}
static int aice_pipe_read(void *buffer, int count)
{
int n;
long long then, cur;
then = timeval_ms();
while (1) {
n = read(aice_pipe_input[0], buffer, count);
if ((n == -1) && (errno == EAGAIN)) {
cur = timeval_ms();
if (cur - then > 500)
keep_alive();
continue;
} else if (n > 0)
break;
else {
LOG_ERROR("read from pipe failed");
break;
}
}
return n;
}
static int aice_pipe_child_init(struct aice_port_param_s *param)
{
close(aice_pipe_output[1]);
close(aice_pipe_input[0]);
if (aice_pipe_output[0] != STDIN_FILENO) {
if (dup2(aice_pipe_output[0], STDIN_FILENO) != STDIN_FILENO) {
LOG_ERROR("Map aice_pipe to STDIN failed");
return ERROR_FAIL;
}
close(aice_pipe_output[0]);
}
if (aice_pipe_input[1] != STDOUT_FILENO) {
if (dup2(aice_pipe_input[1], STDOUT_FILENO) != STDOUT_FILENO) {
LOG_ERROR("Map aice_pipe to STDOUT failed");
return ERROR_FAIL;
}
close(aice_pipe_input[1]);
}
if (execl(param->adapter_name, param->adapter_name, (char *)0) < 0) {
LOG_ERROR("Execute aice_pipe failed");
return ERROR_FAIL;
}
return ERROR_OK;
}
static int aice_pipe_parent_init(struct aice_port_param_s *param)
{
close(aice_pipe_output[0]);
close(aice_pipe_input[1]);
/* set read end of pipe as non-blocking */
if (fcntl(aice_pipe_input[0], F_SETFL, O_NONBLOCK))
return ERROR_FAIL;
/* send open to adapter */
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_OPEN;
set_u16(command + 1, param->vid);
set_u16(command + 3, param->pid);
if (aice_pipe_write(command, 5) != 5) {
LOG_ERROR("write failed\n");
return ERROR_FAIL;
}
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0) {
LOG_ERROR("read failed\n");
return ERROR_FAIL;
}
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static void sig_pipe(int signo)
{
exit(1);
}
static int aice_pipe_open(struct aice_port_param_s *param)
{
pid_t pid;
if (signal(SIGPIPE, sig_pipe) == SIG_ERR) {
LOG_ERROR("Register SIGPIPE handler failed");
return ERROR_FAIL;
}
if (pipe(aice_pipe_output) < 0 || pipe(aice_pipe_input) < 0) {
LOG_ERROR("Create pipes failed");
return ERROR_FAIL;
}
pid = fork();
if (pid < 0) {
LOG_ERROR("Fork new process failed");
return ERROR_FAIL;
} else if (pid == 0) {
if (aice_pipe_child_init(param) != ERROR_OK) {
LOG_ERROR("AICE_PIPE child process initial error");
return ERROR_FAIL;
} else {
if (aice_pipe_parent_init(param) != ERROR_OK) {
LOG_ERROR("AICE_PIPE parent process initial error");
return ERROR_FAIL;
}
}
}
return ERROR_OK;
}
#endif
static int aice_pipe_close(void)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_CLOSE;
if (aice_pipe_write(command, 1) != 1)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK) {
#ifdef _WIN32
WaitForSingleObject(proc_info.hProcess, INFINITE);
CloseHandle(proc_info.hProcess);
CloseHandle(proc_info.hThread);
#endif
return ERROR_OK;
} else
return ERROR_FAIL;
}
static int aice_pipe_idcode(uint32_t *idcode, uint8_t *num_of_idcode)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_IDCODE;
if (aice_pipe_write(command, 1) != 1)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
*num_of_idcode = line[0];
if ((*num_of_idcode == 0) || (*num_of_idcode >= 16))
return ERROR_FAIL;
for (int i = 0 ; i < *num_of_idcode ; i++)
idcode[i] = get_u32(line + i * 4 + 1);
return ERROR_OK;
}
static int aice_pipe_state(enum aice_target_state_s *state)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_STATE;
if (aice_pipe_write(command, 1) != 1)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
*state = (enum aice_target_state_s)line[0];
return ERROR_OK;
}
static int aice_pipe_reset(void)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_RESET;
if (aice_pipe_write(command, 1) != 1)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_assert_srst(enum aice_srst_type_s srst)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_ASSERT_SRST;
command[1] = srst;
if (aice_pipe_write(command, 2) != 2)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_run(void)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_RUN;
if (aice_pipe_write(command, 1) != 1)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_halt(void)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_HALT;
if (aice_pipe_write(command, 1) != 1)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_read_reg(uint32_t num, uint32_t *val)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_READ_REG;
set_u32(command + 1, num);
if (aice_pipe_write(command, 5) != 5)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
*val = get_u32(line);
return ERROR_OK;
}
static int aice_pipe_write_reg(uint32_t num, uint32_t val)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_WRITE_REG;
set_u32(command + 1, num);
set_u32(command + 5, val);
if (aice_pipe_write(command, 9) != 9)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_read_reg_64(uint32_t num, uint64_t *val)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_READ_REG_64;
set_u32(command + 1, num);
if (aice_pipe_write(command, 5) != 5)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
*val = (((uint64_t)get_u32(line + 4)) << 32) | get_u32(line);
return ERROR_OK;
}
static int aice_pipe_write_reg_64(uint32_t num, uint64_t val)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_WRITE_REG_64;
set_u32(command + 1, num);
set_u32(command + 5, val & 0xFFFFFFFF);
set_u32(command + 9, (val >> 32) & 0xFFFFFFFF);
if (aice_pipe_write(command, 13) != 9)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_step(void)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_STEP;
if (aice_pipe_write(command, 1) != 1)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_read_mem_unit(uint32_t addr, uint32_t size,
uint32_t count, uint8_t *buffer)
{
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_READ_MEM_UNIT;
set_u32(command + 1, addr);
set_u32(command + 5, size);
set_u32(command + 9, count);
if (aice_pipe_write(command, 13) != 13)
return ERROR_FAIL;
if (aice_pipe_read(buffer, size * count) < 0)
return ERROR_FAIL;
return ERROR_OK;
}
static int aice_pipe_write_mem_unit(uint32_t addr, uint32_t size,
uint32_t count, const uint8_t *buffer)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_WRITE_MEM_UNIT;
set_u32(command + 1, addr);
set_u32(command + 5, size);
set_u32(command + 9, count);
/* WRITE_MEM_UNIT|addr|size|count|data */
memcpy(command + 13, buffer, size * count);
if (aice_pipe_write(command, 13 + size * count) < 0)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
return ERROR_OK;
}
static int aice_pipe_read_mem_bulk(uint32_t addr, uint32_t length, uint8_t *buffer)
{
char line[AICE_PIPE_MAXLINE + 1];
char command[AICE_PIPE_MAXLINE];
uint32_t remain_len = length;
uint32_t prepare_len;
char *received_line;
uint32_t received_len;
int read_len;
command[0] = AICE_READ_MEM_BULK;
set_u32(command + 1, addr);
set_u32(command + 5, length);
if (aice_pipe_write(command, 9) < 0)
return ERROR_FAIL;
while (remain_len > 0) {
if (remain_len > AICE_PIPE_MAXLINE)
prepare_len = AICE_PIPE_MAXLINE;
else
prepare_len = remain_len;
prepare_len++;
received_len = 0;
received_line = line;
do {
read_len = aice_pipe_read(received_line, prepare_len - received_len);
if (read_len < 0)
return ERROR_FAIL;
received_line += read_len;
received_len += read_len;
} while (received_len < prepare_len);
if (line[0] != AICE_OK)
return ERROR_FAIL;
prepare_len--;
memcpy(buffer, line + 1, prepare_len);
remain_len -= prepare_len;
buffer += prepare_len;
}
return ERROR_OK;
}
static int aice_pipe_write_mem_bulk(uint32_t addr, uint32_t length, const uint8_t *buffer)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE + 4];
uint32_t remain_len = length;
uint32_t written_len = 0;
uint32_t write_len;
command[0] = AICE_WRITE_MEM_BULK;
set_u32(command + 1, addr);
set_u32(command + 5, length);
/* Send command first */
if (aice_pipe_write(command, 9) < 0)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_ERROR)
return ERROR_FAIL;
while (remain_len > 0) {
if (remain_len > AICE_PIPE_MAXLINE)
write_len = AICE_PIPE_MAXLINE;
else
write_len = remain_len;
set_u32(command, write_len);
memcpy(command + 4, buffer + written_len, write_len); /* data only */
if (aice_pipe_write(command, write_len + 4) < 0)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_ERROR)
return ERROR_FAIL;
remain_len -= write_len;
written_len += write_len;
}
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_read_debug_reg(uint32_t addr, uint32_t *val)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_READ_DEBUG_REG;
set_u32(command + 1, addr);
if (aice_pipe_write(command, 5) != 5)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
*val = get_u32(line);
return ERROR_OK;
}
static int aice_pipe_write_debug_reg(uint32_t addr, const uint32_t val)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_WRITE_DEBUG_REG;
set_u32(command + 1, addr);
set_u32(command + 5, val);
if (aice_pipe_write(command, 9) != 9)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_set_jtag_clock(uint32_t a_clock)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_SET_JTAG_CLOCK;
set_u32(command + 1, a_clock);
if (aice_pipe_write(command, 5) != 5)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_select_target(uint32_t target_id)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_SELECT_TARGET;
set_u32(command + 1, target_id);
if (aice_pipe_write(command, 5) != 5)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_memory_access(enum nds_memory_access access_channel)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_MEMORY_ACCESS;
set_u32(command + 1, access_channel);
if (aice_pipe_write(command, 5) != 5)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_memory_mode(enum nds_memory_select mem_select)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_MEMORY_MODE;
set_u32(command + 1, mem_select);
if (aice_pipe_write(command, 5) != 5)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_read_tlb(uint32_t virtual_address, uint32_t *physical_address)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_READ_TLB;
set_u32(command + 1, virtual_address);
if (aice_pipe_write(command, 5) != 5)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK) {
*physical_address = get_u32(line + 1);
return ERROR_OK;
} else
return ERROR_FAIL;
}
static int aice_pipe_cache_ctl(uint32_t subtype, uint32_t address)
{
char line[AICE_PIPE_MAXLINE];
char command[AICE_PIPE_MAXLINE];
command[0] = AICE_CACHE_CTL;
set_u32(command + 1, subtype);
set_u32(command + 5, address);
if (aice_pipe_write(command, 9) != 9)
return ERROR_FAIL;
if (aice_pipe_read(line, AICE_PIPE_MAXLINE) < 0)
return ERROR_FAIL;
if (line[0] == AICE_OK)
return ERROR_OK;
else
return ERROR_FAIL;
}
static int aice_pipe_set_retry_times(uint32_t a_retry_times)
{
return ERROR_OK;
}
/** */
struct aice_port_api_s aice_pipe = {
/** */
.open = aice_pipe_open,
/** */
.close = aice_pipe_close,
/** */
.idcode = aice_pipe_idcode,
/** */
.state = aice_pipe_state,
/** */
.reset = aice_pipe_reset,
/** */
.assert_srst = aice_pipe_assert_srst,
/** */
.run = aice_pipe_run,
/** */
.halt = aice_pipe_halt,
/** */
.step = aice_pipe_step,
/** */
.read_reg = aice_pipe_read_reg,
/** */
.write_reg = aice_pipe_write_reg,
/** */
.read_reg_64 = aice_pipe_read_reg_64,
/** */
.write_reg_64 = aice_pipe_write_reg_64,
/** */
.read_mem_unit = aice_pipe_read_mem_unit,
/** */
.write_mem_unit = aice_pipe_write_mem_unit,
/** */
.read_mem_bulk = aice_pipe_read_mem_bulk,
/** */
.write_mem_bulk = aice_pipe_write_mem_bulk,
/** */
.read_debug_reg = aice_pipe_read_debug_reg,
/** */
.write_debug_reg = aice_pipe_write_debug_reg,
/** */
.set_jtag_clock = aice_pipe_set_jtag_clock,
/** */
.select_target = aice_pipe_select_target,
/** */
.memory_access = aice_pipe_memory_access,
/** */
.memory_mode = aice_pipe_memory_mode,
/** */
.read_tlb = aice_pipe_read_tlb,
/** */
.cache_ctl = aice_pipe_cache_ctl,
/** */
.set_retry_times = aice_pipe_set_retry_times,
};

32
src/jtag/aice/aice_pipe.h Normal file
View File

@@ -0,0 +1,32 @@
/***************************************************************************
* Copyright (C) 2013 by Andes Technology *
* Hsiangkai Wang <hkwang@andestech.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
#ifndef _AICE_PIPE_H_
#define _AICE_PIPE_H_
#include <helper/types.h>
#define set_u32(buffer, value) h_u32_to_le((uint8_t *)buffer, value)
#define set_u16(buffer, value) h_u16_to_le((uint8_t *)buffer, value)
#define get_u32(buffer) le_to_h_u32((const uint8_t *)buffer)
#define get_u16(buffer) le_to_h_u16((const uint8_t *)buffer)
extern struct aice_port_api_s aice_pipe;
#endif

47
src/jtag/aice/aice_port.c Normal file
View File

@@ -0,0 +1,47 @@
/***************************************************************************
* Copyright (C) 2013 by Andes Technology *
* Hsiangkai Wang <hkwang@andestech.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <helper/log.h>
#include "aice_usb.h"
#include "aice_pipe.h"
#include "aice_port.h"
static const struct aice_port aice_ports[] = {
{
.name = "aice_usb",
.type = AICE_PORT_AICE_USB,
.api = &aice_usb_api,
},
{
.name = "aice_pipe",
.type = AICE_PORT_AICE_PIPE,
.api = &aice_pipe,
},
{.name = NULL, /* END OF TABLE */ },
};
/** */
const struct aice_port *aice_port_get_list(void)
{
return aice_ports;
}

234
src/jtag/aice/aice_port.h Normal file
View File

@@ -0,0 +1,234 @@
/***************************************************************************
* Copyright (C) 2013 by Andes Technology *
* Hsiangkai Wang <hkwang@andestech.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
#ifndef _AICE_PORT_H_
#define _AICE_PORT_H_
#include <target/nds32_edm.h>
#define ERROR_AICE_DISCONNECT (-200)
#define ERROR_AICE_TIMEOUT (-201)
enum aice_target_state_s {
AICE_DISCONNECT = 0,
AICE_TARGET_DETACH,
AICE_TARGET_UNKNOWN,
AICE_TARGET_RUNNING,
AICE_TARGET_HALTED,
AICE_TARGET_RESET,
AICE_TARGET_DEBUG_RUNNING,
};
enum aice_srst_type_s {
AICE_SRST = 0x1,
AICE_RESET_HOLD = 0x8,
};
enum aice_target_endian {
AICE_LITTLE_ENDIAN = 0,
AICE_BIG_ENDIAN,
};
enum aice_api_s {
AICE_OPEN = 0x0,
AICE_CLOSE,
AICE_RESET,
AICE_ASSERT_SRST,
AICE_RUN,
AICE_HALT,
AICE_STEP,
AICE_READ_REG,
AICE_WRITE_REG,
AICE_READ_REG_64,
AICE_WRITE_REG_64,
AICE_READ_MEM_UNIT,
AICE_WRITE_MEM_UNIT,
AICE_READ_MEM_BULK,
AICE_WRITE_MEM_BULK,
AICE_READ_DEBUG_REG,
AICE_WRITE_DEBUG_REG,
AICE_IDCODE,
AICE_STATE,
AICE_SET_JTAG_CLOCK,
AICE_SELECT_TARGET,
AICE_MEMORY_ACCESS,
AICE_MEMORY_MODE,
AICE_READ_TLB,
AICE_CACHE_CTL,
AICE_SET_RETRY_TIMES,
AICE_PROGRAM_EDM,
AICE_PACK_COMMAND,
AICE_EXECUTE,
AICE_SET_CUSTOM_SRST_SCRIPT,
AICE_SET_CUSTOM_TRST_SCRIPT,
AICE_SET_CUSTOM_RESTART_SCRIPT,
AICE_SET_COUNT_TO_CHECK_DBGER,
AICE_SET_DATA_ENDIAN,
};
enum aice_error_s {
AICE_OK,
AICE_ACK,
AICE_ERROR,
};
enum aice_cache_ctl_type {
AICE_CACHE_CTL_L1D_INVALALL = 0,
AICE_CACHE_CTL_L1D_VA_INVAL,
AICE_CACHE_CTL_L1D_WBALL,
AICE_CACHE_CTL_L1D_VA_WB,
AICE_CACHE_CTL_L1I_INVALALL,
AICE_CACHE_CTL_L1I_VA_INVAL,
};
struct aice_port_param_s {
/** */
char *device_desc;
/** */
char *serial;
/** */
uint16_t vid;
/** */
uint16_t pid;
/** */
char *adapter_name;
};
struct aice_port_s {
/** */
struct aice_port_param_s param;
/** */
const struct aice_port *port;
/** */
uint32_t retry_times;
/** */
uint32_t count_to_check_dbger;
};
/** */
extern struct aice_port_api_s aice_usb_layout_api;
/** */
struct aice_port_api_s {
/** */
int (*open)(struct aice_port_param_s *param);
/** */
int (*close)(void);
/** */
int (*reset)(void);
/** */
int (*assert_srst)(enum aice_srst_type_s srst);
/** */
int (*run)(void);
/** */
int (*halt)(void);
/** */
int (*step)(void);
/** */
int (*read_reg)(uint32_t num, uint32_t *val);
/** */
int (*write_reg)(uint32_t num, uint32_t val);
/** */
int (*read_reg_64)(uint32_t num, uint64_t *val);
/** */
int (*write_reg_64)(uint32_t num, uint64_t val);
/** */
int (*read_mem_unit)(uint32_t addr, uint32_t size, uint32_t count,
uint8_t *buffer);
/** */
int (*write_mem_unit)(uint32_t addr, uint32_t size, uint32_t count,
const uint8_t *buffer);
/** */
int (*read_mem_bulk)(uint32_t addr, uint32_t length,
uint8_t *buffer);
/** */
int (*write_mem_bulk)(uint32_t addr, uint32_t length,
const uint8_t *buffer);
/** */
int (*read_debug_reg)(uint32_t addr, uint32_t *val);
/** */
int (*write_debug_reg)(uint32_t addr, const uint32_t val);
/** */
int (*idcode)(uint32_t *idcode, uint8_t *num_of_idcode);
/** */
int (*state)(enum aice_target_state_s *state);
/** */
int (*set_jtag_clock)(uint32_t a_clock);
/** */
int (*select_target)(uint32_t target_id);
/** */
int (*memory_access)(enum nds_memory_access a_access);
/** */
int (*memory_mode)(enum nds_memory_select mem_select);
/** */
int (*read_tlb)(uint32_t virtual_address, uint32_t *physical_address);
/** */
int (*cache_ctl)(uint32_t subtype, uint32_t address);
/** */
int (*set_retry_times)(uint32_t a_retry_times);
/** */
int (*program_edm)(char *command_sequence);
/** */
int (*pack_command)(bool enable_pack_command);
/** */
int (*execute)(uint32_t *instructions, uint32_t instruction_num);
/** */
int (*set_custom_srst_script)(const char *script);
/** */
int (*set_custom_trst_script)(const char *script);
/** */
int (*set_custom_restart_script)(const char *script);
/** */
int (*set_count_to_check_dbger)(uint32_t count_to_check);
/** */
int (*set_data_endian)(enum aice_target_endian target_data_endian);
};
#define AICE_PORT_UNKNOWN 0
#define AICE_PORT_AICE_USB 1
#define AICE_PORT_AICE_PIPE 2
/** */
struct aice_port {
/** */
char *name;
/** */
int type;
/** */
struct aice_port_api_s *api;
};
/** */
const struct aice_port *aice_port_get_list(void);
#endif

View File

@@ -0,0 +1,385 @@
/***************************************************************************
* Copyright (C) 2013 by Andes Technology *
* Hsiangkai Wang <hkwang@andestech.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
/* project specific includes */
#include <jtag/interface.h>
#include <jtag/tcl.h>
#include <transport/transport.h>
#include <target/target.h>
#include <jtag/aice/aice_interface.h>
#include <jtag/aice/aice_transport.h>
/* */
static int jim_newtap_expected_id(Jim_Nvp *n, Jim_GetOptInfo *goi,
struct jtag_tap *pTap)
{
jim_wide w;
int e = Jim_GetOpt_Wide(goi, &w);
if (e != JIM_OK) {
Jim_SetResultFormatted(goi->interp, "option: %s bad parameter",
n->name);
return e;
}
unsigned expected_len = sizeof(uint32_t) * pTap->expected_ids_cnt;
uint32_t *new_expected_ids = malloc(expected_len + sizeof(uint32_t));
if (new_expected_ids == NULL) {
Jim_SetResultFormatted(goi->interp, "no memory");
return JIM_ERR;
}
memcpy(new_expected_ids, pTap->expected_ids, expected_len);
new_expected_ids[pTap->expected_ids_cnt] = w;
free(pTap->expected_ids);
pTap->expected_ids = new_expected_ids;
pTap->expected_ids_cnt++;
return JIM_OK;
}
#define NTAP_OPT_EXPECTED_ID 0
/* */
static int jim_aice_newtap_cmd(Jim_GetOptInfo *goi)
{
struct jtag_tap *pTap;
int x;
int e;
Jim_Nvp *n;
char *cp;
const Jim_Nvp opts[] = {
{.name = "-expected-id", .value = NTAP_OPT_EXPECTED_ID},
{.name = NULL, .value = -1},
};
pTap = calloc(1, sizeof(struct jtag_tap));
if (!pTap) {
Jim_SetResultFormatted(goi->interp, "no memory");
return JIM_ERR;
}
/*
* we expect CHIP + TAP + OPTIONS
* */
if (goi->argc < 3) {
Jim_SetResultFormatted(goi->interp,
"Missing CHIP TAP OPTIONS ....");
free(pTap);
return JIM_ERR;
}
Jim_GetOpt_String(goi, &cp, NULL);
pTap->chip = strdup(cp);
Jim_GetOpt_String(goi, &cp, NULL);
pTap->tapname = strdup(cp);
/* name + dot + name + null */
x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1;
cp = malloc(x);
sprintf(cp, "%s.%s", pTap->chip, pTap->tapname);
pTap->dotted_name = cp;
LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc);
while (goi->argc) {
e = Jim_GetOpt_Nvp(goi, opts, &n);
if (e != JIM_OK) {
Jim_GetOpt_NvpUnknown(goi, opts, 0);
free((void *)pTap->dotted_name);
free(pTap);
return e;
}
LOG_DEBUG("Processing option: %s", n->name);
switch (n->value) {
case NTAP_OPT_EXPECTED_ID:
e = jim_newtap_expected_id(n, goi, pTap);
if (JIM_OK != e) {
free((void *)pTap->dotted_name);
free(pTap);
return e;
}
break;
} /* switch (n->value) */
} /* while (goi->argc) */
/* default is enabled-after-reset */
pTap->enabled = !pTap->disabled_after_reset;
jtag_tap_init(pTap);
return JIM_OK;
}
/* */
static int jim_aice_newtap(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
{
Jim_GetOptInfo goi;
Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
return jim_aice_newtap_cmd(&goi);
}
/* */
COMMAND_HANDLER(handle_aice_init_command)
{
if (CMD_ARGC != 0)
return ERROR_COMMAND_SYNTAX_ERROR;
static bool jtag_initialized;
if (jtag_initialized) {
LOG_INFO("'jtag init' has already been called");
return ERROR_OK;
}
jtag_initialized = true;
LOG_DEBUG("Initializing jtag devices...");
return jtag_init(CMD_CTX);
}
static int jim_aice_arp_init(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
{
LOG_DEBUG("No implement: jim_aice_arp_init");
return JIM_OK;
}
/* */
static int aice_init_reset(struct command_context *cmd_ctx)
{
LOG_DEBUG("Initializing with hard TRST+SRST reset");
int retval;
enum reset_types jtag_reset_config = jtag_get_reset_config();
jtag_add_reset(1, 0); /* TAP_RESET */
if (jtag_reset_config & RESET_HAS_SRST) {
jtag_add_reset(1, 1);
if ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)
jtag_add_reset(0, 1);
}
jtag_add_reset(0, 0);
retval = jtag_execute_queue();
if (retval != ERROR_OK)
return retval;
return ERROR_OK;
}
/* */
static int jim_aice_arp_init_reset(Jim_Interp *interp, int argc, Jim_Obj * const *argv)
{
int e = ERROR_OK;
Jim_GetOptInfo goi;
Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
if (goi.argc != 0) {
Jim_WrongNumArgs(goi.interp, 1, goi.argv - 1, "(no params)");
return JIM_ERR;
}
struct command_context *context = current_command_context(interp);
e = aice_init_reset(context);
if (e != ERROR_OK) {
Jim_Obj *eObj = Jim_NewIntObj(goi.interp, e);
Jim_SetResultFormatted(goi.interp, "error: %#s", eObj);
Jim_FreeNewObj(goi.interp, eObj);
return JIM_ERR;
}
return JIM_OK;
}
static int jim_aice_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_GetOptInfo goi;
Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
if (goi.argc != 0) {
Jim_WrongNumArgs(goi.interp, 1, goi.argv, "Too many parameters");
return JIM_ERR;
}
Jim_SetResult(goi.interp, Jim_NewListObj(goi.interp, NULL, 0));
struct jtag_tap *tap;
for (tap = jtag_all_taps(); tap; tap = tap->next_tap)
Jim_ListAppendElement(goi.interp,
Jim_GetResult(goi.interp),
Jim_NewStringObj(goi.interp,
tap->dotted_name, -1));
return JIM_OK;
}
/* */
static const struct command_registration
aice_transport_jtag_subcommand_handlers[] = {
{
.name = "init",
.mode = COMMAND_ANY,
.handler = handle_aice_init_command,
.help = "initialize jtag scan chain",
.usage = ""
},
{
.name = "arp_init",
.mode = COMMAND_ANY,
.jim_handler = jim_aice_arp_init,
.help = "Validates JTAG scan chain against the list of "
"declared TAPs.",
},
{
.name = "arp_init-reset",
.mode = COMMAND_ANY,
.jim_handler = jim_aice_arp_init_reset,
.help = "Uses TRST and SRST to try resetting everything on "
"the JTAG scan chain, then performs 'jtag arp_init'."
},
{
.name = "newtap",
.mode = COMMAND_CONFIG,
.jim_handler = jim_aice_newtap,
.help = "Create a new TAP instance named basename.tap_type, "
"and appends it to the scan chain.",
.usage = "basename tap_type ['-expected_id' number]"
},
{
.name = "tapisenabled",
.mode = COMMAND_EXEC,
.jim_handler = jim_jtag_tap_enabler,
.help = "Returns a Tcl boolean (0/1) indicating whether "
"the TAP is enabled (1) or not (0).",
.usage = "tap_name",
},
{
.name = "tapenable",
.mode = COMMAND_EXEC,
.jim_handler = jim_jtag_tap_enabler,
.help = "Try to enable the specified TAP using the "
"'tap-enable' TAP event.",
.usage = "tap_name",
},
{
.name = "tapdisable",
.mode = COMMAND_EXEC,
.jim_handler = jim_jtag_tap_enabler,
.help = "Try to disable the specified TAP using the "
"'tap-disable' TAP event.",
.usage = "tap_name",
},
{
.name = "configure",
.mode = COMMAND_EXEC,
.jim_handler = jim_jtag_configure,
.help = "Provide a Tcl handler for the specified "
"TAP event.",
.usage = "tap_name '-event' event_name handler",
},
{
.name = "cget",
.mode = COMMAND_EXEC,
.jim_handler = jim_jtag_configure,
.help = "Return any Tcl handler for the specified "
"TAP event.",
.usage = "tap_name '-event' event_name",
},
{
.name = "names",
.mode = COMMAND_ANY,
.jim_handler = jim_aice_names,
.help = "Returns list of all JTAG tap names.",
},
COMMAND_REGISTRATION_DONE
};
/* */
static const struct command_registration aice_transport_command_handlers[] = {
{
.name = "jtag",
.mode = COMMAND_ANY,
.usage = "",
.chain = aice_transport_jtag_subcommand_handlers,
},
COMMAND_REGISTRATION_DONE
};
/* */
static int aice_transport_register_commands(struct command_context *cmd_ctx)
{
return register_commands(cmd_ctx, NULL,
aice_transport_command_handlers);
}
/* */
static int aice_transport_init(struct command_context *cmd_ctx)
{
LOG_DEBUG("aice_transport_init");
struct target *t = get_current_target(cmd_ctx);
struct transport *transport;
if (!t) {
LOG_ERROR("no current target");
return ERROR_FAIL;
}
transport = get_current_transport();
if (!transport) {
LOG_ERROR("no transport selected");
return ERROR_FAIL;
}
LOG_DEBUG("current transport %s", transport->name);
return aice_init_target(t);
}
/* */
static int aice_transport_select(struct command_context *ctx)
{
LOG_DEBUG("aice_transport_select");
int retval;
retval = aice_transport_register_commands(ctx);
if (retval != ERROR_OK)
return retval;
return ERROR_OK;
}
static struct transport aice_jtag_transport = {
.name = "aice_jtag",
.select = aice_transport_select,
.init = aice_transport_init,
};
const char *aice_transports[] = { "aice_jtag", NULL };
static void aice_constructor(void) __attribute__((constructor));
static void aice_constructor(void)
{
transport_register(&aice_jtag_transport);
}

View File

@@ -0,0 +1,26 @@
/***************************************************************************
* Copyright (C) 2013 by Andes Technology *
* Hsiangkai Wang <hkwang@andestech.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
#ifndef _AICE_TRANSPORT_
#define _AICE_TRANSPORT_
extern const char *aice_transports[];
#endif

3505
src/jtag/aice/aice_usb.c Normal file

File diff suppressed because it is too large Load Diff

140
src/jtag/aice/aice_usb.h Normal file
View File

@@ -0,0 +1,140 @@
/***************************************************************************
* Copyright (C) 2013 by Andes Technology *
* Hsiangkai Wang <hkwang@andestech.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *
***************************************************************************/
#ifndef __AICE_USB_H__
#define __AICE_USB_H__
#include "aice_port.h"
/* AICE USB timeout value */
#define AICE_USB_TIMEOUT 5000
/* AICE USB buffer size */
#define AICE_IN_BUFFER_SIZE 2048
#define AICE_OUT_BUFFER_SIZE 2048
#define AICE_IN_PACKETS_BUFFER_SIZE 2048
#define AICE_OUT_PACKETS_BUFFER_SIZE 2048
/* Constants for AICE command */
#define AICE_CMD_SCAN_CHAIN 0x00
#define AICE_CMD_SELECT_TARGET 0x01
#define AICE_CMD_READ_DIM 0x02
#define AICE_CMD_READ_EDMSR 0x03
#define AICE_CMD_READ_DTR 0x04
#define AICE_CMD_READ_MEM 0x05
#define AICE_CMD_READ_MISC 0x06
#define AICE_CMD_FASTREAD_MEM 0x07
#define AICE_CMD_WRITE_DIM 0x08
#define AICE_CMD_WRITE_EDMSR 0x09
#define AICE_CMD_WRITE_DTR 0x0A
#define AICE_CMD_WRITE_MEM 0x0B
#define AICE_CMD_WRITE_MISC 0x0C
#define AICE_CMD_FASTWRITE_MEM 0x0D
#define AICE_CMD_EXECUTE 0x0E
#define AICE_CMD_READ_MEM_B 0x14
#define AICE_CMD_READ_MEM_H 0x15
#define AICE_CMD_T_READ_MISC 0x20
#define AICE_CMD_T_READ_EDMSR 0x21
#define AICE_CMD_T_READ_DTR 0x22
#define AICE_CMD_T_READ_DIM 0x23
#define AICE_CMD_T_READ_MEM_B 0x24
#define AICE_CMD_T_READ_MEM_H 0x25
#define AICE_CMD_T_READ_MEM 0x26
#define AICE_CMD_T_FASTREAD_MEM 0x27
#define AICE_CMD_T_WRITE_MISC 0x28
#define AICE_CMD_T_WRITE_EDMSR 0x29
#define AICE_CMD_T_WRITE_DTR 0x2A
#define AICE_CMD_T_WRITE_DIM 0x2B
#define AICE_CMD_T_WRITE_MEM_B 0x2C
#define AICE_CMD_T_WRITE_MEM_H 0x2D
#define AICE_CMD_T_WRITE_MEM 0x2E
#define AICE_CMD_T_FASTWRITE_MEM 0x2F
#define AICE_CMD_T_GET_TRACE_STATUS 0x36
#define AICE_CMD_T_EXECUTE 0x3E
#define AICE_CMD_AICE_PROGRAM_READ 0x40
#define AICE_CMD_AICE_PROGRAM_WRITE 0x41
#define AICE_CMD_AICE_PROGRAM_CONTROL 0x42
#define AICE_CMD_READ_CTRL 0x50
#define AICE_CMD_WRITE_CTRL 0x51
#define AICE_CMD_BATCH_BUFFER_READ 0x60
#define AICE_CMD_READ_DTR_TO_BUFFER 0x61
#define AICE_CMD_BATCH_BUFFER_WRITE 0x68
#define AICE_CMD_WRITE_DTR_FROM_BUFFER 0x69
/* Constants for AICE command format length */
#define AICE_FORMAT_HTDA 3
#define AICE_FORMAT_HTDB 6
#define AICE_FORMAT_HTDC 7
#define AICE_FORMAT_HTDD 10
#define AICE_FORMAT_HTDMA 4
#define AICE_FORMAT_HTDMB 8
#define AICE_FORMAT_HTDMC 8
#define AICE_FORMAT_HTDMD 12
#define AICE_FORMAT_DTHA 6
#define AICE_FORMAT_DTHB 2
#define AICE_FORMAT_DTHMA 8
#define AICE_FORMAT_DTHMB 4
/* Constants for AICE command READ_CTRL */
#define AICE_READ_CTRL_GET_ICE_STATE 0x00
#define AICE_READ_CTRL_GET_HARDWARE_VERSION 0x01
#define AICE_READ_CTRL_GET_FPGA_VERSION 0x02
#define AICE_READ_CTRL_GET_FIRMWARE_VERSION 0x03
#define AICE_READ_CTRL_GET_JTAG_PIN_STATUS 0x04
/* Constants for AICE command WRITE_CTRL */
#define AICE_WRITE_CTRL_TCK_CONTROL 0x00
#define AICE_WRITE_CTRL_JTAG_PIN_CONTROL 0x01
#define AICE_WRITE_CTRL_CLEAR_TIMEOUT_STATUS 0x02
#define AICE_WRITE_CTRL_RESERVED 0x03
#define AICE_WRITE_CTRL_JTAG_PIN_STATUS 0x04
#define AICE_WRITE_CTRL_CUSTOM_DELAY 0x0d
/* Constants for AICE command WRITE_CTRL:TCK_CONTROL */
#define AICE_TCK_CONTROL_TCK3048 0x08
/* Constants for AICE command WRITE_CTRL:JTAG_PIN_CONTROL */
#define AICE_JTAG_PIN_CONTROL_SRST 0x01
#define AICE_JTAG_PIN_CONTROL_TRST 0x02
#define AICE_JTAG_PIN_CONTROL_STOP 0x04
#define AICE_JTAG_PIN_CONTROL_RESTART 0x08
/* Constants for AICE command WRITE_CTRL:TCK_CONTROL */
#define AICE_TCK_CONTROL_TCK_SCAN 0x10
/* Custom SRST/DBGI/TRST */
#define AICE_CUSTOM_DELAY_SET_SRST 0x01
#define AICE_CUSTOM_DELAY_CLEAN_SRST 0x02
#define AICE_CUSTOM_DELAY_SET_DBGI 0x04
#define AICE_CUSTOM_DELAY_CLEAN_DBGI 0x08
#define AICE_CUSTOM_DELAY_SET_TRST 0x10
#define AICE_CUSTOM_DELAY_CLEAN_TRST 0x20
struct aice_usb_handler_s {
unsigned int usb_read_ep;
unsigned int usb_write_ep;
struct jtag_libusb_device_handle *usb_handle;
};
extern struct aice_port_api_s aice_usb_api;
int aice_read_ctrl(uint32_t address, uint32_t *data);
int aice_write_ctrl(uint32_t address, uint32_t data);
#endif