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。
外部的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寄存器每一位的定义。
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》。
下图是根据ADI5的说明,网友自己制作的表格,更容易理解。
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权威指南》
DCRSRregister = 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就是发生在写读切换的时候的一个延时。
1) 通过往DP中的CTRL/STAT寄存器写入0x50000000 (第28位和第30位),开启debug port及其时钟;
CSYSPWRUPREQ:System
powerup request
CDBGPWRUPREQ:Debug powerup request
3) 读取IDR寄存器(addr = 0xFC)的数据并验证
4) CSW寄存器写入0x00000002,data_size:32bit
3.3 读写操作
上面截图中说的很清楚,TAR寄存器中的地址,不是AP内部的地址,而是与AP连接的芯片系统中的物理地址。
DRW寄存器将AP访问直接映射到一个或多个芯片系统内部的memory访问。在memory访问完成之前,AP访问不会完成。
DRW寄存器是R/W(可读可写)的,它在MEM-AP寄存器空间中的偏移量是0x0C。
在写入模式下,DRW将当前传输的值写入TAR中指定的地址。
在读取模式下,DRW保存从TAR中指定的地址读取的当前传输值。
3.4 读写时的注意事项:
由于读取AP寄存器的特殊性,当读取AP寄存器时,返回的数据是上一次传输的值。也就是说,有两种方式可以得到正确的 AP 寄存器的值。
a) 发送两次读DRW寄存器的操作;
b) 发送一次读DRW寄存器的操作(读取上一周期的数据),再发送一次读RDBUFF寄存器的操作(读取自己需要的数据)
总的来说,读写DP寄存器没有迟滞,不需要读写两次。读取AP寄存器,有迟滞,第一次读AP,是上一周期的值,第二次读AP才是想要的值。写AP寄存器,没有迟滞。如TAR,DRW只需要写一次即可写进去。
本节将逐步演示如何通过SWD编程内部SRAM。
在对内部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.
现在,内核将在第一条指令时暂停,所有外围设备和寄存器(调试寄存器除外)都将设置为复位值。
a) Set 32 bit width and auto increment in CSW register.
b) Write memory address in TAR register
c) Access DRW register for read/write data.
Read:
b) Write DCRSR address into TAR register.
c) Write core register index Rn into DRW register.
d) Write DCRDR address into TAR register.
e) Read core register value from DRW register.
Write:
出现的原因可能是:Debug power domain被power down了;或者是被调试资源出现了错误(例如内核错误);或者是对应的设计逻辑出现了问题;
一旦检测到这种错误,就要认真debug了,修改code,然后reconnect。
写文章不易,如果觉得对您有帮助,麻烦一键三连,或者赏个鸡腿也行!