DSP系统软件开发通常包括模拟阶段和仿真阶段。模拟在设计的最初阶段开始进行,不需要硬件支持,只需在计算机上运行软件模拟器,可实现代码的初步调试。仿真是将代码下载到目标板上调试、运行,一般需要利用JTAG。JTAG一端与DSP相连;另一端与主机相连,可实现代码下载、代码运行、变量查看、变量设置等。
但JTAG调试多DSP系统不方便,这是因为: ① 多个DSP需要多个JTAG、多台主机;② 通过JTAG查看变量通常需要暂停DSP运行。
笔者曾经为某基站系统开发过带多DSP的信道板:每块信道板有1片MPC860和3片TMS320VC5416(简称“VC5416”)。MPC860与每片VC5416均采用HPI接口相连,每片VC5416占用MPC860的一个片选,占用MPC860不同的地址空间。信道板逻辑结构如图1所示。
图1信道板逻辑结构
对于这样的结构,若用JTAG调试,则需要3个JTAG、3台主机,而且要求调试人员不时地操作3台主机中的某一台,很不方便。针对此结构,笔者经过摸索,不用JTAG,只需一台主机,即实现了3片DSP代码的调试,整个调试过程简单、快捷。
本文在介绍了HPI的原理后,重点讨论如何实现DSP代码下载、代码运行、变量查看。
1HPI接口简介
1.1HPI概述
DSP的HPI是一个8位或16位的并行接口,主要用来与主设备或主处理器(简称“主机”)接口。DSP内部有一定数量的双口RAM,除了DSP本身可以访问外,通过HPI接口主机也可以访问,从而实现主机与DSP的通信。
通过HPI接口,主机也可以访问VC5416寄存器。VC5416既支持8位HPI接口(简称“HPI8”),也支持16位HPI接口(简称“HPI16”),后者是前者的增强型。除非特别说明,本文所说的HPI均指HPI16。
1.2HPI加载原理
VC5416片内ROM固化有TI公司的自举引导程序Bootloader,用于在上电复位时把用户代码从外部存储器引导到片内RAM并运行。VC5416支持多种引导方式,如HPI引导、并行EPROM引导、并行I/O引导、串行口引导等。DSP采用哪种引导模式取决于硬件设计。
VC5416上电复位后,先检测MP/MC引脚,如果MP/MC=“0”,表示使用片内ROM引导。此时,DSP从0xFF80处开始执行TI的片内引导程序。进入引导程序后,HINT引脚变为低电平,然后开始检测INT2是否为低电平(有效)。若有效,则进入HPI引导方式;否则,检测INT3引 脚。若有INT3请求中断,则进入串行引导方式;否则,就进入并行引导方式。引导程序流程如图2所示。
图2引导模式判别流程
本系统中,采用Bootloader进行引导。为此,应将MP/MC引脚接低电平,并将HINT和INT2引脚连接在一起,以保证 Bootloader能检测到INT2有效。当检测其为低电平时,进入HPI引导方式。当进入HPI引导方式后,Boodloader开始反复检测0x7f单元的内容(0x7e、0x7f两单元内容在Boodloader开始执行时清零)。当检测到其内容不为零时,即将0x7e的内容赋给XPC,将0x7f的内容赋给PC,程序跳转到PC所指向位置执行用户代码。这样就实现了VC5416的程序加载启动。
2用户代码生成及下载
在本系统中,MPC860充当了3片VC5416加载启动时需要的主机。
2.1用户代码生成
工程文件(包含库文件、配置文件、源程序文件)经CCS编译、链接后生成.out文件。.out文件是公共目标文件格式(COFF)的,不能用于HPI自举引导,需要进行格式转换。转换可在MPC860上进行,也可在本地计算机上进行。在实现时,选择了后一种方式。转换工作分为两步:
① 将COFF格式文件转换为Hex格式,需要用到文件格式转换工具hex500.exe。
② 将Hex格式文件转换为Bin格式。经hex500.exe转换而成的Hex文件是ASCII形式的,也不能用于HPI自举,需要将其转换为二进制(Bin)格式。转换程序hex2bin.exe自己编程实现。
2.2用户代码下载
必须先将Bin格式文件上传到MPC860,再由MPC860写入DSP的相应RAM区(具体位置由工程中的配置文件决定)。将Bin文件由本地计算机上传到MPC860可以有多种方式,既可以编程实现,也可通过现成的工具(如ftp)实现。
配置文件规定的地址是DSP地址空间的地址,而用户代码写入是由MPC860完成的,所以必须将DSP地址空间的地址换算为MPC860地址空间的地址。DSP单元宽度为16位,是MPC860的2倍,所以换算公式为:
MPC860地址空间的地址=DSP地址空间的地址×2+DSP的片选地址
3用户代码运行
要运行用户代码,只需将代码的入口地址写入DSP的0x7e、0x7f单元。入口地址有两种设置方法: 一种为c_int00的地址,可从编译生成的.map文件得到;但只要有文件修改,c_int00的地址就可能改变。这意味着只要修改了DSP的代码,就要相应地修改MPC860的代码,很不方便。另一种为上电复位中断处理入口地址。对于VC5416,中断处理入口地址处存放的即中断处理函数,而上电复位中断处理函数是c_int00,所以此方法的效果等同于前一种方法,但由于上电复位中断处理入口地址(由配置文件决定)固定,因而入口地址的值不变。本文选择了后者。
4变量查看
变量查看是程序调试的一种基本手段,特别是在系统调试后期,Bug越来越少、越来越隐蔽,查看状态变量是最常用的调试方法。
通过HPI接口,主机可以访问DSP的RAM和寄存器。所以,只要知道变量的地址,就可以查看变量的值。而变量的地址记录在符号表中,获取符号表有两种方法。
图3COFF的文件结构
① 从CCS编译生成的.out文件中导出。COFF文件结构包含了符号表段和字符串段,如图3所示。根据COFF文件结构,可导出全部符号表。
② 从CCS编译生成的.map文件中导出。配置CCS编译选项,可生成.map文件。.map文件包含了全部符号表,包括用户变量、用户函数、系统变量、系统函数等,数量比较大(上千个)。但调试人员真正需要关心的只是用户变量,而这部分变量并不多,所以可对符号表进行筛选。筛选的实现思路是:用户变量(分为初始化变量.data和未初始化变量.bss)的符号表只可能出现在源程序编译生成的目标文件(.obj)中,而不同目标文件的.data和.bss段的符号表均在.map文件中详细列出。
下面为一个工程编译生成的.map文件的例子。工程中包含了一个源程序mcbsp.c,编译生成的mcbsp.obj的.bss段从0x4080单元开始,至0x41e2单元结束,包含了mcbspq、sp、xmt_cnt、rcv_cnt、start_demodule变量,长度分别为0x158、2、2、2、4。
.bss 1 00004080 000002e6 UNINITIALIZED
00004080 00000162 mcbsp.obj(.bss)
00004080 _mcbspq
000041d8 _sp
000041da _xmt_cnt
000041dc _rcv_cnt
000041de _start_demodule
000041e2 _HWI_dispatchTab
建立一张新的符号表,表中的每一条记录对应一个变量。一条记录包含3项内容:变量名、起始地址和长度。下载用户代码的同时下载该符号表到MPC860。查看变量时,根据变量名称查询符号表,可获取该变量的起始地址和长度,读出相应地址空间的内容即可。由于筛选后的符号表很小(只有几十个),下载、查询速度很快。系统实现时,采用了此方法。
设置变量与查看变量过程类似,不再赘述。
结语
上述调试方法,充分利用了VC5416和MPC860的特性,不使用JTAG即实现了多片DSP软件调试;整个调试过程简单、快捷,不失为一种好方法。