跳至主要内容

【转】JTAG接口解读

通常所说的JTAG大致分两类,一类用于测试芯片的电气特性,检测芯片是否有问题;一类用于Debug;一般支持JTAG的CPU内都包含了这两个模块。
一个含有JTAG Debug接口模块的CPU,只要时钟正常,就可以通过JTAG接口访问CPU的内部寄存器和挂在CPU总线上的设备,如FLASH,RAM,SOC(比如4510B,44Box,AT91M系列)内置模块的寄存器,象UART,Timers,GPIO等等的寄存器。

上面说的只是JTAG接口所具备的能力,要使用这些功能,还需要软件的配合,具体实现的功能则由具体的软件决定。
例如下载程序到RAM功能。了解SOC的都知道,要使用外接的RAM,需要参照SOC DataSheet的寄存器说明,设置RAM的基地址,总线宽度,访问速度等等。有的SOC则还需要Remap,才能正常工作。运行Firmware时,这些设置由Firmware的初始化程序完成。但如果使用JTAG接口,相关的寄存器可能还处在上电值,甚至时错误值,RAM不能正常工作,所以下载必然要失败。要正常使用,先要想办法设置RAM。在ADW中,可以在Console窗口通过Let 命令设置,在AXD中可以在Console窗口通过Set命令设置。
下面是一个设置AT91M40800的命令序列,关闭中断,设置CS0-CS3, 并进行Remap,适用于AXD(ADS带的Debug)
setmem 0xfffff124,0xFFFFFFFF,32 ---关闭所有中断
setmem 0xffe00000,0x0100253d,32 ---设置CS0
setmem 0xffe00004,0x02002021,32 ---设置CS1
setmem 0xffe00008,0x0300253d,32 ---设置CS2
setmem 0xffe0000C,0x0400253d,32 ---设置CS3
setmem 0xffe00020,1,32 ---Remap
如果要在ADW(SDT带的DEBUG)中使用,则要改为:
let 0xfffff124=0xFFFFFFFF ---关闭所有中断
let 0xffe00000=0x0100253d ---设置CS0
let 0xffe00004=0x02002021 ---设置CS1
let 0xffe00008=0x0300253d ---设置CS2
let 0xffe0000C=0x0400253d ---设置CS3
let 0xffe00020=1 ---Remap
为了方便使用,可以将上述命令保存为一个文件config.ini, 在Console窗口输入 ob config.ini 即可执行。
使用其他debug,大体类似,只是命令和命令的格式不同。


设置RAM时,设置的寄存器以及寄存器的值必须和要运行程序的设置一致。一般编译生成的目标文件是ELF格式,或类似的格式,包含有目标码运行地址,运行地址在Link时候确定。Debug下载程序时根据ELF文件中的地址信息下载程序到指定的地址。如果在把RAM的基地址设置为0x10000000, 而在编译的时候指定Firmware的开始地址在0x02000000, 下载的时候,目标码将被下载到0x02000000,显然下载会失败。

通过JTAG下载程序前应关闭所有中断,这一点和Firmware初始化时关闭中断的原因相同。在使用JTAG接口的时候,各中断的使能未知,尤其是FLASH里有可执行码的情况,可能会有一些中断被使能。使用JTAG下载完代码,要执行时,有可能因为未完成初始化就产生了中断,导致程序异常。所以,需要先关闭中断,一般通过设置SOC的中断控制寄存器完成。

使用JTAG写Flash。在理论上,通过JTAG可以访问CPU总线上的所有设备,所以应该可以写FLASH,但是FLASH写入方式和RAM大不相同,需要特殊的命令,而且不同的FLASH擦除,编程命令不同,而且块的大小,数量也不同,很难提供这一项功能。所以一般Debug不提供写Flash功能,或者仅支持少量几种Flash。

目前就我知道的,针对ARM,只有FlashPGM这个软件提供写FLASH功能,但使用也非常麻烦。AXD,ADW都不提供写FLASH功能。我写Flash的方法时是,自己写一个简单的程序,专门用于写目标板的FLASH,利用JTAG接口,下载到目标板,再把要烧写的目标码装成BIN格式,也下到目标板(地址和烧FLASH的程序的地址不同),然后运行已经下载的烧FLASH的程序。使用这种方式,比起FlashPGM的写Flash,速度似乎要快一些。

关于简单JTAG电缆。
目前有各种各样简单JTAG电缆,其实只是一个电平转换电路,同时还起到保护作用。JTAG的逻辑则由运行在PC上的软件实现,所以在理论上,任何一个简单JTAG电缆,都可以支持各种应用软件,如Debug等。我就曾使用同一个JTAG电缆写Xilinx CPLD,AXD/ADW调试程序。关键再于软件的支持,大多数软件都不提供设定功能,因而只能支持某种JTAG电缆。

关于简单JTAG电缆的速度。
JTAG是串行接口,使用打印口的简单JTAG电缆,利用的是打印口的输出带锁存的特点,使用软件通过I/O产生JTAG时序。由JTAG标准决定,通过JTAG写/读一个字节要一系列的操作,根据我的分析,使用简单JTAG电缆,利用打印口,通过JTAG输出一个字节到目标板,平均需要43个打印口I/O, 在我机器上(P4 1.7G),每秒大约可进行660K次 I/O 操作,所以下载速度大约在660K/43, 约等于15K Byte/S. 对于其他机器,I/O速度大致相同,一般在600K ~ 800K.

关于如何提高JTAG下载速度。
很明显,使用简单JTAG电缆无法提高速度。要提高速度,大致有两种办法,
1。使用嵌入式系统提供JTAG接口,嵌入式系统和微机之间通过USB/Ethernet相连,这要求使用MCU。
2。使用CPLD/FPGA提供JTAG接口,CPLD/FPGA和微机之间使用EPP接口(一般微机打印口都支持EPP模式),EPP接口完成微机和CPLD/FPGA之间的数据传输,CPLD/FPGA完成JTAG时序。

这两种方法本人都实现过。第一个方法可以达到比较高的速度,实测超过了200KByte/S(注意:是Byte,不是Bit);但是相对来说,硬件复杂,制造相对复杂。第二种相对来说,下载速度要慢一些,最快时达到96KByte/S,但电路简单,制造方便,而且速度可以满足需要。第二种方案还有一个缺点,由于进行I/O操作时,CPU不会被释放,因此在下载程序时,微机CPU显得很繁忙。

评论

此博客中的热门博文

【转】cs8900网卡的移植至基于linux2.6内核的s3c2410平台

cs8900网卡的移植至基于linux2.6内核的s3c2410平台(转) 2008-03-11 20:58 硬件环境:SBC-2410X开发板(CPU:S3C2410X) 内核版本:2.6.11.1 运行环境:Debian2.6.8 交叉编译环境:gcc-3.3.4-glibc-2.3.3 第一部分 网卡CS8900A驱动程序的移植 一、从网上将Linux内核源代码下载到本机上,并将其解压: #tar jxf linux-2.6.11.1.tar.bz2 二、打开内核顶层目录中的Makefile文件,这个文件中需要修改的内容包括以下两个方面。 (1)指定目标平台。 移植前:         ARCH?= $(SUBARCH) 移植后: ARCH            :=arm (2)指定交叉编译器。 移植前: CROSS_COMPILE ?= 移植后: CROSS_COMPILE   :=/opt/crosstool/arm-s3c2410-linux-gnu/gcc-3.3.4-glibc-2.3.3/bin/arm-s3c2410-linux-gnu- 注:这里假设编译器就放在本机的那个目录下。 三、添加驱动程序源代码,这涉及到以下几个方面。(1)、从网上下载了cs8900.c和cs8900.h两个针对2.6.7的内核的驱动程序源代码,将其放在drivers/net/arm/目录下面。 #cp cs8900.c ./drivers/net/arm/ #cp cs8900.h ./drivers/net/arm/ 并在cs8900_probe()函数中,memset (&priv,0,sizeof (cs8900_t));函数之后添加如下两条语句: __raw_writel(0x2211d110,S3C2410_BWSCON); __raw_writel(0x1f7c,S3C2410_BANKCON3); 注:其原因在"第二部分"解释。 (2)、修改drivers/net/arm/目录下的Kconfig文件,在最后添加如...

【转】嵌入式开发中使用DDD进行调试

 在嵌入式程序开发过程中,程序员要进行大量的调试,以此验证程序的正确性,修改潜在的错误。调试器对于程序员来说是不可或缺的必备工具。在Linux环境中,有很多调试工具和调试辅助工具,例如GDB、XXGDB、RHIDE、XWPE、GVD和DDD等。其中,DDD是命令行调试器的图形前端,除了一般的程序调试功能以外,还具有交互式图形数据显示的功能。它在嵌入式应用开发中也十分出色。本文主要讲述DDD(Data Display Debugger)的使用方法。      1.认识DDD     GNU DDD是命令行调试程序,如GDB、DBX、WDB、Ladebug、JDB、XDB、Perl Debugger或Python Debugger的可视化图形前端。它特有的图形数据显示功能(Graphical Data Display)可以把数据结构按照图形的方式显示出来。DDD最初源于1990年Andreas Zeller编写的VSL结构化语言,后来经过一些程序员的努力,演化成今天的模样。DDD的功能非常强大,可以调试用C\C++、Ada、 Fortran、Pascal、Modula-2和Modula-3编写的程序;可以超文本方式浏览源代码;能够进行断点设置、回溯调试和历史纪录编辑;具有程序在终端运行的仿真窗口,并在远程主机上进行调试的能力;图形数据显示功能(Graphical Data Display)是创建该调试器的初衷之一,能够显示各种数据结构之间的关系,并将数据结构以图形化形式显示;具有GDB/DBX/XDB的命令行界面,包括完全的文本编辑、历史纪录、搜寻引擎。     DDD是开源软件,用户可以去 http://www.cs.tubs.de/softech/ddd/ 下载.rpm格式的DDD源码文件。      图1显示的是DDD的主窗口。它主要由选单栏、工具条、数据窗口、源文件窗口、机器码窗口、控制台和命令工具窗口等几部分组成。其中,数据窗口用于观察复杂的数据结构,在删除数据之后,显示仍然有效;源文件窗口显示源代码、断点和当前执行到达的位置,选择该窗口中的"Display"项,可以显示任意表达式的值;机...

【转】函数指针和指针函数

【函数指针】        在程序运行中,函数代码是程序的算法指令部分,它们和数组一样也占用存储空间,都有相应的地址。可以使用指针变量指向数组的首地址,也可以使用指针变量指向函数代码的首地址,指向函数代码首地址的指针变量称为函数指针。 1.函数指针定义 函数类型 (*指针变量名)(形参列表); "函数类型"说明函数的返回类型,由于"()"的优先级高于"*",所以指针变量名外的括号必不可少,后面的"形参列表"表示指针变量指向的函数所带的参数列表。 例如: int (*f)(int x); double (*ptr)(double x); 在定义函数指针时请注意:     函数指针和它指向的函数的参数个数和类型都应该是―致的; 函数指针的类型和函数的返回值类型也必须是一致的。 2.函数指针的赋值 函数名和数组名一样代表了函数代码的首地址,因此在赋值时,直接将函数指针指向函数名就行了。 例如, int func(int x);   /* 声明一个函数 */ int (*f) (int x);    /* 声明一个函数指针 */ f=func;            /* 将func函数的首地址赋给指针f */ 赋值时函数func不带括号,也不带参数,由于func代表函数的首地址,因此经过赋值以后,指针f就指向函数func(x)的代码的首地址。 3.通过函数指针调用函数 函数指针是通过函数名及有关参数进行调用的。 与其他指针变量相类似,如果指针变量pi是指向某整型变量i的指针,则*p等于它所指的变量i;如果pf是指向某浮点型变量f的指针,则*pf就等价于它所指的变量f。同样地,*f是指向函数func(x)的指针,则*f就代表它所指向的函数func。所以在执行了f=func;之后,(*f)和func代表同一函数。 由于函数指针指向存储区中的某个函数,因此可以通过函数指针调用相应的函数。现在我们就讨论如何用函数指针调用函数,它应执行下面三步: 首先,要说明函数指针变量。 例如:int (*f)...