JTAG: Restore CPLD pin config functions, leave pins in pull-only state when not actively operating.

This commit is contained in:
Jared Boone
2018-12-31 10:12:28 -08:00
parent cd24e01d75
commit f60b2479fb
4 changed files with 84 additions and 42 deletions

View File

@ -29,6 +29,75 @@ static refill_buffer_cb refill_buffer;
static uint32_t xsvf_buffer_len, xsvf_pos; static uint32_t xsvf_buffer_len, xsvf_pos;
static unsigned char* xsvf_buffer; static unsigned char* xsvf_buffer;
void cpld_jtag_init(jtag_t* const jtag) {
/* Initialize pin GPIOs in "released" state. */
cpld_jtag_release(jtag);
/* TDI and TMS pull-ups are required in all JTAG-compliant devices.
*
* The HackRF CPLD is always present, so let the CPLD pull up its TDI and TMS.
*
* The PortaPack may not be present, so pull up the PortaPack TMS pin from the
* microcontroller.
*
* TCK is recommended to be held low, so use microcontroller pull-down.
*
* TDO is undriven except when in Shift-IR or Shift-DR phases.
* Use the microcontroller to pull down to keep from floating.
*
* LPC43xx pull-up and pull-down resistors are approximately 53K.
*/
#ifdef USER_INTERFACE_PORTAPACK
scu_pinmux(SCU_PINMUX_PP_TMS, SCU_GPIO_PUP | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_PP_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
#endif
scu_pinmux(SCU_PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_CPLD_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_PINMUX_CPLD_TCK, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
}
void cpld_jtag_take(jtag_t* const jtag) {
const jtag_gpio_t* const gpio = jtag->gpio;
#ifdef USER_INTERFACE_PORTAPACK
/* Do not drive PortaPack-specific TMS pin initially, just to be cautious. */
gpio_input(gpio->gpio_pp_tms);
gpio_input(gpio->gpio_pp_tdo);
#endif
gpio_output(gpio->gpio_tms);
gpio_output(gpio->gpio_tdi);
gpio_output(gpio->gpio_tck);
gpio_input(gpio->gpio_tdo);
}
void cpld_jtag_release(jtag_t* const jtag) {
const jtag_gpio_t* const gpio = jtag->gpio;
/* Make all pins inputs when JTAG interface not active.
* Let the pull-ups/downs do the work.
*/
#ifdef USER_INTERFACE_PORTAPACK
/* Do not drive PortaPack-specific pins, initially, just to be cautious. */
gpio_input(gpio->gpio_pp_tms);
gpio_input(gpio->gpio_pp_tdo);
#endif
gpio_input(gpio->gpio_tms);
gpio_input(gpio->gpio_tdi);
gpio_input(gpio->gpio_tck);
gpio_input(gpio->gpio_tdo);
/* Set initial GPIO state to the voltages of the internal or external pull-ups/downs,
* to avoid any glitches.
*/
#ifdef USER_INTERFACE_PORTAPACK
gpio_set(gpio->gpio_pp_tms);
#endif
gpio_set(gpio->gpio_tms);
gpio_set(gpio->gpio_tdi);
gpio_clear(gpio->gpio_tck);
}
/* return 0 if success else return error code see xsvfExecute() */ /* return 0 if success else return error code see xsvfExecute() */
int cpld_jtag_program( int cpld_jtag_program(
jtag_t* const jtag, jtag_t* const jtag,
@ -37,10 +106,12 @@ int cpld_jtag_program(
refill_buffer_cb refill refill_buffer_cb refill
) { ) {
int error; int error;
cpld_jtag_take(jtag);
xsvf_buffer = buffer; xsvf_buffer = buffer;
xsvf_buffer_len = buffer_length; xsvf_buffer_len = buffer_length;
refill_buffer = refill; refill_buffer = refill;
error = xsvfExecute(jtag->gpio); error = xsvfExecute(jtag->gpio);
cpld_jtag_release(jtag);
return error; return error;
} }

View File

@ -43,6 +43,10 @@ typedef struct jtag_t {
typedef void (*refill_buffer_cb)(void); typedef void (*refill_buffer_cb)(void);
void cpld_jtag_init(jtag_t* const jtag);
void cpld_jtag_take(jtag_t* const jtag);
void cpld_jtag_release(jtag_t* const jtag);
/* Return 0 if success else return error code see xsvfExecute() see micro.h. /* Return 0 if success else return error code see xsvfExecute() see micro.h.
* *
* We expect the buffer to be initially full of data. After the entire * We expect the buffer to be initially full of data. After the entire

View File

@ -33,6 +33,7 @@
#include "w25q80bv_target.h" #include "w25q80bv_target.h"
#include "i2c_bus.h" #include "i2c_bus.h"
#include "i2c_lpc.h" #include "i2c_lpc.h"
#include "cpld_jtag.h"
#include <libopencm3/lpc43xx/cgu.h> #include <libopencm3/lpc43xx/cgu.h>
#include <libopencm3/lpc43xx/ccu.h> #include <libopencm3/lpc43xx/ccu.h>
#include <libopencm3/lpc43xx/scu.h> #include <libopencm3/lpc43xx/scu.h>
@ -758,49 +759,11 @@ void ssp1_set_mode_max5864(void)
spi_bus_start(max5864.bus, &ssp_config_max5864); spi_bus_start(max5864.bus, &ssp_config_max5864);
} }
static void jtag_setup(void) {
/* TDI and TMS pull-ups are required in all JTAG-compliant devices.
* Therefore, do not pull up TDI and TMS on HackRF CPLD, which is always present.
* HackRF TMS and TDI are dedicated, just drive instead of pulling up/down.
* TCK is recommended to be held low.
* TDO is undriven except when in Shift-IR or Shift-DR phases, so pull down to keep from floating.
* Nail down other signals before causing any transitions on TCK, to prevent undesired
* state changes.
*/
/* LPC43xx pull-up and pull-down resistors are approximately 53K. */
#ifdef USER_INTERFACE_PORTAPACK
gpio_set(jtag_gpio_cpld.gpio_pp_tms);
#endif
gpio_set(jtag_gpio_cpld.gpio_tms);
gpio_set(jtag_gpio_cpld.gpio_tdi);
gpio_clear(jtag_gpio_cpld.gpio_tck);
#ifdef USER_INTERFACE_PORTAPACK
/* Do not drive PortaPack-specific pins, initially, just to be cautious. */
gpio_input(jtag_gpio_cpld.gpio_pp_tms);
gpio_input(jtag_gpio_cpld.gpio_pp_tdo);
#endif
gpio_output(jtag_gpio_cpld.gpio_tms);
gpio_output(jtag_gpio_cpld.gpio_tdi);
gpio_output(jtag_gpio_cpld.gpio_tck);
gpio_input(jtag_gpio_cpld.gpio_tdo);
/* Configure CPLD JTAG pins */
#ifdef USER_INTERFACE_PORTAPACK
scu_pinmux(SCU_PINMUX_PP_TMS, SCU_GPIO_PUP | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_PP_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
#endif
scu_pinmux(SCU_PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_CPLD_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_PINMUX_CPLD_TCK, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
}
void pin_setup(void) { void pin_setup(void) {
/* Configure all GPIO as Input (safe state) */ /* Configure all GPIO as Input (safe state) */
gpio_init(); gpio_init();
jtag_setup(); cpld_jtag_init(&jtag_cpld);
/* Configure SCU Pin Mux as GPIO */ /* Configure SCU Pin Mux as GPIO */
scu_pinmux(SCU_PINMUX_LED1, SCU_GPIO_NOPULL); scu_pinmux(SCU_PINMUX_LED1, SCU_GPIO_NOPULL);

View File

@ -503,6 +503,11 @@ static uint32_t jtag_pp_shift(const uint32_t tms_bits, const size_t count) {
} }
static uint32_t jtag_pp_idcode() { static uint32_t jtag_pp_idcode() {
cpld_jtag_take(&jtag_cpld);
/* TODO: Check if PortaPack TMS is floating or driven by an external device. */
gpio_output(jtag_cpld.gpio->gpio_pp_tms);
/* Test-Logic/Reset -> Run-Test/Idle -> Select-DR/Scan -> Capture-DR */ /* Test-Logic/Reset -> Run-Test/Idle -> Select-DR/Scan -> Capture-DR */
jtag_pp_shift(0b11111010, 8); jtag_pp_shift(0b11111010, 8);
@ -512,6 +517,8 @@ static uint32_t jtag_pp_idcode() {
/* Exit1-DR -> Update-DR -> Run-Test/Idle -> ... -> Test-Logic/Reset */ /* Exit1-DR -> Update-DR -> Run-Test/Idle -> ... -> Test-Logic/Reset */
jtag_pp_shift(0b11011111, 8); jtag_pp_shift(0b11011111, 8);
cpld_jtag_release(&jtag_cpld);
return idcode; return idcode;
} }
@ -998,9 +1005,6 @@ static const hackrf_ui_t portapack_ui = {
}; };
const hackrf_ui_t* portapack_detect(void) { const hackrf_ui_t* portapack_detect(void) {
/* TODO: Check if PortaPack TMS is floating or driven by an external device. */
gpio_output(jtag_cpld.gpio->gpio_pp_tms);
if( jtag_pp_idcode() == 0x020A50DD ) { if( jtag_pp_idcode() == 0x020A50DD ) {
return &portapack_ui; return &portapack_ui;
} else { } else {