digilent: implement Init / DeInit
DmgrOpen + DjtgEnable + DjtgSetSpeed at 4 MHz (Adept rounds to the nearest supported, e.g. 3.75 MHz on SMT2-NC). DeInit does the reverse. An atexit hook also forces Close on process shutdown — leaving an open HIF when libdjtg's C++ static destructors run triggers "pure virtual method called".
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
@@ -71,6 +72,21 @@ static struct {
|
||||
|
||||
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;
|
||||
@@ -115,6 +131,8 @@ static int digilent_load(jtag_core *jc)
|
||||
RESOLVE(PutTmsTdiBits, libjtg, DjtgPutTmsTdiBits);
|
||||
#undef RESOLVE
|
||||
|
||||
atexit(digilent_atexit_close);
|
||||
|
||||
g_dj_loaded = 1;
|
||||
return 0;
|
||||
|
||||
@@ -184,14 +202,67 @@ static int drv_Digilent_Detect(jtag_core *jc)
|
||||
|
||||
static int drv_Digilent_Init(jtag_core *jc, int sub_drv, char *params)
|
||||
{
|
||||
jtagcore_logs_printf(jc, MSG_ERROR,
|
||||
"drv_Digilent_Init : not yet implemented (step 3)\r\n");
|
||||
return -1;
|
||||
DJ_DWORD frq_req = 4000000; /* 4 MHz — safe and fast enough for IDCODE/IR */
|
||||
DJ_DWORD frq_set = 0;
|
||||
|
||||
(void)params;
|
||||
|
||||
if (g_dj_loaded != 1) {
|
||||
jtagcore_logs_printf(jc, MSG_ERROR,
|
||||
"drv_Digilent_Init : Adept libs not loaded\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)
|
||||
{
|
||||
return 0;
|
||||
(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;
|
||||
}
|
||||
|
||||
static int drv_Digilent_TMS_xfer(jtag_core *jc, unsigned char *str_out, int size)
|
||||
|
||||
Reference in New Issue
Block a user