您的位置 首页 IC

DSP编程技巧之17—十分“要害”的要害字

什么是“关键字”?关键字就是已被C语言本身使用,不能作其它用途使用的字,例如关键字不能用作变量名、函数名等。那“关键字”到底有多关键?简单得说,就是如果不掌握它们的使用方法,程序就不能按照我们的设

  什么是“要害字”?要害字便是已被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

  默许情况下,C/C++的编译器只支撑到低64K的存储空间,且一切的指针都默许为16位的。可是C28x的存储空间一般都在16bit以上,此刻经过运用far类型,C代码中的指针能够为22bit宽(需求两个存储单元来存储),并支撑对高达4M的存储空间的存取。(在C++中,不支撑far要害字,对高地址的存取是经过运用在编译器选项中敞开large memory model选项完成的。)

  当一个变量被界说为far类型时,它被存储在高于64K的地址规模中,此刻far类型的全局变量不再保存在.bss段中,而是保存在一个新的段,即.ebss中,相同的道理,far类型的const变量也被保存到.econst段中。留意:只要全局变量和静态变量能够被界说为far类型,函数中的非静态变量(主动存储目标)由于被分配到栈中,被主动当near类型来处理。关于结构体,假如结构体被声明为far类型,则悉数成员都会主动承继为far类型。举例如下;

  int far *ptr; // 指针指向far类型的int,可是指针自身是near类型的

  int * far ptr; // 指针指向near类型的int,可是指针自身是far类型的

  int far * far ptr; //指针和指向的内容都是far类型的

  int far *memcpy_ff(far void *dest, const far void *src, int count);

  // 函数的参数为两个far类型的指针,且返回值也为far类型的指针

  int *far func();// 过错:far类型只能用于数据,不能用于函数

  //由于程序地址空间自身便是22位的

  最终需求留意的是,现在关于两个far类型指针相减的操作,其成果是16位的指针。

  4. _interrupt

  __interrupt用来声明一个函数是中止处理函数;在严厉的ANSIC/C++形式下,也能够运用interrupt要害字来替代。中止处理函数要遵从特别的寄存器保存规矩和退出次序,然后确保代码的安全。在C/C++程序中发生中止时,一切被中止子程序运用,或许被中止子程序调用的函数运用的状况都需求被保存。此外,__interrupt界说的函数不能有参数,也没有返回值,即:

  __interrupt void int_handler()

  {

  unsigned int flags;

  …

  }

  仅有特别的是c_int00函数,它是C/C++程序的进口点,被体系保存为默许的复位中止函数,并在其间调用main函数。由于c_int00函数不被任何函数所调用,所以它不需求保存任何状况(毕竟是在复位和初始化状况)。

  在DSP/BIOS和SYS/BIOS HWI目标中,不需求运用__interrupt要害字,由于Hwi_enter/Hwi_exit宏和Hwi解包器现已包含了该函数,此刻运用__interrupt要害字会发生负面的作用。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/bandaoti/117958.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部