问题现象

main函数初始化时,关闭CPU的中断使能,清除不断标志,一般都是这么写的:

    IER = 0x0000;IFR = 0x0000;

但是,CCS却提示:

Symbol 'IER' could not be resolved

可是呢,编译整个工程时,也不会报错。

<Linking>
Finished building target: "DCDC.out"
 
"D:/ti/ccs1040/ccs/utils/tiobj2bin/tiobj2bin" "DCDC.out" "DCDC.bin" "D:/ti/ccs1040/ccs/tools/compiler/ti-cgt-c2000_20.2.5.LTS/bin/ofd2000" "D:/ti/ccs1040/ccs/tools/compiler/ti-cgt-c2000_20.2.5.LTS/bin/hex2000" "D:/ti/ccs1040/ccs/utils/tiobj2bin/mkhex4bin"

**** Build Finished ****

那么,IER是什么?为什么IER不能解析呢?这种写法到底是否符合C语言规范呢?

原因分析

首先,IER是一个寄存器。并且是CPU内核的寄存器。IFR也一样。

与外设寄存器类似,在CCS的编译环境中,都把这类寄存器当作一个全局变量来处理。

比如,要使能PIE中的ADCD1中断,则是直接改变PieCtrlRegs这个全局变量中的某个位。

    PieCtrlRegs.PIEIER1.bit.INTx6 = 1;    /* PIE Group 1.6, ADCD1_INT*/

C语言规范要求,在使用变量之前,必须先声明,并且要在合适的地方定义这个变量。那么,外设寄存器这一类的全局变量在哪里声明和定义的呢?

外设寄存器变量的声明

在headers\include文件夹中,有各个外设寄存器变量的类型定义,以及全局变量的声明。

比如,在F2837xD_piectrl.h中:

struct PIE_CTRL_REGS {union   PIECTRL_REG                      PIECTRL;                      // ePIE Control Registerunion   PIEACK_REG                       PIEACK;                       // Interrupt Acknowledge Registerunion   PIEIER1_REG                      PIEIER1;                      // Interrupt Group 1 Enable Registerunion   PIEIFR1_REG                      PIEIFR1;                      // Interrupt Group 1 Flag Registerunion   PIEIER2_REG                      PIEIER2;                      // Interrupt Group 2 Enable Registerunion   PIEIFR2_REG                      PIEIFR2;                      // Interrupt Group 2 Flag Registerunion   PIEIER3_REG                      PIEIER3;                      // Interrupt Group 3 Enable Registerunion   PIEIFR3_REG                      PIEIFR3;                      // Interrupt Group 3 Flag Registerunion   PIEIER4_REG                      PIEIER4;                      // Interrupt Group 4 Enable Registerunion   PIEIFR4_REG                      PIEIFR4;                      // Interrupt Group 4 Flag Registerunion   PIEIER5_REG                      PIEIER5;                      // Interrupt Group 5 Enable Registerunion   PIEIFR5_REG                      PIEIFR5;                      // Interrupt Group 5 Flag Registerunion   PIEIER6_REG                      PIEIER6;                      // Interrupt Group 6 Enable Registerunion   PIEIFR6_REG                      PIEIFR6;                      // Interrupt Group 6 Flag Registerunion   PIEIER7_REG                      PIEIER7;                      // Interrupt Group 7 Enable Registerunion   PIEIFR7_REG                      PIEIFR7;                      // Interrupt Group 7 Flag Registerunion   PIEIER8_REG                      PIEIER8;                      // Interrupt Group 8 Enable Registerunion   PIEIFR8_REG                      PIEIFR8;                      // Interrupt Group 8 Flag Registerunion   PIEIER9_REG                      PIEIER9;                      // Interrupt Group 9 Enable Registerunion   PIEIFR9_REG                      PIEIFR9;                      // Interrupt Group 9 Flag Registerunion   PIEIER10_REG                     PIEIER10;                     // Interrupt Group 10 Enable Registerunion   PIEIFR10_REG                     PIEIFR10;                     // Interrupt Group 10 Flag Registerunion   PIEIER11_REG                     PIEIER11;                     // Interrupt Group 11 Enable Registerunion   PIEIFR11_REG                     PIEIFR11;                     // Interrupt Group 11 Flag Registerunion   PIEIER12_REG                     PIEIER12;                     // Interrupt Group 12 Enable Registerunion   PIEIFR12_REG                     PIEIFR12;                     // Interrupt Group 12 Flag Register
};//---------------------------------------------------------------------------
// PIECTRL External References & Function Declarations:
//extern volatile struct PIE_CTRL_REGS PieCtrlRegs;

前面是PieCtrlRegs这个变量的类型定义:结构体struct PIE_CTRL_REGS;

后面是PieCtrlRegs这个变量的声明:extern volatile struct PIE_CTRL_REGS PieCtrlRegs;

再比如,在f28002x_gpio.h文件中:


struct GPIO_DATA_REGS {union   GPADAT_REG                       GPADAT;                       // GPIO A Data Register (GPIO0 to 31)union   GPASET_REG                       GPASET;                       // GPIO A Data Set Register (GPIO0 to 31)union   GPACLEAR_REG                     GPACLEAR;                     // GPIO A Data Clear Register (GPIO0 to 31)union   GPATOGGLE_REG                    GPATOGGLE;                    // GPIO A Data Toggle Register (GPIO0 to 31)union   GPBDAT_REG                       GPBDAT;                       // GPIO B Data Register (GPIO32 to 63)union   GPBSET_REG                       GPBSET;                       // GPIO B Data Set Register (GPIO32 to 63)union   GPBCLEAR_REG                     GPBCLEAR;                     // GPIO B Data Clear Register (GPIO32 to 63)union   GPBTOGGLE_REG                    GPBTOGGLE;                    // GPIO B Data Toggle Register (GPIO32 to 63)Uint16                                   rsvd1[40];                    // Reservedunion   GPHDAT_REG                       GPHDAT;                       // GPIO H Data Register (GPIO224 to 255)
};struct GPIO_DATA_READ_REGS {Uint32                                   GPADAT_R;                     // GPIO A Data Read RegisterUint32                                   GPBDAT_R;                     // GPIO B Data Read RegisterUint16                                   rsvd1[10];                    // ReservedUint32                                   GPHDAT_R;                     // GPIO H Data Read Register
};//---------------------------------------------------------------------------
// GPIO External References & Function Declarations:
//
extern volatile struct GPIO_CTRL_REGS GpioCtrlRegs;
extern volatile struct GPIO_DATA_REGS GpioDataRegs;
extern volatile struct GPIO_DATA_READ_REGS GpioDataReadRegs;

同样的,前面也是寄存器变量的类型定义,后面是全局变量的声明。

外设寄存器变量的定义

变量声明只解决了编译问题,光声明还不够,如果只声明但不定义,则在链接过程中还会报错。那么,一定有一个地方去定义这些变量。答案就在headers\source\f28002x_globalvariabledefs.c文件中。

//----------------------------------------
#ifdef __cplusplus
#pragma DATA_SECTION("GpioCtrlRegsFile")
#else
#pragma DATA_SECTION(GpioCtrlRegs,"GpioCtrlRegsFile");
#endif
volatile struct GPIO_CTRL_REGS GpioCtrlRegs;//----------------------------------------
#ifdef __cplusplus
#pragma DATA_SECTION("GpioDataReadRegsFile")
#else
#pragma DATA_SECTION(GpioDataReadRegs,"GpioDataReadRegsFile");
#endif
volatile struct GPIO_DATA_READ_REGS GpioDataReadRegs;//----------------------------------------
#ifdef __cplusplus
#pragma DATA_SECTION("GpioDataRegsFile")
#else
#pragma DATA_SECTION(GpioDataRegs,"GpioDataRegsFile");
#endif
volatile struct GPIO_DATA_REGS GpioDataRegs;

其中的“volatile struct GPIO_CTRL_REGS GpioCtrlRegs;”没有“extern”关键字,表示这是一个变量的定义。编译器会给该变量分配存储器空间。

特别需要说明的是,这里不光是定义了全局变量,还要与外设寄存器绑定起来。

外设寄存器全局变量与外设寄存器硬件的绑定关系

在每个全局变量的前面,都有类似这样的编译指令:

#pragma DATA_SECTION(GpioCtrlRegs,"GpioCtrlRegsFile");

这条指令的意思是,告诉编译器,GpioCtrlRegs这个变量,不要随便放置到RAM中,而是要放到GpioCtrlRegsFile这个section.

那么,问题又来了,这个section又有什么用呢?跟GPIO控制寄存器这个外设又是如何关联的呢?

答案在cmd文件里。

打开 headers\cmd\f28002x_headers_nonbios.cmd文件看看。这里节选了ADC和GPIO相关的内容:

MEMORY
{ADCA                       : origin = 0x00007400, length = 0x00000080ADCC                       : origin = 0x00007500, length = 0x00000080ADCARESULT                 : origin = 0x00000B00, length = 0x00000018ADCCRESULT                 : origin = 0x00000B40, length = 0x00000018…………GPIOCTRL                   : origin = 0x00007C00, length = 0x00000200GPIODATAREAD               : origin = 0x00007F80, length = 0x00000010GPIODATA                   : origin = 0x00007F00, length = 0x00000040…………
}SECTIONS
{AdcaRegsFile               : > ADCA, type=NOINITAdccRegsFile               : > ADCC, type=NOINITAdcaResultRegsFile         : > ADCARESULT, type=NOINITAdccResultRegsFile         : > ADCCRESULT, type=NOINIT…………GpioCtrlRegsFile           : > GPIOCTRL, type=NOINITGpioDataReadRegsFile       : > GPIODATAREAD, type=NOINITGpioDataRegsFile           : > GPIODATA, type=NOINIT…………
}

可以看到,在MEMORY中定义了各外设对应的区间,其地址也CPU外设地址一致。在SECTIONS中,指定各个节(比如GpioCtrlRegsFile)要放置的空间(比如放置至GPIOCTRL区间)。

这样,整个链条都打通了。在C语言代码中,对寄存器变量的访问,最终就等同于对硬件寄存器的访问。

以上语法完全符合ANSI C语言规范。CCS只是在此基础上扩展了编译器指令。

那么,针对IER和IFR,CCS又是如何做的呢?

IER和IFR的声明

在C代码中,想要给IER赋值,自然也要先告诉编译器,有IER这个变量。

这个,当然是有的。必须有。比如,在F2837xD_device.h文件中:

//
// User To Select Target Device:
//
#define   F28_2837xD    TARGET//
// Common CPU Definitions:
//
extern __cregister volatile unsigned int IFR;
extern __cregister volatile unsigned int IER;

再比如,在X:\ti\c2000\C2000Ware_3_04_00_00\device_support\f28002x\headers\include\f28002x_device.h文件中,也有类似的定义:

#ifndef __TMS320C28XX__
#define __cregister
#endif  //__TMS320C28xx__extern __cregister volatile unsigned int IFR;
extern __cregister volatile unsigned int IER;

这里出现了一个新的关键字:__cregister。关于这个关键字的说明如下。

__cregister关键字

查询手册:《TMS320C28x Optimizing C_C++ Compiler v21.6.0.LTS User's Guide (Rev. W)-spru514w.pdf》 第6.5.2章节,

The compiler extends the C/C++ language by adding the cregister keyword to allow high level language access to control registers. This keyword is available in normal mode, but not in strict ANSI/ISO mode (using the --strict_ansi compiler option). The alternate keyword, __cregister, provides the same functionality but is available in either strict ANSI/ISO mode or normal mode.
When you use the cregister keyword on an object, the compiler compares the name of the object to a list of standard control registers for the C28x (see Table 6-2). If the name matches, the compiler generates the code to reference the control register. If the name does not match, the compiler issues an error.

使用DriverLib库

如果使用的是新的driverlib库,也有同样的声明。是在cpu.h文件中。比如

X:\ti\c2000\C2000Ware_3_04_00_00\driverlib\f28002x\driverlib\cpu.h文件中:

CCS中的IER和IFR寄存器:Symbol ‘IER‘ could not be resolved相关推荐

  1. CCS中给工程加入C66x CSL库和头文件

    CCS中给工程加入C66x CSL库和头文件 下载CSL头文件和库. 下载后解压缩进行安装,我安装的位置为:C:\ti\C6xCSL,装好后"/include/"文件夹下面是CSL ...

  2. CCS中调试DM6467高清视频采集(TVP7002输入)

    DM6467的VPIF接口支持BT.1120和SMPTE 296M两种高清格式,其中BT.1120是1080P(1080I)分辨率,SMPTE296M是720P分辨率.我们这里直接测试BT.1120格 ...

  3. CCS中的cmd命令文件

    CMD的专业名称叫链接器配置文件,是存放链接器的配置信息的,我们简称为命令文件,其中比较关键的就是MEMORY和SECTIONS两个伪指令的使用,常常令人困惑,系统出现的问题也经常与它们的不当使用有关 ...

  4. ccs读取dat文件c语言程序,CCS中dat文件的格式

    在CCS中,需要处理数据的时候有一种方式是采用load data,这时可以从文件中装入数据到板子的内存,数据文件格式有特定的要求,具体的格式如下: 文件头为 1651             1    ...

  5. ccs读取dat文件c语言程序,详解CCS中的.dat文件

    CCS支持的.dat文件的格式为: 文件头为 定数 数据格式 起始地址 页类型 数据块大小 1651             1                  80000000         0 ...

  6. det曲线_Winform中设置ZedGraph的曲线符号Symbol以及对应关系

    场景 Winforn中设置ZedGraph曲线图的属性.坐标轴属性.刻度属性: Winform中实现ZedGraph的多条Y轴(附源码下载): 添加多条曲线后,会默认生成不带任何Symbol的曲线,如 ...

  7. 【操作系统】计算机中内存、cache和寄存器之间的关系及区别

    1. 寄存器是中央处理器内的组成部份.寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令.数据和位址.在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC).在中央处理器的 ...

  8. 如何在CCS中建立自己的工程

    如何在CCS中建立自己的工程 相信有很多人用了好久的CCS了,却不会建立自己的工程文件,大家要不就是在TI的例程里改,要不就是弄的工程文件路径很复杂,而且有时还会有致命的缺点--不能换路径,也就是说放 ...

  9. ccs中c语言定义布尔常量,CCS中寄存器定义方法

    <TMS 320 F28x源码解读>第1章DSP F28x 使用入门,通过位域结构体的方法为F28x 提供了一个完整的头文件体系,并且针对F28x 的外围设备给出了20 个外设示例,这是D ...

最新文章

  1. oracle中怎么查看存储过程的源码
  2. java 双调旅行商 hamiltonian,双调欧几里得旅行商问题(TSP)
  3. 由于找不到appvisvsubsystems32.dll_去固始张街逛一逛,以后可能看不到了......
  4. sublime,gedit,vim和mousepad等都出现fribidi_get_par_embedding_levels_ex
  5. 2019.5.8_此书真乃宝书也_从定位参数到仅限关键字参数
  6. Android 基础 —— 模拟实现拨打电话功能
  7. “智企云中享“,首届SAP中国云大会召开
  8. 移植内核过程的几个问题
  9. python模拟seo_Python模拟鼠标点击实现方法(将通过实例自动化模拟在360浏览器中自动搜索python)_天津SEO...
  10. 运动控制卡中伺服电机的规划位置与编码器位置的区别
  11. JAVA 内部类 泛型 实现堆栈
  12. VMware - 虚拟机系统中无法使用键盘
  13. 【硬石科技】电机系列教学(基于STM32)——直流有刷电机和直流减速电机及其驱动电路
  14. Android使用iconfont图标
  15. ov5640帧率配置_OV5640(2):配置寄存器
  16. (一)基于Multisim的超外差接收系统:本地振荡器的设计
  17. 云计算淡定从容的大局观
  18. 2019-2021 文本生成图片 Text To Image(T2I) Synthesis 论文整理
  19. 深信服 华为路由器 ipsce对接
  20. pythoncookie自动登录_Python爬虫连载6-cookie深入使用实例化实现自动登录

热门文章

  1. 从冷战到深度学习:一篇图文并茂的机器翻译史
  2. ETH基于POA的环境搭建
  3. 计算机网络判断题(详细解析)
  4. 通过内容提供者获取手机上的音乐资源
  5. 【JAVA】计算算式
  6. python从小到大排序
  7. 校验手机号和获取验证码
  8. 实训:网站诊断分析(12.10)
  9. 哥德尔奖得主Cynthia Dwork:实现算法公平性,长路漫漫
  10. OpenGL基础绘制