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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
@@ -71,6 +72,21 @@ static struct {
|
|||||||
|
|
||||||
static int g_dj_loaded = 0; /* 0 = not tried, 1 = ok, -1 = failed */
|
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)
|
static int digilent_load(jtag_core *jc)
|
||||||
{
|
{
|
||||||
if (g_dj_loaded > 0) return 0;
|
if (g_dj_loaded > 0) return 0;
|
||||||
@@ -115,6 +131,8 @@ static int digilent_load(jtag_core *jc)
|
|||||||
RESOLVE(PutTmsTdiBits, libjtg, DjtgPutTmsTdiBits);
|
RESOLVE(PutTmsTdiBits, libjtg, DjtgPutTmsTdiBits);
|
||||||
#undef RESOLVE
|
#undef RESOLVE
|
||||||
|
|
||||||
|
atexit(digilent_atexit_close);
|
||||||
|
|
||||||
g_dj_loaded = 1;
|
g_dj_loaded = 1;
|
||||||
return 0;
|
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)
|
static int drv_Digilent_Init(jtag_core *jc, int sub_drv, char *params)
|
||||||
{
|
{
|
||||||
jtagcore_logs_printf(jc, MSG_ERROR,
|
DJ_DWORD frq_req = 4000000; /* 4 MHz — safe and fast enough for IDCODE/IR */
|
||||||
"drv_Digilent_Init : not yet implemented (step 3)\r\n");
|
DJ_DWORD frq_set = 0;
|
||||||
return -1;
|
|
||||||
|
(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)
|
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)
|
static int drv_Digilent_TMS_xfer(jtag_core *jc, unsigned char *str_out, int size)
|
||||||
|
|||||||
Reference in New Issue
Block a user