I think it's the time to implement this feature.
For STM32 JTAG/SWD support, this feature is MUCH more difficult than the
change in ADIv5 code.

I demonstrate the multi-interface framework in vsprog, which is the
programmer for Versaloon supporting
JTAG/SWD/SPI/UART/USART/IIC/PSoC_ISSP/LPC900_ICP/C8051F_C2/STM8_SWIM and so
on.

Every interface has an ID(bit-mask):
// interfaces
#define USART                    (1 << 0)           // UART and USART
#define SPI                        (1 << 1)
#define I2C                        (1 << 2)
#define GPIO                    (1 << 3)
#define CAN                        (1 << 4)
#define CLOCK                    (1 << 5)          // clock output control
#define ADC                        (1 << 6)           // analog to digit
#define DAC                        (1 << 7)           // digit to analog
#define POWER                    (1 << 8)         // power output control
#define ISSP                    (1 << 16)            // PSoc_ISSP
#define JTAG_LL                    (1 << 17)      // similar low level
driver to OpenOCD JTAG drive, used in SVF Player
#define JTAG_HL                    (1 << 18)      // A high level driver
used in MCU support
#define MSP430_SBW                (1 << 19)
#define C2                        (1 << 20)            // C8051F_C2
#define MSP430_JTAG                (1 << 21)
#define LPC_ICP                    (1 << 22)       // LPC900_ICP
#define SWJ                        (1 << 23)         // acutally it should
be SWD
#define SWIM                    (1 << 24)           // STM8_SWIM
#define HV                        (1 << 25)           // High Voltage
control, some targets including AVR/PIC need High Voltage support
......
Disadvantage is that the number of interfaces is limitted, if using 64-bit
integer, ONLY 64 interfaces can be defined.

Every target must define a interface_needed according to different
program_mode.
For AVR:
const struct program_mode_t avr8_program_mode[] =
{
    {'i', SET_FREQUENCY, SPI | GPIO},    // ISP mode, SPI and GPIO(for reset
control) is needed
    {'j', SET_FREQUENCY, JTAG_HL},      // JTAG mode, JTAG_HL is needed
    {'p', "", HV | GPIO},                             // High Voltage
Parallel Mode, HV and GPIO
    {'s', "", HV | GPIO},                             // High Voltage Serial
Mode, HV and GPIO
    {0, NULL, 0}
};
For STM32:
const struct program_mode_t stm32_program_mode[] =
{
    {'j', SET_FREQUENCY, JTAG_HL},      // JTAG mode, JTAG_HL
    {'s', "", SWJ},                                      // SWD mode, SWJ
    {'i', USE_COMM, 0},                            // ISP mode, ComPort on
PC
    {0, NULL, 0}
};

When initializing dongle, a interface_supported should be returned to
indicate the supported interfaces.
// init programmer capabilities
cur_programmer->init_capability(cur_programmer);

RESULT versaloon_init_capability(void *p)
{
    struct programmer_info_t *t = (struct programmer_info_t *)p;

    t->init = versaloon_init;
    t->fini = versaloon_fini;

    t->interfaces = (SPI | GPIO | ISSP | JTAG_LL | JTAG_HL | SWIM
                        | C2 | MSP430_JTAG | MSP430_SBW | LPC_ICP | SWJ);
......
    // SPI
    t->spi_init = versaloon_spi_init;
    t->spi_fini = versaloon_spi_fini;
    t->spi_config = versaloon_spi_config;
    t->spi_io = versaloon_spi_io;
......
    // GPIO
    t->gpio_init = versaloon_gpio_init;
    t->gpio_fini = versaloon_gpio_fini;
    t->gpio_config = versaloon_gpio_config;
    t->gpio_in = versaloon_gpio_in;
    t->gpio_out = versaloon_gpio_out;
......
}

Check whether the specified mode of the target is supported.
// init and check programmer's ability
i = cur_target->program_mode[program_info.mode].interface_needed;
if ((cur_programmer->interfaces & i) != i)
{
    LOG_ERROR(_GETTEXT("%s can not support %s in the mode defined.\n"),
              cur_programmer->name, cur_target->name);
    free_all_and_exit(EXIT_FAILURE);
}

And then, target related code could call the specified interfaces.
// init
spi_init();
reset_init();

// use avr8_isp_frequency
spi_conf(pi->frequency);

// toggle reset
reset_clr();
reset_output();
delay_ms(1);
reset_input();
delay_ms(1);
reset_clr();
reset_output();
delay_ms(10);

// enter into program mode command
cmd_buf[0] = 0xAC;
cmd_buf[1] = 0x53;
cmd_buf[2] = 0x00;
cmd_buf[3] = 0x00;
poll_byte = 0;
// ret[2] should be 0x53
spi_io(cmd_buf, 4, &poll_byte, 2, 1);      // send out 4 bytes in cmd_buf,
receive 1 byte from the 2nd byte into poll_byte
if ((ERROR_OK != commit()) || (poll_byte != 0x53))
{
    return ERRCODE_FAILURE_ENTER_PROG_MODE;
}

-- 
Best Regards, SimonQian
http://www.SimonQian.com
_______________________________________________
Openocd-development mailing list
Openocd-development@lists.berlios.de
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to