头图

前言

  • 1)前面几节我们学习了 ① ~ ③ 中的解析命令行参数与解析配置文件,接下来我们来看一下剩余的 ④ ~ ⑥ 部分:server_init() 函数、init 命令和 server_loop() 函数:

1 server_init()

  • 1)server_init() 的执行逻辑如下:
  • 2)总的来说,添加了两个 service 到 struct service *services; 链表中:

    • (1)tcl_service:应该是与 tcl 语法相关的 tcp 连接,暂时未用到
    • (2)telnet_service:创建 telnet 相关的 tcp 连接,主要作用是让我们可以通过 telnet 连接到 OpenOCD 服务端,OpenOCD 支持的所有命令均可以在 telnet 连接后执行,也是我编写芯片烧录驱动的主要测试方式。

2 执行 init 命令

  • 1)OpenOCD 通过 command_run_line(ctx, "init") 执行 init 命令的逻辑如下:
这可能就是所谓的冰山一角吧:看着是一条 init 命令,其实内部执行一系列的初始化操作。

2.1 target init

  • 1)target init 命令的大概执行逻辑如下:
  • 2)init_targets、init_target_events、init_board 三个命令是定义在 src/target/startup.tcl 文件中三个调用过程 proc。可以让用户在初始化过程中的进行功能补充。
  • 3)接下来在 target_init() 函数中,主要有以下内容:

    • (1)根据全局变量 struct target *all_targets; 遍历所有 target,并通过 target->type->init_target() 函数指针进行 target_type 的初始化,最后对 target_type 进行其它属性填充。关于 target_type,上一节中创建 target 时,我们提到:

    • (2)通过 target_register_user_commands() 函数注册 target 相关命令,如 target_request debugmsgs,trace history, reg/poll/halt/resume/reset/mdd[w/h/b]/mwd[w/h/b]/verify_image 等等
    • (3)通过将 handle_target() 函数指针注册给 target_timer_callbacks,获得处理 srst 与 power 事件的能力。
  • 4)关于 target_type->init_target() 的初始化,以 cortexm_target 为例:

    • 百度上说,Semihosting 技术是将目标板的输入/输出请求从应用程序代码传递到远程运行调试器的主机的一种机制。

2.2 adapter_init()

  • 1)adapter 初始化的逻辑如下(右侧还是以 cmsis-dap 为例):
  • 2)首先进行 adapter_driver 的初始化(这里为 cmsis-dap),都是 cmsis-dap 相关的细节,有时间我们再通过 DAPLink 项目深入学习。
  • 3)然后是设置 adapter 的速度。这里首先设置速度,然后会再读取 adapter 的实际速度。

2.3 其它命令

剩余的命令就不再一一分析了,这里仅列出命令的执行函数入口以供有兴趣者研究。
commandhandler function entrylocation概要说明
transport inithandle_transport_init()src/transport/transport.c对命令 'transport select \<transport\>' 中的 \<transport\> 进行初始化,包括 swd、jtag 等
dap inithandle_dap_init()src/target/arm_dap.c对 DAP(Debug Access Port)进行初始化。
flash inithandle_flash_init_command()src/flash/nor/tcl.c注册了许多 flash 开头的命令,如检测命令 flash probe、擦除扇区命令 flash erase_check 等
nand inithandle_nand_init_command()src/flash/nand/tcl.c注册了许多 nand 开头的命令,可能是操作 nand 类存储设备的命令
pld inithandle_pld_init_command()src/pld/pld.cpld,Programmable Logic Device,不太明白,不敢妄言
tpiu inithandle_arm_tpiu_swo_init()src/target/arm_tpiu_swo.c完全不懂
以上命令不再作解析,因为有些内容我实在搞不明白,这里仅做逻辑记录,待日后有机会再深入了解。

3 server_loop()

  • 1)该函数遍历 service,并以 select 的方式对其内部的 socket 进行轮询。
  • 2)从前面几章我们知道,OpenOCD 中一共有以下几种 service:
名称端口简述
gdb service3333用于 gdb 调试
telnet service4444执行擦除、烧录、读取等命令
jtag vpi5555没用到过,不了解
tcl service6666猜测是用来执行 tcl 文件中命令的
jsp service7777没用到过,不了解
rtt servicexxxxReal Time Transfer,类比 SEGGER 的 RTT,通过 rtt start <port> <channel> [message] 指定
通过 telnet ip:port 连接到 OpenOCD 后,根据连接的端口,由对应的 Service 进行命令处理。我们已经了解通过 4444 端口的烧录等命令处理。
下一次,我们将了解通过 RTT service 来打印 DAPLINK 日志的方式。

送南阳马生序
7 声望3 粉丝

余之业有不精、德有不成,非天质之卑,则心不若他之专耳,岂他人之过哉!