研究生期间断断续续做过TI DSP研究,从一个对嵌入式一点也没有了解的新手到快毕业时完成一个自认为满意的项目,其中走过很多弯路,现在把我对DSP学习的心得和一些参考文献列出来,可能对初学者具有帮助。
实验室用的是一款闻亭的DM642开发板,当时这款开发板还比较新,国内中文资料很少,而且闻亭但是的例子程序均是采用TI的原程序,不像合众达的例子程序容易上手,所以可能合众达的板子比较适合初学者使用。
DM642是一款针对图像应用的高端DSP,近几年来国内应用的范围很广。对于DSP软件学习而言个人认为包含了3个方面的东西:1:芯片的外设,对芯片的基本操作和简单程序运行环境。2:嵌入失操作系统原理(DSP/BIOS)。3:DSP算法的移植和优化工作。下面分别对这三个方面做论述。
1:芯片的外设,对芯片的基本操作和简单程序运行。 学习DSP 首先是要对芯片和你所用到的芯片外设的数据手册说明比较清楚,对于初学者可能在刚开始看datasheet时感觉很头晕,因为datasheet只是一些说明性的东西,他没有教你怎么去用,所以datasheet部分一定要结合相应的例子程序去看。对于芯片的外设操作TI提供了一个CSL的函数,帮你事先定义好了一些寄存器地址,这样就不用你去查找每个寄存器的详细地址。 现在的C6000 程序开发大部分采用C语言,极少数的关键代码采用线性汇编或者汇编语言。对于一个C语言运行工程需要的最少元素是:1:mian函数 2:cmd文件3:runtime support lib。这是让一个基于C语言的工程跑起来的最少条件。换句话说只要有了这三个东西我们就可以在DSP上做任何想做的事,但是考虑到做大型工程和复杂应用的需要,通常又要用到操作系统DSP/BIOS和驱动。 在阶段首先是 让一个最简单的hell world工程跑起来,这个工程这包含三个文件,一个main.c 一个CMD文件,一个 rts.lib。然后在查数据手册DSP的外设资源调试一遍,这个过程完成后几基本上手了:)。 在这个过程中需要搞明白的是一个过程,三个文件,和简单的调试方法。一个过程是C语言怎么生成.out可执行文件的过程,通常包含编译,汇编,连接三个过程。几个文件是obj, cmd, map,文件Obj,Cmd和Map文件的格式在TI的CCS 文挡帮助中都有详细论述。调试方面我们可可以利用防真器可以让程序在任何地方停下来,然后利用CCS的Memory View功能可以查看想要知道的CPU地址映射的区域。这部分的参考资料可以查看(1)电子科技大学 出版的 C/C++语言硬件程序设计--基于TMS320C5000系列DSP(2)帮助文档 2:嵌入失操作系统原理(DSP/BIOS) 这部分就有嵌入式操作系统知识了,DSP/BIOS是不开源的,如果想对操作系统的知识了解深入的话可以看看uc/os-II的原代码。嵌入式操作系统的基本原理都一样。这个完成后在把Ti关于DSP/BISO的列子程序跑一便熟悉操作系统中各个模块,如TSK, TIMER…..。 在熟悉完操作系统后,剩下的就是对DSP/BISO的驱动模型了,TI 的驱动模型采用的是class-mini driver模式,其中class driver就是一些函数接口,提供到mini driver的访问。其中mini driver实现方式根据不同的板子和芯片会不一样,建议选取一个外设资源,看懂其源代码,这些代码一般都在几个c 文件内,其中最主要是5-7个函数的实现; mdBindDev() mdUnBindDev() mdControlChan();………………….DSP/BIOS的驱动比较简单,总得来说驱动可以分为2个部分,一部分函数硬件的初始化和控制工作,这部分相对交简单;另外一部分函数负责 I/O,buffer的同步工作,这部分通常要复杂的多,而且这部分函数常常和中断牵涉在一起,所以在看驱动源代码时一定要时刻知道中断什么时候发生,中断服务函数里面做了些什么,对其他函数的影响是什么等。如果能把驱动代码看一遍对于C语言提高是很大的。这部分的参考资料可以查看 (1) DSP/BIOS user guide (2) How to write DSP device driver http://www.embedded.com/columns/ ... 5?_requestid=176707 (3) 嵌入式实时操作系统UC/OS-II 3:DSP算法的移植和优化工作 这部分是最后工作,一般也是比较耗时间的工作。现在如果实现比较复杂的系统不做DSP程序的优化是肯定不行的。DSP程序的优化方法有很多,网上也有很多资料,但是以我实际的经验来看很多人都没有把握关键的地方,如果是复杂算法的话DSP优化的第一步应该是存储器优化,也就是说利用ping-pong buffer技术将待处理的数据分批的搬运到片内存储器中,在这个工程中要结合片内资源,设计好数据结构,并一定要考虑让数据对齐。存储器优化是 program optimization
文档中没有提及,而是在一个叫Cache user guide 文档中说明,所以这样就造成很多人不知道原因。在完成存储器优化之后就是program optimization 文档中所讲的方法,-o3,数据打包,inline,循环展开,汇编等等。 做优化的过程中一定要保证优化之前和之后的处理结果正确性,也就是说优化不能导致错误的发生,然后在尽量提高时间。 关于优化后函数运行时间的测量TI的有个文档里面有教你怎么测,就是利用定时器来测量函数运行的时间,另外对于运行时间本来就只有几百个cycle的短小汇编函数也可以利用CCS 的clock功能来测时间。总之程序优化就是一项耗时间的体力活,哈哈!这部分的参考资料可以查看 (1) program optimization guide(2) cache user guide
写给TI 6000系列DSP初学者
前言
最近在hellodsp([url=../]http://www.hellodsp.com[/url])申请了个版主,本来是要申请TMS320C6000版块的,不过这个版块已经有两位优秀的版主,我是做图像处理的,于是就锁定“语音视频处理”版块了,不过6000版块我还是会经常去,看到很多初学者在问一些入门的问题,有些提问题的同志对问题描述地也不够清楚,可能更多的是想提问题可不知道怎么提吧,我刚学DSP的时候也一样,碰到问题了不知道怎么把问题表述清楚,真有哑巴吃黄连的痛楚。最近有空回忆下自己学DSP的过程,算是个人经历吧,希望对大家有用。
我的经历
错过第一次学习机会
我2000年进入大学,专业通信工程。入学的时候成绩不错,还拿过一等奖学金,自以为自己很聪明。当时我们学院有个科技协会,简称科协,那时的科协会长是个大四的学兄,秃顶,给人印象深刻,感觉他很厉害,就入了科协,第一堂课是用555做个流水灯,科协已经把印制板做好,我只用把器件焊上去就行了,灯是亮了很好玩,于是自己琢磨电路的原理,那时是个刚入学的小子,什么也不懂,看那东西根本搞不懂,感觉太难了,后来慢慢就不去参加活动,再后来放弃了。
现在想想那个时候太轻言放弃了,包括后来大学里自学51单片机、学FPGA都是只浅尝则止,而没有持之以恒,以至于后来错过了很多很多机会。所以在这里要告诉大家,也告诉我自己,学技术一定要坚持,不管碰到什么困难,绝不能轻言放弃,坚持就会有进步,就像长跑,总有几个困难点,坚持过去就觉得不是那么困难,水平才会有提升。
第一次使用C51
说起这个,不得不感谢下我的一个大学室友,是他带我入门C51,第一次用protel画印制板,第一次申请免费样片、第一次编写调试程序,第一次使用示波器等等,这些都得归功于他的指导。
时间过得很快,一转眼就大四了,想想自己大学游戏玩了三年,学业荒废,毕业设计这个机会一定要把握住,不然自己没什么资本找工作啊,于是在选题的时候选了个单片机的题目“基于DDS的信号发生器设计”。虽然之前接触过51、protel,不过那都是看看书而已,实际做起来什么都不会,我确定的方案是用C51去控制AD9853输出相应频率的波形,当然这里离不开键盘和LCD显示,AD9853是从AD公司申请的样片,那时我第一次知道还有免费午餐,大公司真的不错,记得当时TIDSP都可以申请,我就申请了一片6202,不过后来没那么容易申请了,这次我坚持了下来,一步一步地做,最终圆满完成了毕业设计。
我是幸运的,因为身边就有个很好的老师,初学者大都没有这样的条件,即便如此,初学者还是应充分挖掘身边的资源,将它们都利用起来,这样你才能更接近成功。
接触DSP
2004毕业后我到一个研究所工作,我所在的部门是做视频跟踪器的,主要用DSP+FPGA,对我来说入鱼得水,因为我对这些东西很有兴趣。当时我的同事们用的还是TI C50DSP,这个很多人可能听都没听过,TI的DSP按时间大概经历了这几个系列,C25-C50-V33-2000-5000-6000,C50的功能很有限,只有汇编开发环境,因为功能简单,所以学起来也相对容易,加上我有51的基础,很快就上手了,一年半后部门器件换代直接换成了64xx,由于受C50的影响,我们开发还是习惯用汇编,2006年5月前后,我率先用C开发产品,取得了不错的效果。
这当中我接触到了很多,由于我个人性格的原因,学什么都想学精,走了很多弯路。比如PCB刚开始用protel,后来发现它画复杂板子的时候不方便,于是学用allegro,后来又学SI;DSP也是,6000会用了想学2000、5000,后来发现自己很幼稚,其实一到二门精通了足以,学什么要注意学习理念,工具平台这些始终是外家功夫,要勤修内功。
总结及建议
1)选好自己的工具和平台学DSP当然首先要选择一款DSP(这里主要说TI的DSP,AD公司的不熟这里就不说了)。如果是个人学习的话主要看个人需要和应用场合,比如做图像处理那当然首推TI6000了,初学者不必将DSP分出三六九等,各个系列没有明显的优劣,但有明确的应用领域,2000偏接口控制,5000偏语音,6000适合做大数据量信号处理,比如图像、雷达等等。初学者最好有个开发板,不然无异于纸上谈兵,2000、5000的开发板相对便宜,6000的就比较昂贵。
就上手容易度来说,我个人觉得6000更易上手,6000的结构较2000、5000明了清晰,硬件上的条条框框比较少,你不需要看很多的硬件结构资料就能着手编程,这个大概是技术的进步吧。不过还是这句话,应用场合决定你的选择。
2)自己先动手
初学者如果会C语言语法,在看过一些资料后就可以着手写自己的第一个程序,如果写不出来,看看TI最初级的例程,完成自己第一个程序。我给我们单位新同事做6000培训的时候,给他们的第一个题目就是写一个程序让LED灯不停闪烁,这个灯可能接在GPIO上或者通过EMIF译码与FPGA配合控制(后者可能更有意义),更进一步的程序是控制闪烁的频率。我比较喜欢让他们用GPIO和EMIF,它们可能是6000里最简单和用的最多的外设了,它们是初学者最早要攻克的堡垒。
初学者往往对硬件结构和软件的配合没有概念,对片内存储空间、片外存储空间、片上外设这些概念没有实在的理解,这些概念需要自己的反复的思考、反复的实验、反复的体会才能最终搞清楚,这些弄明白了你也就入门了。
初学者比较忌讳看太多和太复杂的例程,看得太多你的思绪会比较乱,看得太复杂你会心浮气躁,复杂的例程一般它都有相对复杂的编程结构,这个初学者是很难体会到的,所以刚开始不要看,等你写了20到30个程序的时候再试着看相对复杂的例程。
3)多动手
这个不用多说了,光看不练假把式。
4)片上外设
这里拿DM642来说,我把常用的外设由简单到复杂排个序:GPIO-TIMER-EDMA-EMIF-I2C-MCASP-VideoPort-EMAC、MDIO,MCASP我没用过,不过看过资料感觉不复杂,我给初学者的建议是先把前面4个学清楚,可以先学GPIO这个真的是简单,刚开始不要急着用CSL,用汇编或是C写个程序让某个GPIO脚上输出波形,这样有助于理解片上外设以及有关的概念。前面4个明白了后面的具体用到再学,这个时候你可以看TI相应的例程,拿来用就可以。
5)汇编、C和线性汇编
现在开发6000的标准流程是先用C写,C的好处很多这里不说了,有太多的文章在论述,不过对于准备做优化的同志们来说,汇编不会也不行,用汇编相对于C更助于你理解6000的架构,很多初学者对C语言中用指针对某个空间操作不理解,用汇编写的话相对要好理解的多。
大家不必对汇编心存畏惧,其实它也很简单,只不过它比较晦涩,用它开发整个系统的时间上的花费太多,不过关键算法的优化有时还是离不开它,TI目前还提供线性汇编,它是汇编和C的折中,兼备汇编的效率和C的易开发性。
汇编和C都只是工具,关键还是你对架构的理解和编程理念,所以选择哪个都有道理,通过工具去探索架构而已。我个人觉得初学者主要应学习C,毕竟它是主流,可以用汇编写4-5个小程序,熟悉它的语法就行,日后用它做优化也不会什么都不知道,而且也助于对硬件架构的理解。
结束
就写这么多了,一家之言,里面有很多废话,希望对初学者有点帮助,抛砖引玉,也希望高手们多多写出自已的经验。
优化一起放过来了~~~
关于优化我的经验是这样的:
一、首先考虑从系统结构上优化,比如尽量减少待处理数据的无谓搬移,考虑你DSP片内存储量和每次处理数据量对系统结构优化,这部分的优化应该最早做;
二、其次从算法层面上着手,看采用的算法有没有更好更简单的计算方法,算法是否有某种对称性,可否采用更合适的数据结构等等,这方面的优化比程序上的优化更明显;
三、如果算法层面暂时无更好的优化办法,看看软件结构能否优化。
比如:
1)多层的循环结构能否减层。我经常看到这样的程序:
for(i = 0; i++; i< A)
for(j = 0; j++ j< B)
{
E
[j] = C[j] - D[j];
}
这个可以优化成:
for(i = 0; i++; i
{
E = C - D;
}
2) 关键循环结构中的条件、跳转指令应尽量避免,哪怕会增加一些循环次数,循环中没有条件指令优化器更容易优化;
3)关键循环不要调用子函数
其它还有一些,具体可以看看手册,手册上讲的很清楚
四、结合DSP系统的硬件结构优化
1)看你处理的数据是放在片内还是片外,如果放在片外的话这个建议将数据分块分批倒入片内处理,类似于流水结构;
2)针对外部数据可对L2 cache优化
五、结合DSP优化器、指令系统等进行优化
这部分可以详细的看TI的手册,大概有这几个方法:
1)优化选项,-o3 -pm 取消-g 等等这些选项,如果你的软件结构很好,那么它们的优化效果很明显;
2)加一些优化指示符指导优化,这部分看手册,包括存储地址无关性,SIMD(单指令多数据处理)等等;
3)用一些专用指令,比如6000提供饱和加、溢出减指令,可以不必用条件判断;
4)如果效果还是不好,用线性汇编改写你的程序,将你的优化思想用线性汇编表述出来,一般到地步就可以了;
5)如果线性汇编优化未能尽显你的优化思想,那就汇编吧,优化器不会再帮助你优化,完全是你自己控制程序了,自己做软件流水吧;
这部分需要有比较丰富的优化经验和扎实的优化功底,多多积累,多看资料。
最后要重点说下:
优化是没有止境的,在对程序对细致优化前要对程序每个部分测试下时间,对非常耗时的部分做优化,一但满足你的要求就可以,不要为了优化而优化,我们应该有更重要的东西要学,不要陷在优化上而不能自拔!!