OpenOCD的remote_bitbang驱动分析

准备用Arduio来实现自己的jtag adapter,so分析分析remote_bitbang驱动。

 

在 interfaces.c 中,有一个BUILD_REMOTE_BITBANG的开关,在make之前,由configure 加入--enable-remote-bitbang开关

#if BUILD_REMOTE_BITBANG == 1
extern struct jtag_interface remote_bitbang_interface;
#endif

随后,在后续代码中注册:

/**
 * The list of built-in JTAG interfaces, containing entries for those
 * drivers that were enabled by the @c configure script.
 *
 * The list should be defined to contain either one minidriver interface
 * or some number of standard driver interfaces, never both.
 */
struct jtag_interface *jtag_interfaces[] = {
#if BUILD_ZY1000 == 1
 &zy1000_interface,
#elif defined(BUILD_MINIDRIVER_DUMMY)
 &minidummy_interface,
#else/* standard drivers */
#if BUILD_PARPORT == 1
 &parport_interface,
#endif
 
// 省略其他代码
 
#if BUILD_REMOTE_BITBANG == 1
 &remote_bitbang_interface,
#endif
 
// 省略其他代码
 
#endif /* standard drivers */
 NULL,
 };

然后,让我们一起来看看remote_bitbang.c里面的三个关键结构:

1.bitbang_interface

staticstruct bitbang_interface remote_bitbang_bitbang = {
 .read = &remote_bitbang_read,
 .write = &remote_bitbang_write,
 .reset = &remote_bitbang_reset,
 .blink = &remote_bitbang_blink,
};

2.command_registration

staticconststruct command_registration remote_bitbang_command_handlers[] = {
 {
 .name = "remote_bitbang_port",
 .handler = remote_bitbang_handle_remote_bitbang_port_command,
 .mode = COMMAND_CONFIG,
 .help = "Set the port to use to connect to the remote jtag.\n"
 " if 0 or unset, use unix sockets to connect to the remote jtag.",
 .usage = "port_number",
 },
 {
 .name = "remote_bitbang_host",
 .handler = remote_bitbang_handle_remote_bitbang_host_command,
 .mode = COMMAND_CONFIG,
 .help = "Set the host to use to connect to the remote jtag.\n"
 " if port is 0 or unset, this is the name of the unix socket to use.",
 .usage = "host_name",
 },
 COMMAND_REGISTRATION_DONE,
};

3.jtag_interface

struct jtag_interface remote_bitbang_interface = {
 .name = "remote_bitbang",
 .execute_queue = &bitbang_execute_queue,
 .commands = remote_bitbang_command_handlers,
 .init = &remote_bitbang_init,
 .quit = &remote_bitbang_quit,
};

我们从后往前分析:

jtag_interface是所有jtag的抽象接口,每一个具体的jtag实现,必须要定义自己的jtag_interface。定义好该结构后,在文章最前面提到的interfaces.c中注册,就算完成了该驱动的注册。

command_registration结构:用来注册jtag相关的命令及其handler实现。如remote_bitbang中的端口和host定义。

现在来到最关键的地方:

bitbang_interface,因为remote_bitbang也属于bitbang_interface,因此在此处定义的结构,属于该jtag专属的“业务逻辑”,系统发出的jtag命令,由该结构定义的函数来实现。

 

注意jtag_interface中的

.execute_queue = &bitbang_execute_queue,

所有实现了bitbang(如parallel)的jtag都调用的是相同的抽象函数bitbang_execute_queue

该函数位于bitbang.c中,代码不算长,该函数实现了真正的jtag控制逻辑:

int bitbang_execute_queue(void)
{
    struct jtag_command *cmd = jtag_command_queue;    /* currently processed command */
    int scan_size;
    enum scan_type type;
    uint8_t *buffer;
    int retval;
 
    if (!bitbang_interface) {
        LOG_ERROR("BUG: Bitbang interface called, but not yet initialized");
        exit(-1);
    }
 
    /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
     * that wasn't handled by a caller-provided error handler
     */
    retval = ERROR_OK;
 
    if (bitbang_interface->blink)
        bitbang_interface->blink(1);
 
    while (cmd) {
        switch (cmd->type) {
            case JTAG_RESET:
#ifdef _DEBUG_JTAG_IO_
                LOG_DEBUG("reset trst: %i srst %i",
                cmd->cmd.reset->trst,
                cmd->cmd.reset->srst);
#endif
                if ((cmd->cmd.reset->trst == 1) ||
                        (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
                    tap_set_state(TAP_RESET);
                bitbang_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
                break;
            case JTAG_RUNTEST:
#ifdef _DEBUG_JTAG_IO_
                LOG_DEBUG("runtest %i cycles, end in %s",
                        cmd->cmd.runtest->num_cycles,
                        tap_state_name(cmd->cmd.runtest->end_state));
#endif
                bitbang_end_state(cmd->cmd.runtest->end_state);
                bitbang_runtest(cmd->cmd.runtest->num_cycles);
                break;
 
            case JTAG_STABLECLOCKS:
                /* this is only allowed while in a stable state.  A check for a stable
                 * state was done in jtag_add_clocks()
                 */
                bitbang_stableclocks(cmd->cmd.stableclocks->num_cycles);
                break;
 
            case JTAG_TLR_RESET:
#ifdef _DEBUG_JTAG_IO_
                LOG_DEBUG("statemove end in %s",
                        tap_state_name(cmd->cmd.statemove->end_state));
#endif
                bitbang_end_state(cmd->cmd.statemove->end_state);
                bitbang_state_move(0);
                break;
            case JTAG_PATHMOVE:
#ifdef _DEBUG_JTAG_IO_
                LOG_DEBUG("pathmove: %i states, end in %s",
                        cmd->cmd.pathmove->num_states,
                        tap_state_name(cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]));
#endif
                bitbang_path_move(cmd->cmd.pathmove);
                break;
            case JTAG_SCAN:
#ifdef _DEBUG_JTAG_IO_
                LOG_DEBUG("%s scan end in %s",
                        (cmd->cmd.scan->ir_scan) ? "IR" : "DR",
                    tap_state_name(cmd->cmd.scan->end_state));
#endif
                bitbang_end_state(cmd->cmd.scan->end_state);
                scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
                type = jtag_scan_type(cmd->cmd.scan);
                bitbang_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
                if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
                    retval = ERROR_JTAG_QUEUE_FAILED;
                if (buffer)
                    free(buffer);
                break;
            case JTAG_SLEEP:
#ifdef _DEBUG_JTAG_IO_
                LOG_DEBUG("sleep %" PRIi32, cmd->cmd.sleep->us);
#endif
                jtag_sleep(cmd->cmd.sleep->us);
                break;
            case JTAG_TMS:
                retval = bitbang_execute_tms(cmd);
                break;
            default:
                LOG_ERROR("BUG: unknown JTAG command type encountered");
                exit(-1);
        }
        cmd = cmd->next;
    }
    if (bitbang_interface->blink)
        bitbang_interface->blink(0);
 
    return retval;
}

 

有如下jtag驱动是用bitbang来实现的:

./jtag/drivers/at91rm9200.c
./jtag/drivers/ep93xx.c
./jtag/drivers/bitbang.c
./jtag/drivers/dummy.c
./jtag/drivers/bcm2835gpio.c
./jtag/drivers/parport.c
./jtag/drivers/remote_bitbang.c
./jtag/drivers/sysfsgpio.c

你可能感兴趣的:(OpenOCD的remote_bitbang驱动分析)