JTAG学习笔记 (3)

来源:互联网 发布:阿里云主要是做什么的 编辑:程序博客网 时间:2024/06/09 21:28

因为WIGGLER的一些不可避免的缺点,我们现在将精力集中在JLink上。

JLink是大家都能够买的起的仿真器(当然是D版),已经是白菜价了,可以参考淘宝。他真的是仿真器,虽然目前只能支持ARM系列的芯片,和WIGGLER的区别是TCK的频率可以到12MHz,从逻辑分析仪上看到的情况是接近13MHz

 

基于JLink2次开发,

可参考的资料有2个:

1.    官方的协议文档:RM08001_JLinkUSBProtocol.pdf

2.    OpenOCD的代码openocd-0.4.0-rc1/src/jtag/drivers/jlink.c

 

首先在Cygwin的环境下编译最新的openocd的代码,具体的编译过程官方的网站上有详细的描述。

下面是我编译的Image的运行情况:

I:/Study/JTAG/bin>openocd -f jlink.cfg

Open On-Chip Debugger 0.4.0-rc1 (2010-02-05-00:04)

For bug reports, read

        http://openocd.berlios.de/doc/doxygen/bugs.html

Info : J-Link initialization started / target CPU reset initiated

Info : J-Link ARM V7 compiled Apr  1 2009 12:02:10

Info : JLink caps 0x39ff7bbf

Info : JLink hw version 70000

Info : JLink max mem block 9120

Info : Vref = 0.0 TCK = 1 TDI = 0 TDO = 0 TMS = 0 SRST = 1 TRST = 1

 

Error: Vref too low. Check Target Power

 

Info : J-Link JTAG Interface ready

Error: jlink_usb_message failed with result=5)

Error: jlink_tap_execute, wrong result -107 (expected 1)

Info : RCLK (adaptive clock speed)

Warn : There are no enabled taps.  AUTO PROBING MIGHT NOT WORK!!

Error: jlink_usb_message failed with result=5)

Error: jlink_tap_execute, wrong result -107 (expected 1)

Error: jlink_usb_message failed with result=5)

Error: jlink_tap_execute, wrong result -107 (expected 1)

Command handler execution failed

Warn : jtag initialization failed; try 'jtag init' again.

Warn : gdb services need one or more targets defined

 

需要说明的是因为OpenOCD使用的是libusb的库,所以相应的JLink官方提供的驱动也就不能用了,下面这段也来自官方网站。

 

Gene Smith wrote:

> I now get a successful build under cygwin. When I plug the jlink usb to

> windows and run openocd I see the the "Cannot find jlink Interface!"

> error as printed below. Do I need another special windows driver when

> running jlink in cygwin? To build I only copied usb.h and libusb.a as

> directed from libusb-win32 project. There is quite a bit of stuff in the

> libusb-win32-device-bin.tar.gz that I haven't used. Should this be

> installed?

>

Yes.

 

I had the segger jlink commander installed so its driver ran when I

plugged in the jlink and didn't work with openocd. I had to replace it

with the driver from libusb-win32-device-bin on sourceforge. (A "no

driver found dialog" would have popped up if I didn't have segger

installed already, I think.) Uninstalling segger jlink tools did not

remove the segger driver. Had to go into Control Panel/System/Device

Manager and update the jlink driver to point at the new jlink.inf file I

had made with the libusb-win32/bin inf-wizard. Then I browsed to the

actual unsigned driver pointed to by the inf, libusb0.dll from the

libusb-win32-device-bin distribution to complete the installation. I did

not try to use the "filter" driver which I think can coexist with the

segger driver (according to a post by Xiaofan which seems to be the only

mention of whether this 3rd party driver is really needed by openocd).

 

Note: the segger driver appeared under "Universal Serial Bus

Controllers" in Device Manager (winXP) while the libusb-win32 driver

appears as new top level Dev Mgr category "LibUSB-Win32 Devices".

 

-gene

 

这样我们就具备了一个JLink的学习环境了。

 

OpenOCD主要精力在ARMx Technical Reference Manual里描述PRIVATE INSTRUCTION的使用,和调试命令的实现上,所以这里我只是用了openocd-0.4.0-rc1/src/jtag/drivers/jlink.c这个文件。

最需要了解的是2点:

1.      JLink内部有3Buffer,大小都是2048Bytes,用来存放TDI TMSTDO的信号,其中每个信号的状态都是以Bit来存放的,所以最长可以支持到16384TCK

Jlink.c里的void jlink_tap_append_step(int tms, int tdi)函数就描述了如何填充TDI TMS buffer的。

2.         就是USB通信命令里的EMU_CMD_HW_JTAG3,因为的确很重要我把他们从RM08001_JLinkUSBProtocol.pdf里复制出来。

Jlink.c里的int jlink_tap_execute(void)函数就描述了这个命令执行的过程。

 

EMU_CMD_HW_JTAG3

Description

Handles the JTAG connection. It receives data for TDI and TMS and sends TDO data

back.

Command

Direction             Data                                  Name                  Explanation

H->E           1 * U8          Cmd            Command: 0xCF

H->E           1 * U8          DUMMY        Dummy data in order to word align data transfers.

H->E           1 * U16         NumBits       Number of bits to transfer.

H->E           <NumBytes>* U8  TMS            Data for TMS. NumBytes calculates as follows: NumBytes = (NumBits + 7) >> 3

H->E           <NumBytes>* U8  TDI             Data for TDI. NumBytes calculates as follows: NumBytes = (NumBits + 7) >> 3

 

Direction             Data                                  Name                  Explanation

H<-E            <NumBytes>* U8  TDO           TDO data. NumBytes calculates as follows: NumBytes = (NumBits + 7) >> 3

H<-E                1 * U8       Return         Return value:     0: O.K. Everything else: Error occured.

 

Response

Additional information

How the JTAG sequence is generated is beyond the scope of this manual.

This command is available for J-Links with hardware version 5 and above only.

The hardware version can be retrieved using the command

EMU_CMD_GET_HW_VERSION on page 32.

 

Sample communication

Output Command and JTAG TDI, TMS data to halt ARM7 CPU.

H->E: CF 00 48 00 86 E3 71 C0 01 00 00 00 0C 20 00 18 02 00 00 00 00 00

Returns TDO data.

H<-E: 20 00 08 00 48 00 00 00 00

Returns O.K.

H<-E: 00

 

下面做了一些简单的封装,以及在逻辑分析仪上的抓图:

1.      复位JTAG逻辑

CODE:

int testLogicReset(void)

{

       int i = 0;

       jlink_tap_init();

 

       for (i = 0; i < 8; i++) {

              jlink_tap_append_step(1, 0);

       }

       jlink_tap_execute();

       jlink_tap_init();

}

WAVE:

URL:http://hi.csdn.net/attachment/201002/9/3466916_1265731414dFif.jpg

 

 

2.      扫描JTAG链:

CODE:

unsigned int dcScan(void)

{

       unsigned int idcode = 0xffffffff;

       testLogicReset();

       sendData(INT_ID_CODE_LEN, (char *)&idcode, false);

       idcode = buf_get_u32(tdo_buffer,8,32);

       return idcode;

}

WAVE:

注释:testLogicReset()对应的波形在7ms以前,样子和上图一样

 

 

 

URL:

http://hi.csdn.net/attachment/201002/9/3466916_12657353076oWz.jpg

 

 

3.         BYPASS指令测试:

CODE:

unsigned int doBypass(unsigned val)

{

       unsigned int ret = 0;

       testLogicReset();

       sendInstruction(8, STR_PQ27E_INSTRU_BYPASS);

       sendData(INT_ID_CODE_LEN, (char *)&val, false);

       ret = buf_get_u32(tdo_buffer,8,32);

}

WAVE:

sendInstruction(8, STR_PQ27E_INSTRU_BYPASS);

URL:

http://hi.csdn.net/attachment/201002/9/3466916_12657317989YCr.jpg

 

sendData(INT_ID_CODE_LEN, (char *)&val, false);

URL:

http://hi.csdn.net/attachment/201002/9/3466916_1265731915j78v.jpg