SWD接口和通信实现

发布时间 2023-08-05 22:23:03作者: Yanye

空闲态电平

  1. SWD接口由SWCLK和SWDIO两根信号线组成,SWCLK调试器给目标芯片的时钟信号,在芯片端需要下拉;SWDIO双向数据信号,在芯片端需要上拉,上/下拉电阻的取值在100K附近即可。
    image

  2. 在调试器端,空闲态下:SWDIO可以输出高,SWCLK可以输出高也可以输出低(DAPLINK初始化端口默认输出高,JLINK的SWCLK和SWDIO输出都是低,JLINK和DAPLINK时序不同)。

DAPLINK的配置:

/** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET.
Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode:
 - SWCLK, SWDIO, nRESET to output mode and set to default high level.
 - TDI, TMS, nTRST to HighZ mode (pins are unused in SWD mode).
*/
__STATIC_INLINE void PORT_SWD_SETUP(void)
{
    // Set SWCLK HIGH
    pin_out_init(SWCLK_TCK_PIN_PORT, SWCLK_TCK_PIN_Bit);
    SWCLK_TCK_PIN_PORT->BSRR = SWCLK_TCK_PIN;
    // Set SWDIO HIGH
    pin_out_init(SWDIO_OUT_PIN_PORT, SWDIO_OUT_PIN_Bit);
    SWDIO_OUT_PIN_PORT->BSRR = SWDIO_OUT_PIN;

    pin_in_init(SWDIO_IN_PIN_PORT, SWDIO_IN_PIN_Bit, 1);
    // Set RESET HIGH
    pin_out_od_init(nRESET_PIN_PORT, nRESET_PIN_Bit);//TODO - fix reset logic
    nRESET_PIN_PORT->BSRR = nRESET_PIN;
}

JLINK电平实测:
image

接口模拟

  1. 纯GPIO模拟,这也是DAPLINK的默认实现方式,只用两个IO,对于SWCLK时钟线,只需要单向输出;但是SWDIO是双向IO,那么调试器就需要对这个GPIO做输入输出切换。该方法优点是简单易实现,缺点是IO翻转频率无法做的很高,输入输出切换时有较大时间消耗。
    image
    image

  2. 纯GPIO模拟,使用三个IO,对于SWCLK时钟线,只需要单向输出;对于SWDIO,使用两个IO,一个输出一个输入,中间串两个或一个电阻防止调试器的输入/输出口灌入大电流。时钟速度仍受GPIO翻转速率限制,优点是省去了IO输入/输出切换的时间。
    JLINK接法:
    当调试器驱动SWDIO时,信号经过MCU_OUT-->R87-->SWDIO传入目标芯片,同时信号也会经过R88返回到调试器,此时调试器忽略输入。
    当目标芯片驱动SWDIO时,信号经过SWDIO-->R88-->MCU_IN被调试器接收,同时信号也会经过R87到达MCU_OUT,由于R87的存在,无论调试器端MCU_OUT之前状态是输出高还是低,都不会造成短路。
    image
    DAPLINK接法:
    简化的版本,SWDIO直连调试器输入端,原理和上文类似。
    image
    关于电阻的取值:电阻值限制了SWDIO信号线的上升/下降速率,需要高速传输取100R左右的小电阻,代价是动态电流较大,在DAPLINK接法的100R电阻下,调试线长15CM左右,满足10M的IO翻转速率是没有问题的。
    推荐的接法:
    满足日常10~20CM的调试线使用,其中22R的电阻用于衰减上升和下降的振铃波形幅度。
    image

  3. 利用SPI实现部分硬件加速,适用于常见的只支持8bit或者16bit固定位宽的SPI外设。这种方案有一定的加速效果,但是使用起来比较麻烦。
    image
    下图是调试器写目标芯片的时序为例:
    1:调试器发送的包请求(8bits)由SPI硬件完成
    2:转向位(1bit) + 芯片发送的应答响应(3bits)+ 转向位(1bit) 切换到GPIO模拟
    3:调试器的数据发送阶段(32bits)由SPI硬件完成
    4:校验位(1bit)切换到GPIO模拟
    image

  4. 完全的SPI硬件加速,硬件连线同上图。例如STM32F072这种最低支持4bit的SPI外设就可以完全模拟SWD协议各个部分的时序了。
    调试器向目标芯片的写操作:8bit写 + 5bit读(丢掉最低位和最高位) + (16bit写 + 8bit写 + 9bit写)。
    image
    调试器向目标芯片的读操作:8bit写 + 4bit读(丢掉最低位) + (16bit读 + 8bit读 + 9bit读)。
    image

// stm32f0xx_spi.h
#define SPI_DataSize_4b                 ((uint16_t)0x0300)
#define SPI_DataSize_5b                 ((uint16_t)0x0400)
#define SPI_DataSize_6b                 ((uint16_t)0x0500)
#define SPI_DataSize_7b                 ((uint16_t)0x0600)
#define SPI_DataSize_8b                 ((uint16_t)0x0700)
#define SPI_DataSize_9b                 ((uint16_t)0x0800)
#define SPI_DataSize_10b                ((uint16_t)0x0900)
#define SPI_DataSize_11b                ((uint16_t)0x0A00)
#define SPI_DataSize_12b                ((uint16_t)0x0B00)
#define SPI_DataSize_13b                ((uint16_t)0x0C00)
#define SPI_DataSize_14b                ((uint16_t)0x0D00)
#define SPI_DataSize_15b                ((uint16_t)0x0E00)
#define SPI_DataSize_16b                ((uint16_t)0x0F00)

另一款芯片ESP8266的SPI使用FIFO模式操作,支持1bit~512bit任意读写,那么在SWD协议的WDATA段直接发起31bit的传输即可。

信号时序