CCS中的IER和IFR寄存器:Symbol ‘IER‘ could not be resolved
问题现象
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相关推荐
- CCS中给工程加入C66x CSL库和头文件
CCS中给工程加入C66x CSL库和头文件 下载CSL头文件和库. 下载后解压缩进行安装,我安装的位置为:C:\ti\C6xCSL,装好后"/include/"文件夹下面是CSL ...
- CCS中调试DM6467高清视频采集(TVP7002输入)
DM6467的VPIF接口支持BT.1120和SMPTE 296M两种高清格式,其中BT.1120是1080P(1080I)分辨率,SMPTE296M是720P分辨率.我们这里直接测试BT.1120格 ...
- CCS中的cmd命令文件
CMD的专业名称叫链接器配置文件,是存放链接器的配置信息的,我们简称为命令文件,其中比较关键的就是MEMORY和SECTIONS两个伪指令的使用,常常令人困惑,系统出现的问题也经常与它们的不当使用有关 ...
- ccs读取dat文件c语言程序,CCS中dat文件的格式
在CCS中,需要处理数据的时候有一种方式是采用load data,这时可以从文件中装入数据到板子的内存,数据文件格式有特定的要求,具体的格式如下: 文件头为 1651 1 ...
- ccs读取dat文件c语言程序,详解CCS中的.dat文件
CCS支持的.dat文件的格式为: 文件头为 定数 数据格式 起始地址 页类型 数据块大小 1651 1 80000000 0 ...
- det曲线_Winform中设置ZedGraph的曲线符号Symbol以及对应关系
场景 Winforn中设置ZedGraph曲线图的属性.坐标轴属性.刻度属性: Winform中实现ZedGraph的多条Y轴(附源码下载): 添加多条曲线后,会默认生成不带任何Symbol的曲线,如 ...
- 【操作系统】计算机中内存、cache和寄存器之间的关系及区别
1. 寄存器是中央处理器内的组成部份.寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令.数据和位址.在中央处理器的控制部件中,包含的寄存器有指令寄存器(IR)和程序计数器(PC).在中央处理器的 ...
- 如何在CCS中建立自己的工程
如何在CCS中建立自己的工程 相信有很多人用了好久的CCS了,却不会建立自己的工程文件,大家要不就是在TI的例程里改,要不就是弄的工程文件路径很复杂,而且有时还会有致命的缺点--不能换路径,也就是说放 ...
- ccs中c语言定义布尔常量,CCS中寄存器定义方法
<TMS 320 F28x源码解读>第1章DSP F28x 使用入门,通过位域结构体的方法为F28x 提供了一个完整的头文件体系,并且针对F28x 的外围设备给出了20 个外设示例,这是D ...
最新文章
- oracle中怎么查看存储过程的源码
- java 双调旅行商 hamiltonian,双调欧几里得旅行商问题(TSP)
- 由于找不到appvisvsubsystems32.dll_去固始张街逛一逛,以后可能看不到了......
- sublime,gedit,vim和mousepad等都出现fribidi_get_par_embedding_levels_ex
- 2019.5.8_此书真乃宝书也_从定位参数到仅限关键字参数
- Android 基础 —— 模拟实现拨打电话功能
- “智企云中享“,首届SAP中国云大会召开
- 移植内核过程的几个问题
- python模拟seo_Python模拟鼠标点击实现方法(将通过实例自动化模拟在360浏览器中自动搜索python)_天津SEO...
- 运动控制卡中伺服电机的规划位置与编码器位置的区别
- JAVA 内部类 泛型 实现堆栈
- VMware - 虚拟机系统中无法使用键盘
- 【硬石科技】电机系列教学(基于STM32)——直流有刷电机和直流减速电机及其驱动电路
- Android使用iconfont图标
- ov5640帧率配置_OV5640(2):配置寄存器
- (一)基于Multisim的超外差接收系统:本地振荡器的设计
- 云计算淡定从容的大局观
- 2019-2021 文本生成图片 Text To Image(T2I) Synthesis 论文整理
- 深信服 华为路由器 ipsce对接
- pythoncookie自动登录_Python爬虫连载6-cookie深入使用实例化实现自动登录