DSP编程技巧之:不得不看的编译指示

发布者:喜茶我要七分糖最新更新时间:2014-12-21 来源: 互联网关键字:DSP  编程技巧 手机看文章 扫描二维码
随时随地手机看文章

  编译指示(Pragma Directives)可能是所有的预处理指令中最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对编译器给出了如何处理特定的函数、对象和代码段的方法,在保持与C/C++语言完全兼容的情况下,给出主机(比如C28x)或操作系统(比如DSP/BIOS)专有的特征。这些编译指示的使用较为复杂,但是我们还必须要了解它们,因为它们是程序中必不可少的东西,例如#pragma DATA_SECTION ( symbol , " section name ");这样的。但是往往讲解它们的资料又不多(因为大部分资料集中在入门指南上面),所以在此我们就总结一下针对C28x编译器的pragma指令,再遇到它们的时候就不会一头雾水了。

  1. CHECK_MISRA

  它的作用与在编译器选项中使用--check_misra是相同的,都是对特定源文件使能MISRA-C:2004规则检查(汽车工业软件可靠性联会),使用方法是:

  #pragma CHECK_MISRA (" {all|required|advisory|none|rulespec} ");

  其中的rulespec是具体MISRA中的规则,使用方法请参考DSP编程技巧之12-揭开编译器神秘面纱之代码规范MISRA-C。

  2. CLINK

  CLINK指令可用于某段代码或者某个数据符号,使用之后会在包含被作用符号的段中产生一个.clink指示,表明在条件链接的情况下,如果这个段没有被其它任何段引用的话,这个段可以被移除,从而减小链接输出文件的尺寸。使用方法是:

  #pragma CLINK (symbol )

  3. CODE_ALIGN

  CODE_ALIGN用来沿着特定的对齐参数constant来对齐函数(从而可以让CPU更快寻址,更快执行指令)。当我们希望函数从特定的边界开始的时候,这个指令非常有用。参数constant必须是2的幂(偶数对齐),使用方法是:

  C代码: #pragma CODE_ALIGN ( func, constant );

  C++代码: #pragma CODE_ALIGN ( constant );

  注:在本文中,在C和C++代码中,指令使用方法一样时,不分别写出,如不一样则分C代码和C++代码分别写出。C代码中的#pragma指令一般需指定函数名,也即其作用域;C++代码中的#pragma指令一般不带有函数名,其作用域为紧邻该指令后面的函数;下同。

  4. CODE_SECTION

  CODE_SECTION是较为常见的指令,默认情况下,代码被存放在.text段中,使用此指令则用来指定并改变某段代码所分配的段,其使用方法是:

  C代码: #pragma CODE_SECTION (symbol , "section name ")

  C++代码: #pragma CODE_SECTION (" section name ")

  例如:

  char bufferA[80];

  char bufferB[80];

  #pragma CODE_SECTION(funcA, "codeA")

  char funcA(int i);

  char funcB(int i);

  void main()

  {

  char c;

  c = funcA(1);

  c = funcB(2);

  }

  char funcA (int i)

  {

  return bufferA[i];

  }

  char funcB (int j)

  {

  return bufferB[j];

  }  5. DATA_SECTION

  DATA_SECTION可能是使用最多的pragma指令了,它用来定义存储某个符号所使用的段,使用方法是:

  C代码: #pragma DATA_SECTION ( symbol , " section name ");

  C++代码: #pragma DATA_SECTION (" section name ");

  例如:

  #pragma DATA_SECTION(bufferB, "my_sect")

  char bufferA[512];

  char bufferB[512];

  6. 与诊断信息有关的Pragma

  诊断信息一般包括:提醒,警告,错误和不提示等几个级别,使用与诊断信息有关的Pragma和使用相关的编译器选项的结果是一样的,其使用方法以及们的对应关系如下:

  Pragma对应的编译器选项

  有关诊断信息的含义,请参考DSP编程技巧之7---揭开编译器神秘面纱之预处理与诊断。

  7. FAST_FUNC_CALL

  使用这个指令,会在编译时调用快速汇编指令FFC,而不是传统的CALL指令来完成函数的跳转,其使用方法是:

  #pragma FAST_FUNC_CALL ( func );

  它的使用范围是受限的:仅限于调用返回LB *XAR7指令的汇编程序。例如:

  ;汇编程序

  _add_long:

  ADD ACC, *-SP[2]

  LB *XAR7

  //调用汇编的C程序

  #pragma FAST_FUNC_CALL (add_long);

  long add_long(long, long);

  void foo()

  {

  long x, y;

  x = 0xffff;

  y = 0xff;

  y = add_long(x, y);

  }

  除此之外,如果使用该指令,编译器会输出警告信息,并忽略其指示。

  8. FUNC_EXT_CALLED

  在我们启用程序级别的优化选项时(-O3),所有未直接或者简介被main函数调用的函数都将被优化掉,但是这些函数也有可能被我们定义的某些汇编代码使用到,所以使用FUNC_EXT_CALLED可以在编译时保留这些代码,其使用方法是:

  C代码: #pragma FUNC_EXT_CALLED ( func );

  C++代码: #pragma FUNC_EXT_CALLED;  9. FUNCTION_OPTIONS

  使用这个选项可以在编译C/C++代码中的某些函数时,使用额外的编译器的命令行选项,实现与在命令行中输入相关的命令同样的效果。其使用方法是:

  C代码: #pragma FUNCTION_OPTIONS ( func, "additional options" );

  C++代码: #pragma FUNCTION_OPTIONS( "additional options" );

  10. INTERRUPT

  使用这个选项可以在C代码中直接操作中断,其使用方法是:

  C代码: #pragma INTERRUPT ( func );

  C++代码: #pragma INTERRUPT ;

  被该指令直接操作的函数将使用IRP(中断返回指针)来返回值。

  在使用FPU时,中断分为两种:高优先级中断HPI和低优先级中断LPI,其中HPI使用快速的上下文存储机制,不能被嵌套,LPI则与普通的C28x中断机制一样,并且可以被嵌套。此时可以增加第二个参数来控制:

  C代码: #pragma INTERRUPT ( func , {HPI|LPI} );

  C++代码: #pragma INTERRUPT ( {HPI|LPI} );

  在DSP/BIOS和SYS/BIOS HWI对象中,不能使用INTERRUPT指令,因为Hwi_enter/Hwi_exit宏和Hwi解包器已经包含了该函数,此时使用该指令会产生负面的效果。

  11. MUST_ITERATE

  使用这个指令的情况下,我们确信某个for循环能够执行指定的次数。使用这个指令能够帮助编译器确定循环的次数和最佳的实现方式,从而减小代码的尺寸。其使用方法是:

  #pragma MUST_ITERATE ( min, max, multiple );

  min是循环的最小次数,max是最大执行次数,multiple则是循环次数的整数倍,如果这其中某个参数不存在,则可以省略,例如:

  #pragma MUST_ITERATE(5); /* 最少循环5次 */

  #pragma MUST_ITERATE(5, , 5); /* max参数省略;循环次数是5的倍数次(至少1倍) */

  pragma MUST_ITERATE(8, 48, 8);

  /* 循环此时可能为8, 16, 24, 32, 40, 48 */

  12. NO_HOOKS

  该指令阻止在调用函数时自动产生进入钩子和退出钩子,使用方法是:

  C代码: #pragma NO_HOOKS ( func );

  C++代码: #pragma NO_HOOKS;  13. RESET_MISRA

  顾名思义,这个指令会把MISRA-C:2004规则检查恢复到它原先的设定状态。例如,某条规则在命令行里被使能,但是在某段代码中被屏蔽了(某些原因导致它无法通过规则检查),使用该指令会规则检查重新使能。使用方法是:

  #pragma RESET_MISRA (" {all|required|advisory|rulespec} ")

  14. RETAIN

  使用这个指令,可以避免某些符号在条件链接时被优化掉,从而在输出文件中保留它。使用方法是:

  #pragma RETAIN ( symbol )

  这个指令与我们的第二条,CLINK的效果是整好相反的。

  15. SET_CODE_SECTION与SET_DATA_SECTION

  这两条指令用来设置其后所有声明的段。使用方法是:

  C代码: #pragma SET_CODE_SECTION ("section name")

  C++代码: #pragma SET_DATA_SECTION ("section name")

  例如:

  #pragma SET_DATA_SECTION("mydata")

  int x;

  int y;

  #pragma SET_DATA_SECTION()

  其中的x和y都被会放入我们指定的段mydata中,直到我们使用空参数SET_DATA_SECTION(),之后的代码或数据才会被放入默认的段之中。

  16. UNROLL

  UNROLL是“摊开”的意思,这个指令与for/while相关,意思是把n次的循环给展开,从而有个n份同样的代码。循环展开,是一种牺牲程序的尺寸来加快程序的执行速度的优化方法。可以手动编程完成,也可由编译器自动优化完成。循环展开通过将循环体代码复制多次实现。循环展开能够增大指令调度的空间,减少循环分支指令的开销。循环展开可以更好地实现数据预取技术。其使用方法是:

  #pragma UNROLL( n );

  只有在编译器认为n是安全的(即展开之后确实都能执行),才能执行此操作。

关键字:DSP  编程技巧 引用地址:DSP编程技巧之:不得不看的编译指示

上一篇:一种基于DSP的MIMO系统空时编码盲识别方法
下一篇:DSP编程技巧之:编译流程与处理器选项

推荐阅读最新更新时间:2024-05-02 23:23

用TL16C752B实现DSP和PC机的串行通信
摘要:介绍了TL16C752B的特点、性能和相关寄存器,给出了通过TL16C752B实现TMS320VC5421和PC机实时通信的方法。同时给出了串口通信部分的硬件应用电路图以及对TL16C752B进行初始化的软件实现程序。 关键词:数字信号处理;通信接口;异步通信;TL16C752B;TMS320VC5421 1 引言 美国德州仪器公司(TI)的TMS320VC54XX系列DSP芯片与PC机实现异步通信通常有两种方法:第一种是使用通用I/O信号XF和BIO作为串口发送和接收信号,用软件逐位发送和接收数据,即软件异步通信方法,这种方法需要占用很多CPU时间,因此,只能在DSP不太忙、实时性要求不高的情况下采用;第二种是通过扩
[嵌入式]
WCDMA系统基带处理的DSP+FPGA实现方案
  摘 要: 本文在分析WCDMA系统基带处理方案的基础上,结合DSP和FPGA性能的比较,提出了一种在性能、灵活性和性价比上都比较理想的DSP+FPGA基带发送的实现方案。   关键词: 第三代移动通信;WCDMA;基带处理;DSP;FPGA   引言   随着Internet的迅猛发展和各种无线业务需求的增加,目前以承载单一话音业务为主的无线通信网已经越来越不适应人们的需要,所以,以大容量、高数据率和承载多媒体业务为目的的第三代移动通信系统(IMT-2000)成为无线通信的发展方向。码分多址(CDMA)技术凭借其良好的抗噪性、保密性和低功率等优点成为第三代移动通信中最主要的多址接入技术。   和传统的CDMA系统相比,
[手机便携]
采用DSP和STM32的双核智能电液伺服控制器
  伺服控制系统大部分都采用传统的硬件结构,控制算法比较固定,而且也无法实现不同工况下的高性能控制算法,难以满足现代工业的需求。现阶段迫切需要研制一种智能型、具有高可靠性、控制性能更加优秀的电液伺服系统。基于DSP与STM32的智能型伺服控制器具有软硬件结合程度更加紧密、系统的智能化程度更高、可实现多种控制策略的优势。本系统从实际的需求出发,结合精确数字PID控制算法和Fuzzy控制算法自身的优势,组合成Fuzzy-PID控制算法,根据偏差的大小范围选择合适的控制算法进行调节。   本设计将两款工控芯片—TI公司的浮点型DSP TMS320F28335和ST公司的ARM7升级版STM32F103RET6引入智能电液伺服系统,设计
[单片机]
采用<font color='red'>DSP</font>和STM32的双核智能电液伺服控制器
面向DSP的电源解决方案
前言 本文描述了一种简单的电源解决方案。它采用同步降压转换控制器,如TPS56100、TPS5210、TPS56xx和TPS5602,面向TI的C6000 DSP应用。同时,本文列举了三种电源解决方案:单电压输入系统(5V或12V)、双电压输入系统(5V和12V)和宽输入电压范围系统(4.5V~25V)。 DSP对电源的要求 TIDSP家族(C6000和C54xx)要求有独立的内核电源和I/0电源。虽然TI的DSP不要求内核电源和I/O电源之间有特殊的上电顺序,但是假如有一个电源低于正常的工作电压,设计时要确保没有任何一个电源在任何时间段处于上电状态。如果违反此规则,将严重影响器件的长期可靠性。另外从系统级考虑,例如
[电源管理]
基于DSP 内嵌ECAN模块的总线接口设计
  0 引言   CAN 总线以其可靠、实时、低成本优势已在汽车、机械等工业控制领域广泛应用。TMS320F2812是TI公司最具代表性的低成本、低功耗和高性能的定点DSP芯片,具有强大的事件管理能力和嵌入式控制能力。其内嵌的增强型CAN 总线控制器(ECAN)模块,完全兼容CAN 2.0B 协议,邮箱数量增加至32 个,并增加了时间戳、消息过滤和超时发送功能,提高了应用CAN通信的灵活性。   ADM3053是ADI公司2011年推出一款集成信号和电源隔离功能的CAN 收发器。本文采用集成ECAN 模块的TMS320F2812 和ADM3053 来设计CAN 节点。该设计将内嵌ECAN模块的DSP作为节点主控制器,同时采
[嵌入式]
一“芯”二用,MCU+DSP处理器大盘点
  近年来,越来越多的领域需要用到高性能,高集成度的DSP器件,功能日益增加的多媒体处理器对DSP的需求也日益剧增,于是,基于MCU+DSP架构的集成芯片也随之应运而生,更低的成本、更小的封装和更微的功耗所开辟的,是一条属于DSP或者MCU厂商们的“阳光大道“而未来,它们还将沿着这条新路继续前行。本系列文章将为你介绍市面上比较流行的基于MCU+DSP架构的处理器或者解决方案。    飞思卡尔DSP56800E   飞思卡尔在DSP与MCU领域深耕数年,为满足市场发展需求,公司率先在56800内核基础上又推出了新一代增强型内核56800E,该产品可在单一内核上提供DSP和MCU双重功能。56800E 系列DSP将为不断增长的工业、
[嵌入式]
一“芯”二用,MCU+<font color='red'>DSP</font>处理器大盘点
基于PCI总线通用DSP信号处理系统的设计
1 引言 1.1 DSP简介及基本特点 数字信号的处理离不开算法和实现手段。数字信号处理器(digital signal processor简称DSP)。是在模拟信号变换成数字信号以后进行高速实时处理的专用处理器,是实现实时数字信号处理的有力工具。DSP目前广泛应用于模式识别,数字通信,信号处理,工业控制等领域。TI公司的TMS320C54X系列DSP有着以下的特点:采用先进的修正增强型哈佛结构,片内共有8条总线(1条程序存储器总线,3条数据存储器总线和4条地址总线);高度并行和带有专用硬件逻辑的CPU设计;高度专业化的指令系统;模块化结构设计;能降低功耗和提高抗辐射能力的新的静电设计方法。因此它能高速实时以及灵活地应用于图像
[嵌入式]
ARM/DSP双核系统的通信接口设计
引 言   嵌入式系统的核心是嵌入式微处理器和嵌入式操作系统。早期的嵌入式系统硬件核心是各种类型的8位和16位单片机;而近年来32位处理器以其高性能、低价格,得到了广泛的应用。近年来,又出现了另一类数据密集处理型芯片DSP。DSP由于其特殊的结构、专门的硬件乘法器和特殊的指令,使其能快速地实现各种数字信号处理及满足各种高实时性要求。随着现代嵌入式系统的复杂度越来越高,操作系统已成为嵌入式系统不可缺少的部分。免费的嵌入式操作系统,如Linux等,随着自身不断的改善,得到了飞速的发展。Linux是一个免费的、强大的、可信赖的、具有可伸缩性与扩充性的操作系统。Linux实现了许多现代化操作系统的理论,并且支持完整的硬件驱动程序、网络通
[嵌入式]
小广播
最新嵌入式文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved