DSP编程技巧之17---非常“关键”的关键字

时间:2017-06-16 15:19

DSP编程技巧之17---非常“关键”的关键字

  什么是“关键字”?关键字就是已被C语言本身使用,不能作其它用途使用的字,例如关键字不能用作变量名、函数名等。那“关键字”到底有多关键?简单得说,就是如果不掌握它们的使用方法,程序就不能按照我们的设计产生预期的结果。C28x的编译器支持所有的标准C89的关键字,包括const、volatile和register,标准的C99关键字,包括inline和restrict,以及支持TI自定义的扩展关键字__cregister、__asm,和__interrupt;对于FPU的操作,还支持restrict关键字。接下来我们就看一下几个常用关键字的用法,包括const,cregister,far,__interrupt等。在前面的一篇文章DSP编程技巧之15-使用代码优化时必须考虑的五大问题中,我们已经描述了volatile和restrict的用法,在此不再重复描述。

本文引用地址:

  1. const

  const关键字用来定义值不会发生变化/不允许被改变的变量、数组等,即相当于这些变量、数组是“只读”的。通常情况下,const定义的全局变量会存放在cmd文件定义的.const段中,而.const段一般会被链接器分配到ROM或者FLASH存储,而不是RAM中;考虑到片上ROM/FLASH的空间通常比RAM的空间大,且RAM的空间经常会比较紧张,这种存储分配方式是很有优势的。但是在两种情况下const定义的全局变量仍然会被分配到RAM的地址空间中,包括:

  1) 使用const定义变量的同时还使用了volatile关键字,例如volatile const int x,volatile类型的变量是默认存放在RAM中的,volative const也会被分配到RAM中;程序中无法对volative const定义的常量进行修改(但是某些情况下外部程序可以对其修改)。

  2) 在函数的作用域内,对象被自动的存储。

  在使用const关键字的时候,其位置是非常重要的,例如:

  int * const p = &x; //指针p为constant类型(p不可变),指向的内容为可变的int类型变量

  const int * q = &x; //指针q为可变的,指向constant的int类型

  使用const关键字,我们可以定义内容较多的常数型数据表(例如一个100点的自定义数学表),并把它们分配到ROM/Flash中,例如

  const int digits[] = {0,1,2,3,4,5,6,7,8,9};

  通常情况下我们会直接使用#define来预定义某些符号的值,那#define与const的区别是什么? const定义的只读变量在程序运行过程中只有一份拷贝(比如它存放在ROM中,有固定的地址),而#define定义的宏常量在内存中有若干个拷贝。#define宏是在预编译阶段进行替换,而const修饰的只读变量是在编译的时候确定其值。#define宏没有类型,而const修饰的只读变量具有特定的类型(该是啥类型还是啥类型,只不过其值为只读的)。const 的好处是引入了常量的概念,让我们不要去修改不该修改的内存;当我们不小心尝试改变const变量的值时,编译器就可以给出相关的错误信息提醒我们了。

  2. cregister

  使用cregister关键字,当我们定义的该类型的对象与C28x的标准的控制寄存器匹配时,编译器会自动产生相关的代码去控制对应的寄存器,使得我们可以在高级编程语言C/C++中对寄存器进行控制;如果不匹配则产生编译器错误。目前可匹配此类型的寄存器包括:

  IER:中断使能寄存器

  IFR:中断标志寄存器

  其定义方式为;

  extern cregister volatile unsigned int IFR;

  extern cregister volatile unsigned int IER;

  cregister类型只能对整形或者指针类型进行定义,并且只在本文件的作用域内生效,它既不能在函数内定义,也不能被用在浮点类型、结构体或者共同体类型上面。如果cregister类型定义的变量是可以被外部控制修改的,那么该变量也必须同时使用volatile类型进行声明。

  在定义了寄存器之后,我们就可以直接使用寄存器的名字了,但是还有以下的限制(如果不按照规范来,则会有“Illegal use of control register”的错误提示):

  1)IFR是不能直接写的,它的置位操作只能通过“或”操作(操作符是|)进行修改,且操作数必须是立即数,它的复位操作只能被“与”操作(操作符是&)进行修改,例如:

  IFR |= 0x4;

  IFR &= 0x0800

  2)IER寄存器除了通过“或”操作或者“与”操作进行修改之外,也可直接赋值,例如:

  IER = x;

  IER |= 0x100;

  printf("IER = %x\n", IER);

  3. far