嵌入式学习小组
直播中

孙成红

7年用户 1412经验值
私信 关注

学习DSP编程会遇见哪些问题?

学习DSP编程过程中经常遇到的问题有哪些

回帖(1)

李佳

2021-4-2 16:58:41
  29. 如果不需要printf()/sprintf()的全部特性,怎么样才能减小代码体积?
  初学者往往使用printf打印“Hello World”这样的方式来完成第一个DSP编程的程序,这种方法虽然是非常直观明了的,感觉起来功能也是非常简单的,但是一编译结果发现提示栈的空间不够,或者有“program will not fit into available memory”之类的错误。这是因为标准的printf()/sprintf()提供了非常多的特性支持,造成了在DSP上实现时,产生的代码尺寸非常大。
  此时我们可以根据需要调整不同级别的格式格式限定符,例如通过链接器的选项,我们可以指定--printf_support=full, minimal或者nofloat, full为默认参数,表示支持所有的格式;nofloat不支持对浮点类型的数据的输入/打印,包括%a,%A, %f, %F,%g,%G,%e和%E,支持其它的字符、定点格式等;minimal:对数据格式的最小支持,只包含了不指定数据宽度和精度标志的整形、字符型或者字符串,即只支持%%,%d,%o,%c,%s和%x格式。需要注意的是,如果--printf_support使用了不支持的格式,链接器并不能给出特定的实时运行库的错误提示,在使用时要仔细检查。
  此外,如果不去指定链接器选项,我们也可以修改printf函数默认对应的源程序_printfi.c来实现类似的效果,它的路径一般在编译器的库函数目录下,例如/ti/ccsv6/tools/compiler/c2000_6.2.5/lib/src。在此路径下,有3个printf函数对应的c程序,它们与链接器选项的对应关系如下表所示。DSP编程技巧之30---答疑解惑哪家强之(5)
  由此我们也可以看出,支持全部格式的printf的源程序的大小,达到了最小格式支持下源程序大小的23倍还要多。
  30. CCS编译器是否支持任何工业标准?
  1) 所有的TI DSP支持的C语言标准:
  C89 (ISO/IEC 9899:1990,或者叫NSI X3.159-1989)
  C99 (ISO/IEC 9899:1999)。 不完全支持。
  2) 不支持的C语言标准:
  C11 (ISO/IEC 9899:2011)
  3) 支持的C++标准:
  C++98 (ISO/IEC 14882:1998)
  C++03 (本质是C++98的bug修复)
  4) 不支持的C++标准:
  C++ TR1
  C++11 (ISO/IEC 14882:2011)
  5) IEEE-754 (ISO/IEC/IEEE 60559)标准:
  TI的ARM和DSP的C/C++编译器支持32位和64位的二进制浮点数运算,能够支持IEEE754标准中大部分特性。
  6) MISRA-C
  MISRA C是由汽车产业软件可靠性协会(MISRA,motor industry software reliability association)提出的C语言开发标准,在控制有关的代码中是非常有用的标准。
  7) 其它标准
  在工业领域中,safety安全特性在一些应用场合中已经是要求必须具备的功能了,相关的标准包括IEC61508、TÜV认证等。目前已经有一部分包含硬件safety特性的DSP器件了;如果使用软件来实现这些特性,则目前还需要我们自己来编写代码以支持这样的特征。
  31. CCS编译器对GCC扩展的支持如何?
  GNU编译器结合GCC支持许多标准ANSI/ISO C/C++所不支持的特性。在开源应用和Linux等开发中,GCC的编译器gcc和g++等都被广泛使用。所以为了保证对GCC工具所开发的代码的兼容性,TI的编译器也支持某些GCC的扩展特性。目前支持的一些特性基本都包含在GCC4.3中,可查看:http://gcc.gnu.org/onlinedocs/gcc-4.3.6/gcc/C-Extensions.html。
  32. 如何了解有关编译/代码产生工具的已知问题,并获得最新进展?
  老外喜欢用IBM的ClearQuest系统来报告bug并分享解决方案,我们可以使用TI提供的开放链接https://cqweb.ext.ti.com/cqweb/# 。.. t=HTML&version=cqwj来报告bug、查看/分享解决方案等,其界面如下图所示:DSP编程技巧之30---答疑解惑哪家强之(5)
  避开老旧的“传统”bug的最好办法当然是定期升级编译器和开发环境了。通过配置,新版本的CCS在启动后会自动检测升级并自动升级,这也简化了我们对开发环境的维护工作。
  33. 链接文件中包含那么多个段,有什么快速识别的方法?
  把下面这个例子记牢就好了:
  //
  // Global variables x & y ==》 .ebss
  // Initial values 2 & 7 ==》 .cinit
  //
  int x = 2;
  int y = 7;
  void main()
  {
  long z; // Local variable =》 .stack
  z = x + y; // Code =》 .text
  }
  34. 为什么我们需要链接文件.cmd?为何编译器不能自动分配存储空间并进行内存管理?
  在操作系统存在的情况下,这些工作确实不需要我们花费太多的心思。但是在嵌入式的DSP处理中,这样做的主要原因是处理能力和存储空间是十分有限的,必须要我们进行一定的介入,例如我们需要考虑的因素包括:
  1) 运行速度:在RAM中比在Flash中快,在Flash中又比在外部存储器(使用XINTF)中快。
  2) 代码是否需要存储在非易失的存储器中(例如Flash)?
  3) 任务是否是时间关键的?例如需要把某个时间关键的ISR被保存在Flash中,然后运行时复制到RAM里。
  4) 一些RAM可被DMA模块所访问,而另一些则不行。
  5) 使用单独的物理RAM模块来避免资源的冲突。例如,在C2000 DSP中,RAM模块都是在单个机器周期内只能访问一次的SARAM(Single-access RAM)。
  6) 资源是否位于外部存储器中?
  7) 代码是否需要保存在包含缓存或者预读的存储器中以提高性能?在C2000DSP中,我们几乎见不到缓存或者预读的概念,它们一般出现在包括ARM处理器的器件中。
  8) 存储器在程序空间、数据空间中是否具有等待状态?
  9) 是否有需要被代码安全模块CSM所保护的代码?CSM并不能保护所有的代码空间。
  以上这些因素,在我们编程时也是需要特别关注,甚至是较为头疼的事情,显然让编辑器去自动实现它们,在目前阶段是不可能的(除非编译器的算法有一天能实现一定程度的人工智能)。所以在现阶段,我们需要使用链接器命令文件cmd去描述每个段所需要使用的内存情况。
  如果我们没有把某一个特殊的或者自定义的段给指定到特定的存储空间中,则此时链接器会自动把它给分配到一个可用的存储空间里,这有可能会影响到程序的执行效果。所以我们要开启编译器的-w选项,这样在在未定义的输出段被创建时,开发环境的控制台窗口中会产生相关的警告信息。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分