admin 管理员组

文章数量: 1086019


2024年3月26日发(作者:violates)

PhoenixTreeSky

Code Composer Studio 教 程

Edited by

PhoenixTree

School of Automation

Beijing Institute of Technology

2014.09.09

0

PhoenixTreeSky

CONTENTS

Code Composer Studio 教程(一)

——

开发一个简单的程序

...................................... 4

步骤1:创建一个新项目 ............................................................................................ 4

步骤2:在项目中加载源文件 ..................................................................................... 4

步骤3:浏览源代码 .................................................................................................... 4

步骤4:建立并运行程序 ............................................................................................ 4

步骤5:改变程序设置并修改语法错误 ...................................................................... 4

步骤6:使用断点和观察窗口 ..................................................................................... 5

步骤7:用Watch window观察指令 ........................................................................... 6

步骤8:代码执行时间的性能分析.............................................................................. 6

Code Composer Studio 教程(二)

——

开发一个

DSP/BIOS

程序

................................. 8

步骤1:创建一个配置文件......................................................................................... 8

步骤2:加载DSP/BIOS文件到项目中......................................................................... 9

步骤3:用CCS来进行测试....................................................................................... 10

步骤4:DSP/BIOS代码执行时间的性能分析............................................................. 10

步骤5:试一试 ......................................................................................................... 11

步骤6:释放性能分析所占用的资源: .................................................................... 12

Code Composer Studio 教程(三)

——

从文件中测试算法和数据

............................. 13

1

PhoenixTreeSky

步骤1:打开并检测项目 .......................................................................................... 13

步骤2:观察源代码 .................................................................................................. 13

步骤3:为文件I/O加一探针点(probe point) ....................................................... 14

步骤4:图表显示 ..................................................................................................... 15

步骤5:启动程序和图表 .......................................................................................... 15

步骤6:调整gain参数 ............................................................................................. 16

步骤7:观察out-of-scope变量................................................................................. 17

步骤8:使用一GEL文件 .......................................................................................... 17

步骤9:调整并分析processingLoad(负载处理) .................................................... 18

Code Composer Studio 教程(四)

——

调试程序性能

............................................... 20

步骤1:打开并检查项目 .......................................................................................... 20

步骤2:观察源代码 .................................................................................................. 20

步骤3:修改配置文件 .............................................................................................. 21

步骤4:用thread execution(线性执行)来观察运行图表 ...................................... 22

步骤5:改变并观察加载程序 ................................................................................... 23

步骤6:分析调度表 .................................................................................................. 24

步骤7:加入外部STS装置 ....................................................................................... 25

Code Composer Studio 教程(五)

——

实时性能分析

............................................... 28

步骤1:打开并检查项目 .......................................................................................... 28

2

PhoenixTreeSky

步骤2:修改配置文件 .............................................................................................. 28

步骤3:观察源代码的改变....................................................................................... 29

步骤4:在运行时用RTDX控制来改变 30

步骤5:修改软中断优先权....................................................................................... 31

Code Composer Studio 教程(六)

——

I/O

设备的连接

........................................ 34

步骤1:打开并检查项目文件 ................................................................................... 34

步骤2:观察C源代码 .............................................................................................. 34

步骤3:回顾signalprog应用程序 ............................................................................. 35

步骤4:运行应用程序 .............................................................................................. 36

步骤5:修改源代码以使用Host Channels and Pipes ................................................. 37

步骤6:更多有关Host Channels and Pipes ................................................................ 38

步骤7:向配置文件中加入通道和一个软中断 ......................................................... 38

步骤8:运行修改后的程序....................................................................................... 39

3

PhoenixTreeSky

Code Composer Studio 教程(一)

—— 开发一个简单的程序

步骤1:创建一个新项目

1) 创建一个工作文件夹,D:hanstudy1。

2) 进入CCS环境中,并编译源文件:

File ——> New ——> Source File ,

编译完毕,分别存为hello.c, ,,hello.h。

3) project ——> New,保存于D:hanstudy1目录下,项目名称为

步骤2:在项目中加载源文件

1) project ——> Add File to project ,分别选择hello.c 、 、

和TiC6000cgtoolslib目录下的 。

步骤3:浏览源代码

1) 双击,打开hello.c,浏览源代码。

步骤4:建立并运行程序

1) project ——> Rebuild All 。在此项目中CCS编译、汇编,并链接所有

文件。生成、和文件。

2) File ——> Load Program,选择 。这样CCS将此程序加载

入目标板DSP中,并同时打开此程序的反汇编文件。

3) Debug ——> Run ,运行程序,输出结果hello world 。

步骤5:改变程序设置并修改语法错误

在以上步骤中,处理器指令#ifdef 和#endif没有运行,因为FILEIO没有定义。

在此,设置CCS处理器设置选择,以运行之,并找出、更正其中的错误。

4

PhoenixTreeSky

1) project ——> Options 。

2) 在Category列表中点击preprocessor,并在Define symbol框中输入

FILEIO。

3) OK,保存新的选项控制设置。

4) Project ——> rebuild All 。

注意:无论何时,项目选项(project options)发生改变,都必须重新建立

(rebuild All)所有文件。

5) 提示:有错误,是否继续链接?取消,改正错误并保存。

6) project ——> Build 。

注意:CCS将重新建立(Buill)更改过数据的文件。

步骤6:使用断点和观察窗口

当你正在开发和测试程序时,经常需要检查程序执行期间的变化值。在此,

使用断点和观察窗口来观察这些值。在到达断点后,也可以使用单步执行命令。

1) File ——> Reload Program 。

2) 双击hello.c。

3) 将光标放置在fprintf(fptr,“%s”,scanStr);行上。

4) 点击“手形图案”(Toggle Breakpoint)或F9。此行此时呈高亮色(紫

色亮条)。

5) View ——> Watch window 。

6) 在Watch window窗口中右击,选择Insert New Expression。

7) 在消息框中输入*scanStr,OK。

8) 此时在Watch window窗口中*scanStr 为尚未定义。因为,当前程序还

未在main()函数的局域变化处运行。

9) Debug ——> Run 或F5。

10) 在提示框中输入goodbye,OK。此时,在Watch window中,为

*scanStr=goodbye。而程序运行并停止在断点处(黄色亮条),并在结果窗口中显

示goodbye。

11) 点击step over 图标或F10来单步调用fpritf()。

12) step into(F8)、step over(F10)、step out(F7)、Run to Cursor(Ctrl F10)。

13) 点击运行(Run)或F5,完成程序的运行。

5

PhoenixTreeSky

步骤7:用Watch window观察指令

1) 在Watch window窗口中右击,选择Insert New Expression项。

2) 在提示框中输入str,OK。则在Watch window中出现+str={…}。“+”表

示此乃一指令,此指令为PARMS类型,并在hello.c中有所描述。此指令类型在

hello.h中定义。

3) 点击“+”,则出现所有元素:

-str={…}

Beta=2934

EchoPower=9432

ErrorPower=213

Ratio=9432

+Link=0x80000174

4) 双击其中任意一个元素行,则打开一个元素编辑窗口,改变元素值,

则Watch window中值亦随之改变。

5) 注意:操作完毕,必须从Watch window中移走指令str,并关闭Watch

window,撤去断点。

步骤8:代码执行时间的性能分析

在此,使用CCS的描述特性来获得有关标准puts()函数的运行统计,并使之

与使用DSP/BIOS API来显示hello world信息相比较。

1) File ——> Reload Program。

2) Profiler ——> Enable clock。此时钟计数指令周期,其必须对profiler-

points使能来计数指令周期。

3) 打开hello.c。

4) View ——> Mixed Source/ASM。在C源代码下出现此指令的汇编指令。

5) 将光标置于指令行puts(“hello world!n”); ,并点击时钟符号(Toggle

Profiler-point),则此行C代码与其下第一行汇编指令变为绿色亮条,其下一条指

令亦如此。

6) Profiler ——> View Statistics。在右下角出现一显示框,以显示对测试

点(profiler-point)的统计。

7) 点击运行符号或F5,运行程序,在弹出的提示框中输入字符串“goodbye”,

6

PhoenixTreeSky

OK。

8) 观察小窗口中数字的变化:注意第二个profiler-point的周期数,其周

期数应在1600-1700间,此乃运行puts()所需要的周期数。

7

PhoenixTreeSky

Code Composer Studio 教程(二)

—— 开发一个DSP/BIOS程序

在此教程中,通过使用DSP/BIOS来优化hello程序。此教程需要一个目标板,

而且不可以用一软件模拟器来实现。同时,此教程需要CCS的DSP/BIOS部分。

步骤1:创建一个配置文件

另一种实现hello程序的方法是使用配有DSP/BIOS API的LOG模块(API—

—应用程序接口)。你可以在加载入的程序中使用DSP/BIOS来提供基本的运行时

间服务。API模块使实时DSPs进行最优化。不同于C库调用如puts(),DSP/BIOS

在不暂停目标硬件的情况下进行实时分析。另外,API代码占用更小的空间,同

时比C标准的I/O运行更快。一个程序可使用一个或更多的DSP/BIOS模块。

在此,修改hello 文件以使用DSP/BIOS API。为应用DSP/BIOS API,一个程序

必须拥有一个程序所使用的定义了DSP/BIOS对象的配置文件。

1) 打开项目。(在D:hanstudy2目录下)

2) File ——> New ——> DSP/BIOS Config。

3) 选择对DSP板的类型,确定。此时弹出一界面窗口。

4) 右击LOG-Event Log Manager,并选择Insert LOG,这样建立一个名为

LOG0的LOG对象。

5) 右击LOG0,选择Rename,改名为“trace”。

6) File ——> Save。保存于工作目录下,配置文件名为。保

存此配置直接产生以下文件:

① :保存配置的设置。

② :连接器命令文件。

③ myhellocfg.s62:汇编语言源文件。

④ myhellocfg.h62:包含在myhellocfg.s62中的汇编语言头文件。

尽管这些文件拥有.s62和.h62 的扩展名,它们也可应用在TMS320C6701中。

DSP/BIOS不需要使用TMS320C6701支持的浮点指令,因此支持二者DSPs只需一

种版本的软件。

8

PhoenixTreeSky

步骤2:加载DSP/BIOS文件到项目中

在此,加载上面生成的新文件于工作目录中,并移走它们替代的文件。

1) Project ——> Add Files to Project 。选择。这样在项目下

DSP/BIOS Config中加入了。此外,CCS自动地在项目下源文件夹中加

入myhellocfg.s62文件。

2) 输出文件的文件名必须与.cdb 文件名相匹配(和

)。选择Project ——> Options,点击Linker标签,在output文件框

中,确认为文件名。

3) project ——> Add File to project。选择文件,确定。此

时,出现一警告板,单击“Yes ”。这样,在保存配置文件是生成的新的.cmd 文

件代替旧的文件()。

4) 在项目目录树中,右击源文件,选择Rename from project,

从项目中移走此文件。硬件中断向量会被DSP/BIOS配置文件自动定义。

5) 同样移走文件。此库文件自动包含于文件

中。

6) 双击打开hello.c文件,选择View ——> Mixed Source/Asm来隐藏其

汇编代码。

7) 改变源文件的内容,替换主函数,因为puts()与LOG_printf使用相同的

资源。

注意:此代码的下列部分:

① 此代码包括std.h和log.h头文件。所有使用DSP/BIOS API的程序必须包

含std,h文件,而且头文件适合于任何程序所使用的模块。log.h头文件定义

LOG_Obj结构,,并且声明API在LOG模块中的运行。Std.h文件必须优先包含。

而包含的拥有模块顺序并不重要。

② 此代码亦声明在配置文件中生成的LOG对象。

③ 在主函数中,此例调用LOG_printf并忽略LOG对象(&trace)和hello

world信息的地址。

④ 最后主函数返回,而导致程序进入DSP/BIOS空循环。在此循环中,

DSP/BIOS等待软中断和硬中断的出现。

8) 保存文件。Project ——> option。在Compiler标签下,Category框中

选择Preprocessor,移走右边Define symbols框中的FILEIO。

9) Project ——> Rebuild All 。

9

PhoenixTreeSky

步骤3:用CCS来进行测试

由于程序只写了一行到一个LOG,在此无须进行分析。

1) File ——> Load program,选择刚刚重建的文件,确定。

2) Debug ——> go main。

3) Tools ——> DSP/BIOS ——> Message Log。此时在CCS窗口底部出现

一消息区域。

4) 在此消息区域上右击,选择Property Page 。

5) 选择trace作为监测记录(the log to monitor)的名字,确定。默认更

新率为1次/秒。(改变更新率,Tools ——> DSP/BIOS ——> RTA。在RTA控制面

板上右击并选择Property Page。选择一个新的更新率,确定。)

6) Debug ——> Run或F5。则hello world显示在消息记录区域。

7) Debug ——> Halt或shift F5停止程序的执行。在主函数返回之后,程

序处于DSP/BIOS空循环状态,直至出现一个事件。

8) 关闭Message Log窗口。(这是必需的一步)

9) Tools ——> RTDX。打开RTDX控制窗口。选择RTDX Disable,在下拉

列表中,在RTDX区域上右击,选择Hide。

注意:profiling与RTDX在一些目标板上不能同时应用。

DSP/BIOS插件程序(plug-ins)使用RTDX来进行主机/目标间的通信。在一

些DSP目标板上(例如,TMS320C6201),不能同时使用profiling和RTDX。关闭

所有使用RTDX的工具,在使用profiling之前,例如Message Log和其它DSP/BIOS

plug-ins。为确保取消RTDX,特别是在使用DSP/BIOS plug-ins之后,选择Tools —

—> RTDX来打开RTDX plug-in。选择RTDX Disable在下拉列表中,右击,选择Hide。

相反地,在使用profiling之后,使用RTDX之前释放protiler资源,如同教程

1步骤8末尾所描述的那样。如尝试同时使用RTDX和profiling,则会出现一个错

误信息。

步骤4:DSP/BIOS代码执行时间的性能分析

以前,使用CCS性能分析特性得到周期数需要调用puts()。现在,通过调用

LOG_printg来完成相同的工作。

1) File ——> Reload program。

2) Profiler ——> Enable Clock。

10

PhoenixTreeSky

3) 打开hello.c文件。

4) View ——> Mixed Source/ASM。

5) 将光标置于LOG_printf(&trace,“hello world!”);行。

6) 点击Toggle profile-point 按钮。

7) 将光标置于程序的最后一行,点击Toggle profile-point按钮。

注意:此最后一行并不是return行,而是大括号“}”行。

8) profiler ——> View statistics。

9) 要使在View statistics窗口中的行数为正序,即行数从上向下,从小变

大。

10) 点击Run或F5,运行程序。

11) 注意指令周期数应为第二个profile-point。其值大约为36,这是执行

调用LOG_printf所必需的周期数。调用LOG_printf是生效的,因为一系列格式化

的执行在主机上要好于在目标DSP上。

12)点击Halt或shift F5,停止程序的运行。

步骤5:试一试

为进一步了解CCS,试一试以下的内容:

① Load ,并设置一断点于LOG_printf行。用Debug ——>

Breakpoints来加入一个断点于IDL_F_Loop。(在位置条输入IDL_F_Loop,单击Add)。

运行程序。在第一个断点,View ——> Cpu registers ——> Cpu register观察

寄存器值列表。注意GIE为0,此表示当主函数(main)正在执行是中断无效。

继续运行程序至下一断点。此时GIE为1,此时中断生效。如果运行程序,

不断访问此断点。在启动过程和主函数完成之后,一个DSP/BIOS进入一空循环。

此循环由IDL模块处理,直到停止程序的运行。此空循环带有中断使能并且可以

通过任何ISR(中断服务程序),或软中断,或事件触发一操纵实时处理应用程序,

在任何点优先取得。

② 在MS-DOS窗口中,以下列命令运行:

cd c:tic6000tutorialhello1

sectti >

cd …hello2

sectti >

当使用stdio.h调用和DSP/BIOS时,比较和二文件以观

11

PhoenixTreeSky

察内存部分和大小的区别。

步骤6:释放性能分析所占用的资源:

1) 在profiler菜单内,取消Enable clock。

2) 关闭profiler统计窗口。

3) 删除所有profiler-profile-points。

4) 取消Mixed Source/ASM。

5) 关闭所有窗口。

6) 关闭项目。

12

PhoenixTreeSky

Code Composer Studio 教程(三)

—— 从文件中测试算法和数据

在此教程中,创建一个执行基本信号处理的程序。在此得使用探点、图形、

动画和GEL文件。

步骤1:打开并检测项目

用CCS打开一个项目并检测源代码和库。

1) 建立一工作文件夹,D:hanstudy3。

2) 在此文件夹中创建一项目,,项目中有,,

volume.c,,volume.h,等文件。

① volume.c:主程序源文件。

② volume.h:包含在volume.c中定义的常量和结构的头文件。

③ :此文件包含载入程序(一个简单的汇编循环程序,可用一条C

指令调用的,其大概消耗1000条指令周期)。

④ :在DSP中断向量表中定义一个复位输入点。

⑤ :此链接命令文件映射内存块。

⑥ :提供目标板的运行支持。

步骤2:观察源代码

注意此例的以下部分:

① 在主函数输出一条信息之后,进入一无限循环。在此循环内,其调用

dataIO和处理函数。

② 此处理函数将input buffer和gain的输入结果值分别相乘,输出到output

buffer。其还调用汇编载入程序,此程序在处理传递程序载入值的基础上占用指

令周期。

③ 此例中的dataIO函数不执行任何动作,除了return之外。除了用C代

码执行I/O外,可以用一探针点来从一个主机上文件读取数据到inp_buffer位置。

13

PhoenixTreeSky

步骤3:为文件I/O加一探针点(probe point)

在此,加入一个探针点,从PC机上的一个文件读取数据。Probe point对于

运算法则的开发是一非常有用的工具。可以在以下几方面使用他们:

① 通过运算法则,传递主机上的文件输入数据到目标的buffer以使用。

② 传递目标buffer上的输出数据到主机一文件中来进行分析。

③ 更新窗口,例如带数据的图表。

Probe point类似于断点,他们都可终止目标的任何动作。然而,probe point

在以下几个方面不同于断点:

① probe point终止目标的瞬间,只执行一单一的动作,并继续执行目标。

② 断点终止CPU,直到手动继续执行并导致所有打开的窗口重新更新。

③ probe point允许自动地执行文件的输入或输出,而断点不可。

此教程显示如何使用probe point来传递PC文件内容到目标上,进行数据测

试。当到达probe point时,其也用一断点来更新所有打开的窗口。这些窗口包

括输入、输出数据的图表。

1) Project ——> Rebuild Add。

2) File ——> Load program。选择。

3) 打开volume.c。

4) 当光标置于主函数中此行:dataIO();

dataIO()函数相当于一占位符,稍后加入其。现在,其在方便位置连接一从PC

文件注入数据的probe point。

5) 点击“眼睛”图标(Toggle probe point),则此行变蓝。

6) File ——> File I/O。此File I/O对话显示可以选择输入、输出文件。

7) 在input tab,单击Add。

8) 选择文件。

注意:可以在文件类型框中选择数据格式(其中有十六进制、整数、浮点等

格式),文件对于一正弦波包含十六进制值(Hex)。

9) 此时,一文件控制窗口出现。随后,当运行程序时,可以用此

窗口来启动、停止、重绕或者在数据文件内快速传递。

10) 在File I/O对话框,改变地址为inp_buffer,长度为100,并选中Wrap

Around。

① 地址域说明从文件来的数据将要放置的地方。Inp_buffer作为BUFSIZE

整数数组在volume.c中定义。

14

PhoenixTreeSky

② 长度域说明每次探点(probe point)到达时有多少从数据文件来的采样

可以读取。使用100是因为它是在volume.h中设置的BUFSIZE常量值。(0x64)

③ 当到达文件末端时,Wrap Around选项启动CCS从文件开始处进行读取。

这样可将数据文件看作一连续的数据流,尽管它仅包含1000值,而且每次探点

到达读取100值。

11) 点击Add probepoint。出现一probe point对话框。

12) 点击probe point列表中的语句,其变为兰色。此时显示无连接。

13) 在connect条框中,在下拉菜单中选择文件。

14) 单击Replace。此时在probe point框中显示probe point已连接到

文件。

15) 确定。

16) 在File I/O对话框中,确定。

步骤4:图表显示

如果现在就运行程序,那么将看不到有关程序运行的相关信息。可以在

inp_buffer和out_buffer地址列上设置观察变量,但是需要观察大量变量,而且

是数字式显示。

CCS提供了多种方法给程序处理的数据图表。此例,将看到一快速信号图。

此步骤中,将打开图表,下一步进行程序。

1) View ——> Graph ——> Time/Frequency

2) 在图表属性对话框,改变图表标题、启始地址、获取缓冲器大小、显

示数据大小、Autoscale(自动测量)和最大Y值等属性。

3) 确定,一个Input buffer的图表出现。

4) 在Input buffer窗口中右击,并选择clear display。

5) View ——> Graph ——> Time/Frequency。

6) 此次,改变Graph Title为Output Buffer,start Address为out_buffer。

其它不变。

7) 确定,在图表窗口中右击,选择clear display。

步骤5:启动程序和图表

到目前为止,已经防止一探点(probe point),它暂时停止目标,从主机传输

15

PhoenixTreeSky

数据到目标,并重新执行目标应用程序。然而,探点不能导致图表的更新。在此,

设置一断点来促使图表的更新,并在到达断点后用Animate命令重新自动执行。

1) 在volume.c窗口中,放置光标在dataIO行。

2) 点击“手”形触发断点钮(Toggle breakpoint)或F9。此行变为紫红色

和兰色,以指示出此行既是断点又是探点。

将断点和探点设置为同一行,这样只被停止一次来执行数据传输和图表更新

两种操作。

3) 排列图表以便二者都可看到。

4) 点击Animate图标或F12运行程序。

此Animate命令与Run命令相似,其促使目标程序运行直至一个断点,目标

则被停止运行并更新窗口内容。然而,与Run命令不同的是,此Animate命令重

新启动直至到达另一断点。此过程一直持续下去直到手工停止目标程序。可以将

Animate命令看作一个Run-Break-contince的过程。

5) 注意每个图表包含两个半正弦波形,并且波形相反。每次到达探点,

CCS从文件得到100个值,并将他们写入inp_buffer地址。波形之所以

相反,因为input buffer中包含从读入的值,而output buffer包含被处理

函数最后设置与处理值。

注意:目标在探点终止

CCS在目标无论何时到达一个探点是都将暂时停止。因此,如果正使用探点,

则目标应用程序不会遇到实时极限(real-time deadlines)。在此发展阶段,正测试

运算法则。稍后分析使用RTDX和DSP/BIOS的实时行为。图表可以用探点或Run

命令更新。

步骤6:调整gain参数

在C源代码中,处理函数通过gain参数在input buffer使每个值相乘,并将

结果送入output buffer。这样做是通过下列包含于一个while 循环的语句:

*output++=*input++*gain;

此语句通过gain参数相乘每一个在inp_buffer 中的值,并将其放入

out_buffer中相应的位置。Gain参数最初设置为MINGAIN,在volume.h中定义

为“1”。为更改output,需更改gain参数。这样做的一种方法是使用一个监视变

量。

1) View ——> Watch window。

16

PhoenixTreeSky

2) 在watch window中右击,选择Insert New Expression。

3) 在对话框中输入gain,确定。则在窗中显示gain的值。

4) 如果已停止程序,点击Animate钮,重新启动程序。

5) 在watch window中双击gain。

6) 在变量编辑窗口中,改变gain的值为10,确定。

7) 观察改变gain值后,在output buffer图表中信号的振幅。

步骤7:观察out-of-scope变量

已经用watch window来观察和改变变量值。当变量目前没有在断点的当前

范围时,有时你应该检查变量。可通过使用堆栈调用来完成。

1) 单击Halt按钮或shift F5停止程序运行。

2) 回顾volume.c程序。注意到*input既在主函数中定义又在处理函数中

定义。然而,其没有在dataIO函数中定义。

3) 在volume.c代码窗口中,将光标放置在dataIO函数的return;行上。

4) 点击“手”形图标(Toggle Breakpoint)或F9,设置一断点。

5) 运行程序(F5)。CCS自动将断点移到此函数的下一行,以与汇编指令

相符合。并将显示一通知框告诉你系统已移走断点。

6) 按下F5,直到程序停止在dataIO函数的末尾断点处。

7) 在watch window窗口中右击,选择insert new expression。

8) 输入*input。

9) 注意:在watch window中显示*input=unknown identifier,表示*input

在dataIO函数范围内没有定义。

10) View ——> call stack。在watch window旁出现一call stack区域。

11) 点击main(),则在watch window中*input的值为主函数范围内的表

示。(此值应为0,如果修改文件可能会不同)。

12) Hide call stack窗口。

13) 移走dataIO中的return;行断点。

步骤8:使用一GEL文件

CCS提供另一种方法更改变量。此方法用GEL,一个扩展名方式,来创建一

个允许更改变量的小窗口。

17

PhoenixTreeSky

1) File ——> Load GEL。在Load GEL文件对话框,选择。

2) GEL ——> Application control ——> gain。当读取GEL文件时,gain已

被加入到菜单中。

3) 如果已经停止程序,点击Animate按钮。注意:gain仍为先前值,直

到改变gain板的滑标。

4) 在Gain窗口中,用滑标改变gain的值。则在output buffer窗口中波形

振幅改变。另外,无论何时移动滑标,在watch window中的gain变量值也随之

改变。

5) 停止程序运行。

6) 为观察gain GEL函数如何工作,在项目上点击GEL文件的“+”。双击

文件,观察其内容。

Gain函数定义一个slider (滑标)的最小值0,最大值10,与一个增量和

up/down页的值为1。当移动滑标,gain变量改变为滑标所显示的新值。

步骤9:调整并分析processingLoad(负载处理)

在教程中,使用profile-points(分析点)来测量调用put()所必需的周期数。

现在,用profile-point在观察processingLoad变量的结果,此变量被传递到汇编

加载程序。

ProcessingLoad最初设置为BASELOAD,BASELOAD在volume.h中定义为1。

1) profiler ——> Enable clock。(如果出现一资源冲突通知,关闭所有

DSP/BIOS plug-in(插件程序)窗口。接下来,选择Tools ——> RTDX,在下拉菜

单中选择RTDX使之无效)。

2) 打开文件volume.c。

3) 将光标放在Load(processingLoad);行,点击“钟形”图标(Toggle profile-

point)。

4) 同样将return(TRUE);行设置为Toggle profile-point。

5) profile ——> view statistics。其中位置标识数字应为从上向下,从小到

大。

6) 点击Animate标签或F12。

7) 注意第二个profile-point所显示的最大周期数,其应为1018个周期。

(实际数目可能不同,尤其是如果使用一特殊的开发板)这就是当processingLoad

为1时,执行加载程序所需的周期数。

18

PhoenixTreeSky

8) GEL ——> Application control ——>Load。

9) 输入2,并单击Execute。第二个profile-point的最大周期数变为2018。

当增加processingLoad 1,周期数增加约1000。这些指令周期在存储在

中的加载函数中执行。

10) 在profile statistics窗口中右击,选择clear All,将分析结果清零。

11) 停止运行程序(Halt或shift F5)。

12) ①关闭Load和gain控制窗口,窗口,时间/频率图形。

②File ——> File IO,点击Remove File来删除 。

③profile ——> Enable clock。

④取消所有的Breakpoints、probe points和profile points。

⑤关闭所有的窗口,关闭项目。

这些是做其它动作所必需的。

试一试:

① 在watch window加入processingLoad。当使用Load GEL控制,

processingLoad在watch window中的值被更新。

② 在watch window中右击,并选择Insert new expression。用不同的显示

形式进行试验。例如,键入*input,x作为表达式来观察十六进制的sine input。

③ 在volume.h中改变BUFSIZE为0x78(或120)并重新链接,接着重新载

入程序。在File IO对话中改变长度为0x78。对于两个图表,改变Acquisition Buffer

size 和Display size为0x78。这导致一个buffer包含了完整的正弦波而不是两个

半波形。激活程序,注意到输入和输出缓冲器图表现在同相。

④ 试着使用二选一时钟来生成统计表。用断点代替profile-point。选择

profile ——> view clock。运行程序到达第一个断点。在时钟区域双击清除之。重

新运行程序。时钟显示其到达第二个断点处的周期数。

⑤ 通过重复操作第3步至第5步来试验probe points。此时,只使用probe

point和Run命令。注意:需要建立3个probe point。这是因为一个probe point

只能与一个动作相关联。在此两个图表将被更新,一个文件被用做输入。每个这

些动作都需要其自己的probe point。

同时注意到每个probe point必须在代码的不同行进行。作为一结果,目标

被停止三次,并且在目标执行过程中在相同点动作不被执行。因为这些原因,在

此教程中使用的一个probe point和一个断点相结合的方法比只用probe points更

有效。

19

PhoenixTreeSky

Code Composer Studio 教程(四)

—— 调试程序性能

在此教程中,修改上一教程中的例子来建立一个确定其运行时间和允许多线

(multi-threading)的程序。看到调试效果的执行信息。也使用到更多的DSP/BIOS

特性,包括运行图表,实时分析控制板(RTA控制板),统计表视图和CLK、SWI、

STS、TRC模块。

此教程需要一个物理板而不能用一软件模拟器来实行。同时,需要CCS

DSP/BIOS成分。

步骤1:打开并检查项目

1) 在D:hanstudy4建立一文件夹。

2) project ——> open。打开。

3) 在此项目中包含以下文件:

① :此项目的配置文件。

② volume.c:主程序源代码文件,此文件使用了DSP/BIOS。

③ volume.h:此为一头文件,包括volume.c文件中定义的各种变量和结构。

④ :此文件包括载入程序,它只是一个可从只有一个自变量的C程

序生成的汇编循环程序。

⑤ :当保存配置文件时,此链接命令文件即生成。

⑥ volumecfg.s62:当保存配置文件时,此汇编文件生成。

⑦ volumecfg.h62:当保存配置文件时,此头文件生成。

步骤2:观察源代码

保持主函数循环,在真正的应用程序中的dataI/O作为一周期性外部中断的

结果是适合的。在例中仿真一周期性外部中断的一个简单方法是从on-chip定时

器中使用定时中断。

1) 打开文件volume.c。

2) 注意例中以下方面:

① 说明的数据类型已经改变,DSP/BIOS提供的数据类型对其它处理器是很

方便的。DSP/BIOS所使用的大部分类型转变成相应的C类型。

20

PhoenixTreeSky

② 代码用#include来定位三个DSP/BIOS头文件:std.h、log.h和swi.h。std.h

文件必须在其它DSP/BIOS头文件前包括其中。

③ 在配置文件中创建的对象视做外部对象。

④ 主函数不再调用dataIO 来进行处理。取而代之的是,主函数只是在调

用LOG_printf来显示一信息之后返回。这将程序投入到DSP/BIOS空循环。在这

点,DSP/BIOS调用程序控制执行路径。

⑤ 处理函数是通过一调用服从所有硬中断的processing_SWI 的软中断来

调用的。作为选择,一硬ISR(中断服务程序)可直接执行信号处理。然而,信

号处理需要大量周期,或者更多的时间直到下一个中断的到来。这样处理将防止

中断被执行。

⑥ dataIO函数调用一与软中断对象相关联的递减计数器的SWI_dec。当计

数器到达0,软中断安排函数执行并复位计数器。

DataIO函数对基于硬件的dataI/O进行仿真。一典型的程序在一缓存中积累

数据直到有足够的数据进行处理。在此例,处理函数每执行一次dataIO 函数运

行10次。计数器递减通过SWI_dec来控制它。

步骤3:修改配置文件

1) 打开文件。

2) 打开CLK、LOG和SWI管理器。此配置文件包含这些模块的对象,除

了配置文件中的默认设置对象。

3) 点亮LOG管理器中的对象trace ,右边窗口中是它的特性。Vo lu me . c

程序调用LOG_printf来写入大量从此LOG对象开始的例子。

4) 在LOG中,LOG_system对象上右击,从弹出菜单中选择propertise项。

此时出现一LOG_system properties对话框。在运行时,此Log通过不同的DSP/BIOS

模块的系统来存储事件轨迹。

5) 改变buflen特性为512words,确定。

6) 点亮CLK管理器中的dataIO_clk 。注意当此CLK对象被_dataIO激活时

此函数调用。在volume.c中有dataIO函数。

注意:下划线和C函数名称。

此C函数名称冠以下划线前缀是因为配置产生汇编语言文件。此下划线前缀

是从汇编中调用C函数的惯例。

此规则只在所编写的C函数中应用。不需要在配置产生对象或DSP/BIOS API

21

PhoenixTreeSky

调用中使用下划线前缀,因为对于每个对象两个名称自动地创建:一个前缀有下

划线,一个没有。

7) 既然在main中dataIO函数不再运行,那么什么导致此CLK对象执行

其函数?

为了找出原因,在CLK-clock manager properties对话框。

注意到clock manager的CPU中断是HWI_INT4。此特性为灰暗色,是因为它

由HWI_INT4对象自动设置。

8) 不做任何动作,cancel(取消)。

9) 打开HWI对象列表并检查HWI_INT4对象特性。其中断源是在DSP上

的定时器,而且当on-chip定时器产生一中断时它执行一函数来调用CLK_F_isr。

CLK对象函数的执行在CLK_F_isr硬中断函数范围内。因此,它们顺利执行且具有

比任何软中断更高的优先权。(CLK_F_isr保存着寄存器范围,因此CLK函数无需

像在一硬中断服务程序函数内通常所要求的那样保存和还原范围。)

10) 在SWI管理器中,在processing_SWI软中断对象上右击。从弹出菜单

中选择properties项。

① function:当此软中断被激活,处理函数运行。

② mailbox:当一软中断运行时,此mailbox值可控制。个别的API调用影响

着mailbox的值,并可传递依靠结果值的软中断。当一软中断被传递时,当有最

高级优先权的软中断和硬中断线被传递完毕时它运行。

③ arg0、arg1: inp_buffer和out_buffer地址被传递到处理函数。

11) 不做任何更改,cancel。

12) 既然处理函数不再在main中运行,那么什么导致此SWI对象来执行

其函数?在volume.c中,dataIO函数调用减少mailbox值并当新的mailbox值为

0时传递软中断的SWI_dec。因 此 ,SWI对象每到dataIO_CLK对象执行dataIO

函数第十次时执行其功能。

13) File ——> close。提示是否保存变动,Yes。保存此文件同时产生

、volumecfg.s62和volumecfg.h62文件。

14) Project ——> Build。

步骤4:用thread execution(线性执行)来观察运行图表

当你可以用在处理函数内放置一个probe point来测试程序并观察输入/输出

数据图表时,你已经测试了信号处理运算法则。到这一步,你的注意焦点在确定

22

PhoenixTreeSky

thread execution能遇到它们的real-time deadline。

1) File ——> Load program,选择。

2) Debug ——> go main。程序运行到主函数的第一条语句。

3) Tools ——> DSP/BIOS ——> RTA control panel。在CCS窗口底部出现

一使用仪器类型的列表。

4) 在此列表中选中enable SWI logging、enable CLK logging和global host

enable项。

5) Tools ——> DSP/BIOS ——> Execution Graph。在CCS窗口底部出现一

执行图形窗口。

6) 在RTA control panel窗口中右击,选择property page项。

7) 检验message Log/Exection Graph的刷新速率为1 second,确定。

8) Debug ——> Run。在Exection Graph窗口中观察图形。

9) 在时间行上的标志显示每次clock 管理器运行了的CLK函数,计数着

两次processing_SWI对象被运行的标志。应该有10个标志。这表示processing_SWI

对象运行其函数每10次dataIO_CLK对象运行其函数。这是所期望的,因为通过

dataIO函数来减少mailbox值是从10开始。

步骤5:改变并观察加载程序

使用执行图表,能看到程序与其real-time deadline相遇。然而,在一个典型

程序中的信号处理函数必须执行复杂而循环的衰减工作,而不是增加一个值并将

其复制到另一缓存中。你可以通过用Load函数逐渐增加循环衰减来仿真如此复

杂的过程。

1) Tools ——> DSP/BIOS ——>CPU Load Graph。出现一空的CPU Load

Graph。

2) 在RTA control panel窗口中右击,选择property page项。

3) 将statistics view/cpu load graph的刷新速率改为0.5秒,确定。

注意:cpu load通常很低。

Statostics view和cpu load从目标传递很少的数据到主机,因此可以不断地

更新其窗口而不会对程序的执行有大的影响。Message Log和Execution Graph传

递的字数指明了配置文件中相应的LOG对象的buflen(缓存长度)的特性。

由于更多的数据将被传递,你可以使这些窗口更新慢些。

4) File ——> Load GEL。选择文件。

23

PhoenixTreeSky

5) GEL ——> Application Control ——> Load。

6) 输入100,点击Exacute。Cpu Load增加到约9%。

7) 在Execution Graph窗口中右击,并选择clear。注意到程序依然遇到它

的real-time deadline。在每个processing_SWI函数执行间有10个时间标志。

8) 使用GEL控制,改变为200,execute。

9) 在Exection Graph窗口中右击,选择clear。当processing_SWI函数执

行时,一个或两个时间标志出现。这样做意味着程序已消除其real-time deadline?

不,这表示程序的正确机能。运行CLK对象函数的硬中断可以中断软中断处理,

并且软中断依然会在其需要重新运行前完成其工作。

10) 使用GEL控制,将load变为1250,execute。Cpu load增加到大约95%,

并且Exeacution Graph和cpu load更新更慢。

11) 在Execution Graph窗口中右击,选择clear。程序依然遇到其real-time

deadline。因为processing_SWI在10个时间标志出现前完成了。

12) 改变GEL load为1500。Cpu load Graph和Execution Graph停止更新。

这是因为Execution Graph数据在一个空thread execution 中送到主机,此空

thread execution在程序中执行优先权最低。因为高级优先权thread execution使

用所有处理时间,没有足够的时间给主机控制更改就已执行。程序此时失去其

real-time deadline。

13) Debug ——> Halt。这将停止程序并更新Execution Graph。你会在

Execution Graph窗口中assertions行看到矩形。这些矩形指出CCS探测到应用程

序失去一real-time deadline。

14) 改变GEL load为10。Cpu load和Execution Graph重新更新。

注:用RTDX更改load

使用load GEL控制暂停目标。如果你正分析一实时系统而不想影响系统的运

行,使用一RTDX(real-time data exchange)应用程序更改load。这在下一教程中

详述。

步骤6:分析调度表

你可以使用其它DSP/BIOS控制来执行DSP上的load和processing_SWI对象

中的处理统计表。

1) Tools ——> DSP/BIOS ——>Statistics view。一 个statistics view区域

出现。接下来需选择你要观察的统计表。

24

PhoenixTreeSky

2) 在statistics view 窗口中右击,选择property page 项。点亮左框中的

processing_SWI项和右框中全部项,确定。

3) 在窗口中出现一processing_SWI对象的统计表区域。

4) 在RTA control panel窗口中,选中enable SWI accumulators项。

5) 运行程序,Run。

6) 注意在statistics view中的max值,SWI statistics在指令周期被测量。

7) 使用GEL控制,增加load,execute。注意从开始到结束processing_SWI

增加指令周期的执行数目max值的改变。

8) 用不同的load值进行试验。如果减小load值,在statistics view窗口中

右击,选择clear项。这样做重置到他们最低的可能值,允许你观察在max区域

中的当前指令周期数。

9) Halt。关闭所有打开的DSP/BIOS和GEL控制。

步骤7:加入外部STS装置

上一步,你使用statistics view来观察在一软中断执行期间指令执行数目。如

果使用一配置文件,DSP/BIOS自动地支持统计表。这个叫做隐性装置。你也可以

使用API调用其它统计表。这叫做显性装置。

1) 打开文件。

2) 在STS管理器上右击,选择Insert STS。

3) 将新的对象STS0改名为processing_STS。此对象的默认特性都是正确

的。

4) File ——> close。保存该改变到文件。

5) 打开volume.c文件。将程序做以下改动:

① 在#include 行下加入以下几行:

#include

#include

#include

② 在注释行/*objects created by the configuration Tool*/下加入下列行:

extern far STS_obj processingLoad_STS;

③ 在processing函数中,调用Load函数前加入下列行:

/*enable instrumentation only if TRC_USER0 is set */

if (TRC_query(TRC_USER0)==0)

25

PhoenixTreeSky

{ STS_set ( &processing_STS,CLK_gethtime());}

④ 在processing函数中,调用Load函数之后加入下列行:

if (TRC_query(TRC_USER0)==0)

{ STS_delta(&processingLoad_STS,CLK_gethtime());}

6) File ——> save。

7) project ——> Build。

步骤8:观察显性装置

1) File ——> Load program。打开文件。

2) Tools ——> DSP/BIOS ——> RTA control panel。

3) 在RTA control panel窗口中,取消前面所选中的项,重新选中enable

SWI accumulators、enable USER0 trace和global host enable项。

4) Enabling USER0 trace致使调用TRC_query(TRC_USER0)返回0。

5) Tools ——> DSP/BIOS ——> Statistics view。

6) 在statistics view窗口中右击,选择property page项。选择processing_SWI

和processingLoad_STS项,并选中所有四个statistic项,确定。

7) Debug ——> Run。

8) 对processingLoad_STS的max值增加4。

因为使用CLK_gethtime函数作为processingLoad的基准,processingLoad_STS

统计表在on-chip定时计数器增量被测量。SWI统计表在指令周期被测量。在

TMS320C6000 DSPs上,时间的高分辨率每4个指令周期被增加。因此,为转换

processingLoad_STS单元到指令周期,增量必须为4。

9) 在指令周期从processing_SWI max值减去processingLoad_STS max值。

结果应为3420指令周期。(实际上可能有所不同,特别是如果使用了特殊的开发

板)。

10) 这些指令在processing函数内执行,但并不在STS_set和STS_delta调

用之间。例如,如果load 为10,processingLoad max约为2604,processing_SWI

max约为13832。为计算在processing 函数内指令周期(除了调用STS_set和

STS_delta之外)的执行数,公式如下:13832-(2604*4)=3416

11) GEL ——> Application control ——>Load。

12) 改变Load的值。

13) 当两max值增加,两者之间的差度保持不变。

14) 在RTA control panel窗口中,取消enable USER0 trace选项。

15) 在statistics view窗口中右击,选择clear项。

26

PhoenixTreeSky

16) 注意processingLoad_STS没有值被更新。这是因为取消USER0 trace导

致程序中的下列说明为错误:

if (TRC_query(TRC_USER0)==0)

结果导致STS_set和STS_delta调用不被执行。

17) Halt,停止程序运行。

试一试:

为更深一层地探究DSP/BIOS,试一试以下内容:

① 在配置文件中改变SWI管理器的统计表单元特性为毫秒或微秒。Rebuild

并Reload程序,观察在statistics view中值的改变。

② 在配置文件中改变processingLoad_STS对象的主机操作特性A*x和A特

性为4。此主机操作对统计表以4来增加。调用CLK_gethtime导致统计表在高分

辨率定时器增量被测量,次增量每4个cpu周期出现一次。因此,改变主机操作

来转换定时器增量为cpu周期。Rebuild程序,观察statistics view 中值的改变。

③ 用CLK_gethtime函数来代替CLK_gethtime函数。Rebuild,观察statistics

view中值的变化。CLK_gethtime函数得到一个在执行图表中符合定时器标志的低

分辨率时间。当使用CLK_gethtime时必须较大幅度地增加load 来改变statistics

view值。

27

PhoenixTreeSky

Code Composer Studio 教程(五)

—— 实时性能分析

在此教程中,你对程序进行实时性能分析和恰当的时序安排。使用RTDX

(real-time data exchange —— 实时数据交换)对目标进行实时改变,使用

DSP/BIOS周期函数,并设置软中断优先权。

此教程需要一物理板而不能用一软件仿真器来实现。同时,也需要CCS的

DSP/BIOS和RTDX部分。

步骤1:打开并检查项目

1) 建立工作文件夹,编译文件,并创建下列文件:

① volume.c:源文件,允许你在不停止目标程序运行的情况下使用RTDX来

改变load。

② :用VB5.0编写的一个简单的窗口应用程序,它实时地用RTDX

将load值送到目标。

③ ,,:如果你已掌握了VB,就可以用VB

来检查应用程序的这些源文件。

2) 进入CCS,打开项目。

步骤2:修改配置文件

在此,需加一个新的对象在配置文件中。

1) 打开文件。

2) 选择LOG_system,改变buflen特性为512 words,确定。

3) 在PRD管理器上右击,选择Insert PRD。

4) 将PRD0改名为loadchange_PRD。

5) 在loadchange_PRD对象上右击,选择properties项。

6) 将period(ticks)框中改为2,function框中改为_loadchange,确定。

① 将period变默认值为2,PRD管理器用CLK管理器来驱动PRD的执行。

CLK类的。默认特性每毫秒产生一个时钟中断来触发一个PRD标记。因此,此

PRD对象每2毫秒运行一次其函数。

② 改变function为_loadchange。每个period,此PRD对象执行一次

28

PhoenixTreeSky

loadchange C函数。

7) 打开SWI管理器。一个SWI对象PRD_SWI已自动加入。在运行期间,

此软中断执行周期函数。因此,所有PRD函数在软中断环境下被调用并对硬中

断让步。相反,CLK函数在硬中断环境下运行。

8) 打开CLK管理器。注意到PRD_clock的CLK对象运行一个叫PRD_F_tick

的函数。此函数导致DSP/BIOS系统时钟做标记(通过调用PRD_tick API函数),

并且如任何PRD函数需要运行,PRD_swi软中断被传递。PRD_swi对所有的PRD

对象运行函数。

9) 右击PRD管理器,选择properties。PRD管理器有一特性叫 Use CLK

manger to drive PRD。确保此项被选中。如此项没选中,PRD_clock对象将自动被

删除。程序可能接着从其它一些事件中调用PRD_tick。例如,一驱动周期函数的

硬中断。

10) 回想一下,processing_SWI对象有一个值为10的mailbox,并且mailbox

值通过每毫秒运行一次的data_CLK对象来递减,结果processing_SWI每10毫秒

运行一次其函数。相反,loadchange_PRD对象应每2毫秒运行其函数一次。

11) File ——> close。保存改动到。同时产生、

volumecfg.s62和volumecfg.h62。

12) Project ——> Rebuild All。

步骤3:观察源代码的改变

打开volume.c文件。与前一教程相比此源代码有所不同。

注意void loadchange() {…}函数,其由PRD对象调用,这是处理器被控制的

地方。

此函数用RTDX API函数在实时信号处理中改变load。对于程序中的改变(与

前一教程相比)注意以下几个方面:

① RTDX_enableinput的调用可将control_channel的输入通道使能,所以数

据可从主机流向目标。在运行时,一个VB主客户程序写一个控制值在那个通道,

从而送数据到目标应用程序。

② RTDX_readNB的调用要求主机送一个load控制值在control_channel上,

并将其存储在不同的被调控制,此调用是非模块化的,它不须等待主机传递数据

即返回。

当主客户程序写入control_channel时,数据到达。从调用RTDX_readNB起

29

PhoenixTreeSky

直到数据被写入不同控制,此通道一直忙,且没有额外的请求在此通道能通过(这

叫调用RTDXreadNB不成功)。在此期间,调用RTDX_channel Busy对

control_channel返回TRUE。

③ ProcessingLoad=control;说明通过control来设置processingLoad为指定值。

步骤4:在运行时用RTDX控制来改变Load

当你通过在处理函数中放置一probe point来测试程序并观察输入/输出数据

图表时,你已经测试了信号处理运算法则。在此发展阶段,你应注意于确保所加

入的调度单元仍能遇到其real-time deadline。同样,probe point终止目标并干扰

测试的实时特性。

1) File ——> Load program,加载。

2) Tools ——> DSP/BIOS ——> RTA control panel。

3) 在RTA control panel中选中以下几项:

enable SWI logging、enable PRD logging、enable CLK logging、enable SWI

accumulators、enable PRD accumulators、global host enable。

4) Tools ——> DSP/BIOS ——> Execution Graph。

5) Tools ——> DSP/BIOS ——> Statistics view。

6) 在statistics view中右击,选择property page。选中以下几项:

loadchange_PRD、PRD_swi、processing_SWI和右框中Count、max、average。

7) 在RTA control panel中右击,选择property page。

8) 将message log/exection graph刷新率设为1秒,将statistics view/cpu

load graph刷新率设为0.5秒,确定。

9) Tool ——> RTDX。

10) 注意到RTDX已激活。这是在第2)步打开DSP/BIOS控制之后出现的。

在持续模式下DSP/BIOS控制配置和使能RTDX。

在持续模式,RTDX没有记录从目标接收到的数据。这允许持续数据流。(如

果你的程序没有使用DSP/BIOS,你可使用RTDX区域来进行配置并直接使能

RTDX)。

11) 使用窗口资源管理器,运行(在study5 文件夹中)。Load

control窗出现。其中每个刻度改变load值50,大约50000指令。这个简单的窗

口应用程序用VB编写的,如果你已掌握了VB,你可检查源文件。此应用程序使

用下列RTDX功能:

30

PhoenixTreeSky

① (“control_channel”,”W”):当打开应用程序,打开一个控制通

道来写信息到目标。

② ():当关闭应用程序,关闭控制通道。

③ 2(datal2,bufstate):写入滑标控制control_channel的当前值,使

目标程序可以读此值并用其来更新load。

12) Debug ——> Run。

Processing_SWI每10个time 记号(和PRD记号)出现一次。PRD_swi每2

个PRD记号运行一次。Loadchange_PRD在PRD_swi顺接运行。这些是预期的运

行频率。

PRD统计表在PRD记号中测量。SWI统计表在指令周期测量。Loadchange_PRD

的max和Average区域显示少于从开始运行到其完成间此函数所需时间的一完

整PRD记号。

13) 用Load control窗口中逐渐地增加processing load。(当DSP程序被终

止时,如果在Load control窗口中移动滑标,新的load control值通过RTDX在主

机上进行缓冲。这些直到DSP应用程序重新运行并从主机调用RTDX_readNB来

请求更新load值)。

14) 重复步骤13),直到看到loadchange_PRD 的max和Average值增加,

并且在Execution Graph的Assertions行出现兰色方块。Assertions表示一个调度

元没有遇到其real-time deadline。

当你增加load,loadchange_PRD 的max值增加,随着load 的增加,

processing_SWI占用长时间来运行而loadchange_PRD 不能开始运行,直到长时

间通过其real-time deadline。

当你不断增加load,因而低优先权的空循环不再执行,主机停止接收实时数

据且DSP/BIOS plug-ins停止更新。用行列数据停止目标更新plug-ins。

步骤5:修改软中断优先权

为理解为什么程序没有遇到其real-time deadline,你需要检查软中断调度元

的优先权。

1) Debug ——> Halt。

2) 打开。

3) 点击SWI管理器。SWI对象优先权在右侧窗口中显示。(KNL_swi对象

运行一个执行TSK管理器的函数。此对象必须总是具有最低的SWI优先权。)因

31

PhoenixTreeSky

为PRD_swi 和processing_SWI 对象二者具有相同的优先级,当processing_SWI

正在运行时PRD_swi不能占在其前面。

Processing_SWI每10毫秒运行一次,PRD_swi每2毫秒运行一次。当load变

高时,processing_SWI运行超时2毫秒,并且其防止PRD_swi遇到其real-time

deadline。

4) 为改正此程序,将PRD_swi拖至一高级别的优先权,如Priority2。

5) File ——> save。

6) File ——> close。关闭。

7) Project ——> Build。

8) File ——> Reload program。

9) Debug ——> Run,重新执行程序。在运行时用Load control窗口来改

变load。

10) 你可立即增加load而不会导致PRD_swi错过其real-time deadline。

11) Debug ——> Halt,关闭所有窗口。

试一试:

为进一步探究DSP/BIOS,试一试下面内容:

① 当你增加load 时,Execution Graph显示processing_SWI需要不止一个

PRD记号来运行。这意味着processing_SWI 正失去其real-time deadline 吗?要

知道processing_SWI必须每10毫秒运行一次,而PRD记号每毫秒都会出现。

② 如果processing函数直接从硬ISR(中断服务程序)调用而不是延迟到

软中断,将会发生什么?这将导致程序失去其real-time deadline。因为硬ISRs运

行的优先权高于最高级别优先权的SWI对象。

当load高时,PRD_swi需要优先于processing_SWI。如果processing_SWI是

一个硬中断,它不能被PRD_swi占先。

③ 观察cpu load graph。使 用RTA control panel来开启和关闭统计表类加

器。注意cpu load graph为受影响。这证明统计表类加器在处理器上放置了一个

非常小的load。

统计表类加器对processing_SWI统计表有多大影响?当你开启和关闭统计

表类加器时观察statistic view。所不同的是每个类加器需要指令数目的一个精确

测量。记住观看结果要clear statistics view。

④在loadchange函数中加入STS_set和STS_delta。这个变化会影响cpu load

32

PhoenixTreeSky

多少?现在,在dataIO函数中加入调用STS_set和STS_delta。这变化会影响cpu

load多少?为什么?认为每个函数周期被执行。甚至对函数处理所需要的有一个

很小的增加,运行周期在cpu load上有惊人的影响。

33

PhoenixTreeSky

Code Composer Studio 教程(六)

—— 与I/O设备的连接

在此,你用RTDX(Real-time Date Exchange)和DSP/BIOS将一个程序与I/O

设备进行连接。你也使用到DSP/BIOS API 中的HST、PIP和SWI模块。

在此需要一个物理板,且不能用一个软件仿真器来实现。同时,需要CCS的

DSP/BIOS和RTDX部分。

步骤1:打开并检查项目文件

打开一个项目文件,并检查此项目文件中的源代码文件和所用到的库文件。

1) 创建一个文件夹,d:hanstudy6 。

2) project ——>open ,打开study6中的文件。

3) 在此项目中包含以下文件:

① hostio.c:主程序源文件。

② :此 VB 应用程序产生一正弦波并显示输入、输出信号。

③ :此 VB 应用程序允许你控制输出信号的 volume。

④ :当保存配置文件(configuration file)时产生的链接命令文

件。

⑤ hostiocfg.s62:保存配置文件时创建的汇编文件。

⑥ hostiocfg.h62:保存配置文件时创建的头文件。

步骤2:观察C源代码

在此教程中的例子对一个将音频信号数字化的DSP应用程序进行仿真,调

整它的volume,且调整volume产生一个模拟输出。为达到简易性,此例中没有

实际的设备被用来发送和接收模拟数据,代替它的是,例子用host-generated数

字数据测试运算法则。输入/输出数据和volume控制用RTDX在host和target之

间进行调动。

在主机上运行一VB应用程序使用RTDX来产生输入信号并显示输入和输出

信号。此应用程序允许开发者不停止目标进行测试运算法则。类似的方法可用来

创建其它应用程序进行实时测试控制的显示。

1)打开hostio.c文件。

34

PhoenixTreeSky

2)注意此例的以下几个方面:

①三个RTDX通道被全局定义。第一个输入通道控制volume。第二个输入通

道接收从主机来的输入信号。输出通道将来自目标的输出信号传送到主机。

②如果通道当前不在等待输入调用RTDX_channelBusy返回FALSE,这表示数

据已到达并可以读取。当主机客户写数据到control_channel时数据被异步传输。

③RTDX_Poll调用与RTDX底层进行对话来读写数据。

④如果通道被使能,调用RTDX_read等待数据。

⑤如果通道使能,调用RTDX_write写缓存中的内容到输出RTDX通道。

⑥当目标通过一个RTDX_enableinput调用使能control_channel,其它RTDX通

道没被使能。取而代之的是,一个主机程序使能这些通道。这是因为被看作应用

程序主要部分的使用control_channel的滑标来进行控制。通过在目标程序中使

能此通道,你知道当应用程序运行时通道被使能。相反,A2D和D2A通道被用来

测试运算法则。因此,这些通道通过主机应用程序被使能和禁止。

步骤3:回顾signalprog应用程序

VB应用程序的源代码在文件中是可用的。关于

此应用程序的详细资料在文件中提供。在此部分,检查几个例中

重要的函数和例程。

① Test_ON:当你点击Test_ON按钮,此例程运行。它创建RTDX输入通道(to

DSP)和输出通道(from DSP)的输出界面实例。接着其打开并使能一通道。在

应用程序中的通道与在hostio.c源代码中全局定义的通道相同。

此例程同时清除图形并启动用来调用Transmit_Signal和Receive_Signal函数

的定时器。

在VB源代码中定义的全局定义将Test_ON例程中用到的READ_CHANNEL和

WRITE_CHANNEL连接到hostio.c中用到的D2A_channel和A2D_channel。

②Test_OFF:此例程禁止、关闭和释放通过Test_ON创建的RTDX对象。它也

禁止定时器。

③Transmit_Signal:此函数产生一正弦波信号并在传输信号图形中显示。接着,

函数试着用toDSP通道的写方法传输信号到目标。

④Receive_signal:此函数用fromDSP通道的ReadSAI2方法从目标读一个信号。

并在接收信号图形中显示。

⑤tmr_MethodDispatch_Timer:此例程中调用

35

Transmit_Signal和

PhoenixTreeSky

Receive_Signal函数。此例程在定时器目标通过Test_ON例程使能之后1毫秒时

间间隔被调用。

步骤4:运行应用程序

1) project ——>Build。

2) File ——>Load program,加载文件。

3) Tools ——>RTDX。

4) 在RTDX窗口中点击configure按钮。在RTDX特性对话框的General

Setting标签,选择Continous模式,确定。

5) 在RTDX窗口中将RTDX disable改为RTDX enable 。

6) Tools ——>DSP/BIOS ——>Message Log 。在Messega Log窗口中右

击,选择property page 项,选择trace作为log名称进行监控,确定。

7) Debug ——>Run 。

8) 运行和。观看这两个VB应用程序。

程序必须在RTDX被使能并且程序在运行之后启动。因为当你运行程序时,它创

建并打开RTDX control channel 。如果在此RTDX没有使能,不能打开此

通道。程序可在任何时候被启动。直到你点击Test ON按钮,它才

使用RTDX 。

9) 在signalprog窗口右上角点击Test ON ,启动输入和输出通道。

10) 在volume slider窗口中拖动滑标。这会改变输出信号的volume 。观

察接收到的信号图形振幅的变化。(只有图形的左、右刻度值发生变化。图形变

化刻度自动地调整正弦波的尺寸和窗口的尺寸。)

注意:volume slider的最初设置volume slider滑标的最初设置与应用程序是

非同步的。当你第1次移动滑标时,它们被同步。

11) 关闭volume slider应用程序。这样就关闭了输入、输出通道。

12) 在signalprog窗口中点击Test OFF,关闭控制通道。

13) Debug ——>Halt。停止程序运行。

14) 这时你在message log区域看到调用LOG_printf的Hostio例子的启动

信息。你先前没有看到此信息是因为整个程序在主程序内运行。DSP/BIOS在空循

环内与主机进行通信。知道从主程序返回一个程序,此程序才进入空循环。因此,

如果你想在运行时刻观察DSP/BIOS调用的结果,你的程序应该在从主函数返回

之后实现其功能。

36

PhoenixTreeSky

步骤5:修改源代码以使用Host Channels and Pipes

现在修改程序来使用DSP/BIOS提供的Host Channels and Pipes。修改后的程

序仍旧实时测试你的DSP运算法则。尤其是在主机上产生一个正弦波,这次数据

来自主机文件。

HST模块用外围设备提供一个更直接的途径以实现I/O。HST模块对主机I/O

使用PIP模块。每次I/O设备和ISRs准备好测试,你可使用PIP模块API对源代

码做最小的修改。

1) 改源文件hostio.c并创建一输入数据文件,如下:

① hostio.c:被修改后的源文件,它使用DSP/BIOS API 的HST和PIP模块来代

替RTDX传送输入、输出信号。

② :此文件包含输入数据。

2) 打开hostio.c,源代码做了如下改动:

① 加入下列头文件:

# include

# include

② 去掉BUFSIZE定义、inp_buffer和out_buffer的全局定义和RTDX输入/

输出通道说明。保留了RTDX通道来控制volume。

③ 将主函数中一个while循环中的input和output功能移到A2DscaleD2A

函数内。

A2DscaleD2A函数由A2DscaleD2A_SWI对象调用。

A2DscaleD2A_SWI对象传递两个HST对象到此函数。此函数于是调用

HST_getpipe来设置每个HST对象使用的内部PIP对象的地址。

调用PIP_getReaderNumFrames和PIP_getWriteNumFrames,然后测定在输入

pipe中是否至少存在一frame已准备好被读出和在输出pipe一frame被写入。

使用与步骤2相同的RTDX调用,此函数获得由RTDX控制通道设置的volume。

PIP_get的调用从输入管道中获得一个完整的frame。PIP_getReaderAddr的

调用获得一个在输入pipe frame中开始数据的指针,并且PIP_getReaderSize获得

在输入pipe frame中的字数。

PIP_alloc的调用从输出pipe中获得一空帧。PIP_getWriterAddr的调用在输

出pipe frame中获得一个写数据开始位置的指针。

函数于是通过volume增加输入信号并将结果写到由PIP_getWriterAddr提供

的使用指针的frame中。

37

PhoenixTreeSky

PIP_put的调用将完整的frame放入输出pipe,PIP_free的调用反复应用输入

图象,因此它可以在下次此函数运行时重新生成。

④ 加入一error函数,此函数写一个error信息到trace log,且将程序置于

一无限循环中。如果当没有可被处理可利用的数据frame 时,A2DscaleD2A运行,

则此函数运行。

步骤6:更多有关Host Channels and Pipes

每个Host Channel使用一个内部pipe。当你正在使用一个Host Channel,你

的目标程序控制一个pipe末端且Host Channel控制plug-in操纵pipe的另一端。

当你正准备修改程序来使用除Host PC之外的外围设备时,你可保持控制目

标端的pipe的代码,并在通过处理I/O设备以控制pipe另一端的函数内加入代

码。

步骤7:向配置文件中加入通道和一个软中断

A2DscaleD2A函数由一SWI对象调用并使用两个HST对象。

A2DscaleD2A函数也涉及两个PIP对象,但当你创建HST对象时,这些对象

被内部创建。HST_getpipe函数获得与每个HST对象进行通信的内部PIP对象的

地址。

1) 打开文件。

2) 在HST管理器上右击,选择Insert HST项。

注意:已经存在两个叫RTA_fromHost和RTA_toHost的HST对象。这些对象

内部使用以更新DSP/BIOS控制。

3) 将HST0改为input_HST。

4) 在input_HST上右击,选择properties项,为此对象设置下列特性:

① mode:此项改为input。此项特性决定目标程序控制pipe的哪一端,与

Host Channels控制play-in操纵哪一端。一输入通道将数据从主机送至目标。一

输出通道将数据从目标送到主机。

② framesize:此项改为64。此特性设置在通道中frame的大小。

③ notify、arg0、arg1:此三项分别为_SWI_andn、A2DscaleD2A_SWI和1。当

此输入通道包含一完整的frame,且参数传递到函数时,这些特性指定函数来运

行。SWI_andn函数提供另一种方法来操纵一个SWI对象的mailbox。

38

PhoenixTreeSky

SWI_andn函数将mailbox值视为一个bitmask(位掩码)。它清除掉由传递到

函数的第二参数指定的bits。因此,当此通道包含一full frame时(因为目标被一

frame 充满),它为A2DscaleD2A对象调用SWI_andn,并致使其清除mailbox的

bit 1。

5) 插入另一个HST对象,并命名为output_HST。

6) 设置下列特性:

① mode : output。

② framesize : 64。

③ notify : _SWI_andn。

④ arg0 : A2DscaleD2A_SWI。

⑤ arg1 : 1。

当此输出通道含有一空frame(因为目标读并释放一frame),其使用SWI_andn

来清除mailbox的第二位。

7) 右击SWI管理器上,选择Insert SWI。

8) 将SWI0改为A2DscaleD2A_SWI。

9) 设置A2DscaleD2A_SWI下列特:

① functin: _A2DscaleD2A。当此软中断被传递并运行时,此项特性致使对象

调用A2DscaleD2A函数。

② mailbox:3。这是mailbox对此对象的原始值。Input_HST对象清除掩码的

第一位,且output_HST对象清除掩码的第二位。当此对象运行A2DscaleD2A函

数时,mailbox值重新设置为3。

③ arg0、arg1:input_HST、output_HST。两个HST对象名称被传递到

A2DscaleD2A函数。

10) File ——> close。保存改变,同时产生、hostiocfg.s62 和

hostcfg.h62。

步骤8:运行修改后的程序

1) project ——> Rebuild All 。

2) File ——> Load Program。选择 。

3) Tools ——> DSP/BIOS ——> Host Channel control 。Host Channel control

列出了HST对象并允许你连接它们到Host PC文件来启动和关闭通道。

4) Debug ——> Run 。

39

PhoenixTreeSky

5) 在input_HST通道上右击,并选择Bind 。

6) 在你的工作文件夹内选择 。

7) 在output_HST通道上右击,并选择Bind 。

8) 在文件名称框中键入 ,并点击Bind 。

9) 在input_HST通道上右击,并选择Start 。

10) 在output_HST通道上右击,并选择Start。注意Transferred列显示数

据正被调用。

11) 当数据调动完毕,Halt

40

,停止程序的运行。


本文标签: 程序 函数 文件 运行 使用