《DSP应用技术实验讲义_图文(精).doc》由会员分享,可在线阅读,更多相关《DSP应用技术实验讲义_图文(精).doc(94页珍藏版)》请在三一办公上搜索。
1、实 验 准 备第一章 CCS介绍1.1 CCS功能CCS 是TI 公司推出的功能强大的软件开发环境,现在该集成软件环境可以用于TI 各系列DSP 系统的软件程序开发。CCS 主要具有以下特性和功能:集成可视化代码编辑界面,可以直接编写C/C+、汇编、头文件以及CMD 文件等; 集成代码生成工具,包括汇编器、C 编译器、C+编译器和链接器等;集成基本调试工具,可以完成执行代码的装入、寄存器和存储器的查看、反汇编器、变量窗口的显示等功能,同时还支持C 源代码级的调试;支持多DSP 的调试;集成断点工具,包括设置硬件断点、数据空间读/写断点,条件断点等; 集成探针工具(Probe Points),可
2、用于算法仿真,数据监视等用途;提供代码分析工具(Profile Points),可用于计算某段代码执行时消耗的时钟数,从而能够对代码的执行效率做出评估;提供数据的图形显示工具,可绘制时域/频域波形等图像;支持通过GEL (通用扩展语言)来扩展CCS 的功能,可以实现用户自定义的控制面板/菜单、自动修改变量或配置参数等功能;支持RTDX (实时数据交换)技术,可在不打断目标系统运行的情况下,实现DSP 与其他应用程序(OLE )间的数据交换;提供开放式的plug-ins 技术,支持其他第三方的ActiveX 插件,支持包括软件仿真在内的各种仿真器(需要安装相应的驱动程序);提供DSP/BIOS工
3、具,增强了对代码的实时分析能力,如分析代码的执行效率、调度程序执行的优先级、方便了对系统资源的管理或使用(代码/数据空间的分配、中断服务程序的调用、定时器的使用等等),减小了开发人员对DSP 硬件知识的依赖程度,从而缩短了软件系统的开发进程。1.2 CCS界面CCS 的主界面如图1.1所示。工程管理器主要用于统一管理各工程中所包含的文件,在工程管理器窗口中,可以添加、删除、激活和编辑工程中的源文件,同时也可以对编译器、汇编器和链接器的参数进行设置。管理器可以同时打开多个工程。但是,当前只能有一个工程是有效的。 调试工具栏集成了程序员调试DSP 软件时最常用的调试命令。输出窗口可以用来输出或者显
4、示编译/汇编/链接过程中的各种信息、输出C 语言标准输出函数的运行结果以及调试过程中出现的错误信息(例如断点设置错误等)。变量观察窗口可以观察程序中变量的地址或者数值,其中Watch Locals标签页窗口中会自动显示当前堆栈帧中的所有局部变量。程序员也可以在这个窗口或者其他Watch 窗口中添加其他需要观察的变量,同时,还能根据需要设置其显示的数据格式。堆栈切换窗口主要用于各个堆栈帧之间的切换,因为当前局部变量的访问涉及当前堆栈帧在堆栈中的位置时,或当调试运行到任意一个被调函数中时,由于其调用函数中的局部变量不在当前堆栈帧中,如果想访问它就必须要进行堆栈切换。这个窗口能显示系统堆栈中的各级堆
5、栈帧,只要点击对应的函数名,就能访问到对应函数中的局部变量。CPU 寄存器窗口显示当前CPU 寄存器中的值,同时也可以对其进行修改。CCS 工作区中,主要有以下四类窗口:1. 源代码编辑窗口:可以打开,编辑C+、C 或者汇编等源代码文件。2. 反汇编窗口:通过仿真器从目标系统中读取二进制程序代码,将其反汇编为汇编指令后显示出来,同时还显示各种符号信息(如函数名)以及对应的地址和指令的二进制目标代码。3. 存储器观察窗口:通过指定存储器的起始地址和数据格式,可以读取目标系统存储器中连续区域的数据并显示,同时也可以对其进行修改。4. 图像显示窗口:根据某段连续存储器中的数据显示特定的图形,具体来说
6、可以显示时/频域波形、眼图等形式的图形,其中时/频域波形的显示在调试信号处理算法的过程中是一个非常有效的工具,不管对于时域的采集信号还是最后计算得到的功率谱,通过这个窗口中的显示波形,都能确定其结果是否正确。状态窗口 菜单栏 工具栏工程管理窗口调试工 具 栏 代 码 编 辑 窗口 反 汇编 窗口 存储器查看窗口 图形显示窗口 输出窗口堆栈窗口 变量查看窗口寄存器窗口 图1.1 CCS界面主要组成窗口1.3 CCS开发流程本节介绍基于TMS320F281x DSP系统软件程序开发的总体步骤,并对其中比较重要和常用的工具进行介绍。图1.2是开发DSP 程序的整体流程,它可以帮助程序开发人员更好地理
7、解如何使用CCS 集成开发环境的各功能部件。由于CCS 集成开发环境在代码生成工具的基础上,扩展了一系列调试和实时分析功能,因此它能够用于DSP 系统软件开发的各个阶段,如图1.2所示。 选择目标DSP/BIOS配置算法标准更新顾问功耗规划 代码生成 项目管理 编辑器 在线帮助 电源管理 代码调试 模拟 多处理器 RTDX 高级事件触发实时分析 可视化数据 代码大小优化运行跟踪图1.2 CCS基本开发流程一般来说,安装好CCS 后,首先要正确地对CCS 进行设置(安装仿真器驱动进行emulate 或安装虚拟驱动进行simulate ),然后对源程序文件进行规划,建立汇编源代码文件、C 或者C+
8、源代码文件和定位控制文件(.cmd ),把这些文件和必要的库文件(主要针对包含C 或者C+源代码文件的工程)都添加到新建的工程中。若采用DSP/BIOS工具来开发程序,还需要添加DSP/BIOS的CDB 文件。接下来对此工程的各种汇编、编译和链接选项进行设置,再通过“build all”命令来完成整个工程的编译和链接。如果编译和链接时没有出现错误就能生成一个输出文件(.out ),最后用File 菜单下的load program命令将其加载到DSP 系统的程序存储器(RAM )中,之后就可以开始对DSP 软件程序进行在线调试,确保软件算法能稳定、可靠地实现目标系统各种功能,另外CCS 还可以通
9、过强大的分析工具,对代码的执行情况进行统计和分析,并将其作为进一步优化的依据,从而提高代码的执行效率。调试出稳定、可靠、高效的软件程序后,我们就能将程序烧写到DSP 芯片内部的Flash 里(如TMS320F2812)使DSP 系统能够脱开仿真器独立工作,从而完成DSP 系统样机的研制。接下来将以CCS (C2000)Version2.20为例,一步一步具体演示如何在CCS 集成开发环境中通过工程来开发DSP 软件。 1.3.1 目标代码生成在完成CCS 设置基础上,就可以连接目标系统、仿真器及PC 机。当用Emulate 仿真方式时,必须首先为仿真器和目标系统上电,然后打开CCS2(C200
10、0)程序,如果CCS 设置正确,同时目标系统、仿真器和PC 机间的连接无误,CCS 就能正常启动(启动过程不出现任何错误提示窗口,并在CCS 窗口的标题栏显示“/F28xx XDS510 Emulator/ CPU_1 - 28xx - Code Composer Studio”)。接下来就能进行具体的软件开发,其一般步骤如下:l. 选择Project New命令,弹出如图1.3所示的创建工程对话框,填入工程名并为其选择工作目录;在Project Type中选择工程最终的输出形式(.out 或者.lib ),在Target 中选择目标芯片的类型(这里须选择TMS320C28XX )。这一过程和
11、目前大多数软件开发环境类似,唯一的区别是必须要指定正确的目标芯片,给定工程的名字后CCS 会在指定的目录下自动产生一个和工程名相同的子目录。一般情况,我们将工程中所需要的文件都存放在该目录下,以便于项目管理。2. 选择File New Source File,在打开的文本编辑器中输入源代码,然后选择File Save as,在出现的文件对话框中输入文件名,并为其选择路径(一般就在对应的工程目录下)。3. 接下来需要将源代码文件包含到工程中:选择Project Add Files to Project ,在出现的对话框中选择要包含的源代码文件,然后通过Project Compile File命令
12、就能对当前文本编辑窗口中的源文件进行编译,根据输出窗口的错误提示对源代码进行修改。除了源代码文件外,一个完整的工程还可能需要包括其他源文件(如库文件、链接器命令文件等)才能生成最终的输出文件。例如,如果工程中存在C 语言源代码文件,则还要添加C 实时运行库,库文件可以通过以下两种方式添加: 利用Project Add files to project命令添加; 选择Project Build Options,在其打开对话框中Linker 标签页下的Library Search Path和Include Libraries框中分别输入库文件的路径和名称。 图1.3 创建工程对话框4. 添加C 实
13、时运行库的同时还要将Build Options中Linker 标签页下的Autoinit Model设置成Run-time Autoinitialization(-c )。5. 接下来用同样的方式,新建链接器命令文件(.cmd ),用Project Add files to project 命令添加链接器命令文件(.cmd )文件。6. 最后选择Project build对整个工程进行编译、汇编和链接。完成上述各步后,CCS 就能生成一个和工程相对应的.out 文件(在工程目录的Debug 中),通过File Load Program命令将此.out 文件加载到目标系统中。1.3.2 目标代码
14、调试下面以CCS 安装目录下的教学程序(TItutorialdsk2812volume1)为例来简单介绍一下软件的调试过程:这个工程包含三个源代码文件:两个汇编源代码文件,一个C 源代码文件(主程序所在文件)。其中vectors.asm 用于存放中断向量表,这里只有一个复位中断向量,因为没有定义其他中断服务函数。Load.asm 中的代码是一个可以在C 语言中调用的汇编函数。主程序的作用非常简单,将输入缓冲单元中的数据乘上一个增益后,放到输出缓冲单元中。因为volume1.pjt 已经存在,可以直接用build 命令对整个工程进行编译、汇编和链接,生成volume1.out ;也可以将volu
15、me1.pjt 删除,用上面介绍的代码生成流程,重新建立这个工程文件,最后将工程volume1生成的volume1.out 目标代码文件加载到目标系统中,接下来就能利用CCS 提供的各种调试手段对其进行调试。1. 调试过程中常用工具命令在图1.1的调试工具栏中,一些常用的调试命令介绍如下: Source - Single step:用于C 源程序里的单步,遇到函数调用会跳到函数中继续单步执行。 Source - Step Over:用于C 源程序里的单步,但是,遇到函数调用时不会跳转到函数中执行,而是把整条函数当成一个单步来执行。Step Out:当程序执行到被调函数中时(无论是在汇编或者C
16、里),如果使用该命令,则程序将执行到该函数返回处才停止。Assembly - Single Step :用于汇编程序里的单步,遇到函数调用会跳到函数中继续单步执行。 Assembly - Step Over :用于汇编程序里的单步,但是,遇到函数调用时不会跳转到函数中执行,而是把整条函数当成一个单步来执行。Run :运行程序,直到断点处停止运行,直到再次触发运行命令才恢复程序的运行。 Halt :停止程序的运行。 Animate :运行程序,遇到断点后,CCS 先暂停程序的运行,对打开的变量、寄存器、存储器、图像显示等窗口中的数据进行刷新。然后,自动恢复程序运行,这样在图像显示窗口中就可以观察
17、到动画效果。Toggle breakpoint:在源程序编辑窗口中提示符所在的行设置断点,如果该行已经存在断点,则取消该断点。Remove all breakpoints:取消工程中所有已设置的断点。Toggle Probe Point:在源程序编辑窗口中提示符所在的行设置探针点,如果该行已经存在探针点,则取消该探针点。Remove all Probe Points:取消工程中所有已设置的探针点。 在调试过程中,可以查看DSP 相关寄存器以及存储器内的数值,如图1.1所示,一些常用的查看指令介绍如下: Registers window:用于打开DSP 内部寄存器窗口,查看各项数值,并可以修改。
18、 Memory Window:用于打开存储器窗口,包括DSP 内部以及外部存储器中地址单元的数值,若该单元可写,则支持数据的修改。View Stack:用于各个堆栈帧之间的快速切换,查看各帧中局部变量数值。 View Disassembly:用于查看二进制程序代码所对应的汇编指令,同时还显示各种符号信息及其对应的二进制地址。Watch window:用于打开变量窗口,观察程序中变量的地址和数值。 Quick Watch:快速打开变量窗口。以上这些快捷方式,在菜单中都可以找到相应的命令。 当把程序加载到DSP 程序空间以后,首先,可以用Debug Go main命令将程序运行到main 源代码处
19、(实际系统在执行源代码里的main 函数前,要先调用一个C 初始化函数即_c_int00,从而完成全局变量的初始化,设置堆栈指针等工作,在这个初始化函数的最后才调用main 函数,这段初始化代码保存在运行支持库函数中,工程在链接阶段会把它加到.out 文件,其实现的源代码可以在库文件所在路径下的rts.src 文件中找到。当把.out 文件加载到目标系统中或者执行Restart 命令后,反汇编窗口中会显示当前的程序指针处于_c_int00函数的入口处,而不是main 函数的入口处),如图1.4所示,其中黄色的箭头(图中上方窗口中)代表当前PC (程序指针)在对应源代码文件中的位置,而反汇编窗口
20、中绿色箭头(图中下方窗口中)处则是当前PC 所指向的存储器地址、机器码数据以及其对应的汇编指令,也就是DSP 下一步要执行的机器指令。 图1.4 源程序窗口和反汇编窗口2. 断点的使用可以通过调试工具栏中的Toggle Breakpoint图标或者右键菜单中的Toggle breakpoint命令来设置断点,同时用Debug 菜单下的BreakPoints 命令能将该断点配置成一般断点、条件断点(特定的表达式为真时才停止程序的运行)或者硬件断点。设置好断点后运行程序(Run )以后,当程序执行到断点处时会停止运行直到下一个运行命令被触发,在程序停止运行期间,CCS 还会对各种调试数据进行更新。
21、在源文件任何有效语句处都可以设置断点,如果断点设置出错,例如将断点设到了无效行,CCS 会给出错误提示,并自动将断点转移到下一有效行处。3. 观察窗口的使用在volume.c 中,选中任意一个变量,在右键菜单中选择Quickwatch 或者Add to watch Window ,CCS 将打开Quickwatch 窗口的Watch1子窗口并显示选中的变量。在观察窗口中变量名后面的Value 一栏中可以直接修改被观察变量的取值,在Radix 一栏中还能设定数据的显示格式(十六进制、八进制、十进制、二进制、浮点数、无符号整型等等)。另外Quickwatch 窗口的Watch Locals子窗口中
22、会自动显示当前函数作用域中所有局部变量的值。把全局变量str 加到观察窗口中,执行程序后,点击变量左边的“+”,观察窗口会将结构变量展开,同时显示结构变量中的每个成员的值,该显示方式同样适用于数组的显示。把main 函数中的局部变量input 添加到观察窗口中,执行程序进入dataIO 函数(通过断点或者单步都可以),此时input 变量超出了起作用范围(main 函数),所以变量Value 一栏显示“identifier not found:input ”,但是可以利用Stack Call窗口来察看不同作用域中的变量,如图1.5所示,执行View Call Stack打开堆栈切换窗口,双击窗
23、口中的main( 项,即可在观察窗口中查看input 变量的当前值了。 图1.5 堆栈切换窗口及变量观察窗口 4. 使用探针实现文件输入/输出探针点是实际上是一种特殊的断点。通过这个功能可以实现:当程序运行到探针点时,CCS 中断目标系统中DSP 的运行,从与该探针点关联的数据文件中(PC 机中的.dat 文件)读出数据并写到目标系统的存储器中,或者从目标系统的存储器中读出数据并写到数据文件中。完成数据的交换后,CCS 自动恢复目标系统DSP 的运行。探针点特别适合用于算法的仿真,在目标系统的输入/输出硬件电路完成前,可以使用该工具来模拟数据的输入/输出。另外,它还可以在软件仿真时为虚拟目标系
24、统提供数据的输入/输出功能。它是用已知的数据流测试算法正确性的必备工具。下面将在工程volume1的基础上,利用探针工具来模拟数据的输入。C 源代码程序中有一个dataIO( 函数,由于没有硬件支持,该函数仅仅是个空函数,所以我们就用探针点来模拟其数据输入的功能,具体步骤如下:(1 假设.out 文件已经加载,在光标移到main( 函数中dataIO( 函数的调用语句行上,用右键菜单或者工具栏上的Toggle Probe Point命令设置探针点,设置好后,该行语句前面会出现一个蓝色的菱形标识。(2 为探针点建立关联的数据文件:在File 菜单中选择File I/O,出现如图1.6所示的数据文
25、件I/O配置对话框,用Add File按钮选择要关联的数据文件,这里可以选择volume1目录下的sine.dat 文件;在Address 文本框中输入相应的目标系统存储器的起始地址,如果此时已经加载了.out 文件,那么也可以直接输入符号来表示该地址,如_inp_buffer(C 源文件中变量inp_buffer在汇编文件中的引用形式)或者inp_buffer;在Length 文本框中输入数据的长度(如100),设置好后运行程序,当程序运行到探针点处时,会从对应的数据文件中读取100个数据到inp_buffer缓冲区中。 图1.6 数据文件I/O设置对话框(3 在图1.6中单击 Add Pr
26、obe Print按钮,弹出如图1.7所示的对话框,在对话框中可以实现探针点和特定I/O文件的关联。这个过程和断点的设置一样,先在已有探针点窗口中选定需要设置的探针点,接着选择探针点的类型(一般探针点、条件探针点还是硬件探针点)。如果是条件探针,还要输入代表条件的表达式;然后在Connect 中选择刚才在File I/O中设置好的输入文件并单击RePlace ,此后可以从探针点窗口观察到探针点属性的变化,确定后就完成了I/O文件的关联。 图1.7 探针设置对话框(4 完成上述设置工作后,即可运行程序,当程序运行至dataIO 处时,CCS 就会自动从sine.dat 文件中读取100个数据并写
27、入到inp_buffer数组中,从而实现输入功能的模拟。如果在数据文件I/O配置窗口中勾选了Wrap Around功能,则CCS 会自动重复使用该文件中的数据。5. 图形功能简介上文中,利用探针工具和外部数据文件模拟实现了数据的输入,下面在此基础上将通过波形显示的方式来观察输入/输出的结果。(1 在View 菜单项中选Graph ,然后选Timer/Frequency,进入图形属性设置对话框,如图1.8所示。 图1.8 图形属性设置对话框(2 在Graph Title中输入图形窗口的名称:input ,在Start Address中输入数据(用于绘制图形)在存储器中的起始地址。如果此时已经加载
28、.out 文件,则可以直接输入变量符号inp_buffer;在Acqusition Buffer Size和Display Data Size中输入要显示的数据长度100,这里前者表示是数据缓冲区的大小,后者表示用于绘制图形的实际数据大小;最后在DSP Data Type 中选择相应的数据类型,此处我们选16-bit signed integer;其他属性都取默认值,点击确认后自动打开图形显示窗口。重复上述过程,在Graph Title中输入output ,将起始地址改为out_buffer,再打开一个图形显示窗口用来显示输出数据。(3 在主函数中dataIO( 函数调用语句处设置一个断点。(
29、4 连续单击Run 运行程序,程序每次都会在断点处停止,同时在图形显示窗口中显示输入信号的波形,这个信号就是从探针点输入的正弦波形数据,所以将看到一个正弦波。(5 使用Animate 命令运行程序,会看到连续变化的输入/输出波形,如图1.9。另外,还可以通过图形属性设置对话框中的Display Type中选择显示的波形类型,如FFT 幅值图,FFT 相位图等;通过Autoscale 选项来开启或者关闭显示比例的自动调整功能,如果该功能被关闭,还可以设置显示波形的最大、最小值。具体其他功能不在此细述,可参考 CCS 是使用手册。 图1.9 图形显示功能6. 分析工具(Profiler )的使用在
30、CCS 中,还集成了代码分析工具Profiler ,可以用来计算某段代码共执行了多少个机器周期。这样不但能为程序代码的进一步优化提供依据,也可以为程序的实时性提供一个较精确的度量。下面还是以工程volume1为例简单介绍一下这个工具的使用。(1 加载生成的volume1.out 文件,将程序执行到main( 处。(2 选择 Profilerstart New session命令,新建一个分析任务,并为其指定任务名。(3 打开主程序源文件,如图1.10所示,在Processing( 函数定义的首行处选择右键菜单中的Profile Function,将该函数添加到分析窗口中。 图1.10 代码分析
31、工具的使用 (4 运行程序,每次程序停止时(遇到断点、单步执行或者使用Halt 命令)或者运行到探针点时,分析窗口的统计数据就会被刷新。统计数据主要包含三个部分,一是被分析代码的长度(Code Size)以及该段代码已经被执行的次数,比如这里Processing( 函数的代码长度就是33,其执行次数随着运行时间的增加而递增;二是整个被分析的代码区间(包含其中子函数调用的执行情况)中以机器周期数为单位的统计数据,如累计执行时间,最大、最小及平均执行时间等;三是整个被分析的代码区间(不包含其子函数调用的开销)中以机器周期数为单位的统计数据,如累计执行时间,最大、最小及平均执行时间等。Profile
32、r 工具其他更深入的使用方法请参考CCS 的使用手册。第二章 C 语言开发文件说明DSP 的软件可以使用汇编(asm )、C 、C+等语言进行开发。下面将介绍以C 语言开发DSP 过程中的文件说明。2.1 实验例程中的相关文件C 语言开发过程中需要一些包含C281x 寄存器声明和定义的C 头文件、源文件以及库文件。这些头文件(主要是片内各外设寄存器对应的结构体及共用体类型的声明)、DSP281xGlobalVariableDefs.c (寄存器变量的定义)和DSP281x_Headers_nonBIOS.cmd(连接器命令文件)主要用于片内系统及外设寄存器变量的声明、定义和定位,同时一些通用的
33、系统或者外设初始化源代码文件(比如DSP281x_DefaultIsr.c、DSP281x_PieCtrl.c、DSP281x_PieVect.c等)也会在一些程序中用到。一般来说,工程中除了主程序源文件外,还包括如下文件: 前面提到的用于声明寄存器变量结构的头文件(每部分外设或者系统功能寄存器组都对应一个头文件),使用时只要在程序中包含DSP281x_Device.h就能包含其他所有的系统及外设寄存器头文件。注意:所有的头文件都不是手工添加的工程中的,只要在源代码文件中加入头文件包含命令,编译连接时会自动添加这些头文件到工程中。 DSP281x_Headers_nonBIOS.cmd:由于同
34、一片内外设模块中的寄存器地址基本上都是连续的,这样这些寄存器变量就能以外设模块为单位配置到一系列输出段,该文件的作用就是根据各寄存器的实际地址将这些段映射到实际的存储器空间中。 DSP281x_GlobalVariableDefs.c:将所有存储器映射的系统及外设寄存器定义成全局变量(这些变量的数据结构已经在对应的系统及外设头文件中声明过),并将这些变量分配到.cmd 文件中对应的输出段中。 F2812_EzDSP_RAM_lnk.cmd:针对在RAM 中运行的程序而编写的链接器命令文件,可以自己根据存储器的扩展情况重新编写一个。 rts2800_ml.lib:C 语言实时运行库文件。2.2
35、CMD文件下面以 F2812_EzDSP_RAM_Ink.cmd为例,简单介绍一下CMD 文件的组成、基本伪指令的含义和用法:CMD 文件的内容主要分为以下两部分:1. MEMORY以伪指令MEMORY 开始的部分是用来定义目标板上存储器资源的分布,即有哪些存储器可以用,该文件中的这部分内容如下所示: MEMORYPAGE 0 :/* 片内的H0被分割成了PAGE 0和PAGE 1两部分 */* BEGIN 区域在“H0引导”模式下使用 */* 当且仅当从XINTF 区域7中引导时, */* 复位向量加载到RESET 区域中 */* 否则,复位向量从Boot ROM中取得 */RAMM0 :
36、origin = 0x000000, length = 0x000400BEGIN : origin = 0x3F8000, length = 0x000002PRAMH0 : origin = 0x3F8002, length = 0x000FFERESET : origin = 0x3FFFC0, length = 0x000002PAGE 1 :/* 片内的H0被分割成了PAGE 0和PAGE 1两部分 */RAMM1 : origin = 0x000400, length = 0x000400DRAMH0 : origin = 0x3f9000, length = 0x001000其中
37、,PAGE 0代表的是程序存储区,PAGE 1指数据存储区,RAMM0和BEGIN 等都是程序存储器中各个自定义子区域的名称,数据存储区同理。每个子区域内的空间是连续的,后面的参数分别指示其起始地址和长度。区域间可以是离散或者连续(有时为了编程思路的清晰化,对实现不同功能的连续存储区域分别独立取名)。如果某一段物理存储器没有在MEMORY 伪指令后进行配置,则链接器不会将任何程序或者变量定位到那里。2. SECTIONS而以伪指令SECTIONS 开始的部分则用来控制程序文件中代码和数据输出段在存储器区域(必须是在MEMORY 部分定义好的子区域)中的定位,该部分内容如下: SECTIONS.
38、text : PRAMH0, PAGE = 0.cinit : PRAMH0, PAGE = 0.pinit : PRAMH0, PAGE = 0.switch : RAMM0, PAGE = 0.reset : RESET, PAGE = 0, TYPE = DSECT /* not used, */.stack : RAMM1, PAGE = 1.ebss : DRAMH0, PAGE = 1.econst : DRAMH0, PAGE = 1.esysmem : DRAMH0, PAGE = 1这里.text 代表程序中的可执行代码段,后面的指令参数表示此段代码程序将被装载到程序存储器的
39、PRAMH0区域中,而.cinit 段的存储器区域定位将紧接着.text 段后面。同理,以.stack 和.ebbs 为首的指令参数表示的是堆栈和未初始化变量在数据存储器DRAMH0区域中的定位。MEMORY 部分描述的是用户如何给目标存储器进行分类、分区,其描述和定义的对象必须是实际存在的物理存储器;而SECTIONS 部分就是规定目标程序代码、变量将被装载或是定位到存储器的哪个区域,其控制的对象是源代码程序的各个输出段,其定位的范围只能是MEMORY 部分中定义好的存储器区域。注意:从CCS2.20开始才允许向一个工程里添加多个CMD 文件。这里仅仅给出了一个CMD 文件最简单的应用,并介
40、绍了其中最基本和最常用伪指令的用法,如果读者需要进一步了解CMD 文件中的其他伪指令及应用,请参考28x 的汇编语言工具使用手册中有关链接器的章节。2.3 寄存器变量的声明和定义文件下面以通用I/O口数据寄存器变量为例,通过其寄存器变量的声明(.h )和定义文件(.c )简单介绍一下寄存器变量型数据结构的声明、寄存器变量对象的定义、输出段的映射以及寄存器变量成员的访问方法。在DSP281x_Gpio.h中有如下声明: struct GPAMUX_BITS / bits descriptionUint16 PWM1_GPIOA0:1; / 0Uint16 PWM2_GPIOA1:1; / 1Ui
41、nt16 PWM3_GPIOA2:1; / 2Uint16 PWM4_GPIOA3:1; / 3Uint16 PWM5_GPIOA4:1; / 4Uint16 PWM6_GPIOA5:1; / 5Uint16 T1PWM_GPIOA6:1; / 6Uint16 T2PWM_GPIOA7:1; / 7Uint16 CAP1Q1_GPIOA8:1; / 8Uint16 CAP2Q2_GPIOA9:1; / 9Uint16 CAP3QI1_GPIOA10:1; / 10Uint16 TDIRA_GPIOA11:1; / 11Uint16 TCLKINA_GPIOA12:1; / 12Uint16 C
42、1TRIP_GPIOA13:1; / 13Uint16 C2TRIP_GPIOA14:1; / 14Uint16 C3TRIP_GPIOA15:1; / 15;上面的代码声明了一个叫GPADAT_BITS的结构体,这个16位结构体中包含16个二进制位成员,这些成员的名称从低到高各位分别对应GPIOA0GPIOA15。 union GPAMUX_REG Uint16 all;struct GPAMUX_BITS bit;上面的代码声明了一个叫GPADAT_REG的共用体,这个共用体既可以当成一个16位无符号整型数据来用,也可以当成GPADAT_BITS结构体形式的数据。如果需要当成前者来引用,就
43、要使用all 这个成员名,如果是后者,则要用成员名bit 。struct GPIO_DATA_REGS union GPADAT_REG GPADAT;union GPASET_REG GPASET;union GPACLEAR_REG GPACLEAR;union GPATOGGLE_REG GPATOGGLE;union GPBDAT_REG GPBDAT;union GPBSET_REG GPBSET;union GPBCLEAR_REG GPBCLEAR;union GPBTOGGLE_REG GPBTOGGLE;Uint16 rsvd14;union GPDDAT_REG GPDDA
44、T;union GPDSET_REG GPDSET;union GPDCLEAR_REG GPDCLEAR;union GPDTOGGLE_REG GPDTOGGLE;union GPEDAT_REG GPEDAT;union GPESET_REG GPESET;union GPECLEAR_REG GPECLEAR;union GPETOGGLE_REG GPETOGGLE;union GPFDAT_REG GPFDAT;union GPFSET_REG GPFSET;union GPFCLEAR_REG GPFCLEAR;union GPFTOGGLE_REG GPFTOGGLE;unio
45、n GPGDAT_REG GPGDAT;union GPGSET_REG GPGSET;union GPGCLEAR_REG GPGCLEAR;union GPGTOGGLE_REG GPGTOGGLE;Uint16 rsvd24;上面的代码声明了一个叫GPIO_DATA_REGS的结构体,它是根据通用I/O口各数据寄存器的地址分布(总体上讲,他们在存储器空间中是连续分布的),为这整块存储区域声明一个结构体。在这块存储区域中,如果遇到保留区域,就根据其大小将这片保留区域声明成16位无符号整型数组,如上面GPIO_DATA_REGS结构体中的rsvd1数组成员就表示GPBTOGGLE 寄存器后面
46、4个字大小的存储区域是被保留的区域。#ifdef _cplusplus#pragma DATA_SECTION(GpioDataRegsFile#else#pragma DATA_SECTION(GpioDataRegs,GpioDataRegsFile;#endifvolatile struct GPIO_DATA_REGS GpioDataRegs;编译指示符DATA_SECTION的作用是通知编译器将某变量分配到指定的输出段里,上面这段代码的功能就是定义GPIO_DATA_REGS结构体型的变量GpioDataRegs (寄存器组变量),并将GpioDataRegs 变量定位到GpioD
47、ataRegsFile 输出数据段中。注意:此处变量定义时使用的volatile 关键词非常重要,它能够告诉编译器此变量的内容可能会被硬件修改,因此,编译器就不会对其进行优化。如果不使用这个关键词,那么编译器有可能将这个变量优化到CPU 寄存器中,从而导致不可预见的错误。在DSP281x_Headers_nonBIOS.cmd中有如下伪指令代码:MEMORYPAGE 0: /* Program Memory */PAGE 1: /* Data Memory */ 省略GPIODAT : origin = 0x0070E0, length = 0x000020 /* GPIO 数据寄存器 */ / 省略SECTIONS/ 省略GpioDataRegsFile : GPIODAT PAGE = 1/ 省略通过上面cmd 文件中的伪指令,能将数据输出段GpioDataRegsFile 指定到实际的数据存储器区域GPIODAT 里(该区域起始地址为0x0070E0,长度是0x000020)。这样,当在主程序中需要访问GPADAT 寄存器时,就能通过下面的形式直接实现:GpioDataRegs.GPA