Compare commits
4 Commits
43d291418b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f47295b94b | |||
| 8acc24eec7 | |||
| 831bd7c129 | |||
| 2752c3404b |
23
CLAUDE.md
23
CLAUDE.md
@@ -20,7 +20,16 @@ other families (Lattice, Microsemi, …) by playing a vendor-exported SVF.
|
|||||||
The Viveris library itself lives unchanged in `src/modules/`. Everything
|
The Viveris library itself lives unchanged in `src/modules/`. Everything
|
||||||
new is in `src/bs/` (the REPL) and the project modules (`target/`,
|
new is in `src/bs/` (the REPL) and the project modules (`target/`,
|
||||||
`bscan/`, `spi_flash/`, `svf/`, `probes/`, `program/`, `arm_debug/`)
|
`bscan/`, `spi_flash/`, `svf/`, `probes/`, `program/`, `arm_debug/`)
|
||||||
sitting alongside the Viveris ones.
|
sitting alongside the Viveris ones. The BSDL parser was extracted into
|
||||||
|
a standalone library, **[libbsdl](ssh://gitea@git.beafrancois.fr:8329/electronics/libbsdl.git)**
|
||||||
|
(LGPL, seeded from the same Viveris loader), and is now pulled in via
|
||||||
|
CMake `FetchContent` instead of vendored. The SVF player core moved the
|
||||||
|
same way into **[libsvf](ssh://gitea@git.beafrancois.fr:8329/electronics/libsvf.git)**
|
||||||
|
(shared with the `wifi_jtag_programmer` Zephyr firmware, which plays SVF
|
||||||
|
through an embedded JTAG port); `src/modules/svf/` is now only the
|
||||||
|
bscan-backed glue. To build against local checkouts (side-by-side dev):
|
||||||
|
configure with `-DFETCHCONTENT_SOURCE_DIR_BSDL=/path/to/libbsdl` and/or
|
||||||
|
`-DFETCHCONTENT_SOURCE_DIR_SVF=/path/to/libsvf`.
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
@@ -30,19 +39,21 @@ src/
|
|||||||
└── modules/
|
└── modules/
|
||||||
— Viveris's library (LGPL, unchanged) —
|
— Viveris's library (LGPL, unchanged) —
|
||||||
├── jtag_core/ TAP state machine, IR/DR shifts
|
├── jtag_core/ TAP state machine, IR/DR shifts
|
||||||
├── bsdl_parser/ .bsd loader
|
|
||||||
├── bus_over_jtag/ SPI/I²C/MDIO/parallel mem bit-bang over EXTEST
|
├── bus_over_jtag/ SPI/I²C/MDIO/parallel mem bit-bang over EXTEST
|
||||||
├── drivers/ FTDI, J-Link, Linux GPIO, LPT, Digilent (optional, dlopen)
|
├── drivers/ FTDI, J-Link, Linux GPIO, LPT, Digilent (optional, dlopen)
|
||||||
├── script/ Script engine (the real UI)
|
├── script/ Script engine (the real UI)
|
||||||
├── config/ Built-in config.script
|
├── config/ Built-in config.script
|
||||||
├── os_interface/ Portable fs/network wrappers
|
├── os_interface/ Portable fs/network wrappers
|
||||||
└── natsort/ Natural pin-name sorting
|
└── natsort/ Natural pin-name sorting
|
||||||
|
— pulled via FetchContent (LGPL, separate repos) —
|
||||||
|
├── (libbsdl) BSDL (.bsd) parser; struct + JSON; stable C ABI
|
||||||
|
└── (libsvf) portable SVF player core (svf_play_buf/file over a 5-op JTAG port)
|
||||||
— new (this project) —
|
— new (this project) —
|
||||||
├── target/ Target registry: FPGAs + CPUs (parses data/targets.yaml)
|
├── target/ Target registry: FPGAs + CPUs (parses data/targets.yaml)
|
||||||
├── bscan/ JTAG TAP primitives (set_ir/shift_ir/shift_dr/tap_reset/
|
├── bscan/ JTAG TAP primitives (set_ir/shift_ir/shift_dr/tap_reset/
|
||||||
│ idle_cycles) + BSCAN proxy (bitstream load, SPI-over-USER1)
|
│ idle_cycles) + BSCAN proxy (bitstream load, SPI-over-USER1)
|
||||||
├── spi_flash/ SPI NOR chip DB + read/erase/program/verify over a callback
|
├── spi_flash/ SPI NOR chip DB + read/erase/program/verify over a callback
|
||||||
├── svf/ SVF player (svf_play): SIR/SDR/RUNTEST/STATE, masked compare
|
├── svf/ glue: bscan_*-backed svf_jtag_ops port for libsvf (bs_svf_play)
|
||||||
├── probes/ Probe-config profiles loader (parses data/probes.yaml, libyaml)
|
├── probes/ Probe-config profiles loader (parses data/probes.yaml, libyaml)
|
||||||
├── program/ `program` dispatch: routes a target to its backend by `prog`
|
├── program/ `program` dispatch: routes a target to its backend by `prog`
|
||||||
└── arm_debug/ ARM7TDMI (EmbeddedICE) debug: halt/resume, Thumb->ARM, memory read (works); flash-write backend TODO
|
└── arm_debug/ ARM7TDMI (EmbeddedICE) debug: halt/resume, Thumb->ARM, memory read (works); flash-write backend TODO
|
||||||
@@ -528,7 +539,11 @@ mkdir build && cd build && cmake .. && make
|
|||||||
Build needs **libyaml** (pkg-config `yaml-0.1`; Arch `libyaml`, Debian
|
Build needs **libyaml** (pkg-config `yaml-0.1`; Arch `libyaml`, Debian
|
||||||
`libyaml-dev`) for the registry, and **libftdi1** + **libusb-1.0**
|
`libyaml-dev`) for the registry, and **libftdi1** + **libusb-1.0**
|
||||||
(pkg-config `libftdi1`; Arch `libftdi`, Debian `libftdi1-dev`) for the
|
(pkg-config `libftdi1`; Arch `libftdi`, Debian `libftdi1-dev`) for the
|
||||||
FTDI/Olimex driver. Run `bs` from the repo root so it finds
|
FTDI/Olimex driver. **libbsdl** (the BSDL parser, separate repo) is
|
||||||
|
pulled in by CMake `FetchContent` at configure time — needs network on
|
||||||
|
first build. For a local checkout, configure with
|
||||||
|
`-DFETCHCONTENT_SOURCE_DIR_BSDL=/path/to/libbsdl` (built-in FetchContent
|
||||||
|
override, no clone happens). Run `bs` from the repo root so it finds
|
||||||
`data/targets.yaml` (and `data/bsdl_files/`, `data/bscan_proxies/`), or
|
`data/targets.yaml` (and `data/bsdl_files/`, `data/bscan_proxies/`), or
|
||||||
point `$BS_TARGETS` at it.
|
point `$BS_TARGETS` at it.
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
|
||||||
project(BoundaryScanExplorer)
|
project(BoundaryScanExplorer)
|
||||||
|
|
||||||
@@ -6,6 +6,28 @@ project(BoundaryScanExplorer)
|
|||||||
# build/src/bs/ where the source tree would otherwise mirror it.
|
# build/src/bs/ where the source tree would otherwise mirror it.
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
|
# ---- libbsdl (BSDL parser, extracted from this repo and now standalone) ----
|
||||||
|
# Pulled via FetchContent from the canonical Gitea URL. For a local checkout,
|
||||||
|
# set -DFETCHCONTENT_SOURCE_DIR_BSDL=/path/to/libbsdl at configure time
|
||||||
|
# (built-in FetchContent override — no clone happens).
|
||||||
|
include(FetchContent)
|
||||||
|
set(BSDL_BUILD_CLI OFF CACHE BOOL "" FORCE)
|
||||||
|
set(BSDL_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||||
|
FetchContent_Declare(bsdl
|
||||||
|
GIT_REPOSITORY ssh://gitea@git.beafrancois.fr:8329/electronics/libbsdl.git
|
||||||
|
GIT_TAG main
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(bsdl)
|
||||||
|
|
||||||
|
# ---- libsvf (SVF player, extracted from this repo and now standalone) ----
|
||||||
|
# Same pattern as libbsdl. Local checkout override:
|
||||||
|
# -DFETCHCONTENT_SOURCE_DIR_SVF=/path/to/libsvf
|
||||||
|
FetchContent_Declare(svf
|
||||||
|
GIT_REPOSITORY ssh://gitea@git.beafrancois.fr:8329/electronics/libsvf.git
|
||||||
|
GIT_TAG main
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(svf)
|
||||||
|
|
||||||
# Digilent JTAG-SMT* backend. The driver dlopen's libdjtg/libdmgr at
|
# Digilent JTAG-SMT* backend. The driver dlopen's libdjtg/libdmgr at
|
||||||
# runtime and degrades to "no probe" if they're absent, so building it
|
# runtime and degrades to "no probe" if they're absent, so building it
|
||||||
# in costs nothing — default ON. Needs <dlfcn.h>, so UNIX only.
|
# in costs nothing — default ON. Needs <dlfcn.h>, so UNIX only.
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
|
||||||
|
|
||||||
file(GLOB_RECURSE ALL_SOURCES "*.c")
|
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
|
||||||
|
|
||||||
add_library(bsdl_parser ${ALL_SOURCES})
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,87 +0,0 @@
|
|||||||
#ifndef _BSDL_LOADER_H
|
|
||||||
#define _BSDL_LOADER_H
|
|
||||||
/*
|
|
||||||
* 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 bsdl_loader.h
|
|
||||||
* @brief bsdl file parser header
|
|
||||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "jtag_core/jtag_core.h"
|
|
||||||
|
|
||||||
#define MAX_ELEMENT_SIZE (64+1)
|
|
||||||
|
|
||||||
typedef struct _pin_ctrl
|
|
||||||
{
|
|
||||||
char pinname[MAX_ELEMENT_SIZE];
|
|
||||||
int pintype;
|
|
||||||
|
|
||||||
char physical_pin[MAX_ELEMENT_SIZE];
|
|
||||||
|
|
||||||
int ctrl_bit_number;
|
|
||||||
int out_bit_number;
|
|
||||||
int in_bit_number;
|
|
||||||
}pin_ctrl;
|
|
||||||
|
|
||||||
typedef struct _jtag_chain
|
|
||||||
{
|
|
||||||
int bit_index;
|
|
||||||
|
|
||||||
int bit_cell_type; // BC_1,BC_2,...
|
|
||||||
|
|
||||||
char pinname[MAX_ELEMENT_SIZE]; // Pin name.
|
|
||||||
|
|
||||||
int bit_type; // None , ctrl , in, out.
|
|
||||||
|
|
||||||
int safe_state; // Default - Safe state. (0,1,-1)
|
|
||||||
|
|
||||||
int control_bit_index; // Indicate the associated control bit. -1 if no control bit.
|
|
||||||
int control_disable_state;
|
|
||||||
int control_disable_result;
|
|
||||||
|
|
||||||
}jtag_chain;
|
|
||||||
|
|
||||||
typedef struct _jtag_bsdl
|
|
||||||
{
|
|
||||||
unsigned long chip_id;
|
|
||||||
unsigned long chip_id_mask;
|
|
||||||
|
|
||||||
char src_filename[512];
|
|
||||||
char entity_name[512];
|
|
||||||
|
|
||||||
int number_of_chainbits;
|
|
||||||
jtag_chain * chain_list;
|
|
||||||
|
|
||||||
int number_of_pins;
|
|
||||||
pin_ctrl * pins_list;
|
|
||||||
|
|
||||||
int number_of_bits_per_instruction;
|
|
||||||
char IDCODE_Instruction[MAX_ELEMENT_SIZE];
|
|
||||||
char EXTEST_Instruction[MAX_ELEMENT_SIZE];
|
|
||||||
char BYPASS_Instruction[MAX_ELEMENT_SIZE];
|
|
||||||
char SAMPLE_Instruction[MAX_ELEMENT_SIZE];
|
|
||||||
|
|
||||||
}jtag_bsdl;
|
|
||||||
|
|
||||||
jtag_bsdl * load_bsdlfile(jtag_core * jc,char *filename);
|
|
||||||
void unload_bsdlfile(jtag_core * jc, jtag_bsdl * bsdl);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 bsdl_strings.c
|
|
||||||
* @brief bsdl file string keywords
|
|
||||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "jtag_core/jtag_core.h"
|
|
||||||
|
|
||||||
#include "bsdl_loader.h"
|
|
||||||
#include "bsdl_strings.h"
|
|
||||||
|
|
||||||
type_strings celltype_str[]=
|
|
||||||
{
|
|
||||||
{"BC_1",CELLTYPE_BC1},
|
|
||||||
{"BC_2",CELLTYPE_BC2},
|
|
||||||
{"BC_3",CELLTYPE_BC3},
|
|
||||||
{"BC_4",CELLTYPE_BC4},
|
|
||||||
{"BC_5",CELLTYPE_BC5},
|
|
||||||
{"BC_6",CELLTYPE_BC6},
|
|
||||||
{"BC_7",CELLTYPE_BC7},
|
|
||||||
|
|
||||||
{0,CELLTYPE_UNKNOWN}
|
|
||||||
};
|
|
||||||
|
|
||||||
type_strings bittype_str[]=
|
|
||||||
{
|
|
||||||
{"INPUT",BITTYPE_INPUT},
|
|
||||||
{"OBSERVE_ONLY",BITTYPE_INPUT},
|
|
||||||
{"OUTPUT",BITTYPE_OUTPUT},
|
|
||||||
{"OUTPUT2", BITTYPE_OUTPUT },
|
|
||||||
{"OUTPUT3",BITTYPE_TRISTATE_OUTPUT},
|
|
||||||
{"BIDIR",BITTYPE_INOUT},
|
|
||||||
{"CONTROL",BITTYPE_CONTROL},
|
|
||||||
{"CONTROLR",BITTYPE_CONTROL},
|
|
||||||
{"INTERNAL",BITTYPE_INTERNAL},
|
|
||||||
{0,BITTYPE_UNKNOWN}
|
|
||||||
};
|
|
||||||
|
|
||||||
type_strings statetype_str[]=
|
|
||||||
{
|
|
||||||
{"X",STATE_UNDEF},
|
|
||||||
{"1",STATE_HIGH},
|
|
||||||
{"0",STATE_LOW},
|
|
||||||
{"Z",STATE_HIGHZ},
|
|
||||||
{0,STATE_UNKNOWN}
|
|
||||||
};
|
|
||||||
|
|
||||||
type_strings pintype_str[]=
|
|
||||||
{
|
|
||||||
{"IN",IO_IN},
|
|
||||||
{"OUT",IO_OUT},
|
|
||||||
{"INOUT",IO_INOUT},
|
|
||||||
{"BUFFER", IO_OUT },
|
|
||||||
{0,IO_UNDEF}
|
|
||||||
};
|
|
||||||
|
|
||||||
int get_typecode(type_strings * typelist,char * name)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
while( typelist[i].type_name )
|
|
||||||
{
|
|
||||||
if(!strcmp( typelist[i].type_name, name ) )
|
|
||||||
{
|
|
||||||
return typelist[i].type_code;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return typelist[i].type_code;
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
#ifndef _BSDL_STRING_H
|
|
||||||
#define _BSDL_STRING_H
|
|
||||||
/*
|
|
||||||
* 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 bsdl_strings.h
|
|
||||||
* @brief bsdl file string keywords header
|
|
||||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct type_strings_
|
|
||||||
{
|
|
||||||
char * type_name;
|
|
||||||
int type_code;
|
|
||||||
}type_strings;
|
|
||||||
|
|
||||||
enum CELLTYPE
|
|
||||||
{
|
|
||||||
CELLTYPE_UNKNOWN = 0x00,
|
|
||||||
CELLTYPE_BC1,
|
|
||||||
CELLTYPE_BC2,
|
|
||||||
CELLTYPE_BC3,
|
|
||||||
CELLTYPE_BC4,
|
|
||||||
CELLTYPE_BC5,
|
|
||||||
CELLTYPE_BC6,
|
|
||||||
CELLTYPE_BC7
|
|
||||||
};
|
|
||||||
|
|
||||||
enum BITTYPE
|
|
||||||
{
|
|
||||||
BITTYPE_UNKNOWN = 0x00,
|
|
||||||
BITTYPE_INPUT,
|
|
||||||
BITTYPE_OUTPUT,
|
|
||||||
BITTYPE_TRISTATE_OUTPUT,
|
|
||||||
BITTYPE_INOUT,
|
|
||||||
BITTYPE_CONTROL,
|
|
||||||
BITTYPE_INTERNAL
|
|
||||||
};
|
|
||||||
|
|
||||||
enum STATETYPE
|
|
||||||
{
|
|
||||||
STATE_UNKNOWN = 0x00,
|
|
||||||
STATE_UNDEF,
|
|
||||||
STATE_HIGH,
|
|
||||||
STATE_LOW,
|
|
||||||
STATE_HIGHZ
|
|
||||||
};
|
|
||||||
|
|
||||||
enum PINIOTYPE
|
|
||||||
{
|
|
||||||
IO_UNDEF = 0x00,
|
|
||||||
IO_IN,
|
|
||||||
IO_OUT,
|
|
||||||
IO_INOUT
|
|
||||||
};
|
|
||||||
|
|
||||||
extern type_strings celltype_str[];
|
|
||||||
extern type_strings bittype_str[];
|
|
||||||
extern type_strings statetype_str[];
|
|
||||||
extern type_strings pintype_str[];
|
|
||||||
|
|
||||||
int get_typecode(type_strings * typelist,char * name);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -5,3 +5,4 @@ file(GLOB_RECURSE ALL_SOURCES "*.c")
|
|||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||||
|
|
||||||
add_library(bus_over_jtag ${ALL_SOURCES})
|
add_library(bus_over_jtag ${ALL_SOURCES})
|
||||||
|
target_link_libraries(bus_over_jtag PUBLIC bsdl::bsdl)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
#include "jtag_core/jtag_core.h"
|
#include "jtag_core/jtag_core.h"
|
||||||
|
|
||||||
#include "bsdl_parser/bsdl_loader.h"
|
#include <bsdl/bsdl.h>
|
||||||
|
|
||||||
#include "drivers/drivers_list.h"
|
#include "drivers/drivers_list.h"
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
int jtagcore_i2c_set_scl_pin(jtag_core * jc, int device, int pin)
|
int jtagcore_i2c_set_scl_pin(jtag_core * jc, int device, int pin)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
|
|
||||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
||||||
{
|
{
|
||||||
@@ -49,7 +49,7 @@ int jtagcore_i2c_set_scl_pin(jtag_core * jc, int device, int pin)
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
if (pin < (int)bsdl_file->pin_count && pin >= 0)
|
||||||
{
|
{
|
||||||
jc->i2c_scl_pin = pin;
|
jc->i2c_scl_pin = pin;
|
||||||
jc->i2c_scl_device = device;
|
jc->i2c_scl_device = device;
|
||||||
@@ -70,7 +70,7 @@ int jtagcore_i2c_set_scl_pin(jtag_core * jc, int device, int pin)
|
|||||||
|
|
||||||
int jtagcore_i2c_set_sda_pin(jtag_core * jc, int device, int pin)
|
int jtagcore_i2c_set_sda_pin(jtag_core * jc, int device, int pin)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
|
|
||||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
||||||
{
|
{
|
||||||
@@ -78,7 +78,7 @@ int jtagcore_i2c_set_sda_pin(jtag_core * jc, int device, int pin)
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
if (pin < (int)bsdl_file->pin_count && pin >= 0)
|
||||||
{
|
{
|
||||||
jc->i2c_sda_pin = pin;
|
jc->i2c_sda_pin = pin;
|
||||||
jc->i2c_sda_device = device;
|
jc->i2c_sda_device = device;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
#include "jtag_core/jtag_core.h"
|
#include "jtag_core/jtag_core.h"
|
||||||
|
|
||||||
#include "bsdl_parser/bsdl_loader.h"
|
#include <bsdl/bsdl.h>
|
||||||
|
|
||||||
#include "drivers/drivers_list.h"
|
#include "drivers/drivers_list.h"
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
int jtagcore_mdio_set_mdc_pin(jtag_core * jc, int device, int pin)
|
int jtagcore_mdio_set_mdc_pin(jtag_core * jc, int device, int pin)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
|
|
||||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
||||||
{
|
{
|
||||||
@@ -47,7 +47,7 @@ int jtagcore_mdio_set_mdc_pin(jtag_core * jc, int device, int pin)
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
if (pin < (int)bsdl_file->pin_count && pin >= 0)
|
||||||
{
|
{
|
||||||
jc->mdio_mdc_pin = pin;
|
jc->mdio_mdc_pin = pin;
|
||||||
jc->mdio_mdc_device = device;
|
jc->mdio_mdc_device = device;
|
||||||
@@ -61,7 +61,7 @@ int jtagcore_mdio_set_mdc_pin(jtag_core * jc, int device, int pin)
|
|||||||
|
|
||||||
int jtagcore_mdio_set_mdio_pin(jtag_core * jc, int device, int pin)
|
int jtagcore_mdio_set_mdio_pin(jtag_core * jc, int device, int pin)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
|
|
||||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >=0)
|
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >=0)
|
||||||
{
|
{
|
||||||
@@ -69,7 +69,7 @@ int jtagcore_mdio_set_mdio_pin(jtag_core * jc, int device, int pin)
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
if (pin < (int)bsdl_file->pin_count && pin >= 0)
|
||||||
{
|
{
|
||||||
jc->mdio_mdio_pin = pin;
|
jc->mdio_mdio_pin = pin;
|
||||||
jc->mdio_mdio_device = device;
|
jc->mdio_mdio_device = device;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
#include "jtag_core/jtag_core.h"
|
#include "jtag_core/jtag_core.h"
|
||||||
|
|
||||||
#include "bsdl_parser/bsdl_loader.h"
|
#include <bsdl/bsdl.h>
|
||||||
|
|
||||||
#include "drivers/drivers_list.h"
|
#include "drivers/drivers_list.h"
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ int jtagcore_memory_clear_pins(jtag_core * jc)
|
|||||||
|
|
||||||
int jtagcore_memory_set_address_pin(jtag_core * jc, int address_bit, int device, int pin)
|
int jtagcore_memory_set_address_pin(jtag_core * jc, int address_bit, int device, int pin)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
|
|
||||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && address_bit < MAX_BUS_WIDTH)
|
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && address_bit < MAX_BUS_WIDTH)
|
||||||
{
|
{
|
||||||
@@ -69,7 +69,7 @@ int jtagcore_memory_set_address_pin(jtag_core * jc, int address_bit, int device,
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
if ( pin < bsdl_file->number_of_pins && pin >= 0 )
|
if ( pin < (int)bsdl_file->pin_count && pin >= 0 )
|
||||||
{
|
{
|
||||||
jc->ram_address_pin[address_bit] = pin;
|
jc->ram_address_pin[address_bit] = pin;
|
||||||
jc->ram_address_device[address_bit] = device;
|
jc->ram_address_device[address_bit] = device;
|
||||||
@@ -83,7 +83,7 @@ int jtagcore_memory_set_address_pin(jtag_core * jc, int address_bit, int device,
|
|||||||
|
|
||||||
int jtagcore_memory_set_data_pin(jtag_core * jc, int data_bit, int device, int pin)
|
int jtagcore_memory_set_data_pin(jtag_core * jc, int data_bit, int device, int pin)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
|
|
||||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && data_bit < MAX_BUS_WIDTH)
|
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && data_bit < MAX_BUS_WIDTH)
|
||||||
{
|
{
|
||||||
@@ -91,7 +91,7 @@ int jtagcore_memory_set_data_pin(jtag_core * jc, int data_bit, int device, int p
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
if ( pin < bsdl_file->number_of_pins && pin >= 0 )
|
if ( pin < (int)bsdl_file->pin_count && pin >= 0 )
|
||||||
{
|
{
|
||||||
jc->ram_data_pin[data_bit] = pin;
|
jc->ram_data_pin[data_bit] = pin;
|
||||||
jc->ram_data_device[data_bit] = device;
|
jc->ram_data_device[data_bit] = device;
|
||||||
@@ -105,7 +105,7 @@ int jtagcore_memory_set_data_pin(jtag_core * jc, int data_bit, int device, int p
|
|||||||
|
|
||||||
int jtagcore_memory_set_ctrl_pin(jtag_core * jc, int ctrl, int polarity, int device, int pin)
|
int jtagcore_memory_set_ctrl_pin(jtag_core * jc, int ctrl, int polarity, int device, int pin)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
|
|
||||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && ctrl < 16)
|
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && ctrl < 16)
|
||||||
{
|
{
|
||||||
@@ -113,7 +113,7 @@ int jtagcore_memory_set_ctrl_pin(jtag_core * jc, int ctrl, int polarity, int dev
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
if ( pin < bsdl_file->number_of_pins && pin >= 0 )
|
if ( pin < (int)bsdl_file->pin_count && pin >= 0 )
|
||||||
{
|
{
|
||||||
jc->ram_ctrl_pin[ctrl] = pin;
|
jc->ram_ctrl_pin[ctrl] = pin;
|
||||||
jc->ram_ctrl_pin_pol[ctrl] = polarity;
|
jc->ram_ctrl_pin_pol[ctrl] = polarity;
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
#include "jtag_core/jtag_core.h"
|
#include "jtag_core/jtag_core.h"
|
||||||
|
|
||||||
#include "bsdl_parser/bsdl_loader.h"
|
#include <bsdl/bsdl.h>
|
||||||
|
|
||||||
#include "drivers/drivers_list.h"
|
#include "drivers/drivers_list.h"
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
int jtagcore_spi_set_mosi_pin(jtag_core * jc, int device, int pin, int sample_clk_phase)
|
int jtagcore_spi_set_mosi_pin(jtag_core * jc, int device, int pin, int sample_clk_phase)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
|
|
||||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
||||||
{
|
{
|
||||||
@@ -47,7 +47,7 @@ int jtagcore_spi_set_mosi_pin(jtag_core * jc, int device, int pin, int sample_cl
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
if (pin < (int)bsdl_file->pin_count && pin >= 0)
|
||||||
{
|
{
|
||||||
jc->spi_mosi_pin = pin;
|
jc->spi_mosi_pin = pin;
|
||||||
if(sample_clk_phase)
|
if(sample_clk_phase)
|
||||||
@@ -65,7 +65,7 @@ int jtagcore_spi_set_mosi_pin(jtag_core * jc, int device, int pin, int sample_cl
|
|||||||
|
|
||||||
int jtagcore_spi_set_miso_pin(jtag_core * jc, int device, int pin, int sample_clk_phase)
|
int jtagcore_spi_set_miso_pin(jtag_core * jc, int device, int pin, int sample_clk_phase)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
|
|
||||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
||||||
{
|
{
|
||||||
@@ -73,7 +73,7 @@ int jtagcore_spi_set_miso_pin(jtag_core * jc, int device, int pin, int sample_cl
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
if (pin < (int)bsdl_file->pin_count && pin >= 0)
|
||||||
{
|
{
|
||||||
jc->spi_miso_pin = pin;
|
jc->spi_miso_pin = pin;
|
||||||
if(sample_clk_phase)
|
if(sample_clk_phase)
|
||||||
@@ -91,7 +91,7 @@ int jtagcore_spi_set_miso_pin(jtag_core * jc, int device, int pin, int sample_cl
|
|||||||
|
|
||||||
int jtagcore_spi_set_clk_pin(jtag_core * jc, int device, int pin, int polarity)
|
int jtagcore_spi_set_clk_pin(jtag_core * jc, int device, int pin, int polarity)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
|
|
||||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
||||||
{
|
{
|
||||||
@@ -99,7 +99,7 @@ int jtagcore_spi_set_clk_pin(jtag_core * jc, int device, int pin, int polarity)
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
if (pin < (int)bsdl_file->pin_count && pin >= 0)
|
||||||
{
|
{
|
||||||
jc->spi_clk_pin = pin;
|
jc->spi_clk_pin = pin;
|
||||||
if(polarity)
|
if(polarity)
|
||||||
@@ -117,7 +117,7 @@ int jtagcore_spi_set_clk_pin(jtag_core * jc, int device, int pin, int polarity)
|
|||||||
|
|
||||||
int jtagcore_spi_set_cs_pin(jtag_core * jc, int device, int pin, int polarity)
|
int jtagcore_spi_set_cs_pin(jtag_core * jc, int device, int pin, int polarity)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
|
|
||||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
||||||
{
|
{
|
||||||
@@ -125,7 +125,7 @@ int jtagcore_spi_set_cs_pin(jtag_core * jc, int device, int pin, int polarity)
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
if (pin < (int)bsdl_file->pin_count && pin >= 0)
|
||||||
{
|
{
|
||||||
jc->spi_cs_pin = pin;
|
jc->spi_cs_pin = pin;
|
||||||
if(polarity)
|
if(polarity)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ add_library(drivers ${MAIN_SOURCES} ${FTDI_SOURCES} ${GPIO_SOURCES} ${JLINK_SOUR
|
|||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
pkg_check_modules(LIBFTDI REQUIRED IMPORTED_TARGET libftdi1)
|
pkg_check_modules(LIBFTDI REQUIRED IMPORTED_TARGET libftdi1)
|
||||||
pkg_check_modules(LIBUSB REQUIRED IMPORTED_TARGET libusb-1.0)
|
pkg_check_modules(LIBUSB REQUIRED IMPORTED_TARGET libusb-1.0)
|
||||||
target_link_libraries(drivers PUBLIC PkgConfig::LIBFTDI PkgConfig::LIBUSB)
|
target_link_libraries(drivers PUBLIC PkgConfig::LIBFTDI PkgConfig::LIBUSB bsdl::bsdl)
|
||||||
|
|
||||||
if(BS_ENABLE_DIGILENT)
|
if(BS_ENABLE_DIGILENT)
|
||||||
target_link_libraries(drivers PUBLIC ${CMAKE_DL_LIBS})
|
target_link_libraries(drivers PUBLIC ${CMAKE_DL_LIBS})
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#include "jtag_core/jtag_core.h"
|
#include "jtag_core/jtag_core.h"
|
||||||
|
|
||||||
#include "bsdl_parser/bsdl_loader.h"
|
#include <bsdl/bsdl.h>
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include "./lpt_jtag/lpt_jtag_drv.h"
|
#include "./lpt_jtag/lpt_jtag_drv.h"
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include "jtag_core/jtag_core.h"
|
#include "jtag_core/jtag_core.h"
|
||||||
|
|
||||||
#include "bsdl_parser/bsdl_loader.h"
|
#include <bsdl/bsdl.h>
|
||||||
|
|
||||||
#include "drivers_list.h"
|
#include "drivers_list.h"
|
||||||
|
|
||||||
|
|||||||
@@ -21,3 +21,4 @@ include_directories(${DIR_MODULES})
|
|||||||
|
|
||||||
add_library(jtag_core ${ALL_SOURCES})
|
add_library(jtag_core ${ALL_SOURCES})
|
||||||
add_dependencies(jtag_core prebuild)
|
add_dependencies(jtag_core prebuild)
|
||||||
|
target_link_libraries(jtag_core PUBLIC bsdl::bsdl)
|
||||||
@@ -32,13 +32,27 @@
|
|||||||
|
|
||||||
#include "script/env.h"
|
#include "script/env.h"
|
||||||
|
|
||||||
#include "bsdl_parser/bsdl_loader.h"
|
#include <bsdl/bsdl.h>
|
||||||
#include "bsdl_parser/bsdl_strings.h"
|
|
||||||
|
|
||||||
#include "drivers/drivers_list.h"
|
#include "drivers/drivers_list.h"
|
||||||
|
|
||||||
/* #include "config_script.h" */
|
/* #include "config_script.h" */
|
||||||
|
|
||||||
|
/* Look up an INSTRUCTION_OPCODE by name. Returns the bit-string (e.g.
|
||||||
|
* "00000000001") or NULL if absent. */
|
||||||
|
static const char * jc_bsdl_opcode(const bsdl_t * b, const char * name)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
if (!b)
|
||||||
|
return NULL;
|
||||||
|
for (i = 0; i < b->instruction_count; i++)
|
||||||
|
{
|
||||||
|
if (b->instructions[i].name && !strcmp(b->instructions[i].name, name))
|
||||||
|
return b->instructions[i].opcode;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
jtag_core * jtagcore_init()
|
jtag_core * jtagcore_init()
|
||||||
{
|
{
|
||||||
jtag_core * jc;
|
jtag_core * jc;
|
||||||
@@ -86,7 +100,7 @@ int jtagcore_scan_and_init_chain(jtag_core * jc)
|
|||||||
{
|
{
|
||||||
if (jc->devices_list[i].bsdl)
|
if (jc->devices_list[i].bsdl)
|
||||||
{
|
{
|
||||||
unload_bsdlfile(jc,jc->devices_list[i].bsdl);
|
bsdl_free(jc->devices_list[i].bsdl);
|
||||||
jc->devices_list[i].bsdl = 0;
|
jc->devices_list[i].bsdl = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -272,12 +286,12 @@ unsigned long jtagcore_get_dev_id(jtag_core * jc,int device)
|
|||||||
|
|
||||||
int jtagcore_loadbsdlfile(jtag_core * jc, char * path, int device)
|
int jtagcore_loadbsdlfile(jtag_core * jc, char * path, int device)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if ( (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0) || device == -1)
|
if ( (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0) || device == -1)
|
||||||
{
|
{
|
||||||
bsdl_file = load_bsdlfile(jc,path);
|
bsdl_file = bsdl_parse_file(path, NULL);
|
||||||
if (bsdl_file)
|
if (bsdl_file)
|
||||||
{
|
{
|
||||||
if (device == -1)
|
if (device == -1)
|
||||||
@@ -288,7 +302,7 @@ int jtagcore_loadbsdlfile(jtag_core * jc, char * path, int device)
|
|||||||
{
|
{
|
||||||
if (jc->devices_list[i].bsdl)
|
if (jc->devices_list[i].bsdl)
|
||||||
{
|
{
|
||||||
unload_bsdlfile(jc,jc->devices_list[i].bsdl);
|
bsdl_free(jc->devices_list[i].bsdl);
|
||||||
jc->devices_list[i].bsdl = 0;
|
jc->devices_list[i].bsdl = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +318,7 @@ int jtagcore_loadbsdlfile(jtag_core * jc, char * path, int device)
|
|||||||
{
|
{
|
||||||
if (jc->devices_list[device].bsdl)
|
if (jc->devices_list[device].bsdl)
|
||||||
{
|
{
|
||||||
unload_bsdlfile(jc,jc->devices_list[device].bsdl);
|
bsdl_free(jc->devices_list[device].bsdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
jc->devices_list[device].bsdl = bsdl_file;
|
jc->devices_list[device].bsdl = bsdl_file;
|
||||||
@@ -316,20 +330,21 @@ int jtagcore_loadbsdlfile(jtag_core * jc, char * path, int device)
|
|||||||
if (jc->devices_list[device].out_boundary_scan)
|
if (jc->devices_list[device].out_boundary_scan)
|
||||||
free(jc->devices_list[device].out_boundary_scan);
|
free(jc->devices_list[device].out_boundary_scan);
|
||||||
|
|
||||||
jc->devices_list[device].in_boundary_scan = malloc(bsdl_file->number_of_chainbits);
|
jc->devices_list[device].in_boundary_scan = malloc(bsdl_file->chain_count);
|
||||||
if (jc->devices_list[device].in_boundary_scan)
|
if (jc->devices_list[device].in_boundary_scan)
|
||||||
memset(jc->devices_list[device].in_boundary_scan, 0, bsdl_file->number_of_chainbits);
|
memset(jc->devices_list[device].in_boundary_scan, 0, bsdl_file->chain_count);
|
||||||
|
|
||||||
jc->devices_list[device].out_boundary_scan = malloc(bsdl_file->number_of_chainbits);
|
jc->devices_list[device].out_boundary_scan = malloc(bsdl_file->chain_count);
|
||||||
if (jc->devices_list[device].out_boundary_scan)
|
if (jc->devices_list[device].out_boundary_scan)
|
||||||
{
|
{
|
||||||
memset(jc->devices_list[device].out_boundary_scan, 0, bsdl_file->number_of_chainbits);
|
size_t bi;
|
||||||
for (i = 0; i < bsdl_file->number_of_chainbits; i++)
|
memset(jc->devices_list[device].out_boundary_scan, 0, bsdl_file->chain_count);
|
||||||
|
for (bi = 0; bi < bsdl_file->chain_count; bi++)
|
||||||
{
|
{
|
||||||
if(bsdl_file->chain_list[i].safe_state == STATE_HIGH)
|
if(bsdl_file->chain[bi].safe == BSDL_STATE_HIGH)
|
||||||
jc->devices_list[device].out_boundary_scan[i] = 0x01;
|
jc->devices_list[device].out_boundary_scan[bi] = 0x01;
|
||||||
else
|
else
|
||||||
jc->devices_list[device].out_boundary_scan[i] = 0x00;
|
jc->devices_list[device].out_boundary_scan[bi] = 0x00;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,18 +361,18 @@ int jtagcore_loadbsdlfile(jtag_core * jc, char * path, int device)
|
|||||||
|
|
||||||
unsigned long jtagcore_get_bsdl_id(jtag_core * jc, char * path, unsigned long * mask)
|
unsigned long jtagcore_get_bsdl_id(jtag_core * jc, char * path, unsigned long * mask)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
unsigned long chip_id;
|
unsigned long chip_id;
|
||||||
|
|
||||||
bsdl_file = load_bsdlfile(jc,path);
|
bsdl_file = bsdl_parse_file(path, NULL);
|
||||||
if (bsdl_file)
|
if (bsdl_file)
|
||||||
{
|
{
|
||||||
chip_id = bsdl_file->chip_id;
|
chip_id = bsdl_file->idcode;
|
||||||
if( mask )
|
if( mask )
|
||||||
{
|
{
|
||||||
*mask = bsdl_file->chip_id_mask;
|
*mask = bsdl_file->idcode_mask;
|
||||||
}
|
}
|
||||||
unload_bsdlfile(jc,bsdl_file);
|
bsdl_free(bsdl_file);
|
||||||
return chip_id;
|
return chip_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +381,7 @@ unsigned long jtagcore_get_bsdl_id(jtag_core * jc, char * path, unsigned long *
|
|||||||
|
|
||||||
int jtagcore_get_dev_name(jtag_core * jc, int device, char * devname, char * bsdlpath)
|
int jtagcore_get_dev_name(jtag_core * jc, int device, char * devname, char * bsdlpath)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
|
|
||||||
if ( device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 )
|
if ( device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 )
|
||||||
{
|
{
|
||||||
@@ -376,7 +391,7 @@ int jtagcore_get_dev_name(jtag_core * jc, int device, char * devname, char * bsd
|
|||||||
|
|
||||||
if(devname)
|
if(devname)
|
||||||
{
|
{
|
||||||
strcpy(devname,bsdl_file->entity_name);
|
strcpy(devname,bsdl_file->entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bsdlpath)
|
if(bsdlpath)
|
||||||
@@ -405,7 +420,7 @@ int jtagcore_get_dev_name(jtag_core * jc, int device, char * devname, char * bsd
|
|||||||
|
|
||||||
int jtagcore_get_number_of_pins(jtag_core * jc, int device)
|
int jtagcore_get_number_of_pins(jtag_core * jc, int device)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
|
|
||||||
if ( device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 )
|
if ( device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 )
|
||||||
{
|
{
|
||||||
@@ -413,7 +428,7 @@ int jtagcore_get_number_of_pins(jtag_core * jc, int device)
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
return bsdl_file->number_of_pins;
|
return (int)bsdl_file->pin_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,7 +437,7 @@ int jtagcore_get_number_of_pins(jtag_core * jc, int device)
|
|||||||
|
|
||||||
int jtagcore_get_pin_properties(jtag_core * jc, int device,int pin,char * pinname,int maxsize,int * type)
|
int jtagcore_get_pin_properties(jtag_core * jc, int device,int pin,char * pinname,int maxsize,int * type)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
int type_code;
|
int type_code;
|
||||||
|
|
||||||
if (device >= jc->nb_of_devices_in_chain ||
|
if (device >= jc->nb_of_devices_in_chain ||
|
||||||
@@ -437,25 +452,25 @@ int jtagcore_get_pin_properties(jtag_core * jc, int device,int pin,char * pinnam
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
if (pin < bsdl_file->number_of_pins )
|
if (pin < (int)bsdl_file->pin_count )
|
||||||
{
|
{
|
||||||
type_code = 0x00;
|
type_code = 0x00;
|
||||||
|
|
||||||
if (pinname)
|
if (pinname)
|
||||||
{
|
{
|
||||||
strncpy(pinname, bsdl_file->pins_list[pin].pinname, maxsize - 1);
|
strncpy(pinname, bsdl_file->pins[pin].name, maxsize - 1);
|
||||||
pinname[maxsize - 1] = '\0';
|
pinname[maxsize - 1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type)
|
if (type)
|
||||||
{
|
{
|
||||||
if (bsdl_file->pins_list[pin].ctrl_bit_number != -1)
|
if (bsdl_file->pins[pin].ctrl_bit != -1)
|
||||||
type_code |= JTAG_CORE_PIN_IS_TRISTATES;
|
type_code |= JTAG_CORE_PIN_IS_TRISTATES;
|
||||||
|
|
||||||
if (bsdl_file->pins_list[pin].out_bit_number != -1)
|
if (bsdl_file->pins[pin].out_bit != -1)
|
||||||
type_code |= JTAG_CORE_PIN_IS_OUTPUT;
|
type_code |= JTAG_CORE_PIN_IS_OUTPUT;
|
||||||
|
|
||||||
if (bsdl_file->pins_list[pin].in_bit_number != -1)
|
if (bsdl_file->pins[pin].in_bit != -1)
|
||||||
type_code |= JTAG_CORE_PIN_IS_INPUT;
|
type_code |= JTAG_CORE_PIN_IS_INPUT;
|
||||||
|
|
||||||
*type = type_code;
|
*type = type_code;
|
||||||
@@ -470,7 +485,7 @@ int jtagcore_get_pin_properties(jtag_core * jc, int device,int pin,char * pinnam
|
|||||||
|
|
||||||
int jtagcore_get_pin_state(jtag_core * jc, int device, int pin, int type)
|
int jtagcore_get_pin_state(jtag_core * jc, int device, int pin, int type)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
int bit_number, ret;
|
int bit_number, ret;
|
||||||
int disable_state;
|
int disable_state;
|
||||||
|
|
||||||
@@ -481,12 +496,12 @@ int jtagcore_get_pin_state(jtag_core * jc, int device, int pin, int type)
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
if (pin < bsdl_file->number_of_pins)
|
if (pin < (int)bsdl_file->pin_count)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case JTAG_CORE_OUTPUT:
|
case JTAG_CORE_OUTPUT:
|
||||||
bit_number = bsdl_file->pins_list[pin].out_bit_number;
|
bit_number = bsdl_file->pins[pin].out_bit;
|
||||||
|
|
||||||
if (bit_number != -1)
|
if (bit_number != -1)
|
||||||
{
|
{
|
||||||
@@ -509,14 +524,14 @@ int jtagcore_get_pin_state(jtag_core * jc, int device, int pin, int type)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case JTAG_CORE_OE:
|
case JTAG_CORE_OE:
|
||||||
bit_number = bsdl_file->pins_list[pin].ctrl_bit_number;
|
bit_number = bsdl_file->pins[pin].ctrl_bit;
|
||||||
|
|
||||||
if (bit_number != -1)
|
if (bit_number != -1)
|
||||||
{
|
{
|
||||||
disable_state = bsdl_file->chain_list[bsdl_file->pins_list[pin].out_bit_number].control_disable_state;
|
disable_state = bsdl_file->chain[bsdl_file->pins[pin].out_bit].disable_state;
|
||||||
if (jc->devices_list[device].scan_mode == JTAG_CORE_EXTEST_SCANMODE)
|
if (jc->devices_list[device].scan_mode == JTAG_CORE_EXTEST_SCANMODE)
|
||||||
{
|
{
|
||||||
if (disable_state == STATE_HIGH)
|
if (disable_state == BSDL_STATE_HIGH)
|
||||||
{
|
{
|
||||||
if (jc->devices_list[device].out_boundary_scan[bit_number])
|
if (jc->devices_list[device].out_boundary_scan[bit_number])
|
||||||
ret = 0x00;
|
ret = 0x00;
|
||||||
@@ -552,7 +567,7 @@ int jtagcore_get_pin_state(jtag_core * jc, int device, int pin, int type)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case JTAG_CORE_INPUT:
|
case JTAG_CORE_INPUT:
|
||||||
bit_number = bsdl_file->pins_list[pin].in_bit_number;
|
bit_number = bsdl_file->pins[pin].in_bit;
|
||||||
|
|
||||||
if (bit_number != -1)
|
if (bit_number != -1)
|
||||||
{
|
{
|
||||||
@@ -572,7 +587,7 @@ int jtagcore_get_pin_state(jtag_core * jc, int device, int pin, int type)
|
|||||||
|
|
||||||
int jtagcore_set_pin_state(jtag_core * jc, int device, int pin, int type,int state)
|
int jtagcore_set_pin_state(jtag_core * jc, int device, int pin, int type,int state)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
int bit_number,ret;
|
int bit_number,ret;
|
||||||
int disable_state;
|
int disable_state;
|
||||||
|
|
||||||
@@ -584,12 +599,12 @@ int jtagcore_set_pin_state(jtag_core * jc, int device, int pin, int type,int sta
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
if (pin < bsdl_file->number_of_pins)
|
if (pin < (int)bsdl_file->pin_count)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case JTAG_CORE_OUTPUT:
|
case JTAG_CORE_OUTPUT:
|
||||||
bit_number = bsdl_file->pins_list[pin].out_bit_number;
|
bit_number = bsdl_file->pins[pin].out_bit;
|
||||||
|
|
||||||
if (bit_number != -1)
|
if (bit_number != -1)
|
||||||
{
|
{
|
||||||
@@ -604,13 +619,13 @@ int jtagcore_set_pin_state(jtag_core * jc, int device, int pin, int type,int sta
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case JTAG_CORE_OE:
|
case JTAG_CORE_OE:
|
||||||
bit_number = bsdl_file->pins_list[pin].ctrl_bit_number;
|
bit_number = bsdl_file->pins[pin].ctrl_bit;
|
||||||
|
|
||||||
if (bit_number != -1)
|
if (bit_number != -1)
|
||||||
{
|
{
|
||||||
disable_state = bsdl_file->chain_list[bsdl_file->pins_list[pin].out_bit_number].control_disable_state;
|
disable_state = bsdl_file->chain[bsdl_file->pins[pin].out_bit].disable_state;
|
||||||
|
|
||||||
if (disable_state == STATE_HIGH)
|
if (disable_state == BSDL_STATE_HIGH)
|
||||||
{
|
{
|
||||||
if (state)
|
if (state)
|
||||||
jc->devices_list[device].out_boundary_scan[bit_number] = 0x00;
|
jc->devices_list[device].out_boundary_scan[bit_number] = 0x00;
|
||||||
@@ -638,7 +653,7 @@ int jtagcore_set_pin_state(jtag_core * jc, int device, int pin, int type,int sta
|
|||||||
|
|
||||||
int jtagcore_get_pin_id(jtag_core * jc, int device, char * pinname)
|
int jtagcore_get_pin_id(jtag_core * jc, int device, char * pinname)
|
||||||
{
|
{
|
||||||
jtag_bsdl * bsdl_file;
|
bsdl_t * bsdl_file;
|
||||||
int pin;
|
int pin;
|
||||||
|
|
||||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && pinname)
|
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && pinname)
|
||||||
@@ -647,11 +662,11 @@ int jtagcore_get_pin_id(jtag_core * jc, int device, char * pinname)
|
|||||||
{
|
{
|
||||||
bsdl_file = jc->devices_list[device].bsdl;
|
bsdl_file = jc->devices_list[device].bsdl;
|
||||||
|
|
||||||
for ( pin = 0; pin < bsdl_file->number_of_pins; pin++)
|
for ( pin = 0; pin < (int)bsdl_file->pin_count; pin++)
|
||||||
{
|
{
|
||||||
if(bsdl_file->pins_list[pin].pinname)
|
if(bsdl_file->pins[pin].name)
|
||||||
{
|
{
|
||||||
if(!strcmp(bsdl_file->pins_list[pin].pinname, pinname))
|
if(!strcmp(bsdl_file->pins[pin].name, pinname))
|
||||||
{
|
{
|
||||||
return pin;
|
return pin;
|
||||||
}
|
}
|
||||||
@@ -702,7 +717,7 @@ int jtagcore_push_and_pop_chain(jtag_core * jc, int mode)
|
|||||||
unsigned char buf_in[512];
|
unsigned char buf_in[512];
|
||||||
int d,i,irlen;
|
int d,i,irlen;
|
||||||
int bit,first_bit,jtag_chain_check_needed;
|
int bit,first_bit,jtag_chain_check_needed;
|
||||||
jtag_bsdl * bsdl;
|
bsdl_t * bsdl;
|
||||||
|
|
||||||
jtag_chain_check_needed = 0;
|
jtag_chain_check_needed = 0;
|
||||||
|
|
||||||
@@ -725,26 +740,26 @@ int jtagcore_push_and_pop_chain(jtag_core * jc, int mode)
|
|||||||
{
|
{
|
||||||
if (d == (jc->nb_of_devices_in_chain - 1)) // Last device in chain ?
|
if (d == (jc->nb_of_devices_in_chain - 1)) // Last device in chain ?
|
||||||
{
|
{
|
||||||
jc->io_functions.drv_TXRX_DATA(jc, jc->devices_list[d].out_boundary_scan, jc->devices_list[d].in_boundary_scan, bsdl->number_of_chainbits - 1);
|
jc->io_functions.drv_TXRX_DATA(jc, jc->devices_list[d].out_boundary_scan, jc->devices_list[d].in_boundary_scan, (int)bsdl->chain_count - 1);
|
||||||
buf_out[0] = jc->devices_list[d].out_boundary_scan[bsdl->number_of_chainbits - 1] | JTAG_STR_TMS;
|
buf_out[0] = jc->devices_list[d].out_boundary_scan[(int)bsdl->chain_count - 1] | JTAG_STR_TMS;
|
||||||
jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, &jc->devices_list[d].in_boundary_scan[bsdl->number_of_chainbits - 1], 1);
|
jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, &jc->devices_list[d].in_boundary_scan[(int)bsdl->chain_count - 1], 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
jc->io_functions.drv_TXRX_DATA(jc, jc->devices_list[d].out_boundary_scan, jc->devices_list[d].in_boundary_scan, bsdl->number_of_chainbits);
|
jc->io_functions.drv_TXRX_DATA(jc, jc->devices_list[d].out_boundary_scan, jc->devices_list[d].in_boundary_scan, (int)bsdl->chain_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the incomming data
|
// Check the incomming data
|
||||||
if(bsdl->number_of_chainbits)
|
if((int)bsdl->chain_count)
|
||||||
{
|
{
|
||||||
first_bit = jc->devices_list[d].in_boundary_scan[0];
|
first_bit = jc->devices_list[d].in_boundary_scan[0];
|
||||||
bit = 0;
|
bit = 0;
|
||||||
while( (bit < bsdl->number_of_chainbits) && (first_bit == jc->devices_list[d].in_boundary_scan[bit]) )
|
while( (bit < (int)bsdl->chain_count) && (first_bit == jc->devices_list[d].in_boundary_scan[bit]) )
|
||||||
{
|
{
|
||||||
bit++;
|
bit++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( bit == bsdl->number_of_chainbits)
|
if( bit == (int)bsdl->chain_count)
|
||||||
{
|
{
|
||||||
// All bits have the same value.
|
// All bits have the same value.
|
||||||
// Program a jtag chain check
|
// Program a jtag chain check
|
||||||
@@ -758,13 +773,13 @@ int jtagcore_push_and_pop_chain(jtag_core * jc, int mode)
|
|||||||
// Write only mode - Ignore incoming chain.
|
// Write only mode - Ignore incoming chain.
|
||||||
if (d == (jc->nb_of_devices_in_chain - 1)) // Last device in chain ?
|
if (d == (jc->nb_of_devices_in_chain - 1)) // Last device in chain ?
|
||||||
{
|
{
|
||||||
jc->io_functions.drv_TXRX_DATA(jc, jc->devices_list[d].out_boundary_scan, 0, bsdl->number_of_chainbits - 1);
|
jc->io_functions.drv_TXRX_DATA(jc, jc->devices_list[d].out_boundary_scan, 0, (int)bsdl->chain_count - 1);
|
||||||
buf_out[0] = jc->devices_list[d].out_boundary_scan[bsdl->number_of_chainbits - 1] | JTAG_STR_TMS;
|
buf_out[0] = jc->devices_list[d].out_boundary_scan[(int)bsdl->chain_count - 1] | JTAG_STR_TMS;
|
||||||
jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, 1);
|
jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
jc->io_functions.drv_TXRX_DATA(jc, jc->devices_list[d].out_boundary_scan, 0, bsdl->number_of_chainbits);
|
jc->io_functions.drv_TXRX_DATA(jc, jc->devices_list[d].out_boundary_scan, 0, (int)bsdl->chain_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -878,32 +893,36 @@ int jtagcore_push_and_pop_chain(jtag_core * jc, int mode)
|
|||||||
bsdl = jc->devices_list[d].bsdl;
|
bsdl = jc->devices_list[d].bsdl;
|
||||||
if ( bsdl )
|
if ( bsdl )
|
||||||
{
|
{
|
||||||
switch ( jc->devices_list[d].scan_mode )
|
|
||||||
{
|
{
|
||||||
case JTAG_CORE_SAMPLE_SCANMODE:
|
const char *opcode = NULL;
|
||||||
for (i = 0; i < bsdl->number_of_bits_per_instruction; i++)
|
switch ( jc->devices_list[d].scan_mode )
|
||||||
|
{
|
||||||
|
case JTAG_CORE_SAMPLE_SCANMODE:
|
||||||
|
opcode = jc_bsdl_opcode(bsdl, "SAMPLE");
|
||||||
|
break;
|
||||||
|
case JTAG_CORE_EXTEST_SCANMODE:
|
||||||
|
opcode = jc_bsdl_opcode(bsdl, "EXTEST");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (opcode)
|
||||||
|
{
|
||||||
|
for (i = 0; i < bsdl->instruction_length; i++)
|
||||||
{
|
{
|
||||||
buf_out[(bsdl->number_of_bits_per_instruction - 1) - i] = bsdl->SAMPLE_Instruction[i] - '0';
|
buf_out[(bsdl->instruction_length - 1) - i] = opcode[i] - '0';
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case JTAG_CORE_EXTEST_SCANMODE:
|
|
||||||
for (i = 0; i < bsdl->number_of_bits_per_instruction; i++)
|
|
||||||
{
|
|
||||||
buf_out[(bsdl->number_of_bits_per_instruction - 1) - i] = bsdl->EXTEST_Instruction[i] - '0';
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (d == (jc->nb_of_devices_in_chain - 1)) // Last device in chain ?
|
if (d == (jc->nb_of_devices_in_chain - 1)) // Last device in chain ?
|
||||||
{
|
{
|
||||||
jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, bsdl->number_of_bits_per_instruction - 1);
|
jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, bsdl->instruction_length - 1);
|
||||||
buf_out[0] = buf_out[bsdl->number_of_bits_per_instruction - 1] | JTAG_STR_TMS;
|
buf_out[0] = buf_out[bsdl->instruction_length - 1] | JTAG_STR_TMS;
|
||||||
jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, 1);
|
jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, bsdl->number_of_bits_per_instruction);
|
jc->io_functions.drv_TXRX_DATA(jc, (unsigned char *)&buf_out, 0, bsdl->instruction_length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -921,7 +940,7 @@ int jtagcore_push_and_pop_chain(jtag_core * jc, int mode)
|
|||||||
if ( jc->devices_list[0].bsdl )
|
if ( jc->devices_list[0].bsdl )
|
||||||
{
|
{
|
||||||
bsdl = jc->devices_list[0].bsdl;
|
bsdl = jc->devices_list[0].bsdl;
|
||||||
irlen = jc->total_IR_lenght - bsdl->number_of_bits_per_instruction;
|
irlen = jc->total_IR_lenght - bsdl->instruction_length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -929,7 +948,7 @@ int jtagcore_push_and_pop_chain(jtag_core * jc, int mode)
|
|||||||
if ( jc->devices_list[1].bsdl )
|
if ( jc->devices_list[1].bsdl )
|
||||||
{
|
{
|
||||||
bsdl = jc->devices_list[1].bsdl;
|
bsdl = jc->devices_list[1].bsdl;
|
||||||
irlen = jc->total_IR_lenght - bsdl->number_of_bits_per_instruction;
|
irlen = jc->total_IR_lenght - bsdl->instruction_length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "program.h"
|
#include "program.h"
|
||||||
#include "svf/svf.h"
|
#include "svf/svf_glue.h"
|
||||||
#include "arm_debug/arm_debug.h"
|
#include "arm_debug/arm_debug.h"
|
||||||
|
|
||||||
/* program_log_fn, svf_log_fn and arm_log_fn are the same shape
|
/* program_log_fn, svf_log_fn and arm_log_fn are the same shape
|
||||||
@@ -17,7 +17,7 @@ int program_dispatch(jtag_core *jc, const jtag_target *t, const char *file,
|
|||||||
|
|
||||||
switch (t->prog) {
|
switch (t->prog) {
|
||||||
case TARGET_PROG_SVF:
|
case TARGET_PROG_SVF:
|
||||||
return svf_play_file(jc, file, (svf_log_fn)log, user, NULL);
|
return bs_svf_play(jc, file, (svf_log_fn)log, user, NULL);
|
||||||
|
|
||||||
case TARGET_PROG_ARM_FLASH:
|
case TARGET_PROG_ARM_FLASH:
|
||||||
return arm_flash_program(jc, t, file, (arm_log_fn)log, user);
|
return arm_flash_program(jc, t, file, (arm_log_fn)log, user);
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ include_directories(${DIR_MODULES})
|
|||||||
include_directories(${DIR_LIBS})
|
include_directories(${DIR_LIBS})
|
||||||
|
|
||||||
add_library(script ${ALL_SOURCES})
|
add_library(script ${ALL_SOURCES})
|
||||||
|
target_link_libraries(script PUBLIC bsdl::bsdl svf)
|
||||||
|
|||||||
@@ -35,12 +35,12 @@
|
|||||||
#include "jtag_core/jtag_core.h"
|
#include "jtag_core/jtag_core.h"
|
||||||
#include "config/version.h"
|
#include "config/version.h"
|
||||||
|
|
||||||
#include "bsdl_parser/bsdl_loader.h"
|
#include <bsdl/bsdl.h>
|
||||||
#include "os_interface/os_interface.h"
|
#include "os_interface/os_interface.h"
|
||||||
#include "target/target.h"
|
#include "target/target.h"
|
||||||
#include "probes/probes.h"
|
#include "probes/probes.h"
|
||||||
#include "bscan/bscan.h"
|
#include "bscan/bscan.h"
|
||||||
#include "svf/svf.h"
|
#include "svf/svf_glue.h"
|
||||||
#include "program/program.h"
|
#include "program/program.h"
|
||||||
#include "arm_debug/arm_debug.h"
|
#include "arm_debug/arm_debug.h"
|
||||||
#include "spi_flash/spi_flash.h"
|
#include "spi_flash/spi_flash.h"
|
||||||
@@ -3546,7 +3546,7 @@ static int cmd_svf_play(script_ctx *ctx, char *line)
|
|||||||
ctx->script_printf(ctx, MSG_ERROR, "Usage: svf_play <file>\n");
|
ctx->script_printf(ctx, MSG_ERROR, "Usage: svf_play <file>\n");
|
||||||
return JTAG_CORE_BAD_PARAMETER;
|
return JTAG_CORE_BAD_PARAMETER;
|
||||||
}
|
}
|
||||||
if (svf_play_file(jc, path, svf_log_cb, ctx, NULL) < 0)
|
if (bs_svf_play(jc, path, svf_log_cb, ctx, NULL) < 0)
|
||||||
return JTAG_CORE_ACCESS_ERROR;
|
return JTAG_CORE_ACCESS_ERROR;
|
||||||
return JTAG_CORE_NO_ERROR;
|
return JTAG_CORE_NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|
||||||
file(GLOB_RECURSE ALL_SOURCES "*.c")
|
|
||||||
|
|
||||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||||
|
|
||||||
add_library(svf ${ALL_SOURCES})
|
# Glue over libsvf (FetchContent'd at top level): bscan_* backed JTAG port.
|
||||||
|
add_library(svf svf_glue.c)
|
||||||
|
target_link_libraries(svf PUBLIC svf::svf)
|
||||||
|
|||||||
@@ -1,447 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "bscan/bscan.h"
|
|
||||||
#include "svf.h"
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ *
|
|
||||||
* Player state
|
|
||||||
* ------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
jtag_core *jc;
|
|
||||||
svf_log_fn log;
|
|
||||||
void *user;
|
|
||||||
long line; /* 1-based, for diagnostics */
|
|
||||||
svf_stats stats;
|
|
||||||
|
|
||||||
/* Sticky TDI / MASK per scan type ([0] = DR, [1] = IR). TDO is not
|
|
||||||
* sticky: a compare happens only when TDO is given on that scan. */
|
|
||||||
struct {
|
|
||||||
int len;
|
|
||||||
uint8_t *tdi;
|
|
||||||
uint8_t *mask;
|
|
||||||
} st[2];
|
|
||||||
} svf_player;
|
|
||||||
|
|
||||||
static void slog(svf_player *p, int is_error, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
char buf[256];
|
|
||||||
va_list ap;
|
|
||||||
if (!p->log) return;
|
|
||||||
va_start(ap, fmt);
|
|
||||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
|
||||||
va_end(ap);
|
|
||||||
p->log(p->user, is_error, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ *
|
|
||||||
* Hex / token helpers
|
|
||||||
* ------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
static int hexval(int c)
|
|
||||||
{
|
|
||||||
if (c >= '0' && c <= '9') return c - '0';
|
|
||||||
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
|
||||||
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse `hexlen` chars of hex (whitespace allowed) representing `nbits`
|
|
||||||
* bits, LSB shifted first, into buf (LSB-first per byte, as the bscan_*
|
|
||||||
* shifters expect). Returns 0, or -1 on a stray character. */
|
|
||||||
static int parse_hex_bits(const char *hex, int hexlen, int nbits, uint8_t *buf)
|
|
||||||
{
|
|
||||||
int nbytes = (nbits + 7) / 8;
|
|
||||||
int i, nib = 0;
|
|
||||||
|
|
||||||
memset(buf, 0, (size_t)nbytes);
|
|
||||||
for (i = hexlen - 1; i >= 0; i--) {
|
|
||||||
int v;
|
|
||||||
char c = hex[i];
|
|
||||||
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
|
|
||||||
continue;
|
|
||||||
v = hexval((unsigned char)c);
|
|
||||||
if (v < 0) return -1;
|
|
||||||
if (v) {
|
|
||||||
int k;
|
|
||||||
for (k = 0; k < 4; k++) {
|
|
||||||
int bit = nib * 4 + k;
|
|
||||||
if (bit < nbits && (v & (1 << k)))
|
|
||||||
buf[bit / 8] |= (uint8_t)(1u << (bit & 7));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nib++;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct { const char *p, *end; } svf_cur;
|
|
||||||
|
|
||||||
enum { TK_END = 0, TK_WORD, TK_HEX };
|
|
||||||
|
|
||||||
/* Next token: TK_WORD copies into word[wordsz]; TK_HEX returns a pointer
|
|
||||||
* and length into the source (no copy — bodies can be large). */
|
|
||||||
static int svf_next(svf_cur *c, char *word, int wordsz,
|
|
||||||
const char **hp, int *hlen)
|
|
||||||
{
|
|
||||||
while (c->p < c->end &&
|
|
||||||
(*c->p == ' ' || *c->p == '\t' || *c->p == '\r' || *c->p == '\n'))
|
|
||||||
c->p++;
|
|
||||||
if (c->p >= c->end) return TK_END;
|
|
||||||
|
|
||||||
if (*c->p == '(') {
|
|
||||||
const char *start = ++c->p;
|
|
||||||
while (c->p < c->end && *c->p != ')') c->p++;
|
|
||||||
*hp = start;
|
|
||||||
*hlen = (int)(c->p - start);
|
|
||||||
if (c->p < c->end) c->p++; /* skip ')' */
|
|
||||||
return TK_HEX;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
int n = 0;
|
|
||||||
while (c->p < c->end && *c->p != ' ' && *c->p != '\t' &&
|
|
||||||
*c->p != '\r' && *c->p != '\n' && *c->p != '(') {
|
|
||||||
if (n < wordsz - 1) word[n++] = *c->p;
|
|
||||||
c->p++;
|
|
||||||
}
|
|
||||||
word[n] = '\0';
|
|
||||||
}
|
|
||||||
return TK_WORD;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ci_eq(const char *a, const char *b)
|
|
||||||
{
|
|
||||||
while (*a && *b) {
|
|
||||||
int ca = *a, cb = *b;
|
|
||||||
if (ca >= 'a' && ca <= 'z') ca -= 32;
|
|
||||||
if (cb >= 'a' && cb <= 'z') cb -= 32;
|
|
||||||
if (ca != cb) return 0;
|
|
||||||
a++; b++;
|
|
||||||
}
|
|
||||||
return *a == *b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ *
|
|
||||||
* Commands
|
|
||||||
* ------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
/* SIR / SDR: shift IR/DR with optional masked TDO compare. */
|
|
||||||
static int do_scan(svf_player *p, int is_ir, svf_cur *c)
|
|
||||||
{
|
|
||||||
char word[64];
|
|
||||||
const char *hex;
|
|
||||||
int hlen, t;
|
|
||||||
int len = -1;
|
|
||||||
int nbytes;
|
|
||||||
uint8_t *tdi = NULL, *tdo = NULL, *mask = NULL, *cap = NULL;
|
|
||||||
int have_tdi = 0, have_tdo = 0, have_mask = 0;
|
|
||||||
int idx = is_ir ? 1 : 0;
|
|
||||||
int rc = -1, i;
|
|
||||||
|
|
||||||
/* length */
|
|
||||||
if (svf_next(c, word, sizeof(word), &hex, &hlen) != TK_WORD) {
|
|
||||||
slog(p, 1, "line %ld: %s missing length", p->line, is_ir ? "SIR" : "SDR");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
len = atoi(word);
|
|
||||||
if (len <= 0) {
|
|
||||||
slog(p, 1, "line %ld: %s bad length '%s'", p->line, is_ir ? "SIR" : "SDR", word);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
nbytes = (len + 7) / 8;
|
|
||||||
|
|
||||||
/* fields */
|
|
||||||
while ((t = svf_next(c, word, sizeof(word), &hex, &hlen)) != TK_END) {
|
|
||||||
const char *fld = word;
|
|
||||||
uint8_t **dst;
|
|
||||||
int *flag;
|
|
||||||
if (t != TK_WORD) goto out;
|
|
||||||
if (ci_eq(fld, "TDI")) { dst = &tdi; flag = &have_tdi; }
|
|
||||||
else if (ci_eq(fld, "TDO")) { dst = &tdo; flag = &have_tdo; }
|
|
||||||
else if (ci_eq(fld, "MASK")) { dst = &mask; flag = &have_mask; }
|
|
||||||
else if (ci_eq(fld, "SMASK")) { dst = NULL; flag = NULL; }
|
|
||||||
else { slog(p, 1, "line %ld: unexpected '%s' in scan", p->line, fld); goto out; }
|
|
||||||
|
|
||||||
if (svf_next(c, word, sizeof(word), &hex, &hlen) != TK_HEX) {
|
|
||||||
slog(p, 1, "line %ld: '%s' without (hex)", p->line, fld);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if (!dst) continue; /* SMASK: parsed, ignored */
|
|
||||||
*dst = malloc((size_t)nbytes);
|
|
||||||
if (!*dst) { slog(p, 1, "out of memory"); goto out; }
|
|
||||||
if (parse_hex_bits(hex, hlen, len, *dst) < 0) {
|
|
||||||
slog(p, 1, "line %ld: bad hex in %s", p->line, fld);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
*flag = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Resolve sticky TDI: reuse last value of same length when omitted. */
|
|
||||||
if (!have_tdi) {
|
|
||||||
if (p->st[idx].tdi && p->st[idx].len == len) {
|
|
||||||
tdi = malloc((size_t)nbytes);
|
|
||||||
if (!tdi) { slog(p, 1, "out of memory"); goto out; }
|
|
||||||
memcpy(tdi, p->st[idx].tdi, (size_t)nbytes);
|
|
||||||
} else {
|
|
||||||
tdi = calloc(1, (size_t)nbytes); /* default: shift zeros */
|
|
||||||
if (!tdi) { slog(p, 1, "out of memory"); goto out; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Resolve sticky MASK when a compare is wanted but no MASK given. */
|
|
||||||
if (have_tdo && !have_mask) {
|
|
||||||
mask = malloc((size_t)nbytes);
|
|
||||||
if (!mask) { slog(p, 1, "out of memory"); goto out; }
|
|
||||||
if (p->st[idx].mask && p->st[idx].len == len)
|
|
||||||
memcpy(mask, p->st[idx].mask, (size_t)nbytes);
|
|
||||||
else
|
|
||||||
memset(mask, 0xFF, (size_t)nbytes); /* default: all care */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Shift. */
|
|
||||||
if (have_tdo) {
|
|
||||||
cap = calloc(1, (size_t)nbytes);
|
|
||||||
if (!cap) { slog(p, 1, "out of memory"); goto out; }
|
|
||||||
}
|
|
||||||
if ((is_ir ? bscan_shift_ir(p->jc, tdi, cap, len)
|
|
||||||
: bscan_shift_dr(p->jc, tdi, cap, len)) < 0) {
|
|
||||||
slog(p, 1, "line %ld: shift %s failed (probe ok?)", p->line, is_ir ? "IR" : "DR");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
p->stats.scans++;
|
|
||||||
|
|
||||||
/* Masked compare. */
|
|
||||||
if (have_tdo) {
|
|
||||||
p->stats.compares++;
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
int m = (mask[i / 8] >> (i & 7)) & 1u;
|
|
||||||
if (!m) continue;
|
|
||||||
if (((cap[i / 8] >> (i & 7)) & 1u) != ((tdo[i / 8] >> (i & 7)) & 1u)) {
|
|
||||||
slog(p, 1, "line %ld: %s TDO mismatch at bit %d (len %d)",
|
|
||||||
p->line, is_ir ? "SIR" : "SDR", i, len);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update sticky state. */
|
|
||||||
if (have_tdi || p->st[idx].len != len) {
|
|
||||||
free(p->st[idx].tdi);
|
|
||||||
p->st[idx].tdi = malloc((size_t)nbytes);
|
|
||||||
if (p->st[idx].tdi) memcpy(p->st[idx].tdi, tdi, (size_t)nbytes);
|
|
||||||
}
|
|
||||||
if (have_mask) {
|
|
||||||
free(p->st[idx].mask);
|
|
||||||
p->st[idx].mask = malloc((size_t)nbytes);
|
|
||||||
if (p->st[idx].mask) memcpy(p->st[idx].mask, mask, (size_t)nbytes);
|
|
||||||
}
|
|
||||||
p->st[idx].len = len;
|
|
||||||
|
|
||||||
rc = 0;
|
|
||||||
out:
|
|
||||||
free(tdi); free(tdo); free(mask); free(cap);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* HIR/HDR/TIR/TDR: header/trailer bits. Single-device only -> must be 0. */
|
|
||||||
static int do_header(svf_player *p, const char *kw, svf_cur *c)
|
|
||||||
{
|
|
||||||
char word[64];
|
|
||||||
const char *hex; int hlen, t, len;
|
|
||||||
|
|
||||||
if (svf_next(c, word, sizeof(word), &hex, &hlen) != TK_WORD) {
|
|
||||||
slog(p, 1, "line %ld: %s missing length", p->line, kw);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
len = atoi(word);
|
|
||||||
if (len != 0) {
|
|
||||||
slog(p, 1, "line %ld: %s %d — multi-device chains not supported",
|
|
||||||
p->line, kw, len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
/* drain any TDI()/TDO()/... that may accompany a 0-length header */
|
|
||||||
while ((t = svf_next(c, word, sizeof(word), &hex, &hlen)) != TK_END)
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int do_endstate(svf_player *p, const char *kw, svf_cur *c)
|
|
||||||
{
|
|
||||||
char word[64]; const char *hex; int hlen;
|
|
||||||
if (svf_next(c, word, sizeof(word), &hex, &hlen) != TK_WORD) {
|
|
||||||
slog(p, 1, "line %ld: %s missing state", p->line, kw);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!ci_eq(word, "IDLE")) {
|
|
||||||
slog(p, 1, "line %ld: %s %s — only IDLE end state supported",
|
|
||||||
p->line, kw, word);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0; /* scans already finish in Run-Test/Idle */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int do_state(svf_player *p, svf_cur *c)
|
|
||||||
{
|
|
||||||
char word[64]; const char *hex; int hlen, t;
|
|
||||||
int want_reset = 0, only_idle = 1;
|
|
||||||
|
|
||||||
while ((t = svf_next(c, word, sizeof(word), &hex, &hlen)) != TK_END) {
|
|
||||||
if (t != TK_WORD) continue;
|
|
||||||
if (ci_eq(word, "RESET")) want_reset = 1;
|
|
||||||
else if (ci_eq(word, "IDLE")) /* ok */;
|
|
||||||
else only_idle = 0;
|
|
||||||
}
|
|
||||||
if (want_reset)
|
|
||||||
return bscan_tap_reset(p->jc);
|
|
||||||
if (only_idle)
|
|
||||||
return 0; /* already in Idle between commands */
|
|
||||||
slog(p, 1, "line %ld: STATE — only RESET / IDLE supported", p->line);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int do_runtest(svf_player *p, svf_cur *c)
|
|
||||||
{
|
|
||||||
char word[64]; const char *hex; int hlen, t;
|
|
||||||
long cycles = 0;
|
|
||||||
double secs = 0.0;
|
|
||||||
char pending[64];
|
|
||||||
int have_pending = 0;
|
|
||||||
|
|
||||||
while ((t = svf_next(c, word, sizeof(word), &hex, &hlen)) != TK_END) {
|
|
||||||
if (t != TK_WORD) continue;
|
|
||||||
if (have_pending && (ci_eq(word, "TCK") || ci_eq(word, "SCK"))) {
|
|
||||||
cycles = atol(pending);
|
|
||||||
have_pending = 0;
|
|
||||||
} else if (have_pending && ci_eq(word, "SEC")) {
|
|
||||||
secs = atof(pending);
|
|
||||||
have_pending = 0;
|
|
||||||
} else if (word[0] == '.' || (word[0] >= '0' && word[0] <= '9')) {
|
|
||||||
strncpy(pending, word, sizeof(pending) - 1);
|
|
||||||
pending[sizeof(pending) - 1] = '\0';
|
|
||||||
have_pending = 1;
|
|
||||||
} else {
|
|
||||||
have_pending = 0; /* MAXIMUM / ENDSTATE / state names, etc. */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (cycles > 0) {
|
|
||||||
int chunk = (cycles > 1000000) ? 1000000 : (int)cycles;
|
|
||||||
if (bscan_idle_cycles(p->jc, chunk) < 0) {
|
|
||||||
slog(p, 1, "line %ld: RUNTEST idle failed", p->line);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
cycles -= chunk;
|
|
||||||
}
|
|
||||||
if (secs > 0.0) {
|
|
||||||
if (secs > 60.0) secs = 60.0; /* sanity cap */
|
|
||||||
usleep((useconds_t)(secs * 1e6));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ *
|
|
||||||
* Top-level
|
|
||||||
* ------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
/* Blank out '!' and '//' comments to end-of-line (keep newlines). */
|
|
||||||
static void strip_comments(char *buf, long len)
|
|
||||||
{
|
|
||||||
long i;
|
|
||||||
for (i = 0; i < len; i++) {
|
|
||||||
if (buf[i] == '!' || (buf[i] == '/' && i + 1 < len && buf[i + 1] == '/')) {
|
|
||||||
while (i < len && buf[i] != '\n') buf[i++] = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dispatch(svf_player *p, char *cmd, long cmdlen)
|
|
||||||
{
|
|
||||||
svf_cur c;
|
|
||||||
char kw[64];
|
|
||||||
const char *hex; int hlen;
|
|
||||||
|
|
||||||
c.p = cmd; c.end = cmd + cmdlen;
|
|
||||||
if (svf_next(&c, kw, sizeof(kw), &hex, &hlen) != TK_WORD)
|
|
||||||
return 0; /* blank */
|
|
||||||
|
|
||||||
p->stats.commands++;
|
|
||||||
|
|
||||||
if (ci_eq(kw, "SDR")) return do_scan(p, 0, &c);
|
|
||||||
else if (ci_eq(kw, "SIR")) return do_scan(p, 1, &c);
|
|
||||||
else if (ci_eq(kw, "RUNTEST")) return do_runtest(p, &c);
|
|
||||||
else if (ci_eq(kw, "STATE")) return do_state(p, &c);
|
|
||||||
else if (ci_eq(kw, "ENDIR") || ci_eq(kw, "ENDDR")) return do_endstate(p, kw, &c);
|
|
||||||
else if (ci_eq(kw, "HIR") || ci_eq(kw, "HDR") ||
|
|
||||||
ci_eq(kw, "TIR") || ci_eq(kw, "TDR")) return do_header(p, kw, &c);
|
|
||||||
else if (ci_eq(kw, "TRST") || ci_eq(kw, "FREQUENCY"))
|
|
||||||
return 0; /* accepted; not acted on (single-device, clock set at open) */
|
|
||||||
|
|
||||||
slog(p, 1, "line %ld: unsupported command '%s'", p->line, kw);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int svf_play_file(jtag_core *jc, const char *path,
|
|
||||||
svf_log_fn log, void *user, svf_stats *stats)
|
|
||||||
{
|
|
||||||
FILE *f;
|
|
||||||
long size, i, cmd_start;
|
|
||||||
char *buf;
|
|
||||||
svf_player p;
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
memset(&p, 0, sizeof(p));
|
|
||||||
p.jc = jc; p.log = log; p.user = user; p.line = 1;
|
|
||||||
|
|
||||||
f = fopen(path, "rb");
|
|
||||||
if (!f) { slog(&p, 1, "cannot open %s", path); return -1; }
|
|
||||||
if (fseek(f, 0, SEEK_END) != 0) { fclose(f); return -1; }
|
|
||||||
size = ftell(f);
|
|
||||||
if (size <= 0) { fclose(f); slog(&p, 1, "empty file"); return -1; }
|
|
||||||
rewind(f);
|
|
||||||
buf = malloc((size_t)size + 1);
|
|
||||||
if (!buf) { fclose(f); slog(&p, 1, "out of memory"); return -1; }
|
|
||||||
if (fread(buf, 1, (size_t)size, f) != (size_t)size) {
|
|
||||||
free(buf); fclose(f); slog(&p, 1, "read error"); return -1;
|
|
||||||
}
|
|
||||||
buf[size] = '\0';
|
|
||||||
fclose(f);
|
|
||||||
|
|
||||||
strip_comments(buf, size);
|
|
||||||
|
|
||||||
/* Warm up the link before the first real scan: the FTDI MPSSE's first
|
|
||||||
* data read after a fresh open returns stale FIFO content. The normal
|
|
||||||
* Viveris flow hides this (jtag_scan/autoinit runs first); do a
|
|
||||||
* throwaway reset + DR read so a standalone svf_play is reliable. */
|
|
||||||
{
|
|
||||||
uint8_t junk[4];
|
|
||||||
bscan_tap_reset(jc);
|
|
||||||
bscan_shift_dr(jc, NULL, junk, 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Split on ';' and dispatch each command, tracking the line number. */
|
|
||||||
cmd_start = 0;
|
|
||||||
for (i = 0; i < size; i++) {
|
|
||||||
if (buf[i] == '\n') p.line++;
|
|
||||||
if (buf[i] == ';') {
|
|
||||||
rc = dispatch(&p, buf + cmd_start, i - cmd_start);
|
|
||||||
if (rc < 0) break;
|
|
||||||
cmd_start = i + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
free(p.st[0].tdi); free(p.st[0].mask);
|
|
||||||
free(p.st[1].tdi); free(p.st[1].mask);
|
|
||||||
|
|
||||||
if (stats) *stats = p.stats;
|
|
||||||
if (rc == 0)
|
|
||||||
slog(&p, 0, "SVF done: %ld commands, %ld scans, %ld compares",
|
|
||||||
p.stats.commands, p.stats.scans, p.stats.compares);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#ifndef _SVF_H
|
|
||||||
#define _SVF_H
|
|
||||||
|
|
||||||
#include "jtag_core/jtag_core.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SVF player (single-device chain).
|
|
||||||
*
|
|
||||||
* Plays a standard subset of Serial Vector Format over the currently
|
|
||||||
* open probe, using the bscan_* TAP primitives. SVF is what Libero,
|
|
||||||
* Diamond/Radiant, Vivado, … export with the vendor programming
|
|
||||||
* algorithm already baked in, so one player programs many targets with
|
|
||||||
* no per-vendor code.
|
|
||||||
*
|
|
||||||
* Supported: SIR / SDR with TDI/TDO/MASK/SMASK and a masked TDO compare;
|
|
||||||
* RUNTEST (TCK/SCK counts and SEC delays); STATE (RESET / IDLE);
|
|
||||||
* ENDIR / ENDDR (IDLE only); HIR/HDR/TIR/TDR (length 0 only); TRST;
|
|
||||||
* FREQUENCY. SMASK is parsed but not applied.
|
|
||||||
*
|
|
||||||
* Not supported (single-device tool): non-zero header/trailer scans
|
|
||||||
* (multi-device chains) and non-IDLE stable end states — both rejected
|
|
||||||
* with a clear error.
|
|
||||||
*
|
|
||||||
* log() receives progress / error lines (is_error != 0 on failure).
|
|
||||||
* Returns 0 on success, < 0 on parse error or a TDO compare mismatch.
|
|
||||||
* stats may be NULL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef void (*svf_log_fn)(void *user, int is_error, const char *msg);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
long commands; /* commands executed */
|
|
||||||
long scans; /* SIR + SDR */
|
|
||||||
long compares; /* TDO compares performed */
|
|
||||||
} svf_stats;
|
|
||||||
|
|
||||||
int svf_play_file(jtag_core *jc, const char *path,
|
|
||||||
svf_log_fn log, void *user, svf_stats *stats);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
58
src/modules/svf/svf_glue.c
Normal file
58
src/modules/svf/svf_glue.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* bs_explorer glue for libsvf: maps the svf_jtag_ops port onto the
|
||||||
|
* bscan_* TAP primitives.
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "svf_glue.h"
|
||||||
|
#include "bscan/bscan.h"
|
||||||
|
|
||||||
|
static int ops_tap_reset(void *ctx)
|
||||||
|
{
|
||||||
|
return bscan_tap_reset((jtag_core *)ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ops_shift_ir(void *ctx, const uint8_t *tdi, uint8_t *tdo, int nbits)
|
||||||
|
{
|
||||||
|
return bscan_shift_ir((jtag_core *)ctx, tdi, tdo, nbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ops_shift_dr(void *ctx, const uint8_t *tdi, uint8_t *tdo, int nbits)
|
||||||
|
{
|
||||||
|
return bscan_shift_dr((jtag_core *)ctx, tdi, tdo, nbits);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ops_idle_cycles(void *ctx, int ncycles)
|
||||||
|
{
|
||||||
|
return bscan_idle_cycles((jtag_core *)ctx, ncycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ops_delay_us(void *ctx, unsigned long us)
|
||||||
|
{
|
||||||
|
(void)ctx;
|
||||||
|
usleep((useconds_t)us);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const svf_jtag_ops bscan_svf_ops = {
|
||||||
|
.tap_reset = ops_tap_reset,
|
||||||
|
.shift_ir = ops_shift_ir,
|
||||||
|
.shift_dr = ops_shift_dr,
|
||||||
|
.idle_cycles = ops_idle_cycles,
|
||||||
|
.delay_us = ops_delay_us,
|
||||||
|
};
|
||||||
|
|
||||||
|
int bs_svf_play(jtag_core *jc, const char *path,
|
||||||
|
svf_log_fn log, void *user, svf_stats *stats)
|
||||||
|
{
|
||||||
|
/* Warm up the link before the first real scan: the FTDI MPSSE's first
|
||||||
|
* data read after a fresh open returns stale FIFO content. The normal
|
||||||
|
* Viveris flow hides this (jtag_scan/autoinit runs first); do a
|
||||||
|
* throwaway reset + DR read so a standalone svf_play is reliable. */
|
||||||
|
uint8_t junk[4];
|
||||||
|
bscan_tap_reset(jc);
|
||||||
|
bscan_shift_dr(jc, NULL, junk, 32);
|
||||||
|
|
||||||
|
return svf_play_file(&bscan_svf_ops, jc, path, log, user, stats);
|
||||||
|
}
|
||||||
20
src/modules/svf/svf_glue.h
Normal file
20
src/modules/svf/svf_glue.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* bs_explorer glue for libsvf: plays SVF through the bscan_* TAP
|
||||||
|
* primitives of the currently open probe.
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SVF_GLUE_H
|
||||||
|
#define _SVF_GLUE_H
|
||||||
|
|
||||||
|
#include <svf/svf.h>
|
||||||
|
|
||||||
|
#include "jtag_core/jtag_core.h"
|
||||||
|
|
||||||
|
/* Plays `path` over the probe held by `jc` (single-device chain).
|
||||||
|
* Warms the link up first (stale-FIFO probes like FTDI MPSSE).
|
||||||
|
* Returns 0 on success, < 0 on error; stats may be NULL. */
|
||||||
|
int bs_svf_play(jtag_core *jc, const char *path,
|
||||||
|
svf_log_fn log, void *user, svf_stats *stats);
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user