编译指示(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是安全的(即打开之后的确都能履行),才干履行此操作。