赞
踩
芯片验证工程师
32 人赞同了该文章
一文帮你彻底搞懂ARM Debug Interface之SWD - 知乎
ARM的文档写的已经很好了,但是关于上电以后的第一时间应该怎么操作,依然写的不够清晰,导致我第一次用的时候还是费了一些周折。今天做一个详细的梳理,希望能够帮助到更多的朋友。BTW, ARM_Cortex-M0/3 DesignStart系列会持续更新,只是中间可能会穿插其他知识点。
SWD是Serial Wire Debug的简称,翻译成中文是”串行线调试”。 SWD是ARM目前支持的两种调试端口之一,另一个调试端口叫做JTAG Debug Port,也就是我们常用的J-link上面的调试端口(JTAG模式下)。基于ARM CoreSight调试构架,SWD可以通过传输数据包来读写芯片的寄存器。SWD是用于访问ARM调试接口的双线协议。它是ARM调试接口规范(ARM Debug Interface Architecture Specification)的一部分,是JTAG的替代品。SWD的物理层由两条线组成:
SWDIO: 双向数据线
SWCLK: host驱动的时钟线
下图是SWD的简易连接图:
外部设备(如调试探针)通过连接到SWDIO/SWCLK,可以直接访问串行线调试端口(SW-DP)。SW-DP可以访问一个或多个接入端口(AP),通过AP可以访问系统的其余部分寄存器。 Cortex M系列CPU的一个重要AP是AHB-AP,它是内部AHB总线上的主机。换句话说,AHB-AP可以访问内部核心的内存映射。由于内部闪存、SRAM、调试组件和外围设备都是内存映射,因此AHB-AP可以控制整个设备,包括对其进行编程。整个SWD操作过程是分级进行的,时钟信号由SWCLK 管脚输入,数据信号从SWDIO管脚输入输出。首先Debugger对SW-DP进行操作,确定AP寄存器的参数,达到对Cortex Memory Map进行操作。
下面三幅截图是ARM Debug Interface的连接实现示意图。如下图所示,DAP由两部分组成:DP和MEM-AP (就是通常所说的AP)。MEM-AP是一个统称,APB/AHB/AXI-AP都统称为MEM-AP。
SWCLK是始终由host驱动的时钟信号。双方将推动SWDIO线路发送数据,SWDIO上的高值表示逻辑“1”,低值表示逻辑的“0”。协议规定当双方都将驱动SWDIO线时,规定了三个不同的阶段。每个事务都以host发送请求为开始;Target随后以应答回应;最后是数据传输阶段。数据阶段由谁控制线路,取决于host发出的请求类型。如果host发出的是写请求,host将驱动SWDIO线。在读请求时,target将驱动SWDIO线,将数据从target传输到host。在所有阶段,数据都是首先传输LSB(最低有效位)。不管是target从SWDIO线上采样数据,还是驱动数据到SWDIO线上,都是在时钟SWCLK的上升沿进行。
外部的host debugger发送一个request(请求)给DP, DP就是这个请求的target
主机host发出的请求由 8bit 组成,具体如下图所示:
Bit0:Start,固定为 1。
Bit1:APnDP,0表示访问 DP 寄存器,1 表示访问 MEM-AP 寄存器。
Bit2:RnW,0表示写请求,1表示读请求。
Bit[4:3]:地址值A[3:2],存放DP/AP寄存器的地址。
Bit5:Parity,用于表示由{APnDP,RnW, A[2:3]}组成这四位数的奇偶总个数。
Bit6:Stop,固定为0。
Bit7:Park,固定为1。
Target返回的ACK值由3bit组成
ACK[0:2]==001,表示FAULT
ACK[0:2]==010,表示WAIT
ACK[0:2]==100,表示OK response
数据由32bit有效数据 + 1bit数据的奇偶校验位组成
SWD通信的时候主要涉及的寄存器就两个,一个DP(即Debug port),一个AP(即Access port)。如果要访问内核寄存器,访问顺序是DP ->AP -> Core Register。
DP寄存器如下图,地址就是我们在包头中的ADDR[2:3],这两位指示的地址。具体请参考《ARM Debug Interface v5 Architecture Specification》。
下图是根据ADI5的说明,网友自己制作的表格,更容易理解。
IDCODE:识别码寄存器,用于识别SW-DP。IDCODE寄存器提供有关SW-DP的标识信息。在具有Cortex-M3或Cortex-M4内核的设备上,该寄存器应为0x2BA01477。对于具有CortexM0+内核的设备,该寄存器应该为0x0BC11477。更多优质内容,欢迎关注微信公众号《芯片验证日记》。
ABORT:中止寄存器,强制AP事务中止。在通信中,若发生粘性错 误位置1(ack = 4)。将0b1写入ABORT中,会生成一个DAP中止使当前AP事务中止。
ABORT寄存器的主要用途是强制DAP中止,在SW-DP上,它还用于清除错误和粘性标志条件。以下是AP ABORT寄存器每一位的定义。
如果希望找到导致标志设置为1的原因。通常:
对于STICKYCMP或STICKYARR标志,必须找到访问的位置,才能将标志设置为1。
对于WDATAERR标志,必须重新发送损坏的数据。
对于STICKYORUN标志,必须找到导致溢出的DP或AP事务。然后必须从那一点开始重复交易。
CTRL/STAT:控制状态寄存器,用于控制和获取有关DP的状态信息。
SELECT:AHB-AP选择寄存器,选择要访问的端口(AP)和AP中的bank地址和DP的bank地址。
RDBUFF:读缓冲寄存器,在SW-DP上,RDBUFF显示了在上一次AP读取期间捕获的数据,允许重复返回值而不生成新的AP访问。
值得说明的是,总线复位之后,需要先进行JTAG和SWD的切换操作(发送0x79E7或者0xE79E),然后必须先读下IDCODE,判断下MCU的类型,然后才能继续别的操作。
MEM-AP为DAP提供对内存子系统的访问。由于内存、外围设备和调试组件都是内存映射的,因此MEM-AP可用于对Cortex M0/M3等进行编程和调试。
AP寄存器相比较于DP寄存器复杂了很多。具体请参考《ARM Debug Interface v5 Architecture Specification》。
CSW:控制/状态字寄存器,CSW配置和控制通过MEM-AP访问连接的内存系统。size:32bit-0b010;16bit-0b001
TAR寄存器: 传送地址寄存器,保存要访问的内存地址。通过CSW寄存器的AddrInc字段中设置b01,成功访问DRW时,TAR的内容可以自动递增。
DRW:数据读/写寄存器,用于写入或读取TAR中地址的数据。DRW将AP访问中传递的值直接映射到TAR中指定的地址中的一个或多个内存访问。打算将值写入内存地址时,首先将地址写入TAR寄存器,然后将值写入DRW。打算要读取内存地址的数据时,首先将地址写入TAR,然后读取DRW中的值。
IDR:识别寄存器,IDR标识访问的端口。要读取此寄存器时,APBANKSEL字段应设置为0xF。然后可以使用地址0x0C读取IDR寄存器(ADDR[3:2]=b11)。对于具有Cortex-M3或Cortex-M4内核的设备,IDR寄存器应返回值0x24770011。在带有Cortex-M0+的设备上,它应该返回0x0477003。
下面截图中的是Cortex M3调试寄存器。使用调试寄存器,我们可以将Core设置为暂停模式,并可以更改Core寄存器,如SP或PC。
DHCSR=Debug Halting Control and Status Register
DHCSR控制处理器的暂停、单步和重启等动作。当C_DEBUGEN设置为1时,将启用暂停调试。更详细的信息,请参考《ARM Cortex-Mx权威指南》
D
CRSRregister = Debug Core Register Selector Register,provides debug access to the ARM core registers, special-purpose registers, and Floating-point extension registers. A write to DCRSR specifies the resister to transfer.
Debug Core Register Data Register, DCRDR寄存器提供对ARM核心寄存器、专用寄存器和浮点扩展寄存器的调试访问。DCRDR是这些访问的数据寄存器。
Debug Exception and Monitor Control Register, DEMCR register manages vector catch
behavior and DebugMonitor handling when debugging. Bits [23:16] provide DebugMonitor exception control. Bits [15:0] provide Debug state, halting debug, control.
Application Interrupt and Reset Control Register,AIRCR寄存器设置或返回中断控制数据。
2.4.1 成功的写时序
如下图所示,值得注意的是,trn(调转周期),因为我们是单总线通信,一根线上既有写又有读,而这个trn就是发生在写读切换的时候的一个延时。
ARM spec中的内容如下图所示,更多请参考《ARM Debug Interface v5 Architecture Specification ADIv5.0 to ADIv5.2》。
CSYSPWRUPREQ:System powerup request
CDBGPWRUPREQ:Debug powerup request
比如,写入的数据为0x000000F0。意味着APSEL=0x00,表示AHB访问;APBANKSEL=0xF,表示选择当前AP的bank地址;DPBANKSEL=0x0,表示DP.CTRL
3) 读取IDR寄存器(addr = 0xFC)的数据并验证
IDR也就是AP寄存器的IDCODE,IDR寄存器是只读寄存器,IDR寄存器存在于AP寄存器空间的偏移地址0xFC处,IDR值为零表示不存在AP。读取IDR寄存器的数值时,需要读两次,第一次是dummy read,第二次读取到的才是正确的数据。(第二次也可以读RDBUFF寄存器)。
4) CSW寄存器写入0x00000002,data_size:32bit
Size:访问MEM-AP的数据类型的大小
其中:如果寄存器的数据是32bit,CSW.Size=’b010,如果编程写入的数据是16bit, CSW.Size=’b001。
3.3 读写操作
如果想要写入/读出芯片内部Flash/Sram/Register的数值,需要用到两个AP寄存器:TAR(Transfer Address Register)和DRW(Data Read/Write Register)。
上面截图中说的很清楚,TAR寄存器中的地址,不是AP内部的地址,而是与AP连接的芯片系统中的物理地址。
DRW寄存器将AP访问直接映射到一个或多个芯片系统内部的memory访问。在memory访问完成之前,AP访问不会完成。
DRW寄存器是R/W(可读可写)的,它在MEM-AP寄存器空间中的偏移量是0x0C。
在写入模式下,DRW将当前传输的值写入TAR中指定的地址。
在读取模式下,DRW保存从TAR中指定的地址读取的当前传输值。
1) 在TAR寄存器中写入要访问的内存地址数值 (比如addr = 0x08000000)
2) 在DRW寄存器中写入要往芯片的memory中写入的数据 (比如data = 0x12345678)
1) 在TAR寄存器中写入要访问的内存地址数值 (比如addr = 0x08000000)
2) 从DRW寄存器中读取要访问的内存中存放的数据
3) 从RDBUFF寄存器(DP)中读取数据,或者第二次从DRW寄存器(AP)中读取数据
3.4 读写时的注意事项:
由于读取AP寄存器的特殊性,当读取AP寄存器时,返回的数据是上一次传输的值。也就是说,有两种方式可以得到正确的 AP 寄存器的值。
a) 发送两次读DRW寄存器的操作;
b) 发送一次读DRW寄存器的操作(读取上一周期的数据),再发送一次读RDBUFF寄存器的操作(读取自己需要的数据)
总的来说,读写DP寄存器没有迟滞,不需要读写两次。读取AP寄存器,有迟滞,第一次读AP,是上一周期的值,第二次读AP才是想要的值。写AP寄存器,没有迟滞。如TAR,DRW只需要写一次即可写进去。
本节将逐步演示如何通过SWD编程内部SRAM。
在使用SW-DP之前,必须执行初始化序列,以建立通信并使SW-DP进入已知状态。
在对内部SRAM或FLASH编程之前,应首先复位并Halt CPU。这主要是使CPU和外围设备进入已知状态,并禁止CPU在编写程序时意外运行部分代码。
具体操作步骤如下,
a)Write 0xA05F0001 to DHCSR, which halting debug enabled.
b)Write 0x01 to DEMCR. This enable Reset Vector Catch.
c)Write 0xFA050004 to AIRCR. This reset the core.
现在,内核将在第一条指令时暂停,所有外围设备和寄存器(调试寄存器除外)都将设置为复位值。
Read:
Write:
a) Set 32 bit width in CSW register.
如下面截图所示,主要是确保数据传输的稳定。
如下图所示,一般来说出现这种状况时,都是HOST发送的请求包中奇偶校验出错,有可能是HOST本身出现了BUG,发出了一个错误的奇偶校验位,也可能是发送过程中传输错误,错误的可能性比较多,但最终都导致一点,主机在ACK phase发现target没有驱动SWDIO线,由于带有上拉电阻,所以主机最终会查看到接收的ACK为3’b111.一旦出现这种错误,主机只能line reset the DAP,然后读取DPIDR,建立同步机制后再进行通信。也就是从新开始。
如下图所示,DP会监测到这种状况,导致三个后果:
第一,写操作不会被触发,因为检测到校验错误;
第二,在接下来的两个周期置位错误标志WDATAERR;
第三,主机发起下一次传输时,会在其ACK phase接收到Fault ACK,即ACK=3’b001。
一旦某次ACK是ACK_FAULT,应立刻读取CTRL/STAT查看是何种原因导致了错误,如果查看到了是WDATAERR,则应向AP Abort寄存器指定位写1清楚错误状态,并再次发起前一次失败的写操作。
出现的原因可能是:Debug power domain被power down了;或者是被调试资源出现了错误(例如内核错误);或者是对应的设计逻辑出现了问题;
一旦检测到这种错误,就要认真debug了,修改code,然后reconnect。
发布于 2022-11-23 09:31・IP 属地上海
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。