Files
bs_explorer/modules/script/script.c
François d579c56de6 fpga: don't warn on BSDLs that share an IDCODE in autoinit
Several BSDL files can legitimately match one IDCODE (same die in
different packages, or twins like SmartFusion2 / IGLOO2). The autoinit
loader loaded every match onto the device, silently overwriting the
first, and flagged it as "ID conflit ?". Keep the first match and skip
later files with the same IDCODE instead.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 10:46:58 +02:00

3444 lines
98 KiB
C

/*
* JTAG Core library
* Copyright (c) 2008 - 2024 Viveris Technologies
*
* JTAG Core library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* JTAG Core library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with JTAG Core library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file script.c
* @brief Script engine.
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#define MAX_PATH 256
#include "script.h"
#include "jtag_core/jtag_core.h"
#include "config/version.h"
#include "bsdl_parser/bsdl_loader.h"
#include "os_interface/os_interface.h"
#include "fpga/fpga.h"
#include "bscan_spi/bscan_spi.h"
#include "spi_flash/spi_flash.h"
#include "env.h"
static int dummy_script_printf(script_ctx *ctx, enum MSGTYPE typ, char *string, ...)
{
return 0;
}
static int is_end_line(char c)
{
if (c == 0 || c == '#' || c == '\r' || c == '\n')
{
return 1;
}
else
{
return 0;
}
}
static int is_space(char c)
{
if (c == ' ' || c == '\t')
{
return 1;
}
else
{
return 0;
}
}
static int is_label(char *command)
{
int i;
i = 0;
while (command[i])
{
i++;
}
if (i > 1)
{
if (command[i - 1] == ':')
return 1;
}
return 0;
}
static int is_variable(char *command)
{
if (strlen(command) > 1)
{
if (command[0] == '$' && command[1] && (command[1] != ' ' || command[1] != '\t'))
return 1;
else
return 0;
}
return 0;
}
static int get_next_word(char *line, int offset)
{
while (!is_end_line(line[offset]) && (line[offset] == ' ' || line[offset] == '\t'))
{
offset++;
}
return offset;
}
static int copy_param(char *dest, char *line, int offs)
{
int i, insidequote;
i = 0;
insidequote = 0;
while (!is_end_line(line[offs]) && (insidequote || !is_space(line[offs])) && (i < (DEFAULT_BUFLEN - 1)))
{
if (line[offs] != '"')
{
if (dest)
dest[i] = line[offs];
i++;
}
else
{
if (insidequote)
insidequote = 0;
else
insidequote = 1;
}
offs++;
}
if (dest)
dest[i] = 0;
return offs;
}
static int get_param_offset(char *line, int param)
{
int param_cnt, offs;
offs = 0;
offs = get_next_word(line, offs);
if (param)
{
param_cnt = 0;
do
{
offs = copy_param(NULL, line, offs);
offs = get_next_word(line, offs);
if (line[offs] == 0 || line[offs] == '#' || line[offs] == '\r' || line[offs] == '\n')
return -1;
param_cnt++;
} while (param_cnt < param);
}
return offs;
}
static int get_param(script_ctx *ctx, char *line, int param_offset, char *param)
{
int offs;
char var_str[DEFAULT_BUFLEN];
offs = get_param_offset(line, param_offset);
if (offs >= 0)
{
if (line[offs] != '$')
{
offs = copy_param(param, line, offs);
}
else
{
copy_param(var_str, line, offs);
if (!strcmp(var_str, "$LASTDATA"))
{
sprintf(param, "0x" LONGHEXSTR, ctx->last_data_value);
return 1;
}
if (!strcmp(var_str, "$LASTFLAGS"))
{
sprintf(param, "0x%X", ctx->last_flags);
return 1;
}
if (!strcmp(var_str, "$LASTERROR"))
{
sprintf(param, "%d", ctx->last_error_code);
return 1;
}
if (!getEnvVarDat((envvar_entry *)ctx->env, (char *)&var_str[1], param, DEFAULT_BUFLEN))
{
copy_param(param, line, offs);
}
}
return 1;
}
return -1;
}
static int get_param_str(script_ctx *ctx, char *line, int param_offset, char *param)
{
int offs;
offs = get_param_offset(line, param_offset);
if (offs >= 0)
{
offs = copy_param(param, line, offs);
return 1;
}
return -1;
}
env_var_value strbin_to_val(char *str)
{
int l;
env_var_value val;
env_var_value mask;
val = 0;
// -> end of the string
l = 0;
while (str[l])
{
l++;
}
// -> find the lowest bit
while (l)
{
if (str[l] == '1' || str[l] == '0')
{
break;
}
l--;
};
mask = 0x1;
// convert
while (l >= 0)
{
if (str[l] != '1' && str[l] != '0')
{
break;
}
if (str[l] == '1')
{
val |= mask;
}
mask <<= 1;
l--;
}
return val;
}
static env_var_value str_to_int(char *str)
{
env_var_value value;
value = 0;
if (str)
{
if (strlen(str) > 2)
{
if (str[0] == '0')
{
switch (str[1])
{
// hex
case 'x':
case 'X':
value = (env_var_value)STRTOVALUE(str, NULL, 0);
break;
// binary
case 'b':
case 'B':
value = strbin_to_val(str);
break;
// decimal
default:
value = atoi(str);
break;
}
}
else
{
value = atoi(str);
}
}
else
{
value = atoi(str);
}
}
return value;
}
static env_var_value get_script_variable(script_ctx *ctx, char *varname)
{
env_var_value value;
if (!strcmp(varname, "$LASTDATA"))
{
return ctx->last_data_value;
}
if (!strcmp(varname, "$LASTFLAGS"))
{
return ctx->last_flags;
}
if (!strcmp(varname, "$LASTERROR"))
{
return (env_var_value)(ctx->last_error_code);
}
if (varname[0] == '$')
value = getEnvVarValue((envvar_entry *)ctx->env, (char *)&varname[1]);
else
value = str_to_int((char *)varname);
return value;
}
static void set_script_variable(script_ctx *ctx, char *varname, env_var_value value)
{
char tmp_str[64];
if (!strcmp(varname, "$LASTDATA"))
{
ctx->last_data_value = value;
return;
}
if (!strcmp(varname, "$LASTFLAGS"))
{
ctx->last_flags = value;
return;
}
if (!strcmp(varname, "$LASTERROR"))
{
ctx->last_error_code = value;
return;
}
if (varname[0] == '$' && varname[1])
{
sprintf(tmp_str, "0x" LONGHEXSTR, value);
setEnvVarDat((envvar_entry *)ctx->env, (char *)&varname[1], tmp_str);
return;
}
}
script_ctx *init_script(void *app_ctx, unsigned int flags, void *env)
{
script_ctx *ctx;
ctx = malloc(sizeof(script_ctx));
if (ctx)
{
memset(ctx, 0, sizeof(script_ctx));
ctx->env = env;
setOutputFunc_script(ctx, dummy_script_printf);
ctx->app_ctx = (void *)app_ctx;
ctx->cur_label_index = 0;
ctx->cmdlist = (void *)script_commands_list;
ctx->script_file = NULL;
}
return ctx;
}
static int extract_cmd(script_ctx *ctx, char *line, char *command)
{
int offs, i;
i = 0;
offs = 0;
offs = get_next_word(line, offs);
if (!is_end_line(line[offs]))
{
while (!is_end_line(line[offs]) && !is_space(line[offs]) && i < (DEFAULT_BUFLEN - 1))
{
command[i] = line[offs];
offs++;
i++;
}
command[i] = 0;
return i;
}
return 0;
}
static int exec_cmd(script_ctx *ctx, char *command, char *line)
{
int i;
cmd_list *cmdlist;
cmdlist = (cmd_list *)ctx->cmdlist;
i = 0;
while (cmdlist[i].func)
{
if (!strcmp(cmdlist[i].command, command))
{
return cmdlist[i].func(ctx, line);
}
i++;
}
return JTAG_CORE_CMD_NOT_FOUND;
}
static int add_label(script_ctx *ctx, char *label)
{
int i, j;
char tmp_label[MAX_LABEL_SIZE];
if (ctx->cur_label_index < MAX_LABEL)
{
i = 0;
while (i < (MAX_LABEL_SIZE - 1) && label[i] && label[i] != ':')
{
tmp_label[i] = label[i];
i++;
}
tmp_label[i] = 0;
i = 0;
while (i < ctx->cur_label_index)
{
if (!strcmp(tmp_label, ctx->labels[i].label_name))
{
break;
}
i++;
}
j = i;
i = 0;
while (i < (MAX_LABEL_SIZE - 1) && label[i])
{
ctx->labels[j].label_name[i] = tmp_label[i];
i++;
}
ctx->labels[j].label_name[i] = 0;
ctx->labels[j].offset = ctx->cur_script_offset;
if (ctx->cur_label_index == j)
{
ctx->cur_label_index++;
}
}
return 0;
}
static int goto_label(script_ctx *ctx, char *label)
{
int i;
char tmp_label[MAX_LABEL_SIZE];
i = 0;
while (i < (MAX_LABEL_SIZE - 1) && label[i] && label[i] != ':')
{
tmp_label[i] = label[i];
i++;
}
tmp_label[i] = 0;
i = 0;
while (i < ctx->cur_label_index)
{
if (!strcmp(tmp_label, ctx->labels[i].label_name))
{
break;
}
i++;
}
if (i != ctx->cur_label_index)
{
ctx->cur_script_offset = ctx->labels[i].offset;
if (ctx->script_file)
fseek(ctx->script_file, ctx->cur_script_offset, SEEK_SET);
return JTAG_CORE_NO_ERROR;
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Label %s not found\n", tmp_label);
return JTAG_CORE_NOT_FOUND;
}
}
///////////////////////////////////////////////////////////////////////////////
static int alu_operations(script_ctx *ctx, char *line)
{
int i;
int valid;
env_var_value data_value;
env_var_value value_1, value_2;
char params_str[5][DEFAULT_BUFLEN];
for (i = 0; i < 5; i++)
{
params_str[i][0] = 0;
}
valid = 0;
for (i = 0; i < 5; i++)
{
get_param_str(ctx, line, i, (char *)&params_str[i]);
if (strlen((char *)&params_str[i]))
valid++;
}
data_value = 0;
if (((valid == 3) || (valid == 5)) && params_str[1][0] == '=' && params_str[0][0] == '$')
{
value_1 = get_script_variable(ctx, params_str[2]);
if (valid == 5)
{
value_2 = get_script_variable(ctx, params_str[4]);
if (!strcmp(params_str[3], "+"))
data_value = value_1 + value_2;
if (!strcmp(params_str[3], "-"))
data_value = value_1 - value_2;
if (!strcmp(params_str[3], "*"))
data_value = value_1 * value_2;
if (!strcmp(params_str[3], "/") && value_2)
data_value = value_1 / value_2;
if (!strcmp(params_str[3], "&"))
data_value = value_1 & value_2;
if (!strcmp(params_str[3], "^"))
data_value = value_1 ^ value_2;
if (!strcmp(params_str[3], "|"))
data_value = value_1 | value_2;
if (!strcmp(params_str[3], ">>"))
data_value = value_1 >> value_2;
if (!strcmp(params_str[3], "<<"))
data_value = value_1 << value_2;
}
else
{
data_value = value_1;
}
if (data_value)
ctx->last_flags = 1;
else
ctx->last_flags = 0;
set_script_variable(ctx, (char *)&params_str[0], data_value);
return JTAG_CORE_NO_ERROR;
}
return JTAG_CORE_BAD_PARAMETER;
}
void setOutputFunc_script(script_ctx *ctx, SCRIPT_PRINTF_FUNC ext_printf)
{
ctx->script_printf = ext_printf;
return;
}
int execute_line_script(script_ctx *ctx, char *line)
{
char command[DEFAULT_BUFLEN];
command[0] = 0;
if (extract_cmd(ctx, line, command))
{
if (strlen(command))
{
if (!is_label(command))
{
if (!ctx->dry_run)
{
if (!is_variable(command))
{
ctx->last_error_code = exec_cmd(ctx, command, line);
if (ctx->last_error_code == JTAG_CORE_CMD_NOT_FOUND)
{
ctx->script_printf(ctx, MSG_ERROR, "Command not found ! : %s\n", line);
return ctx->last_error_code;
}
}
else
{
ctx->last_error_code = alu_operations(ctx, line);
}
}
else
ctx->last_error_code = JTAG_CORE_NO_ERROR;
}
else
{
add_label(ctx, command);
ctx->last_error_code = JTAG_CORE_NO_ERROR;
}
return ctx->last_error_code;
}
}
ctx->last_error_code = JTAG_CORE_BAD_CMD;
return ctx->last_error_code;
}
int execute_file_script(script_ctx *ctx, char *filename)
{
int err;
char line[DEFAULT_BUFLEN];
err = JTAG_CORE_INTERNAL_ERROR;
ctx->script_file = fopen(filename, "r");
if (ctx->script_file)
{
strncpy(ctx->script_file_path, filename, DEFAULT_BUFLEN - 1);
ctx->script_file_path[DEFAULT_BUFLEN - 1] = 0;
// Dry run -> populate the labels...
ctx->dry_run++;
do
{
if (!fgets(line, sizeof(line), ctx->script_file))
break;
ctx->cur_script_offset = ftell(ctx->script_file);
if (feof(ctx->script_file))
break;
execute_line_script(ctx, line);
} while (1);
fseek(ctx->script_file, 0, SEEK_SET);
ctx->cur_script_offset = ftell(ctx->script_file);
ctx->dry_run--;
if (!ctx->dry_run)
{
if (strlen(ctx->pre_command))
{
err = execute_line_script(ctx, ctx->pre_command);
if (err != JTAG_CORE_NO_ERROR)
{
fclose(ctx->script_file);
return err;
}
}
do
{
if (!fgets(line, sizeof(line), ctx->script_file))
break;
ctx->cur_script_offset = ftell(ctx->script_file);
if (feof(ctx->script_file))
break;
err = execute_line_script(ctx, line);
} while (1);
}
fclose(ctx->script_file);
err = JTAG_CORE_NO_ERROR;
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Can't open %s !", filename);
ctx->script_file_path[0] = 0;
err = JTAG_CORE_ACCESS_ERROR;
}
return err;
}
int execute_ram_script(script_ctx *ctx, unsigned char *script_buffer, int buffersize)
{
int err = 0;
int buffer_offset, line_offset;
char line[DEFAULT_BUFLEN];
int cont;
ctx->dry_run++;
cont = 1;
while (cont)
{
buffer_offset = 0;
line_offset = 0;
ctx->cur_script_offset = 0;
do
{
memset(line, 0, DEFAULT_BUFLEN);
line_offset = 0;
while ((buffer_offset < buffersize) && script_buffer[buffer_offset] && script_buffer[buffer_offset] != '\n' && script_buffer[buffer_offset] != '\r' && (line_offset < DEFAULT_BUFLEN - 1))
{
line[line_offset++] = script_buffer[buffer_offset++];
}
while ((buffer_offset < buffersize) && script_buffer[buffer_offset] && (script_buffer[buffer_offset] == '\n' || script_buffer[buffer_offset] == '\r'))
{
buffer_offset++;
}
ctx->cur_script_offset = buffer_offset;
execute_line_script(ctx, line);
buffer_offset = ctx->cur_script_offset;
if ((buffer_offset >= buffersize) || !script_buffer[buffer_offset])
break;
} while (buffer_offset < buffersize);
if (!ctx->dry_run || (ctx->dry_run > 1))
{
cont = 0;
}
else
{
ctx->dry_run = 0;
if (strlen(ctx->pre_command))
execute_line_script(ctx, ctx->pre_command);
}
}
return err;
}
script_ctx *deinit_script(script_ctx *ctx)
{
if (ctx)
{
free(ctx);
}
ctx = NULL;
return ctx;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////// Generic commands/operations /////////////////////////////
///////////////////////////////////////////////////////////////////////////////
const char *cmd_goto_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_goto(script_ctx *ctx, char *line)
{
int i;
char label_str[DEFAULT_BUFLEN];
i = get_param(ctx, line, 1, label_str);
if (i >= 0)
{
return goto_label(ctx, label_str);
}
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_if_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_if(script_ctx *ctx, char *line)
{
//"if" command example :
// if $VARIABLE > 0x2222 then goto label
int i;
int eval;
int ret;
int valid;
char params_str[5][DEFAULT_BUFLEN];
env_var_value value_1, value_2, tmp_val;
int op_offset;
ret = JTAG_CORE_BAD_PARAMETER;
eval = 0;
for (i = 0; i < 5; i++)
{
params_str[i][0] = 0;
}
valid = 0;
for (i = 0; i < 5; i++)
{
get_param(ctx, line, i, (char *)&params_str[i]);
if (strlen((char *)&params_str[i]))
valid++;
}
i = 0;
while (i < 5 && strcmp((char *)&params_str[i], "then"))
{
i++;
}
if (i < 5)
{
if (i == 2)
{
value_1 = get_script_variable(ctx, params_str[1]);
if (value_1)
eval = 1;
ret = JTAG_CORE_NO_ERROR;
}
if (i == 4)
{
value_1 = get_script_variable(ctx, params_str[1]);
value_2 = get_script_variable(ctx, params_str[3]);
if (!strcmp((char *)&params_str[2], ">=") && ((signed_env_var_value)value_1 >= (signed_env_var_value)value_2))
eval = 1;
if (!strcmp((char *)&params_str[2], "<=") && ((signed_env_var_value)value_1 <= (signed_env_var_value)value_2))
eval = 1;
if (!strcmp((char *)&params_str[2], ">") && ((signed_env_var_value)value_1 > (signed_env_var_value)value_2))
eval = 1;
if (!strcmp((char *)&params_str[2], "<") && ((signed_env_var_value)value_1 < (signed_env_var_value)value_2))
eval = 1;
if (!strcmp((char *)&params_str[2], "==") && (value_1 == value_2))
eval = 1;
if (!strcmp((char *)&params_str[2], "!=") && (value_1 != value_2))
eval = 1;
if (!strcmp((char *)&params_str[2], "&") && (value_1 & value_2))
eval = 1;
if (!strcmp((char *)&params_str[2], "^") && (value_1 ^ value_2))
eval = 1;
if (!strcmp((char *)&params_str[2], "|") && (value_1 | value_2))
eval = 1;
tmp_val = value_1 >> value_2;
if (!strcmp((char *)&params_str[2], ">>") && tmp_val)
eval = 1;
tmp_val = value_1 << value_2;
if (!strcmp((char *)&params_str[2], "<<") && tmp_val)
eval = 1;
ret = JTAG_CORE_NO_ERROR;
}
if (eval)
{
op_offset = get_param_offset(line, i + 1);
if (op_offset >= 0)
{
ret = execute_line_script(ctx, (char *)&line[op_offset]);
}
}
return ret;
}
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_return_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_return(script_ctx *ctx, char *line)
{
if (ctx->script_file)
{
fseek(ctx->script_file, 0, SEEK_END);
}
return JTAG_CORE_NO_ERROR;
}
const char *cmd_system_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_system(script_ctx *ctx, char *line)
{
int offs;
int ret;
offs = get_param_offset(line, 1);
if (offs >= 0)
{
ret = system(&line[offs]);
if (ret != 1)
return JTAG_CORE_NO_ERROR;
else
return JTAG_CORE_NOT_FOUND;
}
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_print_env_var_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_print_env_var(script_ctx *ctx, char *line)
{
int i;
char varname[DEFAULT_BUFLEN];
char varvalue[DEFAULT_BUFLEN];
char *ptr;
i = get_param(ctx, line, 1, varname);
if (i >= 0)
{
ptr = getEnvVarDat((envvar_entry *)ctx->env, (char *)&varname, (char *)&varvalue, sizeof(varvalue));
if (ptr)
{
ctx->script_printf(ctx, MSG_INFO_1, "%s = %s", varname, varvalue);
return JTAG_CORE_NO_ERROR;
}
return JTAG_CORE_NOT_FOUND;
}
else
{
return JTAG_CORE_BAD_PARAMETER;
}
}
const char *cmd_version_help[] = {
"<none>",
"prints the version of the tool.",
""};
static int cmd_version(script_ctx *ctx, char *line)
{
ctx->script_printf(ctx, MSG_INFO_0, "%s, Date : "__DATE__
" "__TIME__
"\n",
APP_VER_STR_LONG(APP_VER));
return JTAG_CORE_NO_ERROR;
}
const char *cmd_print_help[] = {
"<arg>(string)",
"sends <arg> to standard output.",
""};
static int cmd_print(script_ctx *ctx, char *line)
{
int i, j, s;
char tmp_str[DEFAULT_BUFLEN];
char str[DEFAULT_BUFLEN * 2];
char *ptr;
str[0] = '\0';
j = 1;
do
{
ptr = NULL;
i = get_param_offset(line, j);
s = 0;
if (i >= 0)
{
tmp_str[0] = '\0';
get_param(ctx, line, j, (char *)&tmp_str);
s = strlen(tmp_str);
if (s)
{
if (tmp_str[0] != '$')
{
genos_strndstcat((char *)str, tmp_str, sizeof(str));
genos_strndstcat((char *)str, " ", sizeof(str));
str[sizeof(str) - 1] = '\0';
}
else
{
ptr = getEnvVarDat((envvar_entry *)ctx->env, &tmp_str[1], NULL, 0);
if (ptr)
{
genos_strndstcat((char *)str, ptr, sizeof(str));
genos_strndstcat((char *)str, " ", sizeof(str));
}
else
{
genos_strndstcat((char *)str, tmp_str, sizeof(str));
genos_strndstcat((char *)str, " ", sizeof(str));
}
str[sizeof(str) - 1] = '\0';
}
}
}
j++;
} while (s);
ctx->script_printf(ctx, MSG_NONE, "%s\n", str);
return JTAG_CORE_NO_ERROR;
}
const char *cmd_pause_help[] = {
"<arg>(int)",
"pauses the program for <arg> ms.",
""};
static int cmd_pause(script_ctx *ctx, char *line)
{
int i;
char delay_str[DEFAULT_BUFLEN];
i = get_param(ctx, line, 1, delay_str);
if (i >= 0)
{
genos_pause(str_to_int(delay_str));
return JTAG_CORE_NO_ERROR;
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_help_help[] = {
"<command>(string)",
"if no args, it prints the list of commands,",
"otherwise the help of the <command>.",
""};
static int cmd_help(script_ctx *ctx, char *line)
{
int i;
int j;
int not_found = 1;
char hcmd[DEFAULT_BUFLEN];
cmd_list *cmdlist;
cmdlist = (cmd_list *)ctx->cmdlist;
i = get_param(ctx, line, 1, hcmd);
if (i >= 0)
{
i = 0;
while (cmdlist[i].func)
{
if (0 == strcmp(hcmd, cmdlist[i].command))
{
not_found = 0;
ctx->script_printf(ctx, MSG_NONE, "Documentation of command '%s' :\n", cmdlist[i].command);
ctx->script_printf(ctx, MSG_NONE, "---------------------------------------------------\n");
j = 0;
while (strcmp(cmdlist[i].help[j], "")) {
if (j == 0) {
ctx->script_printf(ctx, MSG_NONE, "Parameters :\n");
ctx->script_printf(ctx, MSG_NONE, " %s\n", cmdlist[i].help[j]);
} else {
if (j == 1) {
ctx->script_printf(ctx, MSG_NONE, "Description :\n");
}
ctx->script_printf(ctx, MSG_NONE, " %s\n", cmdlist[i].help[j]);
}
j++;
}
break;
}
i++;
}
if (not_found)
{
ctx->script_printf(ctx, MSG_ERROR, "Command '%s' not found :\n\n", hcmd);
}
}
else
{
ctx->script_printf(ctx, MSG_INFO_0, "Supported Commands :\n\n");
i = 0;
while (cmdlist[i].func)
{
ctx->script_printf(ctx, MSG_NONE, "%s\n", cmdlist[i].command);
i++;
}
}
return JTAG_CORE_NO_ERROR;
}
const char *cmd_call_help[] = {
"<path>(string)",
"Executes a script located at <path>.",
""
};
static int cmd_call(script_ctx *ctx, char *line)
{
int offs;
char path[DEFAULT_BUFLEN];
char function[DEFAULT_BUFLEN];
script_ctx *new_ctx;
int ret;
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
path[0] = '\0';
get_param(ctx, line, 1, (char *)&path);
offs = get_param_offset(line, 1);
if (offs >= 0)
{
ret = JTAG_CORE_INTERNAL_ERROR;
new_ctx = init_script((void *)jc, 0x00000000, (void *)jc->envvar);
if (new_ctx)
{
new_ctx->script_printf = ctx->script_printf;
function[0] = '\0';
get_param(ctx, line, 2, (char *)&function);
if (!strcmp(path, "."))
{
if (strlen(function))
{
snprintf(new_ctx->pre_command, sizeof(new_ctx->pre_command), "goto %s", function);
ret = execute_file_script(new_ctx, (char *)&ctx->script_file_path);
new_ctx->pre_command[0] = 0;
if (ret == JTAG_CORE_ACCESS_ERROR)
{
ctx->script_printf(ctx, MSG_ERROR, "call : script not found ! : %s\n", path);
}
}
}
else
{
if (strlen(function))
{
snprintf(new_ctx->pre_command, sizeof(new_ctx->pre_command), "goto %s", function);
ret = execute_file_script(new_ctx, (char *)&path);
new_ctx->pre_command[0] = 0;
if (ret == JTAG_CORE_ACCESS_ERROR)
{
ctx->script_printf(ctx, MSG_ERROR, "call : script/function not found ! : %s %s\n", path, function);
}
}
else
{
ret = execute_file_script(new_ctx, (char *)&path);
if (ret == JTAG_CORE_ACCESS_ERROR)
{
ctx->script_printf(ctx, MSG_ERROR, "call : script not found ! : %s\n", path);
}
}
}
deinit_script(new_ctx);
}
ctx->last_error_code = ret;
return ret;
}
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_set_env_var_help[] = {
"<varname>(string) <varvalue>(string)",
"Stores <varvalue> in the environmen variable <varname>.",
""};
static int cmd_set_env_var(script_ctx *ctx, char *line)
{
int i, j, ret;
char varname[DEFAULT_BUFLEN];
char varvalue[DEFAULT_BUFLEN];
ret = JTAG_CORE_BAD_PARAMETER;
i = get_param(ctx, line, 1, varname);
j = get_param(ctx, line, 2, varvalue);
if (i >= 0 && j >= 0)
{
if (setEnvVarDat((envvar_entry *)ctx->env, (char *)&varname, (char *)&varvalue) >= 0)
{
ret = JTAG_CORE_NO_ERROR;
}
else
ret = JTAG_CORE_MEM_ERROR;
}
return ret;
}
const char *cmd_rand_help[] = {
"<seed>(int)",
"Generates a random integer. Uses the <seed> value if present.",
""};
static int cmd_rand(script_ctx *ctx, char *line)
{
int i;
uint32_t seed;
char rand_seed[DEFAULT_BUFLEN];
seed = ctx->rand_seed;
i = get_param(ctx, line, 1, rand_seed);
if (i >= 0)
{
seed = str_to_int((char *)rand_seed);
}
/* Algorithm "xor" from p. 4 of Marsaglia, "Xorshift RNGs" */
seed ^= seed << 13;
seed ^= seed >> 17;
seed ^= seed << 5;
ctx->rand_seed = seed;
ctx->last_data_value = seed;
return JTAG_CORE_NO_ERROR;
}
int is_valid_hex_quartet(char c)
{
if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))
return 1;
else
return 0;
}
int is_valid_hex_byte(char *str)
{
if (is_valid_hex_quartet(str[0]) && is_valid_hex_quartet(str[1]))
return 1;
else
return 0;
}
char *arrayresize(char *array, int size, unsigned char c)
{
int cursize;
char *ptr;
if (size < 0)
return array;
if (array)
{
if (array[0] == '0' && (array[1] == 'x' || array[1] == 'X'))
{
ptr = (array + 2);
}
else
{
ptr = (array);
}
}
else
{
array = malloc(DEFAULT_BUFLEN + 1);
if (array)
{
size = DEFAULT_BUFLEN / 2;
memset(array, 0, DEFAULT_BUFLEN + 1);
}
ptr = array;
}
if (ptr)
{
cursize = 0;
while (is_valid_hex_byte(&ptr[cursize * 2]))
{
cursize++;
}
ptr[cursize * 2] = '\0';
if (cursize < size)
{
while (cursize < size)
{
sprintf(&ptr[(cursize * 2) + 0], "%.2X", c);
ptr[(cursize * 2) + 2] = '\0';
cursize++;
}
}
}
return array;
}
const char *cmd_initarray_help[] = {
"<varname>(string) <varsize>(int) <value>(int)",
"Initializes an array of size <varsize> with <value>. Stores it in the environment.",
""};
static int cmd_initarray(script_ctx *ctx, char *line)
{
// initarray $VARIABLE_1_TEST $BYTES $VALUE
int i, j, ret;
char varname[DEFAULT_BUFLEN];
char varsize[DEFAULT_BUFLEN];
char varvalue[DEFAULT_BUFLEN];
char *ptr;
int size;
ret = JTAG_CORE_BAD_PARAMETER;
strcpy(varvalue, "0");
varname[0] = '\0';
i = get_param_str(ctx, line, 1, varname);
j = get_param(ctx, line, 2, varsize);
get_param(ctx, line, 3, varvalue);
if (i >= 0 && j >= 0)
{
size = str_to_int(varsize);
if (size >= 0 && strlen(varname))
{
ptr = getEnvVarDat((envvar_entry *)ctx->env, (char *)&varname, NULL, 0);
if (ptr)
{
arrayresize(ptr, size, (unsigned char)(str_to_int((char *)&varvalue) & 0xFF));
}
else
{
ptr = malloc(DEFAULT_BUFLEN);
if (ptr)
{
memset(ptr, 0x00, DEFAULT_BUFLEN);
arrayresize(ptr, size, (unsigned char)(str_to_int((char *)&varvalue) & 0xFF));
}
}
if (ptr)
setEnvVarDat((envvar_entry *)ctx->env, (char *)&varname[1], ptr);
}
ret = JTAG_CORE_NO_ERROR;
}
return ret;
}
///////////////////////////////////////////////////////////////////////////////
/////////////////////// JTAG commands/operations //////////////////////////////
///////////////////////////////////////////////////////////////////////////////
const char *cmd_autoinit_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_autoinit(script_ctx *ctx, char *line)
{
jtag_core *jc;
int number_of_devices, dev_nb;
int loaded_bsdl;
char szExecPath[MAX_PATH + 1];
char scanfolder[MAX_PATH + 1];
char filename[MAX_PATH + 1];
char entityname[DEFAULT_BUFLEN];
char file[MAX_PATH + 1];
filefoundinfo fileinfo;
void *h_file_find;
unsigned long chip_id, chip_id_mask;
jc = (jtag_core *)ctx->app_ctx;
loaded_bsdl = 0;
// BSDL Auto load : check which bsdl file match with the device
// And load it.
jtagcore_scan_and_init_chain(jc);
number_of_devices = jtagcore_get_number_of_devices(jc);
ctx->script_printf(ctx, MSG_INFO_0, "%d device(s) found\n", number_of_devices);
// Get the bsdl_files folder path
genos_getcurrentdirectory(szExecPath, MAX_PATH);
strncpy(scanfolder, szExecPath, sizeof(scanfolder));
genos_strndstcat(scanfolder, DIR_SEPARATOR "bsdl_files" DIR_SEPARATOR, sizeof(scanfolder) - 1);
scanfolder[sizeof(scanfolder) - 1] = '\0';
h_file_find = genos_find_first_file(scanfolder, "*.*", &fileinfo);
// Scan and check files in the folder.
if (h_file_find)
{
do
{
strcpy(filename, szExecPath);
genos_strndstcat(filename, DIR_SEPARATOR "bsdl_files" DIR_SEPARATOR, sizeof(filename));
genos_strndstcat(filename, fileinfo.filename, sizeof(filename));
filename[sizeof(filename) - 1] = '\0';
if (!fileinfo.isdirectory)
{
chip_id_mask = 0xFFFFFFFF;
ctx->script_printf(ctx, MSG_INFO_0, "[identify] reading IDCODE from %s :\n", fileinfo.filename);
chip_id = jtagcore_get_bsdl_id(jc, filename, &chip_id_mask);
if (chip_id)
{
for (dev_nb = 0; dev_nb < number_of_devices; dev_nb++)
{
if ((chip_id & chip_id_mask) == (jtagcore_get_dev_id(jc, dev_nb) & chip_id_mask))
{
if (jtagcore_get_number_of_pins(jc, dev_nb) > 0)
{
// A BSDL is already attached to this device.
// Several files can legitimately share one
// IDCODE (same die in different packages, or
// twins like SmartFusion2 / IGLOO2). Keep the
// first match and just note the others, rather
// than overwriting it and crying "conflict".
ctx->script_printf(ctx, MSG_INFO_0,
"[skip] %s also matches device %d's IDCODE; keeping the BSDL already loaded\n",
fileinfo.filename, dev_nb);
continue;
}
// The BSDL ID match with the device.
ctx->script_printf(ctx, MSG_INFO_0, "[load] IDCODE 0x%.8lX matches device %d, attaching %s :\n", chip_id, dev_nb, fileinfo.filename);
if (jtagcore_loadbsdlfile(jc, filename, dev_nb) == JTAG_CORE_NO_ERROR)
{
entityname[0] = 0;
jtagcore_get_dev_name(jc, dev_nb, entityname, file);
ctx->script_printf(ctx, MSG_INFO_0, "Device %d (%.8X - %s) - BSDL Loaded : %s\n", dev_nb, chip_id, entityname, file);
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "ERROR while loading %s !\n", filename);
}
}
}
}
}
} while (genos_find_next_file(h_file_find, scanfolder, "*.*", &fileinfo));
genos_find_close(h_file_find);
loaded_bsdl = 0;
// Count the loaded bsdl
for (dev_nb = 0; dev_nb < number_of_devices; dev_nb++)
{
if (jtagcore_get_number_of_pins(jc, dev_nb) > 0)
{
loaded_bsdl++;
}
else
{
ctx->script_printf(ctx, MSG_WARNING, "Device %d (%.8X) - NO BSDL Loaded !\n", dev_nb, jtagcore_get_dev_id(jc, dev_nb));
}
}
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Can't access the bsdl sub folder ! : %s\n", scanfolder);
return JTAG_CORE_ACCESS_ERROR;
}
// Expose the count to scripts via last_data_value, but report success
// (a non-zero return is treated as an error code by the engine).
ctx->last_data_value = loaded_bsdl;
return JTAG_CORE_NO_ERROR;
}
const char *cmd_init_and_scan_help[] = {
"",
"Scan the JTAG chain and report the devices found with their IDCODEs.",
"Unlike jtag_autoinit, it does not load any BSDL.",
""
};
static int cmd_init_and_scan(script_ctx *ctx, char *line)
{
jtag_core *jc;
int ret, n, i;
jc = (jtag_core *)ctx->app_ctx;
ret = jtagcore_scan_and_init_chain(jc);
if (ret != JTAG_CORE_NO_ERROR)
{
ctx->script_printf(ctx, MSG_ERROR, "JTAG scan failed (code %d)\n", ret);
return ret;
}
n = jtagcore_get_number_of_devices(jc);
ctx->script_printf(ctx, MSG_INFO_0, "%d device(s) found\n", n);
for (i = 0; i < n; i++)
{
ctx->script_printf(ctx, MSG_INFO_0, " Device %d : IDCODE 0x%.8lX\n",
i, jtagcore_get_dev_id(jc, i));
}
ctx->last_data_value = n;
return JTAG_CORE_NO_ERROR;
}
const char *cmd_print_nb_dev_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_print_nb_dev(script_ctx *ctx, char *line)
{
jtag_core *jc;
int i;
jc = (jtag_core *)ctx->app_ctx;
i = jtagcore_get_number_of_devices(jc);
ctx->script_printf(ctx, MSG_INFO_0, "%d device(s) found in chain\n", i);
ctx->last_data_value = i;
return JTAG_CORE_NO_ERROR;
}
const char *cmd_bsdl_id_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static void bsdl_id_str(unsigned long id, char *str)
{
int i;
str[0] = 0;
for (i = 0; i < 32; i++)
{
if ((0x80000000 >> i) & id)
{
strcat(str, "1");
}
else
{
strcat(str, "0");
}
if (i == 3)
strcat(str, " ");
if (i == 19)
strcat(str, " ");
if (i == 30)
strcat(str, " ");
}
str[i] = 0;
}
static char *get_id_str(script_ctx *ctx, int numberofdevice)
{
// compare passed device ID to the one returned from the ID command
jtag_core *jc;
int i;
unsigned int idcode = 0;
char *stringbuffer;
char tempstr[DEFAULT_BUFLEN];
jc = (jtag_core *)ctx->app_ctx;
stringbuffer = NULL;
if (numberofdevice < 0 || numberofdevice > 256)
return NULL;
stringbuffer = malloc(256 * numberofdevice);
if (stringbuffer)
{
memset(stringbuffer, 0, 256 * numberofdevice);
// and read the IDCODES
for (i = 0; i < numberofdevice; i++)
{
idcode = jtagcore_get_dev_id(jc, i);
sprintf(tempstr, "Device %d : 0x%.8X - ", i, idcode);
bsdl_id_str(idcode, &tempstr[strlen(tempstr)]);
strcat(stringbuffer, tempstr);
strcat(stringbuffer, "\n");
}
}
return stringbuffer;
}
const char *cmd_print_devs_list_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_print_devs_list(script_ctx *ctx, char *line)
{
jtag_core *jc;
int i;
char *ptr;
jc = (jtag_core *)ctx->app_ctx;
i = jtagcore_get_number_of_devices(jc);
if (i > 0)
{
ptr = get_id_str(ctx, i);
if (ptr)
{
ctx->script_printf(ctx, MSG_INFO_0, "%s\n", ptr);
free(ptr);
}
return JTAG_CORE_NO_ERROR;
}
return JTAG_CORE_NOT_FOUND;
}
const char *cmd_print_probes_list_help[] = {
"<none>", // Arguments "1<arg>(type) ..."
"Displays the list of detected probes.", // Explanations
""
};
/* Map the flat index shown by jtag_probes (0, 1, 2, ...) to the
* encoded (drv << 8 | probe) id, walking drivers/probes in the same order
* the list prints them. Returns -1 if the index is out of range. */
static int resolve_flat_probe_index(jtag_core *jc, int flat)
{
int nb_of_drivers = jtagcore_get_number_of_probes_drv(jc);
int j, i, n = 0;
for (j = 0; j < nb_of_drivers; j++)
{
int nb_of_probes = jtagcore_get_number_of_probes(jc, j);
for (i = 0; i < nb_of_probes; i++)
{
if (n == flat)
return PROBE_ID(j, i);
n++;
}
}
return -1;
}
static int cmd_print_probes_list(script_ctx *ctx, char *line)
{
jtag_core *jc;
int i, j, flat;
char probe_list[64];
int nb_of_drivers, nb_of_probes;
jc = (jtag_core *)ctx->app_ctx;
nb_of_drivers = jtagcore_get_number_of_probes_drv(jc);
flat = 0;
j = 0;
while (j < nb_of_drivers)
{
nb_of_probes = jtagcore_get_number_of_probes(jc, j);
i = 0;
while (i < nb_of_probes)
{
jtagcore_get_probe_name(jc, PROBE_ID(j, i), probe_list);
// [flat index] is what to pass to jtag_open; the
// 0x id after it is the raw form, also accepted.
ctx->script_printf(ctx, MSG_INFO_0, " [%d] 0x%.8X %s\n", flat, PROBE_ID(j, i), probe_list);
flat++;
i++;
}
j++;
}
return JTAG_CORE_NO_ERROR;
}
const char *cmd_open_probe_help[] = {
"<probe>(int)", // Arguments "1<arg>(type) ..."
"Open a probe by its index from jtag_probes (0, 1, 2, ...).",
"A raw 0x-prefixed probe id (as printed after the index) also works.",
""
};
static int cmd_open_probe(script_ctx *ctx, char *line)
{
int ret;
int id;
char probe_id[64];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
if (get_param(ctx, line, 1, probe_id) > 0)
{
if (probe_id[0] == '0' && (probe_id[1] == 'x' || probe_id[1] == 'X'))
{
// Raw encoded id (drv << 8 | probe).
id = (int)strtoul(probe_id, NULL, 16);
}
else
{
// Sequential index from jtag_probes.
id = resolve_flat_probe_index(jc, (int)strtoul(probe_id, NULL, 10));
if (id < 0)
{
ctx->script_printf(ctx, MSG_ERROR,
"No probe at index %s. Run jtag_probes first.\n", probe_id);
return JTAG_CORE_BAD_PARAMETER;
}
}
ret = jtagcore_select_and_open_probe(jc, id);
if (ret != JTAG_CORE_NO_ERROR)
{
ctx->script_printf(ctx, MSG_ERROR, "Code %d !\n", ret);
return ret;
}
else
{
ctx->script_printf(ctx, MSG_INFO_0, "Probe Ok !\n");
return JTAG_CORE_NO_ERROR;
}
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
}
const char *cmd_load_bsdl_help[] = {
"<file>(string) <device>(int)",
"Load/attach a bsdl file to a device into the chain.",
""
};
static int cmd_load_bsdl(script_ctx *ctx, char *line)
{
int i, j;
char dev_index[DEFAULT_BUFLEN];
char filename[DEFAULT_BUFLEN];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, filename);
j = get_param(ctx, line, 2, dev_index);
if (i >= 0 && j >= 0)
{
if (jtagcore_loadbsdlfile(jc, filename, str_to_int(dev_index)) >= 0)
{
ctx->script_printf(ctx, MSG_INFO_0, "BSDL %s loaded and parsed !\n", filename);
return JTAG_CORE_NO_ERROR;
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "File open & parsing error (%s)!\n", filename);
return JTAG_CORE_ACCESS_ERROR;
}
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_set_scan_mode_help[] = {
"<device>(int) <mode>(string)",
"Set the scan mode for a particular device.",
"mode to be chosen in EXTEST or SAMPLE",
""
};
static int cmd_set_scan_mode(script_ctx *ctx, char *line)
{
int i, j;
char dev_index[DEFAULT_BUFLEN];
char scan_mode[DEFAULT_BUFLEN];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, dev_index);
j = get_param(ctx, line, 2, scan_mode);
if (i >= 0 && j >= 0)
{
if (!strcmp(scan_mode, "EXTEST"))
{
jtagcore_set_scan_mode(jc, str_to_int(dev_index), JTAG_CORE_EXTEST_SCANMODE);
ctx->script_printf(ctx, MSG_INFO_0, "EXTEST mode\n");
}
else
{
if (!strcmp(scan_mode, "SAMPLE"))
{
jtagcore_set_scan_mode(jc, str_to_int(dev_index), JTAG_CORE_SAMPLE_SCANMODE);
ctx->script_printf(ctx, MSG_INFO_0, "SAMPLE mode\n");
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "%s : unknown mode !\n", scan_mode);
return JTAG_CORE_BAD_PARAMETER;
}
}
return JTAG_CORE_NO_ERROR;
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_push_and_pop_help[] = {
"<none>",
"Do a JTAG chain transaction.",
""
};
static int cmd_push_and_pop(script_ctx *ctx, char *line)
{
int ret;
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
ret = jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ);
if (ret != JTAG_CORE_NO_ERROR)
{
ctx->script_printf(ctx, MSG_ERROR, "Code %d !\n", ret);
return ret;
}
else
{
ctx->script_printf(ctx, MSG_INFO_0, "JTAG chain updated\n");
}
return JTAG_CORE_NO_ERROR;
}
const char *cmd_set_pin_mode_help[] = {
"<device>(int) <pin>(string) <mode>(int)",
"Change the mode (input: 0 or output: 1) of the pin of the given device.",
""
};
static int cmd_set_pin_mode(script_ctx *ctx, char *line)
{
int i, j, k, id;
char dev_index[DEFAULT_BUFLEN];
char pinname[DEFAULT_BUFLEN];
char mode[DEFAULT_BUFLEN];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, dev_index);
j = get_param(ctx, line, 2, pinname);
k = get_param(ctx, line, 3, mode);
if (i >= 0 && j >= 0 && k >= 0)
{
id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname);
if (id >= 0)
{
jtagcore_set_pin_state(jc, str_to_int(dev_index), id, JTAG_CORE_OE, str_to_int(mode));
ctx->script_printf(ctx, MSG_INFO_0, "Pin %s mode set to %d\n", pinname, str_to_int(mode));
return JTAG_CORE_NO_ERROR;
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Pin %s not found\n", pinname);
return JTAG_CORE_NOT_FOUND;
}
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_set_pin_state_help[] = {
"<device>(int) <pin>(string) <state>(string)",
"Change the state (0 or 1) of the pin of the given device.",
""
};
static int cmd_set_pin_state(script_ctx *ctx, char *line)
{
int i, j, k, id;
char dev_index[DEFAULT_BUFLEN];
char pinname[DEFAULT_BUFLEN];
char state[DEFAULT_BUFLEN];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, dev_index);
j = get_param(ctx, line, 2, pinname);
k = get_param(ctx, line, 3, state);
if (i >= 0 && j >= 0 && k >= 0)
{
id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname);
if (id >= 0)
{
jtagcore_set_pin_state(jc, str_to_int(dev_index), id, JTAG_CORE_OUTPUT, str_to_int(state));
ctx->script_printf(ctx, MSG_INFO_0, "Pin %s set to %d\n", pinname, str_to_int(state));
return JTAG_CORE_NO_ERROR;
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Pin %s not found\n", pinname);
return JTAG_CORE_NOT_FOUND;
}
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_get_pin_state_help[] = {
"<device>(int) <pin>(string)",
"Gets the state (0 or 1) of the pin of the given device.",
"The mode is to be chosen between 'input' or 'output'.",
""
};
static int cmd_get_pin_state(script_ctx *ctx, char *line)
{
int i, j, k, ret, id;
char dev_index[DEFAULT_BUFLEN];
char pinname[DEFAULT_BUFLEN];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, dev_index);
j = get_param(ctx, line, 2, pinname);
if (i >= 0 && j >= 0 && k >= 0)
{
id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname);
if (id >= 0)
{
ret = jtagcore_get_pin_state(jc, str_to_int(dev_index), id, JTAG_CORE_INPUT);
ctx->script_printf(ctx, MSG_INFO_0, "Pin %s state : %d\n", pinname, ret);
ctx->last_data_value = ret;
return JTAG_CORE_NO_ERROR;
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Pin %s not found\n", pinname);
return JTAG_CORE_NOT_FOUND;
}
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
/////////////////////////////////////////////////////////////////////////////////////////
// I2C Commands
/////////////////////////////////////////////////////////////////////////////////////////
const char *cmd_set_i2c_sda_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_set_i2c_sda_pin(script_ctx *ctx, char *line)
{
int i, j, id;
char dev_index[DEFAULT_BUFLEN];
char pinname[DEFAULT_BUFLEN];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, dev_index);
j = get_param(ctx, line, 2, pinname);
if (i >= 0 && j >= 0)
{
id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname);
if (id >= 0)
{
jtagcore_i2c_set_sda_pin(jc, str_to_int(dev_index), id);
ctx->script_printf(ctx, MSG_INFO_0, "SDA set to Pin %s\n", pinname);
return JTAG_CORE_NO_ERROR;
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Pin %s not found\n", pinname);
return JTAG_CORE_NOT_FOUND;
}
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_set_i2c_scl_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_set_i2c_scl_pin(script_ctx *ctx, char *line)
{
int i, j, id;
char dev_index[DEFAULT_BUFLEN];
char pinname[DEFAULT_BUFLEN];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, dev_index);
j = get_param(ctx, line, 2, pinname);
if (i >= 0 && j >= 0)
{
id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname);
if (id >= 0)
{
jtagcore_i2c_set_scl_pin(jc, str_to_int(dev_index), id);
ctx->script_printf(ctx, MSG_INFO_0, "SCL set to Pin %s\n", pinname);
return JTAG_CORE_NO_ERROR;
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Pin %s not found\n", pinname);
return JTAG_CORE_NOT_FOUND;
}
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_do_i2c_wr_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_do_i2c_wr(script_ctx *ctx, char *line)
{
// jtag_set_do_i2c_wr E8 EAACCDD4455
int i, j;
int i2cadr, size, ret;
char adresse[DEFAULT_BUFLEN];
char data[DEFAULT_BUFLEN];
unsigned char tmp_buffer2[DEFAULT_BUFLEN];
char tmp_buffer3[16];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, adresse);
j = get_param(ctx, line, 2, data);
if (i >= 0 && j >= 0)
{
i2cadr = strtoul(adresse, 0, 16);
size = strlen(data);
size = size / 2;
for (i = 0; i < size; i++)
{
tmp_buffer3[0] = data[i * 2];
tmp_buffer3[1] = data[i * 2 + 1];
tmp_buffer3[2] = 0;
tmp_buffer2[i] = (char)strtoul(tmp_buffer3, 0, 16);
}
ret = jtagcore_i2c_write_read(jc, i2cadr, 0, size, tmp_buffer2, 0, 0);
if (ret <= 0)
{
if (ret == 0)
{
ctx->script_printf(ctx, MSG_WARNING, "Device Ack not detected ! 0x%.2X\n", i2cadr);
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Code %d !\n", ret);
}
return ret;
}
else
{
for (i = 0; i < size; i++)
{
sprintf(&data[i * 3], " %.2X", tmp_buffer2[i]);
}
ctx->script_printf(ctx, MSG_INFO_0, "WR I2C 0x%.2X :%s\n", i2cadr, data);
return JTAG_CORE_NO_ERROR;
}
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_do_i2c_rd_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_do_i2c_rd(script_ctx *ctx, char *line)
{
// jtag_set_do_i2c_rd 0xE8 8
int i, j, i2cadr, size;
char adresse[DEFAULT_BUFLEN];
char sizebuf[DEFAULT_BUFLEN];
char tmp_buffer[DEFAULT_BUFLEN];
char tmp_buffer2[DEFAULT_BUFLEN];
char tmp_buffer3[16];
int ret;
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, adresse);
j = get_param(ctx, line, 2, sizebuf);
if (i >= 0 && j >= 0)
{
i2cadr = strtoul(adresse, 0, 16);
size = str_to_int(sizebuf);
ret = jtagcore_i2c_write_read(jc, i2cadr, 0, 0, (unsigned char *)tmp_buffer2, size, (unsigned char *)tmp_buffer2);
if (ret <= 0)
{
if (ret == 0)
{
ctx->script_printf(ctx, MSG_WARNING, "Device Ack not detected ! 0x%.2X\n", i2cadr);
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Code %d !\n", ret);
}
return ret;
}
else
{
memset(tmp_buffer, 0, sizeof(tmp_buffer));
for (i = 0; i < size && i < sizeof(tmp_buffer2); i++)
{
sprintf(tmp_buffer3, " %.2X", tmp_buffer2[i]);
strcat(tmp_buffer, tmp_buffer3);
}
ctx->script_printf(ctx, MSG_INFO_0, "RD I2C 0x%.2X :%s\n", i2cadr, tmp_buffer);
return JTAG_CORE_NO_ERROR;
}
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
/////////////////////////////////////////////////////////////////////////////////////////
// MDIO Commands
/////////////////////////////////////////////////////////////////////////////////////////
const char *cmd_set_mdio_mdc_pin_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_set_mdio_mdc_pin(script_ctx *ctx, char *line)
{
int i, j, id;
char dev_index[DEFAULT_BUFLEN];
char pinname[DEFAULT_BUFLEN];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, dev_index);
j = get_param(ctx, line, 2, pinname);
if (i >= 0 && j >= 0)
{
id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname);
if (id >= 0)
{
jtagcore_mdio_set_mdc_pin(jc, str_to_int(dev_index), id);
ctx->script_printf(ctx, MSG_INFO_0, "MDC set to Pin %s\n", pinname);
return JTAG_CORE_NO_ERROR;
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Pin %s not found\n", pinname);
return JTAG_CORE_NOT_FOUND;
}
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_set_mdio_mdio_pin_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_set_mdio_mdio_pin(script_ctx *ctx, char *line)
{
int i, j, id;
char dev_index[DEFAULT_BUFLEN];
char pinname[DEFAULT_BUFLEN];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, dev_index);
j = get_param(ctx, line, 2, pinname);
if (i >= 0 && j >= 0)
{
id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname);
if (id >= 0)
{
jtagcore_mdio_set_mdio_pin(jc, str_to_int(dev_index), id);
ctx->script_printf(ctx, MSG_INFO_0, "MDIO set to Pin %s\n", pinname);
return JTAG_CORE_NO_ERROR;
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Pin %s not found\n", pinname);
return JTAG_CORE_NOT_FOUND;
}
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_do_mdio_wr_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_do_mdio_wr(script_ctx *ctx, char *line)
{
// jtag_mdio_wr 01 04 EAAC
int i, j, k, mdioadr, regadr, datatowrite;
char address[DEFAULT_BUFLEN];
char reg[DEFAULT_BUFLEN];
char data[DEFAULT_BUFLEN];
int ret;
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, address);
j = get_param(ctx, line, 2, reg);
k = get_param(ctx, line, 3, data);
if (i >= 0 && j >= 0 && k >= 0)
{
mdioadr = strtoul(address, 0, 16);
regadr = strtoul(reg, 0, 16);
datatowrite = strtoul(data, 0, 16);
ret = jtagcore_mdio_write(jc, mdioadr, regadr, datatowrite);
if (ret < 0)
{
ctx->script_printf(ctx, MSG_ERROR, "Code %d !\n", ret);
return ret;
}
ctx->script_printf(ctx, MSG_INFO_0, "WR MDIO 0x%.2X : [0x%.2X] = 0x%.4X\n", mdioadr, regadr, datatowrite);
return JTAG_CORE_NO_ERROR;
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_do_mdio_rd_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_do_mdio_rd(script_ctx *ctx, char *line)
{
// jtag_mdio_rd 01 04
int i, j, mdioadr, regadr, dataread;
char address[DEFAULT_BUFLEN];
char reg[DEFAULT_BUFLEN];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, address);
j = get_param(ctx, line, 2, reg);
if (i >= 0 && j >= 0)
{
mdioadr = strtoul(address, 0, 16);
regadr = strtoul(reg, 0, 16);
dataread = jtagcore_mdio_read(jc, mdioadr, regadr);
if (dataread < 0)
{
ctx->script_printf(ctx, MSG_ERROR, "Code %d !\n", dataread);
return dataread;
}
ctx->last_data_value = dataread;
ctx->script_printf(ctx, MSG_INFO_0, "RD MDIO 0x%.2X : [0x%.2X] = 0x%.4X\n", mdioadr, regadr, dataread);
return JTAG_CORE_NO_ERROR;
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
/////////////////////////////////////////////////////////////////////////////////////////
// SPI Commands
/////////////////////////////////////////////////////////////////////////////////////////
const char *cmd_set_spi_cs_pin_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_set_spi_cs_pin(script_ctx *ctx, char *line)
{
int i, j, k, id;
char dev_index[DEFAULT_BUFLEN];
char pinname[DEFAULT_BUFLEN];
char polarity[DEFAULT_BUFLEN];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, dev_index);
j = get_param(ctx, line, 2, pinname);
k = get_param(ctx, line, 3, polarity);
if (i >= 0 && j >= 0 && k >= 0)
{
id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname);
if (id >= 0)
{
jtagcore_spi_set_cs_pin(jc, str_to_int(dev_index), id, str_to_int(polarity));
ctx->script_printf(ctx, MSG_INFO_0, "CS set to Pin %s with polarity %d\n", pinname, str_to_int(polarity));
return JTAG_CORE_NO_ERROR;
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Pin %s not found\n", pinname);
return JTAG_CORE_NOT_FOUND;
}
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_set_spi_clk_pin_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_set_spi_clk_pin(script_ctx *ctx, char *line)
{
int i, j, k, id;
char dev_index[DEFAULT_BUFLEN];
char pinname[DEFAULT_BUFLEN];
char polarity[DEFAULT_BUFLEN];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, dev_index);
j = get_param(ctx, line, 2, pinname);
k = get_param(ctx, line, 3, polarity);
if (i >= 0 && j >= 0 && k >= 0)
{
id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname);
if (id >= 0)
{
jtagcore_spi_set_clk_pin(jc, str_to_int(dev_index), id, str_to_int(polarity));
ctx->script_printf(ctx, MSG_INFO_0, "CLK set to Pin %s with polarity %d\n", pinname, str_to_int(polarity));
return JTAG_CORE_NO_ERROR;
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Pin %s not found\n", pinname);
return JTAG_CORE_NOT_FOUND;
}
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_set_spi_mosi_pin_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_set_spi_mosi_pin(script_ctx *ctx, char *line)
{
int i, j, k, id;
char dev_index[DEFAULT_BUFLEN];
char pinname[DEFAULT_BUFLEN];
char phase[DEFAULT_BUFLEN];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, dev_index);
j = get_param(ctx, line, 2, pinname);
k = get_param(ctx, line, 3, phase);
if (i >= 0 && j >= 0 && k >= 0)
{
id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname);
if (id >= 0)
{
jtagcore_spi_set_mosi_pin(jc, str_to_int(dev_index), id, str_to_int(phase));
ctx->script_printf(ctx, MSG_INFO_0, "MOSI set to Pin %s with polarity %d\n", pinname, str_to_int(phase));
return JTAG_CORE_NO_ERROR;
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Pin %s not found\n", pinname);
return JTAG_CORE_NOT_FOUND;
}
}
ctx->script_printf(ctx, MSG_ERROR, "Bad/Missing parameter(s) ! : %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_set_spi_miso_pin_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_set_spi_miso_pin(script_ctx *ctx, char *line)
{
int i, j, k, id;
char dev_index[DEFAULT_BUFLEN];
char pinname[DEFAULT_BUFLEN];
char phase[DEFAULT_BUFLEN];
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, dev_index);
j = get_param(ctx, line, 2, pinname);
k = get_param(ctx, line, 3, phase);
if (i >= 0 && j >= 0 && k >= 0)
{
id = jtagcore_get_pin_id(jc, str_to_int(dev_index), pinname);
if (id >= 0)
{
jtagcore_spi_set_miso_pin(jc, str_to_int(dev_index), id, str_to_int(phase));
ctx->script_printf(ctx, MSG_INFO_0, "MISO set to Pin %s with polarity %d\n", pinname, str_to_int(phase));
return JTAG_CORE_NO_ERROR;
}
else
{
ctx->script_printf(ctx, MSG_ERROR, "Pin %s not found\n", pinname);
return JTAG_CORE_NOT_FOUND;
}
}
ctx->script_printf(ctx, MSG_ERROR, "Parameters error: %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_spi_rd_wr_help[] = {
"", // Arguments "1<arg>(type) ..."
"explanations line one", // Explanations
"explanations line two",
""
};
static int cmd_spi_rd_wr(script_ctx *ctx, char *line)
{
int i, j, k, size;
char data_out_txt[DEFAULT_BUFLEN];
unsigned char data_out[DEFAULT_BUFLEN];
unsigned char data_in[DEFAULT_BUFLEN];
char lsbfirst[DEFAULT_BUFLEN];
char tmp_buffer[3];
int ret;
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
// jtag_spi_xfer 00123344 1 (DATA LSBFirst)
i = get_param(ctx, line, 1, data_out_txt);
j = get_param(ctx, line, 2, lsbfirst);
if (i >= 0)
{
if (j >= 0)
{
jtagcore_spi_set_bitorder(jc, str_to_int(lsbfirst));
}
size = strlen(data_out_txt);
size = size / 2;
for (k = 0; k < size; k++)
{
tmp_buffer[0] = data_out_txt[k * 2];
tmp_buffer[1] = data_out_txt[k * 2 + 1];
tmp_buffer[2] = 0;
data_out[k] = (unsigned char)strtoul(tmp_buffer, 0, 16);
}
ret = jtagcore_spi_write_read(jc, size, data_out, data_in, 0);
if (ret < 0)
{
ctx->script_printf(ctx, MSG_ERROR, "Code %d !\n", ret);
return ret;
}
ctx->script_printf(ctx, MSG_INFO_0, "SPI TX:");
for (k = 0; k < size; k++)
{
ctx->script_printf(ctx, MSG_NONE, " %.2X", data_out[k]);
}
ctx->script_printf(ctx, MSG_NONE, "\n");
ctx->script_printf(ctx, MSG_INFO_0, "SPI RX:");
for (k = 0; k < size; k++)
{
ctx->script_printf(ctx, MSG_NONE, " %.2X", data_in[k]);
}
ctx->script_printf(ctx, MSG_NONE, "\n");
return JTAG_CORE_NOT_FOUND;
}
ctx->script_printf(ctx, MSG_ERROR, "Parameters error: %s\n", line);
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_get_pins_list_help[] = {
"<device>(int)",
"Lists the device pins and their properties",
""
};
static int cmd_get_pins_list(script_ctx *ctx, char *line)
{
int i, j, nb_of_pins;
char dev_index[DEFAULT_BUFLEN];
char pinname[DEFAULT_BUFLEN];
int type;
jtag_core *jc;
jc = (jtag_core *)ctx->app_ctx;
i = get_param(ctx, line, 1, dev_index);
if (i >= 0)
{
nb_of_pins = jtagcore_get_number_of_pins(jc, str_to_int(dev_index));
if (nb_of_pins >= 0)
{
ctx->script_printf(ctx, MSG_INFO_0, "Device %d : %d pin(s)\n", str_to_int(dev_index), nb_of_pins);
for (j = 0; j < nb_of_pins; j++)
{
if (jtagcore_get_pin_properties(jc, str_to_int(dev_index), j, pinname, sizeof(pinname), &type) == JTAG_CORE_NO_ERROR)
{
ctx->script_printf(ctx, MSG_NONE, "%s : ", pinname);
if (type & JTAG_CORE_PIN_IS_INPUT)
{
ctx->script_printf(ctx, MSG_NONE, " in ");
}
else
{
ctx->script_printf(ctx, MSG_NONE, " ");
}
if (type & JTAG_CORE_PIN_IS_OUTPUT)
{
ctx->script_printf(ctx, MSG_NONE, " out ");
}
else
{
ctx->script_printf(ctx, MSG_NONE, " ");
}
if (type & JTAG_CORE_PIN_IS_TRISTATES)
{
ctx->script_printf(ctx, MSG_NONE, " tris");
}
else
{
ctx->script_printf(ctx, MSG_NONE, " ");
}
ctx->script_printf(ctx, MSG_NONE, "\n");
}
}
}
return JTAG_CORE_NO_ERROR;
}
return JTAG_CORE_BAD_PARAMETER;
}
const char *cmd_fpga_list_help[] = {
"",
"Lists the FPGA targets in the registry (loaded from fpga_registry.yaml).",
""};
static int cmd_fpga_list(script_ctx *ctx, char *line)
{
int i, n;
const fpga_target *t;
const char *src;
(void)line;
n = fpga_get_target_count();
src = fpga_registry_source();
ctx->script_printf(ctx, MSG_INFO_0, "%d FPGA target(s) registered (from %s):\n",
n, src ? src : "<no registry loaded>");
for (i = 0; i < n; i++) {
t = fpga_get_target_by_index(i);
ctx->script_printf(ctx, MSG_NONE,
" [%d] IDCODE %.8lX/%.8lX %s (%s)\n",
i, t->idcode, t->idcode_mask,
t->name, fpga_family_name(t->family));
ctx->script_printf(ctx, MSG_NONE,
" bsdl=%s ir=%d proxy=%s caveats=0x%x\n",
t->bsdl_filename, t->ir_length,
t->proxy_bitstream ? t->proxy_bitstream : "(none yet)",
t->caveats);
}
return JTAG_CORE_NO_ERROR;
}
const char *cmd_fpga_info_help[] = {
"",
"Reports, for each device on the JTAG chain, whether its IDCODE",
"matches a known FPGA target. Requires jtag_scan or jtag_autoinit first.",
""};
static int cmd_fpga_info(script_ctx *ctx, char *line)
{
jtag_core *jc;
int i, n;
unsigned long idcode;
const fpga_target *t;
(void)line;
jc = (jtag_core *)ctx->app_ctx;
n = jtagcore_get_number_of_devices(jc);
if (n <= 0) {
ctx->script_printf(ctx, MSG_WARNING, "No device on the chain. Run jtag_autoinit first.\n");
return JTAG_CORE_NOT_FOUND;
}
for (i = 0; i < n; i++) {
idcode = jtagcore_get_dev_id(jc, i);
t = fpga_lookup_by_idcode(idcode);
if (t) {
ctx->script_printf(ctx, MSG_INFO_0,
"Device %d IDCODE 0x%.8lX -> %s [%s]\n",
i, idcode, t->name, fpga_family_name(t->family));
if (t->caveats & FPGA_CAVEAT_CCLK_VIA_STARTUP) {
ctx->script_printf(ctx, MSG_NONE,
" caveat: CCLK routed via STARTUP primitive (not drivable in EXTEST)\n");
}
} else {
ctx->script_printf(ctx, MSG_INFO_0,
"Device %d IDCODE 0x%.8lX -> not in registry\n",
i, idcode);
}
}
return JTAG_CORE_NO_ERROR;
}
const char *cmd_bscan_set_ir_help[] = {
"<opcode_hex> <ir_length>",
"Shifts <opcode_hex> into the IR (single-device chain).",
"Useful for testing the low-level JTAG primitives.",
""};
static int cmd_bscan_set_ir(script_ctx *ctx, char *line)
{
char op_txt[DEFAULT_BUFLEN];
char len_txt[DEFAULT_BUFLEN];
unsigned int opcode;
int ir_length, ret;
jtag_core *jc = (jtag_core *)ctx->app_ctx;
if (get_param(ctx, line, 1, op_txt) < 0 || get_param(ctx, line, 2, len_txt) < 0) {
ctx->script_printf(ctx, MSG_ERROR, "Usage: bscan_set_ir <opcode_hex> <ir_length>\n");
return JTAG_CORE_BAD_PARAMETER;
}
opcode = (unsigned int)strtoul(op_txt, NULL, 16);
ir_length = (int)strtoul(len_txt, NULL, 0);
ret = bscan_set_ir(jc, opcode, ir_length);
if (ret < 0) {
ctx->script_printf(ctx, MSG_ERROR, "bscan_set_ir failed (%d)\n", ret);
return JTAG_CORE_IO_ERROR;
}
ctx->script_printf(ctx, MSG_INFO_0, "IR <- 0x%X (%d bits)\n", opcode, ir_length);
return JTAG_CORE_NO_ERROR;
}
const char *cmd_bscan_shift_dr_help[] = {
"<nbits>",
"Shifts <nbits> zeros into DR, prints the captured TDO in hex (LSB first).",
"Run after bscan_set_ir to read a register (e.g. IDCODE -> shift 32 bits).",
""};
static int cmd_bscan_shift_dr(script_ctx *ctx, char *line)
{
char nb_txt[DEFAULT_BUFLEN];
int nbits, nbytes, i, ret;
uint8_t *tdo;
jtag_core *jc = (jtag_core *)ctx->app_ctx;
if (get_param(ctx, line, 1, nb_txt) < 0) {
ctx->script_printf(ctx, MSG_ERROR, "Usage: bscan_shift_dr <nbits>\n");
return JTAG_CORE_BAD_PARAMETER;
}
nbits = (int)strtoul(nb_txt, NULL, 0);
if (nbits <= 0 || nbits > 8 * DEFAULT_BUFLEN) {
ctx->script_printf(ctx, MSG_ERROR, "Invalid nbits\n");
return JTAG_CORE_BAD_PARAMETER;
}
nbytes = (nbits + 7) / 8;
tdo = calloc(1, (size_t)nbytes);
if (!tdo) return JTAG_CORE_MEM_ERROR;
ret = bscan_shift_dr(jc, NULL, tdo, nbits);
if (ret < 0) {
free(tdo);
ctx->script_printf(ctx, MSG_ERROR, "bscan_shift_dr failed (%d)\n", ret);
return JTAG_CORE_IO_ERROR;
}
ctx->script_printf(ctx, MSG_INFO_0, "DR =");
for (i = nbytes - 1; i >= 0; i--) {
ctx->script_printf(ctx, MSG_NONE, " %.2X", tdo[i]);
}
ctx->script_printf(ctx, MSG_NONE, "\n");
free(tdo);
return JTAG_CORE_NO_ERROR;
}
const char *cmd_bscan_load_bitstream_help[] = {
"<device> <path>",
"Loads a bitstream (.bit or raw .bin) into device <device> via JPROGRAM/CFG_IN/JSTART.",
"Device must be matched in the FPGA registry (run fpga_info to check).",
""};
static int cmd_bscan_load_bitstream(script_ctx *ctx, char *line)
{
char dev_txt[DEFAULT_BUFLEN];
char path[DEFAULT_BUFLEN];
int device, ret;
unsigned long idcode;
const fpga_target *t;
jtag_core *jc = (jtag_core *)ctx->app_ctx;
if (get_param(ctx, line, 1, dev_txt) < 0 || get_param(ctx, line, 2, path) < 0) {
ctx->script_printf(ctx, MSG_ERROR, "Usage: bscan_load_bitstream <device> <path>\n");
return JTAG_CORE_BAD_PARAMETER;
}
device = (int)strtoul(dev_txt, NULL, 0);
if (jtagcore_get_number_of_devices(jc) <= 0) {
ctx->script_printf(ctx, MSG_ERROR, "No device on the chain. Run jtag_autoinit first.\n");
return JTAG_CORE_NOT_FOUND;
}
idcode = jtagcore_get_dev_id(jc, device);
t = fpga_lookup_by_idcode(idcode);
if (!t) {
ctx->script_printf(ctx, MSG_ERROR, "Device %d IDCODE 0x%.8lX not in FPGA registry\n", device, idcode);
return JTAG_CORE_NOT_FOUND;
}
ctx->script_printf(ctx, MSG_INFO_0, "Loading %s on device %d (%s)...\n", path, device, t->name);
ret = bscan_load_bitstream_file(jc, t, path);
if (ret < 0) {
ctx->script_printf(ctx, MSG_ERROR, "bscan_load_bitstream_file failed (%d)\n", ret);
return JTAG_CORE_IO_ERROR;
}
ctx->script_printf(ctx, MSG_INFO_0, "Bitstream loaded.\n");
return JTAG_CORE_NO_ERROR;
}
const char *cmd_bscan_jedec_help[] = {
"<device>",
"Read the SPI flash JEDEC ID (0x9F) through the loaded BSCAN proxy.",
"JEDEC ID = 1 manufacturer byte (e.g. 0x20 Micron) + 2 device bytes;",
"identifies which flash chip is wired to the FPGA.",
"Requires a proxy bitstream already loaded (bscan_load_bitstream).",
""};
static int cmd_bscan_jedec(script_ctx *ctx, char *line)
{
char dev_txt[DEFAULT_BUFLEN];
int device;
unsigned long idcode;
const fpga_target *t;
uint8_t tx = 0x9F;
uint8_t rx[3] = {0};
jtag_core *jc = (jtag_core *)ctx->app_ctx;
if (get_param(ctx, line, 1, dev_txt) < 0) {
ctx->script_printf(ctx, MSG_ERROR, "Usage: bscan_jedec <device>\n");
return JTAG_CORE_BAD_PARAMETER;
}
device = (int)strtoul(dev_txt, NULL, 0);
if (jtagcore_get_number_of_devices(jc) <= 0) {
ctx->script_printf(ctx, MSG_ERROR, "No device on the chain. Run jtag_autoinit first.\n");
return JTAG_CORE_NOT_FOUND;
}
idcode = jtagcore_get_dev_id(jc, device);
t = fpga_lookup_by_idcode(idcode);
if (!t) {
ctx->script_printf(ctx, MSG_ERROR, "Device %d IDCODE 0x%.8lX not in FPGA registry\n", device, idcode);
return JTAG_CORE_NOT_FOUND;
}
if (bscan_spi_xfer(jc, t, &tx, 1, rx, sizeof(rx)) < 0) {
ctx->script_printf(ctx, MSG_ERROR, "bscan_spi_xfer failed (proxy not loaded?)\n");
return JTAG_CORE_IO_ERROR;
}
ctx->script_printf(ctx, MSG_INFO_0,
"JEDEC ID: %.2X %.2X %.2X (manufacturer 0x%.2X, device 0x%.2X%.2X)\n",
rx[0], rx[1], rx[2], rx[0], rx[1], rx[2]);
ctx->last_data_value = (rx[0] << 16) | (rx[1] << 8) | rx[2];
return JTAG_CORE_NO_ERROR;
}
/* Adapt the BSCAN proxy to the spi_flash transport callback. */
struct flash_proxy_ctx {
jtag_core *jc;
const fpga_target *t;
};
static int flash_proxy_xfer(void *c, const uint8_t *tx, size_t txlen,
uint8_t *rx, size_t rxlen)
{
struct flash_proxy_ctx *p = (struct flash_proxy_ctx *)c;
return bscan_spi_xfer(p->jc, p->t, tx, txlen, rx, rxlen);
}
/* Look up the FPGA target for a chain device and wire a spi_flash over
* the proxy. Returns 0 and fills *sf/*pc, or prints an error and returns
* a JTAG_CORE_* code. */
static int flash_setup(script_ctx *ctx, int device,
spi_flash *sf, struct flash_proxy_ctx *pc)
{
jtag_core *jc = (jtag_core *)ctx->app_ctx;
unsigned long idcode;
const fpga_target *t;
if (jtagcore_get_number_of_devices(jc) <= 0) {
ctx->script_printf(ctx, MSG_ERROR, "No device on the chain. Run jtag_autoinit first.\n");
return JTAG_CORE_NOT_FOUND;
}
idcode = jtagcore_get_dev_id(jc, device);
t = fpga_lookup_by_idcode(idcode);
if (!t) {
ctx->script_printf(ctx, MSG_ERROR, "Device %d IDCODE 0x%.8lX not in FPGA registry\n", device, idcode);
return JTAG_CORE_NOT_FOUND;
}
pc->jc = jc;
pc->t = t;
memset(sf, 0, sizeof(*sf));
sf->xfer = flash_proxy_xfer;
sf->ctx = pc;
return JTAG_CORE_NO_ERROR;
}
const char *cmd_flash_detect_help[] = {
"<device>",
"Identify the SPI flash behind the loaded BSCAN proxy: read its JEDEC",
"ID and match the built-in chip database. Requires a proxy loaded.",
""};
static int cmd_flash_detect(script_ctx *ctx, char *line)
{
char dev_txt[DEFAULT_BUFLEN];
struct flash_proxy_ctx pc;
spi_flash sf;
int device, r;
if (get_param(ctx, line, 1, dev_txt) < 0) {
ctx->script_printf(ctx, MSG_ERROR, "Usage: flash_detect <device>\n");
return JTAG_CORE_BAD_PARAMETER;
}
device = (int)strtoul(dev_txt, NULL, 0);
if ((r = flash_setup(ctx, device, &sf, &pc)) != JTAG_CORE_NO_ERROR) return r;
r = spi_flash_detect(&sf);
if (r < 0) {
ctx->script_printf(ctx, MSG_ERROR, "spi_flash_detect failed (proxy not loaded?)\n");
return JTAG_CORE_IO_ERROR;
}
ctx->script_printf(ctx, MSG_INFO_0, "JEDEC ID: %.2X %.2X %.2X\n",
sf.jedec[0], sf.jedec[1], sf.jedec[2]);
ctx->last_data_value = (sf.jedec[0] << 16) | (sf.jedec[1] << 8) | sf.jedec[2];
if (!sf.chip) {
ctx->script_printf(ctx, MSG_WARNING, "Flash not in database — add it to spi_flash.c\n");
return JTAG_CORE_NO_ERROR;
}
ctx->script_printf(ctx, MSG_INFO_0,
"Flash: %s - %u MB, page %u B, sector %u B, %d-byte address\n",
sf.chip->name, sf.chip->size_bytes / (1024u * 1024u),
sf.chip->page_size, sf.chip->sector_size, sf.chip->addr_bytes);
return JTAG_CORE_NO_ERROR;
}
/* Set up the proxy transport and detect the flash. Returns NO_ERROR with
* sf->chip set, or an error code (with a message already printed). */
static int flash_setup_detected(script_ctx *ctx, int device,
spi_flash *sf, struct flash_proxy_ctx *pc)
{
int r = flash_setup(ctx, device, sf, pc);
if (r != JTAG_CORE_NO_ERROR) return r;
if (spi_flash_detect(sf) < 0 || !sf->chip) {
ctx->script_printf(ctx, MSG_ERROR, "Flash not detected/known - run flash_detect first.\n");
return JTAG_CORE_NOT_FOUND;
}
return JTAG_CORE_NO_ERROR;
}
/* Read a whole file into a malloc'd buffer. Caller frees. */
static uint8_t *read_file(const char *path, size_t *out_len)
{
FILE *f = fopen(path, "rb");
long sz;
uint8_t *b;
if (!f) return NULL;
if (fseek(f, 0, SEEK_END) != 0) { fclose(f); return NULL; }
sz = ftell(f);
rewind(f);
if (sz <= 0) { fclose(f); return NULL; }
b = malloc((size_t)sz);
if (!b) { fclose(f); return NULL; }
if (fread(b, 1, (size_t)sz, f) != (size_t)sz) { free(b); fclose(f); return NULL; }
fclose(f);
*out_len = (size_t)sz;
return b;
}
const char *cmd_flash_read_help[] = {
"<device> <addr> <len> [file]",
"Read <len> bytes from the SPI flash at <addr> (hex). With [file], dump",
"the raw bytes to it (e.g. to back up before erasing); otherwise hex-dump.",
"Read-only. Requires a proxy loaded and a flash known to flash_detect.",
""};
static int cmd_flash_read(script_ctx *ctx, char *line)
{
char dev_txt[DEFAULT_BUFLEN], addr_txt[DEFAULT_BUFLEN], len_txt[DEFAULT_BUFLEN], file[DEFAULT_BUFLEN];
struct flash_proxy_ctx pc;
spi_flash sf;
uint8_t *buf;
uint32_t addr;
size_t len, i;
int device, r, to_file;
if (get_param(ctx, line, 1, dev_txt) < 0 || get_param(ctx, line, 2, addr_txt) < 0 ||
get_param(ctx, line, 3, len_txt) < 0) {
ctx->script_printf(ctx, MSG_ERROR, "Usage: flash_read <device> <addr> <len> [file]\n");
return JTAG_CORE_BAD_PARAMETER;
}
to_file = (get_param(ctx, line, 4, file) > 0);
device = (int)strtoul(dev_txt, NULL, 0);
addr = (uint32_t)strtoul(addr_txt, NULL, 0);
len = (size_t)strtoul(len_txt, NULL, 0);
if (len == 0) return JTAG_CORE_NO_ERROR;
if (!to_file && len > 65536) {
ctx->script_printf(ctx, MSG_ERROR, "flash_read: len capped at 65536 for a hex dump (use a file for more)\n");
return JTAG_CORE_BAD_PARAMETER;
}
if ((r = flash_setup_detected(ctx, device, &sf, &pc)) != JTAG_CORE_NO_ERROR) return r;
buf = malloc(len);
if (!buf) return JTAG_CORE_BAD_PARAMETER;
if (spi_flash_read(&sf, addr, buf, len) < 0) {
free(buf);
ctx->script_printf(ctx, MSG_ERROR, "spi_flash_read failed\n");
return JTAG_CORE_IO_ERROR;
}
if (to_file) {
FILE *f = fopen(file, "wb");
size_t wr = 0;
if (f) { wr = fwrite(buf, 1, len, f); fclose(f); }
free(buf);
if (!f || wr != len) {
ctx->script_printf(ctx, MSG_ERROR, "Can't write %s\n", file);
return JTAG_CORE_IO_ERROR;
}
ctx->script_printf(ctx, MSG_INFO_0, "Read %lu bytes from 0x%.8X to %s\n",
(unsigned long)len, (unsigned)addr, file);
return JTAG_CORE_NO_ERROR;
}
for (i = 0; i < len; i += 16) {
char linebuf[16 * 3 + 16];
size_t j, pos = 0;
pos += (size_t)snprintf(linebuf + pos, sizeof(linebuf) - pos, "%.8X: ", (unsigned)(addr + i));
for (j = 0; j < 16 && (i + j) < len; j++) {
pos += (size_t)snprintf(linebuf + pos, sizeof(linebuf) - pos, "%.2X ", buf[i + j]);
}
ctx->script_printf(ctx, MSG_INFO_0, "%s\n", linebuf);
}
free(buf);
return JTAG_CORE_NO_ERROR;
}
const char *cmd_flash_erase_help[] = {
"<device> <addr> <len>",
"Erase the flash sectors covering [addr, addr+len) (hex). DESTRUCTIVE.",
"Requires a proxy loaded and a flash known to flash_detect.",
""};
static int cmd_flash_erase(script_ctx *ctx, char *line)
{
char dev_txt[DEFAULT_BUFLEN], addr_txt[DEFAULT_BUFLEN], len_txt[DEFAULT_BUFLEN];
struct flash_proxy_ctx pc;
spi_flash sf;
uint32_t addr, end, a, ss;
size_t len;
int device, r, nsec = 0;
if (get_param(ctx, line, 1, dev_txt) < 0 || get_param(ctx, line, 2, addr_txt) < 0 ||
get_param(ctx, line, 3, len_txt) < 0) {
ctx->script_printf(ctx, MSG_ERROR, "Usage: flash_erase <device> <addr> <len>\n");
return JTAG_CORE_BAD_PARAMETER;
}
device = (int)strtoul(dev_txt, NULL, 0);
addr = (uint32_t)strtoul(addr_txt, NULL, 0);
len = (size_t)strtoul(len_txt, NULL, 0);
if (len == 0) return JTAG_CORE_NO_ERROR;
if ((r = flash_setup_detected(ctx, device, &sf, &pc)) != JTAG_CORE_NO_ERROR) return r;
ss = sf.chip->sector_size;
end = addr + (uint32_t)len; /* exclusive */
for (a = addr - (addr % ss); a < end; a += ss) {
if (spi_flash_erase_sector(&sf, a) < 0) {
ctx->script_printf(ctx, MSG_ERROR, "Erase failed at 0x%.8X\n", a);
return JTAG_CORE_IO_ERROR;
}
nsec++;
}
ctx->script_printf(ctx, MSG_INFO_0, "Erased %d sector(s) of %u B from 0x%.8X\n",
nsec, ss, addr - (addr % ss));
return JTAG_CORE_NO_ERROR;
}
const char *cmd_flash_write_help[] = {
"<device> <addr> <file>",
"Program the flash at <addr> (hex) with the contents of <file>. DESTRUCTIVE.",
"Does NOT erase first - run flash_erase over the range beforehand.",
""};
static int cmd_flash_write(script_ctx *ctx, char *line)
{
char dev_txt[DEFAULT_BUFLEN], addr_txt[DEFAULT_BUFLEN], file[DEFAULT_BUFLEN];
struct flash_proxy_ctx pc;
spi_flash sf;
uint8_t *data;
uint32_t addr;
size_t len = 0;
int device, r;
if (get_param(ctx, line, 1, dev_txt) < 0 || get_param(ctx, line, 2, addr_txt) < 0 ||
get_param(ctx, line, 3, file) < 0) {
ctx->script_printf(ctx, MSG_ERROR, "Usage: flash_write <device> <addr> <file>\n");
return JTAG_CORE_BAD_PARAMETER;
}
device = (int)strtoul(dev_txt, NULL, 0);
addr = (uint32_t)strtoul(addr_txt, NULL, 0);
if ((r = flash_setup_detected(ctx, device, &sf, &pc)) != JTAG_CORE_NO_ERROR) return r;
data = read_file(file, &len);
if (!data) {
ctx->script_printf(ctx, MSG_ERROR, "Can't read %s\n", file);
return JTAG_CORE_IO_ERROR;
}
if (spi_flash_program(&sf, addr, data, len) < 0) {
free(data);
ctx->script_printf(ctx, MSG_ERROR, "spi_flash_program failed\n");
return JTAG_CORE_IO_ERROR;
}
free(data);
ctx->script_printf(ctx, MSG_INFO_0, "Wrote %lu bytes to 0x%.8X\n",
(unsigned long)len, (unsigned)addr);
return JTAG_CORE_NO_ERROR;
}
const char *cmd_flash_verify_help[] = {
"<device> <addr> <file>",
"Compare the flash content at <addr> (hex) against <file>.",
""};
static int cmd_flash_verify(script_ctx *ctx, char *line)
{
char dev_txt[DEFAULT_BUFLEN], addr_txt[DEFAULT_BUFLEN], file[DEFAULT_BUFLEN];
struct flash_proxy_ctx pc;
spi_flash sf;
uint8_t *data;
uint32_t addr, mismatch = 0;
size_t len = 0;
int device, r;
if (get_param(ctx, line, 1, dev_txt) < 0 || get_param(ctx, line, 2, addr_txt) < 0 ||
get_param(ctx, line, 3, file) < 0) {
ctx->script_printf(ctx, MSG_ERROR, "Usage: flash_verify <device> <addr> <file>\n");
return JTAG_CORE_BAD_PARAMETER;
}
device = (int)strtoul(dev_txt, NULL, 0);
addr = (uint32_t)strtoul(addr_txt, NULL, 0);
if ((r = flash_setup_detected(ctx, device, &sf, &pc)) != JTAG_CORE_NO_ERROR) return r;
data = read_file(file, &len);
if (!data) {
ctx->script_printf(ctx, MSG_ERROR, "Can't read %s\n", file);
return JTAG_CORE_IO_ERROR;
}
r = spi_flash_verify(&sf, addr, data, len, &mismatch);
free(data);
if (r < 0) {
ctx->script_printf(ctx, MSG_ERROR, "spi_flash_verify failed\n");
return JTAG_CORE_IO_ERROR;
}
ctx->last_data_value = r; /* 0 = match, 1 = mismatch */
if (r == 1) {
ctx->script_printf(ctx, MSG_WARNING,
"Verify MISMATCH at offset 0x%X (flash 0x%.8X)\n",
(unsigned)mismatch, (unsigned)(addr + mismatch));
return JTAG_CORE_NO_ERROR;
}
ctx->script_printf(ctx, MSG_INFO_0, "Verify OK (%lu bytes)\n", (unsigned long)len);
return JTAG_CORE_NO_ERROR;
}
cmd_list script_commands_list[] =
{
{"print", cmd_print, cmd_print_help},
{"help", cmd_help, cmd_help_help},
{"?", cmd_help, cmd_help_help},
{"version", cmd_version, cmd_version_help},
{"pause", cmd_pause, cmd_pause_help},
{"set", cmd_set_env_var, cmd_set_env_var_help},
{"print_env_var", cmd_print_env_var, cmd_print_env_var_help},
{"call", cmd_call, cmd_call_help},
{"system", cmd_system, cmd_system_help},
{"if", cmd_if, cmd_if_help},
{"goto", cmd_goto, cmd_goto_help},
{"return", cmd_return, cmd_return_help},
{"rand", cmd_rand, cmd_rand_help},
{"init_array", cmd_initarray, cmd_initarray_help},
{"jtag_probes", cmd_print_probes_list, cmd_print_probes_list_help},
{"jtag_open", cmd_open_probe, cmd_open_probe_help},
{"jtag_autoinit", cmd_autoinit, cmd_autoinit_help},
{"jtag_scan", cmd_init_and_scan, cmd_init_and_scan_help},
{"jtag_ndev", cmd_print_nb_dev, cmd_print_nb_dev_help},
{"jtag_devices", cmd_print_devs_list, cmd_print_devs_list_help},
{"jtag_bsdl", cmd_load_bsdl, cmd_load_bsdl_help},
{"jtag_mode", cmd_set_scan_mode, cmd_set_scan_mode_help},
{"jtag_push_pop", cmd_push_and_pop, cmd_push_and_pop_help},
{"jtag_pins", cmd_get_pins_list, cmd_get_pins_list_help},
{"jtag_pin_dir", cmd_set_pin_mode, cmd_set_pin_mode_help},
{"jtag_pin_set", cmd_set_pin_state, cmd_set_pin_state_help},
{"jtag_pin_get", cmd_get_pin_state, cmd_get_pin_state_help},
{"jtag_i2c_scl", cmd_set_i2c_scl_pin, cmd_set_i2c_scl_help},
{"jtag_i2c_sda", cmd_set_i2c_sda_pin, cmd_set_i2c_sda_help},
{"jtag_i2c_rd", cmd_do_i2c_rd, cmd_do_i2c_wr_help},
{"jtag_i2c_wr", cmd_do_i2c_wr, cmd_do_i2c_rd_help},
{"jtag_mdio_mdc", cmd_set_mdio_mdc_pin, cmd_set_mdio_mdc_pin_help},
{"jtag_mdio_io", cmd_set_mdio_mdio_pin, cmd_set_mdio_mdio_pin_help},
{"jtag_mdio_rd", cmd_do_mdio_rd, cmd_do_mdio_rd_help},
{"jtag_mdio_wr", cmd_do_mdio_wr, cmd_do_mdio_wr_help},
{"jtag_spi_cs", cmd_set_spi_cs_pin, cmd_set_spi_cs_pin_help},
{"jtag_spi_mosi", cmd_set_spi_mosi_pin, cmd_set_spi_mosi_pin_help},
{"jtag_spi_miso", cmd_set_spi_miso_pin, cmd_set_spi_miso_pin_help},
{"jtag_spi_clk", cmd_set_spi_clk_pin, cmd_set_spi_clk_pin_help},
{"jtag_spi_xfer", cmd_spi_rd_wr, cmd_spi_rd_wr_help},
{"fpga_list", cmd_fpga_list, cmd_fpga_list_help},
{"fpga_info", cmd_fpga_info, cmd_fpga_info_help},
{"bscan_set_ir", cmd_bscan_set_ir, cmd_bscan_set_ir_help},
{"bscan_shift_dr", cmd_bscan_shift_dr, cmd_bscan_shift_dr_help},
{"bscan_load_bitstream", cmd_bscan_load_bitstream, cmd_bscan_load_bitstream_help},
{"bscan_jedec", cmd_bscan_jedec, cmd_bscan_jedec_help},
{"flash_detect", cmd_flash_detect, cmd_flash_detect_help},
{"flash_read", cmd_flash_read, cmd_flash_read_help},
{"flash_erase", cmd_flash_erase, cmd_flash_erase_help},
{"flash_write", cmd_flash_write, cmd_flash_write_help},
{"flash_verify", cmd_flash_verify, cmd_flash_verify_help},
{0, 0}};
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
script_ctx *jtagcore_initScript(jtag_core *jc)
{
return init_script((void *)jc, 0x00000000, (void *)jc->envvar);
}
int jtagcore_savePinsStateScript(jtag_core *jc, int device, char *script_path)
{
FILE *f;
int number_of_pins;
int pin_type;
int i, state;
char pin_name[DEFAULT_BUFLEN];
f = fopen(script_path, "w");
if (f)
{
if (jc)
{
number_of_pins = jtagcore_get_number_of_pins(jc, device);
if (number_of_pins > 0)
{
for (i = 0; i < number_of_pins; i++)
{
pin_type = 0;
jtagcore_get_pin_properties(jc, device, i, (char *)&pin_name, sizeof(pin_name), &pin_type);
if (pin_type)
{
fprintf(f, "print ----------------------------\n");
// output enable
if (pin_type & JTAG_CORE_PIN_IS_TRISTATES)
{
state = jtagcore_get_pin_state(jc, device, i, JTAG_CORE_OE);
fprintf(f, "print Pin %s direction : %d\n", pin_name, state);
fprintf(f, "jtag_pin_dir %d %s %d\n", device, pin_name, state);
}
// output data
if (pin_type & JTAG_CORE_PIN_IS_OUTPUT)
{
state = jtagcore_get_pin_state(jc, device, i, JTAG_CORE_OUTPUT);
fprintf(f, "print Pin %s state : %d\n", pin_name, state);
fprintf(f, "jtag_pin_set %d %s %d\n", device, pin_name, state);
}
// input data
if (pin_type & JTAG_CORE_PIN_IS_INPUT)
{
state = jtagcore_get_pin_state(jc, device, i, JTAG_CORE_INPUT);
fprintf(f, "print Input pin %s state : %d\n", pin_name, state);
}
fprintf(f, "\n");
}
}
fprintf(f, "jtag_push_pop\n");
fprintf(f, "\n");
}
}
fclose(f);
}
return 0;
}