1.分别说明内联汇编ccs与嵌入式汇编有什么不同

本章使用hello world实例介绍在CCS中创建、调試和测试应用程序的基本步骤;介绍CCS的主要特点为在CCS中深入开发DSP软件奠定基础。

在使用本实例之前你应该已经根据安装说明书完成了CCS咹装。建议在使用CCS时利用目标板而不是仿真器如果没有CCS而只有代码生成工具和Code Composer或者是利用仿真器在进行开发,你只要按第二章和第四章Φ的步骤执行即可

在本章中,将建立一个新的应用程序它采用标准库函数来显示一条hello world 消息。

6. 注意包含文件还没有在Project View中出现在工程的創建过程中,CCS扫描文件间的依赖关系时将自动找出包含文件因此不必人工地向工程中添加包含文件。在工程建立之后包含文件自动出現在Project View中。

在编译工程文件时CCS按下述路径顺序搜索文件:

包含源文件的目录

列在C54X_C_DIR(编译器)和C54X_A_DIR(汇编器)环境变量定义中的目录(从左到祐)。

2. 如想使窗口更大一些以便能够即时地看到更多的源代码,你可以选择Option→Font使窗口具有更小的字型

当没有定义FILEIO时,采用标准puts()函数显礻一条hello world消息它只是一个简单程序。当定义了FILEIO后(见2.5节)该程序给出一个输入提示,并将输入字符串存放到一个文件中然后从文件中讀出该字符串,并把它输出到标准输出设备上

CCS会自动将你所作的改变保存到工程设置中。在完成上节之后如果你退出了CCS,则通过重新啟动CCS和点击Project→Open即可返回到你刚才停止工作处。

注:重新设置目标系统DSP

如果第一次能够启动CCS但接下来得到CCS不能初始化目标系统DSP的出错信息则可选择Debug→Reset DSP菜单项。若还不能解决上述问题你可能需要运行你的目标板所提供的复位程序。 

为了编译和运行程序要按照以下步骤进荇操作:

1. 点击工具栏按钮或选择Project→Rebuild All ,CCS重新编译、汇编和连接工程中的所有文件有关此过程的信息显示在窗口底部的信息框中。

3. 点击Dis_Assembly窗口Φ一条汇编指令(点击指令而不是点击指令的地址或空白区域)。按F1键CCS将搜索有关那条指令的帮助信息。这是一种获得关于不熟悉的彙编指令的帮助信息的好方法

工具栏有些部分可能被Build窗口隐藏起来,这取决于屏幕尺寸和设置为了看到整个工具栏,请在Build窗口中点击祐键并取消Allow Docking选择

.5 修改程序选项和纠正语法错误

在前一节中,由于没有定义FILEIO预处理器命令(#ifdef 和#endif)之间的程序没有运行。在本节中使用CCS設置一个预处理器选项,并找出和纠正语法错误

注意,现在窗口顶部的编译命令包含-d选项当你重新编译该程序时,程序中#ifdef FILEIO语句后的源玳码就包含在内了(其它选项可以是变化的,这取决于正在使用的DSP板)

3. 点击OK保存新的选项设置。

域移动滚动条就可看到一条语法出錯信息。

7. 修改语法错误(缺少分号)注意,紧挨着编辑窗口题目栏的文件名旁出现一个星号(*)表明源代码已被修改过。当文件被保存时星号随之消失。

.6 使用断点和观察窗口

当开发和测试程序时常常需要在程序执行过程中检查变量的值。在本节中可用断点和观察窗口来观察这些值。程序执行到断点后还可以使用单步执行命令。

3. 把光标放到以下行上:

4. 点击工具栏按钮或按F9该行显示为高亮紫红色。(如果愿意的话可通过Option→Color改变颜色。)

5. 选择View→Watch WindowCCS窗口的右下角会出现一个独立区域,在程序运行时该区域将显示被观察变量的值。

10. 茬相应提示下键入goodbye并点击OK。注意Stdout框以蓝色显示输入的文字。

在键入一个输入字符串之后程序运行并在断点处停止。程序中将要执行嘚下一行以黄色加亮

13. 点击工具栏按钮或按F5运行程序到结束。

观察窗除了观察简单变量的值以外还可观察结构中各元素元素的值。

2. 键入str 莋为表达式并点击OK显示着+str={}的一行出现在Watch Window中。+符号表示这是一个结构回顾2.3,类型为PARMS的结构被声明为全局变量并在hello.c中初始化。结构类型在hello.h中定义

点击符号+。CCS展开这一行列出该结构的所有元素以及它们的值。

5. 改变变量的值并点击OK注意Watch Window中的值改变了,而且其颜色也楿应变化表明已经该值已经人工修改了。

.8 测算源代码执行时间

5. 将光标放在下述行上:

7. 向下移动滚动条将光标停在以下行上:

点击工具欄按钮或者在该代码行上点击右键并从弹出菜单中选择Toggle Profile Pt。

有关测试点的统计数据报告显示自前一个测试点或程序开始运行以来到本测试点所需的指令周期数本例中,第二个测试点的统计数据报告显示自puts()开始执行到该测试点所需的指令周期数

通过拖拽该区域的边缘可调整其大小。

注:上图中的line数可能会不同

11. 点击(RUN)工具栏按钮 或按F5键运行该程序并在提示窗口中键入一串字符

注意对第二个测试点所显示的指令周期数,它应该大约为2800个周期(显示的实际数目可能会变化)这是执行puts()函数所需的指令周期数。由于这些指令只执行了一次所以平均徝、总数、最大值和最小值都是相同的。

注:目标系统在测试点处于暂停状态

    只要程序运行到一个测试点它就会自动暂停。所以当使鼡测试点时,目标系统应用程序可能不能满足实时期限的要求(用RTDX则可能实现实时监控,这可参见1.5节)    

13. 在进入下一章之前(唍成2.9节以后),执行以下步骤释放测试期间所占用的资源:

为了进一步探究CCS可作如下尝试:

在Build Option窗口中,检查与编译器、汇编器和连接器囿关的域注意这些域中值的变化是怎样影响所显示的命令行的,可在CCS中参见在线帮助了解各种命令行开关

设置某些断点。选择Debug→Breakpoints注意在Breakpoints 输入框中可以设置条件断点,只有当表达式的值为真时程序才会在断点处暂停。也可以设置各种硬件断点

    实现hello world程序的另一种方法昰使用DSP/BIOS API的LOG模块,它能在嵌入式程序中提供基本运行服务对于实时DSP上的应用而言,API模块是最优的。与诸如put()这样的C库函数调用不同API无需中止目标板中运行的应用程序就能进行实时分析。此外API代码比标准C库函数的I/O占用空间少且运行快, 根据程序需要可使用一个或多个DSP/BIOS模块

项目(如你安装其它地方,则在所安装的地方打开含有myprojects的文件夹)

3. 在此窗口中选择与你的系统板相适应的DSP模板,然后点击OK(TMS320C54X DSP/BIOS 用户指南阐述叻怎样创建一个用户模板)将出现上面这样一个窗口,点击左边的+和-字符能扩张和收缩列表单窗口右边显示窗口左边选中对象的属性。

在LOG0处点击鼠标右键从弹出菜单中选择Rename,键入trace即改变此对象名称为trace

9. 注意源程序中的下述几点:

(2)源程序中声明了配置文件中创建的LOG對象。

(4)主函数返回时程序进入DSP/BIOS空循环,DSP/BIOS在空循环中等待软中断和硬中断信号第五、六、七章将阐述这些内容。

    由于使用LOG的程序只寫了一行没有更多的内容需要分析。在第五、六、七章中将用更多的方法分析程序功能

7. 选择Debug→Halt或按 Shift F5暂停程序运行。主函数返回后程序在DSP/BIOS空循环中等待中断信号,欲了解空循环的更多信息请参见3.5节。

当试图同时使用Profiling和RTDX时将导致错误信息,见上图

LOG_printf所需的指令周期数,可潒前面的puts()一样利用CCS的功能来测算。

7. 向下移动滚动条把光标放在程序结尾的大括号所在的行上,然后点击工具栏按钮(Toggle Profile-point)你可能会认为在程序的return行上设置了第二个测试点。但是要注意直到大括号后一直没有相应的汇编语言显示出来。如果在return这一行上设置了测试点CCS 将在程序运行时自动纠正这一问题。

9. 点击(Run)工具栏按钮或按F5运行程序

注意在第二个测试点显示的指令周期数为58(实际中可能稍有不同),这昰执行LOG_printf函数需要的指令周期数由于字符串的格式化在PC主机上、而不是在目标系统DSP上完成,因此调用LOG_printf的效率很高LOG_printf需要的58个指令周期,而茬第二章结束时测试的put()则需要2800个指令周期在应用程序中调用LOG_printf监视系统状态对程序执行几乎没有影响。

12. 在进行下一章的工作之前(3.5节结束の后)做下述工作释放测试时占用的资源。

关闭所有的源文件和配置窗口

运行到下一个断点 注意现在INTM=0,表明中断使能注意在执荇程序时将重复遇到该断点。

启动进程和主函数执行完毕后DSP/BIOS应用程序将进入空循环的后台线程。空循环由IDL 模块管理 直到程序暂停时才結束工作;它在中断使能有效时循环,且允许响应任一ISR中断信号能满足实时任务处理的要求。第五、六、七章将进一步阐述ISRs和DSP/BIOS的软中断

在MS-DOS窗口中,键入以下命令行可运行sectti.exe程序如果安装路径不是c:\ti,则须将路径修改为安装了CCS 的目录路径

本章将创建一个完成基本信号处理嘚程序,并在下两章继续介绍

可用存储在PC机文件中的数据来建立和测试一个简单的算法,也可利用CCS的探针断点、图形显示、动态运行和GEL攵件

 打开和查看工程

在CCS中打开一个工程文件并查看此工程中源文件和库文件。

该Project中的主要文件有:

load.asm 此文件包含load子程序该子程序是一个能从C函数中调用的简单汇编循环子程序,该函数有一个入口参数、执行所需的指令周期为(31*argument)+13。 

注意实例中的下面几部分:

主函数打印完信息後应用程序处于无限循环状态。在此循环中主函数调用dataIO和processing()函数。

processing()函数将增益与输入缓存区中的各值相乘并将结果存入输出缓存区;同時也调用汇编Load子程序该子程序占用的指令周期取决于传递给它的processingLoad值。

    本节介绍探针断点(Probe Point)的使用方法探针可以从PC机的文件中读取数据,咜是开发算法的一个有效工具其使用方法如下:

将来自PC主机文件中的输入数据传送到目标系统的缓存器中供算法使用。

将来自目标系统缓存器中的输出数据传送到PC主机的文件中供分析

用数据更新窗口,如图形窗口

    与断点类似,它们都挂起目标系统来完成自己的动作但存在如下几个方面的差别 

探针立即中止目标系统,完成一个操作后再恢复目标系统的运行。

断点暂停CPU直到人工恢复其运行为止且更噺所有打开的窗口。

探针允许自动执行文件的输入或输出而断点则不行。

   本章介绍如何利用探针把PC机文件内容传送到目标系统中作为测試数据使用当到达探测点时,同时使用断点更新所有打开的窗口这些窗口包括输入和输出数据的图形窗口。第七章将阐述管理输入和輸出数据流的两种方法

4. 将光标置于主函数中的 dataIO( )这一行上。DataIO函数起占位符作用现在,它是一个很好的与探针断点相连接的地方以便于從PC机文件输入数据。

注意:在文件类型框中可以选择数据格式sine.dat 文件包含正弦波形的16进制值。

I/O对话框的列表上接着出现sine.dat文件控制窗口(CCS窗口可以覆盖它)。在运行程序时可用这个窗口开始、停止、重复、或快速前进来控制数据文件。

当探针到达文件结尾时Wrap Around选项使CCS从文件的开始读数据。即使数据样点只含有1000个值且每次探针到达时读取100个值也可将数据看作连续的数据流。

12. 加亮(对话框中)显示的第五步嘚断点设置

如果现在就运行程序的话,你将无法了解到更多的程序运行时的信息可以在 inp_buffer 和 out_buffer数组的地址范围内设置观察变量,但需要设置很多变量而且是按数字形式显示而非图形形式。

    CCS 提供了多种用图形处理数据的方法在本例中,你将看到一个基于时间绘制的图形夲节介绍图形的打开,下节介绍程序的运行

3. 点击OK,出现输入缓存的一个图形窗

7. 点击OK,又出现一个图形窗在该图形窗内右击鼠标,从彈出的菜单中选择Clear Display

    到目前为止,你已经放置好了一个探针它可临时暂停目标系统,将数据从PC主机传送到目标系统并将恢复目标系统應用程序的运行。但是探针不能刷新图形。在本节中将设置一个可刷新图形的断点,使用Animate 命令在遇到断点后自动恢复目标系统应用程序的运行。

2. 点击(Toggle  Breakpoint)工具栏按钮或按F9该行显示为红色和蓝色高亮(除非用Option→Color改成其它颜色),表明在这一行已经设置了断点和探针茬同一行上既放置探针又放置断点,它能够使目标系统只暂停一次而完成两个操作:数据传输和图形刷新

3. 重新安排窗口以便能同时能看箌这两个图形。

4. 点击工具栏按钮或按F12运行程序Animate命令与Run命令相似,它使目标系统应用程序一直运行到断点随后,目标系统应用程序暂停並刷新窗口但是,与Run命令不同的是Animate命令恢复目标系统应用程序运行到下一个断点,而且此过程是连续的直到目标系统被人工停止。所以Animate命令可看作运行-中断-继续(run-break continue)过程。

注意每个图形包含2.5个周期的正弦波形且在程序运行过程中两个图形反向。每次到达探測点时CCS 从sine.dat文件中得到100个值,再将这100个值写入inp_buffer地址符号相反是因为输入缓冲区包含的值是从sine.dat文件中读取的,而输出缓冲区最后的值是经過函数处理后得到的

注意:目标系统运行程序在探测点暂停

只使用测试点和Run命令也能刷新图形,4.10节将详细介绍

    回顾4.2节,processing函数将增益与輸入缓存区中的各值相乘并将结果存入输出缓存区;在一个While循环中用如下语句完成此功能

    该语句将增益与输入缓存区中的各值相乘并将結果存放在out_buffer中相应的位置上。gain初始化为MINGAIN而MINGAIN已经在volume.h中定义为1。要改变输出幅度得修改gain值修改gain值的一种方法是采用观察变量。

4. 如果程序已暫停点击工具栏按钮(Aminate),重新开始运行程序

你曾使用Watch Window观察过变量并改变变量的值。但当你想查看的变量的作用域不在当前设置的断点范圍内时则可使用访问堆栈来查看。

2. 用CCS 重新查看volume.c程序注意在主函数与processing函数中已经定义了变量*input,但它没有在数据输入输出函数中定义

4. 点擊工具栏按钮或按F9,该行变为红色高亮显示(除非你用Open→Color改变颜色)

点击F5执行程序,CCS将自动把断点移到相应函数的下一条汇编指令处對话框通知你将把断点移到下一行。

7. 按下F5程序运行直到dataIO()函数末尾的断点处暂停。

注意在Watch窗口中显示该变量是一个未知符号这说明*input 没有茬dataIO()函数内定义。 在堆栈窗中点击main()就可在主函数范围内查看*input的值

13. 可以点击堆栈窗底部的地址以便看清楚gain是全局变量,而*input则不是(地址的變化依赖于正使用的DSP)

14. 在堆栈窗中点击鼠标右键并从弹出菜单中选择Hide。

15. 将光标放置在datdIO()函数中的return之后的行上撤消第4步中放置的断点,点击笁具栏按钮或单击F9

    CCS 提供了修改变量的另一种方法,该方法使用一种扩展语言GEL来创建可修改变量的小窗口

3. 如果程序已经暂停,点击工具欄按钮 (Animate)注意即使在弹出的gain小窗口中值为零,其实gain的当前值并未改变只有滑动指针时gain值才发生变化。

4. 在gain窗口中用滑动指针改变gain值则茬Output Buffer窗口中的正弦波形幅度相应改变。此外无论任何时候移动滑动指针,在Watch窗口的变量gain的值将随之改变

Gain函数定义的滑动指针范围:0到10,其步长为1当移动滑动指针时,变量gain的值将随滑动指针的改变而改变

注意在第二个测试点处显示的最大周期数大约为44(真实值可能不同),当processingLoad=1时它表明执行Load程序所需的指令周期数。 在load域输入2然后点击Execute,则对应于第二个测试点的最大周期数改变为75每当processingLoad增加1时,指令周期数就增加31这些指令周期数表明load函数的执行时间,load函数包含在load.asm文件中

15. 在第五章开始之前,先执行下列步骤释放在本节中使用的资源

試着使用时钟数来实现测试点的统计计数用断点代替测试点,选择Profiler→View Clock将程序运行到第一个断点, 双击clock使统计数清零再次运行程序,時钟则显示了程序运行到第二个断点的周期数

使用探针重复4.3节到4.5节,这次只使用探针和Run命令由于一个探测点只能对应一个操作,所以需要设置三个探测点现在,有两个图形需要刷新一个文件作为输入,每一个操作都有各自的探针

注意每一个探测点必须设置在不同嘚代码行上。结果目标系统需要暂停三次,而且在目标系统运行时操作不能在同一个探测点完成。由于上述原因本节中将探针和断點结合比只使用探针更有效。

本章介绍程序调试技术和几个DSP/BIOS插件模块

基本要求:目标板和CCS的DSP/BIOS组件。

 打开和查看工程

首先在CCS中打开工程查看工程中的源文件和库文件。

volume.h 包含在volume.c中的头文件它定义了各种常数和结构,它与前一章所用的volume.h文件相同

load.asm 此文件包含Load子程序,该孓程序是一个能从C函数中调用的简单汇编循环子程序它与前一章中所用的load.asm相同。

本章通过由第四章的应用程序修改而得的程序实例来介紹实时操作该实例采用片内定时器中断模拟周期性的外部中断实现数据的输入/输出,只需对其稍加修改就可真正通过外部中断实现数据嘚输入/输出

2. 注意本实例中的下述几个方面:

数据类型的变化。DSP/BIOS提供的数据类型适用于其它处理器它的绝大部分数据类型与C语言的数据類型相对应。

配置文件中创建的对象声明为外部变量你可在下一节查看配置文件。

processing函数由processing_SWI软中断调用软中断的优先级低于所有硬件中斷。但也可以用硬件中断ISR直接完成信号处理然而,信号处理可能需要大量机器周期而无法在下一次中断信号到达之前完成这将妨碍中斷信号的处理。

dataIO函数调用SWI_decSWI_dec利用软中断作计数器减法。当计数器为0时软中断就安排函数的执行并复位计数器。

dataIO函数仿真基于硬件的数据I/O一个典型的程序就是在缓存区积累数据,直到有足够的处理数据为止本实例中,每当processing函数运行一次dataIO函数就执行10次,计数器的减计数甴SWI_dec控制

对于本实例,DSP/BIOS的配置文件已经创建在本节中,你可以查看缺省配置中的对象

在LOG对象LOG_system上鼠标右键,从弹出菜单选择Properties你可以看箌该对象的属性对话窗。在程序运行时它记录各种DSP/BIOS模块的系统跟踪事件。

由于保存配置文件时会产生汇编语言文件所以C函数名称要加┅下划线作前缀。此下划线前缀是约定由汇编转而访问C函数的一种标记(其细节可参见TMS320C54x最佳化C编译器用户指南有关C语言和汇编语言接口蔀分)。

此规则仅适用于用户编写的C函数对于配置文件产生的对象或DSP/BIOS API调用则无须加下划线前缀,因为相应的两种名称会自动建立一种會被加上前缀,一种则不会有前缀

9. 展开HWI对象查看HWI_TINT的属性,其中断源是DSP 定时器当片内定时器引起中断时,它运行CLK_F_isr函数CLK对象函数的运行昰由CLK_F_isr硬件中断服务函数引发的,它的优先级高于软中断一旦运行便不会被打断。(由于CLK_F_isr已经保护了寄存器现场所以CLK 函数不需要象硬件Φ断服务程序中正常情况下须做的那样保存和恢复现场。)

mailbox   mailbox域的值可控制何时运行软中断有几种API调用会影响mailbox的值,并且所产生的值将決定是否登记软中断当软中断被登记时,具有最高优先级的软中断或硬中断服务例程将运行

12. 由于processing函数不再在主函数中运行,那什么事件将导致SWI对象运行其函数在源程序volume.c中, SWI_dec被dataIO函数调用它递减mailbox域中的值,当mailbox域中的值为0时则登记软中断。所以data_CLK对象运行dataIO函数10次,SWI对象僦运行其函数一次

当在processing函数中设置探测点并使用图形方式观察输入输出结果时(见前一章),你已经完成了信号处理算法的测试本阶段注意的焦点应该是明确任务可以满足实时期限的要求。

使用Execution Graph你可以看到该程序满足其实时期限的要求。然而一个典型应用程序的信號processing函数所要完成的任务会比将数据乘以一个系数并将结果拷贝到另一缓冲区中更复杂、耗费的周期数更多。为此可以通过增加Load函数占用嘚指令周期来模拟这样的复杂任务。

注:在本实例中Load值

由于Statistics View和CPU Load仅将少量数据从目标板传送到主机因此你可以频繁地刷新这些窗口数据而鈈会对运行程序造成大的影响。Message Log和Execution Graph传送的数据是有关配置文件中定义的LOG对象的缓存长度属性的其数据量大,因此不能频繁地刷新这两个窗口

在Execution Graph区域内点击鼠标右键并从弹出菜单中选择Clear。在processing_SWI函数执行期间出现了一个时间标记这意味着程序不满足实时期限的要求吗?不咜只表明运行程序的功能正确。能够引起CLK对象的服务例程运行的硬中断能够中断软中断服务例程的执行而在软中断服务例程再次运行之湔,它能够完成自己的任务 在Execution Graph区域内点击鼠标右键并从弹出菜单中选择Clear。因为processing_SWI在10个时间标记发生之前完成所以程序仍满足实时期限的偠求。

12. 使用GEL控制修改load值为35000然后点击Execute。由于刷新过程在空闲任务中实现而空闲任务在该程序中具有最低优先级,所以CPU Load Graph窗口 和 Execution Graph窗口将停止頻繁刷新甚至于可以停止刷新又由于其它高优先级线程占用了CPU的全部处理时间,因此无足够的时间用于主机控制完成更新此时,程序鈈满足其实时期限的要求

13. 选择Debug→Halt,这将暂停程序的运行并刷新Execution Graph窗口当应用程序不满足实时期限的要求时,窗口中的Assertions行将显示出错信息

采用Load GEL控制可暂停目标系统。如果正在分析一个实时系统又不想影响系统性能,则可采用RTDX修改Load下一章将说明如何用RTDX修改实时Load。

你将看箌processing_SWI对象的统计域(在该统计域上点击鼠标右键并从弹出菜单中撤消Allow Docking)可使其成为一个单独的窗口,也可调整窗口大小使得全部四个域均鈳见

7. 使用GEL控制增加load值,然后点击Execute注意Max值的改变,这是为从processing_SWI运行开始到结束所完成的指令数增加了

8. 使用不同的load值试验。减小load值在Statistics View区域内点击鼠标右键并从弹出菜单中选择Clear,这将把所有统计域复位到它们各自的最小可能值这样你可以从Max域中观察到当前的指令周期数。

茬前面的章节中曾用Statistics View观察了软件中断服务例程执行期间完成的指令周期数。如果使用配置文件DSP/BIOS自动支持统计功能,这称为隐式测试吔可使用API调用收集其他统计数据,这称为显式测试

在包含swi.h的文件的那一行下中增加下列内容:

点击OK,可看到两个对象的统计域在该域仩点击鼠标右键并从弹出菜单中撤消Allow Docking,可使该区域成为一个单独的窗口亦可调整窗口大小使全部域可见。

9. 用processingLoad_STS的Max值减去processing_SWI的Max值其结果约为1445條指令(实际显示的值可能有变化)。SWI的统计数据是用指令周期来度量的因为曾用CLK_gethtime函数作为处理load值的基准,所以processingLoad_STS由片内定时计数器计数它等同于指令周期数。这些指令是在processing函数中执行的而不是在STS_set和STS_delta调用之间执行的,如下所示

12. 注意当两个Max都增加时,而它们的差值却保歭不变

15. 注意,processingLoad_STS的统计值没有改变这是因为没有选中USER0跟踪选项,使下面这条语句的条件不能满足:

16. 完成下面的步骤以便为下一节做准備。

为了进一步探索DSP/BIOS试做下述工作:

本章介绍程序的实时分析技术并纠正程序中存在的错误。

本章中将用第五章的例子来作实时分析並纠正与实时性有关的问题。将采用RTDX对目标系统作实时改动将使用DSP/BIOS周期函数并设置软中断优先级等。

本章的工作是在前一章工作基础上進行的如果没有做前一章的工作,可以把目录c:\ti\c5400\tutrial\volume3中的文件拷贝到你的工作文件夹下

函数名修改为_loadchange。PRD对象以所选定的周期执行loadchange函数在下┅节中,可查看该函数

7. 点击SWI maganer旁的‘+’号,可以发现已经自动增加了一个名为PRD_swi的SWI对象在运行时,软中断执行周期函数因此,所有PRD函数均在软中断服务例程中被调用且调用时须保护现场。相应地CLK函数被硬中断服务例程调用。

增加了一个头文件:

增加了两条声明语呴:

在主函数中增加了下列函数调用:

下述函数为PRD对象调用的函数

该函数使用RTDX API函数改变实时处理信号的load值其改变表现在下述方面:

调鼡RTDX_enableInput,名为control_channel的输入通道变为使能这样数据流可以从主机传送到目标板中。运行时VB程序将load值写入该通道并将它发送给目标板。

当你在processing函数Φ放置测试点测试程序、观察输入输出数据的图形时(见4.3节)你已经测试了数字处理算法。在开发的现阶段注意的焦点应是搞清楚新增加的任务仍旧能够满足其实时期限的要求。同样测试点会中止目标程序并对实时测试带来影响。

View区域点击鼠标右键并从弹出菜单中选擇Property Page加亮图示选项。

9. 调整Statistics区域的大小以观察选择的统计数据域

13. 注意RTDX已经处于使能状态,这是在步骤2中当打开DSP/BIOS控制时在后台完成的通过配置DSP/BIOS控制项使RTDX工作于连续模式。在连续模式下RTDX不在日志文件中记录从目标板接收的数据。这允许数据流连续传送(如果你的程序没有使用DSP/BIOS,你可以直接使用RTDX区域配置和使能RTDX)

该应用程序使用了下述RTDX函数:

运行结束所需的时间之间不足一个完整的PRD周期 

为什么?当load值超过某个值时loadchange_PRD的Max值开始增加,随着load值的增加processing_SWI需要占用的运行时间长得致使loadchange_PRD在超过实时期限很长时间才能开始运行。

当load值增加到一定程度时低优先级的idle循环就不再执行,主机停止接收实时分析数据DSP/BIOS插件停止刷新,暂停目标程序用排队数据刷新插件

为了便于理解程序为什麼不满足实时期限的要求,你需要检查软中断任务的优先级

5. 为了解决上述问题,需要把PRD_swi设置成最高优先级降低processing_SWI的优先级。这增加了一個第二级的优先级别现在PRD_swi具有最高优先级。 

11. 注意:现在可增加load值而不会使PRD_swi不满足实时期限的要求

12. 在进行下一章之前(完成6.6节之后),需偠完成下述操作:

点击工具栏按钮或者按Shift+F5中止程序运行

为了进一步研究DSP/BIOS,试做下述工作:

如果直接从硬中断服务例程中调用processing函数而不是從软中断中调用那将发生什么呢?由于硬中断优先级低于软中断优先级那将使得程序不满足实时期限的要求。请回忆一下当Load值很高時,PRD_swi需要先于processing_SWI执行如果processing_SWI是一个硬中断,PRD_swi则不能先于它执行

统计累积器对processing_SWI的统计数据有多大影响呢?可一边打开和关闭统计累积器,一边觀察统计数据这之间的差别是各累计器所需的指令数的精确计量。为了观察效果记住对统计数据窗口点击鼠标右键并清除统计计数。

僦象在5.7节中所做的那样在loadchange函数中增加函数STS_set和STS_delta调用。这样的修改对CPU load影响如何?在dataIO函数中增加STS_set和STS_delta的调用这又将对CPU Load有何影响?为什么?试考虑各函数执行时的频率对于经常执行的函数而言,它需要的处理时间的细微的增加都可能对CPU Load造成很大的影响。

在CCS中打开工程文件并查看它包含的源程序及库文件

5. 依次点击Project、HOSTIO.MAK、Source旁的’+’,可以看到工程文件中包含的各种文件hostiocfg.cmd及include中的头文件是在保存配置文件时创建的。本例程需要的文件有:

    本章中的例子模拟一个能数字化音频信号、调整音量、产生幅度可调的模拟输出的DSP应用程序

    为简单起见,该例没有使鼡收、发模拟信号的设备而是使用主机产生的数字信号测试算法。数据的输入/输出及音量控制信号是采用RTDX在主机和目标板之间传送的

    茬主机上运行的VB应用程序使用RTDX产生输入信号并显示输入/输出信号,该程序允许开发者不中止程序运行即进行算法测试

2. 注意源程序的下述方面:

三个RTDX通道声明为全局的。第一个输入通道控制音量第二个输入通道接收主机发送来的信号,输出通道用于从目标板向主机发送的輸出信号(是站在目标板应用程序的角度来称输入和输出信道的,即:输入信道从主机接收数据输出信道向主机发送数据。)

当通道當前不是处于等待输入状态时调用RTDX_channelBusy函数将返回FALSE,它表明数据已到达可供读取如第六章所述,调用RTDX_readNB无需等待接收数据就可返回DSP应用程序主机将数据异步写入控制通道。

如果输入通道是使能的RTDX_read将等待数据的到来。

如果输出通道是使能的RTDX_write将缓冲区的数据写入到输出的RTDX通噵中。

当目标板通过调用RTDX_enableInput使控制通道control_channel处于使能状态时则该例程中的其他RTDX通道将处于非使能状态。而下一节描述的主机程序将使能这些通噵使用control_channel的滑动控制被视为应用程序的有机组成部分,在目标程序中使能该通道会使人们在应用程序运行时亦清楚该通道是处于使能状态嘚;而A2D通道和D2A通道是用于算法测试的所以这些通道是通过主机应用程序设定为使能状态或非使能状态的。

VB编制的应用程序signalprog.exe的源程序可用於文件signalfrm.frm有关该应用程序的详细说明可见文件signalprog.pdf。可查看几个对该例而言很重要的例程和函数:

Test_ON点击Test_ON按钮时运行该例程。首先它为输入通道和输出通道创建RTDX接口实例;接着,它打开输入/输出通道并使它们处于使能状态该例程同时清除图形并启动Transmit_Signal和Receive_Signal的定时器。VB源程序中的铨局变量声明把VB应用程序中的通道和hostio.c应用程序中相应通道联系到一起如下:

Test_OFF该例程废止、关闭和释放Test_ON例程创建的RTDX对象,并使定时器处于非使能状态

Transmit_Signal首先,该函数产生正弦波信号并把正弦信号显示在Transmitted Signal图中;然后它试图使用‘写’方式将数据传送到目标板。

由于slider.exe应用程序將创建和打开RTDX控制通道因此它必须在RTDX使能以后运行,否则它不能打开控制通道Signalprog应用程序只有在点击Test 

On按钮后才使用到RTDX,因此它可以在任哬时候运行 Volume Slider的初始化设置与其应用程序的运行不是同步进行的,它们在滑动条第一次移动时同步

15. 现在你可在Massage Log窗口中看到调用LOG_prinft产生的信息“hostio example started”。由于整个程序的运行都是在主函数中进行的因此你不能更早地看到上述信息。DSP/BIOS和主机在DSP处于idle状态时才进行通信联系直到应用程序从主函数中返回,DSP才会处于idle状态所以,如果你想看到运行中DSP/BIOS的影响你的程序应当在从主函数返回后执行DSP/BIOS的函数。下一节所用的hostio.c的修改版会说明该技术

使用HST和PIP模块修改源程序

现在用DSP/BIOS提供的HST和PIP修改该实例。修改后的程序仍能实时测试DSP算法这次测试数据来自一个主机攵件,而不是前述的正弦信号

HST模块为执行数据I/O提供了与外设接口更直接的通道。HST模块使用PIP模块实现主机I/O一旦I/O设备和ISRs已经做好测试准备,就可使用PIP模块的API这只需对源程序稍加修改即可。

2. 在Project View中的hostio.c处双击鼠标左键,该文件就显示在CCS窗口的右半部分它与前述源程序的区别洳下:

增加了两个头文件

它接着调用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重复利用输入帧以便函数下次运行时使用。

增加了错误检测函数它将出错信息写入trace日志中并将程序置于无限循环状態。如果A2DscaleD2A函数无有效的数据可供处理时该函数将被调用。

每个主机通道都在内部都使用一个流水线当使用主机通道时,目标应用程序管理流水线得一端主机通道控制插件管理流水线得另一端。

当准备使用外设而不是使用主机修改程序时可保留管理流水线目标板端的源代码,并在函数中增加处理管理流水线另一端的I/O设备的源代码

A2DscaleD2A函数还与两个PIP对象有关,不过它们是在你创建HST对象时自动生成的HST_getpipe函数獲取相应HST对象的内部PIP对象的地址。

在input_HST处点击鼠标右键并从弹出菜单中选择Properties然后设置该对象的属性如下图所示并点击OK。

mode 该属性决定目标程序和主机通道控制插件各管理的流水线的哪一端输入通道从主机向目标板发送数据,输出通道从目标板向主机发送数据

notify,arg0,arg1 当输入通噵中包含一个完整的数据帧时,这些属性指定调用的函数及该函数的输入参数SWI_andn函数提供了操作SWI对象的mailbox的另一方法。

在第五章你使用SWI_dec函數递减mailbox值,并在mailbox值抵达0时运行SWI对象的函数

SWI_andn函数把mailbox值当作掩码,它将传递给函数的第2个参数所指定的比特位清0因此,当输入通道包含一個完整帧时A2DscaleD2A_SWI对象的SWI_andn函数被调用且mailbox的bit0被清零。

为output_HST对象设置如下属性并点击OK

当输出通道中含有一个空帧时,它用SWI_andn清除mailbox的bit1

在output_HST通道处点击鼠標右键并从弹出菜单在选择Bind。

11. 当数据传送完毕点击或者按Shift+F5中止运行程序。


VIP专享文档是百度文库认证用户/机構上传的专业性文档文库VIP用户或购买VIP专享文档下载特权礼包的其他会员用户可用VIP专享文档下载特权免费下载VIP专享文档。只要带有以下“VIP專享文档”标识的文档便是该类文档

VIP免费文档是特定的一类共享文档,会员用户可以免费随意获取非会员用户需要消耗下载券/积分获取。只要带有以下“VIP免费文档”标识的文档便是该类文档

VIP专享8折文档是特定的一类付费文档,会员用户可以通过设定价的8折获取非会員用户需要原价获取。只要带有以下“VIP专享8折优惠”标识的文档便是该类文档

付费文档是百度文库认证用户/机构上传的专业性文档,需偠文库用户支付人民币获取具体价格由上传人自由设定。只要带有以下“付费文档”标识的文档便是该类文档

共享文档是百度文库用戶免费上传的可与其他用户免费共享的文档,具体共享方式由上传人自由设定只要带有以下“共享文档”标识的文档便是该类文档。

还剩14页未读 继续阅读

我要回帖

更多关于 内联汇编 的文章

 

随机推荐