restructure: code+libs under src/, runtime resources under data/
Separate the two concerns the repo root was mixing:
- src/ — bs/, modules/, libs/ (code + vendored libs)
- data/ — fpga_registry.yaml, probes.yaml, bsdl_files/, bscan_proxies/,
scripts/ (everything the tool reads at runtime, CWD-relative)
- doc/ — kept at the root
CMake: repoint DIR_MODULES/DIR_LIBS and add_subdirectory at src/; emit
the binary at the build/ root (build/bs) via CMAKE_RUNTIME_OUTPUT_DIRECTORY
instead of the nested build/src/bs/. The jtag_core ../../libs path still
resolves since modules and libs moved together.
Runtime default paths now point under data/ (fpga.c, probes.c, script.c
bsdl_files lookup, init.c config.script). Docs (README/tutorial/CLAUDE)
updated for the new layout, src/ module paths, and ./build/bs.
Validated on the IGLOO2/FlashPro: profiles, autoinit, and svf_play all
work run from the repo root.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
15
src/bs/CMakeLists.txt
Normal file
15
src/bs/CMakeLists.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
file(GLOB_RECURSE ALL_SOURCES "*.c")
|
||||
|
||||
# Application configuration
|
||||
add_executable(
|
||||
bs
|
||||
${ALL_SOURCES}
|
||||
)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../modules)
|
||||
|
||||
# linking configuration
|
||||
target_link_libraries(
|
||||
bs PRIVATE ${BS_MODULES} readline ncurses
|
||||
)
|
||||
101
src/bs/init.c
Normal file
101
src/bs/init.c
Normal file
@@ -0,0 +1,101 @@
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
#include "config/version.h"
|
||||
#include "script/env.h"
|
||||
#include "script/script.h"
|
||||
#include "config/config_script.h"
|
||||
|
||||
#include "init.h"
|
||||
|
||||
void jprint(jtag_core *jc, const char *msg)
|
||||
{
|
||||
fputs(msg, stdout);
|
||||
}
|
||||
|
||||
int script_print(script_ctx *sctx, enum MSGTYPE typ, char *string, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
const char *prefix = "";
|
||||
va_list args;
|
||||
|
||||
switch (typ)
|
||||
{
|
||||
case MSG_DEBUG: prefix = "DEBUG : "; break;
|
||||
case MSG_INFO_1: prefix = "INFO : "; break;
|
||||
case MSG_WARNING: prefix = "WARNING : "; break;
|
||||
case MSG_ERROR: prefix = "ERROR : "; break;
|
||||
case MSG_INFO_0:
|
||||
default: prefix = ""; break;
|
||||
}
|
||||
|
||||
va_start(args, string);
|
||||
ret = fputs(prefix, stdout);
|
||||
ret += vprintf(string, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void bsexp_init(jtag_core **jc, script_ctx **sctx)
|
||||
{
|
||||
*jc = jtagcore_init();
|
||||
if (NULL == *jc)
|
||||
return;
|
||||
|
||||
(*jc)->envvar = (void *)initEnv(NULL, NULL);
|
||||
if (NULL == (*jc)->envvar) {
|
||||
jtagcore_deinit(*jc);
|
||||
*jc = NULL;
|
||||
return;
|
||||
}
|
||||
jtagcore_setEnvVar(*jc, "VERSION", "v" APP_VER_STR(APP_VER));
|
||||
|
||||
*sctx = jtagcore_initScript(*jc);
|
||||
if (NULL == *sctx) {
|
||||
deinitEnv((*jc)->envvar);
|
||||
jtagcore_deinit(*jc);
|
||||
*jc = NULL;
|
||||
return;
|
||||
}
|
||||
setOutputFunc_script(*sctx, script_print);
|
||||
execute_ram_script(*sctx, config_script, config_script_len);
|
||||
/* User override is optional — silence the engine's "not found" message. */
|
||||
{
|
||||
FILE *f = fopen("data/config.script", "r");
|
||||
if (f) {
|
||||
fclose(f);
|
||||
execute_file_script(*sctx, "data/config.script");
|
||||
}
|
||||
}
|
||||
|
||||
if (jtagcore_set_logs_callback(*jc, jprint) < 0)
|
||||
{
|
||||
fputs("Impossible to define the logs callback!\n", stderr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (jtagcore_getEnvVar(*jc, "LOG_MESSAGES_FILTER_LEVEL", NULL))
|
||||
{
|
||||
jtagcore_set_logs_level(*jc, jtagcore_getEnvVarValue(*jc, "LOG_MESSAGES_FILTER_LEVEL"));
|
||||
}
|
||||
if (jtagcore_getEnvVar(*jc, "LOG_MESSAGES_FILE_OUTPUT", NULL))
|
||||
{
|
||||
jtagcore_set_logs_file(*jc, jtagcore_getEnvVar(*jc, "LOG_MESSAGES_FILE_OUTPUT", NULL));
|
||||
}
|
||||
}
|
||||
|
||||
void bsexp_deinit(jtag_core *jc, script_ctx *sctx)
|
||||
{
|
||||
if (NULL != sctx)
|
||||
{
|
||||
deinit_script(sctx);
|
||||
}
|
||||
if (NULL != jc)
|
||||
{
|
||||
deinitEnv((envvar_entry *)jc->envvar);
|
||||
jtagcore_deinit(jc);
|
||||
}
|
||||
}
|
||||
10
src/bs/init.h
Normal file
10
src/bs/init.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef _BS_INIT_H
|
||||
#define _BS_INIT_H
|
||||
|
||||
#include "config/bs_defines.h"
|
||||
|
||||
int script_print(script_ctx *sctx, enum MSGTYPE typ, char *string, ...);
|
||||
void bsexp_init(jtag_core **jc, script_ctx **sctx);
|
||||
void bsexp_deinit(jtag_core *jc, script_ctx *sctx);
|
||||
|
||||
#endif
|
||||
147
src/bs/main.c
Normal file
147
src/bs/main.c
Normal file
@@ -0,0 +1,147 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
|
||||
#include "config/bs_defines.h"
|
||||
#include "config/version.h"
|
||||
#include "jtag_core/jtag_core.h"
|
||||
#include "script/script.h"
|
||||
#include "init.h"
|
||||
|
||||
#define PROMPT "bs_explorer> "
|
||||
|
||||
static jtag_core *jc = NULL;
|
||||
static script_ctx *sctx = NULL;
|
||||
|
||||
#define HISTORY_MAX_ENTRIES 1000
|
||||
static char history_file[1024] = "";
|
||||
|
||||
/* Persist the REPL command history across sessions in
|
||||
* $HOME/.bs_explorer_history (skipped if HOME is unset). */
|
||||
static void init_history(void)
|
||||
{
|
||||
const char *home = getenv("HOME");
|
||||
if (home && *home) {
|
||||
snprintf(history_file, sizeof(history_file), "%s/.bs_explorer_history", home);
|
||||
using_history();
|
||||
read_history(history_file);
|
||||
}
|
||||
}
|
||||
|
||||
static void save_history(void)
|
||||
{
|
||||
if (history_file[0]) {
|
||||
write_history(history_file);
|
||||
history_truncate_file(history_file, HISTORY_MAX_ENTRIES);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_sigint(int sig)
|
||||
{
|
||||
(void)sig;
|
||||
fputs("\n", stdout);
|
||||
save_history();
|
||||
bsexp_deinit(jc, sctx);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static char *command_generator(const char *text, int state)
|
||||
{
|
||||
static int idx;
|
||||
static size_t len;
|
||||
const char *name;
|
||||
|
||||
if (!state) {
|
||||
idx = 0;
|
||||
len = strlen(text);
|
||||
}
|
||||
|
||||
while ((name = script_commands_list[idx].command) != NULL) {
|
||||
idx++;
|
||||
if (strncmp(name, text, len) == 0) {
|
||||
return strdup(name);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char **bs_completion(const char *text, int start, int end)
|
||||
{
|
||||
(void)end;
|
||||
rl_attempted_completion_over = 0;
|
||||
if (start == 0) {
|
||||
return rl_completion_matches(text, command_generator);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int is_blank(const char *s)
|
||||
{
|
||||
while (*s) {
|
||||
if (*s != ' ' && *s != '\t') return 0;
|
||||
s++;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void print_banner(void)
|
||||
{
|
||||
int n_drv = jtagcore_get_number_of_probes_drv(jc);
|
||||
|
||||
printf("\n");
|
||||
printf(" Boundary Scan Explorer " APP_VER_STR(APP_VER) "\n");
|
||||
printf(" Based on Viveris jtag-boundary-scanner\n");
|
||||
printf("\n");
|
||||
printf(" %d probe driver(s) available.\n", n_drv);
|
||||
printf(" Type 'help' or '?' to list commands, 'exit' or Ctrl-D to quit.\n");
|
||||
printf(" <Tab> completes commands.\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *line = NULL;
|
||||
int error = 0;
|
||||
|
||||
bsexp_init(&jc, &sctx);
|
||||
if (NULL == jc || NULL == sctx) {
|
||||
fputs("JTAG Core initialization failed!\n", stderr);
|
||||
return JTAG_CORE_MEM_ERROR;
|
||||
}
|
||||
|
||||
signal(SIGINT, handle_sigint);
|
||||
rl_attempted_completion_function = bs_completion;
|
||||
rl_readline_name = "bs_explorer";
|
||||
init_history();
|
||||
|
||||
print_banner();
|
||||
|
||||
while ((line = readline(PROMPT)) != NULL) {
|
||||
if (is_blank(line)) {
|
||||
free(line);
|
||||
continue;
|
||||
}
|
||||
if (strcmp(line, "exit") == 0 || strcmp(line, "quit") == 0) {
|
||||
free(line);
|
||||
break;
|
||||
}
|
||||
add_history(line);
|
||||
|
||||
error = execute_line_script(sctx, line);
|
||||
if (error != JTAG_CORE_NO_ERROR && error != JTAG_CORE_NOT_FOUND) {
|
||||
printf("Command failed with code: %d\n", error);
|
||||
}
|
||||
free(line);
|
||||
}
|
||||
|
||||
if (line == NULL) {
|
||||
fputs("\n", stdout);
|
||||
}
|
||||
|
||||
save_history();
|
||||
bsexp_deinit(jc, sctx);
|
||||
return 0;
|
||||
}
|
||||
154
src/libs/libftd2xx/WinTypes.h
Executable file
154
src/libs/libftd2xx/WinTypes.h
Executable file
@@ -0,0 +1,154 @@
|
||||
#ifndef __WINDOWS_TYPES__
|
||||
#define __WINDOWS_TYPES__
|
||||
|
||||
#define WINAPI
|
||||
|
||||
typedef unsigned int DWORD;
|
||||
typedef unsigned int ULONG;
|
||||
typedef unsigned short USHORT;
|
||||
typedef unsigned short SHORT;
|
||||
typedef unsigned char UCHAR;
|
||||
typedef unsigned short WORD;
|
||||
typedef unsigned short WCHAR;
|
||||
typedef unsigned char BYTE;
|
||||
typedef BYTE *LPBYTE;
|
||||
typedef unsigned int BOOL;
|
||||
typedef unsigned char BOOLEAN;
|
||||
typedef unsigned char CHAR;
|
||||
typedef BOOL *LPBOOL;
|
||||
typedef UCHAR *PUCHAR;
|
||||
typedef const char *LPCSTR;
|
||||
typedef char *PCHAR;
|
||||
typedef void *PVOID;
|
||||
typedef void *HANDLE;
|
||||
typedef unsigned int LONG;
|
||||
typedef int INT;
|
||||
typedef unsigned int UINT;
|
||||
typedef char *LPSTR;
|
||||
typedef char *LPTSTR;
|
||||
typedef const char *LPCTSTR;
|
||||
typedef DWORD *LPDWORD;
|
||||
typedef WORD *LPWORD;
|
||||
typedef ULONG *PULONG;
|
||||
typedef LONG *LPLONG;
|
||||
typedef PVOID LPVOID;
|
||||
typedef void VOID;
|
||||
typedef USHORT *PUSHORT;
|
||||
typedef unsigned long long int ULONGLONG;
|
||||
|
||||
typedef struct _OVERLAPPED {
|
||||
DWORD Internal;
|
||||
DWORD InternalHigh;
|
||||
union {
|
||||
struct{
|
||||
DWORD Offset;
|
||||
DWORD OffsetHigh;
|
||||
};
|
||||
PVOID Pointer;
|
||||
};
|
||||
HANDLE hEvent;
|
||||
} OVERLAPPED, *LPOVERLAPPED;
|
||||
|
||||
typedef struct _SECURITY_ATTRIBUTES {
|
||||
DWORD nLength;
|
||||
LPVOID lpSecurityDescriptor;
|
||||
BOOL bInheritHandle;
|
||||
} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES;
|
||||
|
||||
#include <pthread.h>
|
||||
// Substitute for HANDLE returned by Windows CreateEvent API.
|
||||
// FT_SetEventNotification expects parameter 3 to be the address
|
||||
// of one of these structures.
|
||||
typedef struct _EVENT_HANDLE
|
||||
{
|
||||
pthread_cond_t eCondVar;
|
||||
pthread_mutex_t eMutex;
|
||||
int iVar;
|
||||
} EVENT_HANDLE;
|
||||
|
||||
typedef struct timeval SYSTEMTIME;
|
||||
typedef struct timeval FILETIME;
|
||||
|
||||
// WaitForSingleObject return values.
|
||||
#define WAIT_ABANDONED 0x00000080L
|
||||
#define WAIT_OBJECT_0 0x00000000L
|
||||
#define WAIT_TIMEOUT 0x00000102L
|
||||
#define WAIT_FAILED 0xFFFFFFFF
|
||||
// Special value for WaitForSingleObject dwMilliseconds parameter
|
||||
#define INFINITE 0xFFFFFFFF // Infinite timeout
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef CONST
|
||||
#define CONST const
|
||||
#endif
|
||||
//
|
||||
// Modem Status Flags
|
||||
//
|
||||
#define MS_CTS_ON ((DWORD)0x0010)
|
||||
#define MS_DSR_ON ((DWORD)0x0020)
|
||||
#define MS_RING_ON ((DWORD)0x0040)
|
||||
#define MS_RLSD_ON ((DWORD)0x0080)
|
||||
|
||||
//
|
||||
// Error Flags
|
||||
//
|
||||
#define CE_RXOVER 0x0001 // Receive Queue overflow
|
||||
#define CE_OVERRUN 0x0002 // Receive Overrun Error
|
||||
#define CE_RXPARITY 0x0004 // Receive Parity Error
|
||||
#define CE_FRAME 0x0008 // Receive Framing error
|
||||
#define CE_BREAK 0x0010 // Break Detected
|
||||
#define CE_TXFULL 0x0100 // TX Queue is full
|
||||
#define CE_PTO 0x0200 // LPTx Timeout
|
||||
#define CE_IOE 0x0400 // LPTx I/O Error
|
||||
#define CE_DNS 0x0800 // LPTx Device not selected
|
||||
#define CE_OOP 0x1000 // LPTx Out-Of-Paper
|
||||
#define CE_MODE 0x8000 // Requested mode unsupported
|
||||
|
||||
//
|
||||
// Events
|
||||
//
|
||||
#define EV_RXCHAR 0x0001 // Any Character received
|
||||
#define EV_RXFLAG 0x0002 // Received certain character
|
||||
#define EV_TXEMPTY 0x0004 // Transmit Queue Empty
|
||||
#define EV_CTS 0x0008 // CTS changed state
|
||||
#define EV_DSR 0x0010 // DSR changed state
|
||||
#define EV_RLSD 0x0020 // RLSD changed state
|
||||
#define EV_BREAK 0x0040 // BREAK received
|
||||
#define EV_ERR 0x0080 // Line status error occurred
|
||||
#define EV_RING 0x0100 // Ring signal detected
|
||||
#define EV_PERR 0x0200 // Printer error occured
|
||||
#define EV_RX80FULL 0x0400 // Receive buffer is 80 percent full
|
||||
#define EV_EVENT1 0x0800 // Provider specific event 1
|
||||
#define EV_EVENT2 0x1000 // Provider specific event 2
|
||||
|
||||
//
|
||||
// Escape Functions
|
||||
//
|
||||
#define SETXOFF 1 // Simulate XOFF received
|
||||
#define SETXON 2 // Simulate XON received
|
||||
#define SETRTS 3 // Set RTS high
|
||||
#define CLRRTS 4 // Set RTS low
|
||||
#define SETDTR 5 // Set DTR high
|
||||
#define CLRDTR 6 // Set DTR low
|
||||
#define RESETDEV 7 // Reset device if possible
|
||||
#define SETBREAK 8 // Set the device break line.
|
||||
#define CLRBREAK 9 // Clear the device break line.
|
||||
|
||||
//
|
||||
// PURGE function flags.
|
||||
//
|
||||
#define PURGE_TXABORT 0x0001 // Kill the pending/current writes to the comm port.
|
||||
#define PURGE_RXABORT 0x0002 // Kill the pending/current reads to the comm port.
|
||||
#define PURGE_TXCLEAR 0x0004 // Kill the transmit queue if there.
|
||||
#define PURGE_RXCLEAR 0x0008 // Kill the typeahead buffer if there.
|
||||
|
||||
#ifndef INVALID_HANDLE_VALUE
|
||||
#define INVALID_HANDLE_VALUE 0xFFFFFFFF
|
||||
#endif
|
||||
|
||||
#endif /* __WINDOWS_TYPES__ */
|
||||
1446
src/libs/libftd2xx/ftd2xx.h
Executable file
1446
src/libs/libftd2xx/ftd2xx.h
Executable file
File diff suppressed because it is too large
Load Diff
BIN
src/libs/libftd2xx/libftd2xx.a
Normal file
BIN
src/libs/libftd2xx/libftd2xx.a
Normal file
Binary file not shown.
7
src/modules/bscan/CMakeLists.txt
Normal file
7
src/modules/bscan/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
file(GLOB_RECURSE ALL_SOURCES "*.c")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
|
||||
add_library(bscan ${ALL_SOURCES})
|
||||
418
src/modules/bscan/bscan.c
Normal file
418
src/modules/bscan/bscan.c
Normal file
@@ -0,0 +1,418 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bscan.h"
|
||||
|
||||
/* JTAG byte format expected by drv_TXRX_DATA / drv_TX_TMS:
|
||||
* bit 0 (JTAG_STR_DOUT) = TDI value
|
||||
* bit 1 (JTAG_STR_TMS) = TMS value
|
||||
* bit 4 (JTAG_STR_DIN) = TDO returned by the driver (1 if TDO was high).
|
||||
* In practice, jtag_core treats the input byte as "non-zero if TDO=1",
|
||||
* so we just check buf_in[i] != 0 on read. */
|
||||
|
||||
static int drv_ok(jtag_core *jc)
|
||||
{
|
||||
return jc && jc->io_functions.drv_TX_TMS && jc->io_functions.drv_TXRX_DATA;
|
||||
}
|
||||
|
||||
/* --- Low-level primitives ----------------------------------------- */
|
||||
|
||||
int bscan_set_ir(jtag_core *jc, unsigned int opcode, int ir_length)
|
||||
{
|
||||
unsigned char tms_buf[8];
|
||||
unsigned char *data_buf;
|
||||
int i;
|
||||
|
||||
if (!drv_ok(jc) || ir_length <= 0 || ir_length > 32) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Idle -> Select-DR -> Select-IR -> Capture-IR -> Shift-IR */
|
||||
tms_buf[0] = JTAG_STR_TMS;
|
||||
tms_buf[1] = JTAG_STR_TMS;
|
||||
tms_buf[2] = 0;
|
||||
tms_buf[3] = 0;
|
||||
jc->io_functions.drv_TX_TMS(jc, tms_buf, 4);
|
||||
|
||||
/* Shift IR LSB first; raise TMS on the last bit (-> Exit1-IR) */
|
||||
data_buf = malloc(ir_length);
|
||||
if (!data_buf) return -1;
|
||||
for (i = 0; i < ir_length; i++) {
|
||||
data_buf[i] = ((opcode >> i) & 1u) ? JTAG_STR_DOUT : 0;
|
||||
if (i == ir_length - 1) {
|
||||
data_buf[i] |= JTAG_STR_TMS;
|
||||
}
|
||||
}
|
||||
jc->io_functions.drv_TXRX_DATA(jc, data_buf, NULL, ir_length);
|
||||
free(data_buf);
|
||||
|
||||
/* Exit1-IR -> Update-IR -> Idle */
|
||||
tms_buf[0] = JTAG_STR_TMS;
|
||||
tms_buf[1] = 0;
|
||||
jc->io_functions.drv_TX_TMS(jc, tms_buf, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bscan_shift_dr(jtag_core *jc, const uint8_t *tdi, uint8_t *tdo, int nbits)
|
||||
{
|
||||
unsigned char tms_buf[8];
|
||||
unsigned char *buf_out, *buf_in;
|
||||
int i;
|
||||
|
||||
if (!drv_ok(jc) || nbits <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Idle -> Select-DR -> Capture-DR -> Shift-DR */
|
||||
tms_buf[0] = JTAG_STR_TMS;
|
||||
tms_buf[1] = 0;
|
||||
tms_buf[2] = 0;
|
||||
jc->io_functions.drv_TX_TMS(jc, tms_buf, 3);
|
||||
|
||||
buf_out = malloc(nbits);
|
||||
if (!buf_out) return -1;
|
||||
buf_in = tdo ? malloc(nbits) : NULL;
|
||||
if (tdo && !buf_in) { free(buf_out); return -1; }
|
||||
|
||||
for (i = 0; i < nbits; i++) {
|
||||
uint8_t bit = 0;
|
||||
if (tdi) {
|
||||
bit = (tdi[i / 8] >> (i & 7)) & 1u;
|
||||
}
|
||||
buf_out[i] = bit ? JTAG_STR_DOUT : 0;
|
||||
if (i == nbits - 1) {
|
||||
buf_out[i] |= JTAG_STR_TMS;
|
||||
}
|
||||
}
|
||||
jc->io_functions.drv_TXRX_DATA(jc, buf_out, buf_in, nbits);
|
||||
|
||||
if (tdo && buf_in) {
|
||||
memset(tdo, 0, (size_t)((nbits + 7) / 8));
|
||||
for (i = 0; i < nbits; i++) {
|
||||
if (buf_in[i]) {
|
||||
tdo[i / 8] |= (uint8_t)(1u << (i & 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(buf_out);
|
||||
free(buf_in);
|
||||
|
||||
/* Exit1-DR -> Update-DR -> Idle */
|
||||
tms_buf[0] = JTAG_STR_TMS;
|
||||
tms_buf[1] = 0;
|
||||
jc->io_functions.drv_TX_TMS(jc, tms_buf, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bscan_shift_ir(jtag_core *jc, const uint8_t *tdi, uint8_t *tdo, int nbits)
|
||||
{
|
||||
unsigned char tms_buf[8];
|
||||
unsigned char *buf_out, *buf_in;
|
||||
int i;
|
||||
|
||||
if (!drv_ok(jc) || nbits <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Idle -> Select-DR -> Select-IR -> Capture-IR -> Shift-IR */
|
||||
tms_buf[0] = JTAG_STR_TMS;
|
||||
tms_buf[1] = JTAG_STR_TMS;
|
||||
tms_buf[2] = 0;
|
||||
tms_buf[3] = 0;
|
||||
jc->io_functions.drv_TX_TMS(jc, tms_buf, 4);
|
||||
|
||||
buf_out = malloc(nbits);
|
||||
if (!buf_out) return -1;
|
||||
buf_in = tdo ? malloc(nbits) : NULL;
|
||||
if (tdo && !buf_in) { free(buf_out); return -1; }
|
||||
|
||||
for (i = 0; i < nbits; i++) {
|
||||
uint8_t bit = 0;
|
||||
if (tdi) {
|
||||
bit = (tdi[i / 8] >> (i & 7)) & 1u;
|
||||
}
|
||||
buf_out[i] = bit ? JTAG_STR_DOUT : 0;
|
||||
if (i == nbits - 1) {
|
||||
buf_out[i] |= JTAG_STR_TMS; /* last bit -> Exit1-IR */
|
||||
}
|
||||
}
|
||||
jc->io_functions.drv_TXRX_DATA(jc, buf_out, buf_in, nbits);
|
||||
|
||||
if (tdo && buf_in) {
|
||||
memset(tdo, 0, (size_t)((nbits + 7) / 8));
|
||||
for (i = 0; i < nbits; i++) {
|
||||
if (buf_in[i]) {
|
||||
tdo[i / 8] |= (uint8_t)(1u << (i & 7));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(buf_out);
|
||||
free(buf_in);
|
||||
|
||||
/* Exit1-IR -> Update-IR -> Idle */
|
||||
tms_buf[0] = JTAG_STR_TMS;
|
||||
tms_buf[1] = 0;
|
||||
jc->io_functions.drv_TX_TMS(jc, tms_buf, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bscan_tap_reset(jtag_core *jc)
|
||||
{
|
||||
unsigned char tms_buf[8];
|
||||
|
||||
if (!drv_ok(jc)) return -1;
|
||||
|
||||
/* 5 TMS=1 forces Test-Logic-Reset from any state, then 1 TMS=0
|
||||
* lands in Run-Test/Idle (where the shift primitives start). */
|
||||
tms_buf[0] = JTAG_STR_TMS;
|
||||
tms_buf[1] = JTAG_STR_TMS;
|
||||
tms_buf[2] = JTAG_STR_TMS;
|
||||
tms_buf[3] = JTAG_STR_TMS;
|
||||
tms_buf[4] = JTAG_STR_TMS;
|
||||
tms_buf[5] = 0;
|
||||
jc->io_functions.drv_TX_TMS(jc, tms_buf, 6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bscan_idle_cycles(jtag_core *jc, int ncycles)
|
||||
{
|
||||
unsigned char *buf;
|
||||
int i;
|
||||
|
||||
if (!drv_ok(jc) || ncycles <= 0) {
|
||||
return -1;
|
||||
}
|
||||
buf = malloc(ncycles);
|
||||
if (!buf) return -1;
|
||||
for (i = 0; i < ncycles; i++) buf[i] = 0;
|
||||
jc->io_functions.drv_TX_TMS(jc, buf, ncycles);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* --- High-level operations ---------------------------------------- */
|
||||
|
||||
static uint8_t reverse_bits(uint8_t b)
|
||||
{
|
||||
b = (uint8_t)(((b & 0xF0u) >> 4) | ((b & 0x0Fu) << 4));
|
||||
b = (uint8_t)(((b & 0xCCu) >> 2) | ((b & 0x33u) << 2));
|
||||
b = (uint8_t)(((b & 0xAAu) >> 1) | ((b & 0x55u) << 1));
|
||||
return b;
|
||||
}
|
||||
|
||||
int bscan_load_bitstream(jtag_core *jc, const fpga_target *t,
|
||||
const uint8_t *data, size_t nbytes)
|
||||
{
|
||||
uint8_t *reversed;
|
||||
unsigned int bypass;
|
||||
size_t i;
|
||||
|
||||
if (!drv_ok(jc) || !t || !data || nbytes == 0) return -1;
|
||||
if (!t->ir_jprogram || !t->ir_cfg_in || !t->ir_jstart) {
|
||||
/* No configuration opcodes known for this family. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* JPROGRAM clears the configuration memory. Min ~10k TCK cycles
|
||||
* to wait for INIT_B to go high before CFG_IN.
|
||||
* TODO: poll INIT_B via SAMPLE instead of fixed wait. */
|
||||
if (bscan_set_ir(jc, t->ir_jprogram, t->ir_length) < 0) return -1;
|
||||
bscan_idle_cycles(jc, 10000);
|
||||
|
||||
/* CFG_IN routes DR shifts to the configuration interface. */
|
||||
if (bscan_set_ir(jc, t->ir_cfg_in, t->ir_length) < 0) return -1;
|
||||
|
||||
/* Xilinx bitstream bytes must be bit-reversed before JTAG shift
|
||||
* (configuration interface latches MSB first, JTAG shifts LSB first). */
|
||||
reversed = malloc(nbytes);
|
||||
if (!reversed) return -1;
|
||||
for (i = 0; i < nbytes; i++) {
|
||||
reversed[i] = reverse_bits(data[i]);
|
||||
}
|
||||
if (bscan_shift_dr(jc, reversed, NULL, (int)(nbytes * 8)) < 0) {
|
||||
free(reversed);
|
||||
return -1;
|
||||
}
|
||||
free(reversed);
|
||||
|
||||
/* JSTART triggers the fabric startup. UG470/UG570: ≥12 cycles in
|
||||
* Idle to complete the sequence. Use 2000 for margin. */
|
||||
if (bscan_set_ir(jc, t->ir_jstart, t->ir_length) < 0) return -1;
|
||||
bscan_idle_cycles(jc, 2000);
|
||||
|
||||
/* Park on BYPASS (all 1s) so other operations don't trip on a
|
||||
* lingering instruction. */
|
||||
bypass = (t->ir_length >= 32) ? 0xFFFFFFFFu : ((1u << t->ir_length) - 1u);
|
||||
bscan_set_ir(jc, bypass, t->ir_length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse a Xilinx .bit container; return offset and length of the raw
|
||||
* bitstream payload. Returns -1 if not a .bit. */
|
||||
static int xilinx_bit_payload(const uint8_t *buf, size_t buflen,
|
||||
size_t *out_off, size_t *out_len)
|
||||
{
|
||||
size_t off = 0;
|
||||
uint16_t hdr_len;
|
||||
|
||||
if (buflen < 13) return -1;
|
||||
/* First 2 bytes are big-endian length of a magic block (typically 0x0009),
|
||||
* followed by 9 magic bytes. */
|
||||
hdr_len = (uint16_t)((buf[0] << 8) | buf[1]);
|
||||
if (hdr_len != 0x0009) return -1;
|
||||
off = 2 + hdr_len;
|
||||
|
||||
/* Then 2 bytes (0x0001) and ASCII-tagged sections a/b/c/d, then 'e'
|
||||
* followed by 4 bytes big-endian length of the bitstream payload. */
|
||||
if (off + 2 > buflen) return -1;
|
||||
off += 2;
|
||||
while (off < buflen) {
|
||||
uint8_t tag = buf[off++];
|
||||
if (tag == 'e') {
|
||||
uint32_t bit_len;
|
||||
if (off + 4 > buflen) return -1;
|
||||
bit_len = ((uint32_t)buf[off] << 24) | ((uint32_t)buf[off + 1] << 16)
|
||||
| ((uint32_t)buf[off + 2] << 8) | (uint32_t)buf[off + 3];
|
||||
off += 4;
|
||||
if (off + bit_len > buflen) return -1;
|
||||
*out_off = off;
|
||||
*out_len = bit_len;
|
||||
return 0;
|
||||
}
|
||||
if (tag >= 'a' && tag <= 'd') {
|
||||
if (off + 2 > buflen) return -1;
|
||||
hdr_len = (uint16_t)((buf[off] << 8) | buf[off + 1]);
|
||||
off += 2 + hdr_len;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int bscan_load_bitstream_file(jtag_core *jc, const fpga_target *t,
|
||||
const char *path)
|
||||
{
|
||||
FILE *f;
|
||||
long size;
|
||||
uint8_t *buf;
|
||||
size_t payload_off = 0;
|
||||
size_t payload_len = 0;
|
||||
int ret;
|
||||
|
||||
if (!path) return -1;
|
||||
f = fopen(path, "rb");
|
||||
if (!f) return -1;
|
||||
if (fseek(f, 0, SEEK_END) != 0) { fclose(f); return -1; }
|
||||
size = ftell(f);
|
||||
if (size <= 0) { fclose(f); return -1; }
|
||||
rewind(f);
|
||||
|
||||
buf = malloc((size_t)size);
|
||||
if (!buf) { fclose(f); return -1; }
|
||||
if (fread(buf, 1, (size_t)size, f) != (size_t)size) {
|
||||
free(buf); fclose(f); return -1;
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
if (xilinx_bit_payload(buf, (size_t)size, &payload_off, &payload_len) < 0) {
|
||||
/* Treat as raw .bin */
|
||||
payload_off = 0;
|
||||
payload_len = (size_t)size;
|
||||
}
|
||||
|
||||
ret = bscan_load_bitstream(jc, t, buf + payload_off, payload_len);
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Pipeline latency between a MOSI bit going in and its MISO bit
|
||||
* appearing on TDO, in TCK cycles. For a single-device chain this is
|
||||
* one (the proxy registers TDO); equals jtag_tap_count_enabled() in
|
||||
* OpenOCD's jtagspi. The header asserts a single-device chain. */
|
||||
#define BSCAN_SPI_READ_LATENCY 1
|
||||
|
||||
int bscan_spi_xfer(jtag_core *jc, const fpga_target *t,
|
||||
const uint8_t *tx, size_t txlen,
|
||||
uint8_t *rx, size_t rxlen)
|
||||
{
|
||||
/* DR frame (quartiq/OpenOCD jtagspi proxy, single device):
|
||||
* marker(1)=1 | count(32, MSB-first) | MOSI(txlen*8, MSB-first/byte)
|
||||
* | latency skip | MISO capture(rxlen*8, MSB-first/byte)
|
||||
* count = total SPI bits - 1. The skip absorbs the TDO pipeline
|
||||
* delay so the captured MISO aligns to byte boundaries.
|
||||
* Bits are placed LSB-first per byte, the layout bscan_shift_dr
|
||||
* shifts in order; ordering them here gives MSB-first on the wire. */
|
||||
size_t spi_bytes = txlen + rxlen;
|
||||
uint32_t count;
|
||||
int total_bits, dr_bytes, capture_start, bit, j;
|
||||
size_t i;
|
||||
uint8_t *dr_out, *dr_in;
|
||||
|
||||
if (!drv_ok(jc) || !t || !t->ir_user1 || spi_bytes == 0) return -1;
|
||||
if (txlen && !tx) return -1;
|
||||
if (rxlen && !rx) return -1;
|
||||
|
||||
count = (uint32_t)(spi_bytes * 8u) - 1u;
|
||||
|
||||
total_bits = 1 + 32 + (int)txlen * 8;
|
||||
if (rxlen) total_bits += BSCAN_SPI_READ_LATENCY + (int)rxlen * 8;
|
||||
dr_bytes = (total_bits + 7) / 8;
|
||||
|
||||
dr_out = calloc(1, (size_t)dr_bytes);
|
||||
dr_in = rxlen ? calloc(1, (size_t)dr_bytes) : NULL;
|
||||
if (!dr_out || (rxlen && !dr_in)) { free(dr_out); free(dr_in); return -1; }
|
||||
|
||||
#define BS_SET(buf, pos) ((buf)[(pos) >> 3] |= (uint8_t)(1u << ((pos) & 7)))
|
||||
#define BS_GET(buf, pos) (((buf)[(pos) >> 3] >> ((pos) & 7)) & 1u)
|
||||
|
||||
bit = 0;
|
||||
BS_SET(dr_out, bit); bit++; /* marker = 1 */
|
||||
|
||||
for (j = 31; j >= 0; j--) { /* count, MSB-first */
|
||||
if (count & (1u << j)) BS_SET(dr_out, bit);
|
||||
bit++;
|
||||
}
|
||||
|
||||
for (i = 0; i < txlen; i++) { /* MOSI, MSB-first/byte */
|
||||
for (j = 7; j >= 0; j--) {
|
||||
if (tx[i] & (1u << j)) BS_SET(dr_out, bit);
|
||||
bit++;
|
||||
}
|
||||
}
|
||||
|
||||
capture_start = -1;
|
||||
if (rxlen) {
|
||||
bit += BSCAN_SPI_READ_LATENCY; /* skip pipeline delay */
|
||||
capture_start = bit;
|
||||
bit += (int)rxlen * 8; /* MISO region (MOSI=0) */
|
||||
}
|
||||
|
||||
if (bscan_set_ir(jc, t->ir_user1, t->ir_length) < 0 ||
|
||||
bscan_shift_dr(jc, dr_out, dr_in, total_bits) < 0) {
|
||||
free(dr_out); free(dr_in);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rxlen) {
|
||||
memset(rx, 0, rxlen);
|
||||
for (i = 0; i < rxlen * 8; i++) {
|
||||
if (BS_GET(dr_in, capture_start + (int)i)) {
|
||||
rx[i >> 3] |= (uint8_t)(1u << (7 - (i & 7))); /* MSB-first */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef BS_SET
|
||||
#undef BS_GET
|
||||
free(dr_out);
|
||||
free(dr_in);
|
||||
return 0;
|
||||
}
|
||||
72
src/modules/bscan/bscan.h
Normal file
72
src/modules/bscan/bscan.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef _BSCAN_H
|
||||
#define _BSCAN_H
|
||||
|
||||
/*
|
||||
* Single-device JTAG primitives and BSCAN-proxy operations.
|
||||
*
|
||||
* Provides:
|
||||
* - low-level JTAG TAP primitives (set_ir, shift_ir, shift_dr,
|
||||
* idle_cycles, tap_reset) that operate directly on jc->io_functions,
|
||||
* leaving jtag_core untouched. These are the building blocks the SVF
|
||||
* player and the proxy paths share;
|
||||
* - bitstream loading via CFG_IN to install a BSCAN proxy in the FPGA
|
||||
* fabric (Xilinx);
|
||||
* - a fast SPI transfer routine via USER1 once the proxy is loaded.
|
||||
*
|
||||
* (Was modules/bscan_spi/ — renamed once it grew past the SPI bridge
|
||||
* into general TAP primitives.)
|
||||
*
|
||||
* Current assumption: single device on the JTAG chain. Multi-device
|
||||
* support requires knowing the IR length of bypassed devices; defer.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
#include "fpga/fpga.h"
|
||||
|
||||
/* --- Low-level primitives (single-device chain) -------------------- */
|
||||
|
||||
/* Shift `opcode` into IR. `ir_length` is the IR width in bits. */
|
||||
int bscan_set_ir(jtag_core *jc, unsigned int opcode, int ir_length);
|
||||
|
||||
/* Shift `nbits` through DR. `tdi` may be NULL (shifts zeros).
|
||||
* `tdo` may be NULL (write only). Both buffers are LSB-first per byte. */
|
||||
int bscan_shift_dr(jtag_core *jc, const uint8_t *tdi, uint8_t *tdo, int nbits);
|
||||
|
||||
/* Like bscan_shift_dr but through Shift-IR — a general IR scan with TDO
|
||||
* capture (bscan_set_ir is opcode-only). Single-device chain; buffers
|
||||
* LSB-first per byte. Both ends in Run-Test/Idle. */
|
||||
int bscan_shift_ir(jtag_core *jc, const uint8_t *tdi, uint8_t *tdo, int nbits);
|
||||
|
||||
/* Emit `ncycles` TCK cycles while staying in Run-Test/Idle. */
|
||||
int bscan_idle_cycles(jtag_core *jc, int ncycles);
|
||||
|
||||
/* Force Test-Logic-Reset (5 TCK with TMS=1) and land in Run-Test/Idle. */
|
||||
int bscan_tap_reset(jtag_core *jc);
|
||||
|
||||
/* --- High-level operations ---------------------------------------- */
|
||||
|
||||
/* Load a raw bitstream payload (no .bit container header) into the
|
||||
* FPGA via JPROGRAM -> CFG_IN -> shift -> JSTART. Bit-reverses each
|
||||
* byte before shifting (Xilinx convention). */
|
||||
int bscan_load_bitstream(jtag_core *jc, const fpga_target *t,
|
||||
const uint8_t *data, size_t nbytes);
|
||||
|
||||
/* Convenience wrapper: read a file and load it. Detects the Xilinx
|
||||
* .bit header and skips it; otherwise treats the file as raw payload. */
|
||||
int bscan_load_bitstream_file(jtag_core *jc, const fpga_target *t,
|
||||
const char *path);
|
||||
|
||||
/* One CS-framed SPI transaction through the BSCAN proxy (USER1 DR):
|
||||
* clock out `txlen` MOSI bytes (e.g. command + address + write data),
|
||||
* then read `rxlen` MISO bytes into `rx`. Either length may be 0.
|
||||
* Bytes are MSB-first on the wire; bit-order juggling is internal.
|
||||
* Follows the quartiq/OpenOCD jtagspi proxy framing. Single-device
|
||||
* chain only. Requires a proxy bitstream already loaded (USER1 live). */
|
||||
int bscan_spi_xfer(jtag_core *jc, const fpga_target *t,
|
||||
const uint8_t *tx, size_t txlen,
|
||||
uint8_t *rx, size_t rxlen);
|
||||
|
||||
#endif
|
||||
7
src/modules/bsdl_parser/CMakeLists.txt
Normal file
7
src/modules/bsdl_parser/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
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})
|
||||
1520
src/modules/bsdl_parser/bsdl_loader.c
Normal file
1520
src/modules/bsdl_parser/bsdl_loader.c
Normal file
File diff suppressed because it is too large
Load Diff
87
src/modules/bsdl_parser/bsdl_loader.h
Normal file
87
src/modules/bsdl_parser/bsdl_loader.h
Normal file
@@ -0,0 +1,87 @@
|
||||
#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
|
||||
93
src/modules/bsdl_parser/bsdl_strings.c
Normal file
93
src/modules/bsdl_parser/bsdl_strings.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
81
src/modules/bsdl_parser/bsdl_strings.h
Normal file
81
src/modules/bsdl_parser/bsdl_strings.h
Normal file
@@ -0,0 +1,81 @@
|
||||
#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
|
||||
7
src/modules/bus_over_jtag/CMakeLists.txt
Normal file
7
src/modules/bus_over_jtag/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
file(GLOB_RECURSE ALL_SOURCES "*.c")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
|
||||
add_library(bus_over_jtag ${ALL_SOURCES})
|
||||
357
src/modules/bus_over_jtag/i2c_over_jtag.c
Normal file
357
src/modules/bus_over_jtag/i2c_over_jtag.c
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* 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 i2c_over_jtag.c
|
||||
* @brief I2C over jtag API
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
|
||||
#include "bsdl_parser/bsdl_loader.h"
|
||||
|
||||
#include "drivers/drivers_list.h"
|
||||
|
||||
#include "jtag_core/dbg_logs.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// I2C Over JTAG API
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int jtagcore_i2c_set_scl_pin(jtag_core * jc, int device, int pin)
|
||||
{
|
||||
jtag_bsdl * bsdl_file;
|
||||
|
||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
||||
{
|
||||
if (jc->devices_list[device].bsdl)
|
||||
{
|
||||
bsdl_file = jc->devices_list[device].bsdl;
|
||||
|
||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
||||
{
|
||||
jc->i2c_scl_pin = pin;
|
||||
jc->i2c_scl_device = device;
|
||||
|
||||
jtagcore_logs_printf(jc,MSG_DEBUG,"jtagcore_i2c_set_scl_pin : device %d, pin %d\r\n",device,pin);
|
||||
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
else
|
||||
jtagcore_logs_printf(jc,MSG_DEBUG,"jtagcore_i2c_set_scl_pin : ERROR invalid pin %d\r\n",pin);
|
||||
}
|
||||
else
|
||||
jtagcore_logs_printf(jc,MSG_DEBUG,"jtagcore_i2c_set_scl_pin : ERROR bsdl not loaded\r\n");
|
||||
}
|
||||
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
int jtagcore_i2c_set_sda_pin(jtag_core * jc, int device, int pin)
|
||||
{
|
||||
jtag_bsdl * bsdl_file;
|
||||
|
||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
||||
{
|
||||
if (jc->devices_list[device].bsdl)
|
||||
{
|
||||
bsdl_file = jc->devices_list[device].bsdl;
|
||||
|
||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
||||
{
|
||||
jc->i2c_sda_pin = pin;
|
||||
jc->i2c_sda_device = device;
|
||||
|
||||
jtagcore_logs_printf(jc,MSG_DEBUG,"jtagcore_i2c_set_sda_pin : device %d, pin %d\r\n",device,pin);
|
||||
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
else
|
||||
jtagcore_logs_printf(jc,MSG_DEBUG,"jtagcore_i2c_set_sda_pin : ERROR invalid pin %d\r\n",pin);
|
||||
}
|
||||
else
|
||||
jtagcore_logs_printf(jc,MSG_DEBUG,"jtagcore_i2c_set_sda_pin : ERROR bsdl not loaded\r\n");
|
||||
}
|
||||
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
static void jtagcore_i2c_set_scl_state_high(jtag_core * jc)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->i2c_scl_device, jc->i2c_scl_pin, JTAG_CORE_OE, 0);
|
||||
jtagcore_set_pin_state(jc, jc->i2c_scl_device, jc->i2c_scl_pin, JTAG_CORE_OUTPUT, 1);
|
||||
}
|
||||
|
||||
static void jtagcore_i2c_set_scl_state_low(jtag_core * jc)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->i2c_scl_device, jc->i2c_scl_pin, JTAG_CORE_OE, 1);
|
||||
jtagcore_set_pin_state(jc, jc->i2c_scl_device, jc->i2c_scl_pin, JTAG_CORE_OUTPUT, 0);
|
||||
}
|
||||
|
||||
static void jtagcore_i2c_set_sda_state_high(jtag_core * jc)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->i2c_sda_device, jc->i2c_sda_pin, JTAG_CORE_OE, 0);
|
||||
jtagcore_set_pin_state(jc, jc->i2c_sda_device, jc->i2c_sda_pin, JTAG_CORE_OUTPUT, 1);
|
||||
}
|
||||
|
||||
static void jtagcore_i2c_set_sda_state_low(jtag_core * jc)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->i2c_sda_device, jc->i2c_sda_pin, JTAG_CORE_OE, 1);
|
||||
jtagcore_set_pin_state(jc, jc->i2c_sda_device, jc->i2c_sda_pin, JTAG_CORE_OUTPUT, 0);
|
||||
}
|
||||
|
||||
static void i2c_start_bit(jtag_core * jc)
|
||||
{
|
||||
// Start bit.
|
||||
|
||||
jtagcore_i2c_set_sda_state_low(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
jtagcore_i2c_set_scl_state_low(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
}
|
||||
|
||||
static void i2c_push_bit(jtag_core * jc, int sda_state)
|
||||
{
|
||||
if (sda_state)
|
||||
{
|
||||
jtagcore_i2c_set_sda_state_high(jc);
|
||||
}
|
||||
else
|
||||
{
|
||||
jtagcore_i2c_set_sda_state_low(jc);
|
||||
}
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
jtagcore_i2c_set_scl_state_high(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
jtagcore_i2c_set_scl_state_low(jc);
|
||||
|
||||
jtagcore_i2c_set_sda_state_high(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
if (!sda_state)
|
||||
{
|
||||
// jtagcore_i2c_set_sda_state_high(jc);
|
||||
// jtagcore_push_and_pop_chain(jc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void i2c_stop_bit(jtag_core * jc)
|
||||
{
|
||||
// Stop bit.
|
||||
|
||||
jtagcore_i2c_set_sda_state_low(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
jtagcore_i2c_set_scl_state_high(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
jtagcore_i2c_set_sda_state_high(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
}
|
||||
|
||||
|
||||
static int i2c_wait_ack(jtag_core * jc)
|
||||
{
|
||||
int i, acknowledged;
|
||||
|
||||
acknowledged = 0;
|
||||
|
||||
// ACK
|
||||
jtagcore_i2c_set_sda_state_high(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
jtagcore_i2c_set_scl_state_high(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
if ( jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ) != JTAG_CORE_NO_ERROR )
|
||||
{
|
||||
return JTAG_CORE_IO_ERROR;
|
||||
}
|
||||
|
||||
i++;
|
||||
} while (jtagcore_get_pin_state(jc, jc->i2c_sda_device, jc->i2c_sda_pin, JTAG_CORE_INPUT) && i < 10);
|
||||
|
||||
if (i < 10)
|
||||
acknowledged = 1;
|
||||
|
||||
jtagcore_i2c_set_scl_state_low(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
return acknowledged;
|
||||
}
|
||||
|
||||
int jtagcore_i2c_write_read(jtag_core * jc, int address, int address10bits,int wr_size,unsigned char * wr_buffer,int rd_size,unsigned char * rd_buffer)
|
||||
{
|
||||
int i,j,acknowledged;
|
||||
|
||||
acknowledged = 0;
|
||||
|
||||
if( jc )
|
||||
{
|
||||
jtagcore_i2c_set_scl_state_high(jc);
|
||||
jtagcore_i2c_set_sda_state_high(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
// Is the bus Free / High state?
|
||||
if ( jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ) != JTAG_CORE_NO_ERROR )
|
||||
{
|
||||
return JTAG_CORE_IO_ERROR;
|
||||
}
|
||||
|
||||
if (!jtagcore_get_pin_state(jc, jc->i2c_sda_device, jc->i2c_sda_pin, JTAG_CORE_INPUT) || !jtagcore_get_pin_state(jc, jc->i2c_scl_device, jc->i2c_scl_pin, JTAG_CORE_INPUT))
|
||||
{
|
||||
return JTAG_CORE_I2C_BUS_NOTFREE;
|
||||
}
|
||||
|
||||
// Start bit.
|
||||
i2c_start_bit(jc);
|
||||
|
||||
for(i=0;i<7;i++)
|
||||
{
|
||||
i2c_push_bit(jc, address & (0x80 >> i));
|
||||
}
|
||||
|
||||
// WR/RD
|
||||
if(wr_size)
|
||||
{
|
||||
i2c_push_bit(jc, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
i2c_push_bit(jc, 1);
|
||||
}
|
||||
|
||||
// ACK
|
||||
acknowledged = i2c_wait_ack(jc);
|
||||
|
||||
if( acknowledged < 0 ) // Error ?
|
||||
{
|
||||
jtagcore_i2c_set_scl_state_high(jc);
|
||||
jtagcore_i2c_set_sda_state_high(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
return acknowledged;
|
||||
}
|
||||
|
||||
if(wr_size)
|
||||
{
|
||||
for(i=0;i<wr_size;i++)
|
||||
{
|
||||
for(j=0;j<8;j++)
|
||||
{
|
||||
i2c_push_bit(jc, wr_buffer[i] & (0x80 >> j));
|
||||
}
|
||||
|
||||
// ACK
|
||||
i2c_push_bit(jc, 1);
|
||||
}
|
||||
|
||||
// Stop bit.
|
||||
i2c_stop_bit(jc);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(i=0;i<rd_size;i++)
|
||||
{
|
||||
rd_buffer[i] = 0x00;
|
||||
|
||||
for(j=0;j<8;j++)
|
||||
{
|
||||
do
|
||||
{
|
||||
jtagcore_i2c_set_scl_state_high(jc);
|
||||
|
||||
if ( jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ) != JTAG_CORE_NO_ERROR )
|
||||
{
|
||||
jtagcore_i2c_set_scl_state_high(jc);
|
||||
jtagcore_i2c_set_sda_state_high(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
return JTAG_CORE_IO_ERROR;
|
||||
}
|
||||
|
||||
if ( jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ) != JTAG_CORE_NO_ERROR )
|
||||
{
|
||||
jtagcore_i2c_set_scl_state_high(jc);
|
||||
jtagcore_i2c_set_sda_state_high(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
return JTAG_CORE_IO_ERROR;
|
||||
}
|
||||
}while(!jtagcore_get_pin_state(jc,jc->i2c_scl_device,jc->i2c_scl_pin,JTAG_CORE_INPUT));
|
||||
|
||||
|
||||
if(jtagcore_get_pin_state(jc,jc->i2c_sda_device,jc->i2c_sda_pin,JTAG_CORE_INPUT))
|
||||
{
|
||||
rd_buffer[i] |= 0x80>>j;
|
||||
}
|
||||
|
||||
jtagcore_i2c_set_scl_state_low(jc);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
}
|
||||
|
||||
if(i!=rd_size-1)
|
||||
{
|
||||
// ACK
|
||||
i2c_push_bit(jc, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// NACK
|
||||
i2c_push_bit(jc, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Stop bit.
|
||||
i2c_stop_bit(jc);
|
||||
}
|
||||
|
||||
return acknowledged;
|
||||
}
|
||||
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
289
src/modules/bus_over_jtag/mdio_over_jtag.c
Normal file
289
src/modules/bus_over_jtag/mdio_over_jtag.c
Normal file
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* 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 mdio_over_jtag.c
|
||||
* @brief MDC/MDIO over jtag API
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
|
||||
#include "bsdl_parser/bsdl_loader.h"
|
||||
|
||||
#include "drivers/drivers_list.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// MDIO Over JTAG API
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int jtagcore_mdio_set_mdc_pin(jtag_core * jc, int device, int pin)
|
||||
{
|
||||
jtag_bsdl * bsdl_file;
|
||||
|
||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
||||
{
|
||||
if (jc->devices_list[device].bsdl)
|
||||
{
|
||||
bsdl_file = jc->devices_list[device].bsdl;
|
||||
|
||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
||||
{
|
||||
jc->mdio_mdc_pin = pin;
|
||||
jc->mdio_mdc_device = device;
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
int jtagcore_mdio_set_mdio_pin(jtag_core * jc, int device, int pin)
|
||||
{
|
||||
jtag_bsdl * bsdl_file;
|
||||
|
||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >=0)
|
||||
{
|
||||
if (jc->devices_list[device].bsdl)
|
||||
{
|
||||
bsdl_file = jc->devices_list[device].bsdl;
|
||||
|
||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
||||
{
|
||||
jc->mdio_mdio_pin = pin;
|
||||
jc->mdio_mdio_device = device;
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
static void mdio_push_bit(jtag_core * jc, int bit_state)
|
||||
{
|
||||
if (bit_state)
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdio_device, jc->mdio_mdio_pin, JTAG_CORE_OE, 0); // MDIO High
|
||||
else
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdio_device, jc->mdio_mdio_pin, JTAG_CORE_OE, 1); // MDIO Low
|
||||
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OUTPUT, 0); // MDC Low
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OUTPUT, 1); // MDC High
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
}
|
||||
|
||||
|
||||
static int mdio_get_bit(jtag_core * jc)
|
||||
{
|
||||
int state;
|
||||
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OUTPUT, 1); // MDC High
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OUTPUT, 0); // MDC Low
|
||||
|
||||
if ( jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ) != JTAG_CORE_NO_ERROR )
|
||||
{
|
||||
return JTAG_CORE_IO_ERROR;
|
||||
}
|
||||
|
||||
state = jtagcore_get_pin_state(jc, jc->mdio_mdio_device, jc->mdio_mdio_pin, JTAG_CORE_INPUT);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
int jtagcore_mdio_write(jtag_core * jc, int phy_adr, int reg_adr, int data)
|
||||
{
|
||||
int i;
|
||||
|
||||
if( jc )
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OE, 1);
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdio_device, jc->mdio_mdio_pin, JTAG_CORE_OE, 0);
|
||||
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OUTPUT, 0);
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdio_device, jc->mdio_mdio_pin, JTAG_CORE_OUTPUT, 0);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
mdio_push_bit(jc, 1);
|
||||
}
|
||||
|
||||
// Start.
|
||||
mdio_push_bit(jc, 0);
|
||||
mdio_push_bit(jc, 1);
|
||||
|
||||
//Write
|
||||
mdio_push_bit(jc, 0);
|
||||
mdio_push_bit(jc, 1);
|
||||
|
||||
// dev address
|
||||
for (i=0;i<5;i++)
|
||||
{
|
||||
if(phy_adr & (0x10>>i))
|
||||
{
|
||||
mdio_push_bit(jc, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
mdio_push_bit(jc, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// reg address
|
||||
for (i=0;i<5;i++)
|
||||
{
|
||||
if(reg_adr & (0x10>>i))
|
||||
{
|
||||
mdio_push_bit(jc, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
mdio_push_bit(jc, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//TA
|
||||
mdio_push_bit(jc, 1);
|
||||
mdio_push_bit(jc, 0);
|
||||
|
||||
// data
|
||||
for (i=0;i<16;i++)
|
||||
{
|
||||
if(data & (0x8000>>i))
|
||||
{
|
||||
mdio_push_bit(jc, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
mdio_push_bit(jc, 0);
|
||||
}
|
||||
}
|
||||
|
||||
mdio_push_bit(jc, 1);
|
||||
mdio_push_bit(jc, 1);
|
||||
mdio_push_bit(jc, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
int jtagcore_mdio_read(jtag_core * jc, int phy_adr, int reg_adr)
|
||||
{
|
||||
int i,data;
|
||||
int bit_state;
|
||||
|
||||
if( jc )
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OE, 1);
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdio_device, jc->mdio_mdio_pin, JTAG_CORE_OE, 0);
|
||||
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OUTPUT, 0);
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdio_device, jc->mdio_mdio_pin, JTAG_CORE_OUTPUT, 0);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
mdio_push_bit(jc, 1);
|
||||
}
|
||||
|
||||
// Start.
|
||||
mdio_push_bit(jc, 0);
|
||||
mdio_push_bit(jc, 1);
|
||||
|
||||
//Read
|
||||
mdio_push_bit(jc, 1);
|
||||
mdio_push_bit(jc, 0);
|
||||
|
||||
// dev address
|
||||
for (i=0;i<5;i++)
|
||||
{
|
||||
if(phy_adr & (0x10>>i))
|
||||
{
|
||||
mdio_push_bit(jc, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
mdio_push_bit(jc, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// reg address
|
||||
for (i=0;i<5;i++)
|
||||
{
|
||||
if(reg_adr & (0x10>>i))
|
||||
{
|
||||
mdio_push_bit(jc, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
mdio_push_bit(jc, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// TA
|
||||
mdio_push_bit(jc, 1);
|
||||
|
||||
jtagcore_set_pin_state(jc, jc->mdio_mdc_device, jc->mdio_mdc_pin, JTAG_CORE_OUTPUT, 0); // MDC Low
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
data = 0;
|
||||
// data
|
||||
for (i=0;i<16;i++)
|
||||
{
|
||||
bit_state = mdio_get_bit(jc);
|
||||
if(bit_state < 0 )
|
||||
{
|
||||
mdio_push_bit(jc, 1);
|
||||
mdio_push_bit(jc, 1);
|
||||
mdio_push_bit(jc, 1);
|
||||
|
||||
return bit_state;
|
||||
}
|
||||
|
||||
if(bit_state)
|
||||
{
|
||||
data |= (0x8000>>i);
|
||||
}
|
||||
}
|
||||
|
||||
mdio_push_bit(jc, 1);
|
||||
mdio_push_bit(jc, 1);
|
||||
mdio_push_bit(jc, 1);
|
||||
|
||||
|
||||
return data;
|
||||
}
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
322
src/modules/bus_over_jtag/memory_over_jtag.c
Normal file
322
src/modules/bus_over_jtag/memory_over_jtag.c
Normal file
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* 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 memory_over_jtag.c
|
||||
* @brief parallel memory over jtag API
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
|
||||
#include "bsdl_parser/bsdl_loader.h"
|
||||
|
||||
#include "drivers/drivers_list.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Memory Over JTAG API
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int jtagcore_memory_clear_pins(jtag_core * jc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0;i<MAX_BUS_WIDTH;i++)
|
||||
{
|
||||
jc->ram_address_pin[i] = -1;
|
||||
jc->ram_address_device[i] = -1;
|
||||
jc->ram_data_pin[i] = -1;
|
||||
jc->ram_data_device[i] = -1;
|
||||
}
|
||||
|
||||
for(i=0;i<16;i++)
|
||||
{
|
||||
jc->ram_ctrl_pin[i] = -1;
|
||||
jc->ram_ctrl_pin_pol[i] = -1;
|
||||
jc->ram_ctrl_device[i] = -1;
|
||||
}
|
||||
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
|
||||
int jtagcore_memory_set_address_pin(jtag_core * jc, int address_bit, int device, int pin)
|
||||
{
|
||||
jtag_bsdl * bsdl_file;
|
||||
|
||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && address_bit < MAX_BUS_WIDTH)
|
||||
{
|
||||
if (jc->devices_list[device].bsdl)
|
||||
{
|
||||
bsdl_file = jc->devices_list[device].bsdl;
|
||||
|
||||
if ( pin < bsdl_file->number_of_pins && pin >= 0 )
|
||||
{
|
||||
jc->ram_address_pin[address_bit] = pin;
|
||||
jc->ram_address_device[address_bit] = device;
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
int jtagcore_memory_set_data_pin(jtag_core * jc, int data_bit, int device, int pin)
|
||||
{
|
||||
jtag_bsdl * bsdl_file;
|
||||
|
||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && data_bit < MAX_BUS_WIDTH)
|
||||
{
|
||||
if (jc->devices_list[device].bsdl)
|
||||
{
|
||||
bsdl_file = jc->devices_list[device].bsdl;
|
||||
|
||||
if ( pin < bsdl_file->number_of_pins && pin >= 0 )
|
||||
{
|
||||
jc->ram_data_pin[data_bit] = pin;
|
||||
jc->ram_data_device[data_bit] = device;
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
int jtagcore_memory_set_ctrl_pin(jtag_core * jc, int ctrl, int polarity, int device, int pin)
|
||||
{
|
||||
jtag_bsdl * bsdl_file;
|
||||
|
||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0 && ctrl < 16)
|
||||
{
|
||||
if (jc->devices_list[device].bsdl)
|
||||
{
|
||||
bsdl_file = jc->devices_list[device].bsdl;
|
||||
|
||||
if ( pin < bsdl_file->number_of_pins && pin >= 0 )
|
||||
{
|
||||
jc->ram_ctrl_pin[ctrl] = pin;
|
||||
jc->ram_ctrl_pin_pol[ctrl] = polarity;
|
||||
jc->ram_ctrl_device[ctrl] = device;
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
unsigned long jtagcore_memory_read(jtag_core * jc, int mem_adr)
|
||||
{
|
||||
int i;
|
||||
unsigned long value;
|
||||
|
||||
// Set address bus
|
||||
for(i=0;i<MAX_BUS_WIDTH;i++)
|
||||
{
|
||||
if(jc->ram_address_pin[i]>=0 && jc->ram_address_device[i]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_address_device[i], jc->ram_address_pin[i], JTAG_CORE_OE, 1);
|
||||
|
||||
if( mem_adr & (0x00000001<<i) )
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_address_device[i], jc->ram_address_pin[i], JTAG_CORE_OUTPUT, 1);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_address_device[i], jc->ram_address_pin[i], JTAG_CORE_OUTPUT, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set data bus tristate.
|
||||
for(i=0;i<MAX_BUS_WIDTH;i++)
|
||||
{
|
||||
if(jc->ram_data_pin[i]>=0 && jc->ram_data_device[i]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_data_device[i], jc->ram_data_pin[i], JTAG_CORE_OE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// deassert control pins.
|
||||
for(i=0;i<16;i++)
|
||||
{
|
||||
if(jc->ram_ctrl_pin[i]>=0 && jc->ram_ctrl_device[i]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_ctrl_device[i], jc->ram_ctrl_pin[i], JTAG_CORE_OE, 1);
|
||||
|
||||
jtagcore_set_pin_state(jc, jc->ram_ctrl_device[i], jc->ram_ctrl_pin[i], JTAG_CORE_OUTPUT, (jc->ram_ctrl_pin_pol[i]&1)^1 );
|
||||
}
|
||||
}
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
// Assert CS
|
||||
if(jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL], JTAG_CORE_OUTPUT, jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_CS_CTRL] & 1 );
|
||||
}
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
// Assert RD
|
||||
if(jc->ram_ctrl_pin[JTAG_CORE_RAM_RD_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_RD_CTRL]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_RD_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_RD_CTRL], JTAG_CORE_OUTPUT, jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_RD_CTRL] & 1 );
|
||||
}
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
if ( jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ) != JTAG_CORE_NO_ERROR )
|
||||
{
|
||||
return (unsigned long)-1;
|
||||
}
|
||||
|
||||
// read the data bus.
|
||||
value = 0x00000000;
|
||||
for(i=0;i<MAX_BUS_WIDTH;i++)
|
||||
{
|
||||
if(jc->ram_data_pin[i]>=0 && jc->ram_data_device[i]>=0)
|
||||
{
|
||||
if(jtagcore_get_pin_state(jc, jc->ram_data_device[i], jc->ram_data_pin[i], JTAG_CORE_INPUT))
|
||||
{
|
||||
value |= (0x00000001<<i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// dessert RD
|
||||
if(jc->ram_ctrl_pin[JTAG_CORE_RAM_RD_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_RD_CTRL]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_RD_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_RD_CTRL], JTAG_CORE_OUTPUT, ( jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_RD_CTRL] & 1 ) ^ 1 );
|
||||
}
|
||||
|
||||
// deassert CS
|
||||
if(jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL], JTAG_CORE_OUTPUT, ( jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_CS_CTRL] & 1 ) ^ 1 );
|
||||
}
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int jtagcore_memory_write(jtag_core * jc, int mem_adr, unsigned long data)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
// Set address bus
|
||||
for(i=0;i<MAX_BUS_WIDTH;i++)
|
||||
{
|
||||
if(jc->ram_address_pin[i]>=0 && jc->ram_address_device[i]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_address_device[i], jc->ram_address_pin[i], JTAG_CORE_OE, 1);
|
||||
|
||||
if( mem_adr & (0x00000001<<i) )
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_address_device[i], jc->ram_address_pin[i], JTAG_CORE_OUTPUT, 1);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_address_device[i], jc->ram_address_pin[i], JTAG_CORE_OUTPUT, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set data bus
|
||||
for(i=0;i<MAX_BUS_WIDTH;i++)
|
||||
{
|
||||
if(jc->ram_data_pin[i]>=0 && jc->ram_data_device[i]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_data_device[i], jc->ram_data_pin[i], JTAG_CORE_OE, 1);
|
||||
|
||||
if( data & (0x00000001<<i) )
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_data_device[i], jc->ram_data_pin[i], JTAG_CORE_OUTPUT, 1);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_data_device[i], jc->ram_data_pin[i], JTAG_CORE_OUTPUT, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// deassert control pins.
|
||||
for(i=0;i<16;i++)
|
||||
{
|
||||
if(jc->ram_ctrl_pin[i]>=0 && jc->ram_ctrl_device[i]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_ctrl_device[i], jc->ram_ctrl_pin[i], JTAG_CORE_OE, 1);
|
||||
|
||||
jtagcore_set_pin_state(jc, jc->ram_ctrl_device[i], jc->ram_ctrl_pin[i], JTAG_CORE_OUTPUT, (jc->ram_ctrl_pin_pol[i]&1)^1 );
|
||||
}
|
||||
}
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
// Assert CS
|
||||
if(jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL], JTAG_CORE_OUTPUT, jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_CS_CTRL] & 1 );
|
||||
}
|
||||
|
||||
// Assert WR
|
||||
if(jc->ram_ctrl_pin[JTAG_CORE_RAM_WR_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_WR_CTRL]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_WR_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_WR_CTRL], JTAG_CORE_OUTPUT, jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_WR_CTRL] & 1 );
|
||||
}
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
// dessert WR
|
||||
if(jc->ram_ctrl_pin[JTAG_CORE_RAM_WR_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_WR_CTRL]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_WR_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_WR_CTRL], JTAG_CORE_OUTPUT, (jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_WR_CTRL] & 1) ^ 1 );
|
||||
}
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
// deassert CS
|
||||
if(jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL]>=0 && jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_ctrl_device[JTAG_CORE_RAM_CS_CTRL], jc->ram_ctrl_pin[JTAG_CORE_RAM_CS_CTRL], JTAG_CORE_OUTPUT, ( jc->ram_ctrl_pin_pol[JTAG_CORE_RAM_CS_CTRL] & 1 ) ^ 1 );
|
||||
}
|
||||
|
||||
// Set data bus tristate.
|
||||
for(i=0;i<MAX_BUS_WIDTH;i++)
|
||||
{
|
||||
if(jc->ram_data_pin[i]>=0 && jc->ram_data_device[i]>=0)
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->ram_data_device[i], jc->ram_data_pin[i], JTAG_CORE_OE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
287
src/modules/bus_over_jtag/spi_over_jtag.c
Normal file
287
src/modules/bus_over_jtag/spi_over_jtag.c
Normal file
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* 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 spi_over_jtag.c
|
||||
* @brief spi over jtag API
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
|
||||
#include "bsdl_parser/bsdl_loader.h"
|
||||
|
||||
#include "drivers/drivers_list.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SPI Over JTAG API
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int jtagcore_spi_set_mosi_pin(jtag_core * jc, int device, int pin, int sample_clk_phase)
|
||||
{
|
||||
jtag_bsdl * bsdl_file;
|
||||
|
||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
||||
{
|
||||
if (jc->devices_list[device].bsdl)
|
||||
{
|
||||
bsdl_file = jc->devices_list[device].bsdl;
|
||||
|
||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
||||
{
|
||||
jc->spi_mosi_pin = pin;
|
||||
if(sample_clk_phase)
|
||||
jc->spi_mosi_pol = 1;
|
||||
else
|
||||
jc->spi_mosi_pol = 0;
|
||||
jc->spi_mosi_device = device;
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
int jtagcore_spi_set_miso_pin(jtag_core * jc, int device, int pin, int sample_clk_phase)
|
||||
{
|
||||
jtag_bsdl * bsdl_file;
|
||||
|
||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
||||
{
|
||||
if (jc->devices_list[device].bsdl)
|
||||
{
|
||||
bsdl_file = jc->devices_list[device].bsdl;
|
||||
|
||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
||||
{
|
||||
jc->spi_miso_pin = pin;
|
||||
if(sample_clk_phase)
|
||||
jc->spi_miso_pol = 1;
|
||||
else
|
||||
jc->spi_miso_pol = 0;
|
||||
jc->spi_miso_device = device;
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
int jtagcore_spi_set_clk_pin(jtag_core * jc, int device, int pin, int polarity)
|
||||
{
|
||||
jtag_bsdl * bsdl_file;
|
||||
|
||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
||||
{
|
||||
if (jc->devices_list[device].bsdl)
|
||||
{
|
||||
bsdl_file = jc->devices_list[device].bsdl;
|
||||
|
||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
||||
{
|
||||
jc->spi_clk_pin = pin;
|
||||
if(polarity)
|
||||
jc->spi_clk_pol = 1;
|
||||
else
|
||||
jc->spi_clk_pol = 0;
|
||||
jc->spi_clk_device = device;
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
int jtagcore_spi_set_cs_pin(jtag_core * jc, int device, int pin, int polarity)
|
||||
{
|
||||
jtag_bsdl * bsdl_file;
|
||||
|
||||
if (device < jc->nb_of_devices_in_chain && device < MAX_NB_JTAG_DEVICE && device >= 0)
|
||||
{
|
||||
if (jc->devices_list[device].bsdl)
|
||||
{
|
||||
bsdl_file = jc->devices_list[device].bsdl;
|
||||
|
||||
if (pin < bsdl_file->number_of_pins && pin >= 0)
|
||||
{
|
||||
jc->spi_cs_pin = pin;
|
||||
if(polarity)
|
||||
jc->spi_cs_pol = 1;
|
||||
else
|
||||
jc->spi_cs_pol = 0;
|
||||
jc->spi_cs_device = device;
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
int jtagcore_spi_set_bitorder(jtag_core * jc, int lsb_first)
|
||||
{
|
||||
if(lsb_first)
|
||||
jc->spi_lsb_first = 1;
|
||||
else
|
||||
jc->spi_lsb_first = 0;
|
||||
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
int jtagcore_spi_write_read(jtag_core * jc, int wr_size,unsigned char * wr_buffer,unsigned char * rd_buffer, int flags)
|
||||
{
|
||||
int i,j;
|
||||
unsigned char byte_mask;
|
||||
|
||||
if( jc )
|
||||
{
|
||||
if(jc->spi_lsb_first)
|
||||
byte_mask = (0x01);
|
||||
else
|
||||
byte_mask = (0x80);
|
||||
|
||||
jtagcore_set_pin_state(jc, jc->spi_mosi_device, jc->spi_mosi_pin, JTAG_CORE_OUTPUT, 0);
|
||||
if(wr_size)
|
||||
{
|
||||
if( wr_buffer[0] & byte_mask )
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->spi_mosi_device, jc->spi_mosi_pin, JTAG_CORE_OUTPUT, 1);
|
||||
}
|
||||
}
|
||||
|
||||
jtagcore_set_pin_state(jc, jc->spi_miso_device, jc->spi_miso_pin, JTAG_CORE_OUTPUT, 1);
|
||||
jtagcore_set_pin_state(jc, jc->spi_cs_device, jc->spi_cs_pin, JTAG_CORE_OUTPUT, 1 ^ jc->spi_cs_pol);
|
||||
jtagcore_set_pin_state(jc, jc->spi_clk_device, jc->spi_clk_pin, JTAG_CORE_OUTPUT, 0 ^ jc->spi_clk_pol);
|
||||
|
||||
jtagcore_set_pin_state(jc, jc->spi_miso_device, jc->spi_miso_pin, JTAG_CORE_OE, 0);
|
||||
jtagcore_set_pin_state(jc, jc->spi_mosi_device, jc->spi_mosi_pin, JTAG_CORE_OE, 1);
|
||||
jtagcore_set_pin_state(jc, jc->spi_cs_device, jc->spi_cs_pin, JTAG_CORE_OE, 1);
|
||||
jtagcore_set_pin_state(jc, jc->spi_clk_device, jc->spi_clk_pin, JTAG_CORE_OE, 1);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
jtagcore_set_pin_state(jc, jc->spi_cs_device, jc->spi_cs_pin, JTAG_CORE_OUTPUT, 0 ^ jc->spi_cs_pol);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
for(i=0;i<wr_size;i++)
|
||||
{
|
||||
for(j=0;j<8;j++)
|
||||
{
|
||||
if(jc->spi_lsb_first)
|
||||
byte_mask = (0x01<<j);
|
||||
else
|
||||
byte_mask = (0x80>>j);
|
||||
|
||||
if(!jc->spi_mosi_pol) // CPHA = 0
|
||||
{ // MOSI OUT on clock phase 0
|
||||
if( wr_buffer[i] & byte_mask )
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->spi_mosi_device, jc->spi_mosi_pin, JTAG_CORE_OUTPUT, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->spi_mosi_device, jc->spi_mosi_pin, JTAG_CORE_OUTPUT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(!jc->spi_miso_pol) // CPHA = 0
|
||||
{ // MISO IN on clock phase 0
|
||||
|
||||
// clock phase 0
|
||||
jtagcore_set_pin_state(jc, jc->spi_clk_device, jc->spi_clk_pin, JTAG_CORE_OUTPUT, 1 ^ jc->spi_clk_pol);
|
||||
if ( jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ) != JTAG_CORE_NO_ERROR )
|
||||
{
|
||||
return JTAG_CORE_IO_ERROR;
|
||||
}
|
||||
|
||||
if(jtagcore_get_pin_state(jc,jc->spi_miso_device,jc->spi_miso_pin,JTAG_CORE_INPUT))
|
||||
{
|
||||
rd_buffer[i] |= byte_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
rd_buffer[i] &= ~(byte_mask);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// clock phase 0
|
||||
jtagcore_set_pin_state(jc, jc->spi_clk_device, jc->spi_clk_pin, JTAG_CORE_OUTPUT, 1 ^ jc->spi_clk_pol);
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
}
|
||||
|
||||
if(jc->spi_mosi_pol) // CPHA = 1
|
||||
{ // MOSI OUT on clock phase 1
|
||||
if( wr_buffer[i] & byte_mask )
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->spi_mosi_device, jc->spi_mosi_pin, JTAG_CORE_OUTPUT, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
jtagcore_set_pin_state(jc, jc->spi_mosi_device, jc->spi_mosi_pin, JTAG_CORE_OUTPUT, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(jc->spi_miso_pol) // CPHA = 1
|
||||
{
|
||||
// clock phase 1
|
||||
jtagcore_set_pin_state(jc, jc->spi_clk_device, jc->spi_clk_pin, JTAG_CORE_OUTPUT, 0 ^ jc->spi_clk_pol);
|
||||
|
||||
if ( jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_READ) != JTAG_CORE_NO_ERROR )
|
||||
{
|
||||
return JTAG_CORE_IO_ERROR;
|
||||
}
|
||||
|
||||
// MISO IN on clock phase 1
|
||||
if(jtagcore_get_pin_state(jc,jc->spi_miso_device,jc->spi_miso_pin,JTAG_CORE_INPUT))
|
||||
{
|
||||
rd_buffer[i] |= byte_mask;
|
||||
}
|
||||
else
|
||||
{
|
||||
rd_buffer[i] &= ~(byte_mask);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// clock phase 1
|
||||
jtagcore_set_pin_state(jc, jc->spi_clk_device, jc->spi_clk_pin, JTAG_CORE_OUTPUT, 0 ^ jc->spi_clk_pol);
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jtagcore_set_pin_state(jc, jc->spi_cs_device, jc->spi_cs_pin, JTAG_CORE_OUTPUT, 1 ^ jc->spi_cs_pol);
|
||||
|
||||
jtagcore_push_and_pop_chain(jc, JTAG_CORE_WRITE_ONLY);
|
||||
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
195
src/modules/config/bs_defines.h
Normal file
195
src/modules/config/bs_defines.h
Normal file
@@ -0,0 +1,195 @@
|
||||
#ifndef _BS_TYPES_H
|
||||
#define _BS_TYPES_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Functions Error / return codes
|
||||
|
||||
#define JTAG_CORE_NO_ERROR 0
|
||||
#define JTAG_CORE_BAD_PARAMETER -1
|
||||
#define JTAG_CORE_ACCESS_ERROR -2
|
||||
#define JTAG_CORE_IO_ERROR -3
|
||||
#define JTAG_CORE_MEM_ERROR -4
|
||||
#define JTAG_CORE_NO_PROBE -5
|
||||
#define JTAG_CORE_NOT_FOUND -6
|
||||
#define JTAG_CORE_CMD_NOT_FOUND -7
|
||||
#define JTAG_CORE_INTERNAL_ERROR -8
|
||||
#define JTAG_CORE_BAD_CMD -9
|
||||
|
||||
#define JTAG_CORE_I2C_BUS_NOTFREE -10
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef SCRIPT_64BITS_SUPPORT
|
||||
#define env_var_value uint64_t
|
||||
#define STRTOVALUE strtoull
|
||||
#define LONGHEXSTR "%llX"
|
||||
#else
|
||||
#define env_var_value uint32_t
|
||||
#define STRTOVALUE strtoul
|
||||
#define LONGHEXSTR "%.8X"
|
||||
#endif
|
||||
|
||||
#define MAX_LABEL_SIZE 64
|
||||
#define MAX_LABEL 256
|
||||
|
||||
#define DEFAULT_BUFLEN 1024
|
||||
|
||||
enum {
|
||||
GET_DRV_ID = 1,
|
||||
GET_DRV_DESCRIPTION,
|
||||
GET_DRV_FUNCPTR,
|
||||
GET_DRV_DETECT
|
||||
};
|
||||
|
||||
// Output message types/levels
|
||||
enum MSGTYPE
|
||||
{
|
||||
MSG_DEBUG = 0,
|
||||
MSG_INFO_0,
|
||||
MSG_INFO_1,
|
||||
MSG_WARNING,
|
||||
MSG_ERROR,
|
||||
MSG_NONE
|
||||
};
|
||||
|
||||
typedef struct _script_label
|
||||
{
|
||||
char label_name[MAX_LABEL_SIZE];
|
||||
unsigned int offset;
|
||||
} script_label;
|
||||
|
||||
typedef struct _script_ctx script_ctx;
|
||||
|
||||
typedef int (*SCRIPT_PRINTF_FUNC)(script_ctx * ctx, enum MSGTYPE typ, char *string, ...);
|
||||
|
||||
typedef struct _script_ctx
|
||||
{
|
||||
SCRIPT_PRINTF_FUNC script_printf;
|
||||
void * app_ctx;
|
||||
|
||||
void * env;
|
||||
|
||||
void * cmdlist;
|
||||
|
||||
FILE * script_file;
|
||||
char script_file_path[1024];
|
||||
|
||||
int cur_label_index;
|
||||
script_label labels[MAX_LABEL];
|
||||
|
||||
int cur_script_offset;
|
||||
|
||||
int dry_run;
|
||||
|
||||
int last_error_code;
|
||||
env_var_value last_data_value;
|
||||
int last_flags;
|
||||
|
||||
char pre_command[1024 + 32];
|
||||
|
||||
uint32_t rand_seed;
|
||||
|
||||
} script_ctx;
|
||||
|
||||
#define MAX_NB_JTAG_DEVICE 64
|
||||
#define MAX_NUMBER_BITS_IN_CHAIN (256 * 1024)
|
||||
#define MAX_NUMBER_PINS_PER_DEV (64 * 1024)
|
||||
#define MAX_BSDL_FILE_SIZE (1024 * 1024)
|
||||
#define MAX_NUMBER_OF_BSDL_LINES (64 * 1024)
|
||||
|
||||
#define MAX_PATH_LEN 4096
|
||||
|
||||
typedef struct _jtag_device
|
||||
{
|
||||
void *bsdl;
|
||||
unsigned long devices_id;
|
||||
unsigned char *out_boundary_scan;
|
||||
unsigned char *in_boundary_scan;
|
||||
int boundary_scan_size;
|
||||
int scan_mode;
|
||||
} jtag_device;
|
||||
|
||||
#define MAX_BUS_WIDTH 32
|
||||
|
||||
typedef struct _jtag_core jtag_core;
|
||||
|
||||
typedef int (*DRV_DETECT) (jtag_core* jc);
|
||||
typedef int (*DRV_INIT) (jtag_core* jc,int sub_drv,char * params);
|
||||
typedef int (*DRV_TXRXDATA) (jtag_core* jc, unsigned char * str_out, unsigned char * str_in, int size);
|
||||
typedef int (*DRV_TXTMS) (jtag_core* jc, unsigned char * str_out, int size);
|
||||
typedef int (*DRV_GETMODULEINFOS) (jtag_core* jc,int sub_drv,unsigned int infotype, void * returnvalue);
|
||||
typedef int (*DRV_DEINIT) (jtag_core* jc);
|
||||
|
||||
typedef struct drv_ptr_
|
||||
{
|
||||
DRV_DETECT drv_Detect;
|
||||
DRV_INIT drv_Init;
|
||||
DRV_DEINIT drv_DeInit;
|
||||
DRV_TXTMS drv_TX_TMS;
|
||||
DRV_TXRXDATA drv_TXRX_DATA;
|
||||
DRV_GETMODULEINFOS drv_Get_ModInfos;
|
||||
} drv_ptr;
|
||||
|
||||
typedef struct _jtag_core
|
||||
{
|
||||
drv_ptr io_functions;
|
||||
|
||||
void *jtagcore_print_callback;
|
||||
int logs_level;
|
||||
|
||||
void *envvar;
|
||||
|
||||
int t;
|
||||
|
||||
int nb_of_devices_in_chain;
|
||||
|
||||
int total_IR_lenght;
|
||||
jtag_device devices_list[MAX_NB_JTAG_DEVICE];
|
||||
int IR_filled;
|
||||
|
||||
// I2C over JTAG
|
||||
int i2c_sda_device;
|
||||
int i2c_scl_device;
|
||||
|
||||
int i2c_sda_pin;
|
||||
int i2c_scl_pin;
|
||||
|
||||
// SPI over JTAG
|
||||
int spi_mosi_device;
|
||||
int spi_miso_device;
|
||||
int spi_cs_device;
|
||||
int spi_clk_device;
|
||||
|
||||
int spi_mosi_pin;
|
||||
int spi_miso_pin;
|
||||
int spi_cs_pin;
|
||||
int spi_clk_pin;
|
||||
|
||||
int spi_cs_pol;
|
||||
int spi_clk_pol;
|
||||
int spi_mosi_pol;
|
||||
int spi_miso_pol;
|
||||
|
||||
int spi_lsb_first;
|
||||
|
||||
// MDIO over JTAG
|
||||
int mdio_mdc_pin;
|
||||
int mdio_mdc_device;
|
||||
int mdio_mdio_pin;
|
||||
int mdio_mdio_device;
|
||||
|
||||
// Memory over JTAG
|
||||
int ram_address_pin[MAX_BUS_WIDTH];
|
||||
int ram_address_device[MAX_BUS_WIDTH];
|
||||
int ram_data_pin[MAX_BUS_WIDTH];
|
||||
int ram_data_device[MAX_BUS_WIDTH];
|
||||
int ram_ctrl_pin[16];
|
||||
int ram_ctrl_pin_pol[16];
|
||||
int ram_ctrl_device[16];
|
||||
|
||||
char log_file_path[MAX_PATH_LEN];
|
||||
} jtag_core;
|
||||
|
||||
#endif
|
||||
182
src/modules/config/config.script
Normal file
182
src/modules/config/config.script
Normal file
@@ -0,0 +1,182 @@
|
||||
#
|
||||
# lib jtag core init config script
|
||||
#
|
||||
# This script is built-in the jtag library and is executed at startup to apply
|
||||
# the default variables values.
|
||||
#
|
||||
# You can put a "config.script" file in the JTAG boundaryscanner software's
|
||||
# folder to change one or more of these variables if needed.
|
||||
# Your "config.script" will be executed right after this script at startup.
|
||||
# The syntax to use in your script is exactly the same.
|
||||
#
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# Log messages filter level
|
||||
#
|
||||
# 0 : Debug messages
|
||||
# 1 : Info level 0 messages
|
||||
# 2 : Info level 1 messages
|
||||
# 3 : Warning level messages
|
||||
# 4 : Error level messages
|
||||
# 5 : No log / no message
|
||||
|
||||
set LOG_MESSAGES_FILTER_LEVEL 1
|
||||
|
||||
# Log file
|
||||
|
||||
#set LOG_MESSAGES_FILE_OUTPUT "logs_file.txt"
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
#
|
||||
# Pins name sorter
|
||||
#
|
||||
# 0 To keep the bsdl pins order.
|
||||
# 1 To sort the bsdl pins name.
|
||||
#
|
||||
|
||||
set BSDL_LOADER_SORT_PINS_NAME 1
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
#
|
||||
# This section expose the FTDI probes parameters
|
||||
#
|
||||
|
||||
#
|
||||
# Parameters to compute the FDTI FT2232D/H clock divisor.
|
||||
# ( TCK clock = (12Mhz or 60Mhz)/ ((1 + ([ValueH << 8 | ValueL]))*2) )
|
||||
#
|
||||
|
||||
# Internal clock : FT2232H -> 60 MHz, FT2232D -> 12MHz
|
||||
|
||||
set PROBE_FTDI_INTERNAL_FREQ_KHZ 60000
|
||||
|
||||
# Max TCK Clock
|
||||
|
||||
set PROBE_FTDI_TCK_FREQ_KHZ 1000
|
||||
|
||||
#
|
||||
# To enable the RTCK / adaptative clock mode set the following
|
||||
# variable to 1.
|
||||
# Warning : Need a FDTI chip supporting this mode (FT2232H,...)
|
||||
#
|
||||
|
||||
set PROBE_FTDI_JTAG_ENABLE_RTCK 0
|
||||
|
||||
#
|
||||
# Probe internal mapping
|
||||
#
|
||||
# Olimex ARM-USB-OCD-H JTAG signals example
|
||||
#
|
||||
# VREF – voltage follower input for the output buffers adjust
|
||||
# JTAG signals as per your target board voltage levels
|
||||
#
|
||||
# The TCK/TDI/TDO/TMS signals are fixed to these pins
|
||||
# ADBUS0 -> TCK; (out)
|
||||
# ADBUS1 -> TDI; (out)
|
||||
# ADBUS2 -> TDO; (in)
|
||||
# ADBUS3 -> TMS; (out)
|
||||
|
||||
# ADBUS4 -> 0 to enable JTAG buffers; (GPIOL0) (out)
|
||||
# ADBUS5 -> 0 if target present; (GPIOL1) (in)
|
||||
# ADBUS6 -> TSRST in; (GPIOL2) (in)
|
||||
# ADBUS7 -> RTCK; (in) (GPIOL3) (in)
|
||||
# ACBUS0 -> TRST; (GPIOH0)
|
||||
# ACBUS1 -> SRST; (GPIOH1)
|
||||
# ACBUS2 -> TRST buffer enable (GPIOH2)
|
||||
# ACBUS3 -> RED LED; (GPIOH3)
|
||||
|
||||
#
|
||||
# Set the internal GPIO direction (0 -> input, 1 -> output)
|
||||
#
|
||||
|
||||
set PROBE_FTDI_SET_PIN_DIR_ADBUS0 1 # TCK -> out
|
||||
set PROBE_FTDI_SET_PIN_DIR_ADBUS1 1 # TDI -> out
|
||||
set PROBE_FTDI_SET_PIN_DIR_ADBUS2 0 # TDO -> in
|
||||
set PROBE_FTDI_SET_PIN_DIR_ADBUS3 1 # TMS -> out
|
||||
set PROBE_FTDI_SET_PIN_DIR_ADBUS4 1 # Buffers enable -> out
|
||||
set PROBE_FTDI_SET_PIN_DIR_ADBUS5 0 # Target presence : 0 if target present -> in
|
||||
set PROBE_FTDI_SET_PIN_DIR_ADBUS6 0 # TSRST -> in
|
||||
set PROBE_FTDI_SET_PIN_DIR_ADBUS7 0 # RTCK -> in
|
||||
|
||||
set PROBE_FTDI_SET_PIN_DIR_ACBUS0 1 # TRST -> out
|
||||
set PROBE_FTDI_SET_PIN_DIR_ACBUS1 1 # SRST -> out
|
||||
set PROBE_FTDI_SET_PIN_DIR_ACBUS2 1 # TRST buffer enable -> out
|
||||
set PROBE_FTDI_SET_PIN_DIR_ACBUS3 1 # RED LED -> out
|
||||
|
||||
#
|
||||
# Set the internal GPIOs output state
|
||||
#
|
||||
|
||||
set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS0 0
|
||||
set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS1 0
|
||||
set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS2 0
|
||||
set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS3 1
|
||||
set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS4 0 # JTAG buffer enable (active low)
|
||||
set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS5 0
|
||||
set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS6 0
|
||||
set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS7 0
|
||||
|
||||
set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ACBUS0 0 # TRST
|
||||
set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ACBUS1 0 # SRST
|
||||
set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ACBUS2 0 # TRST buffer enable
|
||||
set PROBE_FTDI_SET_PIN_DEFAULT_STATE_ACBUS3 0 # RED LED
|
||||
|
||||
#
|
||||
# Set the internal GPIOs polarity
|
||||
# 0 : Active High.
|
||||
# 1 : Active Low.
|
||||
#
|
||||
|
||||
set PROBE_FTDI_SET_PIN_POLARITY_ADBUS0 0
|
||||
set PROBE_FTDI_SET_PIN_POLARITY_ADBUS1 0
|
||||
set PROBE_FTDI_SET_PIN_POLARITY_ADBUS2 0
|
||||
set PROBE_FTDI_SET_PIN_POLARITY_ADBUS3 0
|
||||
set PROBE_FTDI_SET_PIN_POLARITY_ADBUS4 0
|
||||
set PROBE_FTDI_SET_PIN_POLARITY_ADBUS5 0
|
||||
set PROBE_FTDI_SET_PIN_POLARITY_ADBUS6 0
|
||||
set PROBE_FTDI_SET_PIN_POLARITY_ADBUS7 0
|
||||
|
||||
set PROBE_FTDI_SET_PIN_POLARITY_ACBUS0 1 # TRST is active-low
|
||||
set PROBE_FTDI_SET_PIN_POLARITY_ACBUS1 0
|
||||
set PROBE_FTDI_SET_PIN_POLARITY_ACBUS2 0
|
||||
set PROBE_FTDI_SET_PIN_POLARITY_ACBUS3 0
|
||||
|
||||
#
|
||||
# Assign the TRST / SRST control pins
|
||||
# 0<>7 : ADBUS
|
||||
# 8<>11 : ACBUS
|
||||
# Set to -1 when not available/used.
|
||||
#
|
||||
|
||||
set PROBE_FTDI_SET_TRST_OE_PINNUM 10
|
||||
set PROBE_FTDI_SET_TRST_STATE_PINNUM 8
|
||||
|
||||
set PROBE_FTDI_SET_SRST_OE_PINNUM -1
|
||||
set PROBE_FTDI_SET_SRST_STATE_PINNUM -1
|
||||
|
||||
set PROBE_FTDI_SET_CONNECTION_LED_PINNUM 11
|
||||
|
||||
set PROBE_FTDI_JTAG_TRST_DELAY_MS 200
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
set PROBE_LINUXGPIO_ENABLE 0
|
||||
|
||||
set PROBE_LINUXGPIO_BASE_FOLDER "/sys/class/gpio"
|
||||
|
||||
set PROBE_LINUXGPIO_TMS_PIN 24
|
||||
set PROBE_LINUXGPIO_TDI_PIN 25
|
||||
set PROBE_LINUXGPIO_TDO_PIN 26
|
||||
set PROBE_LINUXGPIO_TCK_PIN 27
|
||||
|
||||
set PROBE_LINUXGPIO_TMS_PIN_INVERT_POLARITY 0
|
||||
set PROBE_LINUXGPIO_TDI_PIN_INVERT_POLARITY 0
|
||||
set PROBE_LINUXGPIO_TDO_PIN_INVERT_POLARITY 0
|
||||
set PROBE_LINUXGPIO_TCK_PIN_INVERT_POLARITY 0
|
||||
500
src/modules/config/config_script.h
Normal file
500
src/modules/config/config_script.h
Normal file
@@ -0,0 +1,500 @@
|
||||
unsigned char config_script[] = {
|
||||
0x23, 0x0d, 0x0a, 0x23, 0x20, 0x6c, 0x69, 0x62, 0x20, 0x6a, 0x74, 0x61,
|
||||
0x67, 0x20, 0x63, 0x6f, 0x72, 0x65, 0x20, 0x69, 0x6e, 0x69, 0x74, 0x20,
|
||||
0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x54, 0x68, 0x69, 0x73,
|
||||
0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x69, 0x73, 0x20, 0x62,
|
||||
0x75, 0x69, 0x6c, 0x74, 0x2d, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x6a, 0x74, 0x61, 0x67, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,
|
||||
0x20, 0x61, 0x6e, 0x64, 0x20, 0x69, 0x73, 0x20, 0x65, 0x78, 0x65, 0x63,
|
||||
0x75, 0x74, 0x65, 0x64, 0x20, 0x61, 0x74, 0x20, 0x73, 0x74, 0x61, 0x72,
|
||||
0x74, 0x75, 0x70, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x79,
|
||||
0x0d, 0x0a, 0x23, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, 0x61,
|
||||
0x75, 0x6c, 0x74, 0x20, 0x76, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65,
|
||||
0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x2e, 0x0d, 0x0a, 0x23,
|
||||
0x0d, 0x0a, 0x23, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20,
|
||||
0x70, 0x75, 0x74, 0x20, 0x61, 0x20, 0x22, 0x63, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x2e, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x20, 0x66, 0x69,
|
||||
0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4a, 0x54,
|
||||
0x41, 0x47, 0x20, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x73,
|
||||
0x63, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x20, 0x73, 0x6f, 0x66, 0x74, 0x77,
|
||||
0x61, 0x72, 0x65, 0x27, 0x73, 0x0d, 0x0a, 0x23, 0x20, 0x66, 0x6f, 0x6c,
|
||||
0x64, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67,
|
||||
0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x6d, 0x6f, 0x72,
|
||||
0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0x20, 0x76,
|
||||
0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x20, 0x69, 0x66, 0x20,
|
||||
0x6e, 0x65, 0x65, 0x64, 0x65, 0x64, 0x2e, 0x0d, 0x0a, 0x23, 0x20, 0x59,
|
||||
0x6f, 0x75, 0x72, 0x20, 0x22, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
|
||||
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x20, 0x77, 0x69, 0x6c, 0x6c,
|
||||
0x20, 0x62, 0x65, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x64,
|
||||
0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x61, 0x66, 0x74, 0x65, 0x72,
|
||||
0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
||||
0x20, 0x61, 0x74, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x2e,
|
||||
0x0d, 0x0a, 0x23, 0x20, 0x54, 0x68, 0x65, 0x20, 0x73, 0x79, 0x6e, 0x74,
|
||||
0x61, 0x78, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, 0x69, 0x6e,
|
||||
0x20, 0x79, 0x6f, 0x75, 0x72, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
||||
0x20, 0x69, 0x73, 0x20, 0x65, 0x78, 0x61, 0x63, 0x74, 0x6c, 0x79, 0x20,
|
||||
0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x2e, 0x0d, 0x0a, 0x23,
|
||||
0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a,
|
||||
0x23, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x20,
|
||||
0x4c, 0x6f, 0x67, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
|
||||
0x20, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x6c, 0x65, 0x76, 0x65,
|
||||
0x6c, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x30, 0x20, 0x3a, 0x20,
|
||||
0x44, 0x65, 0x62, 0x75, 0x67, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x73, 0x0d, 0x0a, 0x23, 0x20, 0x31, 0x20, 0x3a, 0x20, 0x49, 0x6e,
|
||||
0x66, 0x6f, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x20, 0x30, 0x20, 0x6d,
|
||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x0d, 0x0a, 0x23, 0x20, 0x32,
|
||||
0x20, 0x3a, 0x20, 0x49, 0x6e, 0x66, 0x6f, 0x20, 0x6c, 0x65, 0x76, 0x65,
|
||||
0x6c, 0x20, 0x31, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73,
|
||||
0x0d, 0x0a, 0x23, 0x20, 0x33, 0x20, 0x3a, 0x20, 0x57, 0x61, 0x72, 0x6e,
|
||||
0x69, 0x6e, 0x67, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x20, 0x6d, 0x65,
|
||||
0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x0d, 0x0a, 0x23, 0x20, 0x34, 0x20,
|
||||
0x3a, 0x20, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6c, 0x65, 0x76, 0x65,
|
||||
0x6c, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x0d, 0x0a,
|
||||
0x23, 0x20, 0x35, 0x20, 0x3a, 0x20, 0x4e, 0x6f, 0x20, 0x6c, 0x6f, 0x67,
|
||||
0x20, 0x2f, 0x20, 0x6e, 0x6f, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
|
||||
0x65, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x4c, 0x4f, 0x47,
|
||||
0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x53, 0x5f, 0x46, 0x49,
|
||||
0x4c, 0x54, 0x45, 0x52, 0x5f, 0x4c, 0x45, 0x56, 0x45, 0x4c, 0x20, 0x31,
|
||||
0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x20, 0x4c, 0x6f, 0x67, 0x20, 0x66, 0x69,
|
||||
0x6c, 0x65, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x73, 0x65, 0x74, 0x20, 0x4c,
|
||||
0x4f, 0x47, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x53, 0x5f,
|
||||
0x46, 0x49, 0x4c, 0x45, 0x5f, 0x4f, 0x55, 0x54, 0x50, 0x55, 0x54, 0x20,
|
||||
0x22, 0x6c, 0x6f, 0x67, 0x73, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x74,
|
||||
0x78, 0x74, 0x22, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x20, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x0d, 0x0a, 0x23, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x0d,
|
||||
0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x50, 0x69, 0x6e, 0x73, 0x20, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x20, 0x73, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x0d, 0x0a,
|
||||
0x23, 0x0d, 0x0a, 0x23, 0x20, 0x30, 0x20, 0x54, 0x6f, 0x20, 0x6b, 0x65,
|
||||
0x65, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x73, 0x64, 0x6c, 0x20,
|
||||
0x70, 0x69, 0x6e, 0x73, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x0d,
|
||||
0x0a, 0x23, 0x20, 0x31, 0x20, 0x54, 0x6f, 0x20, 0x73, 0x6f, 0x72, 0x74,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x62, 0x73, 0x64, 0x6c, 0x20, 0x70, 0x69,
|
||||
0x6e, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x0d, 0x0a, 0x23, 0x0d,
|
||||
0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x42, 0x53, 0x44, 0x4c, 0x5f,
|
||||
0x4c, 0x4f, 0x41, 0x44, 0x45, 0x52, 0x5f, 0x53, 0x4f, 0x52, 0x54, 0x5f,
|
||||
0x50, 0x49, 0x4e, 0x53, 0x5f, 0x4e, 0x41, 0x4d, 0x45, 0x20, 0x31, 0x0d,
|
||||
0x0a, 0x0d, 0x0a, 0x23, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x23,
|
||||
0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x0d, 0x0a,
|
||||
0x23, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x73, 0x65, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x46, 0x54, 0x44, 0x49, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x65,
|
||||
0x73, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73,
|
||||
0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20,
|
||||
0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x74,
|
||||
0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x46, 0x44, 0x54, 0x49, 0x20, 0x46, 0x54, 0x32, 0x32, 0x33,
|
||||
0x32, 0x44, 0x2f, 0x48, 0x20, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x64,
|
||||
0x69, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x2e, 0x0d, 0x0a, 0x23, 0x20, 0x28,
|
||||
0x20, 0x54, 0x43, 0x4b, 0x20, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x3d,
|
||||
0x20, 0x28, 0x31, 0x32, 0x4d, 0x68, 0x7a, 0x20, 0x6f, 0x72, 0x20, 0x36,
|
||||
0x30, 0x4d, 0x68, 0x7a, 0x29, 0x2f, 0x20, 0x28, 0x28, 0x31, 0x20, 0x2b,
|
||||
0x20, 0x28, 0x5b, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x48, 0x20, 0x3c, 0x3c,
|
||||
0x20, 0x38, 0x20, 0x7c, 0x20, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4c, 0x5d,
|
||||
0x29, 0x29, 0x2a, 0x32, 0x29, 0x20, 0x29, 0x0d, 0x0a, 0x23, 0x0d, 0x0a,
|
||||
0x0d, 0x0a, 0x23, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
|
||||
0x20, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x3a, 0x20, 0x46, 0x54, 0x32,
|
||||
0x32, 0x33, 0x32, 0x48, 0x20, 0x2d, 0x3e, 0x20, 0x36, 0x30, 0x20, 0x4d,
|
||||
0x48, 0x7a, 0x2c, 0x20, 0x46, 0x54, 0x32, 0x32, 0x33, 0x32, 0x44, 0x20,
|
||||
0x2d, 0x3e, 0x20, 0x31, 0x32, 0x4d, 0x48, 0x7a, 0x0d, 0x0a, 0x0d, 0x0a,
|
||||
0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54,
|
||||
0x44, 0x49, 0x5f, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f,
|
||||
0x46, 0x52, 0x45, 0x51, 0x5f, 0x4b, 0x48, 0x5a, 0x20, 0x36, 0x30, 0x30,
|
||||
0x30, 0x30, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x20, 0x4d, 0x61, 0x78, 0x20,
|
||||
0x54, 0x43, 0x4b, 0x20, 0x43, 0x6c, 0x6f, 0x63, 0x6b, 0x0d, 0x0a, 0x0d,
|
||||
0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46,
|
||||
0x54, 0x44, 0x49, 0x5f, 0x54, 0x43, 0x4b, 0x5f, 0x46, 0x52, 0x45, 0x51,
|
||||
0x5f, 0x4b, 0x48, 0x5a, 0x20, 0x31, 0x30, 0x30, 0x30, 0x0d, 0x0a, 0x0d,
|
||||
0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x54, 0x6f, 0x20, 0x65, 0x6e, 0x61,
|
||||
0x62, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x52, 0x54, 0x43, 0x4b,
|
||||
0x20, 0x2f, 0x20, 0x61, 0x64, 0x61, 0x70, 0x74, 0x61, 0x74, 0x69, 0x76,
|
||||
0x65, 0x20, 0x63, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x6d, 0x6f, 0x64, 0x65,
|
||||
0x20, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x6f, 0x6c,
|
||||
0x6c, 0x6f, 0x77, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x23, 0x20, 0x76, 0x61,
|
||||
0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x31, 0x2e,
|
||||
0x0d, 0x0a, 0x23, 0x20, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x20,
|
||||
0x3a, 0x20, 0x4e, 0x65, 0x65, 0x64, 0x20, 0x61, 0x20, 0x46, 0x44, 0x54,
|
||||
0x49, 0x20, 0x63, 0x68, 0x69, 0x70, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6f,
|
||||
0x72, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6d,
|
||||
0x6f, 0x64, 0x65, 0x20, 0x28, 0x46, 0x54, 0x32, 0x32, 0x33, 0x32, 0x48,
|
||||
0x2c, 0x2e, 0x2e, 0x2e, 0x29, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x0d, 0x0a,
|
||||
0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54,
|
||||
0x44, 0x49, 0x5f, 0x4a, 0x54, 0x41, 0x47, 0x5f, 0x45, 0x4e, 0x41, 0x42,
|
||||
0x4c, 0x45, 0x5f, 0x52, 0x54, 0x43, 0x4b, 0x20, 0x30, 0x0d, 0x0a, 0x0d,
|
||||
0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x20,
|
||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x6d, 0x61, 0x70,
|
||||
0x70, 0x69, 0x6e, 0x67, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x4f,
|
||||
0x6c, 0x69, 0x6d, 0x65, 0x78, 0x20, 0x41, 0x52, 0x4d, 0x2d, 0x55, 0x53,
|
||||
0x42, 0x2d, 0x4f, 0x43, 0x44, 0x2d, 0x48, 0x20, 0x4a, 0x54, 0x41, 0x47,
|
||||
0x20, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x73, 0x20, 0x65, 0x78, 0x61,
|
||||
0x6d, 0x70, 0x6c, 0x65, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x56,
|
||||
0x52, 0x45, 0x46, 0x20, 0xe2, 0x80, 0x93, 0x20, 0x76, 0x6f, 0x6c, 0x74,
|
||||
0x61, 0x67, 0x65, 0x20, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x72,
|
||||
0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x62, 0x75,
|
||||
0x66, 0x66, 0x65, 0x72, 0x73, 0x20, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74,
|
||||
0x0d, 0x0a, 0x23, 0x20, 0x4a, 0x54, 0x41, 0x47, 0x20, 0x73, 0x69, 0x67,
|
||||
0x6e, 0x61, 0x6c, 0x73, 0x20, 0x61, 0x73, 0x20, 0x70, 0x65, 0x72, 0x20,
|
||||
0x79, 0x6f, 0x75, 0x72, 0x20, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x20,
|
||||
0x62, 0x6f, 0x61, 0x72, 0x64, 0x20, 0x76, 0x6f, 0x6c, 0x74, 0x61, 0x67,
|
||||
0x65, 0x20, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x73, 0x0d, 0x0a, 0x23, 0x0d,
|
||||
0x0a, 0x23, 0x20, 0x54, 0x68, 0x65, 0x20, 0x54, 0x43, 0x4b, 0x2f, 0x54,
|
||||
0x44, 0x49, 0x2f, 0x54, 0x44, 0x4f, 0x2f, 0x54, 0x4d, 0x53, 0x20, 0x73,
|
||||
0x69, 0x67, 0x6e, 0x61, 0x6c, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x66,
|
||||
0x69, 0x78, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x73,
|
||||
0x65, 0x20, 0x70, 0x69, 0x6e, 0x73, 0x0d, 0x0a, 0x23, 0x20, 0x41, 0x44,
|
||||
0x42, 0x55, 0x53, 0x30, 0x20, 0x2d, 0x3e, 0x20, 0x54, 0x43, 0x4b, 0x3b,
|
||||
0x20, 0x28, 0x6f, 0x75, 0x74, 0x29, 0x0d, 0x0a, 0x23, 0x20, 0x41, 0x44,
|
||||
0x42, 0x55, 0x53, 0x31, 0x20, 0x2d, 0x3e, 0x20, 0x54, 0x44, 0x49, 0x3b,
|
||||
0x20, 0x28, 0x6f, 0x75, 0x74, 0x29, 0x0d, 0x0a, 0x23, 0x20, 0x41, 0x44,
|
||||
0x42, 0x55, 0x53, 0x32, 0x20, 0x2d, 0x3e, 0x20, 0x54, 0x44, 0x4f, 0x3b,
|
||||
0x20, 0x28, 0x69, 0x6e, 0x29, 0x0d, 0x0a, 0x23, 0x20, 0x41, 0x44, 0x42,
|
||||
0x55, 0x53, 0x33, 0x20, 0x2d, 0x3e, 0x20, 0x54, 0x4d, 0x53, 0x3b, 0x20,
|
||||
0x28, 0x6f, 0x75, 0x74, 0x29, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x20, 0x41,
|
||||
0x44, 0x42, 0x55, 0x53, 0x34, 0x20, 0x2d, 0x3e, 0x20, 0x30, 0x20, 0x74,
|
||||
0x6f, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x4a, 0x54, 0x41,
|
||||
0x47, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x73, 0x3b, 0x20, 0x20,
|
||||
0x28, 0x47, 0x50, 0x49, 0x4f, 0x4c, 0x30, 0x29, 0x20, 0x28, 0x6f, 0x75,
|
||||
0x74, 0x29, 0x0d, 0x0a, 0x23, 0x20, 0x41, 0x44, 0x42, 0x55, 0x53, 0x35,
|
||||
0x20, 0x2d, 0x3e, 0x20, 0x30, 0x20, 0x69, 0x66, 0x20, 0x74, 0x61, 0x72,
|
||||
0x67, 0x65, 0x74, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x3b,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x47, 0x50, 0x49, 0x4f,
|
||||
0x4c, 0x31, 0x29, 0x20, 0x28, 0x69, 0x6e, 0x29, 0x0d, 0x0a, 0x23, 0x20,
|
||||
0x41, 0x44, 0x42, 0x55, 0x53, 0x36, 0x20, 0x2d, 0x3e, 0x20, 0x54, 0x53,
|
||||
0x52, 0x53, 0x54, 0x20, 0x69, 0x6e, 0x3b, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x28, 0x47, 0x50, 0x49, 0x4f, 0x4c, 0x32, 0x29, 0x20, 0x28, 0x69,
|
||||
0x6e, 0x29, 0x0d, 0x0a, 0x23, 0x20, 0x41, 0x44, 0x42, 0x55, 0x53, 0x37,
|
||||
0x20, 0x2d, 0x3e, 0x20, 0x52, 0x54, 0x43, 0x4b, 0x3b, 0x20, 0x28, 0x69,
|
||||
0x6e, 0x29, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x47, 0x50, 0x49, 0x4f,
|
||||
0x4c, 0x33, 0x29, 0x20, 0x28, 0x69, 0x6e, 0x29, 0x0d, 0x0a, 0x23, 0x20,
|
||||
0x41, 0x43, 0x42, 0x55, 0x53, 0x30, 0x20, 0x2d, 0x3e, 0x20, 0x54, 0x52,
|
||||
0x53, 0x54, 0x3b, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x28, 0x47, 0x50, 0x49, 0x4f, 0x48, 0x30, 0x29, 0x0d, 0x0a, 0x23,
|
||||
0x20, 0x41, 0x43, 0x42, 0x55, 0x53, 0x31, 0x20, 0x2d, 0x3e, 0x20, 0x53,
|
||||
0x52, 0x53, 0x54, 0x3b, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x28, 0x47, 0x50, 0x49, 0x4f, 0x48, 0x31, 0x29, 0x0d, 0x0a,
|
||||
0x23, 0x20, 0x41, 0x43, 0x42, 0x55, 0x53, 0x32, 0x20, 0x2d, 0x3e, 0x20,
|
||||
0x54, 0x52, 0x53, 0x54, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20,
|
||||
0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x28, 0x47, 0x50, 0x49, 0x4f, 0x48, 0x32, 0x29, 0x0d,
|
||||
0x0a, 0x23, 0x20, 0x41, 0x43, 0x42, 0x55, 0x53, 0x33, 0x20, 0x2d, 0x3e,
|
||||
0x20, 0x52, 0x45, 0x44, 0x20, 0x4c, 0x45, 0x44, 0x3b, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x28, 0x47, 0x50, 0x49, 0x4f, 0x48, 0x33, 0x29,
|
||||
0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20, 0x53, 0x65, 0x74,
|
||||
0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
|
||||
0x6c, 0x20, 0x47, 0x50, 0x49, 0x4f, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x30, 0x20, 0x2d, 0x3e, 0x20, 0x69,
|
||||
0x6e, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x31, 0x20, 0x2d, 0x3e, 0x20, 0x6f,
|
||||
0x75, 0x74, 0x70, 0x75, 0x74, 0x29, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x0d,
|
||||
0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46,
|
||||
0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f,
|
||||
0x44, 0x49, 0x52, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x30, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31,
|
||||
0x20, 0x23, 0x20, 0x54, 0x43, 0x4b, 0x20, 0x2d, 0x3e, 0x20, 0x6f, 0x75,
|
||||
0x74, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45,
|
||||
0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49,
|
||||
0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x31,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x31, 0x20, 0x23, 0x20, 0x54, 0x44, 0x49, 0x20, 0x2d, 0x3e, 0x20,
|
||||
0x6f, 0x75, 0x74, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f,
|
||||
0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f,
|
||||
0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41, 0x44, 0x42, 0x55,
|
||||
0x53, 0x32, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x30, 0x20, 0x23, 0x20, 0x54, 0x44, 0x4f, 0x20, 0x2d,
|
||||
0x3e, 0x20, 0x69, 0x6e, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52,
|
||||
0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54,
|
||||
0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41, 0x44, 0x42,
|
||||
0x55, 0x53, 0x33, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x23, 0x20, 0x54, 0x4d, 0x53, 0x20,
|
||||
0x2d, 0x3e, 0x20, 0x6f, 0x75, 0x74, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20,
|
||||
0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53,
|
||||
0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41,
|
||||
0x44, 0x42, 0x55, 0x53, 0x34, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x23, 0x20, 0x42, 0x75,
|
||||
0x66, 0x66, 0x65, 0x72, 0x73, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
||||
0x20, 0x2d, 0x3e, 0x20, 0x6f, 0x75, 0x74, 0x0d, 0x0a, 0x73, 0x65, 0x74,
|
||||
0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f,
|
||||
0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f,
|
||||
0x41, 0x44, 0x42, 0x55, 0x53, 0x35, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x23, 0x20, 0x54,
|
||||
0x61, 0x72, 0x67, 0x65, 0x74, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e,
|
||||
0x63, 0x65, 0x20, 0x3a, 0x20, 0x30, 0x20, 0x69, 0x66, 0x20, 0x74, 0x61,
|
||||
0x72, 0x67, 0x65, 0x74, 0x20, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74,
|
||||
0x20, 0x2d, 0x3e, 0x20, 0x69, 0x6e, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20,
|
||||
0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53,
|
||||
0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41,
|
||||
0x44, 0x42, 0x55, 0x53, 0x36, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x23, 0x20, 0x54, 0x53,
|
||||
0x52, 0x53, 0x54, 0x20, 0x2d, 0x3e, 0x20, 0x69, 0x6e, 0x0d, 0x0a, 0x73,
|
||||
0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44,
|
||||
0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49,
|
||||
0x52, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x37, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x23,
|
||||
0x20, 0x52, 0x54, 0x43, 0x4b, 0x20, 0x2d, 0x3e, 0x20, 0x69, 0x6e, 0x0d,
|
||||
0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45,
|
||||
0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49,
|
||||
0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41, 0x43, 0x42, 0x55, 0x53, 0x30,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x31, 0x20, 0x23, 0x20, 0x54, 0x52, 0x53, 0x54, 0x20, 0x2d, 0x3e,
|
||||
0x20, 0x6f, 0x75, 0x74, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52,
|
||||
0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54,
|
||||
0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41, 0x43, 0x42,
|
||||
0x55, 0x53, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x23, 0x20, 0x53, 0x52, 0x53, 0x54,
|
||||
0x20, 0x2d, 0x3e, 0x20, 0x6f, 0x75, 0x74, 0x0d, 0x0a, 0x73, 0x65, 0x74,
|
||||
0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f,
|
||||
0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x49, 0x52, 0x5f,
|
||||
0x41, 0x43, 0x42, 0x55, 0x53, 0x32, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x20, 0x23, 0x20, 0x54,
|
||||
0x52, 0x53, 0x54, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x65,
|
||||
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x2d, 0x3e, 0x20, 0x6f, 0x75, 0x74,
|
||||
0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f,
|
||||
0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e,
|
||||
0x5f, 0x44, 0x49, 0x52, 0x5f, 0x41, 0x43, 0x42, 0x55, 0x53, 0x33, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x31, 0x20, 0x23, 0x20, 0x52, 0x45, 0x44, 0x20, 0x4c, 0x45, 0x44, 0x20,
|
||||
0x2d, 0x3e, 0x20, 0x6f, 0x75, 0x74, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x0d,
|
||||
0x0a, 0x23, 0x20, 0x53, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69,
|
||||
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x47, 0x50, 0x49, 0x4f,
|
||||
0x73, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x73, 0x74, 0x61,
|
||||
0x74, 0x65, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74,
|
||||
0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f,
|
||||
0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x45, 0x46, 0x41,
|
||||
0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x44,
|
||||
0x42, 0x55, 0x53, 0x30, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65,
|
||||
0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49,
|
||||
0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x45, 0x46,
|
||||
0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x41,
|
||||
0x44, 0x42, 0x55, 0x53, 0x31, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x73,
|
||||
0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44,
|
||||
0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x45,
|
||||
0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f,
|
||||
0x41, 0x44, 0x42, 0x55, 0x53, 0x32, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a,
|
||||
0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54,
|
||||
0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44,
|
||||
0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45,
|
||||
0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x33, 0x20, 0x20, 0x20, 0x31, 0x0d,
|
||||
0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46,
|
||||
0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f,
|
||||
0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54,
|
||||
0x45, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x34, 0x20, 0x20, 0x20, 0x30,
|
||||
0x20, 0x23, 0x20, 0x4a, 0x54, 0x41, 0x47, 0x20, 0x62, 0x75, 0x66, 0x66,
|
||||
0x65, 0x72, 0x20, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x28, 0x61,
|
||||
0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x6c, 0x6f, 0x77, 0x29, 0x0d, 0x0a,
|
||||
0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54,
|
||||
0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44,
|
||||
0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45,
|
||||
0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x35, 0x20, 0x20, 0x20, 0x30, 0x0d,
|
||||
0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46,
|
||||
0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f,
|
||||
0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54,
|
||||
0x45, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x36, 0x20, 0x20, 0x20, 0x30,
|
||||
0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f,
|
||||
0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e,
|
||||
0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41,
|
||||
0x54, 0x45, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x37, 0x20, 0x20, 0x20,
|
||||
0x30, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f,
|
||||
0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f,
|
||||
0x50, 0x49, 0x4e, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f,
|
||||
0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x43, 0x42, 0x55, 0x53, 0x30,
|
||||
0x20, 0x20, 0x20, 0x30, 0x20, 0x23, 0x20, 0x54, 0x52, 0x53, 0x54, 0x0d,
|
||||
0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46,
|
||||
0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f,
|
||||
0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54,
|
||||
0x45, 0x5f, 0x41, 0x43, 0x42, 0x55, 0x53, 0x31, 0x20, 0x20, 0x20, 0x30,
|
||||
0x20, 0x23, 0x20, 0x53, 0x52, 0x53, 0x54, 0x0d, 0x0a, 0x73, 0x65, 0x74,
|
||||
0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f,
|
||||
0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x45, 0x46, 0x41,
|
||||
0x55, 0x4c, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x43,
|
||||
0x42, 0x55, 0x53, 0x32, 0x20, 0x20, 0x20, 0x30, 0x20, 0x23, 0x20, 0x54,
|
||||
0x52, 0x53, 0x54, 0x20, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x20, 0x65,
|
||||
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50,
|
||||
0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45,
|
||||
0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c,
|
||||
0x54, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x43, 0x42, 0x55,
|
||||
0x53, 0x33, 0x20, 0x20, 0x20, 0x30, 0x20, 0x23, 0x20, 0x52, 0x45, 0x44,
|
||||
0x20, 0x4c, 0x45, 0x44, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23,
|
||||
0x20, 0x53, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x74,
|
||||
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x20, 0x47, 0x50, 0x49, 0x4f, 0x73, 0x20,
|
||||
0x70, 0x6f, 0x6c, 0x61, 0x72, 0x69, 0x74, 0x79, 0x0d, 0x0a, 0x23, 0x20,
|
||||
0x30, 0x20, 0x3a, 0x20, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x48,
|
||||
0x69, 0x67, 0x68, 0x2e, 0x0d, 0x0a, 0x23, 0x20, 0x31, 0x20, 0x3a, 0x20,
|
||||
0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x20, 0x4c, 0x6f, 0x77, 0x2e, 0x0d,
|
||||
0x0a, 0x23, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52,
|
||||
0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54,
|
||||
0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54,
|
||||
0x59, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x30, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50,
|
||||
0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45,
|
||||
0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49,
|
||||
0x54, 0x59, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x31, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20,
|
||||
0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53,
|
||||
0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52,
|
||||
0x49, 0x54, 0x59, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x32, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74,
|
||||
0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f,
|
||||
0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x50, 0x4f, 0x4c, 0x41,
|
||||
0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x33, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65,
|
||||
0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49,
|
||||
0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x50, 0x4f, 0x4c,
|
||||
0x41, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53, 0x34,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a, 0x73,
|
||||
0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44,
|
||||
0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x50, 0x4f,
|
||||
0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x44, 0x42, 0x55, 0x53,
|
||||
0x35, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0d, 0x0a,
|
||||
0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54,
|
||||
0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x50,
|
||||
0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x44, 0x42, 0x55,
|
||||
0x53, 0x36, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x0d,
|
||||
0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46,
|
||||
0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x5f,
|
||||
0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x44, 0x42,
|
||||
0x55, 0x53, 0x37, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30,
|
||||
0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42,
|
||||
0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50,
|
||||
0x49, 0x4e, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f,
|
||||
0x41, 0x43, 0x42, 0x55, 0x53, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x31, 0x20, 0x23, 0x20, 0x54, 0x52, 0x53, 0x54, 0x20, 0x69,
|
||||
0x73, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x2d, 0x6c, 0x6f, 0x77,
|
||||
0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f,
|
||||
0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49, 0x4e,
|
||||
0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x43,
|
||||
0x42, 0x55, 0x53, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45,
|
||||
0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50, 0x49,
|
||||
0x4e, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41,
|
||||
0x43, 0x42, 0x55, 0x53, 0x32, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42,
|
||||
0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x50,
|
||||
0x49, 0x4e, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x5f,
|
||||
0x41, 0x43, 0x42, 0x55, 0x53, 0x33, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x30, 0x0d, 0x0a, 0x0d, 0x0a, 0x23, 0x0d, 0x0a, 0x23, 0x20,
|
||||
0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54,
|
||||
0x52, 0x53, 0x54, 0x20, 0x2f, 0x20, 0x53, 0x52, 0x53, 0x54, 0x20, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20, 0x70, 0x69, 0x6e, 0x73, 0x0d,
|
||||
0x0a, 0x23, 0x20, 0x30, 0x3c, 0x3e, 0x37, 0x20, 0x20, 0x3a, 0x20, 0x41,
|
||||
0x44, 0x42, 0x55, 0x53, 0x0d, 0x0a, 0x23, 0x20, 0x38, 0x3c, 0x3e, 0x31,
|
||||
0x31, 0x20, 0x3a, 0x20, 0x41, 0x43, 0x42, 0x55, 0x53, 0x0d, 0x0a, 0x23,
|
||||
0x20, 0x53, 0x65, 0x74, 0x20, 0x74, 0x6f, 0x20, 0x2d, 0x31, 0x20, 0x77,
|
||||
0x68, 0x65, 0x6e, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x76, 0x61, 0x69,
|
||||
0x6c, 0x61, 0x62, 0x6c, 0x65, 0x2f, 0x75, 0x73, 0x65, 0x64, 0x2e, 0x0d,
|
||||
0x0a, 0x23, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52,
|
||||
0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54,
|
||||
0x5f, 0x54, 0x52, 0x53, 0x54, 0x5f, 0x4f, 0x45, 0x5f, 0x50, 0x49, 0x4e,
|
||||
0x4e, 0x55, 0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20,
|
||||
0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53,
|
||||
0x45, 0x54, 0x5f, 0x54, 0x52, 0x53, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x54,
|
||||
0x45, 0x5f, 0x50, 0x49, 0x4e, 0x4e, 0x55, 0x4d, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x0d, 0x0a, 0x0d, 0x0a, 0x73,
|
||||
0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44,
|
||||
0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x53, 0x52, 0x53, 0x54, 0x5f, 0x4f,
|
||||
0x45, 0x5f, 0x50, 0x49, 0x4e, 0x4e, 0x55, 0x4d, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x31, 0x0d,
|
||||
0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46,
|
||||
0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f, 0x53, 0x52, 0x53, 0x54,
|
||||
0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x50, 0x49, 0x4e, 0x4e, 0x55,
|
||||
0x4d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d,
|
||||
0x31, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f,
|
||||
0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f, 0x53, 0x45, 0x54, 0x5f,
|
||||
0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4c,
|
||||
0x45, 0x44, 0x5f, 0x50, 0x49, 0x4e, 0x4e, 0x55, 0x4d, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x31, 0x31, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74,
|
||||
0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x46, 0x54, 0x44, 0x49, 0x5f,
|
||||
0x4a, 0x54, 0x41, 0x47, 0x5f, 0x54, 0x52, 0x53, 0x54, 0x5f, 0x44, 0x45,
|
||||
0x4c, 0x41, 0x59, 0x5f, 0x4d, 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x30, 0x30, 0x0d, 0x0a,
|
||||
0x0d, 0x0a, 0x23, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x23, 0x20,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
|
||||
0x2d, 0x2d, 0x2d, 0x2d, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20,
|
||||
0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x47,
|
||||
0x50, 0x49, 0x4f, 0x5f, 0x45, 0x4e, 0x41, 0x42, 0x4c, 0x45, 0x20, 0x30,
|
||||
0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42,
|
||||
0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x47, 0x50, 0x49, 0x4f, 0x5f,
|
||||
0x42, 0x41, 0x53, 0x45, 0x5f, 0x46, 0x4f, 0x4c, 0x44, 0x45, 0x52, 0x20,
|
||||
0x22, 0x2f, 0x73, 0x79, 0x73, 0x2f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x2f,
|
||||
0x67, 0x70, 0x69, 0x6f, 0x22, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74,
|
||||
0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58,
|
||||
0x47, 0x50, 0x49, 0x4f, 0x5f, 0x54, 0x4d, 0x53, 0x5f, 0x50, 0x49, 0x4e,
|
||||
0x20, 0x32, 0x34, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f,
|
||||
0x42, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x47, 0x50, 0x49, 0x4f,
|
||||
0x5f, 0x54, 0x44, 0x49, 0x5f, 0x50, 0x49, 0x4e, 0x20, 0x32, 0x35, 0x0d,
|
||||
0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x4c,
|
||||
0x49, 0x4e, 0x55, 0x58, 0x47, 0x50, 0x49, 0x4f, 0x5f, 0x54, 0x44, 0x4f,
|
||||
0x5f, 0x50, 0x49, 0x4e, 0x20, 0x32, 0x36, 0x0d, 0x0a, 0x73, 0x65, 0x74,
|
||||
0x20, 0x50, 0x52, 0x4f, 0x42, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58,
|
||||
0x47, 0x50, 0x49, 0x4f, 0x5f, 0x54, 0x43, 0x4b, 0x5f, 0x50, 0x49, 0x4e,
|
||||
0x20, 0x32, 0x37, 0x0d, 0x0a, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50,
|
||||
0x52, 0x4f, 0x42, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x47, 0x50,
|
||||
0x49, 0x4f, 0x5f, 0x54, 0x4d, 0x53, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x49,
|
||||
0x4e, 0x56, 0x45, 0x52, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49,
|
||||
0x54, 0x59, 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52,
|
||||
0x4f, 0x42, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x47, 0x50, 0x49,
|
||||
0x4f, 0x5f, 0x54, 0x44, 0x49, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x49, 0x4e,
|
||||
0x56, 0x45, 0x52, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54,
|
||||
0x59, 0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f,
|
||||
0x42, 0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x47, 0x50, 0x49, 0x4f,
|
||||
0x5f, 0x54, 0x44, 0x4f, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x49, 0x4e, 0x56,
|
||||
0x45, 0x52, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59,
|
||||
0x20, 0x30, 0x0d, 0x0a, 0x73, 0x65, 0x74, 0x20, 0x50, 0x52, 0x4f, 0x42,
|
||||
0x45, 0x5f, 0x4c, 0x49, 0x4e, 0x55, 0x58, 0x47, 0x50, 0x49, 0x4f, 0x5f,
|
||||
0x54, 0x43, 0x4b, 0x5f, 0x50, 0x49, 0x4e, 0x5f, 0x49, 0x4e, 0x56, 0x45,
|
||||
0x52, 0x54, 0x5f, 0x50, 0x4f, 0x4c, 0x41, 0x52, 0x49, 0x54, 0x59, 0x20,
|
||||
0x30, 0x0d, 0x0a
|
||||
};
|
||||
unsigned int config_script_len = 5955;
|
||||
20
src/modules/config/version.h
Normal file
20
src/modules/config/version.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef _VERSION_H
|
||||
#define _VERSION_H
|
||||
|
||||
#define VDIG1 2
|
||||
#define VDIG2 6
|
||||
#define VDIG3 7
|
||||
#define VDIG4 1
|
||||
|
||||
#define STR_DATE "28 Oct 2024"
|
||||
|
||||
#define vxstr(s) vstr(s)
|
||||
#define vstr(s) #s
|
||||
|
||||
#define APP_VER VDIG1.VDIG2.VDIG3.VDIG4
|
||||
#define APP_VER_TXT_LONG( N ) JTAG Boundary Scanner v##N
|
||||
#define APP_VER_TXT( N ) v##N
|
||||
#define APP_VER_STR_LONG( N ) vxstr( APP_VER_TXT_LONG( N ) )
|
||||
#define APP_VER_STR( N ) vxstr( APP_VER_TXT( N ) )
|
||||
|
||||
#endif
|
||||
24
src/modules/drivers/CMakeLists.txt
Normal file
24
src/modules/drivers/CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
file(GLOB MAIN_SOURCES "*.c")
|
||||
file(GLOB_RECURSE JLINK_SOURCES "jlink_jtag/*.c")
|
||||
file(GLOB_RECURSE FTDI_SOURCES "ftdi_jtag/*.c")
|
||||
file(GLOB_RECURSE GPIO_SOURCES "linux_gpio_jtag/*.c")
|
||||
|
||||
set(DIGILENT_SOURCES "")
|
||||
if(BS_ENABLE_DIGILENT)
|
||||
file(GLOB_RECURSE DIGILENT_SOURCES "digilent_jtag/*.c")
|
||||
add_compile_definitions(BS_ENABLE_DIGILENT)
|
||||
endif()
|
||||
|
||||
include_directories(${DIR_MODULES})
|
||||
include_directories(${DIR_LIBS})
|
||||
|
||||
add_compile_definitions(FTD2XX_STATIC)
|
||||
add_compile_definitions(FTDILIB)
|
||||
|
||||
add_library(drivers ${MAIN_SOURCES} ${FTDI_SOURCES} ${GPIO_SOURCES} ${JLINK_SOURCES} ${DIGILENT_SOURCES})
|
||||
|
||||
if(BS_ENABLE_DIGILENT)
|
||||
target_link_libraries(drivers PUBLIC ${CMAKE_DL_LIBS})
|
||||
endif()
|
||||
408
src/modules/drivers/digilent_jtag/digilent_jtag_drv.c
Normal file
408
src/modules/drivers/digilent_jtag/digilent_jtag_drv.c
Normal file
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
* Boundary-Scan Explorer - Digilent JTAG-SMT* driver
|
||||
*
|
||||
* Talks to Digilent JTAG modules through libdjtg / libdmgr, loaded via
|
||||
* dlopen at runtime. No Digilent binary or header is embedded in this
|
||||
* repository; the typedefs below mirror the public Adept SDK ABI.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
#include "jtag_core/dbg_logs.h"
|
||||
#include "config/bs_defines.h"
|
||||
#include "script/env.h"
|
||||
|
||||
#include "drivers/drv_loader.h"
|
||||
|
||||
#include "digilent_jtag_drv.h"
|
||||
|
||||
#define MAX_PROBES_DIGILENT 8
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Adept SDK ABI mirrors (no Digilent headers included) */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
typedef int DJ_BOOL;
|
||||
typedef uint8_t DJ_BYTE;
|
||||
typedef uint32_t DJ_DWORD;
|
||||
typedef int32_t DJ_INT32;
|
||||
typedef DJ_DWORD DJ_HIF;
|
||||
typedef DJ_DWORD DJ_DTP;
|
||||
|
||||
#define DJ_CCH_DVC_NAME_MAX 64
|
||||
#define DJ_CCH_CONN_MAX 261 /* MAX_PATH(260) + 1 in dpcdecl.h */
|
||||
|
||||
#pragma pack(push, 16)
|
||||
typedef struct dj_dvc {
|
||||
char szName[DJ_CCH_DVC_NAME_MAX];
|
||||
char szConn[DJ_CCH_CONN_MAX];
|
||||
DJ_DTP dtp;
|
||||
} DJ_DVC;
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef DJ_BOOL (*pfn_DmgrEnumDevices)(int *pcdvc);
|
||||
typedef DJ_BOOL (*pfn_DmgrFreeDvcEnum)(void);
|
||||
typedef DJ_BOOL (*pfn_DmgrGetDvc)(int idvc, DJ_DVC *pdvc);
|
||||
typedef DJ_BOOL (*pfn_DmgrOpen)(DJ_HIF *phif, char *szSel);
|
||||
typedef DJ_BOOL (*pfn_DmgrClose)(DJ_HIF hif);
|
||||
typedef DJ_BOOL (*pfn_DjtgEnable)(DJ_HIF hif);
|
||||
typedef DJ_BOOL (*pfn_DjtgDisable)(DJ_HIF hif);
|
||||
typedef DJ_BOOL (*pfn_DjtgSetSpeed)(DJ_HIF hif, DJ_DWORD frqReq, DJ_DWORD *pfrqSet);
|
||||
typedef DJ_BOOL (*pfn_DjtgPutTdiBits)(DJ_HIF hif, DJ_BOOL fTms, DJ_BYTE *rgbSnd, DJ_BYTE *rgbRcv, DJ_DWORD cbits, DJ_BOOL fOverlap);
|
||||
typedef DJ_BOOL (*pfn_DjtgPutTmsBits)(DJ_HIF hif, DJ_BOOL fTdi, DJ_BYTE *rgbSnd, DJ_BYTE *rgbRcv, DJ_DWORD cbits, DJ_BOOL fOverlap);
|
||||
typedef DJ_BOOL (*pfn_DjtgPutTmsTdiBits)(DJ_HIF hif, DJ_BYTE *rgbSnd, DJ_BYTE *rgbRcv, DJ_DWORD cbitpairs, DJ_BOOL fOverlap);
|
||||
|
||||
static struct {
|
||||
void *libmgr;
|
||||
void *libjtg;
|
||||
pfn_DmgrEnumDevices EnumDevices;
|
||||
pfn_DmgrFreeDvcEnum FreeDvcEnum;
|
||||
pfn_DmgrGetDvc GetDvc;
|
||||
pfn_DmgrOpen Open;
|
||||
pfn_DmgrClose Close;
|
||||
pfn_DjtgEnable Enable;
|
||||
pfn_DjtgDisable Disable;
|
||||
pfn_DjtgSetSpeed SetSpeed;
|
||||
pfn_DjtgPutTdiBits PutTdiBits;
|
||||
pfn_DjtgPutTmsBits PutTmsBits;
|
||||
pfn_DjtgPutTmsTdiBits PutTmsTdiBits;
|
||||
} g_dj;
|
||||
|
||||
static int g_dj_loaded = 0; /* 0 = not tried, 1 = ok, -1 = failed */
|
||||
|
||||
static DJ_HIF g_dj_hif = 0;
|
||||
static int g_dj_open = 0;
|
||||
|
||||
static void digilent_atexit_close(void)
|
||||
{
|
||||
/* libdjtg/libdmgr are C++ internally — leaving an open HIF when
|
||||
* their static destructors run triggers "pure virtual method called"
|
||||
* during process shutdown. Force a clean Close from atexit. */
|
||||
if (g_dj_open && g_dj.Disable && g_dj.Close) {
|
||||
g_dj.Disable(g_dj_hif);
|
||||
g_dj.Close(g_dj_hif);
|
||||
g_dj_open = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int digilent_load(jtag_core *jc)
|
||||
{
|
||||
if (g_dj_loaded > 0) return 0;
|
||||
if (g_dj_loaded < 0) return -1;
|
||||
|
||||
g_dj.libmgr = dlopen("libdmgr.so", RTLD_LAZY);
|
||||
if (!g_dj.libmgr) {
|
||||
jtagcore_logs_printf(jc, MSG_INFO_1,
|
||||
"drv_Digilent : libdmgr.so not loadable (Adept Runtime not installed?) : %s\r\n",
|
||||
dlerror());
|
||||
g_dj_loaded = -1;
|
||||
return -1;
|
||||
}
|
||||
g_dj.libjtg = dlopen("libdjtg.so", RTLD_LAZY);
|
||||
if (!g_dj.libjtg) {
|
||||
jtagcore_logs_printf(jc, MSG_INFO_1,
|
||||
"drv_Digilent : libdjtg.so not loadable : %s\r\n", dlerror());
|
||||
dlclose(g_dj.libmgr); g_dj.libmgr = NULL;
|
||||
g_dj_loaded = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define RESOLVE(field, lib, name) \
|
||||
do { \
|
||||
g_dj.field = (pfn_##name)dlsym(g_dj.lib, #name); \
|
||||
if (!g_dj.field) { \
|
||||
jtagcore_logs_printf(jc, MSG_ERROR, \
|
||||
"drv_Digilent : dlsym(%s) failed\r\n", #name); \
|
||||
goto fail; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
RESOLVE(EnumDevices, libmgr, DmgrEnumDevices);
|
||||
RESOLVE(FreeDvcEnum, libmgr, DmgrFreeDvcEnum);
|
||||
RESOLVE(GetDvc, libmgr, DmgrGetDvc);
|
||||
RESOLVE(Open, libmgr, DmgrOpen);
|
||||
RESOLVE(Close, libmgr, DmgrClose);
|
||||
RESOLVE(Enable, libjtg, DjtgEnable);
|
||||
RESOLVE(Disable, libjtg, DjtgDisable);
|
||||
RESOLVE(SetSpeed, libjtg, DjtgSetSpeed);
|
||||
RESOLVE(PutTdiBits, libjtg, DjtgPutTdiBits);
|
||||
RESOLVE(PutTmsBits, libjtg, DjtgPutTmsBits);
|
||||
RESOLVE(PutTmsTdiBits, libjtg, DjtgPutTmsTdiBits);
|
||||
#undef RESOLVE
|
||||
|
||||
atexit(digilent_atexit_close);
|
||||
|
||||
g_dj_loaded = 1;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (g_dj.libjtg) dlclose(g_dj.libjtg);
|
||||
if (g_dj.libmgr) dlclose(g_dj.libmgr);
|
||||
memset(&g_dj, 0, sizeof(g_dj));
|
||||
g_dj_loaded = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Probe registry */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
typedef struct _digilent_drv_desc
|
||||
{
|
||||
char drv_id[64]; /* szName from DVC; passed to DmgrOpen as szSel */
|
||||
char drv_desc[128];
|
||||
int sub_drv_id;
|
||||
} digilent_drv_desc;
|
||||
|
||||
static digilent_drv_desc subdrv_list[MAX_PROBES_DIGILENT];
|
||||
static int g_dj_num_probes = 0;
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Viveris driver interface */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
static int drv_Digilent_Detect(jtag_core *jc)
|
||||
{
|
||||
int cdvc = 0;
|
||||
int i;
|
||||
|
||||
if (digilent_load(jc) < 0) {
|
||||
g_dj_num_probes = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!g_dj.EnumDevices(&cdvc)) {
|
||||
jtagcore_logs_printf(jc, MSG_INFO_1,
|
||||
"drv_Digilent_Detect : DmgrEnumDevices failed\r\n");
|
||||
g_dj_num_probes = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cdvc > MAX_PROBES_DIGILENT) cdvc = MAX_PROBES_DIGILENT;
|
||||
|
||||
for (i = 0; i < cdvc; i++) {
|
||||
DJ_DVC dvc;
|
||||
memset(&dvc, 0, sizeof(dvc));
|
||||
if (!g_dj.GetDvc(i, &dvc)) {
|
||||
snprintf(subdrv_list[i].drv_id, sizeof(subdrv_list[i].drv_id), "unknown%d", i);
|
||||
snprintf(subdrv_list[i].drv_desc, sizeof(subdrv_list[i].drv_desc), "Digilent (idx %d - DmgrGetDvc failed)", i);
|
||||
} else {
|
||||
snprintf(subdrv_list[i].drv_id, sizeof(subdrv_list[i].drv_id), "%s", dvc.szName);
|
||||
snprintf(subdrv_list[i].drv_desc, sizeof(subdrv_list[i].drv_desc), "Digilent: %s", dvc.szName);
|
||||
}
|
||||
subdrv_list[i].sub_drv_id = i;
|
||||
}
|
||||
|
||||
/* Release the enumeration table — required before EnumDevices can be
|
||||
* called again (e.g. a second jtag_probes / open by index). */
|
||||
g_dj.FreeDvcEnum();
|
||||
|
||||
g_dj_num_probes = cdvc;
|
||||
jtagcore_logs_printf(jc, MSG_INFO_1,
|
||||
"drv_Digilent_Detect : %d device(s) found\r\n", cdvc);
|
||||
return cdvc;
|
||||
}
|
||||
|
||||
static int drv_Digilent_Init(jtag_core *jc, int sub_drv, char *params)
|
||||
{
|
||||
DJ_DWORD frq_req;
|
||||
DJ_DWORD frq_set = 0;
|
||||
int tck_khz;
|
||||
|
||||
(void)params;
|
||||
|
||||
/* Driver-neutral JTAG clock (JTAG_TCK_FREQ_KHZ, kHz). Unset/<=0 keeps
|
||||
* the 4 MHz default — safe and fast enough for IDCODE/IR. */
|
||||
tck_khz = jtagcore_getEnvVarValue(jc, "JTAG_TCK_FREQ_KHZ");
|
||||
frq_req = (tck_khz > 0) ? (DJ_DWORD)tck_khz * 1000u : 4000000u;
|
||||
|
||||
/* Lazy enumeration: jtag_open can be called without going
|
||||
* through jtag_probes first, so make sure Detect ran. */
|
||||
if (g_dj_num_probes == 0) {
|
||||
drv_Digilent_Detect(jc);
|
||||
}
|
||||
if (g_dj_loaded != 1) {
|
||||
jtagcore_logs_printf(jc, MSG_ERROR,
|
||||
"drv_Digilent_Init : Adept libs not loadable\r\n");
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
if (sub_drv < 0 || sub_drv >= g_dj_num_probes) {
|
||||
jtagcore_logs_printf(jc, MSG_ERROR,
|
||||
"drv_Digilent_Init : sub_drv %d out of range (have %d)\r\n",
|
||||
sub_drv, g_dj_num_probes);
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
if (g_dj_open) {
|
||||
g_dj.Disable(g_dj_hif);
|
||||
g_dj.Close(g_dj_hif);
|
||||
g_dj_open = 0;
|
||||
}
|
||||
|
||||
if (!g_dj.Open(&g_dj_hif, subdrv_list[sub_drv].drv_id)) {
|
||||
jtagcore_logs_printf(jc, MSG_ERROR,
|
||||
"drv_Digilent_Init : DmgrOpen(\"%s\") failed\r\n",
|
||||
subdrv_list[sub_drv].drv_id);
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
if (!g_dj.Enable(g_dj_hif)) {
|
||||
jtagcore_logs_printf(jc, MSG_ERROR,
|
||||
"drv_Digilent_Init : DjtgEnable failed\r\n");
|
||||
g_dj.Close(g_dj_hif);
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
if (!g_dj.SetSpeed(g_dj_hif, frq_req, &frq_set)) {
|
||||
jtagcore_logs_printf(jc, MSG_WARNING,
|
||||
"drv_Digilent_Init : DjtgSetSpeed failed, keeping default speed\r\n");
|
||||
} else {
|
||||
jtagcore_logs_printf(jc, MSG_INFO_0,
|
||||
"drv_Digilent_Init : JTAG clock = %u Hz (requested %u)\r\n",
|
||||
(unsigned)frq_set, (unsigned)frq_req);
|
||||
}
|
||||
|
||||
g_dj_open = 1;
|
||||
jtagcore_logs_printf(jc, MSG_INFO_0,
|
||||
"drv_Digilent_Init : opened \"%s\"\r\n", subdrv_list[sub_drv].drv_id);
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
|
||||
static int drv_Digilent_DeInit(jtag_core *jc)
|
||||
{
|
||||
(void)jc;
|
||||
if (g_dj_open) {
|
||||
g_dj.Disable(g_dj_hif);
|
||||
g_dj.Close(g_dj_hif);
|
||||
g_dj_open = 0;
|
||||
}
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Bit packing on the wire (Adept API): LSB-first within each byte.
|
||||
* For DjtgPutTmsTdiBits, each clock takes a 2-bit pair where the lower
|
||||
* bit is TDI and the upper bit is TMS (verified against DjtgDemo
|
||||
* sample: rgbSetup = {0xaa, 0x22, 0x00} for the 9-clock TLR->Shift-DR
|
||||
* sequence with TDI held at 0). */
|
||||
|
||||
static int drv_Digilent_TMS_xfer(jtag_core *jc, unsigned char *str_out, int size)
|
||||
{
|
||||
DJ_BYTE *buf_snd;
|
||||
int nbytes = (size + 7) / 8;
|
||||
int i, ok;
|
||||
|
||||
if (!g_dj_open) return JTAG_CORE_BAD_PARAMETER;
|
||||
if (size <= 0) return JTAG_CORE_NO_ERROR;
|
||||
|
||||
/* Heap-allocated and sized to the shift: a bitstream load shifts
|
||||
* millions of bits in one call, far past any fixed buffer. */
|
||||
buf_snd = calloc(1, (size_t)nbytes);
|
||||
if (!buf_snd) return JTAG_CORE_BAD_PARAMETER;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (str_out[i] & JTAG_STR_TMS)
|
||||
buf_snd[i >> 3] |= (DJ_BYTE)(1u << (i & 7));
|
||||
}
|
||||
|
||||
ok = g_dj.PutTmsBits(g_dj_hif, /*fTdi=*/0, buf_snd, NULL, (DJ_DWORD)size, /*fOverlap=*/0);
|
||||
free(buf_snd);
|
||||
if (!ok) {
|
||||
jtagcore_logs_printf(jc, MSG_ERROR,
|
||||
"drv_Digilent_TMS_xfer : DjtgPutTmsBits failed\r\n");
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
|
||||
static int drv_Digilent_TDOTDI_xfer(jtag_core *jc,
|
||||
unsigned char *str_out,
|
||||
unsigned char *str_in,
|
||||
int size)
|
||||
{
|
||||
DJ_BYTE *buf_snd, *buf_rcv = NULL;
|
||||
int has_tms = 0;
|
||||
int i, ok, snd_bytes;
|
||||
|
||||
if (!g_dj_open) return JTAG_CORE_BAD_PARAMETER;
|
||||
if (size <= 0) return JTAG_CORE_NO_ERROR;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (str_out[i] & JTAG_STR_TMS) { has_tms = 1; break; }
|
||||
}
|
||||
|
||||
if (str_in) {
|
||||
buf_rcv = calloc(1, (size_t)((size + 7) / 8));
|
||||
if (!buf_rcv) return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
/* PutTmsTdiBits packs 2 bits/clock, PutTdiBits 1 bit/clock. Buffers
|
||||
* are heap-sized to the shift (bitstream loads run into MB). */
|
||||
snd_bytes = has_tms ? (2 * size + 7) / 8 : (size + 7) / 8;
|
||||
buf_snd = calloc(1, (size_t)snd_bytes);
|
||||
if (!buf_snd) { free(buf_rcv); return JTAG_CORE_BAD_PARAMETER; }
|
||||
|
||||
if (has_tms) {
|
||||
/* 2 bits per clock: TDI low, TMS high, LSB-first. */
|
||||
for (i = 0; i < size; i++) {
|
||||
int pos = 2 * i;
|
||||
if (str_out[i] & JTAG_STR_DOUT)
|
||||
buf_snd[pos >> 3] |= (DJ_BYTE)(1u << (pos & 7));
|
||||
pos++;
|
||||
if (str_out[i] & JTAG_STR_TMS)
|
||||
buf_snd[pos >> 3] |= (DJ_BYTE)(1u << (pos & 7));
|
||||
}
|
||||
ok = g_dj.PutTmsTdiBits(g_dj_hif, buf_snd, buf_rcv, (DJ_DWORD)size, /*fOverlap=*/0);
|
||||
} else {
|
||||
/* Pure data shift: TMS held to 0, 1 bit per clock. */
|
||||
for (i = 0; i < size; i++) {
|
||||
if (str_out[i] & JTAG_STR_DOUT)
|
||||
buf_snd[i >> 3] |= (DJ_BYTE)(1u << (i & 7));
|
||||
}
|
||||
ok = g_dj.PutTdiBits(g_dj_hif, /*fTms=*/0, buf_snd, buf_rcv, (DJ_DWORD)size, /*fOverlap=*/0);
|
||||
}
|
||||
free(buf_snd);
|
||||
|
||||
if (!ok) {
|
||||
free(buf_rcv);
|
||||
jtagcore_logs_printf(jc, MSG_ERROR,
|
||||
"drv_Digilent_TDOTDI_xfer : Djtg shift failed (size %d)\r\n", size);
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
if (str_in) {
|
||||
for (i = 0; i < size; i++) {
|
||||
str_in[i] = (buf_rcv[i >> 3] & (1u << (i & 7))) ? JTAG_STR_DOUT : 0;
|
||||
}
|
||||
free(buf_rcv);
|
||||
}
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
|
||||
int drv_Digilent_libGetDrv(jtag_core *jc, int sub_drv, unsigned int infotype, void *returnvalue)
|
||||
{
|
||||
drv_ptr drv_funcs = {
|
||||
(DRV_DETECT) drv_Digilent_Detect,
|
||||
(DRV_INIT) drv_Digilent_Init,
|
||||
(DRV_DEINIT) drv_Digilent_DeInit,
|
||||
(DRV_TXTMS) drv_Digilent_TMS_xfer,
|
||||
(DRV_TXRXDATA) drv_Digilent_TDOTDI_xfer,
|
||||
(DRV_GETMODULEINFOS) drv_Digilent_libGetDrv,
|
||||
};
|
||||
|
||||
if (sub_drv < 0 || sub_drv >= MAX_PROBES_DIGILENT)
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
|
||||
return GetDrvInfo(
|
||||
jc,
|
||||
infotype,
|
||||
returnvalue,
|
||||
subdrv_list[sub_drv].drv_id,
|
||||
subdrv_list[sub_drv].drv_desc,
|
||||
&drv_funcs
|
||||
);
|
||||
}
|
||||
18
src/modules/drivers/digilent_jtag/digilent_jtag_drv.h
Normal file
18
src/modules/drivers/digilent_jtag/digilent_jtag_drv.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _DIGILENT_JTAG_DRV_H
|
||||
#define _DIGILENT_JTAG_DRV_H
|
||||
/*
|
||||
* Boundary-Scan Explorer - Digilent JTAG-SMT* driver
|
||||
*
|
||||
* Talks to Digilent JTAG modules (SMT2, SMT2-NC, SMT3, ...) through
|
||||
* dlopen of libdjtg.so / libdmgr.so at runtime. No Digilent binary or
|
||||
* header is embedded in this repository; the typedefs in djtg_dlsym.h
|
||||
* are hand-rolled from the public Adept API.
|
||||
*
|
||||
* Enabled with -DBS_ENABLE_DIGILENT=ON at CMake configure time.
|
||||
*/
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
|
||||
int drv_Digilent_libGetDrv(jtag_core * jc, int sub_drv, unsigned int infotype, void * returnvalue);
|
||||
|
||||
#endif
|
||||
69
src/modules/drivers/drivers_list.c
Normal file
69
src/modules/drivers/drivers_list.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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 drivers_list.h
|
||||
* @brief drivers list
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
|
||||
#include "bsdl_parser/bsdl_loader.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include "./lpt_jtag/lpt_jtag_drv.h"
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
#include "./linux_gpio_jtag/linux_gpio_jtag_drv.h"
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(WIN32)
|
||||
#include "./ftdi_jtag/ftdi_jtag_drv.h"
|
||||
#include "./jlink_jtag/jlink_jtag_drv.h"
|
||||
#endif
|
||||
|
||||
#ifdef BS_ENABLE_DIGILENT
|
||||
#include "./digilent_jtag/digilent_jtag_drv.h"
|
||||
#endif
|
||||
|
||||
#include "drivers_list.h"
|
||||
|
||||
const drv_entry staticdrvs[] =
|
||||
{
|
||||
#ifdef WIN32
|
||||
#if !defined(_WIN64)
|
||||
{(DRV_GETMODULEINFOS)drv_LPT_libGetDrv,0},
|
||||
{(DRV_GETMODULEINFOS)drv_LPT_libGetDrv,1},
|
||||
{(DRV_GETMODULEINFOS)drv_LPT_libGetDrv,2},
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__linux__) || defined(WIN32)
|
||||
{(DRV_GETMODULEINFOS)drv_FTDI_libGetDrv,0},
|
||||
{(DRV_GETMODULEINFOS)drv_JLINK_libGetDrv,0},
|
||||
#endif
|
||||
#if defined(__linux__)
|
||||
{(DRV_GETMODULEINFOS)drv_LinuxGPIO_libGetDrv,0},
|
||||
#endif
|
||||
#ifdef BS_ENABLE_DIGILENT
|
||||
{(DRV_GETMODULEINFOS)drv_Digilent_libGetDrv,0},
|
||||
#endif
|
||||
{(DRV_GETMODULEINFOS)-1,0}
|
||||
};
|
||||
35
src/modules/drivers/drivers_list.h
Normal file
35
src/modules/drivers/drivers_list.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef _DRIVERS_LIST_H
|
||||
#define _DRIVERS_LIST_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 drivers_list.h
|
||||
* @brief drivers list struct
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
typedef struct _drv_entry
|
||||
{
|
||||
DRV_GETMODULEINFOS getinfosfunc;
|
||||
int sub_drv_id;
|
||||
}drv_entry;
|
||||
|
||||
extern const drv_entry staticdrvs[];
|
||||
|
||||
#endif
|
||||
117
src/modules/drivers/drv_loader.c
Normal file
117
src/modules/drivers/drv_loader.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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 drv_loader.c
|
||||
* @brief driver loader
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
|
||||
#include "bsdl_parser/bsdl_loader.h"
|
||||
|
||||
#include "drivers_list.h"
|
||||
|
||||
#include "jtag_core/dbg_logs.h"
|
||||
|
||||
int GetDrvInfo(void * jc_ctx,unsigned long infotype,void * returnvalue,const char * drv_id,const char * drv_desc,drv_ptr * drv_func)
|
||||
{
|
||||
if(jc_ctx)
|
||||
{
|
||||
if(returnvalue)
|
||||
{
|
||||
switch(infotype)
|
||||
{
|
||||
case GET_DRV_ID:
|
||||
*(char**)(returnvalue)=(char*)drv_id;
|
||||
break;
|
||||
|
||||
case GET_DRV_DESCRIPTION:
|
||||
strcpy(returnvalue, (char*)drv_desc);
|
||||
break;
|
||||
|
||||
case GET_DRV_FUNCPTR:
|
||||
memcpy(returnvalue,drv_func,sizeof(drv_ptr));
|
||||
break;
|
||||
|
||||
case GET_DRV_DETECT:
|
||||
*((int*)(returnvalue)) = drv_func->drv_Detect(jc_ctx);
|
||||
break;
|
||||
|
||||
default:
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
}
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
|
||||
int jtagcore_loaddriver(jtag_core * jc, int id, char * parameters)
|
||||
{
|
||||
int i,ret;
|
||||
i = 0;
|
||||
|
||||
while (staticdrvs[i].getinfosfunc != (DRV_GETMODULEINFOS)-1 )
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
if ( (id >> 8) < i)
|
||||
{
|
||||
if (jc->io_functions.drv_DeInit)
|
||||
{
|
||||
jc->io_functions.drv_DeInit(jc);
|
||||
memset(&jc->io_functions, 0, sizeof(drv_ptr));
|
||||
}
|
||||
|
||||
staticdrvs[id>>8].getinfosfunc(jc, id & 0xFF, GET_DRV_FUNCPTR, &jc->io_functions);
|
||||
|
||||
if( jc->io_functions.drv_Init )
|
||||
{
|
||||
ret = jc->io_functions.drv_Init(jc, id & 0xFF,0);
|
||||
if (ret < 0)
|
||||
{
|
||||
jtagcore_logs_printf(jc, MSG_ERROR, "jtagcore_loaddriver : Can't load the driver !\r\n");
|
||||
memset(&jc->io_functions, 0, sizeof(drv_ptr));
|
||||
}
|
||||
else
|
||||
{
|
||||
jtagcore_logs_printf(jc, MSG_INFO_0, "jtagcore_loaddriver : Probe Driver 0x%.8X loaded...\r\n", id);
|
||||
}
|
||||
}
|
||||
else
|
||||
goto fail;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
fail:
|
||||
jtagcore_logs_printf(jc, MSG_ERROR, "jtagcore_loaddriver : Driver ID not found !\r\n");
|
||||
|
||||
return JTAG_CORE_NOT_FOUND;
|
||||
};
|
||||
|
||||
32
src/modules/drivers/drv_loader.h
Normal file
32
src/modules/drivers/drv_loader.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef _DRV_LOADER_H
|
||||
#define _DRV_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 drv_loader.h
|
||||
* @brief driver functions definitions
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include "config/bs_defines.h"
|
||||
|
||||
int GetDrvInfo(void * jc_ctx, unsigned long infotype, void * returnvalue, const char * drv_id, const char * drv_desc, drv_ptr * drv_func);
|
||||
|
||||
#endif
|
||||
953
src/modules/drivers/ftdi_jtag/ftdi_jtag_drv.c
Normal file
953
src/modules/drivers/ftdi_jtag/ftdi_jtag_drv.c
Normal file
@@ -0,0 +1,953 @@
|
||||
/*
|
||||
* 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 ftdi_jtag_drv.c
|
||||
* @brief FTDI based probes driver
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(WIN32)
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "script/env.h"
|
||||
#include "jtag_core/jtag_core.h"
|
||||
#include "drivers/drv_loader.h"
|
||||
#include "jtag_core/dbg_logs.h"
|
||||
#include "os_interface/os_interface.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "libftd2xx/ftd2xx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_WIN64)
|
||||
#define MACH_WORD long long
|
||||
#else
|
||||
#define MACH_WORD int
|
||||
#endif
|
||||
|
||||
typedef struct _drv_desc
|
||||
{
|
||||
char drv_id[128];
|
||||
char drv_desc[128];
|
||||
int id;
|
||||
int ftdi_index;
|
||||
}drv_desc;
|
||||
|
||||
#define PROBE_GENERIC_FTDI 0
|
||||
|
||||
#define MAX_PROBES_FTDI 8
|
||||
|
||||
static drv_desc subdrv_list[MAX_PROBES_FTDI]=
|
||||
{
|
||||
{"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0},
|
||||
{"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0},
|
||||
{"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0},
|
||||
{"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0},
|
||||
{"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0},
|
||||
{"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0},
|
||||
{"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0},
|
||||
{"USB_GENERIC_FTDI_PROBE","GENERIC USB FTDI PROBE",PROBE_GENERIC_FTDI,0}
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Command Processor for MPSSE and MCU Host Bus Emulation Modes
|
||||
//
|
||||
// The data shifting commands are made up of the following definitions:
|
||||
// Bit 7 : 0
|
||||
// Bit 6 : Do write TMS
|
||||
// Bit 5 : Do read TDO
|
||||
// Bit 4 : Do write TDI
|
||||
// Bit 3 : LSB first = 1 else MSB first = 0
|
||||
// Bit 2 : -ve CLK on read
|
||||
// Bit 1 : bit mode = 1 else byte mode = 0
|
||||
// Bit 0 : -ve CLK on write
|
||||
|
||||
// The write commands to TDI take effect when bits 7 and 6 are '0'. Read TDO will operate with TMS output or TDI output or on its own.
|
||||
|
||||
// Clock Data Bytes Out on +ve clock edge MSB first (no read)
|
||||
// 0x10, LengthL, LengthH, [Byte1..Byte65536 (max)]
|
||||
|
||||
#define OP_WR_TMS (0x1 << 6)
|
||||
#define OP_RD_TDO (0x1 << 5)
|
||||
#define OP_WR_TDI (0x1 << 4)
|
||||
#define OP_LSB_FIRST (0x1 << 3)
|
||||
#define OP_FEDGE_RD (0x1 << 2)
|
||||
#define OP_BIT_MODE (0x1 << 1)
|
||||
#define OP_FEDGE_WR (0x1 << 0)
|
||||
|
||||
#define CMD_ENABLE_LOOPBACK 0x84
|
||||
#define CMD_DISABLE_LOOPBACK 0x85
|
||||
#define CMD_SET_DIVISOR 0x86 // +0xValueL, 0xValueH
|
||||
#define CMD_WAIT_IO_HIGH 0x88
|
||||
#define CMD_WAIT_IO_LOW 0x89
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static FT_HANDLE ftdih = NULL;
|
||||
static FT_DEVICE ftdi_device;
|
||||
|
||||
static int trst_oe_pin, trst_state_pin;
|
||||
static int srst_oe_pin, srst_state_pin;
|
||||
static int led_pin;
|
||||
|
||||
static unsigned char low_direction;
|
||||
static unsigned char low_polarity;
|
||||
static unsigned char low_output;
|
||||
|
||||
static unsigned char high_output;
|
||||
static unsigned char high_polarity;
|
||||
static unsigned char high_direction;
|
||||
|
||||
unsigned char ftdi_out_buf[64 * 1024];
|
||||
unsigned char ftdi_in_buf[64 * 1024];
|
||||
|
||||
#if !defined(WIN32)
|
||||
|
||||
int Sleep( unsigned int timeout_ms )
|
||||
{
|
||||
struct timeval tv;
|
||||
tv.tv_sec = timeout_ms/1000;
|
||||
tv.tv_usec = (timeout_ms%1000) * 1000;
|
||||
select(0, NULL, NULL, NULL, &tv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined(FTDILIB)
|
||||
|
||||
typedef FT_STATUS(WINAPI * FT_OPEN)(DWORD deviceNumber, FT_HANDLE *pHandle);
|
||||
typedef FT_STATUS(WINAPI * FT_OPENEX)(PVOID pArg1, DWORD Flags, FT_HANDLE *pHandle);
|
||||
typedef FT_STATUS(WINAPI * FT_READ)(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesReturned);
|
||||
typedef FT_STATUS(WINAPI * FT_WRITE)(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesWritten);
|
||||
typedef FT_STATUS(WINAPI * FT_GETSTATUS)(FT_HANDLE ftHandle, DWORD *dwRxBytes, DWORD *dwTxBytes, DWORD *dwEventDWord);
|
||||
typedef FT_STATUS(WINAPI * FT_PURGE)(FT_HANDLE ftHandle, ULONG Mask);
|
||||
typedef FT_STATUS(WINAPI * FT_SETUSBPARAMETERS)(FT_HANDLE ftHandle, ULONG ulInTransferSize, ULONG ulOutTransferSize);
|
||||
typedef FT_STATUS(WINAPI * FT_SETLATENCYTIMER)(FT_HANDLE ftHandle, UCHAR ucLatency);
|
||||
typedef FT_STATUS(WINAPI * FT_SETEVENTNOTIFICATION)(FT_HANDLE ftHandle, DWORD dwEventMask, PVOID pvArg);
|
||||
typedef FT_STATUS(WINAPI * FT_CLOSE)(FT_HANDLE ftHandle);
|
||||
typedef FT_STATUS(WINAPI * FT_LISTDEVICES)(LPVOID pArg1, LPVOID pArg2, DWORD Flags);
|
||||
typedef FT_STATUS(WINAPI * FT_SETBITMODE)(FT_HANDLE ftHandle, UCHAR ucMask, UCHAR ucEnable);
|
||||
typedef FT_STATUS(WINAPI * FT_SETTIMEOUTS)(FT_HANDLE ftHandle, ULONG ReadTimeout, ULONG WriteTimeout);
|
||||
typedef FT_STATUS(WINAPI * FT_GETQUEUESTATUS)(FT_HANDLE ftHandle, DWORD *dwRxBytes);
|
||||
typedef FT_STATUS(WINAPI * FT_GETDEVICEINFO)(FT_HANDLE ftHandle, FT_DEVICE *lpftDevice, LPDWORD lpdwID, PCHAR SerialNumber, PCHAR Description, LPVOID Dummy);
|
||||
typedef FT_STATUS(WINAPI * FT_RESETDEVICE)(FT_HANDLE ftHandle);
|
||||
typedef FT_STATUS(WINAPI * FT_SETCHARS)(FT_HANDLE ftHandle, UCHAR EventChar, UCHAR EventCharEnabled, UCHAR ErrorChar, UCHAR ErrorCharEnabled);
|
||||
|
||||
FT_OPEN pFT_Open;
|
||||
FT_OPENEX pFT_OpenEx;
|
||||
FT_READ pFT_Read;
|
||||
FT_WRITE pFT_Write;
|
||||
FT_GETSTATUS pFT_GetStatus;
|
||||
FT_PURGE pFT_Purge;
|
||||
FT_SETUSBPARAMETERS pFT_SetUSBParameters;
|
||||
FT_SETLATENCYTIMER pFT_SetLatencyTimer;
|
||||
FT_SETEVENTNOTIFICATION pFT_SetEventNotification;
|
||||
FT_CLOSE pFT_Close;
|
||||
FT_LISTDEVICES pFT_ListDevices;
|
||||
FT_SETBITMODE pFT_SetBitMode;
|
||||
FT_SETTIMEOUTS pFT_SetTimeouts;
|
||||
FT_GETQUEUESTATUS pFT_GetQueueStatus;
|
||||
FT_GETDEVICEINFO pFT_GetDeviceInfo;
|
||||
FT_RESETDEVICE pFT_ResetDevice;
|
||||
FT_SETCHARS pFT_SetChars;
|
||||
|
||||
#else
|
||||
#define pFT_Open FT_Open
|
||||
#define pFT_OpenEx FT_OpenEx
|
||||
#define pFT_Read FT_Read
|
||||
#define pFT_Write FT_Write
|
||||
#define pFT_GetStatus FT_GetStatus
|
||||
#define pFT_Purge FT_Purge
|
||||
#define pFT_SetUSBParameters FT_SetUSBParameters
|
||||
#define pFT_SetLatencyTimer FT_SetLatencyTimer
|
||||
#define pFT_SetEventNotification FT_SetEventNotification
|
||||
#define pFT_Close FT_Close
|
||||
#define pFT_ListDevices FT_ListDevices
|
||||
#define pFT_SetBitMode FT_SetBitMode
|
||||
#define pFT_SetTimeouts FT_SetTimeouts
|
||||
#define pFT_GetQueueStatus FT_GetQueueStatus
|
||||
#define pFT_GetDeviceInfo FT_GetDeviceInfo
|
||||
#define pFT_ResetDevice FT_ResetDevice
|
||||
#define pFT_SetChars FT_SetChars
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static int ft2232_set_data_bits_low_byte(unsigned char value, unsigned char direction)
|
||||
{
|
||||
FT_STATUS status;
|
||||
DWORD dw_bytes_written = 0;
|
||||
unsigned char buf[3];
|
||||
|
||||
buf[0] = 0x80; // command "set data bits low byte"
|
||||
buf[1] = value; // value
|
||||
buf[2] = direction; // direction
|
||||
|
||||
status = pFT_Write(ftdih, buf, sizeof(buf), &dw_bytes_written);
|
||||
if ( (status != FT_OK) || (dw_bytes_written != sizeof(buf) ) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ft2232_set_data_bits_high_byte(unsigned char value, unsigned char direction)
|
||||
{
|
||||
FT_STATUS status;
|
||||
DWORD dw_bytes_written = 0;
|
||||
unsigned char buf[3];
|
||||
|
||||
buf[0] = 0x82; // command "set data bits high byte"
|
||||
buf[1] = value; // value
|
||||
buf[2] = direction; // direction
|
||||
|
||||
status = pFT_Write(ftdih, buf, sizeof(buf), &dw_bytes_written);
|
||||
if ( (status != FT_OK) || ( dw_bytes_written != sizeof(buf) ) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ft2232h_enable_rtck(int enable)
|
||||
{
|
||||
FT_STATUS status;
|
||||
DWORD dw_bytes_written = 0;
|
||||
unsigned char buf;
|
||||
|
||||
buf = enable ? 0x96 : 0x97;
|
||||
|
||||
status = pFT_Write(ftdih, &buf, sizeof(buf), &dw_bytes_written);
|
||||
if ( (status != FT_OK) || ( dw_bytes_written != sizeof(buf) ) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drv_FTDI_Detect(jtag_core * jc)
|
||||
{
|
||||
int numDevs,i;
|
||||
FT_STATUS status;
|
||||
char SerialNumber[512];
|
||||
|
||||
status = pFT_ListDevices(&numDevs, NULL, FT_LIST_NUMBER_ONLY);
|
||||
if (status != FT_OK && !numDevs)
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_ListDevices : Error %x !\r\n",status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
while( i<numDevs && i<MAX_PROBES_FTDI )
|
||||
{
|
||||
status = pFT_ListDevices((LPVOID)(MACH_WORD)i, SerialNumber, FT_LIST_BY_INDEX | FT_OPEN_BY_DESCRIPTION);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_ListDevices : Error %x !\r\n",status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy(subdrv_list[i].drv_id,SerialNumber);
|
||||
strcpy(subdrv_list[i].drv_desc,SerialNumber);
|
||||
strcat(subdrv_list[i].drv_desc," ");
|
||||
|
||||
status = pFT_ListDevices((LPVOID)(MACH_WORD)i, SerialNumber, FT_LIST_BY_INDEX | FT_OPEN_BY_SERIAL_NUMBER);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_ListDevices : Error %x !\r\n",status);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcat(subdrv_list[i].drv_desc,SerialNumber);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
jtagcore_logs_printf( jc, MSG_INFO_1, "drv_FTDI_Detect : %d interface(s) found !\r\n", numDevs );
|
||||
|
||||
return numDevs;
|
||||
|
||||
}
|
||||
|
||||
void update_gpio_state(int index,int state)
|
||||
{
|
||||
if( index >=0 )
|
||||
{
|
||||
if(index < 8)
|
||||
{
|
||||
if(state)
|
||||
low_output |= (0x01<<index);
|
||||
else
|
||||
low_output &= ~(0x01<<index);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(state)
|
||||
high_output |= (0x01<<(index - 8));
|
||||
else
|
||||
high_output &= ~(0x01<<(index - 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int drv_FTDI_Init(jtag_core * jc, int sub_drv, char * params)
|
||||
{
|
||||
FT_STATUS status;
|
||||
DWORD deviceID;
|
||||
char SerialNumber[16];
|
||||
char Description[64];
|
||||
char tmp_str[64];
|
||||
int numDevs;
|
||||
int baseclock, divisor, tckfreq;
|
||||
DWORD devIndex;
|
||||
DWORD nbRead,nbtosend;
|
||||
int i;
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
if(lib_handle == NULL)
|
||||
lib_handle = LoadLibrary("ftd2xx.dll");
|
||||
|
||||
if (lib_handle)
|
||||
{
|
||||
pFT_Write = (FT_WRITE)GetProcAddress(lib_handle, "FT_Write");
|
||||
if (!pFT_Write)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_Read = (FT_READ)GetProcAddress(lib_handle, "FT_Read");
|
||||
if (!pFT_Read)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_GetStatus = (FT_GETSTATUS)GetProcAddress(lib_handle, "FT_GetStatus");
|
||||
if (!pFT_GetStatus)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_Open = (FT_OPEN)GetProcAddress(lib_handle, "FT_Open");
|
||||
if (!pFT_Open)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_Close = (FT_CLOSE)GetProcAddress(lib_handle, "FT_Close");
|
||||
if (!pFT_Close)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_Purge = (FT_PURGE)GetProcAddress(lib_handle, "FT_Purge");
|
||||
if (!pFT_Purge)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_SetUSBParameters = (FT_SETUSBPARAMETERS)GetProcAddress(lib_handle, "FT_SetUSBParameters");
|
||||
if (!pFT_SetUSBParameters)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_SetLatencyTimer = (FT_SETLATENCYTIMER)GetProcAddress(lib_handle, "FT_SetLatencyTimer");
|
||||
if (!pFT_SetLatencyTimer)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_SetEventNotification = (FT_SETEVENTNOTIFICATION)GetProcAddress(lib_handle, "FT_SetEventNotification");
|
||||
if (!pFT_SetEventNotification)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_OpenEx = (FT_OPENEX)GetProcAddress(lib_handle, "FT_OpenEx");
|
||||
if (!pFT_OpenEx)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_ListDevices = (FT_LISTDEVICES)GetProcAddress(lib_handle, "FT_ListDevices");
|
||||
if (!pFT_ListDevices)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_SetBitMode = (FT_SETBITMODE)GetProcAddress(lib_handle, "FT_SetBitMode");
|
||||
if (!pFT_SetBitMode)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_SetTimeouts = (FT_SETTIMEOUTS)GetProcAddress(lib_handle, "FT_SetTimeouts");
|
||||
if (!pFT_SetTimeouts)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_GetQueueStatus = (FT_GETQUEUESTATUS)GetProcAddress(lib_handle, "FT_GetQueueStatus");
|
||||
if (!pFT_GetQueueStatus)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_GetDeviceInfo = (FT_GETDEVICEINFO)GetProcAddress(lib_handle, "FT_GetDeviceInfo");
|
||||
if (!pFT_GetDeviceInfo)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_ResetDevice = (FT_RESETDEVICE)GetProcAddress(lib_handle, "FT_ResetDevice");
|
||||
if (!pFT_ResetDevice)
|
||||
goto loadliberror;
|
||||
|
||||
pFT_SetChars = (FT_SETCHARS)GetProcAddress(lib_handle, "FT_SetChars");
|
||||
if (!pFT_SetChars)
|
||||
goto loadliberror;
|
||||
}
|
||||
else
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"drv_FTDI_Init : Can't open ftd2xx.dll !\r\n");
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
status = pFT_ListDevices(&numDevs, NULL, FT_LIST_NUMBER_ONLY);
|
||||
if (status != FT_OK && !numDevs)
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_ListDevices : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
devIndex = sub_drv;
|
||||
status = pFT_ListDevices((LPVOID)(MACH_WORD)devIndex, SerialNumber, FT_LIST_BY_INDEX | FT_OPEN_BY_SERIAL_NUMBER);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_ListDevices : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
status = pFT_OpenEx(SerialNumber, FT_OPEN_BY_SERIAL_NUMBER, &ftdih);
|
||||
if (status != FT_OK)
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_OpenEx : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
status = pFT_ResetDevice(ftdih);
|
||||
if (status != FT_OK) {
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_ResetDevice : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
status = pFT_GetQueueStatus(ftdih, &nbRead);
|
||||
if (status != FT_OK) {
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_GetQueueStatus : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
if ( nbRead > 0)
|
||||
pFT_Read(ftdih, &ftdi_in_buf, nbRead, &nbRead);
|
||||
|
||||
//Set USB request transfer sizes to 64K
|
||||
status = pFT_SetUSBParameters(ftdih, 65536, 65535);
|
||||
if (status != FT_OK) {
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_SetUSBParameters : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
//Disable event and error characters
|
||||
status = pFT_SetChars(ftdih, 0, 0, 0, 0);
|
||||
if (status != FT_OK) {
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_SetChars : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
//Sets the read and write timeouts in milliseconds
|
||||
status = pFT_SetTimeouts(ftdih, 5000, 5000);
|
||||
if (status != FT_OK) {
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_SetTimeouts : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
//Set the latency timer (default is 16mS)
|
||||
status = pFT_SetLatencyTimer(ftdih, 2);
|
||||
if (status != FT_OK) {
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_SetLatencyTimer : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
//Reset controller
|
||||
status = pFT_SetBitMode(ftdih, 0x0, 0x00);
|
||||
if (status != FT_OK) {
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_SetBitMode : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
//Enable MPSSE mode
|
||||
status = pFT_SetBitMode(ftdih, 0x0, 0x02);
|
||||
if (status != FT_OK) {
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_SetBitMode : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
status = pFT_SetBitMode(ftdih, 0x0b, 2);
|
||||
if (status != FT_OK) {
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_SetBitMode : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
status = pFT_GetDeviceInfo(ftdih, &ftdi_device, &deviceID,
|
||||
SerialNumber, Description, NULL);
|
||||
if (status != FT_OK) {
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_GetDeviceInfo : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
/*
|
||||
Olimex ARM-USB-OCD-H JTAG signals
|
||||
|
||||
VREF – voltage follower input for the output buffers adjust JTAG signals as per your target board voltage levels
|
||||
ADBUS0 -> TCK; (out)
|
||||
ADBUS1 -> TDI; (out)
|
||||
ADBUS2 -> TDO; (in)
|
||||
ADBUS3 -> TMS; (out)
|
||||
ADBUS4 -> 0 to enable JTAG buffers; (GPIOL0) (out)
|
||||
ADBUS5 -> 0 if target present; (GPIOL1) (in)
|
||||
ADBUS6 -> TSRST in; (GPIOL2) (in)
|
||||
ADBUS7 -> RTCK; (in) (GPIOL3) (in)
|
||||
|
||||
ACBUS0 -> TRST; (GPIOH0)
|
||||
ACBUS1 -> SRST; (GPIOH1)
|
||||
ACBUS2 -> TRST buffer enable (GPIOH2)
|
||||
ACBUS3 -> RED LED; (GPIOH3)
|
||||
*/
|
||||
|
||||
low_direction = 0x00;
|
||||
for(i=0;i<8;i++)
|
||||
{
|
||||
sprintf(tmp_str,"PROBE_FTDI_SET_PIN_DIR_ADBUS%d",i);
|
||||
if( jtagcore_getEnvVarValue( jc, tmp_str) > 0 )
|
||||
{
|
||||
low_direction |= (0x01<<i);
|
||||
}
|
||||
}
|
||||
|
||||
low_output = 0x00;
|
||||
for(i=0;i<8;i++)
|
||||
{
|
||||
sprintf(tmp_str,"PROBE_FTDI_SET_PIN_DEFAULT_STATE_ADBUS%d",i);
|
||||
if( jtagcore_getEnvVarValue( jc, tmp_str) > 0 )
|
||||
{
|
||||
low_output |= (0x01<<i);
|
||||
}
|
||||
}
|
||||
|
||||
low_polarity = 0;
|
||||
for(i=0;i<8;i++)
|
||||
{
|
||||
sprintf(tmp_str,"PROBE_FTDI_SET_PIN_POLARITY_ADBUS%d",i);
|
||||
if( jtagcore_getEnvVarValue( jc, tmp_str) > 0 )
|
||||
{
|
||||
low_polarity |= (0x01<<i);
|
||||
}
|
||||
}
|
||||
|
||||
high_direction = 0x00;
|
||||
for(i=0;i<4;i++)
|
||||
{
|
||||
sprintf(tmp_str,"PROBE_FTDI_SET_PIN_DIR_ACBUS%d",i);
|
||||
if( jtagcore_getEnvVarValue( jc, tmp_str) > 0 )
|
||||
{
|
||||
high_direction |= (0x01<<i);
|
||||
}
|
||||
}
|
||||
|
||||
high_output = 0x00;
|
||||
for(i=0;i<4;i++)
|
||||
{
|
||||
sprintf(tmp_str,"PROBE_FTDI_SET_PIN_DEFAULT_STATE_ACBUS%d",i);
|
||||
if( jtagcore_getEnvVarValue( jc, tmp_str) > 0 )
|
||||
{
|
||||
high_output |= (0x01<<i);
|
||||
}
|
||||
}
|
||||
|
||||
high_polarity = 0x00;
|
||||
for(i=0;i<4;i++)
|
||||
{
|
||||
sprintf(tmp_str,"PROBE_FTDI_SET_PIN_POLARITY_ACBUS%d",i);
|
||||
if( jtagcore_getEnvVarValue( jc, tmp_str) > 0 )
|
||||
{
|
||||
high_polarity |= (0x01<<i);
|
||||
}
|
||||
}
|
||||
|
||||
trst_oe_pin = jtagcore_getEnvVarValue( jc, "PROBE_FTDI_SET_TRST_OE_PINNUM" );
|
||||
trst_state_pin = jtagcore_getEnvVarValue( jc, "PROBE_FTDI_SET_TRST_STATE_PINNUM" );
|
||||
|
||||
srst_oe_pin = jtagcore_getEnvVarValue( jc, "PROBE_FTDI_SET_SRST_OE_PINNUM" );
|
||||
srst_state_pin = jtagcore_getEnvVarValue( jc, "PROBE_FTDI_SET_SRST_STATE_PINNUM" );
|
||||
|
||||
led_pin = jtagcore_getEnvVarValue( jc, "PROBE_FTDI_SET_CONNECTION_LED_PINNUM" );
|
||||
|
||||
/* jtag reset */
|
||||
update_gpio_state(trst_oe_pin,1);
|
||||
update_gpio_state(trst_state_pin,1);
|
||||
|
||||
update_gpio_state(srst_oe_pin,1);
|
||||
update_gpio_state(srst_state_pin,0);
|
||||
|
||||
/* turn red LED off */
|
||||
update_gpio_state(led_pin,0);
|
||||
|
||||
ft2232_set_data_bits_low_byte( (unsigned char)(low_output ^ low_polarity), low_direction);
|
||||
ft2232_set_data_bits_high_byte( (unsigned char)(high_output ^ high_polarity), high_direction);
|
||||
|
||||
// Clock divisor
|
||||
// 0x86 ValueL ValueH
|
||||
// FT2232D/H
|
||||
// TCK clock = (12Mhz or 60Mhz)/ ((1 + ([ValueH << 8 | ValueL]))*2)
|
||||
|
||||
baseclock = jtagcore_getEnvVarValue( jc, "PROBE_FTDI_INTERNAL_FREQ_KHZ");
|
||||
tckfreq = jtagcore_getEnvVarValue( jc, "PROBE_FTDI_TCK_FREQ_KHZ");
|
||||
if( baseclock <= 0 || tckfreq <= 0){
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"drv_FTDI_Init : Invalid probe clock settings !\r\n");
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
divisor = ( ( baseclock / tckfreq ) - 2 ) / 2;
|
||||
|
||||
nbtosend = 0;
|
||||
ftdi_out_buf[nbtosend++] = CMD_SET_DIVISOR;
|
||||
ftdi_out_buf[nbtosend++] = divisor & 0xFF;
|
||||
ftdi_out_buf[nbtosend++] = (divisor>>8) & 0xFF;
|
||||
|
||||
status = pFT_Write(ftdih, ftdi_out_buf, nbtosend, &nbtosend);
|
||||
if (status != FT_OK) {
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_Write : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
|
||||
#if 0 // Loopback
|
||||
nbtosend = 0;
|
||||
ftdi_out_buf[nbtosend++] = CMD_ENABLE_LOOPBACK;
|
||||
|
||||
status = pFT_Write(ftdih, ftdi_out_buf, nbtosend, &nbtosend);
|
||||
if (status != FT_OK) {
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pFT_Write : Error %x !\r\n",status);
|
||||
goto loadliberror;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(jtagcore_getEnvVarValue( jc, "PROBE_FTDI_JTAG_ENABLE_RTCK") > 0)
|
||||
{
|
||||
ft2232h_enable_rtck(1);
|
||||
}
|
||||
|
||||
/* Delay... */
|
||||
genos_pause(jtagcore_getEnvVarValue( jc, "PROBE_FTDI_JTAG_TRST_DELAY_MS"));
|
||||
|
||||
/* turn red LED on */
|
||||
update_gpio_state(led_pin,1);
|
||||
|
||||
/* Release system & jtag reset */
|
||||
update_gpio_state(trst_state_pin,0);
|
||||
update_gpio_state(srst_state_pin,0);
|
||||
|
||||
ft2232_set_data_bits_low_byte( (unsigned char)(low_output ^ low_polarity), low_direction);
|
||||
ft2232_set_data_bits_high_byte( (unsigned char)(high_output ^ high_polarity), high_direction);
|
||||
|
||||
jtagcore_logs_printf(jc,MSG_INFO_0,"drv_FTDI_Init : Probe Driver loaded successfully...\r\n");
|
||||
|
||||
return 0;
|
||||
|
||||
loadliberror:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int drv_FTDI_DeInit(jtag_core * jc)
|
||||
{
|
||||
pFT_Close(ftdih);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drv_FTDI_TDOTDI_xfer(jtag_core * jc, unsigned char * str_out, unsigned char * str_in, int size)
|
||||
{
|
||||
int wr_bit_index,rd_bit_index;
|
||||
int i,payloadsize;
|
||||
unsigned char bitscnt;
|
||||
int rounded_size;
|
||||
DWORD nbRead,nbtosend;
|
||||
FT_STATUS status;
|
||||
unsigned char opcode,data;
|
||||
|
||||
rd_bit_index = 0;
|
||||
wr_bit_index = 0;
|
||||
|
||||
memset(ftdi_out_buf, 0, sizeof(ftdi_out_buf));
|
||||
memset(ftdi_in_buf, 0, sizeof(ftdi_in_buf));
|
||||
|
||||
if (size)
|
||||
{
|
||||
// Set the first TMS/DOUT bit
|
||||
if ( str_out[wr_bit_index] & JTAG_STR_TMS )
|
||||
{
|
||||
if( str_in )
|
||||
opcode = ( OP_WR_TMS | OP_LSB_FIRST | OP_BIT_MODE | OP_FEDGE_WR | OP_RD_TDO ); // with TDO read back
|
||||
else
|
||||
opcode = ( OP_WR_TMS | OP_LSB_FIRST | OP_BIT_MODE | OP_FEDGE_WR );
|
||||
|
||||
nbtosend = 0;
|
||||
|
||||
ftdi_out_buf[nbtosend++] = opcode;
|
||||
ftdi_out_buf[nbtosend++] = 0x00; // Size field : 1 Bit
|
||||
|
||||
data = 0x7F; // TMS state set
|
||||
|
||||
if (str_out[wr_bit_index] & JTAG_STR_DOUT)
|
||||
data |= 0x80; // Bit 7: TDI/DO pin state
|
||||
|
||||
wr_bit_index++;
|
||||
|
||||
ftdi_out_buf[nbtosend++] = data; // Data field
|
||||
|
||||
status = pFT_Write(ftdih, ftdi_out_buf, nbtosend, &nbtosend);
|
||||
|
||||
if ( opcode & OP_RD_TDO )
|
||||
{
|
||||
status = pFT_GetQueueStatus(ftdih, &nbRead);
|
||||
while (nbRead < 1 && (status == FT_OK))
|
||||
{
|
||||
Sleep(3);
|
||||
status = pFT_GetQueueStatus(ftdih, &nbRead);
|
||||
}
|
||||
|
||||
status = pFT_Read(ftdih, &ftdi_in_buf, nbRead, &nbRead);
|
||||
|
||||
// bits are shifted in from MSB to LSB ...
|
||||
if ( ftdi_in_buf[0] & 0x80 )
|
||||
{
|
||||
str_in[rd_bit_index++] = JTAG_STR_DOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
str_in[rd_bit_index++] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( wr_bit_index >= size )
|
||||
return 0;
|
||||
|
||||
rounded_size = (size - wr_bit_index) & ~(0x7);
|
||||
if( rounded_size )
|
||||
{
|
||||
// byte(s) buffer transmission/reception
|
||||
|
||||
if( str_in )
|
||||
opcode = ( OP_WR_TDI | OP_LSB_FIRST | OP_FEDGE_WR | OP_RD_TDO );
|
||||
else
|
||||
opcode = ( OP_WR_TDI | OP_LSB_FIRST | OP_FEDGE_WR );
|
||||
|
||||
nbtosend = 0;
|
||||
|
||||
ftdi_out_buf[nbtosend++] = opcode;
|
||||
ftdi_out_buf[nbtosend++] = ( ( (rounded_size>>3)-1 ) & 0xff ); // (Size-1) Low byte
|
||||
ftdi_out_buf[nbtosend++] = ( ( (rounded_size>>3)-1 ) >> 8 ); // (Size-1) High byte
|
||||
|
||||
ftdi_out_buf[nbtosend] = 0x00;
|
||||
|
||||
i = 0;
|
||||
payloadsize = 0;
|
||||
while (payloadsize < rounded_size)
|
||||
{
|
||||
if (str_out[wr_bit_index] & JTAG_STR_DOUT)
|
||||
{
|
||||
ftdi_out_buf[nbtosend] |= (0x01 << (i & 0x7));
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
if (!(i & 0x7))
|
||||
{
|
||||
nbtosend++;
|
||||
ftdi_out_buf[nbtosend] = 0x00;
|
||||
}
|
||||
|
||||
payloadsize++;
|
||||
wr_bit_index++;
|
||||
}
|
||||
|
||||
status = pFT_Write(ftdih, ftdi_out_buf, nbtosend, &nbtosend);
|
||||
|
||||
if (str_in)
|
||||
{
|
||||
do
|
||||
{
|
||||
Sleep(3);
|
||||
status = pFT_GetQueueStatus(ftdih, &nbRead);
|
||||
} while (nbRead < (unsigned long)(rounded_size >> 3) && (status == FT_OK ));
|
||||
|
||||
status = pFT_Read(ftdih, &ftdi_in_buf, nbRead, &nbRead);
|
||||
|
||||
for (i = 0; i < rounded_size; i++)
|
||||
{
|
||||
if (ftdi_in_buf[i >> 3] & (0x01 << (i & 7)))
|
||||
{
|
||||
str_in[rd_bit_index++] = JTAG_STR_DOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
str_in[rd_bit_index++] = 0x00;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send the remaining bits...
|
||||
while( wr_bit_index < size )
|
||||
{
|
||||
if( str_in )
|
||||
opcode = ( OP_WR_TDI | OP_LSB_FIRST | OP_BIT_MODE | OP_FEDGE_WR | OP_RD_TDO ); //bit mode with TDO read back
|
||||
else
|
||||
opcode = ( OP_WR_TDI | OP_LSB_FIRST | OP_BIT_MODE | OP_FEDGE_WR ); //bit mode
|
||||
|
||||
nbtosend = 0;
|
||||
|
||||
bitscnt = (size - wr_bit_index);
|
||||
if( bitscnt > 8 )
|
||||
{
|
||||
bitscnt = 8;
|
||||
}
|
||||
|
||||
ftdi_out_buf[nbtosend++] = opcode;
|
||||
ftdi_out_buf[nbtosend++] = (bitscnt - 1) & 7; // Size field
|
||||
ftdi_out_buf[nbtosend] = 0x00;
|
||||
|
||||
i = 0;
|
||||
while( i < bitscnt )
|
||||
{
|
||||
if (str_out[wr_bit_index++] & JTAG_STR_DOUT)
|
||||
ftdi_out_buf[nbtosend] |= 0x01 << i; // Data field
|
||||
|
||||
i++;
|
||||
}
|
||||
nbtosend++;
|
||||
|
||||
status = pFT_Write(ftdih, ftdi_out_buf, nbtosend, &nbtosend);
|
||||
|
||||
if ( opcode & OP_RD_TDO )
|
||||
{
|
||||
do
|
||||
{
|
||||
Sleep(3);
|
||||
status = pFT_GetQueueStatus(ftdih, &nbRead);
|
||||
} while ( ( nbRead < 1 ) && ( status == FT_OK ) );
|
||||
|
||||
status = pFT_Read(ftdih, &ftdi_in_buf, nbRead, &nbRead);
|
||||
|
||||
// bits are shifted in from MSB to LSB ...
|
||||
i = 0;
|
||||
while( i < bitscnt )
|
||||
{
|
||||
if ( ftdi_in_buf[0] & (0x01 << ( (8 - bitscnt) + i ) ) )
|
||||
{
|
||||
str_in[rd_bit_index++] = JTAG_STR_DOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
str_in[rd_bit_index++] = 0x00;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drv_FTDI_TMS_xfer(jtag_core * jc, unsigned char * str_out, int size)
|
||||
{
|
||||
int i;
|
||||
int wr_bit_index;
|
||||
DWORD nbtosend;
|
||||
FT_STATUS status;
|
||||
unsigned char bitscnt;
|
||||
unsigned char opcode;
|
||||
|
||||
status = FT_OK;
|
||||
|
||||
memset(ftdi_out_buf, 0, sizeof(ftdi_out_buf));
|
||||
memset(ftdi_in_buf, 0, sizeof(ftdi_in_buf));
|
||||
|
||||
wr_bit_index = 0;
|
||||
while( wr_bit_index < size )
|
||||
{
|
||||
opcode = ( OP_WR_TMS | OP_LSB_FIRST | OP_BIT_MODE | OP_FEDGE_WR );
|
||||
|
||||
nbtosend = 0;
|
||||
|
||||
bitscnt = (size - wr_bit_index);
|
||||
if( bitscnt > 7 )
|
||||
{
|
||||
bitscnt = 7;
|
||||
}
|
||||
|
||||
ftdi_out_buf[nbtosend++] = opcode;
|
||||
ftdi_out_buf[nbtosend++] = (bitscnt - 1); // Size field
|
||||
ftdi_out_buf[nbtosend] = 0x00;
|
||||
|
||||
i = 0;
|
||||
while( i < bitscnt )
|
||||
{
|
||||
if (str_out[wr_bit_index++] & JTAG_STR_TMS)
|
||||
ftdi_out_buf[nbtosend] |= 0x01 << i; // Data field
|
||||
|
||||
i++;
|
||||
}
|
||||
nbtosend++;
|
||||
|
||||
status = pFT_Write(ftdih, ftdi_out_buf, nbtosend, &nbtosend);
|
||||
}
|
||||
|
||||
if (status != FT_OK)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int drv_FTDI_libGetDrv(jtag_core * jc,int sub_drv,unsigned int infotype,void * returnvalue)
|
||||
{
|
||||
|
||||
drv_ptr drv_funcs =
|
||||
{
|
||||
(DRV_DETECT) drv_FTDI_Detect,
|
||||
(DRV_INIT) drv_FTDI_Init,
|
||||
(DRV_DEINIT) drv_FTDI_DeInit,
|
||||
(DRV_TXTMS) drv_FTDI_TMS_xfer,
|
||||
(DRV_TXRXDATA) drv_FTDI_TDOTDI_xfer,
|
||||
(DRV_GETMODULEINFOS) drv_FTDI_libGetDrv
|
||||
};
|
||||
|
||||
return GetDrvInfo(
|
||||
jc,
|
||||
infotype,
|
||||
returnvalue,
|
||||
subdrv_list[sub_drv].drv_id,
|
||||
subdrv_list[sub_drv].drv_desc,
|
||||
&drv_funcs
|
||||
);
|
||||
}
|
||||
32
src/modules/drivers/ftdi_jtag/ftdi_jtag_drv.h
Normal file
32
src/modules/drivers/ftdi_jtag/ftdi_jtag_drv.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef _FTDI_JTAG_DRV_H
|
||||
#define _FTDI_JTAG_DRV_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 ftdi_jtag_drv.h
|
||||
* @brief FTDI based probes driver entry point definition
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
|
||||
int drv_FTDI_libGetDrv(jtag_core * jc,int sub_drv, unsigned int infotype,void * returnvalue);
|
||||
|
||||
#endif
|
||||
387
src/modules/drivers/jlink_jtag/jlink_jtag_drv.c
Normal file
387
src/modules/drivers/jlink_jtag/jlink_jtag_drv.c
Normal file
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
* 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 jlink_jtag_drv.c
|
||||
* @brief JLINK based probes driver
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "script/env.h"
|
||||
#include "jtag_core/jtag_core.h"
|
||||
#include "drivers/drv_loader.h"
|
||||
#include "jtag_core/dbg_logs.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
// Compiling on Windows
|
||||
#include <windows.h>
|
||||
#elif defined(__linux__)
|
||||
#include <dlfcn.h>
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
#error "Unsupported OS (only available on Windows or Linux)"
|
||||
#endif
|
||||
|
||||
typedef struct _drv_desc
|
||||
{
|
||||
char *drv_id;
|
||||
char *drv_desc;
|
||||
int id;
|
||||
}drv_desc;
|
||||
|
||||
#define PROBE_JLINK_ARM 0
|
||||
|
||||
const static drv_desc subdrv_list[]=
|
||||
{
|
||||
{"JLINK_ARM","USB JLINK ARM",PROBE_JLINK_ARM}
|
||||
};
|
||||
|
||||
unsigned char jlink_out_tms_buf[64 * 1024];
|
||||
unsigned char jlink_out_tdi_buf[64 * 1024];
|
||||
unsigned char jlink_in_buf[64 * 1024];
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
#if defined(_WIN64)
|
||||
#define MODULE_NAME "JLink_x64.dll"
|
||||
#else
|
||||
#define MODULE_NAME "JLinkARM.dll"
|
||||
#endif
|
||||
|
||||
typedef const char* (WINAPIV * JL_OPENEX)(const char* pfLog, void*);
|
||||
typedef int (WINAPIV * JL_JTAG_STORERAW)(const unsigned char* pTDI, const unsigned char* pTMS, unsigned int NumBits);
|
||||
typedef int (WINAPIV * JL_JTAG_STOREGETRAW)(const unsigned char* pTDI, unsigned char* pTDO, const unsigned char* pTMS, unsigned int NumBits);
|
||||
typedef void (WINAPIV * JL_JTAG_SYNCBITS)(void);
|
||||
typedef void (WINAPIV * JL_SETSPEED)(unsigned int Speed);
|
||||
typedef void (WINAPIV * JL_SETRESETDELAY)(int ms);
|
||||
typedef void (WINAPIV * JL_RESETPULLSRESET)(unsigned char OnOff);
|
||||
typedef void (WINAPIV * JL_RESET)(void);
|
||||
typedef int (WINAPIV * JL_HASERROR)(void);
|
||||
typedef void (WINAPIV * JL_CLOSE)(void);
|
||||
|
||||
#else
|
||||
|
||||
#define MODULE_NAME "./libjlinkarm.so"
|
||||
|
||||
#if defined(__i386__)
|
||||
#define __cdecl __attribut__((cdecl))
|
||||
#else // __x86_64__ and others...
|
||||
#define __cdecl
|
||||
#endif
|
||||
|
||||
typedef void* HMODULE;
|
||||
|
||||
typedef const char* (__cdecl * JL_OPENEX)(const char* pfLog, void*);
|
||||
typedef int (__cdecl * JL_JTAG_STORERAW)(const unsigned char* pTDI, const unsigned char* pTMS, unsigned int NumBits);
|
||||
typedef int (__cdecl * JL_JTAG_STOREGETRAW)(const unsigned char* pTDI, unsigned char* pTDO, const unsigned char* pTMS, unsigned int NumBits);
|
||||
typedef void (__cdecl * JL_JTAG_SYNCBITS)(void);
|
||||
typedef void (__cdecl * JL_SETSPEED)(unsigned int Speed);
|
||||
typedef void (__cdecl * JL_SETRESETDELAY)(int ms);
|
||||
typedef void (__cdecl * JL_RESETPULLSRESET)(unsigned char OnOff);
|
||||
typedef void (__cdecl * JL_RESET)(void);
|
||||
typedef int (__cdecl * JL_HASERROR)(void);
|
||||
typedef void (__cdecl * JL_CLOSE)(void);
|
||||
|
||||
void* GetProcAddress(HMODULE handle, const char* name)
|
||||
{
|
||||
if(!handle || !name)
|
||||
return NULL;
|
||||
|
||||
dlerror();
|
||||
|
||||
return dlsym(handle, name);
|
||||
}
|
||||
|
||||
bool FreeLibrary(HMODULE handle)
|
||||
{
|
||||
dlerror();
|
||||
if(0 != dlclose(handle)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
HMODULE LoadLibrary(const char* path)
|
||||
{
|
||||
dlerror();
|
||||
return dlopen(path, RTLD_NOW);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static HMODULE lib_handle = 0;
|
||||
|
||||
JL_OPENEX pJLINKARM_OpenEx;
|
||||
JL_JTAG_STORERAW pJLINKARM_JTAG_StoreRaw;
|
||||
JL_JTAG_STOREGETRAW pJLINKARM_JTAG_StoreGetRaw;
|
||||
JL_JTAG_SYNCBITS pJLINKARM_JTAG_SyncBits;
|
||||
JL_SETSPEED pJLINKARM_SetSpeed;
|
||||
JL_SETRESETDELAY pJLINKARM_SetResetDelay;
|
||||
JL_RESETPULLSRESET pJLINKARM_ResetPullsRESET;
|
||||
JL_RESET pJLINKARM_Reset;
|
||||
JL_HASERROR pJLINKARM_HasError;
|
||||
JL_CLOSE pJLINKARM_Close;
|
||||
|
||||
int drv_JLINK_Detect(jtag_core * jc)
|
||||
{
|
||||
if(lib_handle == NULL) {
|
||||
lib_handle = LoadLibrary(MODULE_NAME);
|
||||
}
|
||||
|
||||
if (lib_handle)
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_INFO_1,"drv_JLINK_Detect : %s JLink library found !\r\n",MODULE_NAME);
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_INFO_1,"drv_JLINK_Detect : %s JLink library not found !\r\n",MODULE_NAME);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void * drv_JLINK_GetDrvFunc(jtag_core * jc, HMODULE libh, char * function_name)
|
||||
{
|
||||
void * function_ptr;
|
||||
|
||||
function_ptr = (void *)GetProcAddress(libh, function_name);
|
||||
if (!function_ptr)
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"drv_JLINK_GetDrvFunc : Can't get %s function !\r\n",function_name);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return function_ptr;
|
||||
}
|
||||
|
||||
int drv_JLINK_Init(jtag_core * jc, int sub_drv, char * params)
|
||||
{
|
||||
const char* sError;
|
||||
|
||||
if(lib_handle == NULL) {
|
||||
lib_handle = LoadLibrary(MODULE_NAME);
|
||||
}
|
||||
|
||||
if (lib_handle)
|
||||
{
|
||||
pJLINKARM_OpenEx = (JL_OPENEX)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_OpenEx");
|
||||
if (!pJLINKARM_OpenEx)
|
||||
goto loadliberror;
|
||||
|
||||
pJLINKARM_JTAG_StoreRaw = (JL_JTAG_STORERAW)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_JTAG_StoreRaw");
|
||||
if (!pJLINKARM_JTAG_StoreRaw)
|
||||
goto loadliberror;
|
||||
|
||||
pJLINKARM_JTAG_StoreGetRaw = (JL_JTAG_STOREGETRAW)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_JTAG_StoreGetRaw");
|
||||
if (!pJLINKARM_JTAG_StoreGetRaw)
|
||||
goto loadliberror;
|
||||
|
||||
pJLINKARM_JTAG_SyncBits = (JL_JTAG_SYNCBITS)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_JTAG_SyncBits");
|
||||
if (!pJLINKARM_JTAG_SyncBits)
|
||||
goto loadliberror;
|
||||
|
||||
pJLINKARM_SetSpeed = (JL_SETSPEED)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_SetSpeed");
|
||||
if (!pJLINKARM_SetSpeed)
|
||||
goto loadliberror;
|
||||
|
||||
pJLINKARM_SetResetDelay = (JL_SETRESETDELAY)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_SetResetDelay");
|
||||
if (!pJLINKARM_SetResetDelay)
|
||||
goto loadliberror;
|
||||
|
||||
pJLINKARM_ResetPullsRESET = (JL_RESETPULLSRESET)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_ResetPullsRESET");
|
||||
if (!pJLINKARM_ResetPullsRESET)
|
||||
goto loadliberror;
|
||||
|
||||
pJLINKARM_Reset = (JL_RESET)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_Reset");
|
||||
if (!pJLINKARM_Reset)
|
||||
goto loadliberror;
|
||||
|
||||
pJLINKARM_HasError = (JL_HASERROR)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_HasError");
|
||||
if (!pJLINKARM_HasError)
|
||||
goto loadliberror;
|
||||
|
||||
pJLINKARM_Close = (JL_CLOSE)drv_JLINK_GetDrvFunc(jc, lib_handle, "JLINKARM_Close");
|
||||
if (!pJLINKARM_Close)
|
||||
goto loadliberror;
|
||||
}
|
||||
else
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"drv_JLINK_Init : Can't load JLinkARM.dll !\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sError = pJLINKARM_OpenEx(NULL, 0);
|
||||
if (sError) {
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"pJLINKARM_OpenEx : Error 0x%x !\r\n",sError);
|
||||
return -1;
|
||||
}
|
||||
|
||||
pJLINKARM_SetSpeed(1000); // 1 Mhz
|
||||
|
||||
jtagcore_logs_printf(jc,MSG_INFO_0,"drv_JLINK_Init : Probe Driver loaded successfully...\r\n");
|
||||
|
||||
return 0;
|
||||
|
||||
loadliberror:
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"drv_JLINK_Init : Something wrong happened ! JLink probe support not enabled.\r\n");
|
||||
|
||||
FreeLibrary(lib_handle);
|
||||
|
||||
lib_handle = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int drv_JLINK_DeInit(jtag_core * jc)
|
||||
{
|
||||
pJLINKARM_Close();
|
||||
FreeLibrary(lib_handle);
|
||||
lib_handle = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drv_JLINK_TDOTDI_xfer(jtag_core * jc, unsigned char * str_out, unsigned char * str_in, int size)
|
||||
{
|
||||
int i;
|
||||
int bitoffset;
|
||||
|
||||
memset(jlink_out_tms_buf, 0, sizeof(jlink_out_tms_buf));
|
||||
memset(jlink_out_tdi_buf, 0, sizeof(jlink_out_tdi_buf));
|
||||
|
||||
if (!str_in)
|
||||
{
|
||||
if (size)
|
||||
{
|
||||
i = 0;
|
||||
bitoffset = 0;
|
||||
while (i < size)
|
||||
{
|
||||
if (str_out[i] & JTAG_STR_TMS)
|
||||
jlink_out_tms_buf[bitoffset >> 3] |= (0x01 << (bitoffset & 7));
|
||||
|
||||
if (str_out[i] & JTAG_STR_DOUT)
|
||||
jlink_out_tdi_buf[bitoffset >> 3] |= (0x01 << (bitoffset & 7));
|
||||
|
||||
bitoffset++;
|
||||
i++;
|
||||
}
|
||||
|
||||
pJLINKARM_JTAG_StoreRaw(jlink_out_tdi_buf, jlink_out_tms_buf, bitoffset);
|
||||
pJLINKARM_JTAG_SyncBits();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (size)
|
||||
{
|
||||
memset(jlink_in_buf, 0, sizeof(jlink_in_buf));
|
||||
|
||||
i = 0;
|
||||
bitoffset = 0;
|
||||
while (i < size)
|
||||
{
|
||||
if (str_out[i] & JTAG_STR_TMS)
|
||||
jlink_out_tms_buf[bitoffset >> 3] |= (0x01 << (bitoffset & 7));
|
||||
|
||||
if (str_out[i] & JTAG_STR_DOUT)
|
||||
jlink_out_tdi_buf[bitoffset >> 3] |= (0x01 << (bitoffset & 7));
|
||||
|
||||
bitoffset++;
|
||||
i++;
|
||||
}
|
||||
|
||||
pJLINKARM_JTAG_StoreGetRaw(jlink_out_tdi_buf, jlink_in_buf, jlink_out_tms_buf, bitoffset);
|
||||
pJLINKARM_JTAG_SyncBits();
|
||||
|
||||
i = 0;
|
||||
while (i < size)
|
||||
{
|
||||
if (jlink_in_buf[i >> 3] & (0x01 << (i & 7)))
|
||||
{
|
||||
str_in[i] = JTAG_STR_DOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
str_in[i] = 0x00;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drv_JLINK_TMS_xfer(jtag_core * jc, unsigned char * str_out, int size)
|
||||
{
|
||||
int bitoffset,i;
|
||||
|
||||
memset(jlink_out_tms_buf, 0, sizeof(jlink_out_tms_buf));
|
||||
memset(jlink_out_tdi_buf, 0, sizeof(jlink_out_tdi_buf));
|
||||
|
||||
if (size)
|
||||
{
|
||||
i = 0;
|
||||
bitoffset = 0;
|
||||
while (i < size)
|
||||
{
|
||||
if (str_out[i] & JTAG_STR_TMS)
|
||||
jlink_out_tms_buf[bitoffset >> 3] |= (0x01 << (bitoffset & 7));
|
||||
|
||||
bitoffset++;
|
||||
i++;
|
||||
}
|
||||
|
||||
pJLINKARM_JTAG_StoreRaw(jlink_out_tdi_buf, jlink_out_tms_buf, bitoffset);
|
||||
pJLINKARM_JTAG_SyncBits();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drv_JLINK_libGetDrv(jtag_core * jc,int sub_drv,unsigned int infotype,void * returnvalue)
|
||||
{
|
||||
drv_ptr drv_funcs =
|
||||
{
|
||||
(DRV_DETECT) drv_JLINK_Detect,
|
||||
(DRV_INIT) drv_JLINK_Init,
|
||||
(DRV_DEINIT) drv_JLINK_DeInit,
|
||||
(DRV_TXTMS) drv_JLINK_TMS_xfer,
|
||||
(DRV_TXRXDATA) drv_JLINK_TDOTDI_xfer,
|
||||
(DRV_GETMODULEINFOS) drv_JLINK_libGetDrv
|
||||
};
|
||||
|
||||
return GetDrvInfo(
|
||||
jc,
|
||||
infotype,
|
||||
returnvalue,
|
||||
subdrv_list[sub_drv].drv_id,
|
||||
subdrv_list[sub_drv].drv_desc,
|
||||
&drv_funcs
|
||||
);
|
||||
}
|
||||
|
||||
32
src/modules/drivers/jlink_jtag/jlink_jtag_drv.h
Normal file
32
src/modules/drivers/jlink_jtag/jlink_jtag_drv.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef _JLINK_JTAG_DRV_H
|
||||
#define _JLINK_JTAG_DRV_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 jlink_jtag_drv.h
|
||||
* @brief JLINK based probes driver entry point definition
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
|
||||
int drv_JLINK_libGetDrv(jtag_core * jc,int sub_drv, unsigned int infotype,void * returnvalue);
|
||||
|
||||
#endif
|
||||
448
src/modules/drivers/linux_gpio_jtag/linux_gpio_jtag_drv.c
Normal file
448
src/modules/drivers/linux_gpio_jtag/linux_gpio_jtag_drv.c
Normal file
@@ -0,0 +1,448 @@
|
||||
/*
|
||||
* 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 linux_gpio_jtag_drv.c
|
||||
* @brief jtag linux gpio probes driver
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#if defined(__linux__)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "script/env.h"
|
||||
#include "jtag_core/jtag_core.h"
|
||||
#include "drivers/drv_loader.h"
|
||||
#include "os_interface/os_interface.h"
|
||||
#include "jtag_core/dbg_logs.h"
|
||||
|
||||
char linux_gpio_base[512];
|
||||
|
||||
#define IGNORE_PORT 0
|
||||
#define READ_PORT 1
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* name;
|
||||
int gpio_num;
|
||||
int dir;
|
||||
int state;
|
||||
int old_state;
|
||||
int negate_polarity;
|
||||
int handle;
|
||||
}io_defs;
|
||||
|
||||
#define TMS_INDEX 0
|
||||
#define TDO_INDEX 1
|
||||
#define TDI_INDEX 2
|
||||
#define TCK_INDEX 3
|
||||
|
||||
io_defs gpio_var_names[]=
|
||||
{
|
||||
{(const char*)"PROBE_LINUXGPIO_TMS_PIN",-1,1,0,-1,0,-1},
|
||||
{(const char*)"PROBE_LINUXGPIO_TDO_PIN",-1,0,0,-1,0,-1},
|
||||
{(const char*)"PROBE_LINUXGPIO_TDI_PIN",-1,1,0,-1,0,-1},
|
||||
{(const char*)"PROBE_LINUXGPIO_TCK_PIN",-1,1,0,-1,0,-1},
|
||||
{(const char*)NULL,-1,-1,0,-1,-1}
|
||||
};
|
||||
|
||||
#if defined(__linux__)
|
||||
|
||||
static int putp(int tdi, int tms, int rp)
|
||||
{
|
||||
int tdo = -1;
|
||||
int ret;
|
||||
char tmp_str[512];
|
||||
char rd_value;
|
||||
|
||||
tmp_str[0] = '0';
|
||||
tmp_str[1] = '\n';
|
||||
tmp_str[2] = 0;
|
||||
|
||||
rd_value = 0;
|
||||
|
||||
if (rp == READ_PORT)
|
||||
{
|
||||
|
||||
rd_value = 0;
|
||||
lseek(gpio_var_names[TDO_INDEX].handle, 0, SEEK_SET);
|
||||
ret = read(gpio_var_names[TDO_INDEX].handle,&rd_value,1);
|
||||
if(ret < 1)
|
||||
goto wr_error;
|
||||
|
||||
if(rd_value >= '0' && rd_value <='1')
|
||||
{
|
||||
gpio_var_names[TDO_INDEX].old_state = gpio_var_names[TDO_INDEX].state;
|
||||
tdo = (rd_value - '0') ^ (gpio_var_names[TDO_INDEX].negate_polarity&1);
|
||||
gpio_var_names[TDO_INDEX].state = tdo;
|
||||
}
|
||||
}
|
||||
|
||||
if( gpio_var_names[TMS_INDEX].old_state != (tms&1))
|
||||
{
|
||||
tmp_str[0] = '0' + ((tms&1) ^ (gpio_var_names[TMS_INDEX].negate_polarity&1));
|
||||
|
||||
ret = write(gpio_var_names[TMS_INDEX].handle,tmp_str,2);
|
||||
if(ret < 2)
|
||||
goto wr_error;
|
||||
|
||||
gpio_var_names[TMS_INDEX].old_state = (tms&1);
|
||||
}
|
||||
|
||||
if( gpio_var_names[TDI_INDEX].old_state != (tdi&1))
|
||||
{
|
||||
tmp_str[0] = '0' + ((tdi&1) ^ (gpio_var_names[TDI_INDEX].negate_polarity&1));
|
||||
ret = write(gpio_var_names[TDI_INDEX].handle,tmp_str,2);
|
||||
if(ret < 2)
|
||||
goto wr_error;
|
||||
|
||||
gpio_var_names[TDI_INDEX].old_state = (tdi&1);
|
||||
}
|
||||
|
||||
tmp_str[0] = '0' + (gpio_var_names[TCK_INDEX].negate_polarity&1);
|
||||
ret = write(gpio_var_names[TCK_INDEX].handle,tmp_str,2);
|
||||
if(ret < 2)
|
||||
goto wr_error;
|
||||
|
||||
gpio_var_names[TCK_INDEX].old_state = 0;
|
||||
|
||||
tmp_str[0] = '0' + (1 ^ (gpio_var_names[TCK_INDEX].negate_polarity&1));
|
||||
ret = write(gpio_var_names[TCK_INDEX].handle,tmp_str,2);
|
||||
if(ret < 2)
|
||||
goto wr_error;
|
||||
|
||||
gpio_var_names[TCK_INDEX].old_state = 1;
|
||||
|
||||
tmp_str[0] = '0' + (gpio_var_names[TCK_INDEX].negate_polarity&1);
|
||||
ret = write(gpio_var_names[TCK_INDEX].handle,tmp_str,2);
|
||||
if(ret < 2)
|
||||
goto wr_error;
|
||||
|
||||
gpio_var_names[TCK_INDEX].old_state = 0;
|
||||
|
||||
return tdo;
|
||||
|
||||
wr_error:
|
||||
return 0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int drv_LinuxGPIO_Detect(jtag_core * jc)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
char tmp_str[1024];
|
||||
FILE * f;
|
||||
|
||||
if( jtagcore_getEnvVarValue( jc, "PROBE_GPIO_LINUX_ENABLE") > 0)
|
||||
{
|
||||
jtagcore_getEnvVar( jc, "PROBE_GPIO_LINUX_BASE_FOLDER", (char*)&linux_gpio_base);
|
||||
|
||||
strncpy(tmp_str, linux_gpio_base, sizeof(tmp_str) - 1);
|
||||
genos_strndstcat(tmp_str,"/export",sizeof(tmp_str));
|
||||
tmp_str[sizeof(tmp_str) - 1] = '\0';
|
||||
|
||||
f = fopen(tmp_str,"rb");
|
||||
if(f)
|
||||
{
|
||||
fclose(f);
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"drv_LinuxGPIO_Detect : JTAG GPIO interface enabled\r\n",tmp_str);
|
||||
return 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"drv_LinuxGPIO_Detect : Can't open %s !\r\n",tmp_str);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
|
||||
static int exportGPIO(char * path_base,int pin)
|
||||
{
|
||||
char tmp_str[512];
|
||||
FILE * f;
|
||||
|
||||
strcpy(tmp_str,path_base);
|
||||
strcat(tmp_str,"/export");
|
||||
|
||||
f = fopen(tmp_str,"w");
|
||||
if(!f)
|
||||
{
|
||||
return JTAG_CORE_ACCESS_ERROR;
|
||||
}
|
||||
|
||||
fprintf(f,"%d\n", pin);
|
||||
fclose(f);
|
||||
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
|
||||
static int setdirGPIO(char * path_base,int pin,int dir)
|
||||
{
|
||||
char tmp_str[1024];
|
||||
char tmp_str2[64];
|
||||
FILE * f;
|
||||
|
||||
strncpy(tmp_str,path_base,sizeof(tmp_str)-1);
|
||||
snprintf(tmp_str2,sizeof(tmp_str2)-1,"/gpio%d/direction",pin);
|
||||
genos_strndstcat(tmp_str,tmp_str2,sizeof(tmp_str));
|
||||
tmp_str[sizeof(tmp_str) - 1] = '\0';
|
||||
|
||||
f = fopen(tmp_str,"w");
|
||||
if(!f)
|
||||
{
|
||||
return JTAG_CORE_ACCESS_ERROR;
|
||||
}
|
||||
|
||||
if(dir)
|
||||
fprintf(f,"out\n");
|
||||
else
|
||||
fprintf(f,"in\n");
|
||||
|
||||
fclose(f);
|
||||
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int drv_LinuxGPIO_Init(jtag_core * jc, int sub_drv,char * params)
|
||||
{
|
||||
int probe_detected;
|
||||
|
||||
probe_detected = 0;
|
||||
|
||||
if( jtagcore_getEnvVarValue( jc, "PROBE_LINUXGPIO_ENABLE") <= 0)
|
||||
{
|
||||
return JTAG_CORE_NO_PROBE;
|
||||
}
|
||||
|
||||
#if defined(__linux__)
|
||||
int i;
|
||||
char tmp_str[1024];
|
||||
|
||||
jtagcore_getEnvVar( jc, "PROBE_LINUXGPIO_BASE_FOLDER", (char*)&linux_gpio_base);
|
||||
|
||||
i = 0;
|
||||
while(gpio_var_names[i].name)
|
||||
{
|
||||
gpio_var_names[i].gpio_num = jtagcore_getEnvVarValue( jc, (char*)gpio_var_names[i].name);
|
||||
|
||||
strncpy(tmp_str,(char*)gpio_var_names[i].name,sizeof(tmp_str) - 1);
|
||||
tmp_str[sizeof(tmp_str) - 1] = '\0';
|
||||
|
||||
genos_strndstcat(tmp_str,"_INVERT_POLARITY",sizeof(tmp_str));
|
||||
tmp_str[sizeof(tmp_str) - 1] = '\0';
|
||||
|
||||
gpio_var_names[i].negate_polarity = jtagcore_getEnvVarValue( jc, (char*)tmp_str);
|
||||
|
||||
if( exportGPIO(linux_gpio_base, gpio_var_names[i].gpio_num) != JTAG_CORE_NO_ERROR )
|
||||
break;
|
||||
|
||||
if( setdirGPIO(linux_gpio_base, gpio_var_names[i].gpio_num, gpio_var_names[i].dir) != JTAG_CORE_NO_ERROR )
|
||||
break;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if(!gpio_var_names[i].name)
|
||||
{
|
||||
probe_detected = 1;
|
||||
|
||||
for(i=0;i<4;i++)
|
||||
{
|
||||
snprintf(tmp_str,sizeof(tmp_str),"%s/gpio%d/value",linux_gpio_base,gpio_var_names[i].gpio_num);
|
||||
|
||||
if(gpio_var_names[i].handle != -1)
|
||||
close(gpio_var_names[i].handle);
|
||||
|
||||
if(gpio_var_names[i].dir)
|
||||
gpio_var_names[i].handle = open(tmp_str, O_WRONLY);
|
||||
else
|
||||
gpio_var_names[i].handle = open(tmp_str, O_RDONLY);
|
||||
|
||||
if(gpio_var_names[i].handle < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if( i == 4 )
|
||||
{
|
||||
// init gpio
|
||||
putp(0, 0, IGNORE_PORT);
|
||||
putp(0, 0, IGNORE_PORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
probe_detected = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(probe_detected)
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_INFO_0,"drv_LinuxGPIO_Init : Probe Driver loaded successfully...\r\n");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"drv_LinuxGPIO_Init : No probe found !\r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int drv_LinuxGPIO_DeInit(jtag_core * jc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drv_LinuxGPIO_TDOTDI_xfer(jtag_core * jc, unsigned char * str_out, unsigned char * str_in, int size)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
|
||||
if (!str_in)
|
||||
{
|
||||
while (i < size)
|
||||
{
|
||||
|
||||
if (str_out[i] & JTAG_STR_TMS)
|
||||
{
|
||||
gpio_var_names[TMS_INDEX].state = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_var_names[TMS_INDEX].state = 0;
|
||||
}
|
||||
|
||||
if (str_out[i] & JTAG_STR_DOUT)
|
||||
{
|
||||
gpio_var_names[TDI_INDEX].state = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_var_names[TDI_INDEX].state = 0;
|
||||
}
|
||||
|
||||
putp(gpio_var_names[TDI_INDEX].state, gpio_var_names[TMS_INDEX].state, IGNORE_PORT);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (i < size)
|
||||
{
|
||||
if (str_out[i] & JTAG_STR_DOUT)
|
||||
{
|
||||
gpio_var_names[TDI_INDEX].state = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_var_names[TDI_INDEX].state = 0;
|
||||
}
|
||||
|
||||
if (str_out[i] & JTAG_STR_TMS)
|
||||
{
|
||||
gpio_var_names[TMS_INDEX].state = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_var_names[TMS_INDEX].state = 0;
|
||||
}
|
||||
|
||||
str_in[i] = putp(gpio_var_names[TDI_INDEX].state, gpio_var_names[TMS_INDEX].state, READ_PORT);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
int drv_LinuxGPIO_TMS_xfer(jtag_core * jc, unsigned char * str_out, int size)
|
||||
{
|
||||
#if defined(__linux__)
|
||||
int i;
|
||||
|
||||
gpio_var_names[TDI_INDEX].state = 0;
|
||||
|
||||
i = 0;
|
||||
while (i < size)
|
||||
{
|
||||
if (str_out[i] & JTAG_STR_TMS)
|
||||
{
|
||||
gpio_var_names[TMS_INDEX].state = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_var_names[TMS_INDEX].state = 0;
|
||||
}
|
||||
|
||||
putp(gpio_var_names[TDI_INDEX].state, gpio_var_names[TMS_INDEX].state, IGNORE_PORT);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
int drv_LinuxGPIO_libGetDrv(jtag_core * jc, int sub_drv, unsigned int infotype,void * returnvalue)
|
||||
{
|
||||
|
||||
drv_ptr drv_funcs =
|
||||
{
|
||||
(DRV_DETECT) drv_LinuxGPIO_Detect,
|
||||
(DRV_INIT) drv_LinuxGPIO_Init,
|
||||
(DRV_DEINIT) drv_LinuxGPIO_DeInit,
|
||||
(DRV_TXTMS) drv_LinuxGPIO_TMS_xfer,
|
||||
(DRV_TXRXDATA) drv_LinuxGPIO_TDOTDI_xfer,
|
||||
(DRV_GETMODULEINFOS) drv_LinuxGPIO_libGetDrv
|
||||
};
|
||||
|
||||
return GetDrvInfo(
|
||||
jc,
|
||||
infotype,
|
||||
returnvalue,
|
||||
"LINUX_GPIO",
|
||||
"GENERIC LINUX GPIO JTAG",
|
||||
&drv_funcs
|
||||
);
|
||||
}
|
||||
32
src/modules/drivers/linux_gpio_jtag/linux_gpio_jtag_drv.h
Normal file
32
src/modules/drivers/linux_gpio_jtag/linux_gpio_jtag_drv.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef _GPIO_JTAG_DRV_H
|
||||
#define _GPIO_JTAG_DRV_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 linux_gpio_jtag_drv.h
|
||||
* @brief jtag linux gpio probes driver
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
|
||||
int drv_LinuxGPIO_libGetDrv(jtag_core * jc,int sub_drv,unsigned int infotype,void * returnvalue);
|
||||
|
||||
#endif
|
||||
423
src/modules/drivers/lpt_jtag/lpt_jtag_drv.c
Normal file
423
src/modules/drivers/lpt_jtag/lpt_jtag_drv.c
Normal file
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
* 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 lpt_jtag_drv.c
|
||||
* @brief parallel port probes driver
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#ifndef _WIN64
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
#include "script/env.h"
|
||||
#include "jtag_core/jtag_core.h"
|
||||
#include "drivers/drv_loader.h"
|
||||
#include "jtag_core/dbg_logs.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
HANDLE h;
|
||||
|
||||
#endif
|
||||
|
||||
#define LPT1 0x3bc
|
||||
#define LPT2 0x378
|
||||
#define LPT3 0x278
|
||||
|
||||
#define IGNORE_PORT 0
|
||||
#define READ_PORT 1
|
||||
|
||||
unsigned short lpt_address;
|
||||
|
||||
|
||||
int sub_probe_id;
|
||||
|
||||
typedef struct _drv_desc
|
||||
{
|
||||
char *drv_id;
|
||||
char *drv_desc;
|
||||
int id;
|
||||
}drv_desc;
|
||||
|
||||
#define PROBE_INSIGHT_IJC 0
|
||||
#define PROBE_ALTERA_BYTEBLASTER 1
|
||||
#define PROBE_MACRAIGOR_WIGGLER 2
|
||||
|
||||
const static drv_desc subdrv_list[]=
|
||||
{
|
||||
{"LPT_INSIGHT_JTAG","LPT Memec IJC-4",PROBE_INSIGHT_IJC},
|
||||
{"LPT_ALTERA_BYTEBLASTER_JTAG","LPT Altera ByteBlaster",PROBE_ALTERA_BYTEBLASTER},
|
||||
{"LPT_MACRAIGOR_WIGGLERJTAG","LPT Macgraigor Wiggler",PROBE_MACRAIGOR_WIGGLER}
|
||||
};
|
||||
|
||||
void out_io_port( unsigned short port, unsigned char data )
|
||||
{
|
||||
#if defined(WIN32)
|
||||
_outp( port, data );
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned char in_io_port( unsigned short port )
|
||||
{
|
||||
#if defined(WIN32)
|
||||
return _inp( port );
|
||||
#else
|
||||
return 0x00;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int test_port(void)
|
||||
{
|
||||
// search for valid parallel port
|
||||
out_io_port(LPT1, 0x55);
|
||||
if ((int)in_io_port(LPT1) == 0x55)
|
||||
{
|
||||
return LPT1;
|
||||
}
|
||||
|
||||
out_io_port(LPT2, 0x55);
|
||||
if ((int)in_io_port(LPT2) == 0x55)
|
||||
{
|
||||
return LPT2;
|
||||
}
|
||||
|
||||
out_io_port(LPT3, 0x55);
|
||||
if ((int)in_io_port(LPT3) == 0x55)
|
||||
{
|
||||
return LPT3;
|
||||
}
|
||||
|
||||
return(0); // return zero if none found
|
||||
}
|
||||
|
||||
int putp(int tdi, int tms, int rp)
|
||||
{
|
||||
int tdo = -1;
|
||||
int lpt_data;
|
||||
|
||||
switch (sub_probe_id)
|
||||
{
|
||||
case PROBE_INSIGHT_IJC:
|
||||
// Insight/Xilinx :
|
||||
// D4 : TDO DRV LOW (AL)
|
||||
// D3 : OE (AL)
|
||||
// D1 : TCK (AH)
|
||||
// D2 : TMS (AH)
|
||||
// D0 : TDI (AH) (To device)
|
||||
// OnLine :TDO (AH) (From device)
|
||||
|
||||
lpt_data = 0x10; //Output to TDO off / Outputs enabled
|
||||
if (tms == 1) lpt_data |= 0x04;
|
||||
if (tdi == 1) lpt_data |= 0x01;
|
||||
|
||||
out_io_port(lpt_address, (unsigned char)lpt_data); // TCK low
|
||||
|
||||
lpt_data |= 0x02;
|
||||
out_io_port(lpt_address, (unsigned char)lpt_data); // TCK high
|
||||
|
||||
if (rp == READ_PORT)
|
||||
{
|
||||
tdo = ((int)in_io_port((unsigned short)(lpt_address + 1)) & 0x10) >> 4; // get TDO data
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PROBE_ALTERA_BYTEBLASTER:
|
||||
// Byteblaster :
|
||||
// AutoF : OE (AH)
|
||||
// D0 : TCK (AH)
|
||||
// D1 : TMS (AH)
|
||||
// D6 : TDI (AH) (To device)
|
||||
// BUSY : TDO (AL) (From device)
|
||||
// D4 : Loopback test out (AH)
|
||||
// Ack : Loopback test in (AH)
|
||||
|
||||
lpt_data = 0x00;
|
||||
|
||||
if (tms == 1) lpt_data |= 0x02;
|
||||
if (tdi == 1) lpt_data |= 0x40;
|
||||
|
||||
out_io_port(lpt_address, (unsigned char)lpt_data); // TCK low
|
||||
|
||||
lpt_data |= 0x01;
|
||||
out_io_port(lpt_address, (unsigned char)lpt_data); // TCK high
|
||||
|
||||
if (rp == READ_PORT)
|
||||
{
|
||||
tdo = (((int)in_io_port((unsigned short)(lpt_address + 1)) & 0x80) >> 7) ^ 1; // get TDO data
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PROBE_MACRAIGOR_WIGGLER:
|
||||
// Macraigor Wiggler :
|
||||
// AutoF : OE (AH)
|
||||
// D0 : RST (AH)
|
||||
// D1 : TMS (AH)
|
||||
// D2 : TCK (AH)
|
||||
// D3 : TDI (AH) (To device)
|
||||
// D4 : TRST (AH)
|
||||
// D7 : "PC VCC"
|
||||
// BUSY : TDO (AL) (From device)
|
||||
// D6 : Loopback test out (AH)
|
||||
// Error : Loopback test in (AH)
|
||||
|
||||
lpt_data = 0x10 | 0x80; //Set PC VCC & TRST to 1
|
||||
|
||||
if (tms == 1) lpt_data |= 0x02;
|
||||
if (tdi == 1) lpt_data |= 0x08;
|
||||
|
||||
out_io_port(lpt_address, (unsigned char)lpt_data); // TCK low
|
||||
|
||||
lpt_data |= 0x04;
|
||||
out_io_port(lpt_address, (unsigned char)lpt_data); // TCK high
|
||||
|
||||
if (rp == READ_PORT)
|
||||
{
|
||||
tdo = (((int)in_io_port((unsigned short)(lpt_address + 1)) & 0x80) >> 7) ^ 1; // get TDO data
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return tdo;
|
||||
}
|
||||
|
||||
int drv_LPT_Detect(jtag_core * jc)
|
||||
{
|
||||
|
||||
#if defined(WIN32)
|
||||
h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"drv_LPT_Init : Can't load giveio !\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"drv_LPT_Detect : giveio enabled !\r\n");
|
||||
#endif
|
||||
|
||||
lpt_address = test_port(); // find a valid parallel port address
|
||||
if (!lpt_address)
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"drv_LPT_Init : No LPT port found !\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
int drv_LPT_Init(jtag_core * jc, int sub_drv,char * params)
|
||||
{
|
||||
int probe_detected;
|
||||
|
||||
#if defined(WIN32)
|
||||
h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"drv_LPT_Init : Can't load giveio !\r\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
lpt_address = test_port(); // find a valid parallel port address
|
||||
if (!lpt_address)
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"drv_LPT_Init : No LPT port found !\r\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
sub_probe_id = subdrv_list[sub_drv].id;
|
||||
|
||||
switch(sub_probe_id)
|
||||
{
|
||||
case PROBE_ALTERA_BYTEBLASTER:
|
||||
probe_detected = 1;
|
||||
|
||||
/*
|
||||
// Loop back test
|
||||
out_io_port(lpt_address, 0x00);
|
||||
if( in_io_port(lpt_address + 1) & 0x40)
|
||||
{
|
||||
probe_detected = 0;
|
||||
}
|
||||
|
||||
out_io_port(lpt_address, 0x10);
|
||||
if( !(in_io_port(lpt_address + 1) & 0x40))
|
||||
{
|
||||
probe_detected = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// Enable outputs.
|
||||
if(probe_detected)
|
||||
out_io_port((unsigned short)(lpt_address + 0x02), 0x02);
|
||||
break;
|
||||
|
||||
default:
|
||||
probe_detected = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(probe_detected)
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_INFO_0,"drv_LPT_Init : Probe Driver loaded successfully...\r\n");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
jtagcore_logs_printf(jc,MSG_ERROR,"drv_LPT_Init : No probe found !\r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int drv_LPT_DeInit(jtag_core * jc)
|
||||
{
|
||||
#if defined(WIN32)
|
||||
CloseHandle(h);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drv_LPT_TDOTDI_xfer(jtag_core * jc, unsigned char * str_out, unsigned char * str_in, int size)
|
||||
{
|
||||
int i;
|
||||
int tms, tdi;
|
||||
|
||||
|
||||
if (size)
|
||||
{
|
||||
if (str_out[0] & JTAG_STR_TMS)
|
||||
{
|
||||
tms = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tms = 0;
|
||||
}
|
||||
}
|
||||
|
||||
i = 0;
|
||||
if (!str_in)
|
||||
{
|
||||
while (i < size)
|
||||
{
|
||||
|
||||
if (str_out[i] & JTAG_STR_DOUT)
|
||||
{
|
||||
tdi = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tdi = 0;
|
||||
}
|
||||
|
||||
putp(tdi, tms, IGNORE_PORT);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (i < size)
|
||||
{
|
||||
|
||||
if (str_out[i] & JTAG_STR_DOUT)
|
||||
{
|
||||
tdi = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tdi = 0;
|
||||
}
|
||||
|
||||
str_in[i] = putp(tdi, tms, READ_PORT);
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drv_LPT_TMS_xfer(jtag_core * jc, unsigned char * str_out, int size)
|
||||
{
|
||||
int i;
|
||||
int tms, tdi;
|
||||
|
||||
tdi = 0;
|
||||
i = 0;
|
||||
|
||||
while (i < size)
|
||||
{
|
||||
if (str_out[i] & JTAG_STR_TMS)
|
||||
{
|
||||
tms = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tms = 0;
|
||||
}
|
||||
|
||||
putp(tdi, tms, IGNORE_PORT);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int drv_LPT_libGetDrv(jtag_core * jc, int sub_drv, unsigned int infotype,void * returnvalue)
|
||||
{
|
||||
|
||||
drv_ptr drv_funcs =
|
||||
{
|
||||
(DRV_DETECT) drv_LPT_Detect,
|
||||
(DRV_INIT) drv_LPT_Init,
|
||||
(DRV_DEINIT) drv_LPT_DeInit,
|
||||
(DRV_TXTMS) drv_LPT_TMS_xfer,
|
||||
(DRV_TXRXDATA) drv_LPT_TDOTDI_xfer,
|
||||
(DRV_GETMODULEINFOS) drv_LPT_libGetDrv
|
||||
};
|
||||
|
||||
return GetDrvInfo(
|
||||
jc,
|
||||
infotype,
|
||||
returnvalue,
|
||||
subdrv_list[sub_drv].drv_id,
|
||||
subdrv_list[sub_drv].drv_desc,
|
||||
&drv_funcs
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
30
src/modules/drivers/lpt_jtag/lpt_jtag_drv.h
Normal file
30
src/modules/drivers/lpt_jtag/lpt_jtag_drv.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef _LPT_JTAG_DRV_H
|
||||
#define _LPT_JTAG_DRV_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 lpt_jtag_drv.h
|
||||
* @brief parallel port probes driver entry point definition
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
int drv_LPT_libGetDrv(jtag_core * jc,int sub_drv,unsigned int infotype,void * returnvalue);
|
||||
|
||||
#endif
|
||||
14
src/modules/fpga/CMakeLists.txt
Normal file
14
src/modules/fpga/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
file(GLOB_RECURSE ALL_SOURCES "*.c")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
|
||||
add_library(fpga ${ALL_SOURCES})
|
||||
|
||||
# The registry is parsed from YAML at runtime via libyaml (the canonical
|
||||
# C YAML parser). Found through pkg-config; PUBLIC so the executable that
|
||||
# links fpga picks up the dependency transitively.
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(YAML REQUIRED IMPORTED_TARGET yaml-0.1)
|
||||
target_link_libraries(fpga PUBLIC PkgConfig::YAML)
|
||||
311
src/modules/fpga/fpga.c
Normal file
311
src/modules/fpga/fpga.c
Normal file
@@ -0,0 +1,311 @@
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <yaml.h>
|
||||
|
||||
#include "fpga.h"
|
||||
|
||||
/*
|
||||
* FPGA registry loaded at runtime from a YAML file (no longer a
|
||||
* compile-time array). Lookup order for the file:
|
||||
* 1. $BS_FPGA_REGISTRY (if set and non-empty)
|
||||
* 2. "fpga_registry.yaml" relative to the current directory
|
||||
* — the same CWD-relative convention as bsdl_files/ and bscan_proxies/,
|
||||
* so run bs_explorer from the repository root.
|
||||
*
|
||||
* Loaded lazily on first access and cached for the process lifetime.
|
||||
* The schema is one flat mapping per entry; see fpga_registry.yaml.
|
||||
*/
|
||||
|
||||
#define DEFAULT_REGISTRY_FILE "data/fpga_registry.yaml"
|
||||
|
||||
static fpga_target *g_registry = NULL;
|
||||
static int g_count = 0;
|
||||
static int g_loaded = 0; /* load attempted (success or not) */
|
||||
static char g_source[1024] = "";
|
||||
|
||||
/* ---- small helpers ----------------------------------------------- */
|
||||
|
||||
static char *xstrdup(const char *s)
|
||||
{
|
||||
char *p;
|
||||
size_t n;
|
||||
if (!s) return NULL;
|
||||
n = strlen(s) + 1;
|
||||
p = (char *)malloc(n);
|
||||
if (p) memcpy(p, s, n);
|
||||
return p;
|
||||
}
|
||||
|
||||
static fpga_family parse_family(const char *s)
|
||||
{
|
||||
if (!s) return FPGA_FAMILY_UNKNOWN;
|
||||
if (!strcmp(s, "xilinx_7")) return FPGA_FAMILY_XILINX_7;
|
||||
if (!strcmp(s, "xilinx_us")) return FPGA_FAMILY_XILINX_US;
|
||||
if (!strcmp(s, "xilinx_usp")) return FPGA_FAMILY_XILINX_USP;
|
||||
if (!strcmp(s, "microsemi_igloo2")) return FPGA_FAMILY_MICROSEMI_IGLOO2;
|
||||
if (!strcmp(s, "microsemi_smartfusion2")) return FPGA_FAMILY_MICROSEMI_SMARTFUSION2;
|
||||
if (!strcmp(s, "lattice_machxo2")) return FPGA_FAMILY_LATTICE_MACHXO2;
|
||||
if (!strcmp(s, "lattice_machxo3")) return FPGA_FAMILY_LATTICE_MACHXO3;
|
||||
fprintf(stderr, "fpga: unknown family '%s'\n", s);
|
||||
return FPGA_FAMILY_UNKNOWN;
|
||||
}
|
||||
|
||||
static fpga_prog_method parse_prog(const char *s)
|
||||
{
|
||||
if (!s) return FPGA_PROG_NONE;
|
||||
if (!strcmp(s, "proxy_spi")) return FPGA_PROG_PROXY_SPI;
|
||||
if (!strcmp(s, "svf")) return FPGA_PROG_SVF;
|
||||
if (!strcmp(s, "none")) return FPGA_PROG_NONE;
|
||||
fprintf(stderr, "fpga: unknown prog method '%s'\n", s);
|
||||
return FPGA_PROG_NONE;
|
||||
}
|
||||
|
||||
/* Guess the programming method when the entry doesn't state one. */
|
||||
static fpga_prog_method infer_prog(const fpga_target *t)
|
||||
{
|
||||
if (t->proxy_bitstream) return FPGA_PROG_PROXY_SPI;
|
||||
switch (t->family) {
|
||||
case FPGA_FAMILY_MICROSEMI_IGLOO2:
|
||||
case FPGA_FAMILY_MICROSEMI_SMARTFUSION2:
|
||||
case FPGA_FAMILY_LATTICE_MACHXO2:
|
||||
case FPGA_FAMILY_LATTICE_MACHXO3: return FPGA_PROG_SVF;
|
||||
default: return FPGA_PROG_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int parse_caveats(const char *s)
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
char buf[256];
|
||||
char *tok;
|
||||
|
||||
if (!s) return 0;
|
||||
strncpy(buf, s, sizeof(buf) - 1);
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
|
||||
for (tok = strtok(buf, " ,|"); tok; tok = strtok(NULL, " ,|")) {
|
||||
if (!strcmp(tok, "cclk_via_startup"))
|
||||
flags |= FPGA_CAVEAT_CCLK_VIA_STARTUP;
|
||||
else
|
||||
fprintf(stderr, "fpga: unknown caveat '%s'\n", tok);
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
/* Apply one "key: value" pair (both scalars) to the entry being built. */
|
||||
static void set_field(fpga_target *t, const char *key, const char *val)
|
||||
{
|
||||
if (!strcmp(key, "name")) { free((void *)t->name); t->name = xstrdup(val); }
|
||||
else if (!strcmp(key, "idcode")) t->idcode = strtoul(val, NULL, 0);
|
||||
else if (!strcmp(key, "idcode_mask")) t->idcode_mask = strtoul(val, NULL, 0);
|
||||
else if (!strcmp(key, "family")) t->family = parse_family(val);
|
||||
else if (!strcmp(key, "bsdl")) { free((void *)t->bsdl_filename); t->bsdl_filename = xstrdup(val); }
|
||||
else if (!strcmp(key, "ir_length")) t->ir_length = (int)strtol(val, NULL, 0);
|
||||
else if (!strcmp(key, "ir_cfg_in")) t->ir_cfg_in = (unsigned int)strtoul(val, NULL, 0);
|
||||
else if (!strcmp(key, "ir_user1")) t->ir_user1 = (unsigned int)strtoul(val, NULL, 0);
|
||||
else if (!strcmp(key, "ir_jprogram")) t->ir_jprogram = (unsigned int)strtoul(val, NULL, 0);
|
||||
else if (!strcmp(key, "ir_jstart")) t->ir_jstart = (unsigned int)strtoul(val, NULL, 0);
|
||||
else if (!strcmp(key, "ir_jshutdown")) t->ir_jshutdown = (unsigned int)strtoul(val, NULL, 0);
|
||||
else if (!strcmp(key, "ir_isc_disable")) t->ir_isc_disable = (unsigned int)strtoul(val, NULL, 0);
|
||||
else if (!strcmp(key, "proxy_bitstream")) { free((void *)t->proxy_bitstream); t->proxy_bitstream = xstrdup(val); }
|
||||
else if (!strcmp(key, "caveats")) t->caveats = parse_caveats(val);
|
||||
else if (!strcmp(key, "max_tck_khz")) t->max_tck_khz = (int)strtol(val, NULL, 0);
|
||||
else if (!strcmp(key, "prog")) t->prog = parse_prog(val);
|
||||
else fprintf(stderr, "fpga: unknown key '%s'\n", key);
|
||||
}
|
||||
|
||||
static int commit_entry(const fpga_target *cur)
|
||||
{
|
||||
fpga_target *tmp = (fpga_target *)realloc(g_registry,
|
||||
(g_count + 1) * sizeof(*g_registry));
|
||||
if (!tmp) {
|
||||
fprintf(stderr, "fpga: out of memory loading registry\n");
|
||||
return -1;
|
||||
}
|
||||
g_registry = tmp;
|
||||
g_registry[g_count] = *cur;
|
||||
if (g_registry[g_count].prog == FPGA_PROG_NONE)
|
||||
g_registry[g_count].prog = infer_prog(&g_registry[g_count]);
|
||||
g_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Walk the YAML event stream. The document is a mapping with a single
|
||||
* "fpgas" key holding a sequence of flat (scalar-only) mappings. */
|
||||
static int load_registry(const char *path)
|
||||
{
|
||||
FILE *f;
|
||||
yaml_parser_t parser;
|
||||
yaml_event_t ev;
|
||||
int done = 0;
|
||||
int rc = 0;
|
||||
|
||||
int in_fpgas = 0; /* inside the fpgas: sequence */
|
||||
int in_item = 0; /* inside one entry mapping */
|
||||
int expect_fpgas_seq = 0; /* last top-level key was "fpgas" */
|
||||
char *pending_key = NULL;
|
||||
fpga_target cur;
|
||||
|
||||
f = fopen(path, "rb");
|
||||
if (!f) return -1;
|
||||
|
||||
if (!yaml_parser_initialize(&parser)) { fclose(f); return -1; }
|
||||
yaml_parser_set_input_file(&parser, f);
|
||||
|
||||
while (!done) {
|
||||
if (!yaml_parser_parse(&parser, &ev)) {
|
||||
fprintf(stderr, "fpga: YAML parse error in %s: %s (line %lu)\n",
|
||||
path, parser.problem ? parser.problem : "?",
|
||||
(unsigned long)parser.problem_mark.line + 1);
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ev.type) {
|
||||
case YAML_SCALAR_EVENT: {
|
||||
const char *v = (const char *)ev.data.scalar.value;
|
||||
if (!in_fpgas) {
|
||||
if (!strcmp(v, "fpgas"))
|
||||
expect_fpgas_seq = 1;
|
||||
} else if (in_item) {
|
||||
if (!pending_key) {
|
||||
pending_key = xstrdup(v);
|
||||
} else {
|
||||
set_field(&cur, pending_key, v);
|
||||
free(pending_key);
|
||||
pending_key = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case YAML_SEQUENCE_START_EVENT:
|
||||
if (expect_fpgas_seq && !in_fpgas) {
|
||||
in_fpgas = 1;
|
||||
expect_fpgas_seq = 0;
|
||||
}
|
||||
break;
|
||||
case YAML_SEQUENCE_END_EVENT:
|
||||
if (in_fpgas && !in_item)
|
||||
in_fpgas = 0; /* end of the fpgas list */
|
||||
break;
|
||||
case YAML_MAPPING_START_EVENT:
|
||||
if (in_fpgas && !in_item) {
|
||||
memset(&cur, 0, sizeof(cur));
|
||||
cur.idcode_mask = 0xFFFFFFFFUL; /* safe default: exact match */
|
||||
in_item = 1;
|
||||
}
|
||||
break;
|
||||
case YAML_MAPPING_END_EVENT:
|
||||
if (in_item) {
|
||||
in_item = 0;
|
||||
free(pending_key);
|
||||
pending_key = NULL;
|
||||
if (commit_entry(&cur) != 0) {
|
||||
rc = -1;
|
||||
yaml_event_delete(&ev);
|
||||
done = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case YAML_STREAM_END_EVENT:
|
||||
done = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
yaml_event_delete(&ev);
|
||||
}
|
||||
|
||||
free(pending_key);
|
||||
yaml_parser_delete(&parser);
|
||||
fclose(f);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void ensure_loaded(void)
|
||||
{
|
||||
const char *path;
|
||||
|
||||
if (g_loaded) return;
|
||||
g_loaded = 1;
|
||||
|
||||
path = getenv("BS_FPGA_REGISTRY");
|
||||
if (!path || !*path) path = DEFAULT_REGISTRY_FILE;
|
||||
|
||||
load_registry(path); /* fills g_registry/g_count; warns on its own errors */
|
||||
|
||||
if (g_count > 0) {
|
||||
strncpy(g_source, path, sizeof(g_source) - 1);
|
||||
g_source[sizeof(g_source) - 1] = '\0';
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"fpga: no targets loaded from '%s' "
|
||||
"(set BS_FPGA_REGISTRY, or run from the directory containing it)\n",
|
||||
path);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- public API -------------------------------------------------- */
|
||||
|
||||
int fpga_get_target_count(void)
|
||||
{
|
||||
ensure_loaded();
|
||||
return g_count;
|
||||
}
|
||||
|
||||
const fpga_target *fpga_get_target_by_index(int index)
|
||||
{
|
||||
ensure_loaded();
|
||||
if (index < 0 || index >= g_count) {
|
||||
return NULL;
|
||||
}
|
||||
return &g_registry[index];
|
||||
}
|
||||
|
||||
const fpga_target *fpga_lookup_by_idcode(unsigned long idcode)
|
||||
{
|
||||
int i;
|
||||
ensure_loaded();
|
||||
for (i = 0; i < g_count; i++) {
|
||||
const fpga_target *t = &g_registry[i];
|
||||
if ((idcode & t->idcode_mask) == (t->idcode & t->idcode_mask)) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *fpga_family_name(fpga_family f)
|
||||
{
|
||||
switch (f) {
|
||||
case FPGA_FAMILY_XILINX_7: return "Xilinx 7-Series";
|
||||
case FPGA_FAMILY_XILINX_US: return "Xilinx UltraScale";
|
||||
case FPGA_FAMILY_XILINX_USP: return "Xilinx UltraScale+";
|
||||
case FPGA_FAMILY_MICROSEMI_IGLOO2: return "Microsemi IGLOO2";
|
||||
case FPGA_FAMILY_MICROSEMI_SMARTFUSION2: return "Microsemi SmartFusion2";
|
||||
case FPGA_FAMILY_LATTICE_MACHXO2: return "Lattice MachXO2";
|
||||
case FPGA_FAMILY_LATTICE_MACHXO3: return "Lattice MachXO3";
|
||||
case FPGA_FAMILY_UNKNOWN:
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char *fpga_prog_method_name(fpga_prog_method m)
|
||||
{
|
||||
switch (m) {
|
||||
case FPGA_PROG_PROXY_SPI: return "proxy_spi";
|
||||
case FPGA_PROG_SVF: return "svf";
|
||||
case FPGA_PROG_NONE:
|
||||
default: return "none";
|
||||
}
|
||||
}
|
||||
|
||||
const char *fpga_registry_source(void)
|
||||
{
|
||||
ensure_loaded();
|
||||
return g_source[0] ? g_source : NULL;
|
||||
}
|
||||
78
src/modules/fpga/fpga.h
Normal file
78
src/modules/fpga/fpga.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef _FPGA_H
|
||||
#define _FPGA_H
|
||||
|
||||
/*
|
||||
* Per-target FPGA descriptor and registry.
|
||||
*
|
||||
* Holds the facts that cannot be derived from the BSDL alone:
|
||||
* - IDCODE pattern to match on the chain
|
||||
* - private IR opcodes (USER1, CFG_IN, JPROGRAM, …) needed for
|
||||
* configuration and for the BSCAN proxy bridge (Phase 2.5)
|
||||
* - path to the BSCAN proxy bitstream
|
||||
* - per-target caveats (known hardware gotchas)
|
||||
*
|
||||
* The registry is loaded at runtime from a YAML file (no longer a
|
||||
* compile-time array). Adding an FPGA = one entry in the YAML +
|
||||
* its .bsd in bsdl_files/ + (optionally) its proxy .bit in
|
||||
* bscan_proxies/. See fpga_registry.yaml for the format.
|
||||
*/
|
||||
|
||||
#include "jtag_core/jtag_core.h"
|
||||
|
||||
typedef enum {
|
||||
FPGA_FAMILY_UNKNOWN = 0,
|
||||
FPGA_FAMILY_XILINX_7,
|
||||
FPGA_FAMILY_XILINX_US,
|
||||
FPGA_FAMILY_XILINX_USP,
|
||||
FPGA_FAMILY_MICROSEMI_IGLOO2,
|
||||
FPGA_FAMILY_MICROSEMI_SMARTFUSION2,
|
||||
FPGA_FAMILY_LATTICE_MACHXO2,
|
||||
FPGA_FAMILY_LATTICE_MACHXO3,
|
||||
} fpga_family;
|
||||
|
||||
/* Programming method — which backend drives this part. */
|
||||
typedef enum {
|
||||
FPGA_PROG_NONE = 0, /* no known method */
|
||||
FPGA_PROG_PROXY_SPI, /* Xilinx external SPI flash via the BSCAN proxy */
|
||||
FPGA_PROG_SVF, /* play a vendor-exported SVF (Lattice/Microsemi/…) */
|
||||
} fpga_prog_method;
|
||||
|
||||
/* Caveat flags: known hardware gotchas for a part. */
|
||||
#define FPGA_CAVEAT_CCLK_VIA_STARTUP (1u << 0) /* CCLK not directly drivable in EXTEST */
|
||||
|
||||
typedef struct {
|
||||
const char *name; /* human-readable part name */
|
||||
unsigned long idcode; /* IDCODE pattern */
|
||||
unsigned long idcode_mask; /* bits to ignore (typically 0x0FFFFFFF for Xilinx — version masked) */
|
||||
fpga_family family;
|
||||
const char *bsdl_filename; /* basename within bsdl_files/ */
|
||||
int ir_length; /* IR width in bits */
|
||||
|
||||
/* Private IR opcodes (0 = N/A for this family).
|
||||
* For Xilinx, these are read from the BSDL INSTRUCTION_OPCODE block. */
|
||||
unsigned int ir_cfg_in;
|
||||
unsigned int ir_user1;
|
||||
unsigned int ir_jprogram;
|
||||
unsigned int ir_jstart;
|
||||
unsigned int ir_jshutdown;
|
||||
unsigned int ir_isc_disable;
|
||||
|
||||
const char *proxy_bitstream; /* path under bscan_proxies/, NULL if not yet available */
|
||||
unsigned int caveats; /* FPGA_CAVEAT_* flags */
|
||||
int max_tck_khz; /* max safe JTAG TCK for this part/board, 0 = unspecified */
|
||||
fpga_prog_method prog; /* programming backend; inferred when omitted */
|
||||
} fpga_target;
|
||||
|
||||
/* Registry access. The YAML file is loaded lazily on first call to any
|
||||
* of these, and cached for the process lifetime. */
|
||||
int fpga_get_target_count(void);
|
||||
const fpga_target * fpga_get_target_by_index(int index);
|
||||
const fpga_target * fpga_lookup_by_idcode(unsigned long idcode);
|
||||
const char * fpga_family_name(fpga_family f);
|
||||
const char * fpga_prog_method_name(fpga_prog_method m);
|
||||
|
||||
/* Path the registry was loaded from, or NULL if nothing loaded
|
||||
* (file missing / parse error). For diagnostics. */
|
||||
const char * fpga_registry_source(void);
|
||||
|
||||
#endif
|
||||
27
src/modules/jtag_core/CMakeLists.txt
Normal file
27
src/modules/jtag_core/CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(CONFIG_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../config/")
|
||||
set(LIB_FTD2XXX "${CMAKE_CURRENT_SOURCE_DIR}/../../libs/libftd2xx/libftd2xx.a")
|
||||
|
||||
file(GLOB_RECURSE ALL_SOURCES "*.c")
|
||||
|
||||
# Custom command to be executed before the build
|
||||
add_custom_command(
|
||||
OUTPUT prebuild_command_done
|
||||
COMMAND cd "${CONFIG_DIR}" && xxd -i config.script > config_script.h
|
||||
COMMENT "Generating the config script"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# Custom target that depends on the custom command
|
||||
add_custom_target(
|
||||
prebuild ALL
|
||||
DEPENDS prebuild_command_done
|
||||
)
|
||||
|
||||
include_directories(${DIR_MODULES})
|
||||
include_directories(${DIR_LIBS})
|
||||
|
||||
add_library(jtag_core ${ALL_SOURCES})
|
||||
add_dependencies(jtag_core prebuild)
|
||||
|
||||
target_link_libraries(jtag_core PRIVATE ${LIB_FTD2XXX})
|
||||
502
src/modules/jtag_core/COPYING.LESSER
Normal file
502
src/modules/jtag_core/COPYING.LESSER
Normal file
@@ -0,0 +1,502 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This 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.
|
||||
|
||||
This 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 this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
137
src/modules/jtag_core/dbg_logs.c
Normal file
137
src/modules/jtag_core/dbg_logs.c
Normal file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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 dbg_logs.c
|
||||
* @brief logs/debug output
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "jtag_core.h"
|
||||
|
||||
#include "os_interface/os_interface.h"
|
||||
|
||||
#include "dbg_logs.h"
|
||||
|
||||
int jtagcore_logs_printf(jtag_core * jc,int MSGTYPE,char * chaine, ...)
|
||||
{
|
||||
char tmp_msg[1024+1];
|
||||
char tmp_msg2[1024];
|
||||
JTAGCORE_PRINT_FUNC print_callback;
|
||||
|
||||
if( jc->logs_level <= MSGTYPE )
|
||||
{
|
||||
if( jc->jtagcore_print_callback )
|
||||
{
|
||||
va_list marker;
|
||||
va_start( marker, chaine );
|
||||
|
||||
print_callback = jc->jtagcore_print_callback;
|
||||
|
||||
switch(MSGTYPE)
|
||||
{
|
||||
case MSG_INFO_0:
|
||||
strcpy(tmp_msg,"Info : ");
|
||||
break;
|
||||
case MSG_INFO_1:
|
||||
strcpy(tmp_msg,"Info : ");
|
||||
break;
|
||||
case MSG_WARNING:
|
||||
strcpy(tmp_msg,"Warning : ");
|
||||
break;
|
||||
case MSG_ERROR:
|
||||
strcpy(tmp_msg,"Error : ");
|
||||
break;
|
||||
case MSG_DEBUG:
|
||||
strcpy(tmp_msg,"Debug : ");
|
||||
break;
|
||||
default:
|
||||
strcpy(tmp_msg,"Unknown : ");
|
||||
break;
|
||||
}
|
||||
|
||||
vsprintf(tmp_msg2,chaine,marker);
|
||||
genos_strndstcat(tmp_msg, tmp_msg2, sizeof(tmp_msg) );
|
||||
tmp_msg[sizeof(tmp_msg) - 1] = '\0';
|
||||
|
||||
print_callback( jc, tmp_msg);
|
||||
|
||||
va_end( marker );
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int jtagcore_set_logs_callback(jtag_core * jc, JTAGCORE_PRINT_FUNC jtag_core_print)
|
||||
{
|
||||
if(jc)
|
||||
{
|
||||
jc->jtagcore_print_callback = jtag_core_print;
|
||||
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
int jtagcore_set_logs_level(jtag_core * jc,int level)
|
||||
{
|
||||
if(jc)
|
||||
{
|
||||
jc->logs_level = level;
|
||||
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
int jtagcore_get_logs_level(jtag_core * jc)
|
||||
{
|
||||
if(jc)
|
||||
{
|
||||
return jc->logs_level;
|
||||
}
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
int jtagcore_set_logs_file(jtag_core * jc,char * path)
|
||||
{
|
||||
if(jc)
|
||||
{
|
||||
strncpy(jc->log_file_path, path, DEFAULT_BUFLEN - 1);
|
||||
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
return JTAG_CORE_BAD_PARAMETER;
|
||||
}
|
||||
|
||||
char * jtagcore_get_logs_file(jtag_core * jc)
|
||||
{
|
||||
if(jc)
|
||||
{
|
||||
return jc->log_file_path;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
32
src/modules/jtag_core/dbg_logs.h
Normal file
32
src/modules/jtag_core/dbg_logs.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef _DBG_LOGS_H
|
||||
#define _DBG_LOGS_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 dbg_logs.c
|
||||
* @brief logs/debug output
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include "config/bs_defines.h"
|
||||
|
||||
int jtagcore_logs_printf(jtag_core * jc, int MSGTYPE, char * chaine, ...);
|
||||
|
||||
#endif
|
||||
1059
src/modules/jtag_core/jtag_core.c
Normal file
1059
src/modules/jtag_core/jtag_core.c
Normal file
File diff suppressed because it is too large
Load Diff
270
src/modules/jtag_core/jtag_core.h
Normal file
270
src/modules/jtag_core/jtag_core.h
Normal file
@@ -0,0 +1,270 @@
|
||||
#ifndef _JTAG_CORE_H
|
||||
#define _JTAG_CORE_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 jtag_core.h
|
||||
* @brief Main jtag core library header
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include "config/bs_defines.h"
|
||||
|
||||
#define JTAG_STR_DOUT 0x01
|
||||
#define JTAG_STR_TMS 0x02
|
||||
#define JTAG_STR_CLKDIS 0x04
|
||||
#define JTAG_STR_JTAGRST 0x08
|
||||
#define JTAG_STR_DIN 0x10
|
||||
#define JTAG_STR_DINREQ 0x20
|
||||
|
||||
int jtagcore_loaddriver(jtag_core *jc, int id, char *parameters);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Lib init functions
|
||||
|
||||
// jtagcore_init : Library alloc and init
|
||||
jtag_core *jtagcore_init();
|
||||
|
||||
// jtagcore_init : Library dealloc and deinit
|
||||
void jtagcore_deinit(jtag_core *jc);
|
||||
|
||||
#ifndef _JTAGCORE_PRINT_FUNC_
|
||||
typedef void (*JTAGCORE_PRINT_FUNC)(jtag_core *jc, const char *string);
|
||||
#define _JTAGCORE_PRINT_FUNC_
|
||||
#endif
|
||||
|
||||
int jtagcore_set_logs_callback(jtag_core *jc, JTAGCORE_PRINT_FUNC jtag_core_print);
|
||||
int jtagcore_set_logs_level(jtag_core *jc, int level);
|
||||
int jtagcore_get_logs_level(jtag_core *jc);
|
||||
int jtagcore_set_logs_file(jtag_core *jc, char *path);
|
||||
char *jtagcore_get_logs_file(jtag_core *jc);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Probe driver selection/initialisation functions
|
||||
|
||||
// jtagcore_get_number_of_probes_drv : Return the "number of supported probes"
|
||||
|
||||
int jtagcore_get_number_of_probes_drv(jtag_core *jc);
|
||||
int jtagcore_get_number_of_probes(jtag_core *jc, int probe_driver_id);
|
||||
|
||||
#define PROBE_ID(drv_id, probe_index) ((drv_id << 8) | probe_index)
|
||||
|
||||
// jtagcore_get_probe_name : Return the probe name (probe_id should be between 0 and "number of supported probes" - 1)
|
||||
|
||||
int jtagcore_get_probe_name(jtag_core *jc, int probe_id, char *name);
|
||||
|
||||
// jtagcore_select_and_open_probe : Try to init the probe (probe_id should be between 0 and "number of supported probes" - 1)
|
||||
|
||||
int jtagcore_select_and_open_probe(jtag_core *jc, int probe_id);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// JTAG Chain init functions
|
||||
|
||||
// jtagcore_scan_and_init_chain : Scan and init the chain (devices detection)
|
||||
|
||||
int jtagcore_scan_and_init_chain(jtag_core *jc);
|
||||
|
||||
// jtagcore_get_number_of_devices : return "the number of devices into the chain" found by jtagcore_scan_and_init_chain
|
||||
|
||||
int jtagcore_get_number_of_devices(jtag_core *jc);
|
||||
|
||||
// jtagcore_get_dev_id : Return the device chip ID
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
|
||||
unsigned long jtagcore_get_dev_id(jtag_core *jc, int device);
|
||||
|
||||
// jtagcore_loadbsdlfile : Load/attach a bsdl file to a device into the chain
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
|
||||
int jtagcore_loadbsdlfile(jtag_core *jc, char *path, int device);
|
||||
|
||||
// jtagcore_get_dev_name : Get the currently loaded bsdl name & path
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
int jtagcore_get_dev_name(jtag_core *jc, int device, char *devname, char *bsdlpath);
|
||||
|
||||
// jtagcore_get_bsdl_id : Return the chip id present into a bsdl file
|
||||
|
||||
unsigned long jtagcore_get_bsdl_id(jtag_core *jc, char *path, unsigned long *mask);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Pins/IO access functions
|
||||
|
||||
// jtagcore_get_number_of_pins : Return the number of pins of a device.
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
// and a bsdl must be attached to this device
|
||||
|
||||
int jtagcore_get_number_of_pins(jtag_core *jc, int device);
|
||||
|
||||
// jtagcore_get_pin_properties : Return the pin properties
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
// and a bsdl must be attached to this device
|
||||
// "pin" should be between 0 and "number of pins of a device" - 1
|
||||
// "type" return is a mask between JTAG_CORE_PIN_IS_INPUT / JTAG_CORE_PIN_IS_OUTPUT / JTAG_CORE_PIN_IS_TRISTATES states
|
||||
|
||||
int jtagcore_get_pin_properties(jtag_core *jc, int device, int pin, char *pinname, int maxsize, int *type);
|
||||
|
||||
#define JTAG_CORE_PIN_IS_INPUT 0x01
|
||||
#define JTAG_CORE_PIN_IS_OUTPUT 0x02
|
||||
#define JTAG_CORE_PIN_IS_TRISTATES 0x04
|
||||
|
||||
// jtagcore_get_pin_id : Find and return a pin id (if exist) from the pin name
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
|
||||
int jtagcore_get_pin_id(jtag_core *jc, int device, char *pinname);
|
||||
|
||||
// jtagcore_get_pin_state : Return the current pin state
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
// "pin" should be between 0 and "number of pins of a device" - 1
|
||||
// "type" should be set to JTAG_CORE_INPUT or JTAG_CORE_OUTPUT or JTAG_CORE_OE
|
||||
|
||||
int jtagcore_get_pin_state(jtag_core *jc, int device, int pin, int type);
|
||||
|
||||
// jtagcore_set_pin_state : Set the pin state
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
// "pin" should be between 0 and "number of pins of a device" - 1
|
||||
// "type" should be set to JTAG_CORE_INPUT or JTAG_CORE_OUTPUT or JTAG_CORE_OE
|
||||
|
||||
int jtagcore_set_pin_state(jtag_core *jc, int device, int pin, int type, int state);
|
||||
|
||||
#define JTAG_CORE_INPUT 0x01
|
||||
#define JTAG_CORE_OUTPUT 0x02
|
||||
#define JTAG_CORE_OE 0x04
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Scan chain functions
|
||||
|
||||
// jtagcore_set_scan_mode : Set the scan mode for a particular device
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
// "scan_mode" should be set to JTAG_CORE_SAMPLE_SCANMODE (observation only) or JTAG_CORE_EXTEST_SCANMODE (full pin control)
|
||||
int jtagcore_set_scan_mode(jtag_core *jc, int device, int scan_mode);
|
||||
|
||||
// JTAG Scan mode
|
||||
#define JTAG_CORE_SAMPLE_SCANMODE 0x00
|
||||
#define JTAG_CORE_EXTEST_SCANMODE 0x01
|
||||
|
||||
// jtagcore_push_and_pop_chain : Do a JTAG chain transaction.
|
||||
// "mode" should be set to JTAG_CORE_WRITE_READ (Push/write and pop/read the chain) or JTAG_CORE_WRITE_ONLY (only Push/write the chain)
|
||||
int jtagcore_push_and_pop_chain(jtag_core *jc, int mode);
|
||||
|
||||
#define JTAG_CORE_WRITE_READ 0x00
|
||||
#define JTAG_CORE_WRITE_ONLY 0x01
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// I2C over JTAG API functions
|
||||
|
||||
// jtagcore_i2c_set_scl_pin : Select the SCL pin
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
// "pin" should be between 0 and "number of pins of a device" - 1
|
||||
|
||||
int jtagcore_i2c_set_scl_pin(jtag_core *jc, int device, int pin);
|
||||
|
||||
// jtagcore_i2c_set_sda_pin : Select the SDA pin
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
// "pin" should be between 0 and "number of pins of a device" - 1
|
||||
|
||||
int jtagcore_i2c_set_sda_pin(jtag_core *jc, int device, int pin);
|
||||
|
||||
// jtagcore_i2c_write_read : Do an I2C transfert
|
||||
// "address" : I2C address (8 bits aligned)
|
||||
// "address10bits" != 0 if this is an 10bits address
|
||||
// "wr_size" write size
|
||||
// "rd_size" read size
|
||||
int jtagcore_i2c_write_read(jtag_core *jc, int address, int address10bits, int wr_size, unsigned char *wr_buffer, int rd_size, unsigned char *rd_buffer);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// SPI over JTAG API functions
|
||||
|
||||
// jtagcore_spi_set_cs_pin : Select the CS pin
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
// "pin" should be between 0 and "number of pins of a device" - 1
|
||||
|
||||
int jtagcore_spi_set_cs_pin(jtag_core *jc, int device, int pin, int polarity);
|
||||
|
||||
// jtagcore_spi_set_clk_pin : Select the CLK pin
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
// "pin" should be between 0 and "number of pins of a device" - 1
|
||||
|
||||
int jtagcore_spi_set_clk_pin(jtag_core *jc, int device, int pin, int polarity);
|
||||
|
||||
// jtagcore_spi_set_miso_pin : Select the MISO pin
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
// "pin" should be between 0 and "number of pins of a device" - 1
|
||||
|
||||
int jtagcore_spi_set_miso_pin(jtag_core *jc, int device, int pin, int sample_clk_phase);
|
||||
|
||||
// jtagcore_spi_set_mosi_pin : Select the MOSI pin
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
// "pin" should be between 0 and "number of pins of a device" - 1
|
||||
|
||||
int jtagcore_spi_set_mosi_pin(jtag_core *jc, int device, int pin, int sample_clk_phase);
|
||||
|
||||
// jtagcore_spi_write_read : Do a SPI transfert
|
||||
// "wr_size" is the transaction size
|
||||
|
||||
int jtagcore_spi_write_read(jtag_core *jc, int wr_size, unsigned char *wr_buffer, unsigned char *rd_buffer, int flags);
|
||||
|
||||
// jtagcore_spi_set_bitorder : Select MSB/LSB first mode
|
||||
|
||||
int jtagcore_spi_set_bitorder(jtag_core *jc, int lsb_first);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// MDIO over JTAG API functions
|
||||
|
||||
// jtagcore_mdio_set_mdio_pin : Select the MDIO pin
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
// "pin" should be between 0 and "number of pins of a device" - 1
|
||||
|
||||
int jtagcore_mdio_set_mdio_pin(jtag_core *jc, int device, int pin);
|
||||
|
||||
// jtagcore_mdio_set_mdc_pin : Select the MDC pin
|
||||
// "device" should be between 0 and "the number of devices into the chain" - 1
|
||||
// "pin" should be between 0 and "number of pins of a device" - 1
|
||||
|
||||
int jtagcore_mdio_set_mdc_pin(jtag_core *jc, int device, int pin);
|
||||
|
||||
// jtagcore_mdio_read : Read to an MDIO register
|
||||
// phy_adr : Phylayer address
|
||||
// reg_adr : Register address
|
||||
|
||||
int jtagcore_mdio_read(jtag_core *jc, int phy_adr, int reg_adr);
|
||||
|
||||
// jtagcore_mdio_write : Write to an MDIO register
|
||||
// phy_adr : Phylayer address
|
||||
// reg_adr : Register address
|
||||
// data : data value to write
|
||||
|
||||
int jtagcore_mdio_write(jtag_core *jc, int phy_adr, int reg_adr, int data);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Parallel Memory over JTAG API functions
|
||||
|
||||
#define JTAG_CORE_RAM_CS_CTRL 0x00
|
||||
#define JTAG_CORE_RAM_WR_CTRL 0x01
|
||||
#define JTAG_CORE_RAM_RD_CTRL 0x02
|
||||
#define JTAG_CORE_RAM_RW_CTRL 0x03
|
||||
|
||||
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_data_pin(jtag_core *jc, int data_bit, int device, int pin);
|
||||
int jtagcore_memory_set_ctrl_pin(jtag_core *jc, int ctrl, int polarity, int device, int pin);
|
||||
unsigned long jtagcore_memory_read(jtag_core *jc, int mem_adr);
|
||||
int jtagcore_memory_write(jtag_core *jc, int mem_adr, unsigned long data);
|
||||
|
||||
#endif
|
||||
5
src/modules/natsort/CMakeLists.txt
Normal file
5
src/modules/natsort/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
file(GLOB_RECURSE ALL_SOURCES "*.c")
|
||||
|
||||
add_library(natsort ${ALL_SOURCES})
|
||||
178
src/modules/natsort/strnatcmp.c
Normal file
178
src/modules/natsort/strnatcmp.c
Normal file
@@ -0,0 +1,178 @@
|
||||
/* -*- mode: c; c-file-style: "k&r" -*-
|
||||
|
||||
strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
|
||||
Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
/* partial change history:
|
||||
*
|
||||
* 2004-10-10 mbp: Lift out character type dependencies into macros.
|
||||
*
|
||||
* Eric Sosman pointed out that ctype functions take a parameter whose
|
||||
* value must be that of an unsigned int, even on platforms that have
|
||||
* negative chars in their default char type.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "strnatcmp.h"
|
||||
|
||||
|
||||
/* These are defined as macros to make it easier to adapt this code to
|
||||
* different characters types or comparison functions. */
|
||||
static /*inline*/ int
|
||||
nat_isdigit(nat_char a)
|
||||
{
|
||||
return isdigit((unsigned char) a);
|
||||
}
|
||||
|
||||
|
||||
static /*inline*/ int
|
||||
nat_isspace(nat_char a)
|
||||
{
|
||||
return isspace((unsigned char) a);
|
||||
}
|
||||
|
||||
|
||||
static /*inline*/ nat_char
|
||||
nat_toupper(nat_char a)
|
||||
{
|
||||
return toupper((unsigned char) a);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
compare_right(nat_char const *a, nat_char const *b)
|
||||
{
|
||||
int bias = 0;
|
||||
|
||||
/* The longest run of digits wins. That aside, the greatest
|
||||
value wins, but we can't know that it will until we've scanned
|
||||
both numbers to know that they have the same magnitude, so we
|
||||
remember it in BIAS. */
|
||||
for (;; a++, b++) {
|
||||
if (!nat_isdigit(*a) && !nat_isdigit(*b))
|
||||
return bias;
|
||||
else if (!nat_isdigit(*a))
|
||||
return -1;
|
||||
else if (!nat_isdigit(*b))
|
||||
return +1;
|
||||
else if (*a < *b) {
|
||||
if (!bias)
|
||||
bias = -1;
|
||||
} else if (*a > *b) {
|
||||
if (!bias)
|
||||
bias = +1;
|
||||
} else if (!*a && !*b)
|
||||
return bias;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
compare_left(nat_char const *a, nat_char const *b)
|
||||
{
|
||||
/* Compare two left-aligned numbers: the first to have a
|
||||
different value wins. */
|
||||
for (;; a++, b++) {
|
||||
if (!nat_isdigit(*a) && !nat_isdigit(*b))
|
||||
return 0;
|
||||
else if (!nat_isdigit(*a))
|
||||
return -1;
|
||||
else if (!nat_isdigit(*b))
|
||||
return +1;
|
||||
else if (*a < *b)
|
||||
return -1;
|
||||
else if (*a > *b)
|
||||
return +1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int strnatcmp0(nat_char const *a, nat_char const *b, int fold_case)
|
||||
{
|
||||
int ai, bi;
|
||||
nat_char ca, cb;
|
||||
int fractional, result;
|
||||
|
||||
assert(a && b);
|
||||
ai = bi = 0;
|
||||
while (1) {
|
||||
ca = a[ai]; cb = b[bi];
|
||||
|
||||
/* skip over leading spaces or zeros */
|
||||
while (nat_isspace(ca))
|
||||
ca = a[++ai];
|
||||
|
||||
while (nat_isspace(cb))
|
||||
cb = b[++bi];
|
||||
|
||||
/* process run of digits */
|
||||
if (nat_isdigit(ca) && nat_isdigit(cb)) {
|
||||
fractional = (ca == '0' || cb == '0');
|
||||
|
||||
if (fractional) {
|
||||
if ((result = compare_left(a+ai, b+bi)) != 0)
|
||||
return result;
|
||||
} else {
|
||||
if ((result = compare_right(a+ai, b+bi)) != 0)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ca && !cb) {
|
||||
/* The strings compare the same. Perhaps the caller
|
||||
will want to call strcmp to break the tie. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fold_case) {
|
||||
ca = nat_toupper(ca);
|
||||
cb = nat_toupper(cb);
|
||||
}
|
||||
|
||||
if (ca < cb)
|
||||
return -1;
|
||||
else if (ca > cb)
|
||||
return +1;
|
||||
|
||||
++ai; ++bi;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int strnatcmp(nat_char const *a, nat_char const *b) {
|
||||
return strnatcmp0(a, b, 0);
|
||||
}
|
||||
|
||||
|
||||
/* Compare, recognizing numeric string and ignoring case. */
|
||||
int strnatcasecmp(nat_char const *a, nat_char const *b) {
|
||||
return strnatcmp0(a, b, 1);
|
||||
}
|
||||
36
src/modules/natsort/strnatcmp.h
Normal file
36
src/modules/natsort/strnatcmp.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef _STRNATCMP_H
|
||||
#define _STRNATCMP_H
|
||||
|
||||
/* -*- mode: c; c-file-style: "k&r" -*-
|
||||
|
||||
strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
|
||||
Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
|
||||
/* CUSTOMIZATION SECTION
|
||||
*
|
||||
* You can change this typedef, but must then also change the inline
|
||||
* functions in strnatcmp.c */
|
||||
typedef char nat_char;
|
||||
|
||||
int strnatcmp(nat_char const *a, nat_char const *b);
|
||||
int strnatcasecmp(nat_char const *a, nat_char const *b);
|
||||
|
||||
#endif
|
||||
5
src/modules/os_interface/CMakeLists.txt
Normal file
5
src/modules/os_interface/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
file(GLOB_RECURSE ALL_SOURCES "*.c")
|
||||
|
||||
add_library(os_interface ${ALL_SOURCES})
|
||||
595
src/modules/os_interface/fs.c
Normal file
595
src/modules/os_interface/fs.c
Normal file
@@ -0,0 +1,595 @@
|
||||
/*
|
||||
* 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 fs.c
|
||||
* @brief Basic/generic OS file system functions wrapper.
|
||||
* @author Jean-Fran<61>ois DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
#ifdef WIN32
|
||||
# include <windows.h>
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
# include <direct.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <dirent.h>
|
||||
|
||||
#ifdef OSX
|
||||
# include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include "os_interface.h"
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
|
||||
int convertpath (const char * path, wchar_t * wpath)
|
||||
{
|
||||
if (!MultiByteToWideChar (CP_UTF8, 0, path, -1, wpath, MAX_PATH))
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
wpath[MAX_PATH] = L'\0';
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
int genos_open (const char *filename, int flags, ...)
|
||||
{
|
||||
|
||||
#ifdef WIN32
|
||||
wchar_t wpath[MAX_PATH+1];
|
||||
#else
|
||||
const char *local_name;
|
||||
#endif
|
||||
|
||||
unsigned int mode = 0;
|
||||
va_list ap;
|
||||
|
||||
#if defined (DEBUG)
|
||||
printf("genos_open : filename=%s flags=%x\n",filename,flags);
|
||||
#endif
|
||||
|
||||
va_start (ap, flags);
|
||||
if (flags & O_CREAT)
|
||||
mode = va_arg (ap, unsigned int);
|
||||
va_end (ap);
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
memset(wpath,0,(MAX_PATH+1)*sizeof(wchar_t));
|
||||
if(convertpath(filename, wpath)<0)
|
||||
return -1;
|
||||
|
||||
return _wopen (wpath, flags, mode);
|
||||
|
||||
#else
|
||||
|
||||
local_name = filename;
|
||||
//local_name = (const char *)ToLocale (filename);
|
||||
|
||||
if (local_name == NULL)
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fd = open (local_name, flags, mode);
|
||||
|
||||
//LocaleFree (local_name);
|
||||
return fd;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
FILE *genos_fopen (const char *filename, const char *mode)
|
||||
{
|
||||
int rwflags, oflags;
|
||||
int append;
|
||||
int fd;
|
||||
const char *ptr;
|
||||
FILE *stream;
|
||||
|
||||
#if defined (DEBUG)
|
||||
printf("genos_fopen : filename=%s mode=%s\n",filename,mode);
|
||||
#endif
|
||||
|
||||
// Try the classic way (ascii path)
|
||||
stream = fopen(filename,mode);
|
||||
|
||||
if( ( stream == NULL ) && (errno == ENOENT) )
|
||||
{
|
||||
// Try the utf8 way
|
||||
rwflags = 0;
|
||||
oflags = 0;
|
||||
append = 0;
|
||||
|
||||
for(ptr = mode;*ptr;ptr++)
|
||||
{
|
||||
switch (*ptr)
|
||||
{
|
||||
case 'r':
|
||||
rwflags = O_RDONLY;
|
||||
break;
|
||||
#ifdef O_BINARY
|
||||
case 'b':
|
||||
oflags |= O_BINARY;
|
||||
break;
|
||||
#endif
|
||||
case 'a':
|
||||
rwflags = O_WRONLY;
|
||||
oflags |= O_CREAT;
|
||||
append = 1;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
rwflags = O_WRONLY;
|
||||
oflags |= O_CREAT | O_TRUNC;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
rwflags = O_RDWR;
|
||||
break;
|
||||
|
||||
#ifdef O_TEXT
|
||||
case 't':
|
||||
oflags |= O_TEXT;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
fd = genos_open (filename, rwflags|oflags, (unsigned int)(0666));
|
||||
if(fd==-1)
|
||||
return NULL;
|
||||
|
||||
if(append)
|
||||
{
|
||||
#if defined (WIN32)
|
||||
if(_lseek(fd,0,SEEK_END) == -1)
|
||||
{
|
||||
_close (fd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
if(lseek(fd,0,SEEK_END) == -1)
|
||||
{
|
||||
close (fd);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (WIN32)
|
||||
_lseek(fd,0,SEEK_SET);
|
||||
#else
|
||||
lseek(fd,0,SEEK_SET);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined (WIN32)
|
||||
stream = _fdopen(fd,mode);
|
||||
if(stream == NULL)
|
||||
{
|
||||
_close (fd);
|
||||
}
|
||||
#else
|
||||
stream = fdopen(fd,mode);
|
||||
if(stream == NULL)
|
||||
{
|
||||
close (fd);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
int genos_fread(void * ptr, size_t size, FILE *f)
|
||||
{
|
||||
|
||||
#if defined (DEBUG)
|
||||
printf("genos_fread : ptr=%p size=%zu file:%p\n",ptr,size,f);
|
||||
#endif
|
||||
|
||||
if( fread(ptr,size,1,f) != 1 )
|
||||
{
|
||||
return 1; // Error
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0; // No Error
|
||||
}
|
||||
}
|
||||
|
||||
char * genos_fgets(char * str, int num, FILE *f)
|
||||
{
|
||||
return fgets( str, num, f );
|
||||
}
|
||||
|
||||
int genos_fclose(FILE * f)
|
||||
{
|
||||
#if defined (DEBUG)
|
||||
printf("genos_fclose : file:%p\n",f);
|
||||
#endif
|
||||
|
||||
return fclose(f);
|
||||
}
|
||||
|
||||
int genos_statex( const char *filename, struct stat *buf)
|
||||
{
|
||||
#if defined (DEBUG)
|
||||
printf("genos_statex : filename=%s\n",filename);
|
||||
#endif
|
||||
#if defined (WIN32)
|
||||
wchar_t wpath[MAX_PATH+1];
|
||||
|
||||
if( convertpath(filename, wpath) < 0 )
|
||||
return -1;
|
||||
|
||||
return _wstat (wpath,(struct _stat *)buf);
|
||||
#else
|
||||
int res;
|
||||
const char *local_name;
|
||||
|
||||
local_name = filename;//ToLocale( filename );
|
||||
|
||||
if( local_name != NULL )
|
||||
{
|
||||
res = lstat( local_name, buf );
|
||||
// LocaleFree( local_name );
|
||||
return res;
|
||||
}
|
||||
|
||||
errno = ENOENT;
|
||||
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int genos_stat( const char *filename, struct stat *buf)
|
||||
{
|
||||
return genos_statex(filename,buf);
|
||||
}
|
||||
|
||||
void * genos_find_first_file(char *folder, char *file, filefoundinfo* fileinfo)
|
||||
{
|
||||
#if defined (DEBUG)
|
||||
printf("genos_find_first_file : folder=%s file=%s\n",folder,file);
|
||||
#endif
|
||||
|
||||
#if defined (WIN32)
|
||||
|
||||
HANDLE hfindfile;
|
||||
char *folderstr;
|
||||
WIN32_FIND_DATAW FindFileData;
|
||||
wchar_t wpath[MAX_PATH+1];
|
||||
|
||||
if(file)
|
||||
{
|
||||
folderstr=(char *) malloc(strlen(folder)+strlen(file)+2);
|
||||
sprintf((char *)folderstr,"%s\\%s",folder,file);
|
||||
}
|
||||
else
|
||||
{
|
||||
folderstr = (char *) malloc(strlen(folder)+1);
|
||||
sprintf((char *)folderstr,"%s",folder);
|
||||
}
|
||||
|
||||
convertpath (folderstr, wpath);
|
||||
hfindfile = FindFirstFileW(wpath, &FindFileData);
|
||||
if(hfindfile!=INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WideCharToMultiByte(CP_UTF8,0,FindFileData.cFileName,-1,fileinfo->filename,sizeof(fileinfo->filename),NULL,NULL);
|
||||
//sprintf(fileinfo->filename,"%s",FindFileData.cFileName);
|
||||
|
||||
fileinfo->isdirectory = 0;
|
||||
|
||||
if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
fileinfo->isdirectory = 1;
|
||||
}
|
||||
|
||||
fileinfo->size = FindFileData.nFileSizeLow;
|
||||
free(folderstr);
|
||||
return (void*)hfindfile;
|
||||
}
|
||||
else
|
||||
{
|
||||
free(folderstr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
struct dirent *d;
|
||||
DIR * dir;
|
||||
struct stat fileStat;
|
||||
char * tmpstr;
|
||||
|
||||
if(!file)
|
||||
{
|
||||
// File mode
|
||||
memset(&fileStat,0,sizeof(struct stat));
|
||||
if(!lstat (folder, &fileStat))
|
||||
{
|
||||
if ( !S_ISDIR ( fileStat.st_mode ) )
|
||||
{
|
||||
fileinfo->isdirectory = 0;
|
||||
fileinfo->size = fileStat.st_size;
|
||||
strncpy(fileinfo->filename,genos_getfilenamebase(folder,NULL,SYS_PATH_TYPE),FILEFOUND_NAMESIZE - 1);
|
||||
fileinfo->filename[FILEFOUND_NAMESIZE - 1] = 0;
|
||||
|
||||
return (void*)-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dir = opendir (folder);
|
||||
if(dir)
|
||||
{
|
||||
d = readdir (dir);
|
||||
if(d)
|
||||
{
|
||||
tmpstr = malloc (strlen(folder) + strlen(d->d_name) + 4 );
|
||||
if(tmpstr)
|
||||
{
|
||||
strcpy(tmpstr,folder);
|
||||
strcat(tmpstr,"/");
|
||||
strcat(tmpstr,d->d_name);
|
||||
|
||||
memset(&fileStat,0,sizeof(struct stat));
|
||||
if(!lstat (tmpstr, &fileStat))
|
||||
{
|
||||
|
||||
if ( S_ISDIR ( fileStat.st_mode ) )
|
||||
fileinfo->isdirectory=1;
|
||||
else
|
||||
fileinfo->isdirectory=0;
|
||||
|
||||
fileinfo->size=fileStat.st_size;
|
||||
|
||||
strncpy(fileinfo->filename,d->d_name,FILEFOUND_NAMESIZE - 1);
|
||||
fileinfo->filename[FILEFOUND_NAMESIZE - 1] = '\0';
|
||||
|
||||
free(tmpstr);
|
||||
return (void*)dir;
|
||||
}
|
||||
|
||||
free(tmpstr);
|
||||
}
|
||||
|
||||
closedir (dir);
|
||||
dir=0;
|
||||
|
||||
return (void*)dir;
|
||||
}
|
||||
|
||||
closedir (dir);
|
||||
dir=0;
|
||||
}
|
||||
|
||||
return (void*)dir;
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int genos_find_next_file(void* handleff, char *folder, char *file, filefoundinfo* fileinfo)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if defined (DEBUG)
|
||||
printf("genos_find_next_file : handleff:%p folder=%s file=%s\n",handleff,folder,file);
|
||||
#endif
|
||||
|
||||
#if defined (WIN32)
|
||||
WIN32_FIND_DATAW FindFileData;
|
||||
|
||||
|
||||
ret=FindNextFileW((HANDLE)handleff,&FindFileData);
|
||||
if(ret)
|
||||
{
|
||||
WideCharToMultiByte(CP_UTF8,0,FindFileData.cFileName,-1,fileinfo->filename,sizeof(fileinfo->filename),NULL,NULL);
|
||||
//sprintf(fileinfo->filename,"%s",FindFileData.cFileName);
|
||||
|
||||
fileinfo->isdirectory=0;
|
||||
|
||||
if( FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
|
||||
{
|
||||
fileinfo->isdirectory = 1;
|
||||
}
|
||||
|
||||
fileinfo->size = FindFileData.nFileSizeLow;
|
||||
}
|
||||
#else
|
||||
struct dirent *d;
|
||||
DIR * dir;
|
||||
struct stat fileStat;
|
||||
char * tmpstr;
|
||||
|
||||
if((long)(handleff) == -1) // File mode
|
||||
return 0;
|
||||
|
||||
dir = (DIR*) handleff;
|
||||
d = readdir (dir);
|
||||
|
||||
ret = 0;
|
||||
if(d)
|
||||
{
|
||||
tmpstr = malloc (strlen(folder) + strlen(d->d_name) + 4 );
|
||||
if(tmpstr)
|
||||
{
|
||||
strcpy(tmpstr,folder);
|
||||
strcat(tmpstr,"/");
|
||||
strcat(tmpstr,d->d_name);
|
||||
|
||||
if(!lstat (tmpstr, &fileStat))
|
||||
{
|
||||
if ( S_ISDIR ( fileStat.st_mode ) )
|
||||
fileinfo->isdirectory=1;
|
||||
else
|
||||
fileinfo->isdirectory=0;
|
||||
|
||||
fileinfo->size=fileStat.st_size;
|
||||
strncpy(fileinfo->filename,d->d_name,FILEFOUND_NAMESIZE - 1);
|
||||
fileinfo->filename[FILEFOUND_NAMESIZE - 1] = '\0';
|
||||
|
||||
ret = 1;
|
||||
free(tmpstr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
free(tmpstr);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int genos_find_close(void* handle)
|
||||
{
|
||||
#if defined (DEBUG)
|
||||
printf("genos_find_close : handle:%p\n",handle);
|
||||
#endif
|
||||
|
||||
#if defined (WIN32)
|
||||
if(handle)
|
||||
FindClose((void*)handle);
|
||||
#else
|
||||
if((long)(handle) == -1) // File mode
|
||||
return 0;
|
||||
|
||||
if(handle)
|
||||
closedir((DIR*) handle);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
char * genos_getcurrentdirectory(char *currentdirectory,int buffersize)
|
||||
{
|
||||
memset(currentdirectory,0,buffersize);
|
||||
#if defined (WIN32)
|
||||
if(GetModuleFileName(GetModuleHandle(NULL),currentdirectory,buffersize))
|
||||
{
|
||||
if(strrchr(currentdirectory,'\\'))
|
||||
{
|
||||
*((char*)strrchr(currentdirectory,'\\')) = 0;
|
||||
return currentdirectory;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
#if defined (OSX)
|
||||
|
||||
if (_NSGetExecutablePath(currentdirectory, &buffersize) == 0)
|
||||
{
|
||||
if(strrchr(currentdirectory,'/'))
|
||||
{
|
||||
*((char*)strrchr(currentdirectory,'/')) = 0;
|
||||
return currentdirectory;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
strncpy(currentdirectory,"./",buffersize - 1);
|
||||
currentdirectory[buffersize-1] = '\0';
|
||||
|
||||
return currentdirectory;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int genos_mkdir(char * folder)
|
||||
{
|
||||
#if defined (DEBUG)
|
||||
printf("genos_mkdir : folder:%s\n",folder);
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
_mkdir(folder);
|
||||
#else
|
||||
mkdir(folder,0777);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int genos_fgetsize( FILE * f )
|
||||
{
|
||||
int cur_pos,filesize;
|
||||
|
||||
filesize = 0;
|
||||
|
||||
if( f )
|
||||
{
|
||||
cur_pos = ftell(f);
|
||||
if( cur_pos >= 0 )
|
||||
{
|
||||
if(fseek (f , 0 , SEEK_END))
|
||||
return 0;
|
||||
|
||||
filesize = ftell(f);
|
||||
|
||||
if( filesize < 0 )
|
||||
filesize = 0;
|
||||
|
||||
fseek (f , cur_pos , SEEK_SET);
|
||||
}
|
||||
|
||||
return filesize;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
202
src/modules/os_interface/network.c
Normal file
202
src/modules/os_interface/network.c
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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 network.c
|
||||
* @brief Basic/generic network functions wrapper.
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define INVALID_SOCKET -1
|
||||
#define SOCKET_ERROR -1
|
||||
#define closesocket(s) close (s)
|
||||
typedef int SOCKET;
|
||||
typedef struct sockaddr_in SOCKADDR_IN;
|
||||
typedef struct sockaddr SOCKADDR;
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#ifdef OSX
|
||||
# include <mach-o/dyld.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include "network.h"
|
||||
#include "os_interface.h"
|
||||
|
||||
void * network_connect(char * address,unsigned short port)
|
||||
{
|
||||
genos_tcp_stat * tcp_stat;
|
||||
#ifdef WIN32
|
||||
int iResult;
|
||||
#endif
|
||||
|
||||
tcp_stat = malloc(sizeof(genos_tcp_stat));
|
||||
if(tcp_stat)
|
||||
{
|
||||
memset(tcp_stat,0,sizeof(genos_tcp_stat));
|
||||
|
||||
#ifdef WIN32
|
||||
iResult = WSAStartup(MAKEWORD(2,2), &tcp_stat->wsaData);
|
||||
if (iResult != NO_ERROR)
|
||||
{
|
||||
free(tcp_stat);
|
||||
return (void*)NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
tcp_stat->m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (tcp_stat->m_socket == INVALID_SOCKET)
|
||||
{
|
||||
#ifdef WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
free(tcp_stat);
|
||||
return (void*)NULL;
|
||||
}
|
||||
|
||||
tcp_stat->clientService.sin_family = AF_INET;
|
||||
tcp_stat->clientService.sin_addr.s_addr = inet_addr(address);
|
||||
tcp_stat->clientService.sin_port = htons(port);
|
||||
|
||||
if (connect(tcp_stat->m_socket, (SOCKADDR*)&tcp_stat->clientService, sizeof(tcp_stat->clientService)) == SOCKET_ERROR)
|
||||
{
|
||||
#ifdef WIN32
|
||||
WSACleanup();
|
||||
#else
|
||||
close(tcp_stat->m_socket);
|
||||
#endif
|
||||
|
||||
free(tcp_stat);
|
||||
return (void*)NULL;
|
||||
}
|
||||
|
||||
return (void*)tcp_stat;
|
||||
}
|
||||
|
||||
return (void*)NULL;
|
||||
}
|
||||
|
||||
int network_read(void * network_connection, unsigned char * buffer, int size,int timeout)
|
||||
{
|
||||
int bytesRecv;
|
||||
int offset;
|
||||
genos_tcp_stat * tcp_stat;
|
||||
|
||||
tcp_stat = (genos_tcp_stat *)network_connection;
|
||||
|
||||
offset=0;
|
||||
|
||||
while(offset < size)
|
||||
{
|
||||
bytesRecv = recv(tcp_stat->m_socket, (char*)&buffer[offset], size - offset, 0);
|
||||
if(bytesRecv == SOCKET_ERROR)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset += bytesRecv;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int network_read2(void * network_connection, unsigned char * buffer, int size,int timeout)
|
||||
{
|
||||
int bytesRecv;
|
||||
int offset;
|
||||
genos_tcp_stat * tcp_stat;
|
||||
|
||||
tcp_stat = (genos_tcp_stat *)network_connection;
|
||||
|
||||
offset=0;
|
||||
|
||||
bytesRecv = recv(tcp_stat->m_socket, (char*)&buffer[offset], size - offset, 0);
|
||||
|
||||
return bytesRecv;
|
||||
}
|
||||
|
||||
int network_write(void * network_connection, unsigned char * buffer, int size,int timeout)
|
||||
{
|
||||
int bytesSent;
|
||||
int offset;
|
||||
genos_tcp_stat * tcp_stat;
|
||||
|
||||
tcp_stat = (genos_tcp_stat *)network_connection;
|
||||
|
||||
offset = 0;
|
||||
while(offset < size)
|
||||
{
|
||||
bytesSent = send(tcp_stat->m_socket, (char*)&buffer[offset], size - offset, 0);
|
||||
if(bytesSent == SOCKET_ERROR)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset += bytesSent;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int network_close(void * network_connection)
|
||||
{
|
||||
genos_tcp_stat * tcp_stat;
|
||||
|
||||
tcp_stat = (genos_tcp_stat *)network_connection;
|
||||
|
||||
closesocket (tcp_stat->m_socket);
|
||||
|
||||
#ifdef WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
free(tcp_stat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
33
src/modules/os_interface/network.h
Normal file
33
src/modules/os_interface/network.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* JTAG Boundary Scanner
|
||||
* Copyright (c) 2008 - 2024 Viveris Technologies
|
||||
*
|
||||
* JTAG Boundary Scanner is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* JTAG Boundary Scanner is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License version 3 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with JTAG Boundary Scanners; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file network.h
|
||||
* @brief Basic/generic network functions wrapper header.
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
typedef struct genos_tcp_stat_
|
||||
{
|
||||
#ifdef WIN32
|
||||
WSADATA wsaData;
|
||||
#endif
|
||||
struct sockaddr_in clientService;
|
||||
SOCKET m_socket;
|
||||
}genos_tcp_stat;
|
||||
514
src/modules/os_interface/os_interface.c
Normal file
514
src/modules/os_interface/os_interface.c
Normal file
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
* 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 os_interface.c
|
||||
* @brief Basic/generic OS functions wrapper.
|
||||
* @author Jean-Fran<61>ois DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "os_interface.h"
|
||||
|
||||
typedef struct _EVENT_HANDLE{
|
||||
pthread_cond_t eCondVar;
|
||||
pthread_mutex_t eMutex;
|
||||
int iVar;
|
||||
} EVENT_HANDLE;
|
||||
|
||||
EVENT_HANDLE * eventtab[256];
|
||||
|
||||
pthread_mutex_t criticalsectiontab[256];
|
||||
|
||||
#if 0
|
||||
void * ThreadProc( void *lpParameter)
|
||||
{
|
||||
threadinit *threadinitptr;
|
||||
THREADFUNCTION thread;
|
||||
jtag_core* jtag_ctx;
|
||||
void * hw_context;
|
||||
|
||||
threadinitptr=(threadinit*)lpParameter;
|
||||
if( threadinitptr )
|
||||
{
|
||||
|
||||
thread=threadinitptr->thread;
|
||||
jtag_ctx = threadinitptr->jtag_ctx;
|
||||
hw_context=threadinitptr->hwcontext;
|
||||
thread(jtag_ctx,hw_context);
|
||||
|
||||
free(threadinitptr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int genos_setevent(unsigned char id)
|
||||
{
|
||||
pthread_mutex_lock(&eventtab[id]->eMutex);
|
||||
pthread_cond_signal(&eventtab[id]->eCondVar);
|
||||
pthread_mutex_unlock(&eventtab[id]->eMutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uintptr_t genos_createevent(unsigned char id)
|
||||
{
|
||||
eventtab[id]=(EVENT_HANDLE*)malloc(sizeof(EVENT_HANDLE));
|
||||
pthread_mutex_init(&eventtab[id]->eMutex, NULL);
|
||||
pthread_cond_init(&eventtab[id]->eCondVar, NULL);
|
||||
return (uintptr_t)eventtab[id];
|
||||
}
|
||||
|
||||
int genos_waitevent(int id,int timeout)
|
||||
{
|
||||
struct timeval now;
|
||||
struct timespec timeoutstr;
|
||||
int retcode;
|
||||
|
||||
pthread_mutex_lock(&eventtab[id]->eMutex);
|
||||
gettimeofday(&now,0);
|
||||
timeoutstr.tv_sec = now.tv_sec + (timeout/1000);
|
||||
timeoutstr.tv_nsec = (now.tv_usec * 1000) ;//+(timeout*1000000);
|
||||
retcode = 0;
|
||||
|
||||
retcode = pthread_cond_timedwait(&eventtab[id]->eCondVar, &eventtab[id]->eMutex, &timeoutstr);
|
||||
if (retcode == ETIMEDOUT)
|
||||
{
|
||||
pthread_mutex_unlock(&eventtab[id]->eMutex);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_mutex_unlock(&eventtab[id]->eMutex);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t genos_createcriticalsection(unsigned char id)
|
||||
{
|
||||
//create mutex attribute variable
|
||||
pthread_mutexattr_t mAttr;
|
||||
|
||||
pthread_mutexattr_init(&mAttr);
|
||||
|
||||
#if defined(__APPLE__)
|
||||
// setup recursive mutex for mutex attribute
|
||||
pthread_mutexattr_settype(&mAttr, PTHREAD_MUTEX_RECURSIVE);
|
||||
#else
|
||||
pthread_mutexattr_settype(&mAttr, PTHREAD_MUTEX_RECURSIVE_NP);
|
||||
#endif
|
||||
// Use the mutex attribute to create the mutex
|
||||
pthread_mutex_init(&criticalsectiontab[id], &mAttr);
|
||||
|
||||
// Mutex attribute can be destroy after initializing the mutex variable
|
||||
pthread_mutexattr_destroy(&mAttr);
|
||||
|
||||
return (uintptr_t)&criticalsectiontab[id];
|
||||
}
|
||||
|
||||
|
||||
void genos_entercriticalsection(unsigned char id)
|
||||
{
|
||||
#ifdef WIN32
|
||||
EnterCriticalSection( &criticalsectiontab[id] );
|
||||
#else
|
||||
pthread_mutex_lock( &criticalsectiontab[id] );
|
||||
#endif
|
||||
}
|
||||
|
||||
void genos_leavecriticalsection(unsigned char id)
|
||||
{
|
||||
#ifdef WIN32
|
||||
LeaveCriticalSection( &criticalsectiontab[id] );
|
||||
#else
|
||||
pthread_mutex_unlock( &criticalsectiontab[id] );
|
||||
#endif
|
||||
}
|
||||
|
||||
void genos_destroycriticalsection(unsigned char id)
|
||||
{
|
||||
#ifdef WIN32
|
||||
DeleteCriticalSection(&criticalsectiontab[id]);
|
||||
#else
|
||||
pthread_mutex_destroy (&criticalsectiontab[id]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void genos_msleep (unsigned int ms) {
|
||||
int microsecs;
|
||||
struct timeval tv;
|
||||
microsecs = ms * 1000;
|
||||
tv.tv_sec = microsecs / 1000000;
|
||||
tv.tv_usec = microsecs % 1000000;
|
||||
select (0, NULL, NULL, NULL, &tv);
|
||||
}
|
||||
|
||||
void genos_pause(int ms)
|
||||
{
|
||||
genos_msleep(ms);
|
||||
}
|
||||
|
||||
#if 0
|
||||
int genos_createthread(void* hwcontext,THREADFUNCTION thread,int priority)
|
||||
{
|
||||
unsigned long sit;
|
||||
int ret;
|
||||
pthread_t threadid;
|
||||
pthread_attr_t threadattrib;
|
||||
threadinit *threadinitptr;
|
||||
struct sched_param param;
|
||||
JTAGCORE_PRINT_FUNC print_callback;
|
||||
|
||||
sit = 0;
|
||||
|
||||
pthread_attr_init(&threadattrib);
|
||||
|
||||
pthread_attr_setinheritsched(&threadattrib, PTHREAD_EXPLICIT_SCHED);
|
||||
|
||||
if(priority)
|
||||
{
|
||||
pthread_attr_setschedpolicy(&threadattrib,SCHED_FIFO);
|
||||
param.sched_priority = sched_get_priority_max(SCHED_FIFO);
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_attr_setschedpolicy(&threadattrib,SCHED_OTHER);
|
||||
param.sched_priority = sched_get_priority_max(SCHED_OTHER);
|
||||
}
|
||||
/* set the new scheduling param */
|
||||
pthread_attr_setschedparam (&threadattrib, ¶m);
|
||||
|
||||
print_callback = jtag_ctx->jtagcore_print_callback;
|
||||
|
||||
threadinitptr = (threadinit *)malloc(sizeof(threadinit));
|
||||
if( threadinitptr )
|
||||
{
|
||||
threadinitptr->thread = thread;
|
||||
threadinitptr->jtag_ctx = jtag_ctx;
|
||||
//threadinitptr->hwcontext=hwcontext;
|
||||
|
||||
ret = pthread_create(&threadid, &threadattrib,ThreadProc, threadinitptr);
|
||||
if(ret)
|
||||
{
|
||||
print_callback(jtag_ctx,"genos_createthread : pthread_create failed !");
|
||||
free( threadinitptr );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print_callback(jtag_ctx,"genos_createthread : memory allocation failed !");
|
||||
}
|
||||
|
||||
return sit;
|
||||
}
|
||||
#endif
|
||||
|
||||
char * genos_strupper(char * str)
|
||||
{
|
||||
int i;
|
||||
|
||||
i=0;
|
||||
while(str[i])
|
||||
{
|
||||
|
||||
if(str[i]>='a' && str[i]<='z')
|
||||
{
|
||||
str[i]=str[i]+('A'-'a');
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
char * genos_strlower(char * str)
|
||||
{
|
||||
int i;
|
||||
|
||||
i=0;
|
||||
while(str[i])
|
||||
{
|
||||
|
||||
if(str[i]>='A' && str[i]<='Z')
|
||||
{
|
||||
str[i]=str[i]+('a'-'A');
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
char * genos_getfilenamebase(char * fullpath,char * filenamebase, int type)
|
||||
{
|
||||
int len,i;
|
||||
char separator;
|
||||
|
||||
if(fullpath)
|
||||
{
|
||||
len=strlen(fullpath);
|
||||
|
||||
separator = DIR_SEPARATOR_CHAR; // system type by default
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case SYS_PATH_TYPE: // System based
|
||||
separator = DIR_SEPARATOR_CHAR;
|
||||
break;
|
||||
|
||||
case UNIX_PATH_TYPE: // Unix style
|
||||
separator = '/';
|
||||
break;
|
||||
|
||||
case WINDOWS_PATH_TYPE: // Windows style
|
||||
separator = '\\';
|
||||
break;
|
||||
}
|
||||
|
||||
i=0;
|
||||
if(len)
|
||||
{
|
||||
i=len-1;
|
||||
while(i && ( fullpath[i] != separator && fullpath[i]!=':') )
|
||||
{
|
||||
i--;
|
||||
}
|
||||
|
||||
if( fullpath[i] == separator || fullpath[i]==':' )
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
if(i>len)
|
||||
{
|
||||
i=len;
|
||||
}
|
||||
}
|
||||
|
||||
if(filenamebase)
|
||||
{
|
||||
strcpy(filenamebase,&fullpath[i]);
|
||||
}
|
||||
|
||||
return &fullpath[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char * genos_getfilenameext(char * fullpath,char * filenameext, int type )
|
||||
{
|
||||
char * filename;
|
||||
int len,i;
|
||||
|
||||
filename = genos_getfilenamebase(fullpath,0,type);
|
||||
|
||||
if(filename)
|
||||
{
|
||||
len=strlen(filename);
|
||||
|
||||
i=0;
|
||||
if(len)
|
||||
{
|
||||
i=len-1;
|
||||
|
||||
while(i && ( filename[i] != '.' ) )
|
||||
{
|
||||
i--;
|
||||
}
|
||||
|
||||
if( filename[i] == '.' )
|
||||
{
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
i=len;
|
||||
}
|
||||
|
||||
if(i>len)
|
||||
{
|
||||
i=len;
|
||||
}
|
||||
}
|
||||
|
||||
if(filenameext)
|
||||
{
|
||||
strcpy(filenameext,&filename[i]);
|
||||
}
|
||||
|
||||
return &filename[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int genos_getfilenamewext(char * fullpath,char * filenamewext, int type)
|
||||
{
|
||||
char * filename;
|
||||
char * ext;
|
||||
int len;
|
||||
|
||||
len = 0;
|
||||
if(fullpath)
|
||||
{
|
||||
filename = genos_getfilenamebase(fullpath,0,type);
|
||||
ext = genos_getfilenameext(fullpath,0,type);
|
||||
|
||||
len = ext-filename;
|
||||
|
||||
if(len && filename[len-1]=='.')
|
||||
{
|
||||
len--;
|
||||
}
|
||||
|
||||
if(filenamewext)
|
||||
{
|
||||
memcpy(filenamewext,filename,len);
|
||||
filenamewext[len]=0;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int genos_getpathfolder(char * fullpath,char * folder,int type)
|
||||
{
|
||||
int len;
|
||||
char * filenameptr;
|
||||
|
||||
len = 0;
|
||||
if(fullpath)
|
||||
{
|
||||
filenameptr = genos_getfilenamebase(fullpath,0,type);
|
||||
|
||||
len = filenameptr-fullpath;
|
||||
|
||||
if(folder)
|
||||
{
|
||||
memcpy(folder,fullpath,len);
|
||||
folder[len]=0;
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int genos_checkfileext(char * path,char *ext,int type)
|
||||
{
|
||||
char pathext[16];
|
||||
char srcext[16];
|
||||
char * ptr;
|
||||
|
||||
if(path && ext)
|
||||
{
|
||||
pathext[0] = '\0';
|
||||
srcext[0] = ' ';
|
||||
srcext[1] = '\0';
|
||||
|
||||
ptr = genos_getfilenameext(path,0,type);
|
||||
if(!ptr)
|
||||
return 0;
|
||||
|
||||
if( ( strlen(ptr) < 16 ) && ( strlen(ext) < 16 ))
|
||||
{
|
||||
genos_getfilenameext(path,(char*)&pathext,type);
|
||||
genos_strlower(pathext);
|
||||
|
||||
strcpy((char*)srcext,ext);
|
||||
genos_strlower(srcext);
|
||||
|
||||
if(!strcmp(pathext,srcext))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int genos_getfilesize(char * path)
|
||||
{
|
||||
int filesize;
|
||||
FILE * f;
|
||||
|
||||
filesize=-1;
|
||||
|
||||
if(path)
|
||||
{
|
||||
f=genos_fopen(path,"rb");
|
||||
if(f)
|
||||
{
|
||||
fseek (f , 0 , SEEK_END);
|
||||
filesize=ftell(f);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
return filesize;
|
||||
}
|
||||
|
||||
char * genos_strndstcat( char *dest, const char *src, size_t maxdestsize )
|
||||
{
|
||||
int i,j;
|
||||
|
||||
i = 0;
|
||||
while( ( i < maxdestsize ) && dest[i] )
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
if( !dest[i] )
|
||||
{
|
||||
j = 0;
|
||||
while( ( i < maxdestsize ) && src[j] )
|
||||
{
|
||||
dest[i] = src[j];
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
if( i < maxdestsize )
|
||||
{
|
||||
dest[i] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
122
src/modules/os_interface/os_interface.h
Normal file
122
src/modules/os_interface/os_interface.h
Normal file
@@ -0,0 +1,122 @@
|
||||
#ifndef _OS_INTERFACE_H
|
||||
#define _OS_INTERFACE_H
|
||||
/*
|
||||
* JTAG Boundary Scanner
|
||||
* Copyright (c) 2008 - 2024 Viveris Technologies
|
||||
*
|
||||
* JTAG Boundary Scanner is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* JTAG Boundary Scanner is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License version 3 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with JTAG Boundary Scanners; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file os_interface.h
|
||||
* @brief Basic/generic OS functions wrapper header.
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DIR_SEPARATOR "/"
|
||||
#define DIR_SEPARATOR_CHAR '/'
|
||||
#define FILEFOUND_NAMESIZE 256
|
||||
|
||||
/////////////// Thread functions ////////////////
|
||||
|
||||
#if 0
|
||||
typedef int (*THREADFUNCTION) (void* jtag_ctx,void* hw_ctx);
|
||||
|
||||
typedef struct threadinit_
|
||||
{
|
||||
THREADFUNCTION thread;
|
||||
jtag_core * jtag_ctx;
|
||||
void * hwcontext;
|
||||
}threadinit;
|
||||
#endif
|
||||
|
||||
typedef struct filefoundinfo_
|
||||
{
|
||||
int isdirectory;
|
||||
char filename[FILEFOUND_NAMESIZE];
|
||||
int size;
|
||||
}filefoundinfo;
|
||||
|
||||
int genos_setevent(unsigned char id );
|
||||
uintptr_t genos_createevent(unsigned char id );
|
||||
int genos_waitevent(int id, int timeout );
|
||||
void genos_pause( int ms );
|
||||
#if 0
|
||||
int genos_createthread(void* hwcontext, THREADFUNCTION thread, int priority );
|
||||
#endif
|
||||
|
||||
uintptr_t genos_createcriticalsection(unsigned char id );
|
||||
void genos_entercriticalsection(unsigned char id );
|
||||
void genos_leavecriticalsection(unsigned char id );
|
||||
void genos_destroycriticalsection(unsigned char id );
|
||||
|
||||
/////////////// String functions ///////////////
|
||||
|
||||
char * genos_strupper( char * str );
|
||||
char * genos_strlower( char * str );
|
||||
char * genos_strndstcat( char *dest, const char *src, size_t maxdestsize );
|
||||
|
||||
/////////////// File functions ////////////////
|
||||
|
||||
int genos_open ( const char *filename, int flags, ... );
|
||||
|
||||
FILE *genos_fopen ( const char *filename, const char *mode );
|
||||
int genos_fread( void * ptr, size_t size, FILE *f );
|
||||
char * genos_fgets( char * str, int num, FILE *f );
|
||||
int genos_fclose( FILE * f );
|
||||
int genos_fgetsize( FILE * f );
|
||||
#ifndef stat
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
int genos_stat( const char *filename, struct stat *buf );
|
||||
|
||||
void* genos_find_first_file( char *folder, char *file, filefoundinfo* fileinfo );
|
||||
int genos_find_next_file( void* handleff, char *folder, char *file, filefoundinfo* fileinfo );
|
||||
int genos_find_close( void* handle );
|
||||
|
||||
int genos_mkdir( char * folder );
|
||||
|
||||
char * genos_getcurrentdirectory( char *currentdirectory, int buffersize );
|
||||
|
||||
enum
|
||||
{
|
||||
SYS_PATH_TYPE = 0,
|
||||
UNIX_PATH_TYPE,
|
||||
WINDOWS_PATH_TYPE,
|
||||
};
|
||||
|
||||
char * genos_getfilenamebase( char * fullpath, char * filenamebase, int type );
|
||||
char * genos_getfilenameext( char * fullpath, char * filenameext, int type );
|
||||
int genos_getfilenamewext( char * fullpath, char * filenamewext, int type );
|
||||
int genos_getpathfolder( char * fullpath, char * folder, int type );
|
||||
int genos_checkfileext( char * path, char *ext, int type );
|
||||
int genos_getfilesize( char * path );
|
||||
|
||||
/////////////// Network functions ////////////////
|
||||
|
||||
void * network_connect(char * address,unsigned short port);
|
||||
int network_read(void * network_connection, unsigned char * buffer, int size,int timeout);
|
||||
int network_read2(void * network_connection, unsigned char * buffer, int size,int timeout);
|
||||
int network_write(void * network_connection, unsigned char * buffer, int size,int timeout);
|
||||
int network_close(void * network_connection);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
12
src/modules/probes/CMakeLists.txt
Normal file
12
src/modules/probes/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
file(GLOB_RECURSE ALL_SOURCES "*.c")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
|
||||
add_library(probes ${ALL_SOURCES})
|
||||
|
||||
# probes.yaml is parsed at runtime via libyaml (same as the fpga module).
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(YAML REQUIRED IMPORTED_TARGET yaml-0.1)
|
||||
target_link_libraries(probes PUBLIC PkgConfig::YAML)
|
||||
213
src/modules/probes/probes.c
Normal file
213
src/modules/probes/probes.c
Normal file
@@ -0,0 +1,213 @@
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <yaml.h>
|
||||
|
||||
#include "probes.h"
|
||||
|
||||
/*
|
||||
* probes.yaml parser. Structure:
|
||||
*
|
||||
* defaults:
|
||||
* VAR: value
|
||||
* ...
|
||||
* profiles:
|
||||
* name:
|
||||
* VAR: value
|
||||
* other: {}
|
||||
*
|
||||
* Parsed once and cached. See probes.h for semantics.
|
||||
*/
|
||||
|
||||
#define DEFAULT_PROBES_FILE "data/probes.yaml"
|
||||
|
||||
typedef struct { char *key; char *val; } kv;
|
||||
typedef struct { char *name; kv *vars; int nvars; } profile;
|
||||
|
||||
static kv *g_def = NULL; static int g_ndef = 0;
|
||||
static profile *g_prof = NULL; static int g_nprof = 0;
|
||||
static int g_loaded = 0;
|
||||
static char g_source[1024] = "";
|
||||
|
||||
static char *xstrdup(const char *s)
|
||||
{
|
||||
char *p;
|
||||
size_t n;
|
||||
if (!s) return NULL;
|
||||
n = strlen(s) + 1;
|
||||
p = (char *)malloc(n);
|
||||
if (p) memcpy(p, s, n);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void add_kv(kv **arr, int *n, const char *k, const char *v)
|
||||
{
|
||||
kv *t = (kv *)realloc(*arr, (*n + 1) * sizeof(kv));
|
||||
if (!t) { fprintf(stderr, "probes: out of memory\n"); return; }
|
||||
*arr = t;
|
||||
t[*n].key = xstrdup(k);
|
||||
t[*n].val = xstrdup(v);
|
||||
(*n)++;
|
||||
}
|
||||
|
||||
static profile *add_profile(const char *name)
|
||||
{
|
||||
profile *t = (profile *)realloc(g_prof, (g_nprof + 1) * sizeof(profile));
|
||||
if (!t) { fprintf(stderr, "probes: out of memory\n"); return NULL; }
|
||||
g_prof = t;
|
||||
g_prof[g_nprof].name = xstrdup(name);
|
||||
g_prof[g_nprof].vars = NULL;
|
||||
g_prof[g_nprof].nvars = 0;
|
||||
return &g_prof[g_nprof++];
|
||||
}
|
||||
|
||||
/* Mapping context at each nesting depth. */
|
||||
enum { C_NONE = 0, C_ROOT, C_DEFAULTS, C_PROFILES, C_PROFBODY };
|
||||
|
||||
#define MAX_DEPTH 16
|
||||
|
||||
static int load(const char *path)
|
||||
{
|
||||
FILE *f;
|
||||
yaml_parser_t parser;
|
||||
yaml_event_t ev;
|
||||
int depth = 0, done = 0, rc = 0;
|
||||
int ctx[MAX_DEPTH];
|
||||
char *key[MAX_DEPTH];
|
||||
profile *cur = NULL;
|
||||
int i;
|
||||
|
||||
f = fopen(path, "rb");
|
||||
if (!f) return -1;
|
||||
if (!yaml_parser_initialize(&parser)) { fclose(f); return -1; }
|
||||
yaml_parser_set_input_file(&parser, f);
|
||||
|
||||
memset(ctx, 0, sizeof(ctx));
|
||||
memset(key, 0, sizeof(key));
|
||||
|
||||
while (!done) {
|
||||
if (!yaml_parser_parse(&parser, &ev)) {
|
||||
fprintf(stderr, "probes: YAML parse error in %s: %s (line %lu)\n",
|
||||
path, parser.problem ? parser.problem : "?",
|
||||
(unsigned long)parser.problem_mark.line + 1);
|
||||
rc = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ev.type) {
|
||||
case YAML_MAPPING_START_EVENT: {
|
||||
int newc = C_NONE;
|
||||
if (depth == 0) {
|
||||
newc = C_ROOT;
|
||||
} else {
|
||||
int c = ctx[depth];
|
||||
const char *k = key[depth];
|
||||
if (c == C_ROOT) {
|
||||
if (k && !strcmp(k, "defaults")) newc = C_DEFAULTS;
|
||||
else if (k && !strcmp(k, "profiles")) newc = C_PROFILES;
|
||||
} else if (c == C_PROFILES) {
|
||||
cur = k ? add_profile(k) : NULL;
|
||||
newc = C_PROFBODY;
|
||||
}
|
||||
}
|
||||
if (depth < MAX_DEPTH - 1) depth++;
|
||||
ctx[depth] = newc;
|
||||
free(key[depth]);
|
||||
key[depth] = NULL;
|
||||
break;
|
||||
}
|
||||
case YAML_MAPPING_END_EVENT:
|
||||
free(key[depth]);
|
||||
key[depth] = NULL;
|
||||
if (depth > 0) depth--;
|
||||
break;
|
||||
case YAML_SCALAR_EVENT: {
|
||||
const char *v = (const char *)ev.data.scalar.value;
|
||||
int c = ctx[depth];
|
||||
if (c == C_DEFAULTS) {
|
||||
if (!key[depth]) { key[depth] = xstrdup(v); }
|
||||
else { add_kv(&g_def, &g_ndef, key[depth], v); free(key[depth]); key[depth] = NULL; }
|
||||
} else if (c == C_PROFBODY) {
|
||||
if (!key[depth]) { key[depth] = xstrdup(v); }
|
||||
else { if (cur) add_kv(&cur->vars, &cur->nvars, key[depth], v); free(key[depth]); key[depth] = NULL; }
|
||||
} else {
|
||||
/* C_ROOT / C_PROFILES: the scalar is a key/name whose
|
||||
* value is the next mapping. */
|
||||
free(key[depth]);
|
||||
key[depth] = xstrdup(v);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case YAML_STREAM_END_EVENT:
|
||||
done = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
yaml_event_delete(&ev);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_DEPTH; i++) free(key[i]);
|
||||
yaml_parser_delete(&parser);
|
||||
fclose(f);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void ensure_loaded(void)
|
||||
{
|
||||
const char *path;
|
||||
|
||||
if (g_loaded) return;
|
||||
g_loaded = 1;
|
||||
|
||||
path = getenv("BS_PROBES");
|
||||
if (!path || !*path) path = DEFAULT_PROBES_FILE;
|
||||
|
||||
if (load(path) == 0 && (g_ndef > 0 || g_nprof > 0)) {
|
||||
strncpy(g_source, path, sizeof(g_source) - 1);
|
||||
g_source[sizeof(g_source) - 1] = '\0';
|
||||
}
|
||||
/* Silent when absent: probe profiles are optional. */
|
||||
}
|
||||
|
||||
int probe_apply_defaults(probe_set_fn set, void *user)
|
||||
{
|
||||
int i;
|
||||
ensure_loaded();
|
||||
for (i = 0; i < g_ndef; i++) set(user, g_def[i].key, g_def[i].val);
|
||||
return g_ndef;
|
||||
}
|
||||
|
||||
int probe_apply_profile(const char *name, probe_set_fn set, void *user)
|
||||
{
|
||||
int i, j;
|
||||
ensure_loaded();
|
||||
for (i = 0; i < g_nprof; i++) {
|
||||
if (!strcmp(g_prof[i].name, name)) {
|
||||
for (j = 0; j < g_prof[i].nvars; j++)
|
||||
set(user, g_prof[i].vars[j].key, g_prof[i].vars[j].val);
|
||||
return g_prof[i].nvars;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int probe_profile_count(void)
|
||||
{
|
||||
ensure_loaded();
|
||||
return g_nprof;
|
||||
}
|
||||
|
||||
const char *probe_profile_name(int index)
|
||||
{
|
||||
ensure_loaded();
|
||||
return (index >= 0 && index < g_nprof) ? g_prof[index].name : NULL;
|
||||
}
|
||||
|
||||
const char *probe_config_source(void)
|
||||
{
|
||||
ensure_loaded();
|
||||
return g_source[0] ? g_source : NULL;
|
||||
}
|
||||
40
src/modules/probes/probes.h
Normal file
40
src/modules/probes/probes.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef _PROBES_H
|
||||
#define _PROBES_H
|
||||
|
||||
/*
|
||||
* Probe configuration profiles, loaded at runtime from probes.yaml.
|
||||
*
|
||||
* The built-in config.script (and an optional CWD config.script) set the
|
||||
* baseline probe variables. probes.yaml layers on top of that:
|
||||
* - a `defaults:` map applied on every jtag_open (so opening without a
|
||||
* profile restores a known baseline), then
|
||||
* - a named `profiles:` map whose vars override the defaults for one
|
||||
* probe (e.g. an embedded FlashPro that needs ADBUS4 high-Z).
|
||||
*
|
||||
* Each key/value is pushed into the script envvar store via the caller's
|
||||
* callback — the same vars config.script sets and the driver reads at
|
||||
* open time (jtagcore_getEnvVarValue). This keeps the parser decoupled
|
||||
* from the script context.
|
||||
*
|
||||
* File lookup: $BS_PROBES, else "probes.yaml" relative to the current
|
||||
* directory (same convention as fpga_registry.yaml). Absence is silent —
|
||||
* profiles are optional.
|
||||
*/
|
||||
|
||||
/* Callback used to set one envvar. `user` is opaque to this module. */
|
||||
typedef void (*probe_set_fn)(void *user, const char *key, const char *value);
|
||||
|
||||
/* Apply the defaults: map. Returns the number of vars applied (0 if none
|
||||
* or no file). */
|
||||
int probe_apply_defaults(probe_set_fn set, void *user);
|
||||
|
||||
/* Apply the named profile's vars on top of the defaults. Returns the
|
||||
* number of vars applied, or -1 if no such profile exists. */
|
||||
int probe_apply_profile(const char *name, probe_set_fn set, void *user);
|
||||
|
||||
/* Listing / diagnostics. */
|
||||
int probe_profile_count(void);
|
||||
const char *probe_profile_name(int index);
|
||||
const char *probe_config_source(void); /* path loaded, or NULL */
|
||||
|
||||
#endif
|
||||
8
src/modules/script/CMakeLists.txt
Normal file
8
src/modules/script/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
file(GLOB_RECURSE ALL_SOURCES "*.c")
|
||||
|
||||
include_directories(${DIR_MODULES})
|
||||
include_directories(${DIR_LIBS})
|
||||
|
||||
add_library(script ${ALL_SOURCES})
|
||||
591
src/modules/script/env.c
Normal file
591
src/modules/script/env.c
Normal file
@@ -0,0 +1,591 @@
|
||||
/*
|
||||
* JTAG Boundary Scanner
|
||||
* Copyright (c) 2008 - 2024 Viveris Technologies
|
||||
*
|
||||
* JTAG Boundary Scanner is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* JTAG Boundary Scanner is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License version 3 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with JTAG Boundary Scanners; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file env.c
|
||||
* @brief Internal variables support.
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "config/bs_defines.h"
|
||||
#include "env.h"
|
||||
|
||||
/*
|
||||
|L|H|str varname\0|L|H|str vardata\0|L|H|str varname\0|L|H|str vardata\0|0|0|
|
||||
|
||||
(H*256)+L = str size (\0 included)
|
||||
if L & H == 0 -> end of buffer
|
||||
*/
|
||||
|
||||
static int stringcopy(char * dst, char * src, unsigned int maxsize)
|
||||
{
|
||||
int s;
|
||||
|
||||
if( !dst || (maxsize <= 0))
|
||||
return 0;
|
||||
|
||||
if( !src )
|
||||
{
|
||||
*dst = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
s = 0;
|
||||
while( *src && s < (maxsize - 1))
|
||||
{
|
||||
*dst++ = *src++;
|
||||
s++;
|
||||
}
|
||||
|
||||
*dst = '\0';
|
||||
s++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
static uint16_t getEnvStrSize(unsigned char * buf)
|
||||
{
|
||||
uint16_t size;
|
||||
|
||||
size = *buf++;
|
||||
size += (((uint16_t)*buf)<<8);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static void setEnvStrSize(unsigned char * buf, uint16_t size)
|
||||
{
|
||||
*buf++ = size & 0xFF;
|
||||
*buf = (size >> 8) & 0xFF;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int getEnvEmptyOffset(envvar_entry * env)
|
||||
{
|
||||
int off;
|
||||
unsigned short varname_size, vardata_size;
|
||||
|
||||
off = 0;
|
||||
|
||||
varname_size = getEnvStrSize(&env->buf[off]); // var name string size
|
||||
vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size
|
||||
|
||||
while( varname_size )
|
||||
{
|
||||
off += (2 + varname_size + 2 + vardata_size);
|
||||
|
||||
varname_size = getEnvStrSize(&env->buf[off]); // var name string size
|
||||
vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size
|
||||
}
|
||||
|
||||
return off;
|
||||
}
|
||||
|
||||
static int getEnvBufOff(envvar_entry * env, char * varname)
|
||||
{
|
||||
unsigned short curstr_size;
|
||||
int str_index,i;
|
||||
|
||||
i = 0;
|
||||
|
||||
str_index = 0;
|
||||
curstr_size = getEnvStrSize(&env->buf[i]);
|
||||
i += 2;
|
||||
|
||||
while( curstr_size )
|
||||
{
|
||||
if( !(str_index & 1) ) // variable name ?
|
||||
{
|
||||
if( !strcmp((char*)&env->buf[i],varname ) )
|
||||
{
|
||||
// this is the variable we are looking for.
|
||||
return (i - 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// not the right variable - skip this string.
|
||||
i += curstr_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//variable data - skip this string.
|
||||
i += curstr_size;
|
||||
}
|
||||
|
||||
if( i < env->bufsize - 2 )
|
||||
{
|
||||
curstr_size = getEnvStrSize(&env->buf[i]);
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
curstr_size = 0;
|
||||
}
|
||||
|
||||
str_index++;
|
||||
}
|
||||
|
||||
return -1; // Not found.
|
||||
}
|
||||
|
||||
static int pushStr(envvar_entry * env, int offset, char * str)
|
||||
{
|
||||
int size;
|
||||
|
||||
if(!str || offset < 0)
|
||||
return -1;
|
||||
|
||||
size = strlen(str) + 1;
|
||||
if(size > 0xFFFF)
|
||||
return -1;
|
||||
|
||||
if( ( offset + 2 + size ) < env->bufsize )
|
||||
{
|
||||
setEnvStrSize(&env->buf[offset], size);
|
||||
offset += 2;
|
||||
stringcopy((char*)&env->buf[offset], str, size);
|
||||
offset += size;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef STATIC_ENV_BUFFER
|
||||
static envvar_entry * realloc_env_buffer(envvar_entry * env, unsigned int size)
|
||||
{
|
||||
unsigned int tmp_bufsize;
|
||||
unsigned char * tmpbuf;
|
||||
|
||||
if( !env )
|
||||
{
|
||||
env = malloc( sizeof(envvar_entry) );
|
||||
if(!env)
|
||||
return NULL;
|
||||
|
||||
memset( env,0,sizeof(envvar_entry));
|
||||
}
|
||||
|
||||
tmp_bufsize = size;
|
||||
|
||||
if( tmp_bufsize & (ENV_PAGE_SIZE - 1) )
|
||||
{
|
||||
tmp_bufsize = (tmp_bufsize & (~(ENV_PAGE_SIZE - 1))) + ENV_PAGE_SIZE;
|
||||
}
|
||||
|
||||
if( tmp_bufsize > ENV_MAX_TOTAL_BUFFER_SIZE )
|
||||
{
|
||||
return env;
|
||||
}
|
||||
|
||||
if( env->bufsize != tmp_bufsize )
|
||||
{
|
||||
tmpbuf = realloc(env->buf, tmp_bufsize);
|
||||
if(tmpbuf)
|
||||
{
|
||||
if( env->bufsize < tmp_bufsize )
|
||||
memset(&tmpbuf[env->bufsize], 0, tmp_bufsize - env->bufsize );
|
||||
|
||||
env->bufsize = tmp_bufsize;
|
||||
env->buf = tmpbuf;
|
||||
}
|
||||
}
|
||||
|
||||
return env;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int pushEnvEntry(envvar_entry * env, char * varname, char * vardata)
|
||||
{
|
||||
unsigned int total_size;
|
||||
int varname_len,vardata_len;
|
||||
int offset;
|
||||
|
||||
if(!varname || !vardata)
|
||||
return -1;
|
||||
|
||||
varname_len = strlen(varname) + 1;
|
||||
vardata_len = strlen(vardata) + 1;
|
||||
|
||||
if( varname_len > ENV_MAX_STRING_SIZE || vardata_len > ENV_MAX_STRING_SIZE)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
total_size = 2 + varname_len + 2 + vardata_len;
|
||||
|
||||
offset = getEnvEmptyOffset(env);
|
||||
if( offset < 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef STATIC_ENV_BUFFER
|
||||
realloc_env_buffer(env, offset + total_size + 4);
|
||||
#endif
|
||||
|
||||
if( (total_size + offset) < env->bufsize )
|
||||
{
|
||||
offset = pushStr(env, offset, varname);
|
||||
offset = pushStr(env, offset, vardata);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int setEnvVarDat( envvar_entry * env, char * varname, char * vardata )
|
||||
{
|
||||
int i,off,ret;
|
||||
unsigned short varname_size, vardata_size;
|
||||
int varname_len, vardata_len;
|
||||
int oldentrysize;
|
||||
|
||||
ret = 0;
|
||||
|
||||
if(!env)
|
||||
return -1;
|
||||
|
||||
i = 0;
|
||||
|
||||
varname_len = 0;
|
||||
vardata_len = 0;
|
||||
|
||||
if( !varname )
|
||||
return -1;
|
||||
|
||||
varname_len = strlen(varname);
|
||||
|
||||
if( vardata )
|
||||
vardata_len = strlen(vardata);
|
||||
|
||||
if( varname_len > ENV_MAX_STRING_SIZE || vardata_len > ENV_MAX_STRING_SIZE)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
off = getEnvBufOff( env, varname );
|
||||
if( off >= 0 )
|
||||
{
|
||||
varname_size = getEnvStrSize(&env->buf[off]); // var name string size
|
||||
vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size
|
||||
|
||||
oldentrysize = 2 + varname_size + 2 + vardata_size;
|
||||
|
||||
if(vardata)
|
||||
{
|
||||
vardata_len = strlen(vardata);
|
||||
if( vardata_len + 1 > 0xFFFF )
|
||||
return -1;
|
||||
|
||||
if( vardata_len + 1 > vardata_size )
|
||||
{
|
||||
// add new entry, and pack the strings
|
||||
ret = pushEnvEntry(env, varname, vardata);
|
||||
if( ret > 0 )
|
||||
{
|
||||
unsigned char byte;
|
||||
for(i=0;i<env->bufsize - (off + oldentrysize);i++)
|
||||
{
|
||||
byte = env->buf[off + i + oldentrysize];
|
||||
env->buf[off + i + oldentrysize] = '\0';
|
||||
env->buf[off + i] = byte;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size
|
||||
if(vardata_size)
|
||||
{
|
||||
memset((char*)&env->buf[off + 2 + varname_size + 2], 0, vardata_size );
|
||||
stringcopy( (char*)&env->buf[off + 2 + varname_size + 2], vardata, vardata_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// unset variable
|
||||
unsigned char byte;
|
||||
for(i=0;i<env->bufsize - (off + oldentrysize);i++)
|
||||
{
|
||||
byte = env->buf[off + i + oldentrysize];
|
||||
env->buf[off + i + oldentrysize] = '\0';
|
||||
env->buf[off + i] = byte;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(vardata)
|
||||
{
|
||||
// New variable
|
||||
ret = pushEnvEntry(env, varname, vardata);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
char * getEnvVarDat( envvar_entry * env, char * varname, char * vardata, int maxsize)
|
||||
{
|
||||
int off;
|
||||
unsigned short varname_size, vardata_size;
|
||||
|
||||
envvar_entry * tmp_envvars;
|
||||
|
||||
tmp_envvars = (envvar_entry *)env;
|
||||
if(!tmp_envvars)
|
||||
return NULL;
|
||||
|
||||
off = getEnvBufOff( env, varname );
|
||||
if( off >= 0 )
|
||||
{
|
||||
varname_size = getEnvStrSize(&env->buf[off]); // var name string size
|
||||
vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size
|
||||
|
||||
if( varname_size>0 && vardata_size>0)
|
||||
{
|
||||
if(vardata)
|
||||
{
|
||||
stringcopy(vardata, (char*)&env->buf[off + 2 + varname_size + 2], maxsize);
|
||||
}
|
||||
|
||||
return (char*)&env->buf[off + 2 + varname_size + 2];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
env_var_value getEnvVarValue( envvar_entry * env, char * varname)
|
||||
{
|
||||
env_var_value value;
|
||||
char * str_return;
|
||||
|
||||
value = 0;
|
||||
|
||||
if(!varname)
|
||||
return 0;
|
||||
|
||||
str_return = getEnvVarDat( env, varname, NULL, 0);
|
||||
|
||||
if(str_return)
|
||||
{
|
||||
if( strlen(str_return) > 2 )
|
||||
{
|
||||
if( str_return[0]=='0' && ( str_return[1]=='x' || str_return[1]=='X'))
|
||||
{
|
||||
value = (env_var_value)STRTOVALUE(str_return, NULL, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = atoi(str_return);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = atoi(str_return);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int setEnvVarValue( envvar_entry * env, char * varname, env_var_value value)
|
||||
{
|
||||
char tmp_str[128];
|
||||
|
||||
tmp_str[128 - 1] = 0;
|
||||
|
||||
snprintf(tmp_str,sizeof(tmp_str) - 1, "%d",value);
|
||||
|
||||
return setEnvVarDat( env, varname, tmp_str );
|
||||
}
|
||||
|
||||
char * getEnvVarDatIndex( envvar_entry * env, int index, char * vardata, int maxsize)
|
||||
{
|
||||
int str_index, off;
|
||||
unsigned short varname_size, vardata_size;
|
||||
|
||||
off = 0;
|
||||
|
||||
str_index = 0;
|
||||
|
||||
varname_size = getEnvStrSize(&env->buf[off]); // var name string size
|
||||
vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size
|
||||
|
||||
while( varname_size )
|
||||
{
|
||||
if( str_index == index )
|
||||
{
|
||||
if( varname_size>0 && vardata_size>0)
|
||||
{
|
||||
if(vardata)
|
||||
{
|
||||
stringcopy(vardata,(char*)&env->buf[off + 2 + varname_size + 2], maxsize);
|
||||
}
|
||||
|
||||
return (char*)&env->buf[off + 2];
|
||||
}
|
||||
}
|
||||
|
||||
off += (2 + varname_size + 2 + vardata_size);
|
||||
|
||||
varname_size = getEnvStrSize(&env->buf[off]); // var name string size
|
||||
vardata_size = getEnvStrSize(&env->buf[off + 2 + varname_size]); // var data string size
|
||||
|
||||
str_index++;
|
||||
}
|
||||
|
||||
return NULL; // Not found.
|
||||
}
|
||||
|
||||
envvar_entry * initEnv(envvar_entry * src, envvar_entry * dst)
|
||||
{
|
||||
if( !dst )
|
||||
{
|
||||
#ifdef STATIC_ENV_BUFFER
|
||||
return NULL;
|
||||
#else
|
||||
dst = malloc( sizeof(envvar_entry) );
|
||||
if(!dst)
|
||||
return NULL;
|
||||
|
||||
memset( dst, 0, sizeof(envvar_entry) );
|
||||
|
||||
if( src )
|
||||
dst->bufsize = src->bufsize;
|
||||
else
|
||||
dst->bufsize = ENV_PAGE_SIZE;
|
||||
|
||||
dst->buf = malloc(dst->bufsize);
|
||||
if(!dst->buf)
|
||||
{
|
||||
free(dst);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( src )
|
||||
memcpy( dst->buf, src->buf, src->bufsize );
|
||||
else
|
||||
memset( dst->buf, 0, dst->bufsize );
|
||||
|
||||
return dst;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef STATIC_ENV_BUFFER
|
||||
|
||||
memset( dst, 0, sizeof(envvar_entry) );
|
||||
dst->bufsize = ENV_PAGE_SIZE;
|
||||
if(src)
|
||||
{
|
||||
memcpy( dst->buf, src->buf, dst->bufsize );
|
||||
}
|
||||
else
|
||||
{
|
||||
memset( dst->buf, 0, dst->bufsize );
|
||||
}
|
||||
|
||||
return dst;
|
||||
#else
|
||||
free(dst->buf);
|
||||
|
||||
dst->buf = NULL;
|
||||
|
||||
if( src )
|
||||
dst->bufsize = src->bufsize;
|
||||
else
|
||||
dst->bufsize = ENV_PAGE_SIZE;
|
||||
|
||||
dst->buf = malloc(dst->bufsize);
|
||||
if(!dst->buf)
|
||||
{
|
||||
dst->bufsize = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(src)
|
||||
{
|
||||
memcpy( dst->buf, src->buf, dst->bufsize );
|
||||
}
|
||||
else
|
||||
{
|
||||
memset( dst->buf, 0, dst->bufsize );
|
||||
}
|
||||
|
||||
return dst;
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int jtagcore_setEnvVar( jtag_core * jc, char * varname, char * varvalue )
|
||||
{
|
||||
if( setEnvVarDat( jc->envvar, varname, varvalue ) >= 0 )
|
||||
{
|
||||
return JTAG_CORE_NO_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return JTAG_CORE_MEM_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
char * jtagcore_getEnvVar( jtag_core * jc, char * varname, char * varvalue)
|
||||
{
|
||||
return getEnvVarDat( jc->envvar, varname, varvalue, 512 );
|
||||
}
|
||||
|
||||
char * jtagcore_getEnvVarIndex( jtag_core * jc, int index, char * varvalue)
|
||||
{
|
||||
return getEnvVarDatIndex( jc->envvar, index, varvalue, 512 );
|
||||
}
|
||||
|
||||
int jtagcore_getEnvVarValue( jtag_core * jc, char * varname)
|
||||
{
|
||||
return getEnvVarValue( jc->envvar, varname);
|
||||
}
|
||||
|
||||
void deinitEnv(envvar_entry * env)
|
||||
{
|
||||
#ifndef STATIC_ENV_BUFFER
|
||||
if(!env)
|
||||
return;
|
||||
|
||||
free(env->buf);
|
||||
|
||||
free(env);
|
||||
#else
|
||||
memset(env,0,sizeof(envvar_entry));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
74
src/modules/script/env.h
Normal file
74
src/modules/script/env.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifndef _ENV_H
|
||||
#define _ENV_H
|
||||
/*
|
||||
* JTAG Boundary Scanner
|
||||
* Copyright (c) 2008 - 2024 Viveris Technologies
|
||||
*
|
||||
* JTAG Boundary Scanner is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* JTAG Boundary Scanner is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License version 3 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with JTAG Boundary Scanners; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file env.h
|
||||
* @brief Internal variables support header file.
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include "config/bs_defines.h"
|
||||
|
||||
#ifdef SCRIPT_64BITS_SUPPORT
|
||||
#define env_var_value uint64_t
|
||||
#define signed_env_var_value int64_t
|
||||
#define STRTOVALUE strtoull
|
||||
#else
|
||||
#define env_var_value uint32_t
|
||||
#define signed_env_var_value int32_t
|
||||
#define STRTOVALUE strtoul
|
||||
#endif
|
||||
|
||||
//#define STATIC_ENV_BUFFER 1
|
||||
#define ENV_PAGE_SIZE (16*1024)
|
||||
#define ENV_MAX_TOTAL_BUFFER_SIZE (1024 * 1024) // 1MB
|
||||
#define ENV_MAX_STRING_SIZE 512
|
||||
|
||||
typedef struct envvar_entry_
|
||||
{
|
||||
#ifdef STATIC_ENV_BUFFER
|
||||
unsigned char buf[ENV_PAGE_SIZE];
|
||||
#else
|
||||
unsigned char * buf;
|
||||
#endif
|
||||
unsigned int bufsize;
|
||||
}envvar_entry;
|
||||
|
||||
envvar_entry * initEnv( envvar_entry * src, envvar_entry * dst );
|
||||
|
||||
int setEnvVarDat( envvar_entry * env, char * varname, char * vardata );
|
||||
int setEnvVarValue( envvar_entry * env, char * varname, env_var_value value );
|
||||
|
||||
char * getEnvVarDat( envvar_entry * env, char * varname, char * vardata, int maxsize );
|
||||
env_var_value getEnvVarValue( envvar_entry * env, char * varname );
|
||||
|
||||
char * getEnvVarDatIndex( envvar_entry * env, int index, char * vardata, int maxsize );
|
||||
|
||||
void deinitEnv( envvar_entry * env );
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Internal variables functions
|
||||
int jtagcore_setEnvVar(jtag_core *jc, char *varname, char *varvalue);
|
||||
char *jtagcore_getEnvVar(jtag_core *jc, char *varname, char *varvalue);
|
||||
int jtagcore_getEnvVarValue(jtag_core *jc, char *varname);
|
||||
char *jtagcore_getEnvVarIndex(jtag_core *jc, int index, char *varvalue);
|
||||
|
||||
#endif
|
||||
3673
src/modules/script/script.c
Normal file
3673
src/modules/script/script.c
Normal file
File diff suppressed because it is too large
Load Diff
56
src/modules/script/script.h
Normal file
56
src/modules/script/script.h
Normal file
@@ -0,0 +1,56 @@
|
||||
#ifndef _SCRIPT_H
|
||||
#define _SCRIPT_H
|
||||
/*
|
||||
* JTAG Boundary Scanner
|
||||
* Copyright (c) 2008 - 2024 Viveris Technologies
|
||||
*
|
||||
* JTAG Boundary Scanner is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* JTAG Boundary Scanner is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License version 3 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with JTAG Boundary Scanners; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file script.h
|
||||
* @brief JTAG Boundary Scanner scripts support header file.
|
||||
* @author Jean-François DEL NERO <Jean-Francois.DELNERO@viveris.fr>
|
||||
*/
|
||||
|
||||
#include "config/bs_defines.h"
|
||||
|
||||
typedef int (* CMD_FUNC)( script_ctx * ctx, char * line);
|
||||
|
||||
typedef struct cmd_list_
|
||||
{
|
||||
const char * command;
|
||||
CMD_FUNC func;
|
||||
const char ** help;
|
||||
}cmd_list;
|
||||
|
||||
typedef struct label_list_
|
||||
{
|
||||
char * label;
|
||||
unsigned int file_offset;
|
||||
}label_list;
|
||||
|
||||
extern cmd_list script_commands_list[];
|
||||
|
||||
script_ctx *jtagcore_initScript(jtag_core *jc);
|
||||
script_ctx * init_script(void * app_ctx, unsigned int flags, void * env);
|
||||
int execute_file_script( script_ctx * ctx, char * filename );
|
||||
int execute_line_script( script_ctx * ctx, char * line );
|
||||
int execute_ram_script( script_ctx * ctx, unsigned char * script_buffer, int buffersize );
|
||||
void setOutputFunc_script( script_ctx * ctx, SCRIPT_PRINTF_FUNC ext_printf );
|
||||
script_ctx * deinit_script(script_ctx * ctx);
|
||||
int jtagcore_savePinsStateScript(jtag_core *jc, int device, char *script_path);
|
||||
|
||||
#endif
|
||||
7
src/modules/spi_flash/CMakeLists.txt
Normal file
7
src/modules/spi_flash/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
file(GLOB_RECURSE ALL_SOURCES "*.c")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
|
||||
add_library(spi_flash ${ALL_SOURCES})
|
||||
202
src/modules/spi_flash/spi_flash.c
Normal file
202
src/modules/spi_flash/spi_flash.c
Normal file
@@ -0,0 +1,202 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "spi_flash.h"
|
||||
|
||||
/* Standard JEDEC SPI NOR opcodes shared by all parts. */
|
||||
#define CMD_RDID 0x9F /* read JEDEC ID */
|
||||
#define CMD_WREN 0x06 /* write enable */
|
||||
#define CMD_RDSR 0x05 /* read status register */
|
||||
#define SR_WIP 0x01 /* status: write-in-progress */
|
||||
|
||||
/* Largest single transport transaction for read/verify, to bound the
|
||||
* buffers the transport has to allocate. */
|
||||
#define SPI_FLASH_CHUNK 4096u
|
||||
|
||||
/* Safety cap on status polling so a stuck WIP can't hang forever. */
|
||||
#define WIP_POLL_MAX 5000000
|
||||
|
||||
/* --- Chip database ------------------------------------------------- */
|
||||
|
||||
static const spi_flash_chip chip_db[] = {
|
||||
/* Micron MT25QU256 — KCU105 config flash, 1.8 V, 32 MB, 4-byte addr.
|
||||
* 4-byte command opcodes (READ4B/PP4B/SUBSEC-ERASE4B) so the full
|
||||
* range is reachable regardless of the address-mode latch. */
|
||||
{ "Micron MT25QU256", 0x20, 0xBB19, 32u * 1024 * 1024, 256, 4096, 4, 0x13, 0x12, 0x21 },
|
||||
{ "Micron MT25QL256", 0x20, 0xBA19, 32u * 1024 * 1024, 256, 4096, 4, 0x13, 0x12, 0x21 },
|
||||
/* 16 MB, 3-byte parts. */
|
||||
{ "Winbond W25Q128", 0xEF, 0x4018, 16u * 1024 * 1024, 256, 4096, 3, 0x03, 0x02, 0x20 },
|
||||
{ "Macronix MX25L128",0xC2, 0x2018, 16u * 1024 * 1024, 256, 4096, 3, 0x03, 0x02, 0x20 },
|
||||
{ "ISSI IS25LP128", 0x9D, 0x6018, 16u * 1024 * 1024, 256, 4096, 3, 0x03, 0x02, 0x20 },
|
||||
};
|
||||
|
||||
#define CHIP_DB_LEN ((int)(sizeof(chip_db) / sizeof(chip_db[0])))
|
||||
|
||||
int spi_flash_chip_count(void)
|
||||
{
|
||||
return CHIP_DB_LEN;
|
||||
}
|
||||
|
||||
const spi_flash_chip *spi_flash_chip_by_index(int i)
|
||||
{
|
||||
if (i < 0 || i >= CHIP_DB_LEN) return NULL;
|
||||
return &chip_db[i];
|
||||
}
|
||||
|
||||
/* --- Helpers ------------------------------------------------------- */
|
||||
|
||||
static int put_addr(uint8_t *b, uint32_t addr, int addr_bytes)
|
||||
{
|
||||
if (addr_bytes == 4) {
|
||||
b[0] = (uint8_t)(addr >> 24);
|
||||
b[1] = (uint8_t)(addr >> 16);
|
||||
b[2] = (uint8_t)(addr >> 8);
|
||||
b[3] = (uint8_t)(addr);
|
||||
return 4;
|
||||
}
|
||||
b[0] = (uint8_t)(addr >> 16);
|
||||
b[1] = (uint8_t)(addr >> 8);
|
||||
b[2] = (uint8_t)(addr);
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int write_enable(spi_flash *sf)
|
||||
{
|
||||
uint8_t cmd = CMD_WREN;
|
||||
return sf->xfer(sf->ctx, &cmd, 1, NULL, 0);
|
||||
}
|
||||
|
||||
/* Poll the status register until write-in-progress clears. */
|
||||
static int wait_wip(spi_flash *sf)
|
||||
{
|
||||
long tries;
|
||||
for (tries = 0; tries < WIP_POLL_MAX; tries++) {
|
||||
uint8_t cmd = CMD_RDSR, st = 0;
|
||||
if (sf->xfer(sf->ctx, &cmd, 1, &st, 1) < 0) return -1;
|
||||
if (!(st & SR_WIP)) return 0;
|
||||
}
|
||||
return -1; /* timeout */
|
||||
}
|
||||
|
||||
/* --- Operations ---------------------------------------------------- */
|
||||
|
||||
int spi_flash_detect(spi_flash *sf)
|
||||
{
|
||||
uint8_t cmd = CMD_RDID;
|
||||
uint8_t id[3] = {0, 0, 0};
|
||||
uint16_t dev;
|
||||
int i;
|
||||
|
||||
if (!sf || !sf->xfer) return -1;
|
||||
if (sf->xfer(sf->ctx, &cmd, 1, id, 3) < 0) return -1;
|
||||
|
||||
memcpy(sf->jedec, id, 3);
|
||||
sf->chip = NULL;
|
||||
|
||||
dev = (uint16_t)((id[1] << 8) | id[2]);
|
||||
for (i = 0; i < CHIP_DB_LEN; i++) {
|
||||
if (chip_db[i].mfg_id == id[0] && chip_db[i].dev_id == dev) {
|
||||
sf->chip = &chip_db[i];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1; /* read OK but unknown part */
|
||||
}
|
||||
|
||||
int spi_flash_read(spi_flash *sf, uint32_t addr, uint8_t *buf, size_t len)
|
||||
{
|
||||
uint8_t cmd[1 + 4];
|
||||
int n;
|
||||
|
||||
if (!sf || !sf->chip || !buf) return -1;
|
||||
|
||||
while (len) {
|
||||
size_t chunk = (len > SPI_FLASH_CHUNK) ? SPI_FLASH_CHUNK : len;
|
||||
cmd[0] = sf->chip->read_cmd;
|
||||
n = 1 + put_addr(&cmd[1], addr, sf->chip->addr_bytes);
|
||||
if (sf->xfer(sf->ctx, cmd, (size_t)n, buf, chunk) < 0) return -1;
|
||||
addr += (uint32_t)chunk;
|
||||
buf += chunk;
|
||||
len -= chunk;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spi_flash_erase_sector(spi_flash *sf, uint32_t addr)
|
||||
{
|
||||
uint8_t cmd[1 + 4];
|
||||
int n;
|
||||
|
||||
if (!sf || !sf->chip) return -1;
|
||||
|
||||
addr -= (addr % sf->chip->sector_size); /* align to sector base */
|
||||
|
||||
if (write_enable(sf) < 0) return -1;
|
||||
cmd[0] = sf->chip->erase_cmd;
|
||||
n = 1 + put_addr(&cmd[1], addr, sf->chip->addr_bytes);
|
||||
if (sf->xfer(sf->ctx, cmd, (size_t)n, NULL, 0) < 0) return -1;
|
||||
return wait_wip(sf);
|
||||
}
|
||||
|
||||
int spi_flash_program_page(spi_flash *sf, uint32_t addr,
|
||||
const uint8_t *data, size_t len)
|
||||
{
|
||||
uint8_t cmd[1 + 4 + 256];
|
||||
int n;
|
||||
|
||||
if (!sf || !sf->chip || !data) return -1;
|
||||
if (len == 0) return 0;
|
||||
if (len > sf->chip->page_size || len > 256) return -1;
|
||||
/* must not cross a page boundary */
|
||||
if ((addr % sf->chip->page_size) + len > sf->chip->page_size) return -1;
|
||||
|
||||
if (write_enable(sf) < 0) return -1;
|
||||
cmd[0] = sf->chip->pp_cmd;
|
||||
n = 1 + put_addr(&cmd[1], addr, sf->chip->addr_bytes);
|
||||
memcpy(&cmd[n], data, len);
|
||||
n += (int)len;
|
||||
if (sf->xfer(sf->ctx, cmd, (size_t)n, NULL, 0) < 0) return -1;
|
||||
return wait_wip(sf);
|
||||
}
|
||||
|
||||
int spi_flash_program(spi_flash *sf, uint32_t addr,
|
||||
const uint8_t *data, size_t len)
|
||||
{
|
||||
if (!sf || !sf->chip || !data) return -1;
|
||||
|
||||
while (len) {
|
||||
uint32_t page = sf->chip->page_size;
|
||||
uint32_t off = addr % page;
|
||||
size_t chunk = page - off;
|
||||
if (chunk > len) chunk = len;
|
||||
if (spi_flash_program_page(sf, addr, data, chunk) < 0) return -1;
|
||||
addr += (uint32_t)chunk;
|
||||
data += chunk;
|
||||
len -= chunk;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spi_flash_verify(spi_flash *sf, uint32_t addr,
|
||||
const uint8_t *data, size_t len, uint32_t *mismatch_off)
|
||||
{
|
||||
uint8_t tmp[SPI_FLASH_CHUNK];
|
||||
uint32_t done = 0;
|
||||
|
||||
if (!sf || !sf->chip || !data) return -1;
|
||||
|
||||
while (len) {
|
||||
size_t chunk = (len > sizeof(tmp)) ? sizeof(tmp) : len;
|
||||
size_t i;
|
||||
if (spi_flash_read(sf, addr, tmp, chunk) < 0) return -1;
|
||||
for (i = 0; i < chunk; i++) {
|
||||
if (tmp[i] != data[done + i]) {
|
||||
if (mismatch_off) *mismatch_off = done + (uint32_t)i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
addr += (uint32_t)chunk;
|
||||
done += (uint32_t)chunk;
|
||||
len -= chunk;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
79
src/modules/spi_flash/spi_flash.h
Normal file
79
src/modules/spi_flash/spi_flash.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#ifndef _SPI_FLASH_H
|
||||
#define _SPI_FLASH_H
|
||||
|
||||
/*
|
||||
* Generic SPI NOR flash layer (Phase 3).
|
||||
*
|
||||
* Transport-agnostic: it issues SPI commands through an `xfer` callback
|
||||
* (one CS-framed transaction), so it works over the BSCAN proxy, the
|
||||
* EXTEST bit-bang, or anything else that can clock bytes in and out.
|
||||
*
|
||||
* Standard JEDEC command set (RDID/READ/WREN/RDSR/PP/SE). Chips are
|
||||
* matched by JEDEC ID against a small built-in database; 3- and 4-byte
|
||||
* addressing are both supported (parts over 16 MB use the 4-byte
|
||||
* command opcodes, which are stateless regardless of the part's
|
||||
* address-mode latch).
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* One CS-framed SPI transaction: clock out `txlen` MOSI bytes, then
|
||||
* read `rxlen` MISO bytes into `rx`. Either length may be 0. Returns 0
|
||||
* on success, <0 on error. */
|
||||
typedef int (*spi_flash_xfer_fn)(void *ctx,
|
||||
const uint8_t *tx, size_t txlen,
|
||||
uint8_t *rx, size_t rxlen);
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
uint8_t mfg_id; /* JEDEC byte 0 (manufacturer) */
|
||||
uint16_t dev_id; /* JEDEC bytes 1..2 ((b1 << 8) | b2) */
|
||||
uint32_t size_bytes; /* total capacity */
|
||||
uint32_t page_size; /* program granularity (typically 256) */
|
||||
uint32_t sector_size; /* erase granularity (typically 4096) */
|
||||
uint8_t addr_bytes; /* address width: 3 or 4 */
|
||||
uint8_t read_cmd; /* READ opcode (no dummy) */
|
||||
uint8_t pp_cmd; /* PAGE PROGRAM opcode */
|
||||
uint8_t erase_cmd; /* sector/subsector ERASE opcode */
|
||||
} spi_flash_chip;
|
||||
|
||||
typedef struct {
|
||||
spi_flash_xfer_fn xfer; /* transport */
|
||||
void *ctx; /* opaque, passed to xfer */
|
||||
const spi_flash_chip *chip; /* matched part, set by detect */
|
||||
uint8_t jedec[3]; /* raw JEDEC ID from last detect */
|
||||
} spi_flash;
|
||||
|
||||
/* Read the JEDEC ID (0x9F) and match the database.
|
||||
* Returns 0 if a known chip matched (sf->chip set), 1 if the ID was
|
||||
* read but is not in the database (sf->chip left NULL, sf->jedec set),
|
||||
* <0 on transport error. */
|
||||
int spi_flash_detect(spi_flash *sf);
|
||||
|
||||
/* Read `len` bytes starting at `addr` into `buf`. Returns 0 / <0. */
|
||||
int spi_flash_read(spi_flash *sf, uint32_t addr, uint8_t *buf, size_t len);
|
||||
|
||||
/* Erase the sector containing `addr` (WREN + ERASE + poll WIP). */
|
||||
int spi_flash_erase_sector(spi_flash *sf, uint32_t addr);
|
||||
|
||||
/* Program at most one page at `addr` (`len` <= page_size and must not
|
||||
* cross a page boundary): WREN + PP + poll WIP. */
|
||||
int spi_flash_program_page(spi_flash *sf, uint32_t addr,
|
||||
const uint8_t *data, size_t len);
|
||||
|
||||
/* Program `len` bytes from `addr`, splitting on page boundaries. The
|
||||
* target range must already be erased. */
|
||||
int spi_flash_program(spi_flash *sf, uint32_t addr,
|
||||
const uint8_t *data, size_t len);
|
||||
|
||||
/* Read back and compare. Returns 0 if identical, 1 on first mismatch
|
||||
* (and reports its offset via *mismatch_off if non-NULL), <0 on error. */
|
||||
int spi_flash_verify(spi_flash *sf, uint32_t addr,
|
||||
const uint8_t *data, size_t len, uint32_t *mismatch_off);
|
||||
|
||||
/* Built-in database access. */
|
||||
int spi_flash_chip_count(void);
|
||||
const spi_flash_chip *spi_flash_chip_by_index(int i);
|
||||
|
||||
#endif
|
||||
7
src/modules/svf/CMakeLists.txt
Normal file
7
src/modules/svf/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
set(SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
file(GLOB_RECURSE ALL_SOURCES "*.c")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..)
|
||||
|
||||
add_library(svf ${ALL_SOURCES})
|
||||
447
src/modules/svf/svf.c
Normal file
447
src/modules/svf/svf.c
Normal file
@@ -0,0 +1,447 @@
|
||||
#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;
|
||||
}
|
||||
40
src/modules/svf/svf.h
Normal file
40
src/modules/svf/svf.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user