本章概述CCS(Code Composer Studio)软件开发过程、CCS组件及CCS使用的文件和变量。
CCS提供了配置、建立、调试、跟踪和分析程序的工具,它便于实时、嵌入式信号处理程序的编制和测试,它能够加速开发进程,提高工作效率。
CCS提供了基本的代码生成工具,它们具有一系列的调试、分析能力。CCS支持如下所示的开发周期的所有阶段。
在使用本教程之前,必须完成下述工作:
o 安装目标板和驱动软件。按照随目标板所提供的说明书安装。如果你正在用仿真器或目标板,其驱动软件已随目标板提供,你可以按产品的安装指南逐步安装。
o 安装CCS.遵循安装说明书安装。如果你已有CCS仿真器和TMS320c54X代码生成工具,但没有完整的CCS,你可以按第二章和第四章所述的步骤进行安装。
o 运行CCS安装程序SETUP. 你可以按步骤执行第二章和第四章的实验。SETUP程序允许CCS使用为目标板所安装的驱动程序。
CCS包括如下各部分:
o CCS代码生成工具:参见1.2节
o CCS集成开发环境(IDE):参见1.3节
o DSP/BIOS插件程序和API:参见1.4节
o RTDX插件、主机接口和API:参见1.5节
图1-1 CCS构成及接口
图1-2 软件开发流程
图1-2描述的工具如下:
o C编译器(C compiler) 产生汇编语言源代码,其细节参见TMS320C54x最优化C编译器用户指南。
o 汇编器(assembler) 把汇编语言源文件翻译成机器语言目标文件,机器语言格式为公用目标格式(COFF),其细节参见TMS320C54x汇编语言工具用户指南。
o 连接器(linker) 把多个目标文件组合成单个可执行目标模块。它一边创建可执行模块,一边完成重定位以及决定外部参考。连接器的输入是可重定位的目标文件和目标库文件,有关连接器的细节参见TMS320C54x最优化C编译器用户指南和汇编语言工具用户指南。
o 归档器(archiver)允许你把一组文件收集到一个归档文件中。归档器也允许你通过删除、替换、提取或添加文件来调整库,其细节参见TMS320C54x汇编语言工具用户指南。
o 助记符到代数汇编语言转换公用程序(mnimonic_to_algebric assembly translator utility)把含有助记符指令的汇编语言源文件转换成含有代数指令的汇编语言源文件,其细节参见TMS320C54x汇编语言工具用户指南。
o 你可以利用建库程序(library_build utility)建立满足你自己要求的“运行支持库”,其细节参见TMS320C54x最优化C编译器用户指南。
o 运行支持库(run_time_support libraries) 它包括C编译器所支持的ANSI标准运行支持函数、编译器公用程序函数、浮点运算函数和C编译器支持的I/O函数,其细节参见TMS320C54x最优化C编译器用户指南。
o 十六进制转换公用程序(hex conversion utility) 它把COFF目标文件转换成TI-Tagged、ASCII-hex、 Intel、 Motorola-S、或 Tektronix 等目标格式,可以把转换好的文件下载到EPROM编程器中,其细节参见TMS320C54x汇编语言工具用户指南。
o 交叉引用列表器(cross_reference lister)它用目标文件产生参照列表文件,可显示符号及其定义,以及符号所在的源文件,其细节参见TMS320C54x汇编语言工具用户指南。
o 绝对列表器(absolute lister)它输入目标文件,输出.abs文件,通过汇编.abs文件可产生含有绝对地址的列表文件。如果没有绝对列表器,这些操作将需要冗长乏味的手工操作才能完成。
CCS集成开发环境(IDE)允许编辑、编译和调试DSP目标程序。
集成编辑环境支持下述功能:
o 用彩色加亮关键字、注释和字符串。
o 以圆括弧或大括弧标记C程序块,查找匹配块或下一个圆括弧或大括弧。
o 在一个或多个文件中查找和替代字符串,能够实现快速搜索。
o 取消和重复多个动作。
o 获得“上下文相关”的帮助。
o 用户定制的键盘命令分配。
应用程序通过工程文件来创建。工程文件中包括C源程序、汇编源程序、目标文件、库文件、连接命令文件和包含文件。编译、汇编和连接文件时,可以分别指定它们的选项。在CCS中,可以选择完全编译或增量编译,可以编译单个文件,也可以扫描出工程文件的全部包含文件从属树,也可以利用传统的makefiles文件编译。
CCS提供下列调试功能:
o 设置可选择步数的断点
o 在断点处自动更新窗口
o 查看变量
o 观察和编辑存储器和寄存器
o 观察调用堆栈
o 对流向目标系统或从目标系统流出的数据采用探针工具观察,并收集存储器映象
o 绘制选定对象的信号曲线
o 估算执行统计数据
o 观察反汇编指令和C指令
CCS提供GEL语言,它允许开发者向CCS菜单中添加功能。
在软件开发周期的分析阶段,调试依赖于时间的例程时,传统调试方法效率低下。
图1-3 应用例程中各线程时序
DSP/BIOS API 具有下列实时分析功能:
o 程序跟踪(Program tracing)显示写入目标系统日志(target log)的事件,反映程序执行过程中的动态控制流。
o 性能监视(Performance monitoring)跟踪反映目标系统资源利用情况的统计表,诸如处理器负荷和线程时序。
o 文件流(File streaming)把常驻目标系统的I/O对象捆绑成主机文档。
DSP/BIOS 也提供基于优先权的调度函数,它支持函数和多优先权线程的周期性执行。
在CCS环境中,可以利用DSP/BIOS API定义的对象创建配置文件,这类文件简化了存储器映象和硬件ISR矢量映象,所以,即使不使用DSP/BIOS API 时,也可以使用配置文件。
配置文件有两个任务:
o 设置全局运行参数。
o 可视化创建和设置运行对象属性,这些运行对象由目标系统应用程序的DSP/BIOS API函数调用,它们包括软中断,I/O管道和事件日志。
DSP/BIOS对象是静态配置的,并限制在可执行程序空间范围内,而运行时创建对象的API调用需要目标系统额外的开销(尤其是代码空间)。静态配置策略通过去除运行代码能够使目标程序存储空间最小化,能够优化内部数据结构,在程序执行之前能够通过确认对象所有权来及早地检测出错误。
保存配置文件时将产生若干个与应用程序联系在一起的文件,这些文件的细节参见1.7.2。
传统调试(debuging)相对于正在执行的程序而言是外部的,而DSP/BIOS API要求将目标系统程序和特定的DSP/BIOS API模块连接在一起。通过在配置文件中定义DSP/BIOS对象,一个应用程序可以使用一个或多个DSP/BIOS模块。在源代码中,这些对象声明为外部的,并调用DSP/BIOS API功能。
每个DSP/BIOS模块都有一个单独的C头文件或汇编宏文件,它们可以包含在应用程序源文件中,这样能够使应用程序代码最小化。
为了尽量少地占用目标系统资源,必须优化(C和汇编源程序)DSP/BIOS API调用。
DSP/BIOS API划分为下列模块,模块内的任何API调用均以下述代码开头。
o CLK。片内定时器模块控制片内定时器并提供高精度的32位实时逻辑时钟,它能够控制中断的速度,使之快则可达单指令周期时间,慢则需若干毫秒或更长时间。
o HST。主机输入/输出模块管理主机通道对象,它允许应用程序在目标系统和主机之间交流数据。主机通道通过静态配置为输入或输出。
o HWI。硬件中断模块提供对硬件中断服务例程的支持,可在配置文件中指定当硬件中断发生时需要运行的函数。
o IDL。休眠功能模块管理休眠函数,休眠函数在目标系统程序没有更高优先权的函数运行时启动。
o LOG。日志模块管理LOG对象,LOG对象在目标系统程序执行时实时捕捉事件。开发者可以使用系统日志或定义自己的日志,并在CCS中利用它实时浏览讯息。
o MEM。存储器模块允许指定存放目标程序的代码和数据所需的存储器段。
o PIP。数据通道模块管理数据通道,它被用来缓存输入和输出数据流。这些数据通道提供一致的软件数据结构,可以使用它们驱动DSP和其它实时外围设备之间的I/O通道。
o PRD。周期函数模块管理周期对象,它触发应用程序的周期性执行。周期对象的执行速率可由时钟模块控制或PRD_tick的规则调用来管理,而这些函数的周期性执行通常是为了响应发送或接收数据流的外围设备的硬件中断。
o RTDX。实时数据交换允许数据在主机和目标系统之间实时交换,在主机上使用自动OLE的客户都可对数据进行实时显示和分析,详细资料参见1.5。
o STS。统计模块管理统计累积器,在程序运行时,它存储关键统计数据并能通过CCS浏览这些统计数据。
o SWI。软件中断模块管理软件中断。软件中断与硬件中断服务例程(ISRs)相似。当目标程序通过API调用发送SWI对象时,SWI模块安排相应函数的执行。软件中断可以有高达15级的优先级,但这些优先级都低于硬件中断的优先级。
o TRC。跟踪模块管理一套跟踪控制比特,它们通过事件日志和统计累积器控制程序信息的实时捕捉。如果不存在TRC对象,则在配置文件中就无跟踪模块。
有关各模块的详细资料,可参见CCS中的在线帮助,或TMS320C54 DSP/BIOS 用户指南。
TI DSPs提供在片仿真支持,它使得CCS能够控制程序的执行,实时监视程序运行。增强型JTAG连接提供了对在片仿真的支持,它是一种可与任意DSP系统相连的低侵扰式的连接。仿真接口提供主机一侧的JTAG连接,如TI XSD510。为方便起见,评估板提供在板JTAG仿真接口。
在片仿真硬件提供多种功能:
o DSP的启动、停止或复位功能
o 向DSP下载代码或数据
o 检查DSP的寄存器或存储器
o 硬件指令或依赖于数据的断点
o 包括周期的精确计算在内的多种记数能力
o 主机和DSP之间的实时数据交换(RTDX)
CCS提供在片能力的嵌入式支持;另外,RTDX通过主机和DSP APIs提供主机和DSP之间的双向实时数据交换,它能够使开发者实时连续地观察到DSP应用的实际工作方式。在目标系统应用程序运行时,RTDX也允许开发者在主机和DSP设备之间传送数据,而且这些数据可以在使用自动OLE的客户机上实时显示和分析,从而缩短研发时间。
图1-4 RTDX系统组成
图1-5 RTDX实例
RTDX能够记录实时数据,并可将其回放用于非实时分析。下述样本由National Instruments’ LabVIEW 软件产生。在目标系统上,一个原始信号通过FIR滤波器,然后与原始信号一起通过RTDX发送给主机。在主机上,LabVIEW显示屏通过RTDX COM API获取数据,并将它们显示在显示屏的左边。利用信号的功率谱可以检验目标系统中FIR滤波器是否正常工作。处理后的信号通过LabVIEW,将其功率谱显示在右上部分;目标系统的原始信号通过LabVIEW的FIR滤波器,再将其功率谱显示在右下部分。比较这两个功率谱便可确认目标系统的滤波器是否正常工作。
RTDX适合于各种控制、伺服和音频应用。例如,无线电通信产品可以通过RTDX捕捉语音合成算法的输出以检验语音应用程序的执行情况;嵌入式系统也可从RTDX获益;硬磁盘驱动设计者可以利用RTDX测试他们的应用软件,不会因不正确的信号加到伺服马达上而与驱动发生冲突;引擎控制器设计者可以利用RTDX在控制程序运行的同时分析随环境条件而变化的系数。对于这些应用,用户都可以使用可视化工具,而且可以根据需要选择信息显示方式。未来的 TI DSPs 将增加RTDX的带宽,为更多的应用提供更强的系统可视性。关于RTDX的详细资料,请参见CCS中RTDX在线帮助。
第三方软件提供者可创建AxtiveX插件扩展CCS功能,目前已有若干第三方插件用于多种用途。
本节简述CCS文件夹、CCS的文件类型及CCS环境变量。
安装进程将在安装CCS的文件夹(典型情况为:c:\ti)中建立子文件夹。此外,子文件夹又建立在Windows目录下(c:\windows or c:\winnt)。
C:\ti包含以下目录:
o bin.各种应用程序
o c5400\bios。DSP/BIOS API的程序编译时使用的文件
o c5400\cgtools.Texas instruments源代码生成工具
o c5400\examples.源程序实例
o c5400\rtdx. RTDX文件
o c5400\tutorial.本手册中使用的实例文件
o cc\bin.关于CCS环境的文件
o cc\gel.与CCS一起使用的GEL文件
o docs.PDS格式的文件和指南
o myprojects.用户文件夹
以下目录结构被添加到Windows目录:
o ti\drivers.各种DSP板驱动文件
o ti\plugins.和CCS一起使用的插件程序
o ti\uninstall.支持卸载CCS软件的文件
当使用CCS时,你将经常遇见下述扩展名文件:
o project.mak.CCS使用的工程文件
o program.c.C程序源文件
o program.asm. 汇编程序源文件
o filename.h.C程序的头文件,包含DSP/BIOS API模块的头文件
o filename.lib.库文件
o project.cmd.连接命令文件
o program.obj.由源文件编译或汇编而得的目标文件
o program.out.(经完整的编译、汇编以及连接的)可执行文件
o project.wks. 存储环境设置信息的工作区文件,
o program.cdb.配置数据库文件。采用DSP/BIOS API的应用程序需要这类文件,对于其它应用程序则是可选的。
保存配置文件时将产生下列文件:
u programcfg.cmd.连接器命令文件
u programcfg.h54.头文件
u programcfg.s54.汇编源文件
安装程序在autoexec.bat文件中定义以下变量(对Windows 95和98)或环境变量(对于Windows NT):
表1-1 环境变量
变 量 |
描 述 |
C54X_A_DIR |
由汇编程序使用的搜索表和用于DSP/BIOS、RTDX以及代码生成工具的包含文件。可参见TMS320C54X汇编语言工具用户指南。 |
C54X_C_DIR |
由编译程序和连接程序使用的搜索表和用于DSP/BIOS、RTDX以及代码生成工具的包含文件。可参见TMS320C54X 最佳C编译器用户指南。 |
PATH |
添加到路径定义中的文件夹列表。缺省将添加文件夹c:\ti\c5400\cgtools\bin和c:\ti\bin。 |
如果使用的是Windows 95,你可能需要增加DOS界面的环境空间,以便支持建立一个CCS应用所需的环境变量。
把下一行添加到config.sys文件中,然后重新启动计算机:
shell=c:\windows\commad.com /e:4096 /p
本章使用hello world实例介绍在CCS中创建、调试和测试应用程序的基本步骤;介绍CCS的主要特点,为在CCS中深入开发DSP软件奠定基础。
在使用本实例之前,你应该已经根据安装说明书完成了CCS安装。建议在使用CCS时利用目标板而不是仿真器。如果没有CCS而只有代码生成工具和Code Composer或者是利用仿真器在进行开发,你只要按第二章和第四章中的步骤执行即可。
在本章中,将建立一个新的应用程序,它采用标准库函数来显示一条hello world 消息。
1. 如果CCS安装在c:\ti中,则可在c:\ti\myprojects建立文件夹hello1。(若将CCS安装在其它位置,则在相应位置创建文件夹hello1。)
2. 将c:\ti\c5400\tutorial\hello1中的所有文件拷贝到上述新文件夹。
3.
注:CCS设置
如果第一次启动CCS时出现错误信息,首先确认是否已经安装了CCS。如果利用目标板进行开发,而不是带有CD-ROM的仿真器,则可参看与目标板一起提供的文档以设置正确的I/O端口地址。
4. 选择菜单项Project→New。
5. 在Save New Project As窗口中选择你所建立的工作文件夹并点击Open。键入myhello作为文件名并点击Save,CCS就创建了myhello.mak的工程文件,它存储你的工程设置,并且提供对工程所使用的各种文件的引用。
1. 选择Project→Add Files to Project,选择hello.c并点击Open。
2. 选择Project→Add Files to Project,在文件类型框中选择*.asm。选择vector.asm并点击Open。该文件包含了设置跳转到该程序的C入口点的RESET中断(c_int00)所需的汇编指令。(对于更复杂的程序,可在vector.asm定义附加的中断矢量,或者,可用3.1节上所说明的DSP/BIOS来自动定义所有的中断矢量)
3. 选择Project→Add Files to Project,在文件类型框中选择*.cmd。选择hello.cmd并点击Open,hello.cmd包含程序段到存储器的映射。
4. 选择Project→Add Files to Project,进入编译库文件夹(C:\ti\c5400\cgtools\lib)。在文件类型框中选择*.o*,*.lib。选择rts.lib并点击Open,该库文件对目标系统DSP提供运行支持。
5. 点击紧挨着Project、Myhello.mak、Library和Source旁边的符号+展开Project表,它称之为Project View。
注:打开Project View
如果看不到Project View,则选择View→Project。如果这时选择过Bookmarks图标,仍看不到Project View,则只须再点击Project View底部的文件图标即可。
6. 注意包含文件还没有在Project View中出现。在工程的创建过程中,CCS扫描文件间的依赖关系时将自动找出包含文件,因此不必人工地向工程中添加包含文件。在工程建立之后,包含文件自动出现在Project View中。
如果需要从工程中删除文件,则只需在Project View中的相应文件上点击鼠标右键,并从弹出菜单中选择Remove from project即可。
在编译工程文件时,CCS按下述路径顺序搜索文件:
o 包含源文件的目录
o 编译器和汇编器选项的Include Search Path中列出的目录(从左到右)
o 列在C54X_C_DIR(编译器)和C54X_A_DIR(汇编器)环境变量定义中的目录(从左到右)。
1. 双击Project View中的文件hello.c,可在窗口的右半部看到源代码。
2. 如想使窗口更大一些,以便能够即时地看到更多的源代码,你可以选择Option→Font使窗口具有更小的字型。
/* ======== hello.c ======== */
#include
#include "hello.h"
#define BUFSIZE 30
struct PARMS str =
{
2934,
9432,
213,
9432,
&str
};
/** ======== main ========**/
void main()
{
#ifdef FILEIO
int i;
char scanStr[BUFSIZE];
char fileStr[BUFSIZE];
size_t readSize;
FILE *fptr;
#endif
/* write a string to stdout */
puts("hello world!\n");
#ifdef FILEIO
/* clear char arrays */
for (i = 0; i < BUFSIZE; i++) {
scanStr[i] = 0 /* deliberate syntax error */
fileStr[i] = 0;
}
/* read a string from stdin */
scanf("%s", scanStr);
/* open a file on the host and write char array */
fptr = fopen("file.txt", "w");
fprintf(fptr, "%s", scanStr);
fclose(fptr);
/* open a file on the host and read char array */
fptr = fopen("file.txt", "r");
fseek(fptr, 0L, SEEK_SET);
readSize = fread(fileStr, sizeof(char), BUFSIZE, fptr);
printf("Read a %d byte char array: %s \n", readSize, fileStr);
fclose(fptr);
#endif
}
当没有定义FILEIO时,采用标准puts()函数显示一条hello world消息,它只是一个简单程序。当定义了FILEIO后(见2.5节),该程序给出一个输入提示,并将输入字符串存放到一个文件中,然后从文件中读出该字符串,并把它输出到标准输出设备上。
CCS会自动将你所作的改变保存到工程设置中。在完成上节之后,如果你退出了CCS,则通过重新启动CCS和点击Project→Open,即可返回到你刚才停止工作处。
注:重新设置目标系统DSP
如果第一次能够启动CCS,但接下来得到CCS不能初始化目标系统DSP的出错信息则可选择Debug→Reset DSP菜单项。若还不能解决上述问题,你可能需要运行你的目标板所提供的复位程序。
为了编译和运行程序,要按照以下步骤进行操作:
1. 点击工具栏按钮或选择Project→Rebuild All ,CCS重新编译、汇编和连接工程中的所有文件,有关此过程的信息显示在窗口底部的信息框中。
2. 选择File→Load Program,选择刚重新编译过的程序myhello.out(它应该在c:\ti\myprojects\hello1文件夹中,除非你把CCS安装在别的地方)并点击Open。CCS把程序加载到目标系统DSP上,并打开Dis_Assembly窗口,该窗口显示反汇编指令。(注意,CCS还会自动打开窗口底部一个 标有Stdout的区域,该区域用以显示程序送往Stdout的输出。)
3. 点击Dis_Assembly窗口中一条汇编指令(点击指令,而不是点击指令的地址或空白区域)。按F1键。CCS将搜索有关那条指令的帮助信息。这是一种获得关于不熟悉的汇编指令的帮助信息的好方法。
4. 点击工具栏按钮或选择Debug→Run。
注:屏幕尺寸和设置
工具栏有些部分可能被Build窗口隐藏起来,这取决于屏幕尺寸和设置。为了看到整个工具栏,请在Build窗口中点击右键并取消Allow Docking选择。
当运行程序时,可在Stdout窗口中看到hello world消息。
在前一节中,由于没有定义FILEIO,预处理器命令(#ifdef 和#endif)之间的程序没有运行。在本节中,使用CCS设置一个预处理器选项,并找出和纠正语法错误。
1. 选择Project→Options。
2. 从Build Option窗口的Compiler栏的Category列表中选择Symbles。在Define Symbles框中键入FILEIO并按Tab键。
注意,现在窗口顶部的编译命令包含-d选项,当你重新编译该程序时,程序中#ifdef FILEIO语句后的源代码就包含在内了。(其它选项可以是变化的,这取决于正在使用的DSP板。)
3. 点击OK保存新的选项设置。
4. 点击(Rebuild All)工具栏按钮或选择Project→Rebuild All。无论何时,只要工程选项改变,就必须重新编译所有文件。
5. 出现一条说明程序含有编译错误的消息,点击Cancel。在Build tab 区
6. 双击描述语法错误位置的红色文字。注意到hello.c源文件是打开的,光标会落在该行上: fileStr[i] = 0
7. 修改语法错误(缺少分号)。注意,紧挨着编辑窗口题目栏的文件名旁出现一个星号(*),表明源代码已被修改过。当文件被保存时,星号随之消失。
8. 选择File→Save 或按Ctrl+S可将所作的改变存入hello.c。
9. 点击(Incremental Build)工具栏按钮或选择Project→Build,CCS重新编译已被更新的文件。
当开发和测试程序时,常常需要在程序执行过程中检查变量的值。在本节中,可用断点和观察窗口来观察这些值。程序执行到断点后,还可以使用单步执行命令。
1. 选择File→Reload Program.
2. 双击Project View中的文件hello.c。可以加大窗口,以便能看到更多的源代码。
3. 把光标放到以下行上:
fprintf(fptr, “%S”, scacStr);
4. 点击工具栏按钮或按F9,该行显示为高亮紫红色。(如果愿意的话,可通过Option→Color改变颜色。)
5. 选择View→Watch Window。CCS窗口的右下角会出现一个独立区域,在程序运行时,该区域将显示被观察变量的值。
6. 在Watch Window区域中点击鼠标右键,从弹出的表中选择Insert New Expression。
7. 键入表达式*scanStr并点击OK。
8. 注意局部变量*scanStr被列在Watch window中,但由于程序当前并未执行到该变量的main()函数,因此没有定义。
9. 选择Debug→Run或按F5。
10. 在相应提示下,键入goodbye并点击OK。注意,Stdout框以蓝色显示输入的文字。
在键入一个输入字符串之后,程序运行并在断点处停止。程序中将要执行的下一行以黄色加亮。
11. 点击(Step Over)工具栏按钮或按F10以便执行到所调用的函数fprintf()之后。
12. 用CCS提供的step命令试验:
■ Step Into (F2)
■ Step over (F10)
■ Step Out (Shift F7)
■ Run to Cursor (Ctrl F10)
13. 点击工具栏按钮或按F5运行程序到结束。
观察窗除了观察简单变量的值以外,还可观察结构中各元素元素的值。
1. 在watch Window区域中点击鼠标右键,并从弹出表中选择Insert New Expression。
2. 键入str 作为表达式并点击OK。显示着+str={…}的一行出现在Watch Window中。+符号表示这是一个结构。回顾2.3,类型为PARMS的结构被声明为全局变量,并在hello.c中初始化。结构类型在hello.h中定义。
3.
4. 双击结构中的任意元素就可打开该元素的Edit Variable窗口。
5. 改变变量的值并点击OK。注意Watch Window中的值改变了,而且其颜色也相应变化,表明已经该值已经人工修改了。
6. 在Watch Window中选择str变量并点击右键,从弹出表中选择Remove Cuurent Expression。在Watch Window中重复上述步骤。
7. 在Watch Window中点击右键,从弹出表中选择Hide可以隐藏观察窗口。
8. 选择Debug→Breakpoits。在Breakpoints tab中点击Delete All,然后点击OK,全部断点都被清除。
在本节中,将使用CCS的profiling功能来统计标准puts()函数的执行情况,可以把这些结果与3.4节中采用DSP/BIOS API显示hello world消息的相应结果相比较。
1. 选择File→Reload Program。
2. 选择Profiler→Enable Clock。标记“√”出现在Profile菜单Enable Clock项的旁边,该选项使能就可计算指令周期。
3. 在Project View中双击文件hello.c.
4. 选择View→Mixed Source/ASM,灰色的汇编指令紧随在C源代码行后面。
5. 将光标放在下述行上:
puts(“hello world!\n”);
6. 点击工具栏按钮 (Toggle Profile_point),该C源代码行和第一条汇编指令被用绿色加亮。
7. 向下移动滚动条,将光标停在以下行上:
for (i = 0; i 8. 有关测试点的统计数据报告显示自前一个测试点或程序开始运行以来到本测试点所需的指令周期数。本例中,第二个测试点的统计数据报告显示自puts()开始执行到该测试点所需的指令周期数。 9. 选择Profile→View Statistics,窗口底部出现一个显示测试点统计数据的区域。 10. 注:上图中的line数可能会不同 本手册中屏幕上所显示的line数可能会和当前所使用的软件版本显示的line数不同。 11. 点击(RUN)工具栏按钮 或按F5键运行该程序并在提示窗口中键入一串字符。 12. 注:目标系统在测试点处于暂停状态 只要程序运行到一个测试点,它就会自动暂停。所以,当使用测试点时,目标系统应用程序可能不能满足实时期限的要求。(用RTDX则可能实现实时监控,这可参见1.5节。) 13. 在进入下一章之前(完成2.9节以后),执行以下步骤释放测试期间所占用的资源: o 进入profiler菜单并撤消 Enable Clock使能。 o 点击鼠标右键从弹出菜单中选择Hide从而关闭Profile Statistcs窗口。 o 进入profiler→profile_points, 选择Dlete All并点击OK。 o 进入View菜单,并撤消 Mixed Source/ASM使能。 为了进一步探究CCS,可作如下尝试: o 在Build Option窗口中,检查与编译器、汇编器和连接器有关的域,注意这些域中值的变化是怎样影响所显示的命令行的,可在CCS中参见在线帮助了解各种命令行开关。 o 设置某些断点。选择Debug→Breakpoints,注意在Breakpoints 输入框中可以设置条件断点,只有当表达式的值为真时,程序才会在断点处暂停。也可以设置各种硬件断点。 为了掌握关于使用CCS的更多的技巧,可参见有关CCS的在线帮助或CCS用户指南(PDF格式)。
点击工具栏按钮或者在该代码行上点击右键并从弹出菜单中选择Toggle Profile Pt。
通过拖拽该区域的边缘可调整其大小。
注意对第二个测试点所显示的指令周期数,它应该大约为2800个周期(显示的实际数目可能会变化),这是执行puts()函数所需的指令周期数。由于这些指令只执行了一次,所以平均值、总数、最大值和最小值都是相同的。
2.9 进一步探索
2.10进一步学习
本章通过使用DSP/BIOS优化第二章中的hello world实例介绍DSP/BIOS及如何创建、编译、调试和测试使用DSP/BIOS编写的程序。
基本要求:CCS的DSP/BIOS组件,目标板。
实现hello world程序的另一种方法是使用DSP/BIOS API的LOG模块,它能在嵌入式程序中提供基本运行服务。对于实时DSP上的应用而言,API模块是最优的。与诸如put()这样的C库函数调用不同,API无需中止目标板中运行的应用程序就能进行实时分析。此外,API代码比标准C库函数的I/O占用空间少且运行快, 根据程序需要可使用一个或多个DSP/BIOS模块。
本章使用DSP/BIOS API修改第二章中的应用程序 (如果要跳过第二章,则须从2.1和2.2节开始)。
在使用DSP/BIOS API的程序中必须创建一个配置文件,它定义了程序中使用的所有DSP/BIOS对象。本节介绍如何创建配置文件。
1.
2. 选择File→New→DSP/BIOS Config,弹出一个含有“c54xx.cdb”和“sd54.cdb”的窗口。
3. 在此窗口中选择与你的系统板相适应的DSP模板,然后点击OK(TMS320C54X DSP/BIOS 用户指南阐述了怎样创建一个用户模板),将出现上面这样一个窗口,点击左边的+和-字符能扩张和收缩列表单,窗口右边显示窗口左边选中对象的属性。
4. 在LOG-Event Log Manager处点击鼠标右键,从弹出菜单中选择Insert LOG, 这时创建一个名为LOG0的LOG对象。
5.
6. 选择File→Save。在弹出窗口中选择你的工作路径(通常是c:\ti\myprojects\hello 1),并将此配置保存为myhello.cdb,实际上创建了下述文件:
o myhello.cdb 保存配置设置
o myhellocfg.cmd 连接命令文件
o myhellocfg.s54 汇编语言源文件
o myhellocfg.h54 由myhellocfg.h54包含的汇编语言头文件
回顾上节所建立的配置文件,它实际上包括四个新文件myhello.cdb、myhellocfg.cmd、myhellocfg.s54、myhellocfg.h54。本节介绍如何向工程添加这些文件并删除被取代的文件。
1. 选择Project→Add Files to Project 在弹出窗口的文件类型框中选择配置文件(*.cdb),然后选择myhello.cdb并点击Open。注意此时在Project View中的DSP/BIOS Config文件夹下面包含配置文件myhello.cdb。另外,myhellocfg.s54作为源文件出现在source文件夹中。注意在编译工程文件的过程中,CCS在扫描文件间的依赖关系时自动向工程中添加包含文件(在此添加的是myhellocfg.h54)。
2. 输出文件名必须与.cdb文件名匹配(myhello.out和 myhello.cdb)。选择Project→Options 将出现Build Option窗口,然后选择Linker ,在Output Filename栏中确认输出文件名为myhello.out,点击OK。
3.
4. 点击Yes,则加入新生成的配置文件myhellocfg.cmd并取代hello.cmd。
5. 在Project View中的vectors.asm源文件上点击鼠标右键,然后从弹出菜单中选择Remove from project。DSP/BIOS配置文件将自动定义硬中断矢量。
6. 在RTS.lib库文件处点击鼠标右键将它从project中删除。该库已经由myhellocfg.cmd文件自动包含。
7. 双击程序hello.c打开并编辑该文件,在弹出的代码框中如果显示了汇编指令,则选择View→Mixed Source/ASM可隐藏汇编代码。
8. 源文件中需修改的内容如下。(可以从c:\ti\c5400\tutorial\hello2\hello.c中复制和粘贴)由于puts()和 LOG_printf使用同样的资源,你必须确保使用下面的主函数取代当前存在的主函数。
/* ======== hello.c ======== */
/* DSP/BIOS header files*/
#include
#include
/* Objects created by the Configuration Tool */
extern LOG_Obj trace;
/* ======== main ======== */
Void main()
{
LOG_printf(&trace, "hello world!");
/* fall into DSP/BIOS idle loop */
return;
}
9. 注意源程序中的下述几点:
(1)C源程序中包含std.h 和 log.h头文件。所有使用DSP/BIOS API的程序都必须包含头文件std.h 和 log.h。在LOG模块中头文件log.h定义了LOG_Obj的结构并阐述了API的功能。源代码中必须首先包含std.h,而其余模块的顺序并不重要。
(2)源程序中声明了配置文件中创建的LOG对象。
(3)主函数中,通过调用LOG_printf,将LOG对象的地址(&trace) 和hello world信息传到LOG_printf。
(4)主函数返回时,程序进入DSP/BIOS空循环,DSP/BIOS在空循环中等待软中断和硬中断信号,第五、六、七章将阐述这些内容。
10. 选择File→Save 或按Ctrl+S保存修改后的源程序。
11. 选择Project→Optins,在弹出窗口中选择Compiler,然后选择Category中的 Symbols,并在define symbols中删除FILEIO, 然后点击OK。
12. 点击工具栏按钮或选择Project→Rebuild All 。
由于使用LOG的程序只写了一行,没有更多的内容需要分析。在第五、六、七章中将用更多的方法分析程序功能。
1. 选择File→Load Program 选取myhello.out并点击open。
2. 选择Debug→Go Main。
3. 选择Tools→DSP/BIOS→Message Log,在CCS 窗口底部出现一个Message Log 窗口。
4. 在Message Log窗口中点击鼠标右键,从弹出的菜单中选择Property Page。
5. 选择trace作为监视对象,然后点击OK。缺省的刷新频率为1秒。(如果要修改刷新频率,可选择Tools→DSP/BIOS→RTA Control Panel。在RTA Control Panel处点击鼠标右键,选择Property Page并选取一个新的刷新频率,点击OK。)
6.
7. 选择Debug→Halt或按 Shift F5暂停程序运行。主函数返回后,程序在DSP/BIOS空循环中等待中断信号,欲了解空循环的更多信息,请参见3.5节。
8. 在Message Log中点击鼠标右键,然后选择Close关闭Message Log。在下一节中将使用Profiler,因此必须关闭Message Log。
9. 选择Tools→RTDX启动RTDX插件,并从下拉的菜单中选取RTDX disable,然后点击鼠标右键并选择Hide。
注意:在某些目标系统中Profiling 和RTDX不能同时使用。
当试图同时使用Profiling和RTDX时将导致错误信息,见上图。
LOG_printf所需的指令周期数,可像前面的puts()一样,利用CCS的功能来测算。
1. 选择File→Reload Program。
2. 选择Profiler→Enable Clock,在Enable Clock旁边可见到√。
3. 在Project View中,双击hello.c文件。
4. 选择View→Mixed Source/ASM,则灰色的汇编指令紧随C源程序。
5. 将光标放在LOG_printf(&trace, "hello world!")行上。
6. 点击工具栏按钮(Toggle Profile-point),则这一行和其下一行的汇编指令变为绿色高亮显示。
7. 向下移动滚动条,把光标放在程序结尾的大括号所在的行上,然后点击工具栏按钮(Toggle Profile-point),你可能会认为在程序的return行上设置了第二个测试点。但是,要注意直到大括号后一直没有相应的汇编语言显示出来。如果在return这一行上设置了测试点,CCS 将在程序运行时自动纠正这一问题。
8. 选择Project→View Statistics。
9. 点击(Run)工具栏按钮或按F5运行程序。
10.
11. 点击工具栏按钮或按Shift F5暂停程序运行。
12. 在进行下一章的工作之前(3.5节结束之后)做下述工作,释放测试时占用的资源。
o 进入Profiler 菜单,撤消Enable Clock前的“√”。
o 在Profiler Statistics 窗口中点击鼠标右键,并从打开的菜单选择Hide
o 选取Profiler→Profile-points,然后选择Delete All ,点击OK。
o 进入View菜单,撤消Mixed Source/ASM前的“√”。
o 关闭所有的源文件和配置窗口。
o 选择Project→Close关闭Project
为进一步了解CCS,试作如下工作:
o 加载myhello.out 并在LOG_printf行设置断点,选取Debug→Breakpoints并在IDL_F_loop上设置断点。(在弹出对话框的Location栏中键入IDL_F_loop,并点击Add)。
运行程序 在第一个断点处,使用ViewCPU RegistersCPU Registers观察寄存器值。注意:当主函数执行时,INTM=1表明中断非使能。
运行到下一个断点 注意现在INTM=0,表明中断使能。注意在执行程序时将重复遇到该断点。
启动进程和主函数执行完毕后,DSP/BIOS应用程序将进入空循环的后台线程。空循环由IDL 模块管理, 直到程序暂停时才结束工作;它在中断使能有效时循环,且允许响应任一ISR中断信号,能满足实时任务处理的要求。第五、六、七章将进一步阐述ISRs和DSP/BIOS的软中断。
o 在MS-DOS窗口中,键入以下命令行可运行sectti.exe程序。如果安装路径不是c:\ti,则须将路径修改为安装了CCS 的目录路径。
cd c:\ti\c5400\tutorial\hello1
sectti hello.out > hello1.prn
cd ..\hello2
sectti hello.out > hello2.prn
比较hello1.prn和 hello2.prn文件可以发现使用stdio.h和DSP/BIOS时存储器段和空间大小的差别。与使用stdio中的puts()函数相比,DSP/BIOS调用LOG_printf时.text段占用的空间小。有关sectti工具的其它信息可参见TMS320C54x DSP/BIOS 用户指南。
进一步学习使用CCS 和DSP/BIOS,请参见CCS中 的在线帮助,也可参见CCS 用户指南和TMS320C54x DSP/BIOS 用户指南。
本章说明创建和测试一个简单算法的过程并介绍CCS附加功能。
本章将创建一个完成基本信号处理的程序,并在下两章继续介绍。
可用存储在PC机文件中的数据来建立和测试一个简单的算法,也可利用CCS的探针断点、图形显示、动态运行和GEL文件。
在CCS中打开一个工程文件并查看此工程中源文件和库文件。
1. 若CCS安装在c:\ti,那么就在c:\ti\myprojects下创建文件夹volume1(若CCS安装在其它位置,那么就在相应位置创建文件夹volume1)。
2. 将文件夹c:\ti\c5400\tutorial\volume1中的所有文件复制到新文件夹。
3. 如果CCS应用程序还未运行,则在开始菜单中选择ProgramCode Composer Studio’C5400CCStudio。
4. 选择ProjectOpen并在volume1中选择volume.mak文件并点击Open。
5.
6. 点击符号+展开Project View,在Project中包含VOLUME.MAK、 Include、Libraries、Source。
该Project中的主要文件有:
o volume.c 包含main()函数的C源程序
o volume.h 源程序volume.c包含的头文件,其中定义了各种常数和结构。
o load.asm 此文件包含load子程序,该子程序是一个能从C函数中调用的简单汇编循环子程序,该函数有一个入口参数、执行所需的指令周期为(31*argument)+13。
o vectors.asm 此文件在第二章使用过,它定义了DSP的中断向量表
o volume.cmd 连接命令文件,它将各段映射到存储器中。
o rts.lib 为DSP目标系统提供运行支持。
在Project View窗口中双击volume.c文件,源程序就显示在CCS窗口的右边。
注意实例中的下面几部分:
o 主函数打印完信息后,应用程序处于无限循环状态。在此循环中,主函数调用dataIO和processing()函数。
o processing()函数将增益与输入缓存区中的各值相乘并将结果存入输出缓存区;同时也调用汇编Load子程序,该子程序占用的指令周期取决于传递给它的processingLoad值。
o dataIO函数是一个空函数,它的作用类似于return语句。可利用CCS中的探针(Probe Point)功能把主机文件中的数据读取到inp_buffer缓存区,此法优于用C代码来完成I/O功能。
#include
#include "volume.h"
/* Global declarations */
int inp_buffer[BUFSIZE]; /* processing data buffers */
int out_buffer[BUFSIZE];
int gain = MINGAIN; /* volume control variable */
unsigned int processingLoad = BASELOAD; /* processing load */
/* Functions */
extern void load(unsigned int loadValue);
static int processing(int *input, int *output);
static void dataIO(void);
/* ======== main ======== */
void main()
{
int *input = &inp_buffer[0];
int *output = &out_buffer[0];
puts("volume example started\n");
/* loop forever */
while(TRUE)
{
/* Read using a Probe Point connected to a host file. */
dataIO();
/* apply gain */
processing(input, output);
}
}
/* ======== processing ======== *
* FUNCTION: apply signal processing transform to input signal.
* PARAMETERS: address of input and output buffers.
* RETURN VALUE: TRUE. */
static int processing(int *input, int *output)
{
int size = BUFSIZE;
while(size--){
*output++ = *input++ * gain;
}
/* additional processing load */
load(processingLoad);
return(TRUE);
}
/* ======== dataIO ======== *
* FUNCTION: read input signal and write output signal.
* PARAMETERS: none.
* RETURN VALUE: none. */
static void dataIO()
{
/* do data I/O */
return;
}
本节介绍探针断点(Probe Point)的使用方法。探针可以从PC机的文件中读取数据,它是开发算法的一个有效工具。其使用方法如下:
o 将来自PC主机文件中的输入数据传送到目标系统的缓存器中供算法使用。
o 将来自目标系统缓存器中的输出数据传送到PC主机的文件中供分析。
o 用数据更新窗口,如图形窗口。
与断点类似,它们都挂起目标系统来完成自己的动作,但存在如下几个方面的差别 :
o 探针立即中止目标系统,完成一个操作后,再恢复目标系统的运行。
o 断点暂停CPU直到人工恢复其运行为止,且更新所有打开的窗口。
o 探针允许自动执行文件的输入或输出,而断点则不行。
本章介绍如何利用探针把PC机文件内容传送到目标系统中作为测试数据使用。当到达探测点时,同时使用断点更新所有打开的窗口,这些窗口包括输入和输出数据的图形窗口。第七章将阐述管理输入和输出数据流的两种方法。
1. 点击工具栏按钮或选择Project→Rebuild All 。
2. 选择File→Lode Program并选取volume.out ,然后点击Open。
3. 在Project View窗口中,双击volume.c文件。
4. 将光标置于主函数中的 dataIO( )这一行上。DataIO函数起占位符作用。现在,它是一个很好的与探针断点相连接的地方,以便于从PC机文件输入数据。
5. 点击工具栏按钮(Toggle Probe Point),则光标所在行变为兰色高亮。
6. 选择File→File I/O,在File I/O 对话窗中可选择输入和输出文件。
7. 在File Input 栏中,点击Add File。
8. 选择sine.dat 文件。
注意:在文件类型框中可以选择数据格式,sine.dat 文件包含正弦波形的16进制值。
9.
10.
o Address栏中的值指定来自文件的数据将要存放的位置,inp_buffer 是由volume.c文件声明为BUFSIZE的整数数组。
o Length栏中的值指定每次探针到达时读入多少个数据样点,使用100是因为BUFSIZE常数已由volume.h(0x64)设置为100。
o 当探针到达文件结尾时,Wrap Around选项使CCS从文件的开始读数据。即使数据样点只含有1000个值且每次探针到达时读取100个值,也可将数据看作连续的数据流。
11. 点击Add Probe Point,Break\Probe\Profile Points 对话窗的Probe Point栏就会出现。
12. 加亮(对话框中)显示的第五步的断点设置。
13. 点击Connect栏尾处的下箭头,在其下拉菜单中选择sine.dat 文件。
14. 点击Replace。 Probe Point列表将显示探测点已连接到sine.dat 文件。
15. 点击OK。 File I/O对话框则显示文件现已被连接到探测点。
16. 在File I/O对话框,点击OK。
如果现在就运行程序的话,你将无法了解到更多的程序运行时的信息。可以在 inp_buffer 和 out_buffer数组的地址范围内设置观察变量,但需要设置很多变量,而且是按数字形式显示而非图形形式。
CCS 提供了多种用图形处理数据的方法。在本例中,你将看到一个基于时间绘制的图形。本节介绍图形的打开,下节介绍程序的运行。
1. 选择View→Graph→Time/Frequency。
2.
3. 点击OK,出现输入缓存的一个图形窗。
4. 在上述窗中右击鼠标,从弹出的菜单中选择Clear Display。
5. 再次选择ViewGraphTime/Frequency。
6. 改变Graph Title的属性为Output Buffer,改变Start Address的属性为Out_buffer,其余的设置都不变。
7. 点击OK,又出现一个图形窗,在该图形窗内右击鼠标,从弹出的菜单中选择Clear Display。
到目前为止,你已经放置好了一个探针,它可临时暂停目标系统,将数据从PC主机传送到目标系统,并将恢复目标系统应用程序的运行。但是,探针不能刷新图形。在本节中,将设置一个可刷新图形的断点,使用Animate 命令在遇到断点后,自动恢复目标系统应用程序的运行。
1. 在C源程序volume.c窗口中,将光标放置在dataIO行。
2. 点击(Toggle Breakpoint)工具栏按钮或按F9,该行显示为红色和蓝色高亮(除非用Option→Color改成其它颜色),表明在这一行已经设置了断点和探针。在同一行上既放置探针又放置断点,它能够使目标系统只暂停一次而完成两个操作:数据传输和图形刷新。
3. 重新安排窗口以便能同时能看到这两个图形。
4. 点击工具栏按钮或按F12运行程序。Animate命令与Run命令相似,它使目标系统应用程序一直运行到断点,随后,目标系统应用程序暂停并刷新窗口。但是,与Run命令不同的是,Animate命令恢复目标系统应用程序运行到下一个断点,而且此过程是连续的,直到目标系统被人工停止。所以,Animate命令可看作运行-中断-继续(run-break –continue)过程。
5.
注意:目标系统运行程序在探测点暂停
不管何时到达探测点,CCS都能暂时停止目标系统。因此,如果使用了探针,目标系统应用程序就不能满足实时期限的要求。在本开发阶段只测试算法,以后将用RTDX和DSP/BOIS分析实时性能。
只使用测试点和Run命令也能刷新图形,4.10节将详细介绍。
回顾4.2节,processing函数将增益与输入缓存区中的各值相乘并将结果存入输出缓存区;在一个While循环中用如下语句完成此功能。
*output++ = *input++ * gain;
该语句将增益与输入缓存区中的各值相乘并将结果存放在out_buffer中相应的位置上。gain初始化为MINGAIN,而MINGAIN已经在volume.h中定义为1。要改变输出幅度得修改gain值。修改gain值的一种方法是采用观察变量。
1. 选择view→Watch Window
2. 在Watch窗中右击鼠标,并从弹出菜单中选择Insert New Expression。
3. 在Expression区敲入gain并单击OK,变量值出现在Watch窗口。
4. 如果程序已暂停,点击工具栏按钮(Aminate),重新开始运行程序。
5. 在Watch窗口中双击gain。
6. 在Edit Variable窗口中修改gain值为10,并点击OK。
7. 注意在Output Buffer图形中信号幅度变化反映了增益的提高。
你曾使用Watch Window观察过变量并改变变量的值。但当你想查看的变量的作用域不在当前设置的断点范围内时,则可使用访问堆栈来查看。
1. 点击工具栏按钮或按Shift F5暂停程序运行。
2. 用CCS 重新查看volume.c程序。注意在主函数与processing函数中已经定义了变量*input,但它没有在数据输入输出函数中定义。
3. 在显示源程序volume.c的窗口中,把光标放置在dataIO()函数的return行上。
4. 点击工具栏按钮或按F9,该行变为红色高亮显示(除非你用Open→Color改变颜色)。
5.
6. 点击OK
7. 按下F5,程序运行直到dataIO()函数末尾的断点处暂停。
8.
9. 在Expression区键入*input并点击OK。
10.
11. 选择View→Call Stack,则可看到相邻的堆栈窗与观察窗。
12.
13. 可以点击堆栈窗底部的地址以便看清楚gain是全局变量,而*input则不是。(地址的变化依赖于正使用的DSP)
14. 在堆栈窗中点击鼠标右键并从弹出菜单中选择Hide。
15. 将光标放置在datdIO()函数中的return之后的行上,撤消第4步中放置的断点,点击工具栏按钮或单击F9。
CCS 提供了修改变量的另一种方法,该方法使用一种扩展语言GEL来创建可修改变量的小窗口。
1. 选择File→Load GEL。在Load GEL File对话框中选择volume.gel文件并点击Open,这个选项是在上步加载GEL文件时自动增加的。
2. 选择GEL→Application Control→Gain,弹出如右图所示的小窗口。
3. 如果程序已经暂停,点击工具栏按钮 (Animate)。注意即使在弹出的gain小窗口中值为零,其实gain的当前值并未改变。只有滑动指针时gain值才发生变化。
4. 在gain窗口中用滑动指针改变gain值,则在Output Buffer窗口中的正弦波形幅度相应改变。此外,无论任何时候移动滑动指针,在Watch窗口的变量gain的值将随之改变。
5. 点击工具栏按钮或按下Shift F5暂停程序运行。
6. 为了了解Gain GEL函数的工作情况,点击Project View中GEL文件前的 +符号,然后在VOLUME.GEL文件上双击鼠标便可查看其内容:
menuitem "Application Control"
dialog Load(loadParm "Load")
{
processingLoad = loadParm;
}
slider Gain(0, 10 ,1, 1, gainParm)
{
gain = gainParm;
}
Gain函数定义的滑动指针范围:0到10,其步长为1。当移动滑动指针时,变量gain的值将随滑动指针的改变而改变。
在第二章中曾使用测试点(profile-points)测试puts()所需的指令周期数。现在,来使用测试点查看变量processingLoad改变后的结果,此结果将传递给汇编Load程序。 ProcessingLoad初始化为BASELOAD, 而BASELOAD在volume.h中定义为1。
1. 选择Profiler→Enable Clock,确保Enable Clock使能。
2. 在Project View 中,双击volume.c文件。
3. 选择View→Mixed Source/ASM使能,查看C源程序及其相应汇编指令。
4. 把光标放置在 load(processingLoad) 行后的汇编指令上。
5. 点击工具栏按钮或点击鼠标右键选择Toggle Profile Pt。
6. 把光标放置在 return(true) 行后的汇编指令上。
7. 点击工具栏按钮(Toggle Profile-point)。
8. 选择Profiler→View Statistics。在Profile Statistics 窗口中的location栏显示了新增测试点对应的汇编指令或地址。可以通过改变Statistics area区域的大小查看更多内容;或者在Statistics area区域内点击鼠标右键,选择Allow Docking可在一个单独窗口中显示Statistics。
9. 点击工具栏按钮或按F12。
10.
11. 选择GEL→Application Control→Load。
12.
13. 在Profile Statistics窗口中点击鼠标右键,从弹出菜单中选择Clear All,这将把Statistics复位为0。平均值、最大值和最小值都等于当前processingLoad的指令周期数。
14. 点击工具栏按钮或按Shift F5暂停程序运行。
15. 在第五章开始之前,先执行下列步骤释放在本节中使用的资源
o 关闭Load、Gain控制窗口、sine.dat控制窗口以及Time/Frequency图形窗。
o 选择File→File I/O并点击Remove File删除sine.dat文件。
o 选择Profiler菜单撤消Enable Clock前的“√”。
o 在Profile Statistics窗口中点击鼠标右键并在弹出菜单中选择Hide。
o 选择Debug→Breakpoints,然后选择Delete All并点击OK。
o 选择Debug→Probe Points,然后选择Delete All并点击OK。
o 选择Profiler→profile-point,然后选择Delete All并点击OK。
o 选择View菜单撤消MixedSource/ASM前的“√”。
o 关闭打开的窗口和工程(Project→Close)。
o 在project View中的volume.gel上击鼠标右键并选择Remove。
o 在Watch Window中删除表达式并隐藏Watch Window。
为了进一步了解CCS,试做如下工作:
o 把processingLoad加到Watch Window,当使用Load GEL 控制时,在Watch Window中processingLoad的值将被更新。
o 在Watch Window中点击鼠标右键,在弹出菜单中选择Insert New Expression,并点击Help按钮则可得到你可以使用的数据格式。试用各种不同的格式。例如:你可键入*input,x作为Expression观察正弦输入数据的16进制格式。
o 在volume.h文件中把BUFSIZE修改为0x78(或120)并重新编译,然后重新加载程序。选择File→File I/O,将对话框中Length值修改为0x78。选择View→Graph→Time/Frequency,在弹出的图表中将Acquisition Buffer Size和Display Data Size均修改为0x78,这将使缓存器存入3个完整的正弦波而不是2.5个。点击工具栏按钮(Animate),注意缓冲器输入输出波形是同相的。
o 试着使用时钟数来实现测试点的统计计数。用断点代替测试点,选择Profiler→View Clock。将程序运行到第一个断点, 双击clock使统计数清零。再次运行程序,时钟则显示了程序运行到第二个断点的周期数。
o 使用探针重复4.3节到4.5节,这次只使用探针和Run命令。由于一个探测点只能对应一个操作,所以需要设置三个探测点。现在,有两个图形需要刷新,一个文件作为输入,每一个操作都有各自的探针。
注意每一个探测点必须设置在不同的代码行上。结果,目标系统需要暂停三次,而且在目标系统运行时,操作不能在同一个探测点完成。由于上述原因,本节中将探针和断点结合比只使用探针更有效。
o 为了练习用CCS编译工程文件。将c:\ti\c5400\tutorial\volume1文件夹中的所有文件拷贝到一个新文件夹中。首先,删除volume.mak文件,然后使用CCS的Project 菜单项中的Project→New 和Project→Add File重建工程。可参见4.1节。
进一步学习关于Probe Points、graphs、animation和GEL文件的知识,请参见CCS中的在线帮助或CCS用户指南。
本章介绍程序调试技术和几个DSP/BIOS插件模块。
在本章中,将修改第四章的应用程序实例创建一个多线程的实例并为调试目的查看执行性能,还可以了解有关DSP/BIOS的更多的功能,其中包括Execution Graph、实时分析控制板(RTA Control Panel)、Statistics View和CLK、SWI、STS、TRC模块。
基本要求:目标板和CCS的DSP/BIOS组件。
首先在CCS中打开工程,查看工程中的源文件和库文件。
1. 如果CCS安装在c:\ti目录下,就创建c:\ti\myprojects\volume2目录。(如果CCS安装在其它位置,就在相应位置创建volume2目录)
2. 将目录c:\ti\c5400\tutorial\volume2下的所有文件拷贝到新目录下。
3. 从WINDOWS“开始”菜单中选择“程序”→Code Composer Studio 5400→CCStudio
4. 选择Project→Open,在文件夹中选择volume.mak文件并点击Open。点击Project、VOLUME.MAK、 DSP/BIOS Config和Source后面的+号展开Project View。根据配置文件创建的volumecfg.cmd文件包含许多DSP/BIOS头文件(不需要检查所有的头文件)
工程中的文件包括:
o volume.cdb 配置文件。
o volume.c 包含main()函数的C源程序
o volume.h 包含在volume.c中的头文件,它定义了各种常数和结构,它与前一章所用的volume.h文件相同。
o load.asm 此文件包含Load子程序,该子程序是一个能从C函数中调用的简单汇编循环子程序。它与前一章中所用的load.asm相同。
o volumecfg.cmd 连接命令文件,在保存配置文件时创建
o volumecfg.s54 汇编源文件,在保存配置文件时创建
o volumecfg.h54 头文件,在保存配置文件时创建
本章通过由第四章的应用程序修改而得的程序实例来介绍实时操作。该实例采用片内定时器中断模拟周期性的外部中断实现数据的输入/输出,只需对其稍加修改就可真正通过外部中断实现数据的输入/输出。
1. 在Project View中双击volume.c,则源程序显示在CCS窗口的右半部分。
2. 注意本实例中的下述几个方面:
o 数据类型的变化。DSP/BIOS提供的数据类型适用于其它处理器,它的绝大部分数据类型与C语言的数据类型相对应。
o C源程序中包括三个DSP/BIOS头文件:std.h、 log.h和swi.h,而且std.h必须放在其它DSP/BIOS头文件之前。
o 配置文件中创建的对象声明为外部变量。你可在下一节查看配置文件。
o 主函数不再调用dataIO和processing函数,而仅仅是在调用LOG_printf显示信息后返回,这将使应用程序进入DSP/BIOS空循环,而后由DSP/BIOS处理各线程。
o processing函数由processing_SWI软中断调用,软中断的优先级低于所有硬件中断。但也可以用硬件中断ISR直接完成信号处理。然而,信号处理可能需要大量机器周期而无法在下一次中断信号到达之前完成,这将妨碍中断信号的处理。
o dataIO函数调用SWI_dec,SWI_dec利用软中断作计数器减法。当计数器为0时,软中断就安排函数的执行并复位计数器。
dataIO函数仿真基于硬件的数据I/O,一个典型的程序就是在缓存区积累数据,直到有足够的处理数据为止。本实例中,每当processing函数运行一次,dataIO函数就执行10次,计数器的减计数由SWI_dec控制。
#include
#include
#include
#include "volume.h"
/* Global declarations */
Int inp_buffer[BUFSIZE]; /* processing data buffers */
Int out_buffer[BUFSIZE];
Int gain = MINGAIN; /* volume control variable */
Uns processingLoad = BASELOAD; /* processing load value */
/* Objects created by the Configuration Tool */
extern LOG_Obj trace;
extern SWI_Obj processing_SWI;
/* Functions */
extern Void load(Uns loadValue);
Int processing(Int *input, Int *output);
Void dataIO(Void);
/* ======== main ======== */
Void main()
{
LOG_printf(&trace,"volume example started\n");
/* fall into DSP/BIOS idle loop */
return;
Debugging Program Behavior /* ======== processing ======== *
* FUNCTION: Called from processing_SWI to apply signal
* processing transform to input signal.
* PARAMETERS: Address of input and output buffers.
* RETURN VALUE: TRUE. */
Int processing(Int *input, Int *output)
{
Int size = BUFSIZE;
while(size--){
*output++ = *input++ * gain;
}
/* additional processing load */
load(processingLoad);
return(TRUE);
}
/* ======== dataIO ======== *
* FUNCTION: Called from timer ISR to fake a periodic
* hardware interrupt that reads in the input
* signal and outputs the processed signal.
* PARAMETERS: none
* RETURN VALUE: none */
Void dataIO()
{
/* do data I/O */
/* post processing_SWI software interrupt */
SWI_dec(&processing_SWI);
对于本实例,DSP/BIOS的配置文件已经创建。在本节中,你可以查看缺省配置中的对象。
1. 在Project View双击volume.cdb文件(在DSP/BIOS的Config文件夹中)
2. 点击CLK、 LOG和 SWI managers旁边的符号+。
3. 点击LOG中的trace项,你可以从窗口的右半部分查看它的特性。这些特性与3.1节创建的trace LOG是一样的。volume.c调用LOG_printf将volume example started写入这个log中。
4.
5. 将buflen域的值修改为512,点击OK。
6. 高亮度显示CLK目标dataIO_CLK。注意,当CLK目标被激活时才调用_dataIO函数,它是volume.c中的数据I/O函数。
注:前缀与C函数名称
由于保存配置文件时会产生汇编语言文件,所以C函数名称要加一下划线作前缀。此下划线前缀是约定由汇编转而访问C函数的一种标记。(其细节可参见TMS320C54x最佳化C编译器用户指南有关C语言和汇编语言接口部分)。
此规则仅适用于用户编写的C函数,对于配置文件产生的对象或DSP/BIOS API调用则无须加下划线前缀,因为相应的两种名称会自动建立,一种会被加上前缀,一种则不会有前缀。
7. 由于dataIO函数不再在主函数中被调用,那由什么事件来激活该CLK对象呢?要想找到答案,在CLK-Clock Manager对象上点击鼠标右键并从弹出菜单中选择Properties,你将看到Clock Manager Properties对话窗口。
注意,在Enable CLK Manager项前有可选标记,当选中时由定时器中断驱动CLK管理器。
8.
9. 展开HWI对象查看HWI_TINT的属性,其中断源是DSP 定时器,当片内定时器引起中断时,它运行CLK_F_isr函数。CLK对象函数的运行是由CLK_F_isr硬件中断服务函数引发的,它的优先级高于软中断,一旦运行便不会被打断。(由于CLK_F_isr已经保护了寄存器现场,所以CLK 函数不需要象硬件中断服务程序中正常情况下须做的那样保存和恢复现场。)
10. 在软中断对象processing_SWI上点击鼠标右键并从弹出菜单中选择Properties。
o
o mailbox mailbox域的值可控制何时运行软中断。有几种API调用会影响mailbox的值,并且所产生的值将决定是否登记软中断。当软中断被登记时,具有最高优先级的软中断或硬中断服务例程将运行。
o arg0, arg1 传递给processing函数的inp_buffer和 out_buffer的地址。
11. 不作任何改变仅点击Cancel关闭Properties对话窗口,。
12. 由于processing函数不再在主函数中运行,那什么事件将导致SWI对象运行其函数?在源程序volume.c中, SWI_dec被dataIO函数调用,它递减mailbox域中的值,当mailbox域中的值为0时,则登记软中断。所以,data_CLK对象运行dataIO函数10次,SWI对象就运行其函数一次。
13. 选择File→Close,将询问是否保存修改过的volume.cdb文件。点击Yes保存,保存时将产生volumecfg.cmd、volumecfg.s54和volumecfg.h54。
14. 点击工具栏按钮或选择Project→Build。
当在processing函数中设置探测点并使用图形方式观察输入输出结果时(见前一章),你已经完成了信号处理算法的测试。本阶段注意的焦点应该是明确任务可以满足实时期限的要求。
1. 选择File→Load并选取volume.out,然后点击OK。
2. 选择Debug→Go Main,程序运行到主函数的第一条语句。
3. 选择Tools→DSP/BIOS→RTA Control Panel,在CCS窗口底部将出现几个可选项。
4. 在几个可选项所在窗口区域内点击鼠标右键,取消Allow Docking显示方式或选择Float in Main Windows方式显示RTA Control Panel。调整窗口尺寸以便看到所有选项。
5. 在选择框内放置选中标志使能SWI和CLK,并使能global host enable,如右图示。
6. 选择Tools→DSP/BIOS→Execution Graph。Execution Graph出现在CCS窗口底部,并可调整其显示方式和大小。
7. 在RTA Control Panel上点击鼠标右键并从弹出菜单中选择Property Page。
8. 确认Message Log/Execution Graph的刷新频率为1秒,然后点击OK。
9.
10. 在Time行的标记给出了Clock Manager运行一次CLK函数的时间。按标记计算processing_SWI执行的时间间隔。在此有10个标记表明:dataIO_CLK对象每执行10次,processing_SWI对象就执行一次。这正如所预料的一样,因为被dataIO函数递减的mailbox域的起始值为10。
使用Execution Graph,你可以看到该程序满足其实时期限的要求。然而,一个典型应用程序的信号processing函数所要完成的任务会比将数据乘以一个系数并将结果拷贝到另一缓冲区中更复杂、耗费的周期数更多。为此,可以通过增加Load函数占用的指令周期来模拟这样的复杂任务。
注:在本实例中Load值
下面的Load值适用于以100MIPS运行的C549的。如果所采用的C54x是以不同速率的运行的,则需要将值乘以该C54x的MIPS/100。如果不知道该MIPS值,可打开volume.cdb查看称之为DSP MIPS的Global Setting属性(CLKOUT)。
1. 选择Tools→DSP/BIOS→CPU Load Graph,将出现一个空白的CPU Load Graph窗口。
2. 在RTA Control Panel上点击鼠标右键并从弹出菜单选择Property Page。
3. 将Statistics View/CPU Load Graph中的Refresh Rate修改为0.5秒并点击OK。注意当前CPU的load值非常低。
由于Statistics View和CPU Load仅将少量数据从目标板传送到主机,因此你可以频繁地刷新这些窗口数据而不会对运行程序造成大的影响。Message Log和Execution Graph传送的数据是有关配置文件中定义的LOG对象的缓存长度属性的,其数据量大,因此不能频繁地刷新这两个窗口。
4. 选择File→Load GEL并选择volume.gel,然后点击Open。
5. 选择GEL→Application Control→Load。
6. 键入3000作为新的load值,然后点击Execute,CPU负荷增加到7%左右。
7. 在Execution Graph项点右键,从弹出菜单选择Clear,注意此时程序仍满足其实时期限的要求。在processing_SWI函数各次执行之间存在10个时间标记。
8. 使用GEL控制修改load值为5000,然后点击Execute。
9.
10. 使用GEL控制修改load值为3000,然后点击Execute。CPU的负荷增加到95%左右。
11.
12. 使用GEL控制修改load值为35000,然后点击Execute。由于刷新过程在空闲任务中实现,而空闲任务在该程序中具有最低优先级,所以CPU Load Graph窗口 和 Execution Graph窗口将停止频繁刷新甚至于可以停止刷新。又由于其它高优先级线程占用了CPU的全部处理时间,因此无足够的时间用于主机控制完成更新。此时,程序不满足其实时期限的要求。
13. 选择Debug→Halt,这将暂停程序的运行并刷新Execution Graph窗口。当应用程序不满足实时期限的要求时,窗口中的Assertions行将显示出错信息。
14. 使用GEL控制修改load值为10,然后点击Execute,则CPU Load Graph和Execution Graph窗口将再次刷新。
注:采用RTDX修改Load
采用Load GEL控制可暂停目标系统。如果正在分析一个实时系统,又不想影响系统性能,则可采用RTDX修改Load。下一章将说明如何用RTDX修改实时Load。
可使用DSP/BIOS的其它控制功能查看DSP的Load值和processing_SWI对象的处理过程的统计数据。
1. 选择Tools→DSP/BIOS→Statistics View将出现一个Statistics View区域,它显示Load DSP/BIOS程序和/或设置使用控制功能的属性。
2.
3.
4. 在RTA Control Panel中,在SWI累积器前放置选中标记“√”。
5. 若已暂停程序,点击工具栏按钮 (Run)。
6. 注意Statistics View中的Max值,SWI的统计计数单位为指令周期。
7. 使用GEL控制增加load值,然后点击Execute。注意Max值的改变,这是为从processing_SWI运行开始到结束所完成的指令数增加了。
8. 使用不同的load值试验。减小load值,在Statistics View区域内点击鼠标右键并从弹出菜单中选择Clear,这将把所有统计域复位到它们各自的最小可能值,这样你可以从Max域中观察到当前的指令周期数。
9. 点击工具栏按钮(Halt),关闭所有已经打开的DSP/BIOS和GEL控制项。
在前面的章节中,曾用Statistics View观察了软件中断服务例程执行期间完成的指令周期数。如果使用配置文件,DSP/BIOS自动支持统计功能,这称为隐式测试。也可使用API调用收集其他统计数据,这称为显式测试。
1. 在Project View中,双击volume.cdb文件(该文件在DSP/BIOSConfig文件夹中)以便打开它。
2. 在STS manager上点击鼠标右键并从弹出菜单中选择Insert STS。
3. 将新增加的对象STS0更名为processingLoad_STS。该对象的缺省属性完全是正确的。
4. 选择File→Close,将询问你是否保存修改过的volume.cdb,点击YES。
5. 在Project View中,双击volume.c打开它进行编辑。对程序作如下修改:
o 在包含swi.h的文件的那一行下中增加下列内容:
#include
#include
#include
o 在标有注释 “Objects created by the Configuration Tool”的程序段中添加下述声明语句:
extern STS_Obj processingLoad_STS;
o 在load函数调用前的processing函数中添加以下内容:
/* enable instrumentation only if TRC_USER0 is set */
if (TRC_query(TRC_USER0) == 0) {
STS_set(&processingLoad_STS, CLK_gethtime());
}
o 在load函数调用后的processing函数中的添加如下语句:
if (TRC_query(TRC_USER0) == 0) {
STS_delta(&processingLoad_STS, CLK_gethtime());
}
6. 选择File→Save保存修改过的volume.c文件。
7. 点击工具栏按钮或选择Project→Build。
要观察由新增STS显式测试所提供的信息,可使用Statistics View和 RTA Control Panel。
1. 选择File→Load Program,选择你刚刚建立的程序volume.out,然后点击Open。
2. 选择Tools→DSP/BIOS→RTA Control Panel。
3. 在RTA Control Panel区域点鼠标击右键,然后取消Allow Docking选项使RTA Control Panel显示为一个独立的窗口。调整窗口尺寸到能够看到所有选项。
4. 将选中标记“√” 放置在enable SWI accumulators、enable USER0 trace和global host enable前面的选择框中 。
使能USER0跟踪,使得TRC_query(TRC_USER0)调用的返回值为0。
5. 选择Tools→DSP/BIOS→Statistics View。
6. 在Statistics View区域点击鼠标右键并从弹出菜单中选择Property Page,然后加亮对象processing_SWI和processingLoad_STS,并加亮所有的四个统计选项。
7.
8. 点击工具栏按钮或选择Debug®Run。
9. 用processingLoad_STS的Max值减去processing_SWI的Max值,其结果约为1445条指令(实际显示的值可能有变化)。SWI的统计数据是用指令周期来度量的。因为曾用CLK_gethtime函数作为处理load值的基准,所以processingLoad_STS由片内定时计数器计数,它等同于指令周期数。这些指令是在processing函数中执行的,而不是在STS_set和STS_delta调用之间执行的,如下所示。
10. 选择GEL→Application Control→Load(如果已关闭CCS 而后又重新启动它,则必须重装GEL文件)
11. 修改load值,然后点击Execute。
12. 注意当两个Max都增加时,而它们的差值却保持不变。
13. 从RTA Control Panel中取消enable USER0 trace前的选中标记“√”。
14. 在Statistics View区域内点击鼠标右键并从弹出菜单中选择Clear。
15. 注意,processingLoad_STS的统计值没有改变,这是因为没有选中USER0跟踪选项,使下面这条语句的条件不能满足:
if (TRC_query(TRC_USER0) = = 0)
因此,不执行对STS_set和 STS_delta的调用。
16. 完成下面的步骤,以便为下一节做准备。
o 点击工具栏按钮或按Shift F5暂停程序的运行。
o 关闭所有GEL对话窗口、DSP/BIOS插件和源程序窗口。
为了进一步探索DSP/BIOS,试做下述工作:
o 在配置文件中,将SWI Manager的Statistics Units的属性修改为毫秒或微秒,重新编译和加载应用程序并请注意观察Statistics View中统计值的变化情况。
o 修改volume.c源文件,用CLK_getltime函数代替CLK_gethtime函数。重新编译和加载应用程序并观察Statistics View中统计值的变化情况。函数CLK_getltime使Execution Graph窗口中时间标记分辨率变低。当使用CLK_getltime时,必须明显地增加load值以改变Statistics View中的数值。
欲了解有关CLK、SWI、STS和TRC模块的知识,请参见CCS中的在线帮助或TMS320C54x DSP/BIOS用户指南。
本章介绍程序的实时分析技术并纠正程序中存在的错误。
本章中,将用第五章的例子来作实时分析并纠正与实时性有关的问题。将采用RTDX对目标系统作实时改动,将使用DSP/BIOS周期函数并设置软中断优先级等。
基本要求:CCS的DSP/BIOS和RTDX组件、目标板
本章的工作是在前一章工作基础上进行的,如果没有做前一章的工作,可以把目录c:\ti\c5400\tutrial\volume3中的文件拷贝到你的工作文件夹下。
1. 从目录c:\ti\c5400\tutrial\volume4下拷贝下述文件到你的工作文件夹中(注:不要拷贝所有文件,特别不要拷贝volume.cdb)
o volume.c 采用RTDX的源程序,它无需中止运行程序即可修改load值。
o loadctrl.exe 用VB5.0编写的Windows应用程序,它采用RTDX实时发送load值到目标板中。
o loadctrl.frm,loadctrl.frx,loadctrl.vbp 如果你拥有VB5.0开发环境,你可以用它来查看loadctrl.exe应用程序的源文件。
2. 从Windows开始菜单中,选择Programs→Code Composer Studio ’C5400→CCStudio。
3. 选择Project→Open并从你的工作文件夹中打开volume.mak。
在本例中,你需要增加一个新对象到配置文件volume.cdb中(该文件已经存在于c:\ti\c5400\tutorial\volume4 目录中)
1. 在Project View的volume.cdb处双击鼠标左键。
2. 选择LOG_system,将属性值buflen修改为512并点击OK。
3. 在PRD magager处点击鼠标右键,并从弹出菜单中选择Insert PRD。
4. 将PRD0改名为loadchange_PRD。
5. 在loadchange_PRD处,点击鼠标右键,并从弹出菜单中选择Properties。
6. 将loadchange_PRD属性设置为下述值并点击OK。
o 周期值设为2。缺省状态下,PRD manager使用CLK maganer驱动PRD。CLK类触发PRD的缺省值为1ms,因此PRD对象每2ms执行一次其服务例程。
o
7. 点击SWI maganer旁的‘+’号,可以发现已经自动增加了一个名为PRD_swi的SWI对象。在运行时,软中断执行周期函数,因此,所有PRD函数均在软中断服务例程中被调用,且调用时须保护现场。相应地,CLK函数被硬中断服务例程调用。
8. 点击CLK manager旁的‘+’号,可以发现名为PRD_clock的CLK对象调用PRD_F_tick函数,该函数促使DSP/BIOS系统时钟计时(通过调用PRD_tick API函数),如果有PRD函数需要运行将产生PRD_swi软中断。
9. 在PRD manager处,点击鼠标右键,并从弹出菜单中选择Properties。选择Use CLK Manager to drive PRD。若在你的工程文件中没有选择该属性,则PRD_clock对象将自动删除,你的程序可以从其他事件(如硬中断)中调用PRD_tick来驱动周期函数。
10. 回忆一下processing_SWI对象,它的mailbox值为10,而且mailbox值在dataIO_CLK对象中每经1ms就减1,因此processing_SWI每10ms运行1次,而loadchange_PRD每2ms运行1次。
11. 选择File→Close,根据提示选择Yes保存volume.cdb,这将自动产生volumecfg.cmd,volumecfg.s54,volumecfg.h54文件。
12. 选择Project→Rebuild All或者点击工具栏按钮(Rebuild All)。
在Project View的volume.c处双击鼠标左键,源文件将显示在CCS窗口的右半部分。由于文件volume.c是从c:\ti\c5400\tutorial\volume4 目录中拷贝到你的工作文件夹中的,因此它与前一章的源程序存在下述差别:
o 增加了一个头文件:
#Include
o 增加了两条声明语句:
RTDX_CreateInputChannel(contro_channel);
Void loadchange(Void);
o 在主函数中增加了下列函数调用:
RTDX_enableInput(&control_channel)
o 下述函数为PRD对象调用的函数
/* ======== loadchange ========
* FUNCTION: Called from loadchange_PRD to
* periodically update load value.
* PARAMETERS: none.
* RETURN VALUE: none.
sizeof(control));
if ((control < MINCONTROL) || (control > MAXCONTROL)) {
*/
Void loadchange()
{
static Int control = MINCONTROL;
/* Read new load control when host sends it */
if (!RTDX_channelBusy(&control_channel)) {
RTDX_readNB(&control_channel, &control,
LOG_printf(&trace,"Control value out of range");
}
else {
processingLoad = BASELOAD << control;
LOG_printf(&trace,"Load value = %u",processingLoad);
}
}
该函数使用RTDX API函数改变实时处理信号的load值,其改变表现在下述方面:
o 调用RTDX_enableInput,名为control_channel的输入通道变为使能,这样数据流可以从主机传送到目标板中。运行时,VB程序将load值写入该通道并将它发送给目标板。
o 调用RTDX_readNB函数,请求主机方通过control_channel发送load值并将该值存入名为control的变量中。该函数调用后立即返回,无需等待主机发送数据。从RTDX_readNB函数调用到数据被写入变量control,control_channel一直处于忙状态,不再响应其他请求,此期间会调用RTDX_channelBusy函数并返回TRUE。
o 语句“processingLoad = BASELOAD << control;”使BASELOAD(1)中的比特向左移位,移动的位数由变量control指定。由于MAXCNTROL设置为31,因此load最大值为32位变量能存储的最大值。
当你在processing函数中放置测试点测试程序、观察输入输出数据的图形时(见4.3节),你已经测试了数字处理算法。在开发的现阶段,注意的焦点应是搞清楚新增加的任务仍旧能够满足其实时期限的要求。同样,测试点会中止目标程序并对实时测试带来影响。
1. 选择File→Load Program,打开刚编译过的volume.out
2. 选择Tools→DSP/BIOS→RTA Control Panel。
3. 在RTA Control Panel处点击鼠标右键,取消Allow Docking选定以便在将一个单独的窗口中显示RTA Control Panel。调整窗口大小以便能看到全部选项。
4. 放置“√”,使SWI、PRD和CLK logging处于使能状态,使SWI和PRD accumulators处于使能状态,使global tracing处于使能状态。
5. 选择Tools→DSP/BIOS→Execution Graph。Execution Graph区域显示在CCS窗口的底部,可调整其大小或将它显示为一个单独的窗口。
6. 选择Tools→DSP/BIOS→Statistics View。
7.
8. 点击OK。
9. 调整Statistics区域的大小以观察选择的统计数据域。
10. 在RTA Control Panel处点击鼠标右键并从弹出菜单中选择Property Page。
11. 设置Message Log/Execution Graph的刷新频率为1s,设置Statistics View/CPU Load Graph的刷新频率为0.5s,然后点击OK。
12. 选择Tools→RTDX。
13. 注意RTDX已经处于使能状态,这是在步骤2中当打开DSP/BIOS控制时在后台完成的。通过配置DSP/BIOS控制项使RTDX工作于连续模式。在连续模式下,RTDX不在日志文件中记录从目标板接收的数据。这允许数据流连续传送。(如果你的程序没有使用DSP/BIOS,你可以直接使用RTDX区域配置和使能RTDX)
14.
该应用程序使用了下述RTDX函数:
o rtdx.Open(“control_channel”,”W”) 当打开应用程序时,打开向目标板写入信息的控制通道。
o rtdx.Close() 当关闭应用程序时,关闭控制通道。
o Rtdx.Writel2(datal2,bufstate) 把滑动控制条的当前值写入控制通道,目标程序可以读取该值并使用它刷新load值。
15. 选择Debug→Run或者点击工具栏按钮(Run)。
PRD统计是用PRD ticks来计量的,SWI统计用指令周期来计量的,loadchange_PRD的Max和Average域显示表明,在该函数开始运行到
16. 使用Load Control窗口逐渐增加处理load值。(如果在DSP 应用程序停止工作的情况下滑动Load Control窗口的控制条,则RTDX将新的load控制值缓存在主机上。这些值直到DSP应用程序重新运行、并调用RTDX_readNB以请求从主机刷新load值时才会有影响)。
17.
为什么?当load值超过某个值时,loadchange_PRD的Max值开始增加,随着load值的增加,processing_SWI需要占用的运行时间长得致使loadchange_PRD在超过实时期限很长时间才能开始运行。
当load值增加到一定程度时,低优先级的idle循环就不再执行,主机停止接收实时分析数据,DSP/BIOS插件停止刷新,暂停目标程序用排队数据刷新插件。
为了便于理解程序为什么不满足实时期限的要求,你需要检查软中断任务的优先级。
1. 选择Debug→Halt中止目标程序。
2. 在Project View中双击文件volume.cdb。
3. 加亮SWI manager,注意SWI对象的优先级显示在窗口的右半部分。
4. 由于PRD_swi和processing_SWI具有相同的优先级,PRD_swi不能先处理processing_SWI。processing_SWI每10ms运行一次而PRD_swi每2ms运行一次。当load值较高时,processing_SWI运行时间超过2ms,它使得PRD_swi不满足实时期限的要求。
5. 为了解决上述问题,需要把PRD_swi设置成最高优先级。降低processing_SWI的优先级。这增加了一个第二级的优先级别,现在PRD_swi具有最高优先级。
6. 选择File→Save保存你所作的修改。
7. 选择File→Close关闭volume.cdb。
8. 选择Project→Build或者点击工具栏按钮(Incremental Build)
9. 选择File→Reload Program。
10. 选择Debug→Run重新运行目标程序。在程序运行时使用RTDX使能的Windows应用程序loadctrl.exe应用程序窗口改变load值。
11. 注意:现在可增加load值而不会使PRD_swi不满足实时期限的要求。
12. 在进行下一章之前(完成6.6节之后),需要完成下述操作:
o 点击工具栏按钮或者按Shift+F5中止程序运行。
o 关闭GEL对话框、DSP/BIOS插件和源程序窗口。
为了进一步研究DSP/BIOS,试做下述工作:
o 当增加load值时,Execution Graph表明processing_SWI需要的运行时间超过1个PRD计数周期。这是否意味着processing_SWI不满足实时期限的要求?请回忆一下,PRD ticks以每毫秒为时间间隔出现的同时,processing_SWI必须每10ms运行一次。
o 如果直接从硬中断服务例程中调用processing函数而不是从软中断中调用,那将发生什么呢?由于硬中断优先级低于软中断优先级,那将使得程序不满足实时期限的要求。请回忆一下,当Load值很高时,PRD_swi需要先于processing_SWI执行。如果processing_SWI是一个硬中断,PRD_swi则不能先于它执行。
o 观察CPU Load Graph。使用RTA Control Panel打开和关闭统计累积器,注意这对CPU Load Graph无影响,这表明统计累器在处理器上放置了一个很小的Load值。
统计累积器对processing_SWI的统计数据有多大影响呢?可一边打开和关闭统计累积器,一边观察统计数据,这之间的差别是各累计器所需的指令数的精确计量。为了观察效果,记住对统计数据窗口点击鼠标右键并清除统计计数。
o 就象在5.7节中所做的那样,在loadchange函数中增加函数STS_set和STS_delta调用。这样的修改对CPU load影响如何?在dataIO函数中增加STS_set和STS_delta的调用,这又将对CPU Load有何影响?为什么?试考虑各函数执行时的频率。对于经常执行的函数而言,它需要的处理时间的细微的增加,都可能对CPU Load造成很大的影响。
想要更多地了解软中断属性、RTDX和PRD模块,请参见CCS和RTDX的在线帮助或者参考TMS320C54x DSP/BIOS User’s Guide(用户指南)。
本章介绍用DSP/BIOS和RTDX技术实现I/O。
在本章中,将采用RTDX和DSP/BIOS使应用程序与I/O设备相连接。也可以采用DSP/BIOS API的HST、PIP和SWI模块。
基本要求:DSP/BIOS和RTDX组件,目标板
在CCS中打开工程文件并查看它包含的源程序及库文件。
1. 如果你把CCS安装在c:\ti 目录,可以创建一个新目录c:\ti\myproject;如果CCS安装在其他目录,则可在相应的位置建立myproject 目录。
2. 将c:\ti\c5400\tutorial\hostio1下的所有文件拷贝到新目录下。
3. 从Windows开始菜单中,选择Program→Code Composer Studio ’C5400→CCStudio。
4. 选择Project→Open并打开hostio.mak。
5. 依次点击Project、HOSTIO.MAK、Source旁的’+’,可以看到工程文件中包含的各种文件。hostiocfg.cmd及include中的头文件是在保存配置文件时创建的。本例程需要的文件有:
o hostio.c 主程序
o signalprog.exe VB应用程序,它产生正弦波并显示输入/输出信号
o slider.exe VB应用程序,它控制输出信号幅度
o hostiocfg.cmd 连接命令文件,它仅增加了名为trace的LOG对象
o hostiocfg.s54 汇编源文件
o hostiocfg.h54 头文件
本章中的例子模拟一个能数字化音频信号、调整音量、产生幅度可调的模拟输出的DSP应用程序。
为简单起见,该例没有使用收、发模拟信号的设备,而是使用主机产生的数字信号测试算法。数据的输入/输出及音量控制信号是采用RTDX在主机和目标板之间传送的。
在主机上运行的VB应用程序使用RTDX产生输入信号并显示输入/输出信号,该程序允许开发者不中止程序运行即进行算法测试。
1. 双击Project View中的hostio.c源程序。
2. 注意源程序的下述方面:
o 三个RTDX通道声明为全局的。第一个输入通道控制音量,第二个输入通道接收主机发送来的信号,输出通道用于从目标板向主机发送的输出信号。(是站在目标板应用程序的角度来称输入和输出信道的,即:输入信道从主机接收数据,输出信道向主机发送数据。)
o 当通道当前不是处于等待输入状态时,调用RTDX_channelBusy函数将返回FALSE,它表明数据已到达可供读取。如第六章所述,调用RTDX_readNB无需等待接收数据就可返回DSP应用程序。主机将数据异步写入控制通道。
o RTDX_Poll用于RTDX下层应用之间的数据读/写的。
o 如果输入通道是使能的,RTDX_read将等待数据的到来。
o 如果输出通道是使能的,RTDX_write将缓冲区的数据写入到输出的RTDX通道中。
o 当目标板通过调用RTDX_enableInput使控制通道control_channel处于使能状态时,则该例程中的其他RTDX通道将处于非使能状态。而下一节描述的主机程序将使能这些通道。使用control_channel的滑动控制被视为应用程序的有机组成部分,在目标程序中使能该通道会使人们在应用程序运行时亦清楚该通道是处于使能状态的;而A2D通道和D2A通道是用于算法测试的。所以这些通道是通过主机应用程序设定为使能状态或非使能状态的。
#include
#include
#include
#include "target.h"
#define BUFSIZE 64
#define MINVOLUME 1
typedef Int sample; /* representation of a data sample from A2D */
/* Global declarations */
sample inp_buffer[ BUFSIZE];
sample out_buffer[ BUFSIZE];
Int volume = MINVOLUME; /* the scaling factor for volume control */
/* RTDX channels */
RTDX_CreateInputChannel(control_channel);
RTDX_CreateInputChannel(A2D_channel);
RTDX_CreateOutputChannel(D2A_channel);
/* Objects created by the Configuration Tool */
extern LOG_Obj trace;
/*
* ======== main ========
*/
Void main()
{
sample *input = inp_buffer;
sample *output = out_buffer;
Uns size = BUFSIZE;
TARGET_INITIALIZE(); /* Enable RTDX interrupt */
LOG_printf(&trace,"hostio example started");
/* enable volume control input channel */
RTDX_enableInput(&control_channel);
Connecting to I/O Devices while (TRUE) {
/* Read a new volume when the hosts send it */
if (!RTDX_channelBusy(&control_channel)){
RTDX_readNB(&control_channel, &volume, sizeof(volume));
}
while (!RTDX_isInputEnabled(&A2D_channel)){
RTDX_Poll(); /* poll comm channel for input */
}
/*
* A2D: get digitized input (get signal from the host through
* RTDX). If A2D_channel is enabled, read data from the host.
*/
RTDX_read(&A2D_channel, input, size*sizeof(sample));
/*
* Vector Scale: Scale the input signal by the volume factor to
* produce the output signal.
*/
while(size--){
*output++ = *input++ * volume;
}
size = BUFSIZE;
input = inp_buffer;
output = out_buffer;
/*
* D2A: produce analog output (send signal to the host through
* RTDX). If D2A_channel is enabled, write data to the host.
*/
RTDX_write(&D2A_channel, output, size*sizeof(sample));
while(RTDX_writing){
RTDX_Poll(); /* poll comm channel for output */
}
}
}
VB编制的应用程序signalprog.exe的源程序可用于文件signalfrm.frm。有关该应用程序的详细说明可见文件signalprog.pdf。可查看几个对该例而言很重要的例程和函数:
o Test_ON。点击Test_ON按钮时运行该例程。首先,它为输入通道和输出通道创建RTDX接口实例;接着,它打开输入/输出通道并使它们处于使能状态。该例程同时清除图形并启动Transmit_Signal和Receive_Signal的定时器。VB源程序中的全局变量声明把VB应用程序中的通道和hostio.c应用程序中相应通道联系到一起,如下:
' Channel name constants
Const READ_CHANNEL = "D2A_channel"
Const WRITE_CHANNEL = "A2D_channel"
o Test_OFF 该例程废止、关闭和释放Test_ON例程创建的RTDX对象,并使定时器处于非使能状态。
o Transmit_Signal首先,该函数产生正弦波信号并把正弦信号显示在Transmitted Signal图中;然后,它试图使用‘写’方式将数据传送到目标板。
o Receive_Signal 该函数使用ReadSAI2方式从目标板读取数据,并将信号显示在Received Signal图中。
o tmr_MethodDispatch_Timer 该例程调用Transmit_Signal和Receive_Signal函数,该例程在定时器被Test_On例程使能后每隔1ms被调用一次。
1. 点击工具栏按钮或选择Project→Build。
2. 选择File→Load Program并双击hostio.out。
3. 选择Tools→RTDX。
4. 选择窗口中RTDX区域的Configure,在RTDX属性对话框的General Settings中选择Continuous RTDX模式并点击OK。
5. 将RTDX域的RTDX Disable改为RTDX Enable,此时按钮Configure变为Diagnostics。
6. 选择Tools→DSP/BIOS→Message Log。在Message Log区域点击鼠标右键并从弹出菜单中选择Property Page,选择名为trace的Log对象并点击OK。
7. 点击工具栏按钮或选择Debug→Run。
8. 使用Windows浏览器,运行signalprog.exe和slider.exe,你可以看到两个VB应用程序。
9. 调整signalprog窗口高度。
10.
11. 滑动Volume Slider窗口的控制钮,这将改变输出信号幅度,观察Received Signal图中信号幅度的变化。
注:Volume Slider初始化设置
12. 关闭Volume Slider应用程序,这将废止输入/输出通道。
13. 点击signalprog窗口中的Test OFF,这将关闭控制通道。
14. 点击工具栏按钮或按Shift+F5中止运行。
15. 现在你可在Massage Log窗口中看到调用LOG_prinft产生的信息“hostio example started”。由于整个程序的运行都是在主函数中进行的,因此你不能更早地看到上述信息。DSP/BIOS和主机在DSP处于idle状态时才进行通信联系。直到应用程序从主函数中返回,DSP才会处于idle状态。所以,如果你想看到运行中DSP/BIOS的影响,你的程序应当在从主函数返回后执行DSP/BIOS的函数。下一节所用的hostio.c的修改版会说明该技术。
现在用DSP/BIOS提供的HST和PIP修改该实例。修改后的程序仍能实时测试DSP算法。这次测试数据来自一个主机文件,而不是前述的正弦信号。
HST模块为执行数据I/O提供了与外设接口更直接的通道。HST模块使用PIP模块实现主机I/O。一旦I/O设备和ISRs已经做好测试准备,就可使用PIP模块的API,这只需对源程序稍加修改即可。
1. 将目录c:\ti\c5400\tutorial\hostio2中的下述文件拷贝到你的工作文件夹下。(不要全部拷贝,特别不能拷贝hostio.cdb文件)。
o hostio.c 已经修改过的源程序,它使用DSP/BIOS API的HST和PIP模块代替RTDX传送输入/输出信号。
o input.dat 该文件包含输入数据
2. 在Project View中的hostio.c处,双击鼠标左键,该文件就显示在CCS窗口的右半部分,它与前述源程序的区别如下:
o 增加了两个头文件
#include
#include
o 删除了BUFSIZE定义、inp_buffer和out_buffer的全局声明以及RTDX的输入和输出通道声明。
o 将输入/输出函数从主函数中的while循环中移到了A2DscaleD2A函数中。
/* ======== A2DscaleD2A ======== */
/* FUNCTION: Called from A2DscaleD2A_SWI to get digitized data
* from a host file through an HST input channel,
* scale the data by the volume factor, and send
* output data back to the host through an HST
* output channel.
* PARAMETERS: Address of input and output HST channels.
* RETURN VALUE: None. */
Void A2DscaleD2A(HST_Obj *inpChannel, HST_Obj *outChannel)
{
PIP_Obj *inp_PIP;
PIP_Obj *out_PIP;
sample *input;
sample *output;
Uns size;
inp_PIP = HST_getpipe(inpChannel);
out_PIP = HST_getpipe(outChannel);
if ((PIP_getReaderNumFrames(inp_PIP) <= 0) ||
(PIP_getWriterNumFrames(out_PIP) <= 0)) {
/* Software interrupt should not have been triggered! */
error();
}
/* Read a new volume when the hosts send it */
if (!RTDX_channelBusy(&control_channel))
RTDX_readNB(&control_channel, &volume, sizeof(volume));
/* A2D: get digitized input (get signal from the host
* through HST). Obtain input frame and allocate output
* frame from the host pipes. */
PIP_get(inp_PIP);
PIP_alloc(out_PIP);
input = PIP_getReaderAddr(inp_PIP);
output = PIP_getWriterAddr(out_PIP);
size = PIP_getReaderSize(inp_PIP);
/* Vector Scale: Scale the input signal by the volume
* factor to produce the output signal. */
while(size--){
*output++ = *input++ * volume;
}
/* D2A: produce analog output (send signal to the host
* through HST). Send output data to the host pipe and
* free the frame from the input pipe. */
PIP_put(out_PIP);
PIP_free(inp_PIP);
A2DscaleD2A函数由A2DscaleD2A_SWI对象调用,在下一节中将创建该SWI对象并使它调用A2DscaleD2A函数。
A2DscaleD2A函数接收A2DscaleD2A_SWI对象传送来的两个HST对象,
它接着调用HST_getpipe函数获取各HST对象所采用的内部PIP对象的地址。
调用PIP_getReaderNumFrames函数和PIP_getWriteNumFrames函数可确定是否在输入流水线中至少有一帧数据可读取,输出管道中是否至少有一帧数据可写入。
使用与7.2节中同样的RTDX调用,该函数获取由RTDX控制通道中设置的幅度值。
调用PIP_get可从输入流水线中获取完整的一帧数据。调用PIP_getReaderAddr获取输入流水线数据帧的起始地址。调用PIP_getReaderSize获取输入流水线中帧的字长。
调用PIP_alloc从输出流水线中获取空帧。调用PIP_getWriterAddr获取输出流水线中输出数据帧的起始地址。
接下来该函数将输入信号乘以幅度值并将结果写入PIP_getWriterAddr提供的地址中。
调用PIP_put将一个完整帧写入到输出流水线中。调用PIP_free重复利用输入帧以便函数下次运行时使用。
o 增加了错误检测函数,它将出错信息写入trace日志中并将程序置于无限循环状态。如果A2DscaleD2A函数无有效的数据可供处理时,该函数将被调用。
每个主机通道都在内部都使用一个流水线。当使用主机通道时,目标应用程序管理流水线得一端,主机通道控制插件管理流水线得另一端。
当准备使用外设而不是使用主机修改程序时,可保留管理流水线目标板端的源代码,并在函数中增加处理管理流水线另一端的I/O设备的源代码。
A2DscaleD2A函数被SWI对象调用并使用两个HST对象,本节将创建这些对象(c:\ti\c5400\tutorial\hostio2\hostio.cdb文件中已经包含了这些对象)。
A2DscaleD2A函数还与两个PIP对象有关,不过它们是在你创建HST对象时自动生成的。HST_getpipe函数获取相应HST对象的内部PIP对象的地址。
1. 在Project View的HOSTIO.CDB处,双击鼠标左键打开该文件。
2. 在HST manager处点击鼠标右键并选择Insert HST。
注意,存在名为RTA_fromHost和RTA_toHost的HST对象,它们是内部用来修改DSP/BIOS控制的。
3. 将对象名HST0修改为input_HST。
4.
o mode 该属性决定目标程序和主机通道控制插件各管理的流水线的哪一端。输入通道从主机向目标板发送数据,输出通道从目标板向主机发送数据。
o framesize 它设置每帧的长度,等同于7.2节定义的BUFSIZE,长度为64字
o notify,arg0,arg1 当输入通道中包含一个完整的数据帧时,这些属性指定调用的函数及该函数的输入参数,SWI_andn函数提供了操作SWI对象的mailbox的另一方法。
在第五章,你使用SWI_dec函数递减mailbox值,并在mailbox值抵达0时运行SWI对象的函数。
SWI_andn函数把mailbox值当作掩码,它将传递给函数的第2个参数所指定的比特位清0。因此,当输入通道包含一个完整帧时,A2DscaleD2A_SWI对象的SWI_andn函数被调用且mailbox的bit0被清零。
5. 插入另一个HST对象并命名为output_HST。
6.
当输出通道中含有一个空帧时,它用SWI_andn清除mailbox的bit1。
7. 在SWI manager处点击鼠标右键并选择Insert SWI。
8. 将新对象SWI0命名为A2DscaleD2A_SWI。
9. 设置A2DscaleD2A_SWI属性并点击OK。
o function 当软中断被登记并执行时,该属性使该对象调用函数A2DscaleD2A。
o mailbox mailbox初始值。input_HST对象清除掩码的第一比特,output_HST清除掩码的第二比特,当运行A2DscaleD2A函数时,mailbox值被复位为3
o arg0,arg1 两个HST对象,它们作为A2DscaleD2A函数的输入参数
10. 选择File→Close,你将被询问是否保存对hostio.cdb的修改,点击Yes保存配置,同时自动产生hostiocfg.cmd、hostiocfg.s54和hostiocfg.h54。
1. 点击工具栏按钮 或选择Project→Rebuild All。
2. 选择File→Load Program。选择hostio.out并点击Open。
3.
4. 点击工具栏按钮或选择Debug→Run。
5. 在input_HST通道处点击鼠标右键并从弹出菜单在选择Bind。
6. 从你的工作文件夹下选择文件input.dat并点击Bind。
7.
8. 在File Name框中敲入output.dat并点击Bind。
9. 在input_HST通道处点击鼠标右键并从弹出菜单在选择Start。
10. 在output_HST通道处点击鼠标右键并从弹出菜单在选择Start,注意在Transferred栏中显示数据正在被传送。
11. 当数据传送完毕,点击或者按Shift+F5中止运行程序。
有关RTDX、HST、PIP和SWI模块信息,请参见在线帮助或TMS320C54x DSP/BIOS User’s Guide(用户指南)。
第一章 CCS概述 1
1.1 CCS概述 1
1.2 代码生成工具 3
1.3 CCS集成开发环境 5
1.3.1 编辑源程序 5
1.3.2创建应用程序 6
1.3.3 调试应用程序 6
1.4 DSP/BIOS 插件 7
1.4.1 DSP/BIOS 配置 7
1.4.2 DSP/BIOS API 模块 8
1.5 硬件仿真和实时数据交换 10
1.6 第三方插件 13
1.7 CCS文件和变量 14
1.7.1安装文件夹 14
1.7.2文件扩展名 14
1.7.3环境变量 15
1.7.4增加DOS环境空间 16
第二章 开发一个简单的应用程序 17
2.1 创建工程文件 17
2.2 向工程添加文件 19
2.3 查看源代码 21
2.4 编译和运行程序 23
2.5 修改程序选项和纠正语法错误 24
2.6 使用断点和观察窗口 26
2.7 使用观察窗口观察structure变量 28
2.8 测算源代码执行时间 29
2.9 进一步探索 31
2.10进一步学习 31
第三章 开发DSP/BIOS程序 32
3.1 创建配置文件 32
3.2 向工程添加DSP/BIOS文件 34
3.3 用CCS 测试 36
3.4 测算DSP/BIOS代码执行时间 38
3.5 进一步探索 40
3.6 进一步学习 40
第四章 算法和数据测试 41
4.1 打开和查看工程 41
4.2 查看源程序 43
4.3 为I/O文件增加探针断点 45
4.4 显示图形 47
4.5 执行程序和绘制图形 48
4.6 调节增益 50
4.7 观察范围外变量 51
4.8 使用GEL文件 53
4.9 调节和测试processing函数 54
4.10 进一步探索 56
4.11 进一步学习 57
第五章 程序调试 58
5.1 打开和查看工程 58
5.2 查看源程序 60
5.3 修改配置文件 63
5.4 用Execution Graph查看任务执行情况 66
5.5 修改和查看load值 67
5.6 分析任务的统计数据 70
5.7 增加STS显式测试 72
5.8 观察显式测试统计数据 73
5.9 进一步探索 75
5.10 进一步学习 75
第六章 实时分析 76
6.1 打开和查看工程 76
6.2 修改配置文件 77
6.3 查看源程序 79
6.4 使用RTDX控制修改运行时的load值 81
6.5 修改软中断优先级 84
6.6 进一步探索 85
6.7 进一步学习 85
第七章 I/O 86
7.1 打开和查看工程 86
7.2 查看源程序 87
7.3 Signalprog应用程序 90
7.4 运行应用程序 91
7.5 使用HST和PIP模块修改源程序 93
7.6 HST和PIP资料 96
7.7 在配置文件中增加通道和SWI 97
7.8 运行修改后的程序 100
7.9 进一步学习 100