在当今电子科技飞速发展的时代, MCU 芯片成为众多企业追求技术突破与创新的关键领域。而芯片的调试过程则是确保其性能与可靠性的重要环节。本文以国科安芯自研 AS32A601为例,旨在详细记录基于 RISC-V 架构的 MCU 芯片JTAG 调试过程及操作,为后续类似调试工作提供详实参考的依据,助力研发团队高效推进芯片研发进程。
RISC-V 架构以其开源、模块化等优势在 MCU 芯片领域崭露头角。JTAG(Joint Test Action Group)调试技术作为芯片调试的主流手段之一,为我们深入芯片内部、精准定位问题提供了有力支持。
我们将深入记录 MCU 芯片AS32A601在 JTAG 调试过程中的具体操作步骤。从硬件连接的细节,包括如何正确设置 JTAG 接口与仿真器的连接,确保信号传输的稳定与准确;到软件调试工具的配置与使用技巧,如调试环境的搭建、调试指令的编写与执行等,都将一一呈现。同时,针对调试过程中可能遇到的常见问题,如通信故障、数据读取错误等,也会详细分析原因并提供相应的解决方法。
通过这份详尽的记录,我们期望为后续的芯片研发与调试工作积累宝贵经验,帮助研发团队更加高效、精准地完成自研 MCU 芯片的开发与优化任务。这不仅有助于提升芯片产品的质量和性能,也对推动整个团队在 RISC-V 架构领域的技术进步具有重要意义,为未来在复杂芯片设计与调试领域的深入探索奠定坚实基础。
JTAG简介
接口
引脚 | 说明 |
TCK | 时钟信号。上升沿捕获输入,下降沿变更输出。 |
TMS | 状态选择,仿真器在 TCK 下降沿输出,被测芯片在 TCK 上升沿捕获 |
TDI | 串行数据输入,仿真器在 TCK 下降沿输出,被测芯片在 TCK 上升沿捕获 |
TDO | 串行数据输出,被测芯片在 TCK 下降沿输出,仿真器在 TCK 上升沿捕获 |
TRSTN | 复位信号,一般是低电平有效 |
TCK 应接下拉电阻,按照 IEEE 1149.1 的要求,被测芯片在 TCK 保持低电平的情况下将保持原有的状态,所以 TCK 应该拉低,确保在没有接仿真器时 TCK 是低电平状态。
TMS 应接上拉电阻,根据 TAP 状态机,任意状态下,只要 TMS 保持高电平 5 个时钟,那么就会进入复位状态,所以 TMS 拉高是安全的。
TAP状态机
所有JTAG操作的源头都是由一个具有16个状态的同步状态机控制。该控制器使用TCK作为时钟,使用TMS作为输入。如果需要复位时使用TRSTN。状态的跳转是由TMS输入1或0决定。 JTAG的TAP状态机
状态机介绍: 寄存器可以分为两大类,数据寄存器和指令寄存器。 标识有DR的这些状态是用来访问数据寄存器的,标识有IR的这些状态是用来访问指令寄存器的。
常用的状态说明如下所示:
-
Test-Logic-Select(TLS):系统上电后,TAP Controller 自动进入该状态。在该状态下,测试部分的逻辑电路全部被禁用,以保证芯片核心逻辑电路的正常工作。通过 TRST 信号也可以对测试逻辑电路进行复位,使得 TAP Controller 进入 Test-Logic Reset 状态。TRST 是可选的一个信号接口,这是因为在 TMS 上连续加 5 个 TCK 脉冲宽度的“1”信号也可以对测试逻辑电路进行复位,使得 TAP Controller 进入 Test-Logic Reset 状态。所以,在不提供 TRST信号的情况下,也不会产生影响。在该状态下,如果 TMS 一直保持为“1”,TAP Controller将保持在 Test-Logic Reset 状态下;如果 TMS 由“1”变为“0”(在 TCK 的上升沿触发), 将使 TAP Controller 进入 Run-Test/Idle 状态。
-
Run-Test/Idle:这个是 TAP Controller 在不同操作间的一个中间状态。这个状态下的动作取决于当前指令寄存器中的指令。有些指令会在该状态下执行一定的操作,而有些指令在该状态下不需要执行任何操作。在该状态下,如果 TMS 一直保持为“0”,TAP Controller 将一直保持在 Run-Test/Idle 状态下;如果 TMS 由“0”变为“1”(在 TCK 的上升沿触发),将使 TAPController 进入 Select-DR-Scan 状态。
-
Select-DR-Scan:这是一个临时的中间状态。如果 TMS 为“0” (在 TCK 的上升沿触发),TAP Controller进入 Capture-DR 状态,后续的系列动作都将以数据寄存器作为操作对象;如果 TMS 为“1” (在 TCK 的上升沿触发),TAP Controller 进入 Select-IR-Scan 状态。
-
Capture-DR:当 TAP Controller 在这个状态中,且当前指令是SAMPLE/PRELOAD指令,那么边界扫描寄存器BSR在TCK信号的上升沿捕 获输入管脚的数据。如果此时不是SAMPLE/PRELOAD指令,那么BSR保持它们先前的值,另外BSR的值被放入连接在TDI和TDO管脚之间的移 位寄存器中。如果 TMS 为“0” (在 TCK 的上升沿触发),TAP Controller 进入 Shift-DR 状态;如果 TMS 为“1” (在 TCK 的上升沿触发),TAPController 进入 Exit1-DR 状态。
-
Shift-DR:在这个状态中,由 TCK 驱动,每一个时钟周期,被连接在 TDI 和 TDO 之间的数据寄存器将从 TDI 接收一位数据,同时通过 TDO 输出一位数据。如果 TMS 为“0” (在 TCK的上升沿触发),TAP Controller 保持在 Shift-DR 状态; 如果 TMS 为“1” (在 TCK 的上升沿触发),TAP Controller 进入到 Exit1-DR 状态。假设当前的数据寄存器的长度为 4。如果 TMS 保持为 0,那在 4 个 TCK 时钟周期后,该数据寄存器中原来的 4 位数据(一般是在 Capture-DR 状态中捕获的数据)将从 TDO 输出来;同时该数据寄存器中的每个寄存器单元中将分别获得从 TDI 输入的 4 位新数据。
-
Exit1-DR:Exit1-DR是TAP控制器的一个临时状态,如果TMS信号在下一个TCK上升沿处于高电平,TAP进入Update-DR状态;如果TMS信号在下一个TCK上升沿处于低电平,则TAP进入Pause-DR状态。处于Exit1-DR状态时,指令不会被改变。
-
Pause-DR: Pause-DR状态允许TAP控制器暂时停止TDI-移位寄存器-TDO串行通道的移位操作。处于Pause-DR状态时,指令不会被改变。如果TMS信号在下一个TCK上升沿处于高电平,TAP进入Exit2-DR状态;如果TMS信号处于低电平,则TAP一直保持暂停状态。
-
Exit2-DR:Exit2-DR也是TAP控制器的临时状态,如果TMS信号在下一个TCK上升沿处于高电平,TAP进入Update-DR状态,结束扫描操作;如果TMS信号在下一个TCK上升沿处于低电平,则TAP重新进入Shift-DR状态。处于Exit2-D状态时,指令不会被改变。
-
Update-DR:在 Update-DR 状态下,由 TCK 上升沿驱动,数据寄存器当中的数据将被加载到相应的芯片管脚上去,用以驱动芯片。在该状态下,如果 TMS 为“0”,TAP Controller 将回到Run-Test/Idle 状态;如果 TMS 为“1”,TAP Controller 将进入 Select-DR-Scan 状态。
-
Select-IR-Scan:这是一个临时的中间状态。如果 TMS 为“0” (在 TCK 的上升沿触发),TAP Controller进入 Capture-IR 状态,后续的系列动作都将以指令寄存器作为操作对象;如果 TMS 为“1” (在 TCK 的上升沿触发),TAP Controller 进入 Test-Logic Reset 状态。
-
Capture-IR:当 TAP Controller 在这个状态中,在 TCK 的上升沿,一个特定的逻辑序列将被装载到指令寄存器中去。如果 TMS 为“0” (在 TCK 的上升沿触发),TAP Controller 进入 Shift-IR状态;如果 TMS 为“1” (在 TCK 的上升沿触发),TAP Controller 进入 Exit1-IR 状态。
-
Shift-IR:在这个状态中,由 TCK 驱动,每一个时钟周期,被连接在 TDI 和 TDO 之间的指令寄存器将从 TDI 接收一位数据,同时通过 TDO 输出一位数据。如果 TMS 为“0” (在 TCK的上升沿触发),TAP Controller 保持在 Shift-IR 状态; 如果 TMS 为“1” (在 TCK 的上升沿触发),TAP Controller 进入到 Exit1-IR 状态。假设指令寄存器的长度为 4。如果TMS 保持为 0,那在 4 个 TCK 时钟周期后,指令寄存器中原来的 4bit 长的特定逻辑序列(在 Capture-IR 状态中捕获的特定逻辑序列)将从 TDO 输出来,该特定的逻辑序列可以用来判断操作是否正确;同时指令寄存器将获得从 TDI 输入的一个 4bit 长的新指令。
-
Exit1-IR:Exit1-IR是TAP控制器的一个临时状态,如果TMS信号在下一个TCK上升沿处于高电平,TAP进入Update-IR状态;如果TMS信号在下一个TCK上升沿处于低电平,则TAP进入Pause-IR状态。处于Exit1-IR状态时,指令不会被改变。
-
Pause-IR:Pause-IR状态允许TAP控制器暂时停止TDI-移位寄存器-TDO串行通道的移位操作。处于Pause-IR状态时,指令不会被改变。如果TMS信号在下一个TCK上升沿处于高电平,TAP进入Exit2-IR状态;如果TMS信号处于低电平,则TAP一直处于暂停状态。
-
Exit2-IR:Exit2-IR也是TAP控制器的临时状态,如果TMS信号在下一个TCK上升沿处于高电平,TAP进入Update-IR状态,结束扫描操作;如果TMS信号在下一个TCK上升沿处于低电平,则TAP重新进入Shift-IR状态。处于Exit2-D状态时,指令不会被改变。
-
Update-IR:在这个状态中,在 Shift-IR 状态下输入的新指令将被用来更新指令寄存器。
JTAG访问的一般过程:
-
系统上电,TAP Controller 进入 Test-Logic Reset 状态,然后依次进入:Run-Test/Idle → Select-DR-Scan → Select-IR-Scan →Capture-IR →Shift-IR →Exit1-IR→Update-IR,最后回到 Run-Test/Idle 状态。在 Capture-IR 状态中,一个特定的逻辑序列被加载到指令寄存器当中;然后进入到 Shift-IR 状态。在 Shift-IR 状态下,通过 TCK 的驱动,可以将一条特定的指令送到指令寄存器当中去。每条指令都将确定一条相关的数据寄存器。然后从 Shift-IR →Exit1-IR → Update-IR。在 Update-IR 状态,刚才输入到指令寄存器中的指令将用来更新指令寄存器。最后,进入到 Run-Test/Idle 状态,指令生效,完成对指令寄存器的访问。
-
当前可以访问的数据寄存器由指令寄存器中的当前指令决定。要访问由刚才的指令选定的数据寄存器,需要以 Run-Test/Idle 为起点,依次进入 Select-DR-Scan →Capture-DR →Shift-DR →Exit1-DR →Update-DR,最后回到 Run-Test/Idle 状态。在这个过程当中,被当前指令选定的数据寄存器会被连接在 TDI 和 TDO 之间。通过TDI 和 TDO,就可以将新的数据加载到数据寄存器当中去,同时,也可以捕获数据寄存器中的数据。具体过程如下。在 Capture-DR 状态中,由 TCK 的驱动,芯片管脚上的输出信号会被“捕获”到相应的边界扫描寄存器单元中去。这样,当前的数据寄存器当中就记录了芯片相应管脚上的输出信号。接下来从 Capture-DR 进入到Shift-DR 状态中去。在 Shift-DR 状态中,由 TCK 驱动,在每一个时钟周期内,一位新的数据可以通过 TDI 串行输入到数据寄存器当中去,同时,数据寄存器可以通过TDO 串行输出一位先前捕获的数据。在经过与数据寄存器长度相同的时钟周期后,就可以完成新信号的输入和捕获数据的输出。接下来通过 Exit1-DR 状态进入到Update-DR 状态。在 Update-DR 状态中,数据寄存器中的新数据被加载到与数据寄存器的每个寄存器单元相连的芯片管脚上去。最后,回到 Run-Test/Idle 状态,完成对数据寄存器的访问。
debug寄存器
目前RISC-V的官方调试上位机是openocd,调试工具可以是JLink或者CMSIS-DAP,RISCV调试框架如图所示。 RISC-V调试系统框架
DTM模块
作为DTM使用的JTAG tap必须具有至少5位的IR。当TAP时,IR必须默认为00001,选择IDCODE指令。DTM模块的寄存器定义如图所示。 DTM寄存器
IDCODE寄存器(0x01)
当TAP状态机复位时,IR寄存器的值默认为0x01,即选择的是IDCODE寄存器。IDCODE寄存器的每一位含义如图5所示。IDCODE是只读寄存器。 IDCODE寄存器
Version:只读,版本号,可为任意值。 PartNumber:只读,可为任意值。 Manufld:只读,厂商号,遵循JEP106标准分配,实际中可为任意值,只要不与已分配的厂商号冲突即可。
DTM控制和状态寄存器(dtmcs,0x10)
dtmcs寄存器
dmihardreset:DTM模块硬复位,写1有效。 dmireset:清除出错,写1有效。 idle:只读,JTAG 主机在Run-Test-Idle状态停留的时钟周期数,0表示不需要进入Run-Test-Idle状态,1表示进入 Run-Test-Idle状态后可以马上进入下一个状态,以此类推。 dmistat:只读,上一次操作的状态。0表示无出错,1或者2表示操作出错,3表示操作还未完成。 abits:只读,dmi寄存器中address域的大小(位数)。 version:只读,实现所对应的spec版本,0表示0.11版本,1表示0.13版本。
DM模块接口访问寄存器(dmi,0x11)
dmi寄存器
address:可读可写,DM寄存器的长度(位数)。 data:可读可写,往DM寄存器读、写的数据,固定为32位。 op:可读可写,读或者写这个域时有不同的含义。当写这个域时,写0表示忽略address和data的值,相当于nop操作;写1表示从address指定的寄存器读数据;写2表示把data的数据写到address指定的寄存器。写3为保留值。当读这个域时,0表示上一个操作正确完成;1为保留值;2表示上一个操作失败,这个状态是会被记住的,因此需要往dtmcs寄存器的dmireset域写1才能清除这个状态。3表示上一个操作还未完成。
在Update-DR状态时,DTM开始执行op指定的操作。在Capture-DR状态时,DTM更新data域。
BYPASS寄存器(0x1f)
只读,长度为1,值固定为0。
DM模块
DM模块的寄存器都为32位,定义如图所示(只描述主要寄存器)。
data0寄存器(0x04)
此寄存器是用于abstract command的数据寄存器,长度为32位,可读可写。
dmcontrol寄存器(0x10)
dmcontrol寄存器
haltreq:只写,写1表示halt(暂停)当前hart(hart表示CPU核,存在多核的情况)。 resumereq:只能写1,写1表示resume(恢复)当前hart,即go。 hartreset:可读可写,写1表示复位DM模块,写0表示撤销复位,这是一个可选的位。 ackhavereset:只能写1,写1表示清除当前hart的havereset状态。 hasel:可读可写,0表示当前只有一个已经被选择了的hart,1表示当前可能有多个已经被选择了的hart。 hartsello:可读可写,当前选择的hart的低10位。1位表示一个hart。 hartselhi:可读可写,当前选择的hart的高10位。1位表示一个hart。如果只有一个hart,那么hasel的值为0, hartsello的值为1,hartselhi的值为0。 setresethaltreq:只能写1,写1表示当前选择的hart复位后处于harted状态。 clrresethaltreq:只能写1,写1表示清除setresethaltreq的值。 ndmreset:可读可写,写1表示复位整个系统,写0表示撤销复位。 dmactive:可读可写,写0表示复位DM模块,写1表示让DM模块正常工作。正常调试时,此位必须为1。
dmstatus寄存器(0x11)
dmstatus寄存器
impebreak:1表示执行完progbuf的指令后自动插入一条ebreak指令,这样就可以节省一个progbuf。当progbufsize的 值为1时,此值必须为1。 allhavereset:1表示当前选择的hart已经复位。 anyhavereset:1表示当前选择的hart至少有一个已经复位。 allresumeack:1表示当前选择的所有hart已经应答上一次的resume请求。 anyresumeack:1表示当前选择的hart至少有一个已经应答上一次的resume请求。 allnonexistent:1表示当前选择的hart不存在于当前平台。 anynonexistent:1表示至少有一个选择了的hart不存在于当前平台。 allunavail:1表示当前选择的hart都不可用。 anyunavail:1表示至少有一个选择了的hart不可用。 allrunning:1表示当前选择的hart都处于running状态。 anyrunning:1表示至少有一个选择了的hart处于running状态。 allhalted:1表示当前选择的hart都处于halted状态。 anyhalted:1表示至少有一个选择了的hart处于halted状态。 authenticated:0表示使用DM模块之前需要进行认证,1表示已经通过认证。 authbusy:0表示可以进行正常的认证,1表示认证处于忙状态。 hasresethaltreq:1表示DM模块支持复位后处于halted状态,0表示不支持。 confstrptrvalid:1表示confstrptr0~3寄存器保存了配置字符串的地址。 version:0表示DM模块不存在,1表示DM模块的版本为0.11,2表示DM模块的版本为0.13。
abstractcs寄存器(0x16)
abstractcs寄存器
progbufsize:只读,program buffer的个数,取值范围为0~16,每一个的大小为32位。 busy:只读,1表示abstract命令正在执行,当写command寄存器后该位应该马上被置位直到命令执行完成。 cmderr:可读、只能写1,cmderr的值仅当busy位为0时有效。0表示无错误,1表示正在操作command、abstractcs、 data或者progbuf寄存器,2表示不支持当前命令,3表示执行命令时出现异常,4表示由于当前hart不可用,或者不是处 于halted/running状态而不能被执行,5表示由于总线出错(对齐、访问大小、超时)导致的错误,7表示其他错误。写1清 零cmderr。 datacount:只读,所实现的data寄存器的个数。
command寄存器(0x17)
当写这个寄存器时,相应的操作就会被执行,command寄存器只能写。 command寄存器
cmdtype:只写,命令类型,0为表示访问寄存器,1表示快速访问,2表示访问内存。 control:只写,不同的命令类型有不同的含义,说明如下。
当cmdtype为0时,control定义下图所示。
cmdtype:值为0。 aarsize:2表示访问寄存器的最低32位,3表示访问寄存器的最低64位,4表示访问寄存器的最低128位。如果大于实际寄存器的大小则此次访问是失败的。 aarpostincrement:1表示成功访问寄存器后自动增加regno的值。 postexec:1表示执行progbuf里的内容(指令)。 transfer:0表示不执行write指定的操作,1表示执行write指定的操作。 write:0表示从指定的寄存器拷贝数据到arg0指定的data寄存器。1表示从arg0指定的data寄存器拷贝数据到指定的寄存器。 regno:要访问的寄存器。
综上,可知:
-
当write=0,transfer=1时,从regno指定的寄存器拷贝数据到arg0对应的data寄存器。
-
当write=1,transfer=1时,从arg0对应的data寄存器拷贝数据到regno指定的寄存器。
-
当aarpostincrement=1时,将regno的值加1。
-
当postexec=1时,执行progbuf寄存器里的指令。
当cmdtype为1时,control定义下图所示。
cmdtyte:值为1。
此命令会执行以下操作:
-
halt住当前hart。
-
执行progbuf寄存器里的指令。
-
resume当前hart。
当cmdtype为2时,control定义下图所示。
cmdtype:值为2。 aamvirtual:0表示访问的是物理地址,1表示访问的是虚拟地址。 aamsize:0表示访问内存的低8位,1表示访问内存的低16位,2表示访问内存的低32位,3表示访问内存的低64位,4表示访问内存的低128位。 aampostincrement:1表示访问成功后,将arg1对应的data寄存器的值加上aamsize对应的字节数。 write:0表示从arg1指定的地址拷贝数据到arg0指定的data寄存器,1表示从arg0指定的data寄存器拷贝数据到arg1指 定的地址。 target-specific:保留。
综上,可知:
-
当write=0时,从arg1指定的地址拷贝数据到arg0指定的data寄存器。
-
当write=1时,从arg0指定的data寄存器拷贝数据到arg1指定的地址。
-
当aampostincrement=1时,增加arg1对应的data寄存器的值。
abstractauto寄存器(0x18)
abstractauto寄存器
autoexecprogbuf:当该字段中的一个位为1时,对对应进程单词的读写访问会导致DM在进程访问完成后将命令中的当前值再次写入其中。 autoexecdata:当该字段中的一个位为1时,对相应数据字的读写访问会导致DM在数据访问完成后将命令中的当前值再次写入那里。
progbuf0寄存器(0x20)
progbuf0寄存器
progbuf寄存器必须提供program buffer的写访问权限,debugger可通过这些寄存器对program buffer读访问,读不支持时返回0。 progbufsize 表示从progbuf0开始实现多少progbuf寄存器。 在执行抽象命令时访问这些寄存器时,如果cmderr为0,则会将其设置为1(busy)。 在busy时尝试编写它们不会改变它们的值。
操作流程
debug读写内存和寄存器步骤
Reading Memory
使用 Program Buffer 从内存中读取数据
program buffer 方式读取单字
program buffer 方式读取块
Writing Memory
使用 Program Buffer 往内存中写入数据
program buffer 方式写单字
program buffer方式写块
debug实际运行状态
逻辑分析仪解析JTAG协议配置
注:TDI为仿真器输入信号,TDO为仿真器输出信号。
读取内存步骤
本例:读取0x20000000地址的数据,以openocd指令操作为例(指令操作为mdw 0x20000000),返回数据为0x100002bc。
-
此波形为操作dmi(0x11)寄存器,向progbuf0寄存器写入lw s0, 0(s0)指令(以gcc/openocd操作为例)。
2.此波形为nop操作。
3.此波形为操作dmi(0x11)寄存器,向progbuf1寄存器写入ebreak指令(以gcc/openocd操作为例)。
4. 此波形为nop操作。
5. 此波形为操作dmi(0x11)寄存器,向data0寄存器写数据0x20000000,表示要写入要读取的地址。
6. 此波形为nop操作。
7. 此波形为操作dmi(0x11)寄存器,从而操作command(0x17)寄存器,从而进行执行progbuf寄存器里的指令、data0数据写入s0的操作。
8. 此波形为操作dmi(0x11)寄存器,发送读取abstractcs(0x16)寄存器操作。
9. 此波形为nop操作,通过TDO线数据获取状态正常。
10. 此波形为操作dmi(0x11)寄存器,从而操作command(0x17)寄存器,从而进行将s0的数据拷贝到data0的操作。
11. 此波形为操作dmi(0x11)寄存器,发送读取abstractcs(0x16)寄存器操作。
12. 此波形为nop操作,通过TDO线数据获取状态正常。
13. 此波形为操作dmi(0x11)寄存器,进行读取data0寄存器的操作。
14. 此波形为nop操作,通过TDO线数据获取要读取内存地址的数据:0x100002bc。
上述流程描述了通过Program Buffer方式读内存操作,实际操作中会加入读取状态寄存器等操作,确保操作正常。mdw实际操作还会加入保存恢复s0寄存器,执行fence指令等,这里不进行过多描述。
写内存步骤
本例:向0x20000000地址写入数据0x12345678,以openocd指令操作为例(指令操作为mww 0x20000000 0x12345678)。
-
此波形为操作dmi(0x11)寄存器,向progbuf0寄存器写入sw s1,0(s0)指令(以gcc/openocd操作为例)。
2. 此波形为nop操作
3.此波形为操作dmi(0x11)寄存器,向progbuf1寄存器写入addi s0, s0, 4指令(以gcc/openocd操作为例)。
4. 此波形为nop操作
5. 此波形为操作dmi(0x11)寄存器,向data0寄存器写数据0x20000000,表示要写入要操作的地址。
6. 此波形为nop操作
7. 此波形为操作dmi(0x11)寄存器,从而操作command(0x17)寄存器,从而进行data0数据写入s0的操作。
8. 此波形为操作dmi(0x11)寄存器,发送读取abstractcs(0x16)寄存器操作。
9. 此波形为nop操作,通过TDO线数据获取状态正常。
10. 此波形为操作dmi(0x11)寄存器,向data0寄存器写数据0x12345678,表示要写入0x20000000地址的数据。
11. 此波形为nop操作
12. 此波形为操作dmi(0x11)寄存器,从而操作command(0x17)寄存器,从而进行执行progbuf寄存器里的指令,data0数据写入s1的操作。
13. 此波形为操作dmi(0x11)寄存器,发送读取abstractcs(0x16)寄存器操作。
14. 此波形为nop操作,通过TDO线数据获取状态正常。
上述流程描述了通过Program Buffer方式写内存操作,实际操作中会加入读取状态寄存器等操作,确保操作正常。mww实际操作还会加入保存恢复s0寄存器,执行fence指令等,这里不进行过多描述。
此流程为可以连续操作内存的一个步骤,下面将进行操作的讲解:
-
sw s1,0(s0)指令为将s1的值写入到s0地址。
-
addi s0, s0, 4指令为执行一次操作后地址增加4字节。
-
此步骤没有ebreak指令,能正常运行的原因是debug支持执行完progbuf指令自动添加ebreak指令,此设置可以查看dmstatus(0x11)寄存器impebreak位。
-
连续操作步骤为编程abstractauto(0x18)寄存器,可以在写完data0寄存器后自动执行progbuf的指令。
连接时循环查询状态
-
此波形为操作dmi(0x11)寄存器,发送读取dmstatus(0x11)寄存器操作。
2. 此波形为nop操作,通过TDO线数据获取cpu状态为halted状态。