diff --git a/modules/drivers/digilent_jtag/digilent_jtag_drv.c b/modules/drivers/digilent_jtag/digilent_jtag_drv.c index 651f795..0a6bf52 100644 --- a/modules/drivers/digilent_jtag/digilent_jtag_drv.c +++ b/modules/drivers/digilent_jtag/digilent_jtag_drv.c @@ -285,26 +285,26 @@ static int drv_Digilent_DeInit(jtag_core *jc) static int drv_Digilent_TMS_xfer(jtag_core *jc, unsigned char *str_out, int size) { - DJ_BYTE buf_snd[1024]; + DJ_BYTE *buf_snd; int nbytes = (size + 7) / 8; - int i; + int i, ok; if (!g_dj_open) return JTAG_CORE_BAD_PARAMETER; if (size <= 0) return JTAG_CORE_NO_ERROR; - if (nbytes > (int)sizeof(buf_snd)) { - jtagcore_logs_printf(jc, MSG_ERROR, - "drv_Digilent_TMS_xfer : size %d > %d bits\r\n", - size, (int)sizeof(buf_snd) * 8); - return JTAG_CORE_BAD_PARAMETER; - } - memset(buf_snd, 0, nbytes); + /* 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)); } - if (!g_dj.PutTmsBits(g_dj_hif, /*fTdi=*/0, buf_snd, NULL, (DJ_DWORD)size, /*fOverlap=*/0)) { + 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; @@ -317,10 +317,9 @@ static int drv_Digilent_TDOTDI_xfer(jtag_core *jc, unsigned char *str_in, int size) { - DJ_BYTE buf_snd[2048]; - DJ_BYTE buf_rcv[1024]; + DJ_BYTE *buf_snd, *buf_rcv = NULL; int has_tms = 0; - int i; + int i, ok, snd_bytes; if (!g_dj_open) return JTAG_CORE_BAD_PARAMETER; if (size <= 0) return JTAG_CORE_NO_ERROR; @@ -329,54 +328,50 @@ static int drv_Digilent_TDOTDI_xfer(jtag_core *jc, 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) { - /* Mixed TMS+TDI shift: 2 bits per clock (TDI low, TMS high), LSB-first. */ - int nbytes_snd = (2 * size + 7) / 8; - if (nbytes_snd > (int)sizeof(buf_snd) || (size + 7) / 8 > (int)sizeof(buf_rcv)) { - jtagcore_logs_printf(jc, MSG_ERROR, - "drv_Digilent_TDOTDI_xfer : size %d too large\r\n", size); - return JTAG_CORE_BAD_PARAMETER; - } - memset(buf_snd, 0, nbytes_snd); + /* 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)); /* TDI = low bit */ + 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)); /* TMS = high bit */ - } - if (!g_dj.PutTmsTdiBits(g_dj_hif, buf_snd, str_in ? buf_rcv : NULL, - (DJ_DWORD)size, /*fOverlap=*/0)) { - jtagcore_logs_printf(jc, MSG_ERROR, - "drv_Digilent_TDOTDI_xfer : DjtgPutTmsTdiBits failed\r\n"); - return JTAG_CORE_BAD_PARAMETER; + 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. */ - int nbytes_snd = (size + 7) / 8; - if (nbytes_snd > (int)sizeof(buf_rcv)) { - jtagcore_logs_printf(jc, MSG_ERROR, - "drv_Digilent_TDOTDI_xfer : size %d too large\r\n", size); - return JTAG_CORE_BAD_PARAMETER; - } - memset(buf_snd, 0, nbytes_snd); for (i = 0; i < size; i++) { if (str_out[i] & JTAG_STR_DOUT) buf_snd[i >> 3] |= (DJ_BYTE)(1u << (i & 7)); } - if (!g_dj.PutTdiBits(g_dj_hif, /*fTms=*/0, buf_snd, str_in ? buf_rcv : NULL, - (DJ_DWORD)size, /*fOverlap=*/0)) { - jtagcore_logs_printf(jc, MSG_ERROR, - "drv_Digilent_TDOTDI_xfer : DjtgPutTdiBits failed\r\n"); - return JTAG_CORE_BAD_PARAMETER; - } + 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; }