"quirk" was unclear jargon; "caveat" matches the wording already used in
the README/CLAUDE.md ("Xilinx caveats"). Renames the struct field, the
FPGA_QUIRK_* macro, the fpga_info output and the docs. No behaviour
change.
3260 lines
91 KiB
C
3260 lines
91 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 *)¶ms_str[i]);
|
|
if (strlen((char *)¶ms_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 *)¶ms_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 *)¶ms_str[i]);
|
|
if (strlen((char *)¶ms_str[i]))
|
|
valid++;
|
|
}
|
|
|
|
i = 0;
|
|
while (i < 5 && strcmp((char *)¶ms_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 *)¶ms_str[2], ">=") && ((signed_env_var_value)value_1 >= (signed_env_var_value)value_2))
|
|
eval = 1;
|
|
|
|
if (!strcmp((char *)¶ms_str[2], "<=") && ((signed_env_var_value)value_1 <= (signed_env_var_value)value_2))
|
|
eval = 1;
|
|
|
|
if (!strcmp((char *)¶ms_str[2], ">") && ((signed_env_var_value)value_1 > (signed_env_var_value)value_2))
|
|
eval = 1;
|
|
|
|
if (!strcmp((char *)¶ms_str[2], "<") && ((signed_env_var_value)value_1 < (signed_env_var_value)value_2))
|
|
eval = 1;
|
|
|
|
if (!strcmp((char *)¶ms_str[2], "==") && (value_1 == value_2))
|
|
eval = 1;
|
|
|
|
if (!strcmp((char *)¶ms_str[2], "!=") && (value_1 != value_2))
|
|
eval = 1;
|
|
|
|
if (!strcmp((char *)¶ms_str[2], "&") && (value_1 & value_2))
|
|
eval = 1;
|
|
|
|
if (!strcmp((char *)¶ms_str[2], "^") && (value_1 ^ value_2))
|
|
eval = 1;
|
|
|
|
if (!strcmp((char *)¶ms_str[2], "|") && (value_1 | value_2))
|
|
eval = 1;
|
|
|
|
tmp_val = value_1 >> value_2;
|
|
if (!strcmp((char *)¶ms_str[2], ">>") && tmp_val)
|
|
eval = 1;
|
|
|
|
tmp_val = value_1 << value_2;
|
|
if (!strcmp((char *)¶ms_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)
|
|
{
|
|
// Device already loaded !
|
|
ctx->script_printf(ctx, MSG_WARNING, "Device %d BSDL already loaded ! ID conflit ?\n", dev_nb);
|
|
}
|
|
|
|
// 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[] = {
|
|
"", // Arguments "1<arg>(type) ..."
|
|
"explanations line one", // Explanations
|
|
"explanations line two",
|
|
""
|
|
};
|
|
static int cmd_init_and_scan(script_ctx *ctx, char *line)
|
|
{
|
|
jtag_core *jc;
|
|
int ret;
|
|
|
|
jc = (jtag_core *)ctx->app_ctx;
|
|
|
|
ret = jtagcore_scan_and_init_chain(jc);
|
|
|
|
if (ret == JTAG_CORE_NO_ERROR)
|
|
{
|
|
ctx->script_printf(ctx, MSG_INFO_0, "JTAG Scan done\n");
|
|
|
|
return JTAG_CORE_NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
ctx->script_printf(ctx, MSG_INFO_0, "JTAG Scan return code : %d\n", ret);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
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 known to this build (registry in modules/fpga/).",
|
|
""};
|
|
static int cmd_fpga_list(script_ctx *ctx, char *line)
|
|
{
|
|
int i, n;
|
|
const fpga_target *t;
|
|
|
|
(void)line;
|
|
|
|
n = fpga_get_target_count();
|
|
ctx->script_printf(ctx, MSG_INFO_0, "%d FPGA target(s) registered:\n", n);
|
|
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;
|
|
}
|
|
|
|
const char *cmd_flash_read_help[] = {
|
|
"<device> <addr> <len>",
|
|
"Read <len> bytes from the SPI flash at <addr> (hex) and hex-dump them.",
|
|
"Read-only. Requires a proxy loaded and a flash recognised by 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];
|
|
struct flash_proxy_ctx pc;
|
|
spi_flash sf;
|
|
uint8_t *buf;
|
|
uint32_t addr;
|
|
size_t len, i;
|
|
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, len_txt) < 0) {
|
|
ctx->script_printf(ctx, MSG_ERROR, "Usage: flash_read <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 (len > 65536) {
|
|
ctx->script_printf(ctx, MSG_ERROR, "flash_read: len capped at 65536 for an interactive dump\n");
|
|
return JTAG_CORE_BAD_PARAMETER;
|
|
}
|
|
if ((r = flash_setup(ctx, device, &sf, &pc)) != 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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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},
|
|
{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;
|
|
}
|