雷竞技注册
技术文章

JTAG测试访问端口(TAP)状态机

2020年11月20日通过Sam Gallagher.

在本文中,我们将详细查看测试访问状态机,甚至查看简单JTAG接口的一些伪代码。

在本系列的第一部分中,我们研究了JTAG,无处不在的微控制器/ FPGA / ASIC接口标准。但是,尽管我们讨论了很多关于指令和寄存器的内容,我们仍然需要了解如何操作JTAG测试访问端口(TAP)。

如前一篇文章所示,点击通过状态机控制,该状态机具有两个路径,具体取决于我们是否正在加载指令,或读取/写入数据寄存器。在这部分中,我们将详细介绍状态机,我们甚至会看到一个简单的JTAG接口的一些伪码。

龙头状态机

如下面的图1所示,IEEE 1149.1-2013标准中显示了状态机。

状态机很简单,包括两条路径:

  • 数据寄存器(DR)路径(以绿色显示),用于加载指令
  • 指令寄存器(IR)路径(以蓝色显示),用于从/向数据寄存器读取/写入数据,包括边界扫描寄存器(BSR)

图1所示。TAP状态机,详见IEEE 1149.1-2013标准。点击这里为了一个更大的版本。

    状态机在测试时钟(TCK)边缘进行,测试模式的值选择(TMS)引脚控制行为。

    假设状态机从测试逻辑复位开始,我们开始通过时钟TMS = 0来输入运行测试/空闲状态,然后时钟TMS = 1开始选择路径。

    图2简要总结了不同状态的角色。

    图2。点击状态机具有状态描述。点击这里为了一个更大的版本。

    为了帮助理解这些状态,再次从上一篇文章中查看JTAG系统,图3。

    图3。JTAG架构

    Tap Controller管理状态机,并且根据所选状态,切换输出MUX。

    这两条路径分别是:

    • 指令捕获换档路径
    • 数据capture-shift路径

    注意,边界扫描寄存器如何包括IO引脚周围的边界扫描单元,是数据寄存器之一。数据寄存器是移位寄存器,并且可以是任意长度。

    捕获、更新和移位状态

    最“活跃”的状态是捕获,转变, 和更新州。

    捕获状态可能是最神秘的,与指令路径相比,数据路径执行不同的操作。在这里,捕获意味着将并行加载数据进入移位寄存器,而不是将数据转换为串行寄存器。转换装置可能期望,将数据转换为移位寄存器。然后,更新阶段锁存寄存器,并且状态机可以重置。

    具体地,Capture-DR是其中的状态,如果需要,测试数据可以并行加载到当前数据寄存器的移位捕获路径中。(当前数据寄存器由先前设置的当前指令设置。)这意味着数据并行加载到当前指令选择的数据寄存器中,而不是转换。

    Capture-IR用于JTAG系统中的故障隔离,但标准对其目的模糊不清。固定逻辑值(必须在{... 01}中结尾)并行加载到指令寄存器移位捕获路径中。这就是说,指令寄存器并行加载(而不是转换),具有固定逻辑值。

    Shift-DR和Shift-IR状态是将数据串行加载到数据寄存器或指令寄存器的主要状态。当状态机处于这些状态之一时,TMS保持LOW状态,直到转移操作完成。Update-DR和Update-IR状态将数据锁存到寄存器中,将指令寄存器中的数据设置为当前指令(这样做时,将为下一个周期设置当前数据寄存器)。

    操作TAP状态机的示例通常以时序图的形式给出,但此类图传递信息的能力有限,因此感兴趣的读者可以参考JTAG标准本身以获得更多信息,包括各种逻辑块的实现建议。

    JTAG接口伪码

    为了充实上述思想,在本节中,我们将组装一些可能控制JTAG接口(可以像微控制器开发板一样简单)的伪代码。代码实现了最基本的功能,没有任何错误检查或指令的特殊处理。包括一些延迟来管理时间,包括一个短延迟来适应不能保证时间的多任务系统。

    //定义针脚

    JTAG_TMS = PA01

    jtag_tck = pa02.

    JTAG_TDI = PA03

    JTAG_TDO = PA04.

    //创建一个由5个1组成的字符串,用于强制重置

    tms_reset_str = {1, 1, 1, 1, 1}

    // JTAG函数

    //发送一个常量字符串到TAP,不设置TDI或TDO

    Transmit_TMS_STR(TMS_STR)

    {

    对于i = 0:len(tms_str)

    {

    set_pin(jtag_tms,tms_str [i])

    jtag_short_delay ()

    set_pin(jtag_tck,高)

    jtag_clock_delay()

    set_pin(jtag_tck,low)

    jtag_clock_delay()

    }

    }

    shift_tdi_str(tdi_str)

    {

    set_pin(JTAG_TMS, LOW) //保持TMS LOW,平移

    对于i = 0:len(tdi_str)

    {

    set_pin (JTAG_TDI tdi_str[我])

    jtag_short_delay ()

    set_pin(jtag_tck,高)

    jtag_clock_delay()

    set_pin(jtag_tck,low)

    jtag_clock_delay()

    }

    }

    shift_tdo_str(长度)

    {

    //此函数返回从TDO移出的字符串

    SET_PIN(JTAG_TMS,LOW)//在移位时保持低电平

    Output_str = {}

    对于i = 0:长度

    {

    set_pin(jtag_tck,高)

    jtag_short_delay ()

    output_str + = read_pin(jtag_tdo)

    jtag_clock_delay()

    set_pin(jtag_tck,low)

    jtag_clock_delay()

    }

    返回output_str.

    }

    reset_jtag ()

    {

    transmit_tms_str (tms_reset_str)

    }

    load_jtag_instruction (instr)

    {

    //假设我们在运行测试/空闲

    //注意:没有错误检查,早期退出或暂停是

    / /在这里实现

    transmit_tms_str({1,1,0,0}) //使我们处于Shift-IR状态

    shift_tdi_str(instr) //转移指令数据

    传输_tms_str({1,0,1,1,0})//返回运行测试/空闲

    }

    read_jtag_register(reg_length)

    {

    //这个函数读取当前数据寄存器(由大多数设置)

    / /最近的指令)

    //假设我们在运行测试/空闲

    //注意:没有错误检查,早期退出或暂停是

    / /在这里实现

    传输_tms_str({1,0,0})//将我们放在Shift-Dr状态

    reg_str = shift_tdo_str(reg_length) //移出寄存器数据

    传输_tms_str({1,0,1,1,0})//返回运行测试/空闲

    返回reg_str.

    }

    如果浏览Black Magic Probe源代码,您可以看到JTAG接口编程的一个实际示例,在这里的github上可用。(特别是src/platforms/目录和src/include/目录)。

    结论

    我们现在已经看到了JTAG TAP最重要的部分,即它的状态机。在IEEE 1149.1-2013标准中可以找到本系列前两部分所涉及的材料,以及许多有用的实现提示和细节。

    从这里开始,我们将变得更加实际,看看各种可用的JTAG接口,讨论常用的pinouts和连接器,最后仔细看看Arm调试接口(ADI),作为实践中的JTAG示例。