• 设为首页
  • 收藏本站
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    查看: 1019|回复: 12

    [技术文章] DSP编程技巧之:非常“关键”的关键字

    [复制链接]

    该用户从未签到

    34

    主题

    285

    回帖

    0

    积分

    二级逆天

    积分
    0

    社区居民终身成就奖

    QQ
    发表于 2017-2-19 22:21:10 | 显示全部楼层 |阅读模式
    什么是“关键字”?关键字就是已被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关键字会产生负面的效果。
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-10-7 21:17
  • 签到天数: 103 天

    [LV.6]常住居民II

    49

    主题

    1万

    回帖

    7万

    积分

    三级逆天

    积分
    73180

    终身成就奖特殊贡献奖原创先锋奖社区居民忠实会员社区劳模最爱沙发社区明星原创达人优秀斑竹奖宣传大使奖

    QQ
    发表于 2017-2-20 06:53:31 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    4 天前
  • 签到天数: 64 天

    [LV.6]常住居民II

    60

    主题

    1万

    回帖

    8345

    积分

    二级逆天

    积分
    8345

    终身成就奖特殊贡献奖原创先锋奖社区居民灌水天才奖优秀斑竹奖宣传大使奖忠实会员最爱沙发社区劳模

    QQ
    发表于 2017-2-20 07:35:21 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    97

    主题

    1715

    回帖

    1万

    积分

    三级逆天

    积分
    10386

    终身成就奖特殊贡献奖优秀斑竹奖

    QQ
    发表于 2017-2-20 09:03:45 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    632

    主题

    6399

    回帖

    209

    积分

    三级逆天

    -

    积分
    209

    忠实会员社区居民社区劳模原创达人最爱沙发终身成就奖特殊贡献奖原创先锋奖优秀斑竹奖金点子奖

    QQ
    发表于 2017-2-20 09:48:47 | 显示全部楼层
    -
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    454

    回帖

    10

    积分

    二级逆天

    积分
    10

    社区居民终身成就奖

    QQ
    发表于 2017-2-20 13:57:53 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    16

    主题

    227

    回帖

    0

    积分

    二级逆天

    积分
    0

    终身成就奖

    QQ
    发表于 2017-2-20 17:29:54 | 显示全部楼层
    回复

    使用道具 举报

    该用户从未签到

    11

    主题

    2173

    回帖

    10

    积分

    二级逆天

    积分
    10

    终身成就奖优秀斑竹奖

    QQ
    发表于 2017-3-4 08:47:36 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2024-10-11 11:45
  • 签到天数: 2 天

    [LV.1]初来乍到

    0

    主题

    1393

    回帖

    2366

    积分

    二级逆天

    积分
    2366

    终身成就奖

    QQ
    发表于 2017-4-18 22:21:20 | 显示全部楼层
    回复

    使用道具 举报

  • TA的每日心情
    开心
    6 天前
  • 签到天数: 152 天

    [LV.7]常住居民III

    2

    主题

    8746

    回帖

    1万

    积分

    三级逆天

    积分
    10093

    社区居民终身成就奖特殊贡献奖原创先锋奖

    QQ
    发表于 2017-12-7 08:50:02 | 显示全部楼层
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    公告:服务器刚移机,
    大家请不要下载东西。
    会下载失败


    QQ 手机版 小黑屋 监管台 遇到问题请联系QQ1308068381 逆天PCB论坛

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表