原创 Mum计划(本自一只鱼的EE小站)

2010-6-10 09:56 4595 4 4 分类: MCU/ 嵌入式



10月10日

Mum计划之urjtag、gdbproxy的下载速度优化



 

国庆假期宅在北京,下回放假一定要出去走走。不过也有收获,就是今天这篇文章。

本文的主要内容是如何修改urjtag和gdbproxy的代码,提高Blackfin GDB调试时,代码下载的速度。

本文属于Mum计划,Mum计划的目的是制作一套开源的Blackfin调试和开发解决方案。

Mum计划使用基于FT2232的JTAG电缆——MumJTAG进行Blackfin处理器的GDB调试。


MumJTAG使用urjtag和gdbproxy来进行GDB调试:urjtag和gdbproxy的基本编译请看这篇文章:http://xianzilu.spaces.live.com/blog/cns!4201FDC93932DDAF!850.entry

本文隐含性的提到JTAG调试原理知识,如果不明白,请自行查找文章。

本文参考文档有,http://blackfin.uclinux.org上的这两篇:



还有http://www.hjtag.com的Twentyone大侠写的一篇,我给放到EE小站的SkyDrive了:


关于DCC下载,请看http://blackfin.uclinux.org上的这篇:


以及ADI官方的Blackfin手册,我下载下来,放到EE小站的SkyDrive:


下面开始正题,转载请注明来自我是一只鱼的EE小站,邮件cosine@126.com

 

虽说之前我成功编译了Blackfin的GDB调试代理,但用起来可不像OpenOCD那么好用,尤其是gdbproxy的代码下载速度仅有4kb/s,一个u-boot就要一分钟才能下载完,简直无法接受。为了让Mum计划的调试方案实用,我付出了很多努力。虽然我没有深究Blackfin JTAG调试原理,但我的代码勉强让gdbproxy的代码下载速度提高到了40~60kb/s,虽然比不上有人专门研究的可以达到120kb/s的ICEBear(http://www.section5.ch/icebear),但是作为开源调试器,60kb/s的下载速度应该可以对付大多数应用了,我就偷点懒,不继续优化,就让ICEBear有点钱赚。微笑同时,由于我是囫囵吞枣式的做了这个优化,肯定有很多不合理之处,请真正牛叉的大侠予以指正,谢谢。

 

为什么urjtag和gdbproxy那么慢呢?因为FT2232这种器件仅仅是一个信号转换器,所有的JTAG操作都是用程序模拟的。FT2232是USB的,这就带来一个问题,USB数据传输不是实时的,每个设备都占用一定的轮询时间;如果要从JTAG读取某些东西,就必须以轮询周期为单位读取。例如,gdbproxy每向JTAG写4个字节(unsigned long),就要读取JTAG状态,看是不是CPU准备好了。由于USB的轮询周期较长,说实话我也不记得了,也许是125us,也许是1ms,那么这个周期写一下数据,下个周期读一下状态,下载速度就只能是个位数的kb了。

 

说说我是怎么做到的:

1.将默认JTAG TCK频率提高到6MHz;

2.实现传说中的DCC下载功能;

3.关闭大于4字节批量写操作的Cache清空功能。

 

第一点没有什么说到的,很好理解。

第二点,什么是DCC下载?DCC这个名字其实借用了ARM公司的说法(Debug Communication Channel),ADI有别的叫法,不管怎么叫,他们描述的事实是一致的——CPU和JTAG扫描链共享某个寄存器。说说DCC下载怎么工作吧,CPU运行一段小程序,不断扫描JTAG共享的寄存器里是不是有新数据,如果有,就保存到内存中;JTAG电缆不断通过JTAG口,向JTAG共享寄存器里写入新数据。由于现代CPU的读取和保存数据速度一般都比JTAG扫描链快很多,所以JTAG电缆就不需要看CPU是不是准备好了,节约了读取CPU状态的时间。这里还牵涉到两个问题:(1)如果不使用DCC下载,是什么样子?(2)为什么节约读取CPU状态的时间就能提高速度?问题(1),不使用DCC下载,CPU的JTAG调试逻辑里一般都有一个仿真指令寄存器(Emulation Instruction Register),用JTAG可以向这个寄存器里写入单条处理器指令,例如对于ARM,可以是MOV R0, 0x00之类的,并执行,这样,R0的数值就变成0了,再写入STR R1, R0之类的指令,就把数据存到内存去了,但对于Blackfin,这样需要查询CPU是不是完成了仿真指令。问题(2),刚才提到了,USB的轮询周期时间太长,FT2232内部有FIFO,可以储存4k个的JTAG信号电平变换的时序数据,也就是说,如果不接收,只发送,那么每当JTAG电平数据达到4k个的时候才需要发送一次,这样一次发送就大约可以发送几十个字节,而不是原先的4个字节;再说接收造成的影响,由于每个USB的轮询周期,数据既有读,又有写,如果某个周期必须读一次数据,而写数据没有那么多,就造成了FT2232内部FIFO不能被填满,浪费了时间。呵呵,很复杂。

DCC下载的使用是有代价的——需要一个很小的内存空间来跑CPU DCC扫描程序。也就是说,先通过JTAG下载一段小程序到CPU的SRAM,然后运行这段小程序来下载代码。在我这个优化里,我使用了0xffa08000~0xffa08020这段32字节的空间,这段空间BF531~533都有。我写的CPU DCC扫描程序很简单:


    P1.L = LO(DBGSTAT);
    P1.H = HI(DBGSTAT);
    R1.L = 0x0002;
    R1.H = 0x0000;
.loop_dbgstat:
    R0 = [P1];
    R0 = R0 & R1;
    cc = R0 == R1;
    if cc jump .write_emudat;
    jump .loop_dbgstat;
.write_emudat:
    R0 = EMUDAT;
    [P0++] = R0;
    jump .loop_dbgstat;

需要做的就是启动DCC之前,保护R0、R1、P0、P1和PC,并把R0设成要下载数据的首地址;在执行程序之后,还原被保护的寄存器。

第三点,我是自作主张的,因为我觉得一般执行load命令的时候才会有大量的数据写入,而load命令执行之后,本身程序就要重启,跟cache没有什么关系,所以无所谓。

 

原理说明白了,下面贴上程序:

 


  • urjtag/src/bfin/bfin.c,982行,增加函数


void
part_emudat_set_new (chain_t *chain, int n, uint32_t value, int exit)
{
  part_t *part;
  tap_register *r;


  assert (exit == EXITMODE_UPDATE || exit == EXITMODE_IDLE);


  if (part_scan_select (chain, n, EMUDAT_SCAN) < 0)
    return;


  part = chain->parts->parts[n];
  r = part->active_instruction->data_register->in;
  emudat_init_value (r, value);
  chain_shift_data_registers_mode (chain, 0, 1, exit);
}



  • gdbproxy/target_bfin_new.c,464行


static char default_jtag_connect[] = "cable gnICE";


修改为


static char default_jtag_connect[] = "cable USB-to-JTAG-IF ftd2xx-mpsse 0725:6010";
static char default_jtag_frequency[] = "frequency 6000000";



  • gdbproxy/target_bfin_new.c,1258行,增加函数


static void
core_emudat_set_new (int core, uint32_t value, int runtest)
{
  part_emudat_set_new (cpu->chain, core, value,
     runtest ? EXITMODE_IDLE : EXITMODE_UPDATE);
}



  • gdbproxy/target_bfin_new.c,3085行,函数修改为


static void
cache_flush (int core, uint32_t addr, int size)
{
  uint32_t p0;
  int i;


  assert (size > 0);


  if (size <= 4)
  {
   p0 = core_register_get (core, REG_P0);


   core_register_set (core, REG_P0, addr);
   core_dbgctl_bit_set_emuirlpsz_2 (core, UPDATE);
   for (i = (size + addr % CACHE_LINE_BYTES - 1) / CACHE_LINE_BYTES + 1;
        i > 0; i--)
     core_emuir_set_2 (core, gen_flush (REG_P0),
         gen_iflush_pm (REG_P0), RUNTEST);
   core_dbgctl_bit_clear_emuirlpsz_2 (core, UPDATE);


   core_register_set (core, REG_P0, p0);
  }



  • gdbproxy/target_bfin_new.c,3409行,函数修改为


static int
memory_write (int core, uint32_t addr, uint8_t *buf, int size)
{
  uint32_t p0, r0, p1, r1, pc;
  int clobbered[BFIN_DCPLB_NUM];
  int i;
  uint8_t isram_backup[32];


  assert (size > 0);


  p0 = core_register_get (core, REG_P0);  //保护各个寄存器
  p1 = core_register_get (core, REG_P1);
  r0 = core_register_get (core, REG_R0);
  r1 = core_register_get (core, REG_R1);
  pc = core_register_get (core, REG_RETE);


  for (i = 0; i < BFIN_DCPLB_NUM; i++)
    clobbered = 0;


  dcplb_validate_clobber_p0r0 (core, addr, size, clobbered);


  core_register_set (core, REG_P0, addr);


  core_dbgctl_bit_set_emuirlpsz_2 (core, UPDATE);


  if ((addr & 0x3) != 0)
    core_emuir_set_2 (core,
        gen_move (REG_R0, REG_EMUDAT),
        gen_store8pi (REG_P0, REG_R0), UPDATE);


  while ((addr & 0x3) != 0 && size != 0)
    {
      core_emudat_set (core, *buf++, RUNTEST);
      addr++;
      size--;
    }
  if (size == 0)
    goto finish_write;


  if (size >= 4)
 {
   bfin_resume_from_addr(0, 0, 0xffa08000);  //启动已经储存在0xffa08000的CPU DCC扫描程序


   for (; size >= 4; size -= 4)
   {
    uint32_t data;
  
    data = *buf++;
    data |= (*buf++) << 8;
    data |= (*buf++) << 16;
    data |= (*buf++) << 24;
    core_emudat_set_new (core, data, RUNTEST);  //往共享寄存器里写数据
   }
 
   bfin_stop();  //停止CPU DCC扫描程序
 }


  if (size == 0)
    goto finish_write;


  core_emuir_set_2 (core,
      gen_move (REG_R0, REG_EMUDAT),
      gen_store8pi (REG_P0, REG_R0), UPDATE);


  for (; size > 0; size--)
    core_emudat_set (core, *buf++, RUNTEST);


finish_write:


  core_dbgctl_bit_clear_emuirlpsz_2 (core, UPDATE);


  dcplb_restore_clobber_p0r0 (core, clobbered);


  core_register_set (core, REG_P0, p0);  //恢复各个寄存器
  core_register_set (core, REG_P1, p1);
  core_register_set (core, REG_R0, r0);
  core_register_set (core, REG_R1, r1);
  core_register_set (core, REG_RETE, pc);


  return 0;
}



  • gdbproxy/target_bfin_new.c,4318行,增加:


  char *freq_string = default_jtag_frequency;



  • gdbproxy/target_bfin_new.c,4342行,增加:


    {"freq", required_argument, 0, 18},



  • gdbproxy/target_bfin_new.c,4520行,增加:


 case 18:
  strcpy(freq_string, "frequency ");
  strcat(freq_string, optarg);
  break;



  • gdbproxy/target_bfin_new.c,4569行,增加:


 jtag_parse_line (chain, freq_string);



  • gdbproxy/target_bfin_new.c,5061行,增加:


  uint32_t dcc_code[] =
  {
   0x5008e109,
   0xffe0e149,
   0x0002e101,
   0x0000e141,
   0x54089108,
   0x18020808,
   0x31c72ffc,
   0x2ff99200,
  };  //CPU DCC扫描程序机器码
  
  bfin_write_mem(0xffa08000, (uint8_t *) dcc_code, 0x20);


 还有一个值得说的是,http://blackfin.uclinux.org上最新的urjtag源码中使用了strcasestr函数,这个函数在cygwin的gcc的glibc里面没有,编译无法通过。不过没有关系,可以自己写一个。



  • jtag/src/cmd/bfin.c,53行,增加:


#include <ctype.h>


#ifndef HAVE_STRCASESTR
char * strcasestr (char *haystack, char *needle)
{
 char *p, *startn = 0, *np = 0;


 for (p = haystack; *p; p++) {
  if (np) {
   if (toupper(*p) == toupper(*np)) {
    if (!*++np)
     return startn;
   } else
    np = 0;
  } else if (toupper(*p) == toupper(*needle)) {
   np = needle + 1;
   startn = p;
  }
 }


 return 0;
}
#endif


今天就写到这里。过一段时间我会放出整理测试后的源代码以及可执行文件,如果你觉得修改过程太过复杂,可以直接使用我写的代码。





4月15日

Mum计划之MumJTAG GDB代理程序编译——OpenOCD、urjtag和gdbproxy的编译




这篇文章主要是讲如何编译MumJTAG的ARM和Blackfin GDB调试代理程序的,如果你对GDB调试还没有什么概念,可以看这篇文章:http://xianzilu.spaces.live.com/blog/cns!4201FDC93932DDAF!268.entry。如果你想知道怎么使用OpenOCD进行ARM调试,请看这篇文章:http://xianzilu.spaces.live.com/blog/cns!4201FDC93932DDAF!485.entry。如果你想知道ARM上GDB调试怎么和Eclipse接口,请看这篇文章:http://xianzilu.spaces.live.com/blog/cns!4201FDC93932DDAF!602.entry

MumJTAG是我设计的一个JTAG调试电缆,它的制作请看这篇文章:http://xianzilu.spaces.live.com/blog/cns!4201FDC93932DDAF!786.entry

本文在Windows下用Cygwin环境,配合FT2232的D2XX驱动,成功编译了OpenOCD、urjtag和gdbproxy;换句话说,采用本文介绍的方法,可以在Windows下使用FTDI提供的驱动,使用FT2232电缆。OpenOCD在Cygwin下的编译没有什么难度,urjtag和gdbproxy的编译,因为没有找到类似的文章,我花了2天的时间……希望我的记录能给大家提供些方便,不要走我的弯路。转载请注明来自我是一只鱼同学的EE小站,邮件cosine@126.com

另外说一下,其实ADI提供了Windows环境下的gdbproxy,但是我试了下,不好使,也许是因为它用的是libftdi驱动的原因,我没有调查在Windows环境下怎么装libftdi驱动,因为我想绝大多数人会使用D2XX驱动吧。给出ADI工具链的地址:http://blackfin.uclinux.org/gf/download/frsrelease/392/5211/blackfin-toolchain-win32-2008R1.5.exe


  • OpenOCD的编译


这个很简单,大家可以看OpenOCD的手册:http://openocd.berlios.de/doc/openocd.pdf。我这里再啰嗦一遍。

先到OpenOCD的官方网站:http://openocd.berlios.de/,下载OpenOCD源代码:http://prdownload.berlios.de/openocd/openocd-0.1.0.tar.gz,假设保存为E:\Mum\OpenOCD\openocd-0.1.0.tar.gz。用命令行来说明:

$ cd /cygdrive/e/mum
$ tar xvzf openocd-0.1.0.tar.gz
$ mv openocd-0.1.0 openocd

当然也可以用svn下载OpenOCD最新的版本,在Cygwin的命令行中输入:

$ cd /cygdrive/e/mum
$ svn checkout svn://svn.berlios.de/openocd/trunk openocd
$ cd openocd
$ ./bootstrap

然后准备MumJTAG的D2XX驱动程序,可以看之前的这篇文章制作一个:http://xianzilu.spaces.live.com/blog/cns!4201FDC93932DDAF!786.entry,或者到这里下载我做好的驱动:http://cid-4201fdc93932ddaf.skydrive.live.com/self.aspx/Mum%e8%ae%a1%e5%88%92/MumJTAG/MumJTAGDriver.rar,假设驱动程序存储在E:\Mum\MumJTAGDriver。现在可以编译了,还是用命令来说明。

$ cd /cygdrive/e/mum/openocd
$ ./configure --prefix=/cygdrive/e/mum/openocd/build --enable-ft2232_ftd2xx --with-ftd2xx-win32-zipdir=/cygdrive/e/mum/mumjtagdriver
$ make
$ make install

这样,OpenOCD就编译好,并拷贝到E:\Mum\OpenOCD\build里了。

为了让OpenOCD正常工作,还需要一个针对要调试的CPU的配置文件,这个配置文件的编写可以参考OpenOCD的手册。这里我给出我编写的MumJTAG连接AT91SAM9263的配置文件:

##########################
# Interface configuration
##########################

interface ft2232
ft2232_device_desc "MumJTAG A"
ft2232_layout "usbjtag"
ft2232_vid_pid 0x0725 0x6010
jtag_khz 8
reset_config trst_and_srst

##########################
# TAP configuration
##########################

jtag newtap at91sam9263 cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id 0x0792603F
jtag_nsrst_delay 200000
jtag_ntrst_delay 200000

##########################
# Target configuration
##########################

set _TARGETNAME [format "%s.cpu" at91sam9263]
target create $_TARGETNAME arm926ejs -endian little -chain-position $_TARGETNAME -variant arm926ejs

# Internal sram1 memory
$_TARGETNAME configure -work-area-virt 0 -work-area-phys 0x00300000 -work-area-size 0x1000 -work-area-backup 1

##########################
# Port configuration
##########################

telnet_port 23
gdb_port 2331
tcl_port 6666

值得一提的是,不同JTAG电缆的ft2232_device_desc、ft2232_vid_pid是不一样的,应根据实际修改;ft2232_layout设定的是电缆的类型,OpenOCD支持很多种电缆的类型,MumJTAG兼容USB to JTAG Interface,所以写“usbjtag”;如果你自己独创了一种电缆,就要修改OpenOCD的源代码。假设将配置文件保存为E:\Mum\OpenOCD\build\AT91SAM9263.cfg,接下来连接MumJTAG到目标板的JTAG,给目标板上电就可以启动OpenOCD了,如下所示。

$ cd /cygdrive/e/mum/openocd/build/bin
$ ./openocd -f /cygdrive/e/mum/openocd/build/mumjtag.cfg
Open On-Chip Debugger 0.1.0 (2009-04-15-16:59) Release


BUGS? Read http://svn.berlios.de/svnroot/repos/openocd/trunk/BUGS


$URL: https://kc8apf@svn.berlios.de/svnroot/repos/openocd/tags/openocd-0.1.0/src
/openocd.c $
8 kHz
Info : JTAG tap: at91sam9263.cpu tap/device found: 0x0792603f (Manufacturer: 0x0
1f, Part: 0x7926, Version: 0x0)
Info : JTAG Tap/device matched

OpenOCD自带很多CPU和JTAG电缆的配置文件,在安装目录里,它的使用就不细说了,大家自己看手册。






















  • urjtag和gdbproxy的编译


urjtag和gdbproxy是uclinux下的一个项目,由ADI官方派人维护。它是可以使用FT2232电缆通过JTAG调试Blackfin系列处理器的一套GDB调试服务程序。顺便提一下,FT2232电缆无法在ADI的Visual DSP++下使用。

urjtag和gdbproxy是一体的一套软件,他们必须一同编译,而且路径有要求,例如urjtag储存在E:\Mum\urjtag_gdbproxy\jtag,那么gdbproxy就必须储存在E:\Mum\urjtag_gdbproxy\gdbproxy。编译的顺序是先urjtag后gdbproxy。urjtag和gdbproxy的编译和使用可以参考blackfin.uclinux.org的wiki,地址是:http://docs.blackfin.uclinux.org/doku.php?id=toolchain:debug:gdbproxy

先到uclinux的官方网站下载urjtag和gdbproxy的源码,地址是:http://blackfin.uclinux.org/gf/download/frsrelease/392/5076/blackfin-jtag-tools-08r1.5-14.src.tar.bz2。将其中的jtag.tar.bz2、gdbproxy.tar.bz2和jtag.diff解压出来,例如储存为E:\Mum\urjtag_gdbproxy\jtag.tar.bz2、E:\Mum\urjtag_gdbproxy\gdbproxy.tar.bz2和E:\Mum\urjtag_gdbproxy\jtag.diff。然后:

$ cd /cygdrive/e/mum/urjtag_gdbproxy
$ tar xvjf jtag.tar.bz2
$ tar xvjf gdbproxy.tar.bz2
$ patch -p0 <jtag.diff

当然可以使用svn下载最新的代码:

$ cd /cygdrive/e/mum/urjtag_gdbproxy
$ svn checkout svn://sources.blackfin.uclinux.org/toolchain/trunk/jtag jtag
$ svn checkout svn://sources.blackfin.uclinux.org/toolchain/trunk/gdbproxy gdbproxy

假设MumJTAG的驱动程序存放E:\Mum\MumJTAGDriver,可以编译urjtag:

$ ./configure --prefix=/cygdrive/e/mum/newbuild/jtag/build --with-ftd2xx=/cygdrive/e/mum/mumjtagdriver
$ make
$ make install

我编译的时候有很多参数类型不匹配的警告,无视它们了……接下来编译gdbproxy,这个优点麻烦,首先确认在你的Cygwin里安装的GCC必须是4.X版本的,然后编辑E:\Mum\urjtag_gdbproxy\gdbproxy\configure.in,找到这段

if test "$host_os" = "cygwin" ; then
    CFLAGS="$CFLAGS -mno-cygwin"
    LIBS="$LIBS -lws2_32"
fi

改成这样

if test "$host_os" = "cygwin" ; then
#    CFLAGS="$CFLAGS -mno-cygwin"
    LIBS="$LIBS -lws2_32 -lintl -lioperm /cygdrive/e/Mum/MumJTAGDriver/i386/ftd2xx.lib"
fi

解释下,应该是gdbproxy的Makefile兼容性不够好,用Cygwin 3.X的GCC有很多错误。另外用4.X的GCC也必须加上intl、ioperm等库,我不太懂Makefile的编写,希望明白的大虾们予以指正。另外,必须加上FTD2XX库,这个库就在驱动程序的目录里,例如前文的E:\Mum\MumJTAGDriver\i386\ftd2xx.lib。然后就可以编译了:

$ cd /cygdrive/e/mum/urjtag_gdbproxy/gdbproxy
$ CC="gcc-4" ./configure --prefix=/cygdrive/e/mum/urjtag_gdbproxy/gdbproxy/build
$ make
$ make install

gdbproxy没有什么配置文件,但是需要在初始化的时候指定JTAG电缆的种类。使用的时候先将MumJTAG连上目标板并给目标板上电,然后:

$ cd /cygdrive/e/mum/urjtag_gdbproxy/gdbproxy/build/bin
$ ./gdbproxy bfin --connect="cable USB-to-JTAG-IF ftd2xx-mpsse 0725:6010"

Remote proxy for GDB, v0.7.2, Copyright (C) 1999 Quality Quorum Inc.
MSP430 adaption Copyright (C) 2002 Chris Liechti and Steve Underwood
Blackfin adaption Copyright (C) 2008 Analog Devices, Inc.

GDBproxy comes with ABSOLUTELY NO WARRANTY; for details
use `--warranty' option. This is Open Source software. You are
welcome to redistribute it under certain conditions. Use the
'--copying' option for details.

Initializing on FTDI device 0725:6010
IR length: 5
Chain length: 1
Device Id: 01000010011110100101000011001011 (0x00000000427A50CB)
  Manufacturer: Analog Devices
  Part(0):         BF533
  Stepping:     4
  Filename:     /cygdrive/e/mum/urjtag_gdbproxy/jtag/build/share/urjtag/analog/b
f533/bf533
warning:   bfin: no board selected, BF533 is detected
notice:    gdbproxy: waiting on TCP port 2000

这说明gdbproxy已经找到目标CPU了。gdbproxy也支持很多种FT2232电缆,MumJTAG兼容USB to JTAG Interface,所以写“USB-to-JTAG-IF”;我用的是FTD2XX的驱动,所以写“ftd2xx-mpsse”,“0725:6010”是VID和PID。具体的使用说明,请看blackfin.uclinux.org的wiki。















如果你觉得以上这一切都很麻烦,那么,你可以从EE小站的SkyDrive下载已经编译好的OpenOCD、urjtag和gdbproxy。注意,这些程序必须使用FTDI官方的FTD2XX驱动;这些程序只能在Windows下运行。我测了下,应该不需要Cygwin的Dll;如果不是这样,请留言,我会把Dll加上。地址如下:
OpenOCD:http://cid-4201fdc93932ddaf.skydrive.live.com/self.aspx/Mum%e8%ae%a1%e5%88%92/MumJTAG/OpenOCD.rar
urjtag_gdbproxy:http://cid-4201fdc93932ddaf.skydrive.live.com/self.aspx/Mum%e8%ae%a1%e5%88%92/MumJTAG/urjtag%7C_gdbproxy.rar





3月16日

Mum计划之陈年往事



 

嘿嘿,先做个铺垫,我的Mum计划基于我的毕业设计中嵌入式视觉这一块。毕业已经有段时间了,我觉得可以贴出来了。视频里的履带机器人识别的目标是我手里拿着的一个红色发光二极管,摄像头安装在机器人中间的那个小突起里面。

 

    

 

解释下那个履带机器人为什么“抽”着动:

设计机构的时候,电机功率选小了,如果不增加电机电压,机器人动不起来;但是增加了电压,机器人运动速度太快,转向无法控制。所以只好让机器人动一下,歇一下,看上去比较别扭尴尬。但是视觉识别部分是没有问题的,可以准确地找到我手里的发光二极管。

今后的目标,就是把这个东东发扬光大。

 

点击看大图 




3月13日

Mum计划之MumJTAG——ARM和Blackfin JTAG调试电缆(FT2232电缆)硬件制作



 

距离上次更新已经3个多月了微笑

 

这段时间我工作的重点在电磁兼容测试上,这东西估计没有什么人有兴趣吧?其实通过测试很简单,对策也就是那些,就是这事情很烦琐。幸好我们公司有Schaffner的快瞬、浪涌发生器和ESD枪,在我无数次的实验轰炸下,把某个我设计的产品抗扰度,快瞬由不到1000V提高到4800V(我们公司标准比国标高多了困惑),ESD由不到1000V提高到15000V空气和8000V接触;还有另一个产品,把差模浪涌从炸机提高到1500~2000V,可惜还有待提高。累死了,光装卸时拧螺钉就拧了能有一千次,后来不行了,申请了个电动螺丝刀……做完测试,我的收获还是很大的,明白了该如何接地、如何屏蔽、如何进行内外互联;相应的,设计产品的风格也变了一些,终于自我感觉入了设计牛X产品的大门了。下一步还有个可靠性需要摸索,还需努力啊,等加速寿命试验做完了,估计就完成绝世武功目录的学习了,嘿嘿。感觉这段时间的收获就是在小公司的好处,可以接触到产品设计的每一个细节。

 

在业余时间,我启动了一个计划——Mum,这是一个用BF系列DSP进行视觉东东开发的计划,分为Mum、MumBurst和MumSW(SW for Silkworm)三个阶段微笑,哈哈,上MOP的同学们可以很快看出来含义。

MumJTAG是整个计划的第一步,这是个FT2232电缆,可以通过OpenOCD调试ARM,通过urjtag和gdbproxy调试Blackfin。MumJTAG和Hubert Hoegl的USB to JTAG Interface电缆(http://www.hs-augsburg.de/~hhoegl/proj/usbjtag/usbjtag.html)是兼容的,但是速度比它快,可以到6MHz,不用它的VID和PID,所以配置文件还需要修改。至于Blackfin调试,我参考了gnICE(http://blackfin.uclinux.org/gf/project/stamp/frs/?action=FrsReleaseBrowse&frs_package_id=146),但为了和ARM调试兼容,也要修改配置。不过这对开源项目来讲,不算什么难事。转载本文,请注明来自我是一只鱼的EE小站,邮件cosine@126.com

先介绍下FT2232电缆。也许有的人不知道这个电缆,但没有搞嵌入式的人不知道Wiggler的各种Clone;FT2232电缆就可以看作Wiggler的升级版本。它的特点是,便宜(批量成本大约50~60RMB),速度快(下载速度可以达到60~70KB/s),可以配置成JTAG和串口并存的模式(非常适合笔记本电脑),开源。嘿嘿,惭愧,在我写“最低成本的ARM调试解决方案”(http://xianzilu.spaces.live.com/blog/cns!4201FDC93932DDAF!485.entry)的时候,我还不看好FT2232电缆,直到我发现它可以调试Blackfin以后,兴趣才来了。

 

MumJTAG的简要信息:


  • 使用FTDI的FT2232D为USB和JTAG协议转换芯片,协议转换过程由PC上的软件控制
  • 20针ARM JTAG接口和Blackfin转换板
  • 串口一个
  • 目标板电压范围1.6V~5.5V
  • JTAG最高频率6MHz

国内其实已经有人用FT2232做出电缆来了,比如Simon的Versaloon(http://group.ednchina.com/1065/)和淘宝有售的OpenJTAG。Versaloon看起来卖得不好,我觉得主要的问题是Simon想用擅长于GDB调试的东西去占领已经被各种成熟仿真器占领的,并不需要GDB调试的单片机开发市场,而且宣传的力度又不够。至于OpenJTAG,我觉得设计者把FT2232电缆+OpenOCD拿来赚钱这一点非常失败,首先FT2232电缆完全开源的;再者170这个价格和我刚才提供的实际成本有很大差距;另外,OpenJTAG怎么面对现在只有100块钱的盗版J-Link?当然,也许OpenJTAG设计出来的时候,盗版J-Link还没有这么便宜;但现在情况已经是这样了,OpenJTAG还卖得动么?

因此,MumJTAG从诞生起就完完全全开源,原理图、Gerber、BOM、调试代理程序映像都公开,想自己做的就自己做;我可能会开淘宝店卖空板,还没有想好。目前,在AT91RM9200和AT91SAM9263上试了下,可以用;在BF531的板子上试了下,可以用Insight修改内存数值,我对Blackfin的开发还不熟悉,目前没有跑程序,所以Blackfin GDB调试的结果未知。另外说一下,Blackfin的调试工具urjtag和gdbproxy编译起来太复杂了,具体过程看我后面的文章。

经过我的努力,已经解决了MumJTAG目标板上电时OpenOCD说找不到FT2232的BUG。毕竟我是做工控设备的吐舌,MumJTAG设计时考虑了脉冲群、静电对策,并对目标板交流电源冲击采取了抗扰措施;我做了几百次电源冲击测试,还用我这个天天和铁桌腿、水龙头放静电的肉身做了几十次放电测试(对比真正的ESD枪的击穿距离,我觉得放电大概有3000~4000V,好疼啊困惑);目前来看,MumJTAG V1.1版还比较稳定,单纯从电路上看,相信MumJTAG比现有所有FT2232电缆都稳定。当然,家里的测试条件有限,不能模拟所有的情况;如果你使用MumJTAG V1.1 Gerber做的板子出现问题,欢迎与我联系:cosine@126.com。MumJTAG将不断更新,请关注EE小站。(更新日期2009年3月28日,如果你看到的是转载的文章,请从这里查看最新信息http://xianzilu.spaces.live.com/blog/cns!4201FDC93932DDAF!786.entry)。

 

请注意我在BOM中选取的元件具体型号,钽电容的耐压、ESR,磁珠绝对不能用电感或零欧姆电阻代替,否则稳定性会下降很多。串口插座我用了带共模滤波器的器件,当然也可以用不带滤波器的,但是这样会稍微降低稳定性。

 







 

先上一张做好的MumJTAG图片:

 

点击看大图 

 

梳理下制作MumJTAG需要做的事情:


  • 设计FT2232的PCB或者用我提供的Gerber
  • 焊接PCB
  • 修改FT2232板载串行EEPROM的内容
  • 修改Windows驱动

我的习惯是在Windows下用虚拟机进行Linux开发,所以,我的文章不涉及Linux下驱动,请原谅。设计焊接PCB就不说了,从修改EEPROM开始。

与FT2232配套的,有一片串行EEPROM,其作用是记录用户自定义的设备名称,USB的VID和PID。在EEPROM没有编程的时候,FT2232使用厂家默认的VID 0x0403和PID 0x6010。这个http://www.ftdichip.com/Resources/Utilities/MProg.pdf是官方的EEPROM编程工具MProg的使用说明,我下面提供的过程是这份说明的简化版。

 

在开始之前,请准备这几样东西:


FTDI的链接总有一天会失效,如果这样,请访问http://www.ftdichip.com查找。

 

先解压缩驱动程序,假设解压到E:\FT2232,然后连接MumJTAG到USB,提示安驱动的时候选择E:\FT2232,这部分不详细写了,相信大家都会。 

驱动安好后,打开MProg,出现如下界面:

 
点击看大图
 

 然后选择菜单Device>Scan,如果硬件正常,窗口下方应该出现:

 

%E6%A3%80%E6%B5%8B%E5%88%B0EEPROM.jpg 

 

然后选择菜单File>Open,打开下载的MumJTAG EEPROM信息文件"MumJTAG USB 配置文件.ept",窗口变为:

 

点击看大图 

 

上图这些,就是需要烧写的配置。可以不用EE小站提供的这个EEPROM信息,但请注意右边的FT2232C/D Options中的设置,将FT2232设置为Side A为JTAG,Side B为串口;你也可以更改Vendor ID、Product ID、Manufacturer、Product Description为你想要的东西。然后点选菜单Device>Program,将信息下载到EEPROM中,拔掉USB插头,硬件方面的动作就完成了。

此时,MumJTAG的VID和PID已经不是FT2232默认的了,FTDI的驱动已经不可用,需要对驱动程序信息进行修改。可以重新解压缩一份驱动程序,例如解压缩到E:\MumJTAG。用文本编辑器打开E:\MumJTAG\ftdibus.inf,修改其中的FtdiHW、FtdiHW.NTamd64、Strings等几段,红色字体表示增加或有变化的部分:


...

 

[FtdiHw]
%USB\VID_0403&PID_6001.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6001
%USB\VID_0403&PID_6010&MI_00.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6010&MI_00
%USB\VID_0403&PID_6010&MI_01.DeviceDesc%=FtdiBus.NT,USB\VID_0403&PID_6010&MI_01
%USB\VID_0725&PID_6010&MI_00.DeviceDesc%=FtdiBus.NT,USB\VID_0725&PID_6010&MI_00
%USB\VID_0725&PID_6010&MI_01.DeviceDesc%=FtdiBus.NT,USB\VID_0725&PID_6010&MI_01

 

[FtdiHw.NTamd64]
%USB\VID_0403&PID_6001.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6001
%USB\VID_0403&PID_6010&MI_00.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6010&MI_00
%USB\VID_0403&PID_6010&MI_01.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0403&PID_6010&MI_01
%USB\VID_0725&PID_6010&MI_00.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0725&PID_6010&MI_00
%USB\VID_0725&PID_6010&MI_01.DeviceDesc%=FtdiBus.NTamd64,USB\VID_0725&PID_6010&MI_01

 

...

 

[Strings]
Ftdi="FTDI"
DESC="CDM Driver Package"
DriversDisk="FTDI USB Drivers Disk"
USB\VID_0403&PID_6001.DeviceDesc="USB Serial Converter"
USB\VID_0403&PID_6010&MI_00.DeviceDesc="USB Serial Converter A"
USB\VID_0403&PID_6010&MI_01.DeviceDesc="USB Serial Converter B"
USB\VID_0725&PID_6010&MI_00.DeviceDesc="JTAG Port"
USB\VID_0725&PID_6010&MI_01.DeviceDesc="USB Serial Converter"

SvcDesc="USB Serial Converter Driver"
ClassName="USB"

用文本编辑器打开E:\MumJTAG\ftdibus.inf,修改其中的FtdiHW、FtdiHW.NTamd64、Strings等几段,红色字体表示增加或有变化的部分:


...

 

[FtdiHw]
%VID_0403&PID_6001.DeviceDesc%=FtdiPort232.NT,FTDIBUS\COMPORT&VID_0403&PID_6001
%VID_0403&PID_6010.DeviceDesc%=FtdiPort2232.NT,FTDIBUS\COMPORT&VID_0403&PID_6010
%VID_0725&PID_6010.DeviceDesc%=FtdiPort2232.NT,FTDIBUS\COMPORT&VID_0725&PID_6010

 

[FtdiHw.NTamd64]
%VID_0403&PID_6001.DeviceDesc%=FtdiPort232.NTamd64,FTDIBUS\COMPORT&VID_0403&PID_6001
%VID_0403&PID_6010.DeviceDesc%=FtdiPort2232.NTamd64,FTDIBUS\COMPORT&VID_0403&PID_6010
%VID_0725&PID_6010.DeviceDesc%=FtdiPort2232.NTamd64,FTDIBUS\COMPORT&VID_0725&PID_6010

 

...

 

[Strings]
FTDI="FTDI"
DESC="CDM Driver Package"
DriversDisk="FTDI USB Drivers Disk"
PortsClassName = "Ports (COM & LPT)"
VID_0403&PID_6001.DeviceDesc="USB Serial Port"
VID_0403&PID_6010.DeviceDesc="USB Serial Port"
VID_0725&PID_6010.DeviceDesc="MumJTAG"
SvcDesc="USB Serial Port Driver"
SerEnum.SvcDesc="Serenum Filter Driver"

这样,驱动程序就修改好了。将MumJTAG的USB电缆连上,提示安装驱动的时候,将路径指向E:\MumJTAG。

至此,MumJTAG就制作完成了。要验证它能不能用,我们还需要使用OpenOCD、urjtag和gdbproxy,请看我后面的文章。
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
4
关闭 站长推荐上一条 /3 下一条