第 5 章 c54x 高级 c 语言程序设计

87
第5第 C54x 第第 C 第第第第第第 C54x 第第第第第第第第第第 第第第第第 C 第第 第第第第第第第第第 第第第第第第第 第第第第第 ,, , 第第第第第第第第第第第第第第第第 第第TMS320C54x Optimizing C_C++ Compiler User‘s Guide.pdf, SPRU103G 2002 TI 第第

Upload: finn-frazier

Post on 30-Dec-2015

302 views

Category:

Documents


1 download

DESCRIPTION

第 5 章 C54x 高级 C 语言程序设计. C54x 的程序设计有两种语言:汇编语言和 C 语言。. 汇编语言程序效率高,硬件定时准确,但不够直观 , 设计周期较长 , 可移植性和可维护性差. 参考: TMS320C54x Optimizing C_C++ Compiler User‘s Guide.pdf, SPRU103G , 2002 , TI 官网. 第 5 章 C54x 高级 C 语言程序设计. C 语言,可移植性好,可维护性好 ,可生成代码执行效率较高的可执行程序。. 第 5 章 C54x 高级 C 语言程序设计. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

C54x 的程序设计有两种语言:汇编语言和 C 语言。

汇编语言程序效率高,硬件定时准确,但不够直观 , 设计周期较长,可移植性和可维护性差

参考: TMS320C54x Optimizing C_C++ Compiler User‘s Guide.pdf, SPRU103G , 2002 , TI 官网

Page 2: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

C 语言,可移植性好,可维护性好 ,可生成代码执行效率较高的可执行程序。

Page 3: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

一般代码用高级语言编写,缩短开发周期,还可使汇编语言编写的程序被高级语言所调用。

Page 4: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

目录:

5.1 C54x C 语言介绍5.2 C54x C 语言编程5.3 C54x C 代码优化

Page 5: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.1 C54x C 语言介绍

1.C54x C 编译器支持开发的 C 语言标准,继承了大多数的 ANSI 的语法规则 。

2.ANSI C和 C54x C 也有许多不同之处 。

Page 6: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.1 C54x C 语言介绍

5.1.1 C54x C 与 ANSI C 的相同点

只要与硬件不是特别相关的部分都是它们的相同点。

Page 7: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.1.1 C54x C 与 ANSI C 的相同点

以函数作为基本单位。 函数的定义和引用方式完全一

致。 大部分变量、常量、数组、结构

体、枚举、联合体、指针的定义语法结构也完全一致。

Page 8: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.1.1 C54x C 与 ANSI C 的相同点

局部变量、全局变量、静态变量、动态变量等基本定义也一致。

宏定义、宏展开、宏调用的基本思想甚至语法规则上基本一致。

Page 9: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.1.1 C54x C 与 ANSI C 的相同点

1. 常量定义格式: const 类型 符号 = 数值 ;

例 5-1 : const short d1=8 ;

C54x C 也可以用下面的方法定义符号常量:#define Vmax 1 ; // 程序中出现 Vmax 时均

会 以1来代替

Page 10: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.1.1 C54x C 与 ANSI C 的相同点

2. 变量定义1) 一般变量的定义:格式: 类型 符号 ;2) 扩展变量的定义: struct, enum

3) 自定义变量的定义:格式: typedef 已有类型 新数据类型 ;

Page 11: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

1) 一般变量的定义:例 5-2 :char ch_1 ;// 定义一个字符变量,名字为 ch_1

short sh_1;// 定义了一个短整型变量,名字为 sh_1

long l_dat1;// 定义了一个长整型变量,名字为 l_dat1

int *pi_1 ; // 定义了一个指向整型数据的指针变量,名字为 pi_1

short sh_a[10] ; // 定义了一个短整型数组,数组的长度为 10

Page 12: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计2) 扩展变量的定义:struct str_t // 定义一个结构类型 str_t

{

short sh_a;

long l_b;

float f_c; };

struct str_t str_a; // 定义一个 str_t 型结构变量str_a 。enum TorF{false,true}; // 定义一个枚举变量 TorF

union un_v{char c;short s;int i;long l};// 定义了一个联合体变量 un_v 。

Page 13: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

3) 自定义变量的定义:例 5-3 :typedef unsigned short US_DATA ;

US_DATA ush_t;

等同于:unsigned short ush_t;

Page 14: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.1.1 C54x C 与 ANSI C 的相同点

3. 函数的定义和组织

C54x C 和 ANSI C 一样,整个程序有一

个主函数( main 函数)和零个或者多个子

函数构成。

Page 15: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

float sub_cac(float a, float b);// 子函数声明void main() // 主函数定义,整个程序内有且只有一个 {

float a=1;

float b=2;

float c;

c=sub_cac(a,b); // 子函数调用 … …

如下所示:

Page 16: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

While(1) // 死循环,等待外部事件发生 { }

}

float sub_cac(float e,float f)// 子函数定义 {

float g;

g=e*f;

return g;

}

Page 17: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.1.2 C54x C 与 ANSI C 的不同点

1. 所处理数据的性质不同2. 数据的输入输出设备不同 3.“ 死循环”的对待上不同4. 语法及数据结构细节上的不同

Page 18: 第 5 章   C54x 高级 C 语言程序设计

5.1.2 C54x C 与 ANSI C 的不同点

1. 所处理数据的性质不同

ANSI C 处理的数据类型采集好的、数据量较多的、以数据块为单位,实时性要求不高

C54x C 处理的数据类型有严格的实时性要求,要求对于数据的处理时间要小于数据的采样时间间隔。

Page 19: 第 5 章   C54x 高级 C 语言程序设计

5.1.2 C54x C 与 ANSI C 的不同点

2. 数据的输入输出设备不同

C54x C

实时采集数据,处理结果给其他计算机或者芯片(如 MCU 、 ARM 等)使用,或者通过 D/A 输出。

ANSI C

输入 : 硬盘、内存等存储介质或键盘、实时采集数据。输出是显示器、通信口或实时输出

Page 20: 第 5 章   C54x 高级 C 语言程序设计

5.1.2 C54x C 与 ANSI C 的不同点3.“ 死循环”的对待上不同

C54x C 程序在 main 函数将所有的初始化任务都完成后安排一个“死循环”语句,如:While(1){ } 。

ANSI C 程序程序内部出现“死循环”,或者程序的处理不当,解决的办法只有重启计算机。

Page 21: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

为什么“死循环”的对待上不同?

面向 PC 机的 ANSI C 程序属于应用程序,架构在操作系统,不和硬件直接打交道,对硬件的操作实际上是通过操作系统的系统调用配合相应的驱动程序来实现。

Page 22: 第 5 章   C54x 高级 C 语言程序设计

5.1.2 C54x C 与 ANSI C 的不同点

而面向 DSP 的 C54x C 程序一般不是架构在操作系统之上,对硬件的操作也都是直接的。

图 5-2 DSP 的软件结构

应用程序

硬件

图 5-1 PC 机的软件结构

应用程序

操作系统

驱动 /BSP

硬件

Page 23: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.1.2 C54x C 与 ANSI C 的不同点4. 语法及数据结构细节上的不同

1)C54x 的 C 语言数据类型及其表示范围

2)C54x 的 C 语言特有数据类型

3)DSP C 语言关于变量的特殊规定

Page 24: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

1 ) C54x 的 C 语言数据类型及其表示范围数据类型 字长 表示意义 最小值 最大值signed char 16 ASC‖ -32768 32767

unsigned char char 16 ASC‖ 0 65535

short, signed short 16 二进制补码 -32768 32767

unsigned short 16 二进制 0 65535

int, signed int 16 二进制补码 -32768 32767

unsigned int 16 二进制 0 65535

Page 25: 第 5 章   C54x 高级 C 语言程序设计

Long, signed long 32 二进制补码 -2147483648 2147483647

unsigned long 32 二进制 0 4294967295

enum 16 二进制补码 -32768 32767

float 32 IEEE-32bit 1.175494e-38

3.40282346e+38

double 32 IEEE-32bit1.175494e-

38 3.40282346e+38

long double32 IEEE-32bit

1.175494e-38 3.40282346e+

38

*( 指针类型)*(pointers )

16 IEEE-32bit 0x0000 0xFFFF

表 5.1 C54X 的编译器所支持的 C 语言数据类型数据类型 字长 表示意义 最小值 最大值

Page 26: 第 5 章   C54x 高级 C 语言程序设计

5.1.2 C54x C 与 ANSI C 的不同点

2)C54x 的 C 语言特有数据类型(1) 地址变量

C54x 的 C 语言编译器设置一种地址变量来实现对指定数据存储单元的访问。

地址变量实际上就是指定了具体地址值的指针变量。如:

volatile short *mcbsp0_drr10=0x10;

short sh_drr10_data;

sh_drr10_data = *mcbsp0_drr10;

Page 27: 第 5 章   C54x 高级 C 语言程序设计

2)C54x 的 C 语言特有数据类型(2) I/O端口变量

I/O端口变量的定义格式如下: ioport 数据类型 porthex_num ;

其中: ioport : 端口变量定义关键字 数据类型:只能是 char,short,int, unsigned 等 16 位的类型 hex_num :该 I/O端口的 16进制格式表示 的端口地址

Page 28: 第 5 章   C54x 高级 C 语言程序设计

ioport unsigned port10;

/* 定义地址为 10H 的 I/O端口变量 */

int func ( )

{

...

port10 = 20; /* write a to port 10H */

...

b = port10; /* read port 10H into b */

...

}

(2) I/O端口变量 举例

Page 29: 第 5 章   C54x 高级 C 语言程序设计

(3) 寄存器变量DSP 的 C 语言扩展了寄存器变量。在一个 C

函数内部最多可以使用两个寄存器变量,编译器在编译这两个寄存器变量时用 AR1 和AR6这两个辅助寄存器分别做了对应:

• AR1 被赋给了第一个寄存器变量;• AR6 被赋给了第二个寄存器变量;

2)C54x 的 C 语言特有数据类型

寄存器变量的定义格式:register type AR1 或 register type AR6

Page 30: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

(1) 变量的初值问题

ANSI C ( ISO C )语言规定:没有显式初

始化的变量都将初始化为 0 。

DSP 的 C 语言规定:没有显式初始化的变量

仍保持未初始化状态。

3 ) DSP C 语言关于变量的特殊规定

Page 31: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

(2) 有符号数的右移

DSP 的 C 语言规定,有符号数的右移

等价于算术右移

3 ) DSP C 语言关于变量的特殊规定

Page 32: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

(3) 除法和取余

DSP 的 C 语言做了如下规定: 10/-3==-3 ; 10%-3==1 ; -10/3==-3 ; -10%3==-1

即:余数的符号与被除数的符号保持一致。

3 ) DSP C 语言关于变量的特殊规定

Page 33: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

(4) 浮点数转换到整数

浮点数转换到整数时, DSP 的 C 语言采用朝0截止的方式,即简单地去掉分数部分 , 如: int a,b;

a=1.3; → a=1

b=-1.3; → b=-1

3 ) DSP C 语言关于变量的特殊规定

Page 34: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

(5) 多字符常量

标准 C 规定:字符用单引号括起来,其本质是代表一个整数,如: char c=‘r’;

3 ) DSP C 语言关于变量的特殊规定

Page 35: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

(5) 多字符常量

标准 C 还允许单引号内包含多个字符,通常取里面的第一个或最后一个字符有效,没有硬性规定。 TI公司的 DSP C 语言规定取最后一个字符有效

‘abc’ == ‘c’

3 ) DSP C 语言关于变量的特殊规定

Page 36: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

(6) 16 位数相乘

DSP C 语言规定:16 位数相乘,如果只想获得乘积结果的高16 位可通过把乘积结果右移 16 位来获得。

3 ) DSP C 语言关于变量的特殊规定

Page 37: 第 5 章   C54x 高级 C 语言程序设计

(6) 16 位数相乘3 ) DSP C 语言关于变量的特殊规定

DSP C 语言规定:16 位数相乘,如果只想获得乘积结果的高 16 位可通过把乘积结果右移 16 位来获得例 5-6 : int m1,m2,result1; unsigned m3,m4,result3; result1=((long)m1*m2)>>16; //16 位 *16 位结果应用 32 位表示 result3=((unsigned long)m3*m4)>>16;这里的 m1*m2 的中间结果作了强制 long转换,是为了防止有效数据位的丢失。

Page 38: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

汇编程序经过汇编将成为 COFF 格式的目

标文件,该文件将包含七个可以进行重新定

位的代码和数据段 :

5.2 C54x C 语言编程

已初始化段和未初始化段

1.C54x C 语言开发的段结构

5.2.1 C54x C 语言开发的存储器结构

Page 39: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

已初始化段:

①.text 段 — 包含了可执行代码; ②.cinit段 — 包含明显初始化的全局变量和静 态变量; ③ .const段 — 包含字符串常数和全局常量; ④ .switch段— 包含大型 switch 语句的跳转表

Page 40: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

未始化段:

⑤.bss 段 — 包含了未初始化的全局变量 和静态变量;⑥.stack段 — 定义软件堆栈⑦.sysmem段 — 为动态存储器函数malloc,calloc, realloc(这些函数由运行支持库提供 ) 分配存储器空间

Page 41: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

1) 已初始化段:1.C54x C 语言开发的段结构

在 DSP 上电时,系统初始化函数

( bootloader )会自动调用段 .cinit 的值

来初始化段 .bss, 如图所示

( 1 ) .cinit段

Page 42: 第 5 章   C54x 高级 C 语言程序设计

5.2.1 C54x C 语言开发的存储器结构

.cinit段实际上就包含了一些全局变量存放位置与其初始值的对应关系,也就是一些关于全局变量的记录。

显式初始化全局变量和静态变量的初始化过程

Page 43: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.2.1 C54x C 语言开发的存储器结构

例 5-7 :假设在 C 程序中定义了两个初始化变量: int a=45;

int b[5]={2,3,4,5,6};

则这两个变量的初始化信息如下: .sect “.cinit” ; 初始化段

Page 44: 第 5 章   C54x 高级 C 语言程序设计

5.2.1 C54x C 语言开发的存储器结构

.sect “.cinit” ; 初始化段******* 变量 a 的记录 *********** .word 1 ; 数据长度为 1 .word _a ; .bss 中的地址 .word 45 ; 数据******* 变量 b 的记录 ************ .word 5 ; 数据长度 5 .word _b ; .bss 中的地址 .word 2,3,4,5,6 ; 数据

int a=45int b[5]={2,3,4,5,6};

Page 45: 第 5 章   C54x 高级 C 语言程序设计

1.C54x C 语言开发的段结构

( 2 ) .switch段当C语言程序中有分支语句 Switch 时,如:   int i;   int function()   {    switch (i){     case 1:       return 1 ;       break;     default:       return 0;       break;       }   }

C 语音编译时将产生 .switch段。 该段记录了开关变量和相应开关值,以及需要执行的程序起始位置的对应关系。

Page 46: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

2 )未初始化段 (1).stack段.stack段定义了软件堆栈,用于函数调用、变量传递以及局部变量分配。堆栈大小由连接器选项设置,如 -stack 40 ,默认大小400h即 1k.注意: C 编译器并不提供检查堆栈溢出的手段,因此,必须保证有足够的空间用于堆栈,否则,发生溢出现象将破坏程序的运行环境,从而导致程序的瘫痪。

Page 47: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

2 )未初始化段( 2 ) .sysmem段.sysmem段用来为动态存储器函数malloc, calloc, realloc 分配存储器空间。大小由连接器选项设置,如 -heap 40 。

对于比较大的数据变量,一般利用这种动态分配的方式在 sysmem段中分配这些变量的空间,以便节省 .bss段的空间

Page 48: 第 5 章   C54x 高级 C 语言程序设计

3) 自定义段

(1) CODE_SECTION pragma其语法结构为:

#pragma CODE_SECTION(symbol,

“section name”)

(2) DATA_SECTION pragma

其语法结构为:

#pragma DATA_SECTION(symbol,

“section name”)

不同于 .text段

不同于 .bss段

Page 49: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

(3) FUNC_EXT_CALLED pragma

其语法结构为:

#pragma FUNC_EXT_CALLED(func)

注: pragma必须出现在对要保持的函数的任何声明或引用前。

3) 自定义段

保持没被 C 调用的函数不被优化掉。

Page 50: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

2.C54x C 语言开发的存储结构1 ) 段的存储器定位:

段名及段的类型 存储器类型 Page 类型

已初始化段

.cinit ROM or RAM 0

.const ROM or RAM 1

.text ROM or RAM 0

.switch ROM or RAM 0

Page 51: 第 5 章   C54x 高级 C 语言程序设计

未初始化段

.bss RAM 1

.stack RAM 1

sysmem RAM 1

命名段

CODE_SECTION ROM or RAM 0

DATA_SECTION RAM 1

表 5.2 C54X 的段存储器分配

段名及段的类型 存储器类型 Page 类型

Page 52: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.2.2 C54x C 语言开发的函数及其约定

1.C54x C 语言开发的寄存器约定规则2.C54x C 语言开发的函数调用规则3.C54x C 语言开发的标识符命名约定和混

合语言编程

参数传递规则

Page 53: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.2.2 C54x C 语言开发的函数及其约定

1.C54x C 语言开发的寄存器约定规则

编译器的寄存器约定规则规定了在函数内如何使用寄存器,以及在函数之间相互调用时如何保存(或称为保护)这些寄存器的值。

寄存器值的保存分成两种基本类型,即:入口保存和调用保存。

Page 54: 第 5 章   C54x 高级 C 语言程序设计

寄存器名 用途 入口保存 调用保存

AR0 指针和表达式 No Yes

AR1 指针和表达式 Yes No

AR2 - AR5 指针和表达式 No Yes

AR6 指针和表达式 Yes No

AR7 指针和表达式 ,

局部帧指针 ( 当需要时 )

Yes No

C54x  C 编译器的寄存器约定

Page 55: 第 5 章   C54x 高级 C 语言程序设计

寄存器名 用途 入口保存 调用保存C54x  C 编译器的寄存器约定

A 表达式 , 第一个入口参数,函数返回结果

No Yes

B 表达式 No Yes

SP 堆栈指针 † †

T 乘和移位表达式 No Yes

ST0, ST1 状态寄存器 有一定的状态

要求

BRC Block repeat

counter No Yes

† The SP is preserved by the convention that everything pushed on the stack is popped off before returning.

Page 56: 第 5 章   C54x 高级 C 语言程序设计

表 5.4 C54x  C 编译器的状态寄存器约定

状态寄存器的域 名称 约定值

编译器生成的程序是否对

其更改

ARP Auxiliary register

pointer 0 Yes

ASM Accumulator shift

mode - Yes

BRAF Block repeat

active bit - No

C Carry bit - Yes

C16 Dual 16-bit math

bit 0 No

Page 57: 第 5 章   C54x 高级 C 语言程序设计

表 5.4 C54x  C 编译器的状态寄存器约定

状态寄存器的域 名称 约定值 编译器生成的程

序是否对其更改

OVM Overflow mode 0 Only with intrinsics

SXM Sign extension mode - Yes

SMUL Saturate-multiply bit 0 Only with

intrinsics

SST Saturate-store bit 0 No

TC Test control bit - Yes

Page 58: 第 5 章   C54x 高级 C 语言程序设计

表 5.4 C54x  C 编译器的状态寄存器约定状态寄存器

的域 名称 约定值 编译器生成的程序是否对其更改

CMPT Compatibility

mode bit 0 No

CPL Compiler mode bit

1 No

FRCT Fractional mode bit

0 No

OVA Overflow flag

for A - Yes

OVB Overflow flag

for B - Yes

Page 59: 第 5 章   C54x 高级 C 语言程序设计

5.2.2 C54x C 语言开发的函数及其约定2.C54x C 语言开发的函数调用规则 例:假定有一个函数 function1 (不是 main 函数,更具有代表性),它接收了调用者(比如说是 main 函数)传递给它的参数,它自己有自己的局部变量,它还要调用另一个函数 function2 , function1 也需要传递参数给 function2 ,并从 function2 中返回计算结果。其调用关系是:main( )→funciton1(… )→function2(…)

Page 60: 第 5 章   C54x 高级 C 语言程序设计

函数调用前后的堆栈使用情况

main( )→funciton1(… )→function2(…)

Page 61: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

3.C54x C 语言开发的标识符命名约定和混合语言编程

C 编译器在编译C语言程序时,会自动在所有标识符(函数名、变量名等)之前加下划线“ _” ; 若希望 C 语言程序能够调用汇编语言定义的标识符,应将该标识符定义成开头为“ _x” 的标识符,而在C语言程序中调用该标识符时要去掉该标识符如 x 来调用。

C54X C 语言标识符命名约定。

Page 62: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

3.C54x C 语言开发的标识符命名约定和混合语言编程

汇编程序和C语言程序一般都是在两个不同的文件之中的,在不同文件中的变量或者函数的应用,必须加以全局说明。

如果在 C 程序中定义的变量 ( 或函数 )需要在汇编中访问,则应该在汇编中用 .global或 .ref 声明为全局引用标识符。

Page 63: 第 5 章   C54x 高级 C 语言程序设计

在 C 程序中访问汇编程序变量或函数 :汇编程序: .bss _var, 1 ;定义变量 .global _var ;说明为外部变

量C 程序: extern int var; /* 外部变量 */ var= 1; /*访问变量 */ 若要在汇编程序中访问 C 程序变量或函数,

也可以采用同样的方法。C 程序: int var; /* 全局变量 */ main() { … }

第 5 章 C54x 高级 C 语言程序设计

Page 64: 第 5 章   C54x 高级 C 语言程序设计

在汇编程序中访问 C 程序变量或函数 :

C 程序: int i; /* 定义 i 为全局变量 */

float x; /* 定义 x 为全局变量 */

main( )

{ …. }

汇编程序: .ref _i; ; 说明 _i 为外部变量 .ref _x; ; 说明 _x 为外部变量 LD @_i, DP

STL _x, A

Page 65: 第 5 章   C54x 高级 C 语言程序设计

4) 在 C 中使用内嵌( inline )汇编 :

在 C 语言程序的相应位置直接嵌入汇编语句,这是一种 C 和汇编之间比较直接的接口方法。 嵌入汇编语句的方法比较简单,只需在汇编语句的左、右加上一个双引号,用小括弧将汇编语句括住,在括弧前加上 asm 标识符即可,如下所示: asm(“ 汇编语句 ” ) ; 功能是控制 C 语言难以实现的 DSP 芯片的一些硬件资源;优化程序。

Page 66: 第 5 章   C54x 高级 C 语言程序设计

5.2.3 C54x C 语言中断处理函数的实现

对于使用 C 语言编程的 DSP应用程序,应该尽量使用 C 语言编写中断处理函数。

1) c_int d 函数 C 编译器约定,任何具有名为 c_int d

的函数 (d 为 00~09) 都被假定为一个中断程序。 其中 c_int00 是 rts.lib库函数中定义的系统

复位中断处理程序,完成系统上电初始化。

1.C 语言中断函数的定义C 语言中断函数的定义有两种实现方法

Page 67: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

如: void c_int01()

{

……

}

该方法定义的中断处理函数数目较少(只有 9 个),另外,函数名称与其功能的对应关系不够直观。

Page 68: 第 5 章   C54x 高级 C 语言程序设计

5.2.3 C54x C 语言中断处理函数的实现2)interrupt 函数定义的另一种方法就是利用 interrupt 关键字,将该关键字后面所定义的函数声明为中断函数。

如下所示: interrupt void isr() { …… }void 既可放在 interrupt前面,也可放在 interrupt 后面。这种方法,可以对每种中断服务函数的功能起个直观的名字,同时,中断服务函数的个数也没有严格的限制。

Page 69: 第 5 章   C54x 高级 C 语言程序设计

5.2.3 C54x C 语言中断处理函数的实现

2. 关于 C 语言中断函数的说明

1.中断函数的返回类型必须是 void 类型,并且不能有参数。

2.对于中断函数来讲,所有自己用到的寄存器包括状态寄存器和累加器都需要保护

3. 在返回时中断函数使用的是 RETE ,而一般函数使用的是 RET 。

4. 中断函数不能被普通的 C 代码直接 调用。

Page 70: 第 5 章   C54x 高级 C 语言程序设计

2. 关于 C 语言中断函数的说明

5.进入中断服务函数时,要求 SP 的内容是偶数。

6. 一个中断程序可以处理一个或多个中断。 7. 中断处理和具体某种中断的联系,由中断向

量表来声明。8. 在汇编语言中,需要访问这些中断处理函数

时,不要忘记在函数名前加上“ _” 。9. 中断程序和它们调用的任何函数都不能由 -oe命令选项(认为不存在中断)进行编译。

Page 71: 第 5 章   C54x 高级 C 语言程序设计

例 5-11 C 语言外部中断 0 的中断处理函数和中断向量表

中断向量表处理 : .sect ".vectors" .ref _c_int00

.ref _int_INT0

.align 0x80 RESET: BD_c_int00 STM #128,SP NOPNMI: RETE NOP NOP NOP

中断处理函数: interrupt void int_INT0() { …. }

sint17 .space 4*16sint18 .space 4*16sint19 .space 4*16sint20 .space 4*16sint21 .space 4*16sint22 .space 4*16sint23 .space 4*16sint24 .space 4*16sint25 .space 4*16sint26 .space 4*16sint27 .space 4*16sint28 .space 4*16

Page 72: 第 5 章   C54x 高级 C 语言程序设计

例 5-11 C 语言外部中断 0 的中断处理函数和中断向量表

中断向量表处理 :sint29 .space 4*16sint30 .space 4*16int0: B _int_INT0 NOP NOP NOPint1: RETE NOP NOP NOPint2: RETE NOP NOP NOP

tint: RETE NOP NOPrint0: RETE NOP NOP NOPxint0: RETE NOP NOP NOPrint1: RETE NOP NOP NOP

xint1: RETE

NOP NOP

NOPint3: RETE

NOP NOP

NOP .end

Page 73: 第 5 章   C54x 高级 C 语言程序设计

3. C 语言中断函数 c_int00 的作用

C 程序开始运行时,必须首先初始化 C运行环境,这是通过 c_int00 函数完成的,这个函数在运行支持库 rts.lib 中。连接器会将这个函数的入口地址放置在复位中断向量处,使其可以在初始化时被调用。 c_int00 函数进行以下工作以建立 C运行环境:① 为系统堆栈产生 .stack 块,并初始化堆栈指针。②从 .cinit 块将初始化数据拷贝到 .bss 块中相应的变量。③ 调用 main 函数,开始运行 C 程序。

Page 74: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.2.4 C54x C 语言库函数调用TI公司提供了一些库函数,对 C 语言编程环境的运行提供支持,称为运行时支持库( rts, runtime-

support library ) 。两种形式的运行时支持库:目标代码的“ rts.lib” 和源代码的“ rts.src” 。

对源代码库函数可以修改,例:想查看源代码库里面的两个文件“ atoi.c” 和“ strcpy.c” 的内容,并对它进行调整,可以采用如下的步骤实现:

Page 75: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

1.抽取文件使用的命令如下: ar500 x rts.src atoi.c strcpy.c

2.查看并修改文件。3. 编译修改后的文件。使用的命令是: cl500 -options atoi.c strcpy.c ; 重编译

5.2.4. C54x C 语言库函数调用

Page 76: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

4.把修改后的文件加入源代码库“ rts.src” ,使用的命令是:

ar500 -r rts.src atoi.c strcpy.c ; 重建库5. 重新生成目标库 目标库“ rts.lib” 可以由新的源代码库“ rts.src” 重新生成,使用的命令是:

mk500 --u -o2 rts.src -l rts.lib

Page 77: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.2.4 C54x C 语言库函数调用

在使用这些标准的库函数时,一定要注意在使用这些库函数的文件中把包含这些库函数声明的头文件包含到自己的文件中 。

Page 78: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.2.4 C54x C 语言库函数调用

例如:要使用标准的输入输出函数“ fprintf” ,就要在自己的文件中加上一条语句“ #include <stdio.h>”把与“ fprintf” 函数有关的头文件“ stdio.h”包含上。

Page 79: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.3 C54x C 代码优化

对 C 代码进行手工汇编优化有二种方法:

1.对照 C 代码写出汇编代码2.先用编译器产生汇编代码,然后改写汇

编代码

Page 80: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.3.1 产生汇编代码

DSP C 代码优化过程

C 代码 剖析器 优化器 代码生成器

汇编代码

Page 81: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.3.1 产生汇编代码

CCS提供了 4 级的文件优化方案,分别是 O0 、 O1 、 O2 、 O3 ,只要调用编译程序之前明确采用 -O0 、 -O1 、 -O2 还是 -O3 优化等级选项,编译程序就会按照这些优化等级的要求进行优化。

Page 82: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.3.1 产生汇编代码

我们在做优化时 ,选的是 O2 级别的

优化,因为使用 O2 级别优化后产生的

汇编文件带有比较多的注释信息,比较

容易看懂程序

Page 83: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.3.1 产生汇编代码1. O0 寄存器级别• 执行控制流程简化• 用寄存器分配变量• 执行循环• 排除未用的代码• 简化语句和表达式• 扩大对内连函数的调用

Page 84: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.3.1 产生汇编代码

2. O1 局部级别• 执行所有 O0 级别的优化• 执行局部拷贝和常量传播• 排除未用的赋值• 排除局部共用表达式

Page 85: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.3.1 产生汇编代码

3.O2 函数级别 • 执行所有 O1 级别的优化• 执行循环优化• 排除全局共用子表达式• 排除全局不用的赋值• 执行循环展开

Page 86: 第 5 章   C54x 高级 C 语言程序设计

第 5 章 C54x 高级 C 语言程序设计

5.3.1 产生汇编代码4. O3 文件级别• 执行所有 O2 级别的优化• 排除未被调用的函数• 简化返回值没被使用的函数• 让小函数变成内联调用• 保存函数说明 , 以便主函数被优化时知道

被调用函数的属性• 识别文件级别的变量的特性

Page 87: 第 5 章   C54x 高级 C 语言程序设计

作业习题 5.2-5.4