首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

DSP学习心得

DSP学习心得

  一、弄清[size=+0]DSP[size=+0]相关资源的来源及熟读手册

  一般主要来源于[size=+0]DSP[size=+0]芯片厂商的官方网站,虽然现在的[size=+0]DSP[size=+0]芯片厂商都提供了中文的官方网站浏览,但我建议还是上英文的网站,其一,有些资源在中文网站上没有(关于这点,我个人认为可能是中文这边的资源未及时上传),其二,一般资料很少有中文版,中文和英文版网站上下载的其实是同一个版本;再就是,要熟悉[size=+0]DSP[size=+0]芯片厂商的官方网站,开发时允分利用官方提供的资源及支持能大大地提高开发效率;最后要注意的是,一般[size=+0]DSP[size=+0]芯片厂商会开放一个技术交流论坛,里面的管理员一般都是[size=+0]DSP[size=+0]芯片厂商的开发工程师,可以以发贴的形式获取他们的技术支持。

  还有一处资源的来源,就是跟[size=+0]DSP[size=+0]芯片厂商有合作的第三方公司(国内),这类公司跟[size=+0]DSP[size=+0]芯片厂商有很好的接触,一般相关的[size=+0]DSP[size=+0]芯片,他们都会先行做成教育开发板,这点当然主要用于教学,所以他们会有相关的中文资料及相应的[size=+0]demo[size=+0]程序,根据这点,可以很好的借鉴他们的经验及参考他们的资料及程序,其次,他们还会出售自制的仿真器,价格比原厂的会便宜,功能上肯定没有原厂出售的仿真器全面,但足以应对基本的项目开发。

  第三处仅供参照,占据国内市场最大的两家[size=+0]DSP[size=+0]厂商[size=+0]TI[size=+0]和[size=+0]ADI[size=+0]在中国都开设的相应级别的[size=+0]DSP[size=+0]培训课程,但费用昂贵,一般都是公司派遣前去学习。

  资源主要包含:

    [size=+0]Datasheet[size=+0](数据手册,主要大体介绍一下[size=+0]DSP[size=+0]芯片的功能,内部结构及外设,软件及硬件一些简单介绍,主要作用是可以很快速的了解这款[size=+0]DSP[size=+0])

    [size=+0]Software Tool Manuals[size=+0](这个手册主要介绍的[size=+0]DSP[size=+0]时钟、存储器、电源管理等等及所有外设的使用及注意事项,其实就是寄存器的配置,完全可以称之为[size=+0]DSP[size=+0]使用手册)

    [size=+0]Hardware Tool Manuals[size=+0](这个手册主要是官方提供的原理图[size=+0]PCB[size=+0]的绘制)、[size=+0]Program Manuals[size=+0](这个手册主要介绍编译器及内置[size=+0]C[size=+0]库的使用,汇编指令的使用及汇编语法的介绍,官方提供的仿真软件的使用)

     [size=+0]Engineer to Engineer Note[size=+0](工程师笔记,这个其实就是[size=+0]DSP[size=+0]芯片自己的工程师在开发这款[size=+0]DSP[size=+0]时所写的笔记,如果你有某个地方未明白,看相应的工程师笔记是最合适的)

    [size=+0]Program Examples[size=+0](主要是针对[size=+0]DSP[size=+0]不同的外设,官方提供的程序例子,包含[size=+0]C[size=+0]及汇编)

  二、官方仿真软件及仿真器的使用(如不使用,可暂时跳过,因为有些[size=+0]DSP[size=+0]可基于开源的操作系统进行开发,例如[size=+0]uClinux[size=+0])

  使用仿真软件的方法其实很简单,一般这种软件都设计成类似[size=+0]VC[size=+0]这种,你逐个去试每个菜单下的选项,此时你如配合[size=+0]Examples[size=+0]去使用,更能加深理解,不过我建议,做[size=+0]DSP[size=+0]软件开发,先简单看一下[size=+0]Datasheet[size=+0]、[size=+0]Software Tool Manuals[size=+0]和[size=+0]Program Manuals[size=+0]这三个文档再开始熟悉仿真软件的使用,当然在你熟悉时,肯定需要去不停的再去看这些文档的。仿真器的使用并没有什么需要注意的,一般的仿真器都做了仿呆处理,所以不会插反,仿真器一般都是配合仿真软件使用。(有一点要提醒的是一般[size=+0]DSP[size=+0]开发是基于[size=+0]C[size=+0]语言,如果不会[size=+0]C[size=+0]语言,请先学习[size=+0]C[size=+0]语言)

  三、[size=+0]DSP[size=+0]最小系统的配置

  这部分就正式开始使用[size=+0]DSP[size=+0]了,最小系统主要指[size=+0]DSP[size=+0]的时钟及存储器系统,这时你需要对照着[size=+0]Software Tool Manualsh[size=+0]去仔细看里面的介绍及相关寄存器的配置,结合[size=+0]Examples[size=+0]及[size=+0]Engineer to Engineer Note[size=+0],如果程序写完后,测试时钟其实很简单,用示波器直接去测量,看测量出来的时钟是否是你配置的那个数,紧接着就是测试存储器,这个测试必须写一段简单的小程序,其实主要就是测试数据总线是否能正常工作,如果在配置最小系统时出现问题,一般问题有二,一是寄存器未正确配置,解决方法是结合[size=+0]Examples[size=+0]及[size=+0]Engineer to Engineer Note[size=+0]仔细看手册,看例程,二是可能开发板上的硬件线路出了问题,解决方法是结合原理图,看线路上是否存在短路的问题,[size=+0]DSP[size=+0]工作电压是否正常等,这步可和硬件工程师一起去查。

  四、[size=+0]DSP[size=+0]外设的使用

  其实这部分和配置最小系统一样,只不过某些外设上可能连接了其它的芯片,不同的功能连接的芯片不一样,此时你需要去看这些芯片的资料,然后开始编写代码,然后再测试,测试方法根据不同的功能也会不同,不过[size=+0]DSP[size=+0]开发最常用的就是使用示波器,如有音视频方面的,可借助摄像头,显示屏等等之类的;如中间开发遇到问题,方法还是一样,结合[size=+0]Examples[size=+0]及[size=+0]Engineer to Engineer Note[size=+0]仔细看手册,看例程,有一点要注意,千万不能怀疑不能实现,要对自己有信心。

  五、[size=+0]DSP[size=+0]优化

  其实到这一步,你已经完全可以使用[size=+0]DSP[size=+0]了,接下来,你需要加深熟悉[size=+0]DSP[size=+0]的整个内部结构,主要包含有几个多少位的[size=+0]MAC[size=+0],有几个多少位的[size=+0]ALU[size=+0],有几个多少位的数据寄存器等等,还有外部数据总线上连接了哪些外设,内部数据总线是怎么连接的,并且这些数据总线是多少位,这些在[size=+0]Datasheet[size=+0]会有一张很清楚的[size=+0]DSP[size=+0]结构图,还有[size=+0]DSP[size=+0]的整个[size=+0]Memory Map[size=+0]是怎样的,片上有多少[size=+0]Data Memory[size=+0],有多少[size=+0]Program Memory[size=+0]等等,了解这些其实就是让你知道[size=+0]DSP[size=+0]的运算性能到底可以达到多少,哪些外设会通过外部数据总线传输数据,[size=+0]DSP[size=+0]内部的寄存器是怎么传输数据的,通过这些可以帮助你解决你在开发中遇到的问题,不过最主要的是帮助你对已经编写完成的代码进行优化,我个人认为的优化方法有以下几种:

  [size=+0]1[size=+0]、一般编写代码首先是用[size=+0]C[size=+0],基于[size=+0]C[size=+0]层面优化的方法,我如下举例说几种:

    ([size=+0]1[size=+0])优化循环

    [size=+0]for(i = 0;i < max;i ++)

     [size=+0]{

        [size=+0]for(j = 0; j < max; j ++)

        [size=+0]{

            [size=+0]float sum = 0.0;

            [size=+0]for(k = 0; k < max; k ++)

            [size=+0]{

                [size=+0]sum += input[i * max + k] * input[j * max + k];

            [size=+0]}

            [size=+0]cover[i * max + j] = sum / max;

        [size=+0]}

    [size=+0]}

    实例,如[size=+0]input[16] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}[size=+0],得出的[size=+0]cover[size=+0]如下:

     [size=+0]7    17   27   37

     [size=+0]17  43   69   95

     [size=+0]27  69  111  153

     [size=+0]37  95  153  211

    图示:

    

    原理:只需要得到左上角或右上角即可,然后半个矩阵赋值给另半个矩阵即可得到整个矩阵。

    算法优化后:

    [size=+0]for(i = 0; i < max; i ++)

    [size=+0]{

        [size=+0]for(j = i; j < max; j ++)[size=+0]                  [size=+0]// [size=+0]减少一半循环

        [size=+0]{

            [size=+0]float sum = 0.0;

            [size=+0]for(k = 0; k < max; k ++)

            [size=+0]{

                [size=+0]sum += input[i * max + k] * input[j * max + k];

            [size=+0]}

            [size=+0]cover[i * max + j] = sum / max;

            [size=+0]if(i != j)[size=+0]                    [size=+0]// [size=+0]可加可不加,消除中线上的重复赋值

            [size=+0]{

                [size=+0]cover[j *max + i] = sum / max;[size=+0]       [size=+0]// [size=+0]赋值给另半个矩阵

            [size=+0]}

        [size=+0]}

    [size=+0]}

    ([size=+0]2[size=+0])条件跳转(使用条件跳转会在流水线中浪费更多的周期)

    [size=+0]k = k -1;

    [size=+0]if(k < -1)

    [size=+0]{

        [size=+0]k = -1;

    [size=+0]}

    原理:[size=+0]C[size=+0]语言中的[size=+0]max[size=+0]函数在编译的过程中实际上实现的是[size=+0]DSP[size=+0]中的[size=+0]MAX[size=+0]指令。

    优化后:

    [size=+0]k = max(k-1, -1);

    转换成汇编后:

    [size=+0]R0 += -1;[size=+0]    [size=+0]// R0 == k;

    [size=+0]R1 = -1;

    [size=+0]R0 = MAX(R0, R1);

    ([size=+0]3[size=+0])[size=+0]for[size=+0]循环中的条件跳转

    [size=+0]for

    [size=+0]{

        [size=+0]if{...}else{...}

    [size=+0]}

    原理:减少频繁的条件跳转,当然并不是所有的情况都可以这样做。

    优化后:

    [size=+0]if

    [size=+0]{

        [size=+0]for{...}

    [size=+0]}

    [size=+0]else

    [size=+0]{

        [size=+0]for{...}

    [size=+0]}

    ([size=+0]4[size=+0])使用断言指令来避免条件跳转

    [size=+0]if(A)

    [size=+0]{

        [size=+0]X = exp1;

     [size=+0]}

    [size=+0]else

    [size=+0]{

        [size=+0]X = exp2;

    [size=+0]}[size=+0]    

    原理:使用断言指令[size=+0]IF(CC) REG = REG[size=+0],只会消耗一个周期。

    优化后:

    [size=+0]X = exp1;

    [size=+0]if(!A)

    [size=+0]{

        [size=+0]X = exp2;

    [size=+0]}

    ([size=+0]5[size=+0])除法(取模)操作

    一般[size=+0]DSP[size=+0]中不支持除法,除法操作是通过仿真的方式来进行实现,有两种,分为低精度和高精度,但都需要相大多的周期。

    除数为[size=+0]2[size=+0]的[size=+0]N[size=+0]次方时可采用右移法。

    如为提高性能,可采取查表的方式,这样会损失精度。

    隐藏的除法:

        [size=+0]for(i = start; i < finish; i += step)

        此时编译器会[size=+0]looper = (finish - start) / step [size=+0]得到次数。

    巧妙利用不等式法测:(不过可能会产生溢出,要小心使用)

        [size=+0]if(x / y > a / b)

        可转换为[size=+0]:

        [size=+0]if(x * b  > a * y)

    ([size=+0]6[size=+0])数据类型

    对于定点[size=+0]DSP[size=+0]而言,对于浮点的操作是用仿真的方式实现的,会消耗很多周期,所以在定点[size=+0]DSP[size=+0]上对于浮点数一般是做定点化的处理,常用的方法我举一个例子:[size=+0]2.5 * a[size=+0],其实可以转换成[size=+0]80 * a >> 5[size=+0],不过在定点化时需要注意防溢出。

    对于[size=+0]64[size=+0]位数据,也是用仿真的方式实现的,会消耗很多周期。(一般最大仅支持[size=+0]32[size=+0]位数据)

    做数字信号处理操作时,如[size=+0]FFT[size=+0],[size=+0]16bit[size=+0]的操作是比较合适的。

    要做控制类,条件跳转时,[size=+0]32bit[size=+0]的操作是比较合适的。

    如你的[size=+0]DSP[size=+0]的[size=+0]MAC[size=+0]是[size=+0]16[size=+0]位的,做乘法时,尽量定义成[size=+0]16bit[size=+0]数据。

    ([size=+0]7[size=+0])[size=+0]Memory[size=+0]分配

    将运算比较频繁的数据和程序段放入片内[size=+0]Memory[size=+0],开启[size=+0]cache[size=+0]。

    如[size=+0]DSP[size=+0]能对[size=+0]SDRAM[size=+0]的不同[size=+0]4[size=+0]个[size=+0]bank[size=+0]可以同时访问,此时你可以将需要同时运算的数据放入不同的[size=+0]bank

    ([size=+0]8[size=+0])开启仿真软件的编译优化选项

    在菜单相应的地方勾上即可,但值得注意时,开启自动编译优化选项后,可能会使执行的结果发生变化,所以需要测试对比一下未开编译优化选项之前的执行结果,一般来说,这个很方便,比较常用。

    以上[size=+0]8[size=+0]种是我常用到的优化方法,当然基于[size=+0]C[size=+0]层面算法类的优化还有很多种,这个需要慢慢积累,总结一下,一般来说先对[size=+0]C[size=+0]层面进行结构上的优化(上面的[size=+0]1-6[size=+0]均属于),然后进行[size=+0]Memory[size=+0]分配,开启仿真软件的编译优化选项,将运算频繁的程序段用汇编实现,当然如果性能满足要求,就没必要利用汇编了。

  六、总结

  我认为学习[size=+0]DSP[size=+0]软件开发没有什么捷径,我花了大量的文字在[size=+0]“[size=+0]弄清[size=+0]DSP[size=+0]相关资源的来源及熟读手册[size=+0]”[size=+0]上,实际上是想说,懂得获取资源是很关键的,只有熟悉手册才能完全去使用你所要开发的[size=+0]DSP[size=+0]芯片,其次[size=+0]DSP[size=+0]的主要特点就是高性能,能做一些算法类的运算,所以[size=+0]DSP[size=+0]的优化是相当重要的,关于算法优化的方法有很多种,基本可分为[size=+0]C[size=+0]结构上的优化及利用[size=+0]DSP[size=+0]的特点来进行优化,优化的学习是日易积累的,所以就要多看看相关的资料了。

  快速入门的步骤如下:

  准备一开发板,简单熟悉一下手册及仿真软件,对照着例程看手册,然后再改例程,看是否能按你的意愿去实现,最小系统和每个外设都熟悉一边,恭喜你,你入门了,待续。。。
返回列表