DSP-起始篇
数字信号处理(Digital Signal Processing,简称DSP)是一门涉及许多学科而又广泛应用于许多领域的新兴学科。20世纪60年代以来,随着计算机和信息技术的飞速发展,数字信号处理技术应运而生并得到迅速的发展。在过去的二十多年时间里,数字信号处理已经在通信等领域得到极为广泛的应用。
数字信号处理是利用计算机或专用处理设备,以数字形式对信号进行采集、变换、滤波、估值、增强、压缩、识别等处理,以得到符合人们需要的信号形式。
数字信号处理是围绕着数字信号处理的理论、实现和应用等几个方面发展起来的。数字信号处理在理论上的发展推动了数字信号处理应用的发展。反过来,数字信号处理的应用又促进了数字信号处理理论的提高。而数字信号处理的实现则是理论和应用之间的桥梁。
数字信号处理是以众多学科为理论基础的,它所涉及的范围极其广泛。例如,在数学领域,微积分、概率统计、随机过程、数值分析等都是数字信号处理的基本工具,与网络理论、信号与系统、控制论、通信理论、故障诊断等也密切相关。近来新兴的一些学科,如人工智能、模式识别、神经网络等,都与数字信号处理密不可分。可以说,数字信号处理是把许多经典的理论体系作为自己的理论基础,同时又使自己成为一系列新兴学科的理论基础。
世界上第一个单片 DSP 芯片应当是1978年 AMI公司发布的 S2811,1979年美国Intel公司发布的商用可编程器件2920是DSP芯片的一个主要里程碑。这两种芯片内部都没有现代DSP芯片所必须有的单周期乘法器。1980 年,日本 NEC 公司推出的μP D7720是第一个具有乘法器的商用 DSP 芯片。
在这之后,最成功的DSP 芯片当数美国德州仪器公司(Texas Instruments,简称TI)的一系列产品。TI 公司在1982年成功推出其第一代 DSP 芯片 TMS32010及其系列产品TMS32011、TMS320C10/C14/C15/C16/C17等,之后相继推出了第二代DSP芯片TMS32020、TMS320C25/C26/C28,第三代DSP芯片TMS320C30/C31/C32,第四代DSP芯片TMS320C40/C44,第五代 DSP 芯片TMS320C5X/C54X,第二代DSP芯片的改进型TMS320C2XX,集多片DSP芯片于一体的高性能DSP芯片TMS320C8X以及目前速度最快的第六代DSP芯片TMS320C62X/C67X等。TI将常用的DSP芯片归纳为三大系列,即:TMS320C2000系列(包括TMS320C2X/C2XX)、TMS320C5000系列(包括TMS320C5X/C54X/C55X)、TMS320C6000系列(TMS320C62X/C67X)。
如今,TI公司的一系列DSP产品已经成为当今世界上最有影响的DSP芯片。TI公司也成为世界上最大的 DSP 芯片供应商,其DSP市场份额占全世界份额近 50%。
自1980年以来,DSP芯片得到了突飞猛进的发展,DSP芯片的应用越来越广泛。从运算速度来看,MAC(一次乘法和一次加法)时间已经从80年代初的400ns(如TMS32010)降低到40ns(如TMS32C40),处理能力提高了10多倍。DSP芯片内部关键的乘法器部件从1980年的占模区的40左右下降到5以下,片内RAM增加一个数量级以上。从制造工艺来看,1980年采用4μ的N沟道MOS工艺,而现在则普遍采用亚微米CMOS工艺。DSP芯片的引脚数量从1980年的最多64个增加到现在的200个以上,引脚数量的增加,意味着结构灵活性的增加。此外,DSP芯片的发展,是DSP系统的成本、体积、重量和功耗都有很大程度的下降。
DSP芯片的分类
DSP的芯片可以按照以下的三种方式进行分类。
1、按基础特性分
这是根据DSP芯片的工作时钟和指令类型来分类的。如果DSP芯片在某时钟频率范围内的任何频率上能正常工作,除计算速度有变化外,没有性能的下降,这类DSP芯片一般称之为静态DSP芯片。
如果有两种或两种以上的DSP芯片,它们的指令集和相应的机器代码机管脚结构相互兼容,则这类DSP芯片称之为一致性的DSP芯片。
2、按数据格式分
这是根据DSP芯片工作的数据格式来分类的。数据以定点格式工作的DSP芯片称之为定点DSP芯片。以浮点格式工作的称为DSP芯片。不同的浮点DSP芯片所采用的浮点格式不完全一样,有的DSP芯片采用自定义的浮点格式,有的DSP芯片则采用IEEE的标准浮点格式。
3、按用途分
按照DSP芯片的用途来分,可分为通用型DSP芯片和专用型的DSP芯片。通用型DSP芯片适合普通的DSP应用,如TI公司的一系列DSP芯片。专用型DSP芯片市为特定的DSP运算而设计,更适合特殊的运算,如数字滤波,卷积和FFT等。
DSP芯片的选择
设计DSP应用系统,选择DSP芯片时非常重要的一个环节。只有选定了DSP芯片才能进一步设计外围电路集系统的其它电路。总的来说,DSP芯片的选择应根据实际的应用系统需要而确定。一般来说,选择DSP芯片时考虑如下诸多因素。
1. DSP芯片的运算速度。运算速度是DSP芯片的一个最重要的性能指标,也是选择DSP芯片时所需要考虑的一个主要因素。DSP芯片的运算速度可以用以下几种性能指标来衡量:
(1) 指令周期。就是执行一条指令所需要的时间,通常以ns为单位。
(2) MAC时间。即一次乘法加上一次加法的时间。
(3) FFT执行时间。即运行一个N点FFT程序所需的时间。
(4) MIPS。即每秒执行百万条指令。
(5) MOPS。即每秒执行百万次操作。
(6) MFLOPS。即每秒执行百万次浮点操作。
(7) BOPS。即每秒执行十亿次操作。
2. DSP芯片的价格。根据一个价格实际的应用情况,确定一个价格适中的DSP芯片。
3. DSP芯片的硬件资源。
4. DSP芯片的运算速度。
5. DSP芯片的开发工具。
6. DSP 芯片的功耗。
7. 其它的因素,如封装的形式、质量标准、生命周期等。
DSP应用系统的运算量是确定选用处理能力多大的DSP芯片的基础。那么如何确定DSP系统的运算量以选择DSP芯片呢?
1. 按样点处理
按样点处理就是DSP算法对每一个输入样点循环一次。例如;一个采用LMS算法的256抽头德的自适应FIR滤波器,假定每个抽头的计算需要3个MAC周期,则256抽头计算需要256*3=768个MAC周期。如果采样频率为8KHz,即样点之间的间隔为125μs的时间,DSP芯片的MAC周期为200μs,则768个周期需要153.6μs的时间,显然无法实时处理,需要选用速度更快的芯片。
2. 按帧处理
有些数字信号处理算法不是每个输入样点循环一次,而是每隔一定的时间间隔(通常称为帧)循环一次。所以选择DSP芯片应该比较一帧内DSP芯片的处理能力和DSP算法的运算量。假设DSP芯片的指令周期为P(ns),一帧的时间为⊿τ(ns),则该DSP芯片在一帧内所提供的最大运算量为⊿τ/ P 条指令。
DSP芯片的基本结构
DSP芯片的基本结构包括:
(1)哈佛结构;
(2)流水线操作;
(3)专用的硬件乘法器;
(4)特殊的DSP指令;
(5)快速的指令周期。
哈佛结构
哈佛结构的主要特点是将程序和数据存储在不同的存储空间中,即程序存储器和数据存储器是两个相互独立的存储器,每个存储器独立编址,独立访问。与两个存储器相对应的是系统中设置了程序总线和数据总线,从而使数据的吞吐率提高了一倍。由于程序和存储器在两个分开的空间中,因此取指和执行能完全重叠。
流水线与哈佛结构相关,DSP芯片广泛采用流水线以减少指令执行的时间,从而增强了处理器的处理能力。处理器可以并行处理二到四条指令,每条指令处于流水线的不同阶段。
专用的硬件乘法器
乘法速度越快,DSP处理器的性能越高。由于具有专用的应用乘法器,乘法可在一个指令周期内完成。
特殊的DSP指令DSP芯片是采用特殊的指令。
快速的指令周期哈佛结构、流水线操作、专用的硬件乘法器、特殊的DSP指令再加上集成电路的优化设计可使DSP芯片的指令周期在200ns以下。
DSP系统的特点
数字信号处理系统是以数字信号处理为基础,因此具有数字处理的全部特点:
接口方便:
DSP系统与其它以现代数字技术为基础的系统或设备都是相互兼容,这样的系统接口以实现某种功能要比模拟系统与这些系统接口要容易的多。
编程方便:
DSP系统种的可编程DSP芯片可使设计人员在开发过程中灵活方便地对软件进行修改和升级。
稳定性好:
DSP系统以数字处理为基础,受环境温度以及噪声的影响较小,可靠性高。
精度高:
16位数字系统可以达到的精度。
可重复性好:
模拟系统的性能受元器件参数性能变化比较大,而数字系统基本上不受影响,因此数字系统便于测试,调试和大规模生产。
集成方便:
DSP系统中的数字部件有高度的规范性,便于大规模集成。
DSP芯片的应用
自从DSP芯片诞生以来,DSP芯片得到了飞速的发展。DSP芯片高速发展,一方面得益于集成电路的发展,另一方面也得益于巨大的市场。在短短的十多年时间,DSP芯片已经在信号处理、通信、雷达等许多领域得到广泛的应用。目前,DSP芯片的价格也越来越低,性能价格比日益提高,具有巨大的应用潜力。DSP芯片的应用主要有:
(1) 信号处理--如,数字滤波、自适应滤波、快速傅里叶变换、相关运算、频谱分析、卷积等。
(2) 通信--如,调制解调器、自适应均衡、数据加密、数据压缩、回坡抵消、多路复用、传真、扩频通信、纠错编码、波形产生等。
(3) 语音--如语音编码、语音合成、语音识别、语音增强、说话人辨认、说话人确认、语音邮件、语音储存等。
(4) 图像/图形--如二维和三维图形处理、图像压缩与传输、图像增强、动画、机器人视觉等。
(5) 军事--如保密通信、雷达处理、声纳处理、导航等。
(6) 仪器仪表--如频谱分析、函数发生、锁相环、地震处理等。
(7) 自动控制--如引擎控制、深空、自动驾驶、机器人控制、磁盘控制。
(8) 医疗--如助听、超声设备、诊断工具、病人监护等。
(9) 家用电器--如高保真音响、音乐合成、音调控制、玩具与游戏、数字电话/电视等
DSP处理器与通用处理器的比较
1 对密集的乘法运算的支持
GPP不是设计来做密集乘法任务的,即使是一些现代的GPP,也要求多个指令周期来做一次乘法。而DSP处理器使用专门的硬件来实现单周期乘法。DSP处理器还增加了累加器寄存器来处理多个乘积的和。累加器寄存器通常比其他寄存器宽,增加称为结果bits的额外bits来避免溢出。
同时,为了充分体现专门的乘法-累加硬件的好处,几乎所有的DSP的指令集都包含有显式的MAC指令。
2 存储器结构
传统上,GPP使用冯.诺依曼存储器结构。这种结构中,只有一个存储器空间通过一组总线(一个地址总线和一个数据总线)连接到处理器核。通常,做一次乘法会发生4次存储器访问,用掉至少四个指令周期。
大多数DSP采用了哈佛结构,将存储器空间划分成两个,分别存储程序和数据。它们有两组总线连接到处理器核,允许同时对它们进行访问。这种安排将处理器存贮器的带宽加倍,更重要的是同时为处理器核提供数据与指令。在这种布局下,DSP得以实现单周期的MAC指令。
还有一个问题,即现在典型的高性能GPP实际上已包含两个片内高速缓存,一个是数据,一个是指令,它们直接连接到处理器核,以加快运行时的访问速度。从物理上说,这种片内的双存储器和总线的结构几乎与哈佛结构的一样了。然而从逻辑上说,两者还是有重要的区别。
GPP使用控制逻辑来决定哪些数据和指令字存储在片内的高速缓存里,其程序员并不加以指定(也可能根本不知道)。与此相反,DSP使用多个片内存储器和多组总线来保证每个指令周期内存储器的多次访问。在使用DSP时,程序员要明确地控制哪些数据和指令要存储在片内存储器中。程序员在写程序时,必须保证处理器能够有效地使用其双总线。
此外,DSP处理器几乎都不具备数据高速缓存。这是因为DSP的典型数据是数据流。也就是说,DSP处理器对每个数据样本做计算后,就丢弃了,几乎不再重复使用。
3 零开销循环
如果了解到DSP算法的一个共同的特点,即大多数的处理时间是花在执行较小的循环上,也就容易理解,为什么大多数的DSP都有专门的硬件,用于零开销循环。所谓零开销循环是指处理器在执行循环时,不用花时间去检查循环计数器的值、条件转移到循环的顶部、将循环计数器减1。
与此相反,GPP的循环使用软件来实现。某些高性能的GPP使用转移预报硬件,几乎达到与硬件支持的零开销循环同样的效果。
4 定点计算
大多数DSP使用定点计算,而不是使用浮点。虽然DSP的应用必须十分注意数字的精确,用浮点来做应该容易的多,但是对DSP来说,廉价也是非常重要的。定点机器比起相应的浮点机器来要便宜(而且更快)。为了不使用浮点机器而又保证数字的准确,DSP处理器在指令集和硬件方面都支持饱和计算、舍入和移位。
5 专门的寻址方式
DSP处理器往往都支持专门的寻址模式,它们对通常的信号处理操作和算法是很有用的。例如,模块(循环)寻址(对实现数字滤波器延时线很有用)、位倒序寻址(对FFT很有用)。这些非常专门的寻址模式在GPP中是不常使用的,只有用软件来实现。
6 执行时间的预测
大多数的DSP应用(如蜂窝电话和调制解调器)都是严格的实时应用,所有的处理必须在指定的时间内完成。这就要求程序员准确地确定每个样本需要多少处理时间,或者,至少要知道,在最坏的情况下,需要多少时间。
如果打算用低成本的GPP去完成实时信号处理的任务,执行时间的预测大概不会成为什么问题,应为低成本GPP具有相对直接的结构,比较容易预测执行时间。然而,大多数实时DSP应用所要求的处理能力是低成本GPP所不能提供的。
这时候,DSP对高性能GPP的优势在于,即便是使用了高速缓存的DSP,哪些指令会放进去也是由程序员(而不是处理器)来决定的,因此很容易判断指令是从高速缓存还是从存储器中读取。DSP一般不使用动态特性,如转移预测和推理执行等。因此,由一段给定的代码来预测所要求的执行时间是完全直截了当的。从而使程序员得以确定芯片的性能限制。
7 定点DSP指令集
定点DSP指令集是按两个目标来设计的:
使处理器能够在每个指令周期内完成多个操作,从而提高每个指令周期的计算效率。
将存贮DSP程序的存储器空间减到最小(由于存储器对整个系统的成本影响甚大,该问题在对成本敏感的DSP应用中尤为重要)。
为了实现这些目标,DSP处理器的指令集通常都允许程序员在一个指令内说明若干个并行的操作。例如,在一条指令包含了MAC操作,即同时的一个或两个数据移动。在典型的例子里,一条指令就包含了计算FIR滤波器的一节所需要的所有操作。这种高效率付出的代价是,其指令集既不直观,也不容易使用(与GPP的指令集相比)。
GPP的程序通常并不在意处理器的指令集是否容易使用,因为他们一般使用象C或C++等高级语言。而对于DSP的程序员来说,不幸的是主要的DSP应用程序都是用汇编语言写的(至少部分是汇编语言优化的)。这里有两个理由:首先,大多数广泛使用的高级语言,例如C,并不适合于描述典型的DSP算法。其次,DSP结构的复杂性,如多存储器空间、多总线、不规则的指令集、高度专门化的硬件等,使得难于为其编写高效率的编译器。
即便用编译器将C源代码编译成为DSP的汇编代码,优化的任务仍然很重。典型的DSP应用都具有大量计算的要求,并有严格的开销限制,使得程序的优化必不可少(至少是对程序的最关键部分)。因此,考虑选用DSP的一个关键因素是,是否存在足够的能够较好地适应DSP处理器指令集的程序员。
8 开发工具的要求
因为DSP应用要求高度优化的代码,大多数DSP厂商都提供一些开发工具,以帮助程序员完成其优化工作。例如,大多数厂商都提供处理器的仿真工具,以准确地仿真每个指令周期内处理器的活动。无论对于确保实时操作还是代码的优化,这些都是很有用的工具。
GPP厂商通常并不提供这样的工具,主要是因为GPP程序员通常并不需要详细到这一层的信息。GPP缺乏精确到指令周期的仿真工具,是DSP应用开发者所面临的的大问题:由于几乎不可能预测高性能GPP对于给定任务所需要的周期数,从而无法说明如何去改善代码的性能。
微处理器(Microprocessor)的分类
通用处理器(GPP)
采用冯.诺依曼结构,程序和数据的存储空间合二而一
8-bit Apple(6502),NEC PC-8000(Z80)
8086/286/386/486/Pentium/Pentium II/ Pentium III
PowerPc 64-bit CPU(SUN Sparc,DEC Alpha, HP)
CISC 复杂指令计算机, RISC 精简指令计算机
采取各种方法提高计算速度,提高时钟频率,高速总线,多级Cashe,协处理器等
Single Chip Computer/ Micro Controller Unit(MCU)
除开通用CPU所具有的ALU和CU,还有存储器(RAM/ROM)寄存器,时钟,计数器,定时器,串/并口,有的还有A/D,D/A
INTEL MCS/48/51/96(98)
MOTOROLA HCS05/011
DSP
采用哈佛结构,程序和数据分开存储
采用一系列措施保证数字信号的处理速度,如对FFT的专门优化
MCU与DSP的简单比较
MCU DSP
低档 高档 低档 高档
指令周期(ns) 600 40 50 5
乘加时间(ns) 1900 80 50 5
US$/MIPS 1.5 0.5 0.15 0.1
飞速发展的数字信号处理器
由于超大规模集成电路技术的迅猛发展,过去二十年中,数字信号处理技术,即DSP(Digital Signal Processor)技术也得到了突飞猛进的发展,这种发展趋势在今后十年内仍将保持下去。据世界半导体贸易统计组织发布的统计与预测报告,2001~2006年可编程DSP市场的预期增长率为27.2%。预期2006年DSP市场将达到141.9亿美元,且增长率是逐年递增的,2005年的增长率预期为34%。到2010年,DSP芯片的集成度将会提高11倍,单个芯片上将会集成5亿只晶体管。目前DSP的生产工艺正在由0.35μm转向0.25μm、0.18μm、0.13μm,到2005年可能达到0.075μm。
集成度的提高使得硅片的面积进一步缩小,从而导致DSP芯片成本降低,价格下降。价格下降促使需求的上升和应用领域的扩展。DSP已从军用转向民用,在计算机、通信、消费类电子产品方面即所谓3C领域得到了广泛的应用。DSP在通信领域应用最多,占72%,计算机占3%,消费类、办公自动化各占2%,从趋势上看,工业(特别是变频电机控制)中的应用,以及消费类产品中应用的份额会有所上升。
在通信领域,DSP产品涵盖了从3G无线基站到无线局域网的广泛应用,数字化电视也离不开DSP。DSP在语言处理中的应用也是尽人皆知的,包括语言的压缩与解压,语言的合成,语言的识别等。
计算机的硬盘驱动器在使用DSP技术以后可大大提高存取速度,提高容量和缩小体积,以至于今后有可能用于掌上电脑。在PC机中,DSP可加速图形处理功能。以后的PC机,可能每台PC中含有不只一颗DSP芯片。在计算机外设中,激光打印机、扫描仪、光盘机等需要大量数据传输的设备,都有可能用到DSP技术。
DSP技术发展的另一趋势是速度更快,功耗更低,DSP片外的速度能达到几十兆赫已经近于极限,为了降低系统的噪声,提高系统抗干扰能力,片外时钟有进一步降低的趋势,即外部使用几兆赫的振荡器就够了,而片内则用压控振荡器加锁相环的技术,把片内时钟速度提高到100MHz、200MHz乃至更高,会有更多的DSP片内时钟达到1GHz。预期到2010年,同类水平的DSP的功耗将降到原来的1/3。
DSP与CPU
如果用普通计算机中的CPU来处理算法,做乘法和加法都要调用相应的乘法、加法函数,如果是浮点数运算,通常CPU需要将浮点运算交给协处理处理,虽然协处理器的浮点运算速度可能很快,但加上CPU将输入参数传出,再将运算结果取回的时间,会显得速度很慢;做循环时,要有循环变量,每次循环变量加1后再判断是否已经循环了n次,这一过程是比较慢的。
而DSP则在硬件设计上针对这类计算采取了一些独特的设计,以求最快的运算速度,以至于趋于模拟电路的延迟时间。
DSP能在一个时钟周期内完成乘法和加法运算,并能并行地同时将下面运算要用到的两个参数传入相应的运算用寄存器。在乘法及乘加指令的执行方式上,DSP的小数乘法在算法上分定点算法DSP与浮点算法DSP。在定点类DSP中,小数点的位置是固定的,不论定点的DSP还是浮点的DSP,乘法器都是用硬件逻辑完成的,乘法可以在一个指令周期内完成。
在循环方面,DSP有诸如重复n次(Repeat n),或循环n次(DO Loop n)等指令,使DSP能迅速完成n次循环,而不必每次都检查是不是已经循环n次了。这就是DSP在做数字信号处理方面的优势与独到之处。也是DSP区别于CPU的地方。
DSP与CPU在结构方面的另一区别是,DSP往往采用哈佛结构,而传统的CPU多为冯.诺曼结构(Von Neuman)。冯.诺曼结构指的是将程序与数据统一编址,不区分存储器的程序空间和数据空间。而哈佛结构指将程序空间与数据空间分开编址,这样在DSP处理数据空间运算与数据传输的同时可以并行地从程序空间读取下一条指令。采用哈佛结构,将程序空间与数据空间分开编址的好处是速度快,读程序和读写数据可以同时进行。
DSP在内核设计方面还有一个特点是采用多重流水线结构,流水线结构的层次深度可以从3级到6级。程序的执行过程大致可分为读指令、指令译码、指令执行等几个阶段。DSP在第一个时钟周期内读第一条指令,在第二个周期译码第一条指令同时在第二个周期内读入第二条指令,在第三个时钟周期内执行第一条指令,译码第二条指令,同时读入第三条指令,这样虽然执行一条指令仍需要三个周期,可是由于并行的流水线处理,看起来好像每条指令都是在一个周期内完成的,这就是流水线结构。
DSP的特点
DSP在体系结构上与通用微处理器有很大的区别。下面是几个关键的不同点:
单周期指令:大多数DSP都拥有流水结构,它可以在一个时钟周期内执行一条语句。
快速乘法器:信号处理算法往往大量用到乘加(multiply-accumulate,MAC)运算。DSP有专用的硬件乘法器,它可以在一个时钟周期内完成MAC运算。硬件乘法器占用了DSP芯片面积的很大一部分。(与之相反,通用微处理器采用一种较慢的、迭代的乘法技术,它可以在多个时钟周期内完成一次乘法运算,但是占用了较少了硅片资源)。
多总线:DSP有分开的代码和数据总线(一般用术语“哈佛结构”表示),这样在同一个时钟周期内可以进行多次存储器访问——这是因为数据总线也往往有好几组。有了这种体系结构,DSP就可以在单个时钟周期内取出一条指令和一个或者两个(或者更多)的操作数。
地址发生器:DSP有专用的硬件地址发生单元,这样它可以支持许多信号处理算法所要求的特定数据地址模式。这包括前(后)增(减)、环状数据缓冲的模地址以及FFT的比特倒置地址。地址发生器单元与主ALU和乘法器并行工作,这就进一步增加了DSP可以在一个时钟周期内可以完成的工作量。
硬件辅助循环:信号处理算法常常需要执行紧密的指令循环。对硬件辅助循环的支持,可以让DSP高效的循环执行代码块而无需让流水线停转或者让软件来测试循环终止条件。
数据格式:除了标准的整数型格式外,DSP一般支持定点和(或)浮点数。对数据格式和精度的选择取决于应用程序所需,例如:
16位定点DSP可以满足语音信号处理和控制所需
24位和32位定点DSP可以满足高质量音频信号处理所需
32位浮点DSP可以满足图形和图像处理所需
DSP的特点:
DSP处理器采用哈佛结构和改进的哈佛结构。
哈佛结构就是将程序代码和数据的存储空间分开,各有自己的地址和数据总线。之所以采用哈佛结构,是为了并行进行指令和数据处理,从而可以大大地提高运算的速度。为了进一步提高信号处理的效率,在哈佛结构的基础上,又加以改善。使得程序代码和数据存储空间之间可以进行数据的传输,称为改善的哈佛结构。
采用流水技术。
流水技术是将各指令的各个步骤重叠起来执行。DSP处理器所采用的将程序存储空和数据存储空间的地址与数据总线分开的哈佛结构,为采用流水技术提供了很大的方便。
为了提高DSP处理器的运算速度,它们无例外地设置了硬件乘法器,以及MAC(乘并且累加)一类的指令。
DSP处理器都为DMA单独设置了完全独立的总线和控制器,这是和通用的CPU很不相同,其目的是在进行数据传输是完全不影响CPU及其相关总线的工作。
在DSP处理器中,设置了专门的数据地址发生器来产生所需的数据地址。数据地址的产生与CPU的工作是并行的,从而节省CPU的时间,提高信号的处理速度。
DSP处理器为了自身工作的需要和外部环境的协调工作。往往都设置了丰富的外设。如时钟发生器。定时器等。
定点DSP处理器和浮点DSP处理器。定点DSP中经常要考虑溢出问题,在浮点DSP基本上可以不考虑。与定点DSP处理器相比,浮点DSP处理器的速度更快,尤其是作浮点运算。在实时性要求很到的场合。往往考虑浮点DSP处理器。而浮点DSP处理器的价格比较高,开发难度更大。
为什么CCS需要安装Driver?
CCS是开放的软件平台,它可以支持不同的硬件接口,因此不同的硬件接口必须通过标准的Driver同CCS连接。
Driver安装的常见问题?
请认真阅读“安装手册”和Driver盘中的Readme。 1)对于SEED-XDS,安装Readme中的步骤,将I/O口设为240/280/320/340。 2)对于SEED-XDSPP,安装Readme中的步骤,将I/O口设为378或278。3)对于SEED-XDSUSB,必须连接目标板,安装Readme中的步骤,将I/O口设为A,USB连接后,主机将自动激活相应的Driver。 4)对于SEED-XDSPCI,安装Readme中的步骤,将I/O口设为240,PCI接口板插入主机后,主机将自动激活相应的Driver。 5)对于Simulator,需要选择不同的CFG文件,以模拟不同的DSP。 6)对于C5402 DSK,将I/O口设为请认真阅读“安装手册”和Driver盘中的Readme。 1)对于SEED-XDS,安装Readme中的步骤,将I/O口设为240/280/320/340。 2)对于SEED-XDSPP,安装Readme中的步骤,将I/O口设为378或278。注意主机BIOS中并口的型式必须同xds510pp.ini中一致。 3)对于SEED-XDSUSB,必须连接目标板,安装Readme中的步骤,将I/O口设为240/280/320/340,USB连接后,主机将自动激活相应的Driver。 4)对于SEED-XDSPCI,安装Readme中的步骤,将I/O口设为240/280/320/340,PCI接口板插入主机后,主机将自动激活相应的Driver。 5)对于Simulator,需要选择不同的CFG文件,以模拟不同的DSP。 6)对于C5402 DSK,将I/O口设为378或278。 7)对于C6211/6711 DSK,将I/O口设为378或278。 8)对于C6201/C6701 EVM,将I/O口设为0。
Link的cmd文件的作用是什么?
Link的cmd文件用于DSP代码的定位。由于DSP的编译器的编译结果是未定位的,DSP没有操作系统来定位执行代码,每个客户设计的DSP系统的配置也不尽相同,因此需要用户自己定义代码的安装位置。以C5000为例,基本格式为:
-o sample.out
-m sample.map
-stack 100
sample.obj meminit.obj
-l rts.lib
MEMORY {
PAGE 0: VECT: origin = 0xff80, length 0x80
PAGE 0: PROG: origin = 0x2000, length 0x400
PAGE 1: DATA: origin = 0x800, length 0x400
}
SECTIONS {
.vectors : {} >PROG PAGE 0
.text : {} >PROG PAGE 0
.data : {} >PROG PAGE 0
.cinit : {} >PROG PAGE 0
.bss : {} >DATA PAGE 1
}
如何将OUT文件转换为16进制的文件格式?
DSP的开发软件集成了一个程序,可以从执行文件OUT转换到编程器可以接受的格式,使得编程器可以用次文件烧写EPROM或Flash。对于C2000的程序为DSPHEX;对于C3x程序为HEX30;对于C54x程序为HEX500;对于C55x程序为HEX55;对于C6x程序为Hex6x。以C32为例,基本格式为:
sample.out
-x
-memwidth 8
-bootorg 900000h
-iostrb 0h
-strb0 03f0000h
-strb1 01f0000h
-o sample.hex
ROMS {
EPROM: org = 0x900000,len=0x02000,romwidth=8
}
SECTIONS {
.text: paddr="boot"
.data: paddr="boot"
}
DSP的C语言同主机C语言的主要区别?
1)DSP的C语言是标准的ANSI C,它不包括同外设联系的扩展部分,如屏幕绘图等。但在CCS中,为了方便调试,可以将数据通过prinf命令虚拟输出到主机的屏幕上。 2)DSP的C语言的编译过程为,C编译为ASM,再由ASM编译为OBJ。因此C和ASM的对应关系非常明确,非常便于人工优化。 3)DSP的代码需要绝对定位;主机的C的代码有操作系统定位。 4)DSP的C的效率较高,非常适合于嵌入系统。
为什么在CCS下编译工具工作不正常?
在CCS下有部分客户会碰到编译工具工作不正常,常见错误为: 1)autoexec.bat的路径“out of memory”。修改autoexec.bat,清除无用的PATH路径。 2)编译的输出文件(OUT文件)写保护,无法覆盖。删除或修改输出文件的属性。 3)Windows有问题。重新安装windows。 4)Windows下有程序对CCS有影响。建议用一“干净”的计算机。
在CCS下,如何选择有效的存储器空间?
CCS下的存储器空间最好设置同你的硬件,没有的存储器不要有效。这样便于调试,CCS会发现你调入程序时或程序运行时,是否访问了无效地址。 1)在GEL文件中设置。参见CCS中的示例。 2)在Option菜单下,选择Memory Map选项,根据你的硬件设置。注意一定要将Enable Memory Mapping置为使能。
在CCS下,OUT文件加载时提示“Data verification failed...”的原因?
Link的CMD文件分配的地址同GEL或设置的有效地址空间不符。中断向量定位处或其它代码、数据段定位处,没有RAM,无法加载OUT文件。解决方法: 1)调整Link的CMD文件,使得定位段处有RAM。 2)调整存储器设置,使得RAM区有效。
为什么要使用BIOS?
1)BIOS是Basic I/O System的简称,是基本的输入、输出管理。 2)用于管理任务的调度,程序实时分析,中断管理,跟踪管理和实时数据交换。 3)BIOS是基本的实时系统,使用BIOS可以方便地实现多任务、多进程的时间管理。 4)BIOS是eXpress DSP的标准平台,要使用eXpress DSP技术,必须使用BIOS。
DSP发展动态
1.TMS320C2000 TMS320C2000系列包括C24x和C28x系列。C24x系列建议使用LF24xx系列替代C24x系列,LF24xx系列的价格比C24x便宜,性能高于C24x,而且LF24xxA具有加密功能。 C28x系列主要用于大存储设备管理,高性能的控制场合。
2.TMS320C3x TMS320C3x系列包括C3x和VC33,主要推荐使用VC33。C3x系列是TI浮点DSP的基础,不可能停产,但价格不会进一步下调。
3.TMS320C5x TMS320C5x系列已不推荐使用,建议使用C24x或C5000系列替代。
4.TMS320C5000 TMS320C5000系列包括C54x和C55x系列。 其中VC54xx还不断有新的器件出现,如:TMS320VC5471(DSP+ARM7)。 C55x系列是TI的第三代DSP,功耗为VC54xx的1/6,性能为VC54xx的5倍,是一个正在发展的系列。 C5000系列是目前TI DSP的主流DSP,它涵盖了从低档到中高档的应用领域,目前也是用户最多的系列。
5.TMS320C6000 TMS320C6000系列包括C62xx、C67xx和C64xx。此系列是TI的高档DSP系列。 其中C62xx系列是定点的DSP,系列芯片种类较丰富,是主要的应用系列。 C67xx系列是浮点的DSP,用于需要高速浮点处理的领域。 C64xx系列是新发展,性能是C62xx的10倍。
6.OMAP系列 是TI专门用于多媒体领域的芯片,它是C55+ARM9,性能卓越,非常适合于手持设备、Internet终端等多媒体应用。
5V/3.3V如何混接?
TI DSP的发展同集成电路的发展一样,新的DSP都是3.3V的,但目前还有许多外围电路是5V的,因此在DSP系统中,经常有5V和3.3V的DSP混接问题。在这些系统中,应注意: 1)DSP输出给5V的电路(如D/A),无需加任何缓冲电路,可以直接连接。 2)DSP输入5V的信号(如A/D),由于输入信号的电压>4V,超过了DSP的电源电压,DSP的外部信号没有保护电路,需要加缓冲,如74LVC245等,将5V信号变换成3.3V的信号。 3)仿真器的JTAG口的信号也必须为3.3V,否则有可能损坏DSP。
为什么要片内RAM大的DSP效率高?
目前DSP发展的片内存储器RAM越来越大,要设计高效的DSP系统,就应该选择片内RAM较大的DSP。片内RAM同片外存储器相比,有以下优点: 1)片内RAM的速度较快,可以保证DSP无等待运行。 2)对于C2000/C3x/C5000系列,部分片内存储器可以在一个指令周期内访问两次,使得指令可以更加高效。 3)片内RAM运行稳定,不受外部的干扰影响,也不会干扰外部。 4)DSP片内多总线,在访问片内RAM时,不会影响其它总线的访问,效率较高。
为什么DSP从5V发展成3.3V?
超大规模集成电路的发展从1um,发展到目前的0.1um,芯片的电源电压也随之降低,功耗也随之降低。DSP也同样从5V发展到目前的3.3V,核心电压发展到1V。目前主流的DSP的外围均已发展为3.3V,5V的DSP的价格和功耗都价格,以逐渐被3.3V的DSP取代。
如何选择DSP的电源芯片?
TMS320LF24xx:TPS7333QD,5V变3.3V,最大500mA。
TMS320VC33: TPS73HD318PWP,5V变3.3V和1.8V,最大750mA。
TMS320VC54xx:TPS73HD318PWP,5V变3.3V和1.8V,最大750mA; TPS73HD301PWP,5V变3.3V和可调,最大750mA。
TMS320VC55xx:TPS73HD301PWP,5V变3.3V和可调,最大750mA。
TMS320C6000: PT6931,TPS56000,最大3A。
软件等待的如何使用?
DSP的指令周期较快,访问慢速存储器或外设时需加入等待。等待分硬件等待和软件等待,每一个系列的等待不完全相同。
1)对于C2000系列: 硬件等待信号为READY,高电平时不等待。 软件等待由WSGR寄存器决定,可以加入最多7个等待。其中程序存储器和数据存储器及I/O可以分别设置。
2)对于C3x系列: 硬件等待信号为/RDY,低电平是不等待。 软件等待由总线控制寄存器中的SWW和WTCNY决定,可以加入最多7个等待,但等待是不分段的,除了片内之外全空间有效。
3)对于C5000系列: 硬件等待信号为READY,高电平时不等待。 软件等待由SWWCR和SWWSR寄存器决定,可以加入最多14个等待。其中程序存储器、控制程序存储器和数据存储器及I/O可以分别设置。
4)对于C6000系列(只限于非同步存储器或外设): 硬件等待信号为ARDY,高电平时不等待。 软件等待由外部存储器接口控制寄存器决定,总线访问外部存储器或设备的时序可以设置,可以方便的同异步的存储器或外设接口。
中断向量为什么要重定位?
为了方便DSP存储器的配置,一般DSP的中断向量可以重新定位,即可以通过设置寄存器放在存储器空间的任何地方。 注意:C2000的中断向量不能重定位。
DSP的最高主频能从芯片型号中获得吗?
TI的DSP最高主频可以从芯片的型号中获得,但每一个系列不一定相同。
1)TMS320C2000系列:
TMS320F206-最高主频20MHz。
TMS320C203/C206-最高主频40MHz。
TMS320F24x-最高主频20MHz。
TMS320LF24xx-最高主频30MHz。
TMS320LF24xxA-最高主频40MHz。
TMS320LF28xx-最高主频150MHz。
2)TMS320C3x系列:
TMS320C30:最高主频25MHz。
TMS320C31PQL80:最高主频40MHz。
TMS320C32PCM60:最高主频30MHz。
TMS320VC33PGE150:最高主频75MHz。
3)TMS320C5000系列:
TMS320VC54xx:最高主频160MHz。
TMS320VC55xx:最高主频300MHz。
4)TMS320C6000系列:
TMS320C62xx:最高主频300MHz。
TMS320C67xx:最高主频230MHz。
TMS320C64xx:最高主频720MHz。
DSP可以降频使用吗?
可以,DSP的主频均有一定的工作范围,因此DSP均可以降频使用。
如何选择外部时钟?
DSP的内部指令周期较高,外部晶振的主频不够,因此DSP大多数片内均有PLL。但每个系列不尽相同。
1)TMS320C2000系列:
TMS320C20x:PLL可以÷2,×1,×2和×4,因此外部时钟可以为5MHz-40MHz。
TMS320F240:PLL可以÷2,×1,×1.5,×2,×2.5,×3,×4,×4.5,×5和×9,因此外部时钟可以为2.22MHz-40MHz。
TMS320F241/C242/F243:PLL可以×4,因此外部时钟为5MHz。 TMS320LF24xx:PLL可以由RC调节,因此外部时钟为4MHz-20MHz。
TMS320LF24xxA:PLL可以由RC调节,因此外部时钟为4MHz-20MHz。
2)TMS320C3x系列:
TMS320C3x:没有PLL,因此外部主频为工作频率的2倍。
TMS320VC33:PLL可以÷2,×1,×5,因此外部主频可以为12MHz-100MHz。
3)TMS320C5000系列:
TMS320VC54xx:PLL可以÷4,÷2,×1-32,因此外部主频可以为0.625MHz-50MHz。
TMS320VC55xx:PLL可以÷4,÷2,×1-32,因此外部主频可以为6.25MHz-300MHz。
4)TMS320C6000系列:
TMS320C62xx:PLL可以×1,×4,×6,×7,×8,×9,×10和×11,因此外部主频可以为11.8MHz-300MHz。
TMS320C67xx:PLL可以×1和×4,因此外部主频可以为12.5MHz-230MHz。
TMS320C64xx:PLL可以×1,×6和×12,因此外部主频可以为30MHz-720MHz
如何选择DSP的外部存储器?
DSP的速度较快,为了保证DSP的运行速度,外部存储器需要具有一定的速度,否则DSP访问外部存储器时需要加入等待周期。
1)对于C2000系列: C2000系列只能同异步的存储器直接相接。 C2000系列的DSP目前的最高速度为150MHz。建议可以用的存储器有:
CY7C199-15:32K×8,15ns,5V;
CY7C1021-12:64K×16,15ns,5V; CY7C1021V33-12:64K×16,15ns,3.3V。
2)对于C3x系列: C3x系列只能同异步的存储器直接相接。 C3x系列的DSP的最高速度,5V的为40MHz,3.3V的为75MHz,为保证DSP无等待运行,分别需要外部存储器的速度<25ns和<12ns。建议可以用的存储器有:
ROM: AM29F400-70:256K×16,70ns,5V,加入一个等待;
AM29LV400-55(SST39VF400):256K×16,55ns,3.3V,加入两个等待(目前没有更快的Flash)。
SRAM: CY7C199-15:32K×8,15ns,5V;
CY7C1021-15:64K×16,15ns,5V;
CY7C1009-15:128K×8,15ns,5V;
CY7C1049-15:512K×8,15ns,5V;
CY7C1021V33-15:64K×16,15ns,3.3V;
CY7C1009V33-15:128K×8,15ns,3.3V;
CY7C1041V33-15:256k×16,15ns,3.3V。
3)对于C54x系列: C54x系列只能同异步的存储器直接相接。 C54x系列的DSP的速度为100MHz或160MHz,为保证DSP无等待运行,需要外部存储器的速度<10ns或<6ns。建议可以用的存储器有:
ROM: AM29LV400-55(SST39VF400):256K×16,55ns,3.3V,加入5或9个等待(目前没有更快的Flash)。
SRAM: CY7C1021V33-12:64K×16,12ns,3.3V,加入一个等待;
CY7C1009V33-12:128K×8,12ns,3.3V,加入一个等待。
4)对于C55x和C6000系列: TI的DSP中只有C55x和C6000可以同同步的存储器相连,同步存储器可以保证系统的数据交换效率更高。
ROM: AM29LV400-55(SST39VF400):256K×16,55ns,3.3V。
SDRAM: HY57V651620BTC-10S:64M,10ns。
SBSRAM: CY7C1329-133AC,64k×32;
CY7C1339-133AC,128k×32。
FIFO:CY7C42x5V-10ASC,32k/64k×18。
DSP芯片有多大的驱动能力?
DSP的驱动能力较强,可以不加驱动,连接8个以上标准TTL门。
调试TMS320C2000系列的常见问题?
1)单步可以运行,连续运行时总回0地址: Watchdog没有关,连续运行复位DSP回到0地址。
2)OUT文件不能load到片内flash中: Flash不是RAM,不能用简单的写指令写入,需要专门的程序写入。CCS和C Source Debugger中的load命令,不能对flash写入。 OUT文件只能load到片内RAM,或片外RAM中。
3)在flash中如何加入断点: 在flash中可以用单步调试,也可以用硬件断点的方法在flash中加入断点,软件断点是不能加在ROM中的。硬件断点,设置存储器的地址,当访问该地址时产生中断。
4)中断向量: C2000的中断向量不可重定位,因此中断向量必须放在0地址开始的flash内。在调试系统时,代码放在RAM中,中断向量也必须放在flash内。
调试TMS320C3x系列的常见问题?
1)TMS320C32的存储器配置: TMS320C32的程序存储器可以配置为16位或32位;数据存储器可以配置为8位、16位或32位。
2)TMS320VC33的PLL控制: TMS320VC33的PLL控制端只能接1.8V,不能接3.3V或5V。
如何调试多片DSP?
对于有MPSD仿真口的DSP(TMS320C30/C31/C32),不能用一套仿真器同时调试,每次只能调试其中的一个DSP; 对于有JTAG仿真口的DSP,可以将JTAG串接在一起,用一套仿真器同时调试多个DSP,每个DSP可以用不同的名字,在不同的窗口中调试。 注意:如果在JTAG和DSP间加入驱动,一定要用快速的门电路,不能使用如LS的慢速门电路。
在DSP系统中为什么要使用CPLD?
DSP的速度较快,要求译码的速度也必须较快。利用小规模逻辑器件译码的方式,已不能满足DSP系统的要求。 同时,DSP系统中也经常需要外部快速部件的配合,这些部件往往是专门的电路,有可编程器件实现。 CPLD的时序严格,速度较快,可编程性好,非常适合于实现译码和专门电路。
DSP系统构成的常用芯片有哪些?
1)电源: TPS73HD3xx,TPS7333,TPS56100,PT64xx...
2)Flash: AM29F400,AM29LV400,SST39VF400...
3)SRAM: CY7C1021,CY7C1009,CY7C1049...
4)FIFO: CY7C425,CY7C42x5...
5)Dual port: CY7C136,CY7C133,CY7C1342...
6)SBSRAM: CY7C1329,CY7C1339...
7)SDRAM: HY57V651620BTC...
8)CPLD: CY37000系列,CY38000系列,CY39000系列...
9)PCI: PCI2040,CY7C09449...
10)USB: AN21xx,CY7C68xxx...
11)Codec:TLV320AIC23,TLV320AIC10...
12)A/D,D/A:ADS7805,TLV2543...
具体资料见www.ti.com,www.cypress.com
什么是boot loader?
DSP的速度尽快,EPROM或flash的速度较慢,而DSP片内的RAM很快,片外的RAM也较快。为了使DSP充分发挥它的能力,必须将程序代码放在RAM中运行。为了方便的将代码从ROM中搬到RAM中,在不带flash的DSP中,TI在出厂时固化了一段程序,在上电后完成从ROM或外设将代码搬到用户指定的RAM中。此段程序称为“boot loader”。
TMS320C3x如何boot?
在MC/MP管脚为高时,C3x进入boot状态。C3x的boot loader在reset时,判断外部中断管脚的电平。根据中断配置决定boot的方式为存储器加载还是串口加载,其中ROM的地址可以为三个中的一个,ROM可以为8位。
Boot有问题如何解决?
1)仔细检查boot的控制字是否正确。 2)仔细检查外部管脚设置是否正确。 3)仔细检查hex文件是否转换正确。 4)用仿真器跟踪boot过程,分析错误原因。
DSP为什么要初始化?
DSP在RESET后,许多的寄存器的初值一般同用户的要求不一致,例如:等待寄存器,SP,中断定位寄存器等,需要通过初始化程序设置为用户要求的数值。 初始化程序的主要作用: 1)设置寄存器初值。 2)建立中断向量表。 3)外围部件初始化。
DSP有哪些数学库及其它应用软件?
TI公司为了方便客户开发DSP,在它的网站上提供了许多程序的示例和应用程序,如MATH库,FFT,FIR/IIR等,可以在TI的网页免费下载。
如何获得DSP专用算法?
TI有许多的Third Party可以通过DSP上的多种算法软件。可以通过TI的网页搜索你所需的算法,找到通过算法的公司,同相应的公司联系。注意这些算法都是要付费的。
eXpressDSP是什么?
eXpressDSP是一种实时DSP软件技术,它是一种DSP编程的标准,利用它可以加快你开发DSP软件的速度。 以往DSP软件的开发没有任何标准,不同的人写的程序一般无法连接在一起。DSP软件的调试工具也非常不方便。使得DSP软件的开发往往滞后于硬件的开发。 eXpressDSP集成了CCS(Code Composer Studio)开发平台,DSP BIOS实时软件平台,DSP算法标准和第三方支持四部分。利用该技术,可以使你的软件调试,软件进程管理,软件的互通及算法的获得,都便的容易。这样就可以加快你的软件开发进程。
1)CCS是eXpressDSP的基础,因此你必须首先拥有CCS软件。
2)DSP BIOS是eXpressDSP的基本平台,你必须学会所有DSP BIOS。
3)DSP算法标准可以保证你的程序可以方便的同其它利用eXpressDSP技术的程序连接在一起。同时也保证你的程序的延续性。
为什么要用DSP?
3G技术和internate的发展,要求处理器的速度越来越高,体积越来越小,DSP的发展正好能满足这一发展的要求。因为,传统的其它处理器都有不同的缺陷。MCU的速度较慢;CPU体积较大,功耗较高;嵌入CPU的成本较高。 DSP的发展,使得在许多速度要求较高,算法较复杂的场合,取代MCU或其它处理器,而成本有可能更低。
如何选择DSP?
选择DSP可以根据以下几方面决定:
1)速度: DSP速度一般用MIPS或FLOPS表示,即百万次/秒钟。根据您对处理速度的要求选择适合的器件。一般选择处理速度不要过高,速度高的DSP,系统实现也较困难。
2)精度: DSP芯片分为定点、浮点处理器,对于运算精度要求很高的处理,可选择浮点处理器。定点处理器也可完成浮点运算,但精度和速度会有影响。
3)寻址空间: 不同系列DSP程序、数据、I/O空间大小不一,与普通MCU不同,DSP在一个指令周期内能完成多个操作,所以DSP的指令效率很高,程序空间一般不会有问题,关键是数据空间是否满足。数据空间的大小可以通过DMA的帮助,借助程序空间扩大。
4)成本: 一般定点DSP的成本会比浮点DSP的要低,速度也较快。要获得低成本的DSP系统,尽量用定点算法,用定点DSP。
5)实现方便: 浮点DSP的结构实现DSP系统较容易,不用考虑寻址空间的问题,指令对C语言支持的效率也较高。
6)内部部件:根据应用要求,选择具有特殊部件的DSP。如:C2000适合于电机控制;OMAP适合于多媒体等。
要了解DSP芯片的性能,本网中的"DSP及相关器件"中有介绍。
DSP同MCU相比的特点?
1)DSP的速度比MCU快,主频较高。
2)DSP适合于数据处理,数据处理的指令效率较高。
3)DSP均为16位以上的处理器,不适合于低档的场合。
4)DSP可以同时处理的事件较多,系统级成本有可能较低。
5)DSP的灵活性较好,大多数算法都可以软件实现。
6)DSP的集成度较高,可靠性较好。
DSP同嵌入CPU相比的特点?
1)DSP是单片机,构成系统简单。 2)DSP的速度快。 3)DSP的成本较低。 4)DSP的性能高,可以处理较多的任务。
如何编写C2000片内Flash?
DSP中的Flash的编写方法有三中:
1.通过仿真器编写:在我们的网页上有相关的软件,在销售仿真器时我们也提供相关软件。其中LF240x的编写可以在CCS中加入一个插件,F24x的编写需要在windows98下的DOS窗中进行。具体步骤见软件中的readme。有几点需要注意: a.必须为MC方式; b.F206的工作频率必须为20MHz; c.F240需要根据PLL修改C240_CFG.I文件。建议外部时钟为20MHz。 d.LF240x也需要根据PLL修改文件。 d.如果编写有问题,可以用BFLWx.BAT修复。
2.提供串口编写:TI的网页上有相关软件。注意只能编写一次,因为编写程序会破坏串口通信程序。
3.在你的程序中编写:TI的网页上有相关资料。
如何编写DSP外部的Flash?
DSP的外部Flash编写方法:
1.通过编程器编写:将OUT文件通过HEX转换程序转换为编程器可以接受的格式,再由编程器编写。
2.通过DSP软件编写:您需要根据Flash的说明,编写Flash的编写程序,将应用程序和编写Flash的程序分别load到RAM中,运行编写程序编写。
对于C5000,大于48K的程序如何BOOT?
对于C5000,片内的BOOT程序在上电后将数据区的内容,搬移到程序区的RAM中,因此FLASH必须在RESET后放在数据区。由于C5000,数据区的空间有限,一次BOOT的程序不能对于48K。解决的方法如下:
1.在RESET后,将FLASH译码在数据区,RAM放在程序区,片内BOOT程序将程序BOOT到RAM中。
2.用户初试化程序发出一个I/O命令(如XF),将FLASH译码到程序区的高地址。开放数据区用于其它的RAM。
3.用户初试化程序中包括第二次BOOT程序(此程序必须用户自己编写),将FLASH中没有BOOT的其它代码搬移到RAM中。
4.开始运行用户处理程序。
DSP外接存储器的控制方式
对于一般的存储器具有RD、WR和CS等控制信号,许多DSP(C3x、C5000)都没有控制信号直接连接存储器,一般采用的方式如下:
1.CS有地址线和PS、DS或STRB译码产生;
2./RD=/STRB+/R/W; 3./WR=/STRB+R/W。
GEL文件的功能?
GEL文件的功能同emuinit.cmd的功能基本相同,用于初始化DSP。但它的功能比emuinit的功能有所增强,GEL在CCS下有一个菜单,可以根据DSP的对象不同,设置不同的初始化程序。以TMS320LF2407为例:
#define SCSR1 0x7018 ;定义scsr1寄存器
#define SCSR2 0X7019 ;定义scsr2寄存器
#define WDKEY 0x7025 ;定义wdkey寄存器
#define WDNTR 0x7029 ;定义wdntr寄存器
StartUp() 开始函数
{
GEL_MapReset(); 存储空间复位 GEL_MapAdd(0x0000,0,0x7fff,1,1); 定义程序空间从0000-7fff 可读写
GEL_MapAdd(0x8000,0,0x7000,1,1); 定义程序空间从8000-f000 可读写
GEL_MapAdd(0x0000,1,0x10000,1,1); 定义数据空间从0000-10000可读写
GEL_MapAdd(0xffff,2,1,1,1); 定义i/o 空间0xffff可读写
GEL_MapOn(); 存储空间打开
GEL_MemoryFill(0xffff,2,1,0x40); 在i/o空间添入数值40h
*(int *)SCSR1=0x0200; 给scsr1寄存器赋值
*(int *)SCSR2=0x000C; 给scsr2寄存器赋值,在这里可以进行mp/mc方式的转换
*(int *)WDNTR=0x006f; 给wdntr寄存器赋值
*(int *)WDKEY=0x055; 给wdkey寄存器赋值
*(int *)WDKEY=0x0AA; 给wdkey寄存器赋值
}
使用TI公司模拟器件与DSP结合使用的好处。
1)在使用TI公司的DSP的同时,使用TI公司的模拟可以和DSP进行无缝连接。器件与器件之间不需要任何的连接或转接器件。这样即减少了板卡的尺寸,也降低了开发难度。
2)同为TI公司的产品,很多器件可以固定搭配使用。少了器件选型的烦恼
3)TI在CCS中提供插件,可以用于DSP和模拟器件的开发,非常方便。
C语言中可以嵌套汇编语言?
可以。在ANSI C标准中的标准用法就是用C语言编写主程序,用汇编语言编写子程序,中断服务程序,一些算法,然后用C语言调用这些汇编程序,这样效率会相对比较高
在定点DSP系统中可否实现浮点运算
当然可以,因为DSP都可以用C,只要是可以使用c语言的场合都可以实现浮点运算。
JTAG头的使用会遇到哪些情况
1)DSP的CLKOUT没有输出,工作不正常。
2)Emu0,Emu1需要上拉。
3)TCK的频率应该为10M。
4)在3.3V DSP中,PD脚为3.3V 供电,但是仿真器上需要5V电压供电,所以PP仿真器盒上需要单独供电。
4)仿真多片DSP。在使用菊花链的时候,第一片DSP的TDO接到第二片DSP的TDI即可。注意当串联DSP比较多的时候,信号线要适当的增加驱动。
include头文件(.h)的主要作用
头文件,一般用于定义程序中的函数、参数、变量和一些宏单元,同库函数配合使用。因此,在使用库时,必须用相应的头文件说明。
DSP中断向量的位置
1)2000系列dsp的中断向量只能从0000H处开始。所以在我们调试程序的时候,要把DSP选择为MP(微处理器方式),把片内的Flash屏蔽掉,免去每次更改程序都要重新烧写Flash工作。
2)3x系列dsp的中断向量也只能在固定的地址。
3)5000,6000系列dsp的中断向量可以重新定位。但是它只能被重新定位到Page0范围内的任何空间。
有源晶振与晶体的区别,应用范围及用法
1)晶体需要用DSP片内的振荡器,在datasheet上有建议的连接方法。晶体没有电压的问题,可以适应于任何DSP,建议用晶体。 2)有源晶振不需要DSP的内部振荡器,信号比较稳定。有源晶振用法:一脚悬空,二脚接地,三脚接输出,四脚接电压。
程序经常跑飞的原因
1)程序没有结尾或不是循环的程序。
2)nmi管脚没有上拉。
3)在看门狗动作的时候程序会经常跑飞。
4)程序编制不当也会引起程序跑飞。
5)硬件系统有问题。
并行FLASH引导的一点经验-阿哲
最近BBS上关于FLASH和BOOT的讨论很活跃,我也多次来此请教。前几天自制的DSP板引导成功,早就打算写写这方面的东西。我用的DSP是5416,以其为核心,做了一个相对独立的子系统(硬件、软件、算法),目前都已基本做好。 下面把在FLASH引导方面做的工作向大家汇报一下,希望能对大家有所帮助。本人经验和文笔都有限,写的不好请大家谅解。 硬件环境:
DSP:TMS320VC5416PGE160
FLASH:SST39VF400A-70-4C-EK 都是贴片的,FLASH映射在DSP数据空间的0x8000-0xFFFF
软件环境: CCS v2.12.01
主程序(要烧入FLASH的程序): DEBUG版,程序占用空间0x28000-0x2FFFF(片内SARAM),中断向量表在0x0080-0x00FF(片内DARAM),数据空间使用0x0100-0x7FFF(片内DARAM)。 因为FLASH是贴片的,所以需要自己编一个数据搬移程序,把要主程序搬移到FLASH中。在写入FLASH数据时,还应写入引导表的格式数据。最后在数据空间的0xFFFF处写入引导表的起始地址(这里为0x8000)。
搬移程序: DEBUG版,程序空间0x38000-0x3FFFF(片内SARAM),中断向量表在0x7800-0x78FF(片内DARAM),数据空间使用0x5000-0x77FF(片内DARAM)。 搬移程序不能使用与主程序的程序空间和中断向量表重合的物理空间,以免覆盖。 烧写时,同时打开主程序和搬移程序的PROJECT,先LOAD主程序,再LOAD搬移程序,然后执行搬移程序,烧写OK! 附:搬移程序(仅供参考)
volatile unsigned int *pTemp=(unsigned int *)0x7e00; unsigned int iFlashAddr;
int iLoop; /* 在引导表头存放并行引导关键字 */
iFlashAddr=0x8000;
WriteFlash(iFlashAddr,0x10aa);
iFlashAddr++; /* 初始化SWWSR值 */
WriteFlash(iFlashAddr,0x7e00);
iFlashAddr++; /* 初始化BSCR值 */
WriteFlash(iFlashAddr,0x8006);
iFlashAddr++; /* 程序执行的入口地址 */
WriteFlash(iFlashAddr,0x0002);
iFlashAddr++;
WriteFlash(iFlashAddr,0x8085);
iFlashAddr++; /* 程序长度 */
WriteFlash(iFlashAddr,0x7f00);
iFlashAddr++; /* 程序要装载到的地址 */
WriteFlash(iFlashAddr,0x0002);
iFlashAddr++;
WriteFlash(iFlashAddr,0x8000);
iFlashAddr++;
for (iLoop=0;iLoop<0x7f00;iLoop++)
{ /* 从程序空间读数据,放到暂存单元 */
asm(" pshm al");
asm(" pshm ah");
asm(" rsbx cpl");
asm(" ld #00fch,dp");
asm(" stm #0000h, ah");
asm(" MVDM _iLoop, al");
asm(" add #2800h,4,a");
asm(" reada 0h");
asm(" popm ah");
asm(" popm al");
asm(" ssbx cpl"); /* 把暂存单元内容写入FLASH */
WriteFlash(iFlashAddr,*pTemp);
iFlashAddr++; } /* 中断向量表长度 */
WriteFlash(iFlashAddr,0x0080);
iFlashAddr++; /* 中断向量表装载地址 */
WriteFlash(iFlashAddr,0x0000);
iFlashAddr++;
WriteFlash(iFlashAddr,0x0080);
iFlashAddr++;
for (iLoop=0;iLoop<0x0080;iLoop++) { /* 从程序空间读数据,放到暂存单元 */
asm(" pshm al");
asm(" pshm ah");
asm(" rsbx cpl");
asm(" ld #00fch,dp");
asm(" stm #0000h, ah");
asm(" MVDM _iLoop, al");
asm(" add #0080h,0,a");
asm(" reada 0h");
asm(" popm ah");
asm(" popm al");
asm(" ssbx cpl"); /* 把暂存单元内容写入FLASH */
WriteFlash(iFlashAddr,*pTemp);
iFlashAddr++;
} /* 写入引导表结束标志 */
WriteFlash(iFlashAddr,0x0000);
iFlashAddr++;
WriteFlash(iFlashAddr,0x0000); /* 在数据空间的0xFFFF写入引导表起始地址 */
iFlashAddr=0xffff;
WriteFlash(iFlashAddr,0x8000);
关于LF2407A的FLASH烧写问题的几点说明
TI现在关于LF24x写入FLASH的工具最新为c2000flashprogsw_v112。可以支持LF2407、LF2407a、LF2401及相关的LF240x系列。建议使用此版本。在http://focus.ti.com/docs/tool/to ... Number="C24XSOFTWARE"上可以下载到这个工具。我们仿真器自带的光盘中也有此烧写程序。 在使用这个工具时注意:
一,先解压,再执行setup.exe。
二、进入cc中,在tools图标下有烧写工具;
1、关于FLASH时钟的选择,此烧写工具默认最高频率进行FLASH的操作。根据目标系统的工作主频重新要进行PLL设置。方法:先在advance options下面的View Config file中修改倍频。存盘后,在相应的目录下(tic2xx\algos\相应目录)运行buildall.bat就可以完成修改了。再进行相应的操作即可。
2、若是你所选的频率不是最高频率,还需要设定你自已的timings.xx来代替系统默认的最高频率的timings.xx。例如LF2407a的默认文件是timings.40。Timings.xx可以利用include\timings.xls的excel工作表来生成。然后在advance options下面的View Config file中修改相应的位置。存盘后,在相应的目录下运行buildall.bat就可以完成修改了。
3、对于TMS320LF240XA系列,还要注意:由于这些DSP的FLASH具有加密功能,加密地址为程序空间的0x40-0X43H,程序禁止写入此空间,如果写了,此空间的数据被认为是加密位,断电后进入保护FLASH状态,使FLASH不可重新操作,从而使DSP报废,烧写完毕后一定要进行Program passwords的操作,如果不做加密操作就默认最后一次写入加密位的数据作为密码。
4、2407A不能用DOS下的烧写软件烧写,必须用c2000flashprogsw_v112软件烧写;
5、建议如下:
1)、一般调试时,在RAM中进行;
2)、程序烧写时,避开程序空间0x40-0x43H加密区,程序最好小于32k;
3)、每次程序烧写完后,将word0,word1,word2,word3分别输入自己的密码,再点击 Program password,如果加密成功,提示Program is arrayed,如果0x40-0x43h中写入的是ffff,认为处于调试状态,flash不会加密;
4)、断电后,下次重新烧写时需要往word0~word3输入已设的密码,再unlock,成功后可以重新烧写了;
6、VCPP管脚接在+5V上,是应直接接的,中间不要加电阻。
7、具体事宜请阅读相应目录下的readme1,readme2帮助文件。
8.注意*.cmd文件的编写时应该避开40-43H单元,好多客户由于没有注意到这里而把FALSH加密。
如何设置硬件断点?
在profiler ->profile point -> break point
c54x的外部中断是电平响应还是沿响应?
是沿响应,准确的说,它要检测到100(一个clk的高和两个clk的低)的变化才可以。
参考程序,里面好象都要 disable wachdog,不知道为什么?
watchdog是一个计数器,溢出时会复位你的DSP,不disable的话,你的系统会动不动就reset。
时钟电路选择原则
1,系统中要求多个不同频率的时钟信号时,首选可编程时钟芯片;
2,单一时钟信号时,选择晶体时钟电路;
3,多个同频时钟信号时,选择晶振;
4,尽量使用DSP片内的PLL,降低片外时钟频率,提高系统的稳定性;
5,C6000、C5510、C5409A、C5416、C5420、C5421和C5441等DSP片内无振荡电路,不能用晶体时钟电路;
6,VC5401、VC5402、VC5409和F281x等DSP时钟信号的电平为1.8V,建议采用晶体时钟电路
C程序的代码和数据如何定位
1,系统定义:
.cinit 存放C程序中的变量初值和常量;
.const 存放C程序中的字符常量、浮点常量和用const声明的常量;
.switch 存放C程序中switch语句的跳针表;
.text 存放C程序的代码;
.bss 为C程序中的全局和静态变量保留存储空间;
.far 为C程序中用far声明的全局和静态变量保留空间;
.stack 为C程序系统堆栈保留存储空间,用于保存返回地址、函数间的参数传递、存储局部变量和保存中间结果;
.sysmem 用于C程序中malloc、calloc和realloc函数动态分配存储空间
2,用户定义:
#pragma CODE_SECTION (symbol, "section name");
#pragma DATA_SECTION (symbol, "section name")
cmd文件
由3部分组成:
1)输入/输出定义:.obj文件:链接器要链接的目标文件;.lib文件:链接器要链接的库文件;.map文件:链接器生成的交叉索引文件;.out文件:链接器生成的可执行代码;链接器选项
2)MEMORY命令:描述系统实际的硬件资源
3)SECTIONS命令:描述“段”如何定位
为什么要设计CSL?
1,DSP片上外设种类及其应用日趋复杂
2,提供一组标准的方法用于访问和控制片上外设
3,免除用户编写配置和控制片上外设所必需的定义和代码
什么是CSL?
1,用于配置、控制和管理DSP片上外设
2,已为C6000和C5000系列DSP设计了各自的CSL库
3,CSL库函数大多数是用C语言编写的,并已对代码的大小和速度进行了优化
4,CSL库是可裁剪的:即只有被使用的CSL模块才会包含进应用程序中
5,CSL库是可扩展的:每个片上外设的API相互独立,增加新的API,对其他片上外设没有影响
CSL的特点
1,片上外设编程的标准协议:定义一组标准的APIs:函数、数据类型、宏;
2,对硬件进行抽象,提取符号化的片上外设描述:定义一组宏,用于访问和建立寄存器及其域值
3,基本的资源管理:对多资源的片上外设进行管理;
4,已集成到DSP/BIOS中:通过图形用户接口GUI对CSL进行配置;
5,使片上外设容易使用:缩短开发时间,增加可移植.
为什么需要电平变换?
1)DSP系统中难免存在5V/3.3V混合供电现象;
2)I/O为3.3V供电的DSP,其输入信号电平不允许超过电源电压3.3V;
3)5V器件输出信号高电平可达4.4V;
4)长时间超常工作会损坏DSP器件;
5)输出信号电平一般无需变换
电平变换的方法
1,总线收发器(Bus Transceiver):
常用器件: SN74LVTH245A(8位)、SN74LVTH16245A(16位)
特点:3.3V供电,需进行方向控制,
延迟:3.5ns,驱动:-32/64mA,
输入容限:5V
应用:数据、地址和控制总线的驱动
2,总线开关(Bus Switch)
常用器件:SN74CBTD3384(10位)、SN74CBTD16210(20位)
特点:5V供电,无需方向控制
延迟:0.25ns,驱动能力不增加
应用:适用于信号方向灵活、且负载单一的应用,如McBSP等外设信号的电平变换
3,2选1切换器(1 of 2 Multiplexer)
常用器件:SN74CBT3257(4位)、SN74CBT16292(12位)
特点:实现2选1,5V供电,无需方向控制
延迟:0.25ns,驱动能力不增加
应用:适用于多路切换信号、且要进行电平变换的应用,如双路复用的McBSP
4,CPLD
3.3V供电,但输入容限为5V,并且延迟较大:>7ns,适用于少量的对延迟要求不高的输入信号
5,电阻分压
10KΩ和20KΩ串联分压,5V×20÷(10+20)≈3.3V
未用的输入/输出引脚的处理
1,未用的输入引脚不能悬空不接,而应将它们上拉活下拉为固定的电平
1)关键的控制输入引脚,如Ready、Hold等,应固定接为适当的状态,Ready引脚应固定接为有效状态,Hold引脚应固定接为无效状态
2)无连接(NC)和保留(RSV)引脚,NC 引脚:除非特殊说明,这些引脚悬空不接,RSV引脚:应根据数据手册具体决定接还是不接
3)非关键的输入引脚,将它们上拉或下拉为固定的电平,以降低功耗
2,未用的输出引脚可以悬空不接
3,未用的I/O引脚:如果确省状态为输入引脚,则作为非关键的输入引脚处理,上拉或下拉为固定的电平;如果确省状态为输出引脚,则可以悬空不接
第一章 CCS概述
本章概述CCS(Code Composer Studio)软件开发过程、CCS组件及CCS使用的文件和变量。
CCS提供了配置、建立、调试、跟踪和分析程序的工具,它便于实时、嵌入式信号处理程序的编制和测试,它能够加速开发进程,提高工作效率。
1.1 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节
CCS构成及接口见图1-1。
图1-1 CCS构成及接口
1.2 代码生成工具
代码生成工具奠定了CCS所提供的开发环境的基础。图1-2是一个典型的软件开发流程图,图中阴影部分表示通常的C语言开发途径,其它部分是为了强化开发过程而设置的附加功能。
图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文件可产生含有绝对地址的列表文件。如果没有绝对列表器,这些操作将需要冗长乏味的手工操作才能完成。
1.3 CCS集成开发环境
CCS集成开发环境(IDE)允许编辑、编译和调试DSP目标程序。
1.3.1 编辑源程序
CCS允许编辑C源程序和汇编语言源程序,你还可以在C语句后面显示汇编指令的方式来查看C源程序。
集成编辑环境支持下述功能:
o 用彩色加亮关键字、注释和字符串。
o 以圆括弧或大括弧标记C程序块,查找匹配块或下一个圆括弧或大括弧。
o 在一个或多个文件中查找和替代字符串,能够实现快速搜索。
o 取消和重复多个动作。
o 获得“上下文相关”的帮助。
o 用户定制的键盘命令分配。
1.3.2创建应用程序
应用程序通过工程文件来创建。工程文件中包括C源程序、汇编源程序、目标文件、库文件、连接命令文件和包含文件。编译、汇编和连接文件时,可以分别指定它们的选项。在CCS中,可以选择完全编译或增量编译,可以编译单个文件,也可以扫描出工程文件的全部包含文件从属树,也可以利用传统的makefiles文件编译。
1.3.3 调试应用程序
CCS提供下列调试功能:
o 设置可选择步数的断点
o 在断点处自动更新窗口
o 查看变量
o 观察和编辑存储器和寄存器
o 观察调用堆栈
o 对流向目标系统或从目标系统流出的数据采用探针工具观察,并收集存储器映象
o 绘制选定对象的信号曲线
o 估算执行统计数据
o 观察反汇编指令和C指令
CCS提供GEL语言,它允许开发者向CCS菜单中添加功能。
1.4 DSP/BIOS 插件
在软件开发周期的分析阶段,调试依赖于时间的例程时,传统调试方法效率低下。
DSP/BIOS插件支持实时分析,它们可用于探测、跟踪和监视具有实时性要求的应用例程,下图显示了一个执行了多个线程的应用例程时序。
图1-3 应用例程中各线程时序
DSP/BIOS API 具有下列实时分析功能:
o 程序跟踪(Program tracing)显示写入目标系统日志(target log)的事件,反映程序执行过程中的动态控制流。
o 性能监视(Performance monitoring)跟踪反映目标系统资源利用情况的统计表,诸如处理器负荷和线程时序。
o 文件流(File streaming)把常驻目标系统的I/O对象捆绑成主机文档。
DSP/BIOS 也提供基于优先权的调度函数,它支持函数和多优先权线程的周期性执行。
1.4.1 DSP/BIOS 配置
在CCS环境中,可以利用DSP/BIOS API定义的对象创建配置文件,这类文件简化了存储器映象和硬件ISR矢量映象,所以,即使不使用DSP/BIOS API 时,也可以使用配置文件。
配置文件有两个任务:
o 设置全局运行参数。
o 可视化创建和设置运行对象属性,这些运行对象由目标系统应用程序的DSP/BIOS API函数调用,它们包括软中断,I/O管道和事件日志。
在CCS中打开一个配置文件时,其显示窗口如下:
DSP/BIOS对象是静态配置的,并限制在可执行程序空间范围内,而运行时创建对象的API调用需要目标系统额外的开销(尤其是代码空间)。静态配置策略通过去除运行代码能够使目标程序存储空间最小化,能够优化内部数据结构,在程序执行之前能够通过确认对象所有权来及早地检测出错误。
保存配置文件时将产生若干个与应用程序联系在一起的文件,这些文件的细节参见1.7.2。
1.4.2 DSP/BIOS API 模块
传统调试(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 用户指南。
1.5 硬件仿真和实时数据交换
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的客户机上实时显示和分析,从而缩短研发时间。
RTDX由目标系统和主机两部分组成。小的RTDX库函数在目标系统DSP上运行。开发者通过调用RTDX软件库的API函数将数据输入或输出目标系统的DSP,库函数通过在片仿真硬件和增强型JTAG接口将数据输入或输出主机平台,数据在DSP应用程序运行时实时传送给主机。
图1-4 RTDX系统组成
在主机平台上,RTDX库函数与CCS一道协同工作。显示和分析工具可以通过COM API与RTDX通信,从而获取目标系统数据,或将数据发送给DSP应用例程。开发者可以使用标准的显示软件包,诸如National Instruments’ LabVIEW,Quinn-Curtis’ Real-Time Graphics Tools,或Microsoft Excel。同时,开发者也可研制他们自己的Visual Basic或Visual C++应用程序。
图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在线帮助。
1.6 第三方插件
第三方软件提供者可创建AxtiveX插件扩展CCS功能,目前已有若干第三方插件用于多种用途。
1.7 CCS文件和变量
本节简述CCS文件夹、CCS的文件类型及CCS环境变量。
1.7.1安装文件夹
安装进程将在安装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.用户文件夹
1.7.2文件扩展名
以下目录结构被添加到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.汇编源文件
1.7.3环境变量
安装程序在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。
1.7.4增加DOS环境空间
如果使用的是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或者是利用仿真器在进行开发,你只要按第二章和第四章中的步骤执行即可。
2.1 创建工程文件
在本章中,将建立一个新的应用程序,它采用标准库函数来显示一条hello world 消息。
1. 如果CCS安装在c:\ti中,则可在c:\ti\myprojects建立文件夹hello1。(若将CCS安装在其它位置,则在相应位置创建文件夹hello1。)
2. 将c:\ti\c5400\tutorial\hello1中的所有文件拷贝到上述新文件夹。
3.
从Windows Start菜单中选择Programs→Code Composer Studio ‘C5400→CCStudio。(或者在桌面上双击Code Composer Studio图标。)
注:CCS设置
如果第一次启动CCS时出现错误信息,首先确认是否已经安装了CCS。如果利用目标板进行开发,而不是带有CD-ROM的仿真器,则可参看与目标板一起提供的文档以设置正确的I/O端口地址。
4. 选择菜单项Project→New。
5. 在Save New Project As窗口中选择你所建立的工作文件夹并点击Open。键入myhello作为文件名并点击Save,CCS就创建了myhello.mak的工程文件,它存储你的工程设置,并且提供对工程所使用的各种文件的引用。
2.2 向工程添加文件
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(汇编器)环境变量定义中的目录(从左到右)。
2.3 查看源代码
1. 双击Project View中的文件hello.c,可在窗口的右半部看到源代码。
2. 如想使窗口更大一些,以便能够即时地看到更多的源代码,你可以选择Option→Font使窗口具有更小的字型。
/* ======== hello.c ======== */
#include <stdio.h>
#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 = 0 /* deliberate syntax error */
fileStr = 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节),该程序给出一个输入提示,并将输入字符串存放到一个文件中,然后从文件中读出该字符串,并把它输出到标准输出设备上。
2.4 编译和运行程序
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消息。
2.5 修改程序选项和纠正语法错误
在前一节中,由于没有定义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 = 0
7. 修改语法错误(缺少分号)。注意,紧挨着编辑窗口题目栏的文件名旁出现一个星号(*),表明源代码已被修改过。当文件被保存时,星号随之消失。
8. 选择File→Save 或按Ctrl+S可将所作的改变存入hello.c。
9. 点击(Incremental Build)工具栏按钮或选择Project→Build,CCS重新编译已被更新的文件。
2.6 使用断点和观察窗口
当开发和测试程序时,常常需要在程序执行过程中检查变量的值。在本节中,可用断点和观察窗口来观察这些值。程序执行到断点后,还可以使用单步执行命令。
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框以蓝色显示输入的文字。
还应注意,Watch Window中显示出*scanStr的值。
在键入一个输入字符串之后,程序运行并在断点处停止。程序中将要执行的下一行以黄色加亮。
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运行程序到结束。
2.7 使用观察窗口观察structure变量
观察窗除了观察简单变量的值以外,还可观察结构中各元素元素的值。
1. 在watch Window区域中点击鼠标右键,并从弹出表中选择Insert New Expression。
2. 键入str 作为表达式并点击OK。显示着+str={…}的一行出现在Watch Window中。+符号表示这是一个结构。回顾2.3,类型为PARMS的结构被声明为全局变量,并在hello.c中初始化。结构类型在hello.h中定义。
3.
点击符号+。CCS展开这一行,列出该结构的所有元素以及它们的值。
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,全部断点都被清除。
2.8 测算源代码执行时间
在本节中,将使用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<BUFSIZE;i++);{
8.
点击工具栏按钮或者在该代码行上点击右键并从弹出菜单中选择Toggle Profile Pt。
有关测试点的统计数据报告显示自前一个测试点或程序开始运行以来到本测试点所需的指令周期数。本例中,第二个测试点的统计数据报告显示自puts()开始执行到该测试点所需的指令周期数。
9. 选择Profile→View Statistics,窗口底部出现一个显示测试点统计数据的区域。
10.
通过拖拽该区域的边缘可调整其大小。
注:上图中的line数可能会不同
本手册中屏幕上所显示的line数可能会和当前所使用的软件版本显示的line数不同。
11. 点击(RUN)工具栏按钮 或按F5键运行该程序并在提示窗口中键入一串字符。
12.
注意对第二个测试点所显示的指令周期数,它应该大约为2800个周期(显示的实际数目可能会变化),这是执行puts()函数所需的指令周期数。由于这些指令只执行了一次,所以平均值、总数、最大值和最小值都是相同的。
注:目标系统在测试点处于暂停状态
只要程序运行到一个测试点,它就会自动暂停。所以,当使用测试点时,目标系统应用程序可能不能满足实时期限的要求。(用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使能。
2.9 进一步探索
为了进一步探究CCS,可作如下尝试:
o 在Build Option窗口中,检查与编译器、汇编器和连接器有关的域,注意这些域中值的变化是怎样影响所显示的命令行的,可在CCS中参见在线帮助了解各种命令行开关。
o 设置某些断点。选择Debug→Breakpoints,注意在Breakpoints 输入框中可以设置条件断点,只有当表达式的值为真时,程序才会在断点处暂停。也可以设置各种硬件断点。
2.10进一步学习
为了掌握关于使用CCS的更多的技巧,可参见有关CCS的在线帮助或CCS用户指南(PDF格式)。
第三章 开发DSP/BIOS程序
本章通过使用DSP/BIOS优化第二章中的hello world实例介绍DSP/BIOS及如何创建、编译、调试和测试使用DSP/BIOS编写的程序。
基本要求:CCS的DSP/BIOS组件,目标板。
3.1 创建配置文件
实现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.
如果已经关闭了CCS,则重新开始。选择Project→Open重新打开c:\ti\myprojects\hello1文件夹中的myhello.mak 项目(如你安装其它地方,则在所安装的地方打开含有myprojects的文件夹。)
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.
在LOG0处点击鼠标右键,从弹出菜单中选择Rename,键入trace即改变此对象名称为trace。
6. 选择File→Save。在弹出窗口中选择你的工作路径(通常是c:\ti\myprojects\hello 1),并将此配置保存为myhello.cdb,实际上创建了下述文件:
o myhello.cdb 保存配置设置
o myhellocfg.cmd 连接命令文件
o myhellocfg.s54 汇编语言源文件
o myhellocfg.h54 由myhellocfg.h54包含的汇编语言头文件
3.2 向工程添加DSP/BIOS文件
回顾上节所建立的配置文件,它实际上包括四个新文件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.
再次选择Project→Add Files to Project,在弹出窗口的文件类型栏中选择Linker Command File(*.cmd), 再选择文件myhellocfg.cmd并点击Open,随之产生如下消息框:
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 <std.h>
#include <log.h>
/* 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 。
3.3 用CCS 测试
由于使用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.
选择Debug→Run 或按F5。 hello world信息将出现在Message Log 区域内。
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的工具,如Message Log或其它的DSP/BIOS 插件。特别是在使用DSP/BIOS插件后,必须确保RTDX无效,选Tools RTDX启动RTDX 插件,并从下拉菜单中选取RTDX disable,然后点击鼠标右键再选择Hide。反之亦然,如2.8节所述。
当试图同时使用Profiling和RTDX时将导致错误信息,见上图。
3.4 测算DSP/BIOS代码执行时间
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.
注意在第二个测试点显示的指令周期数为58(实际中可能稍有不同),这是执行LOG_printf函数需要的指令周期数。由于字符串的格式化在PC主机上、而不是在目标系统DSP上完成,因此调用LOG_printf的效率很高。LOG_printf需要的58个指令周期,而在第二章结束时测试的put()则需要2800个指令周期。在应用程序中调用LOG_printf监视系统状态对程序执行几乎没有影响。
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
3.5 进一步探索
为进一步了解CCS,试作如下工作:
o 加载myhello.out 并在LOG_printf行设置断点,选取Debug→Breakpoints并在IDL_F_loop上设置断点。(在弹出对话框的Location栏中键入IDL_F_loop,并点击Add)。
运行程序 在第一个断点处,使用View CPU Registers CPU 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 用户指南。
3.6 进一步学习
进一步学习使用CCS 和DSP/BIOS,请参见CCS中 的在线帮助,也可参见CCS 用户指南和TMS320C54x DSP/BIOS 用户指南。
第四章 算法和数据测试
本章说明创建和测试一个简单算法的过程并介绍CCS附加功能。
本章将创建一个完成基本信号处理的程序,并在下两章继续介绍。
可用存储在PC机文件中的数据来建立和测试一个简单的算法,也可利用CCS的探针断点、图形显示、动态运行和GEL文件。
4.1 打开和查看工程
在CCS中打开一个工程文件并查看此工程中源文件和库文件。
1. 若CCS安装在c:\ti,那么就在c:\ti\myprojects下创建文件夹volume1(若CCS安装在其它位置,那么就在相应位置创建文件夹volume1)。
2. 将文件夹c:\ti\c5400\tutorial\volume1中的所有文件复制到新文件夹。
3. 如果CCS应用程序还未运行,则在开始菜单中选择Program Code Composer Studio’C5400 CCStudio。
4. 选择Project Open并在volume1中选择volume.mak文件并点击Open。
5.
由于Project已经移动,CCS将显示一个对话框指示没找到库文件。点击Browse键,按路径c:\ti\c5400\cgtools\lib找到并选中rts.lib。(如果CCS安装在其它位置,那么在安装文件夹里找c5400\cgtools\lib)。
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目标系统提供运行支持。
4.2 查看源程序
在Project View窗口中双击volume.c文件,源程序就显示在CCS窗口的右边。
注意实例中的下面几部分:
o 主函数打印完信息后,应用程序处于无限循环状态。在此循环中,主函数调用dataIO和processing()函数。
o processing()函数将增益与输入缓存区中的各值相乘并将结果存入输出缓存区;同时也调用汇编Load子程序,该子程序占用的指令周期取决于传递给它的processingLoad值。
o dataIO函数是一个空函数,它的作用类似于return语句。可利用CCS中的探针(Probe Point)功能把主机文件中的数据读取到inp­_buffer缓存区,此法优于用C代码来完成I/O功能。
#include <stdio.h>
#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;
}
4.3 为I/O文件增加探针断点
本节介绍探针断点(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.
点击Open,将该文件添加到File I/O对话框的列表上,接着出现sine.dat文件控制窗口(CCS窗口可以覆盖它)。在运行程序时,可用这个窗口开始、停止、重复、或快速前进来控制数据文件。
10.
在File I/O对话框中,将Address修改为 inp_buffer,Length修改为100,选中Wrap Around。
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。
4.4 显示图形
如果现在就运行程序的话,你将无法了解到更多的程序运行时的信息。可以在 inp_buffer 和 out_buffer数组的地址范围内设置观察变量,但需要设置很多变量,而且是按数字形式显示而非图形形式。
CCS 提供了多种用图形处理数据的方法。在本例中,你将看到一个基于时间绘制的图形。本节介绍图形的打开,下节介绍程序的运行。
1. 选择View→Graph→Time/Frequency。
2.
在弹出的Graph Property Dialog对话窗中, 将 Graph Title,Start Address,Acquisition Buffer Size,Display Data Size,DSP Data Type,Autoscale和Maximum Y-value 的属性改变为如下图所示。向下滚动或调整 dialog 框的大小可看到所有的属性。
3. 点击OK,出现输入缓存的一个图形窗。
4. 在上述窗中右击鼠标,从弹出的菜单中选择Clear Display。
5. 再次选择View Graph Time/Frequency。
6. 改变Graph Title的属性为Output Buffer,改变Start Address的属性为Out_buffer,其余的设置都不变。
7. 点击OK,又出现一个图形窗,在该图形窗内右击鼠标,从弹出的菜单中选择Clear Display。
4.5 执行程序和绘制图形
到目前为止,你已经放置好了一个探针,它可临时暂停目标系统,将数据从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.
注意每个图形包含2.5个周期的正弦波形,且在程序运行过程中两个图形反向。每次到达探测点时,CCS 从sine.dat文件中得到100个值,再将这100个值写入inp_buffer地址。符号相反是因为输入缓冲区包含的值是从sine.dat文件中读取的,而输出缓冲区最后的值是经过函数处理后得到的。
注意:目标系统运行程序在探测点暂停
不管何时到达探测点,CCS都能暂时停止目标系统。因此,如果使用了探针,目标系统应用程序就不能满足实时期限的要求。在本开发阶段只测试算法,以后将用RTDX和DSP/BOIS分析实时性能。
只使用测试点和Run命令也能刷新图形,4.10节将详细介绍。
4.6 调节增益
回顾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图形中信号幅度变化反映了增益的提高。
4.7 观察范围外变量
你曾使用Watch Window观察过变量并改变变量的值。但当你想查看的变量的作用域不在当前设置的断点范围内时,则可使用访问堆栈来查看。
1. 点击工具栏按钮或按Shift F5暂停程序运行。
2. 用CCS 重新查看volume.c程序。注意在主函数与processing函数中已经定义了变量*input,但它没有在数据输入输出函数中定义。
3. 在显示源程序volume.c的窗口中,把光标放置在dataIO()函数的return行上。
4. 点击工具栏按钮或按F9,该行变为红色高亮显示(除非你用Open→Color改变颜色)。
5.
点击F5执行程序,CCS将自动把断点移到相应函数的下一条汇编指令处。对话框通知你将把断点移到下一行。
6. 点击OK
7. 按下F5,程序运行直到dataIO()函数末尾的断点处暂停。
8.
在Watch窗口中点击鼠标右键并从弹出菜单中选择Insert New Expression。
9. 在Expression区键入*input并点击OK。
10.
注意在Watch窗口中显示该变量是一个未知符号,这说明*input 没有在dataIO()函数内定义。
11. 选择View→Call Stack,则可看到相邻的堆栈窗与观察窗。
12.
在堆栈窗中点击main()就可在主函数范围内查看*input的值。
13. 可以点击堆栈窗底部的地址以便看清楚gain是全局变量,而*input则不是。(地址的变化依赖于正使用的DSP)
14. 在堆栈窗中点击鼠标右键并从弹出菜单中选择Hide。
15. 将光标放置在datdIO()函数中的return之后的行上,撤消第4步中放置的断点,点击工具栏按钮或单击F9。
4.8 使用GEL文件
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的值将随滑动指针的改变而改变。
4.9 调节和测试processing函数
在第二章中曾使用测试点(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.
注意在第二个测试点处显示的最大周期数大约为44(真实值可能不同),当processingLoad=1时,它表明执行Load程序所需的指令周期数。
11. 选择GEL→Application Control→Load。
12.
在load域输入2,然后点击Execute,则对应于第二个测试点的最大周期数改变为75。每当processingLoad增加1时,指令周期数就增加31。这些指令周期数表明load函数的执行时间,load函数包含在load.asm文件中。
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。
4.10 进一步探索
为了进一步了解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节。
4.11 进一步学习
进一步学习关于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组件。
5.1 打开和查看工程
首先在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 头文件,在保存配置文件时创建
5.2 查看源程序
本章通过由第四章的应用程序修改而得的程序实例来介绍实时操作。该实例采用片内定时器中断模拟周期性的外部中断实现数据的输入/输出,只需对其稍加修改就可真正通过外部中断实现数据的输入/输出。
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 <std.h>
#include <log.h>
#include <swi.h>
#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);
5.3 修改配置文件
对于本实例,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.
在LOG对象LOG_system上鼠标右键,从弹出菜单选择Properties。你可以看到该对象的属性对话窗。在程序运行时,它记录各种DSP/BIOS模块的系统跟踪事件。
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.
不作任何变动仅点击Cancel关闭Clock Manager Properties对话窗口。
9. 展开HWI对象查看HWI_TINT的属性,其中断源是DSP 定时器,当片内定时器引起中断时,它运行CLK_F_isr函数。CLK对象函数的运行是由CLK_F_isr硬件中断服务函数引发的,它的优先级高于软中断,一旦运行便不会被打断。(由于CLK_F_isr已经保护了寄存器现场,所以CLK 函数不需要象硬件中断服务程序中正常情况下须做的那样保存和恢复现场。)
10. 在软中断对象processing_SWI上点击鼠标右键并从弹出菜单中选择Properties。
o
function 软中断激活时运行processing函数,见5.2节。
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。
5.4 用Execution Graph查看任务执行情况
当在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.
点击或选择Debug→Run,则Execution Graph显示如下。
10. 在Time行的标记给出了Clock Manager运行一次CLK函数的时间。按标记计算processing_SWI执行的时间间隔。在此有10个标记表明:dataIO_CLK对象每执行10次,processing_SWI对象就执行一次。这正如所预料的一样,因为被dataIO函数递减的mailbox域的起始值为10。
5.5 修改和查看load值
使用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.
在Execution Graph区域内点击鼠标右键并从弹出菜单中选择Clear。在processing_SWI函数执行期间出现了一个时间标记,这意味着程序不满足实时期限的要求吗?不,它只表明运行程序的功能正确。能够引起CLK对象的服务例程运行的硬中断能够中断软中断服务例程的执行,而在软中断服务例程再次运行之前,它能够完成自己的任务。
10. 使用GEL控制修改load值为3000,然后点击Execute。CPU的负荷增加到95%左右。
11.
在Execution Graph区域内点击鼠标右键并从弹出菜单中选择Clear。因为processing_SWI在10个时间标记发生之前完成,所以程序仍满足实时期限的要求。
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。
5.6 分析任务的统计数据
可使用DSP/BIOS的其它控制功能查看DSP的Load值和processing_SWI对象的处理过程的统计数据。
1. 选择Tools→DSP/BIOS→Statistics View将出现一个Statistics View区域,它显示Load DSP/BIOS程序和/或设置使用控制功能的属性。
2.
在Statistics View区域中点击鼠标右键并从弹出菜单中选择Property Page,按下图加亮相应项并点击OK。
3.
你将看到processing_SWI对象的统计域。(在该统计域上点击鼠标右键并从弹出菜单中撤消Allow Docking)可使其成为一个单独的窗口,也可调整窗口大小使得全部四个域均可见。
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控制项。
5.7 增加STS显式测试
在前面的章节中,曾用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 <clk.h>
#include <sts.h>
#include <trc.h>
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。
5.8 观察显式测试统计数据
要观察由新增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.
点击OK,可看到两个对象的统计域。在该域上点击鼠标右键并从弹出菜单中撤消Allow Docking,可使该区域成为一个单独的窗口,亦可调整窗口大小使全部域可见。
8. 点击工具栏按钮或选择Debug®Run。
9. 用processingLoad_STS的Max值减去processing_SWI的Max值,其结果约为1445条指令(实际显示的值可能有变化)。SWI的统计数据是用指令周期来度量的。因为曾用CLK_gethtime函数作为处理load值的基准,所以processingLoad_STS由片内定时计数器计数,它等同于指令周期数。这些指令是在processing函数中执行的,而不是在STS_set和STS_delta调用之间执行的,如下所示。
例如,当load值为10时,processingLoad_STS的Max值约为203,而processing_SWI的Max值约为1648。在STS_set函数和STS_delta函数之外的processing函数中所执行的指令周期数的计算公式为:1648 - 203 = 1445
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插件和源程序窗口。
5.9 进一步探索
为了进一步探索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中的数值。
5.10 进一步学习
欲了解有关CLK、SWI、STS和TRC模块的知识,请参见CCS中的在线帮助或TMS320C54x DSP/BIOS用户指南。
第六章 实时分析
本章介绍程序的实时分析技术并纠正程序中存在的错误。
本章中,将用第五章的例子来作实时分析并纠正与实时性有关的问题。将采用RTDX对目标系统作实时改动,将使用DSP/BIOS周期函数并设置软中断优先级等。
基本要求:CCS的DSP/BIOS和RTDX组件、目标板
6.1 打开和查看工程
本章的工作是在前一章工作基础上进行的,如果没有做前一章的工作,可以把目录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。
6.2 修改配置文件
在本例中,你需要增加一个新对象到配置文件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
函数名修改为_loadchange。PRD对象以所选定的周期执行loadchange函数。在下一节中,可查看该函数。
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)。
6.3 查看源程序
在Project View的volume.c处双击鼠标左键,源文件将显示在CCS窗口的右半部分。由于文件volume.c是从c:\ti\c5400\tutorial\volume4 目录中拷贝到你的工作文件夹中的,因此它与前一章的源程序存在下述差别:
o 增加了一个头文件:
#Include <rtdx.h>
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位变量能存储的最大值。
6.4 使用RTDX控制修改运行时的load值
当你在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.
在Statistics View区域点击鼠标右键并从弹出菜单中选择Property Page,加亮图示选项。
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.
使用Windows浏览器运行你的工作文件夹下的loadctrl.exe程序,就会出现一个Load Control窗口。该应用程序使用VB和RTDX编制而成,如果你拥有VB开发环境,你可以查看loadctrl.exe的VB源程序,它位于c:\ti\c5400\tutorial\volume4目录下。
该应用程序使用了下述RTDX函数:
o rtdx.Open(“control_channel”,”W”) 当打开应用程序时,打开向目标板写入信息的控制通道。
o rtdx.Close() 当关闭应用程序时,关闭控制通道。
o Rtdx.Writel2(datal2,bufstate) 把滑动控制条的当前值写入控制通道,目标程序可以读取该值并使用它刷新load值。
15. 选择Debug→Run或者点击工具栏按钮(Run)。
注意:Processing_SWI每10个计数单位(按PRD ticks计)出现一次,PRD_SWI每2个计数单位运行一次,正如所预料的一样。loadchange_PRD是被PRD_swi调用的。
PRD统计是用PRD ticks来计量的,SWI统计用指令周期来计量的,loadchange_PRD的Max和Average域显示表明,在该函数开始运行到
运行结束所需的时间之间不足一个完整的PRD周期。
16. 使用Load Control窗口逐渐增加处理load值。(如果在DSP 应用程序停止工作的情况下滑动Load Control窗口的控制条,则RTDX将新的load控制值缓存在主机上。这些值直到DSP应用程序重新运行、并调用RTDX_readNB以请求从主机刷新load值时才会有影响)。
17.
重复步骤16,直到loadchange_PRD中的Max和Average值增加并在Execution Graph的Assertion行出现蓝色方块,Assertion表明一个线程不满足实时期限的要求。
为什么?当load值超过某个值时,loadchange_PRD的Max值开始增加,随着load值的增加,processing_SWI需要占用的运行时间长得致使loadchange_PRD在超过实时期限很长时间才能开始运行。
当load值增加到一定程度时,低优先级的idle循环就不再执行,主机停止接收实时分析数据,DSP/BIOS插件停止刷新,暂停目标程序用排队数据刷新插件。
6.5 修改软中断优先级
为了便于理解程序为什么不满足实时期限的要求,你需要检查软中断任务的优先级。
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插件和源程序窗口。
6.6 进一步探索
为了进一步研究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造成很大的影响。
6.7 进一步学习
想要更多地了解软中断属性、RTDX和PRD模块,请参见CCS和RTDX的在线帮助或者参考TMS320C54x DSP/BIOS User’s Guide(用户指南)。
第七章 I/O
本章介绍用DSP/BIOS和RTDX技术实现I/O。
在本章中,将采用RTDX和DSP/BIOS使应用程序与I/O设备相连接。也可以采用DSP/BIOS API的HST、PIP和SWI模块。
基本要求:DSP/BIOS和RTDX组件,目标板
7.1 打开和查看工程
在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 头文件
7.2 查看源程序
本章中的例子模拟一个能数字化音频信号、调整音量、产生幅度可调的模拟输出的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 <std.h>
#include <log.h>
#include <rtdx.h>
#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 */
}
}
}
7.3 Signalprog应用程序
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被调用一次。
7.4 运行应用程序
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应用程序。
由于slider.exe应用程序将创建和打开RTDX控制通道,因此它必须在RTDX使能以后运行,否则它不能打开控制通道。Signalprog应用程序只有在点击Test On按钮后才使用到RTDX,因此它可以在任何时候运行。
9. 调整signalprog窗口高度。
10.
在signalprog窗口中的点击Test ON,这就启动了输入/输出通道。
11. 滑动Volume Slider窗口的控制钮,这将改变输出信号幅度,观察Received Signal图中信号幅度的变化。
注:Volume Slider初始化设置
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的修改版会说明该技术。
7.5 使用HST和PIP模块修改源程序
现在用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 <hst.h>
#include <pip.h>
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函数无有效的数据可供处理时,该函数将被调用。
7.6 HST和PIP资料
每个主机通道都在内部都使用一个流水线。当使用主机通道时,目标应用程序管理流水线得一端,主机通道控制插件管理流水线得另一端。
当准备使用外设而不是使用主机修改程序时,可保留管理流水线目标板端的源代码,并在函数中增加处理管理流水线另一端的I/O设备的源代码。
7.7 在配置文件中增加通道和SWI
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.
在input_HST处点击鼠标右键并从弹出菜单中选择Properties,然后设置该对象的属性如下图所示并点击OK。
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.
为output_HST对象设置如下属性并点击OK。
当输出通道中含有一个空帧时,它用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。
7.8 运行修改后的程序
1. 点击工具栏按钮 或选择Project→Rebuild All。
2. 选择File→Load Program。选择hostio.out并点击Open。
3.
选择Tools→DSP/BIOS→Host Channel Control,Host Channel Control列出了HST对象,它允许你把它们和PC机上的文件捆绑在一起,也可以启动和废止通道。
4. 点击工具栏按钮或选择Debug→Run。
5. 在input_HST通道处点击鼠标右键并从弹出菜单在选择Bind。
6. 从你的工作文件夹下选择文件input.dat并点击Bind。
7.
在output_HST通道处点击鼠标右键并从弹出菜单在选择Bind。
8. 在File Name框中敲入output.dat并点击Bind。
9. 在input_HST通道处点击鼠标右键并从弹出菜单在选择Start。
10. 在output_HST通道处点击鼠标右键并从弹出菜单在选择Start,注意在Transferred栏中显示数据正在被传送。
11. 当数据传送完毕,点击或者按Shift+F5中止运行程序。
文章评论(0条评论)
登录后参与讨论