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 Register
    union   PIEACK_REG                       PIEACK;                       // Interrupt Acknowledge Register
    union   PIEIER1_REG                      PIEIER1;                      // Interrupt Group 1 Enable Register
    union   PIEIFR1_REG                      PIEIFR1;                      // Interrupt Group 1 Flag Register
    union   PIEIER2_REG                      PIEIER2;                      // Interrupt Group 2 Enable Register
    union   PIEIFR2_REG                      PIEIFR2;                      // Interrupt Group 2 Flag Register
    union   PIEIER3_REG                      PIEIER3;                      // Interrupt Group 3 Enable Register
    union   PIEIFR3_REG                      PIEIFR3;                      // Interrupt Group 3 Flag Register
    union   PIEIER4_REG                      PIEIER4;                      // Interrupt Group 4 Enable Register
    union   PIEIFR4_REG                      PIEIFR4;                      // Interrupt Group 4 Flag Register
    union   PIEIER5_REG                      PIEIER5;                      // Interrupt Group 5 Enable Register
    union   PIEIFR5_REG                      PIEIFR5;                      // Interrupt Group 5 Flag Register
    union   PIEIER6_REG                      PIEIER6;                      // Interrupt Group 6 Enable Register
    union   PIEIFR6_REG                      PIEIFR6;                      // Interrupt Group 6 Flag Register
    union   PIEIER7_REG                      PIEIER7;                      // Interrupt Group 7 Enable Register
    union   PIEIFR7_REG                      PIEIFR7;                      // Interrupt Group 7 Flag Register
    union   PIEIER8_REG                      PIEIER8;                      // Interrupt Group 8 Enable Register
    union   PIEIFR8_REG                      PIEIFR8;                      // Interrupt Group 8 Flag Register
    union   PIEIER9_REG                      PIEIER9;                      // Interrupt Group 9 Enable Register
    union   PIEIFR9_REG                      PIEIFR9;                      // Interrupt Group 9 Flag Register
    union   PIEIER10_REG                     PIEIER10;                     // Interrupt Group 10 Enable Register
    union   PIEIFR10_REG                     PIEIFR10;                     // Interrupt Group 10 Flag Register
    union   PIEIER11_REG                     PIEIER11;                     // Interrupt Group 11 Enable Register
    union   PIEIFR11_REG                     PIEIFR11;                     // Interrupt Group 11 Flag Register
    union   PIEIER12_REG                     PIEIER12;                     // Interrupt Group 12 Enable Register
    union   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];                    // Reserved
    union   GPHDAT_REG                       GPHDAT;                       // GPIO H Data Register (GPIO224 to 255)
};

struct GPIO_DATA_READ_REGS {
    Uint32                                   GPADAT_R;                     // GPIO A Data Read Register
    Uint32                                   GPBDAT_R;                     // GPIO B Data Read Register
    Uint16                                   rsvd1[10];                    // Reserved
    Uint32                                   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 = 0x00000080
   ADCC                       : origin = 0x00007500, length = 0x00000080
   ADCARESULT                 : origin = 0x00000B00, length = 0x00000018
   ADCCRESULT                 : origin = 0x00000B40, length = 0x00000018
    …………
   GPIOCTRL                   : origin = 0x00007C00, length = 0x00000200
   GPIODATAREAD               : origin = 0x00007F80, length = 0x00000010
   GPIODATA                   : origin = 0x00007F00, length = 0x00000040
    …………
}

SECTIONS
{
   AdcaRegsFile               : > ADCA, type=NOINIT
   AdccRegsFile               : > ADCC, type=NOINIT
   AdcaResultRegsFile         : > ADCARESULT, type=NOINIT
   AdccResultRegsFile         : > ADCCRESULT, type=NOINIT
    …………
   GpioCtrlRegsFile           : > GPIOCTRL, type=NOINIT
   GpioDataReadRegsFile       : > GPIODATAREAD, type=NOINIT
   GpioDataRegsFile           : > 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文件中:

 

  • 16
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
问题提到的错误"Symbol 'IFR' could not be resolved"是由于在程序找不到对应的符号'IFR'的定义。根据引用\[1\]和引用\[2\]的信息,可以看出,在程序使用了'IFR'和'IER'这两个寄存器,但是在删除.settings文件后,文注释会乱码,并且删除.settings文件后会出现该错误。这可能是由于.settings文件包含了一些编码或配置信息,删除后导致程序无法正确解析文注释和找到对应的符号定义。 为了解决这个问题,可以尝试以下几个步骤: 1. 恢复.settings文件,以确保程序能够正确解析文注释和配置信息。 2. 检查程序是否包含了对'IFR'和'IER'这两个寄存器的定义。可以在相关的头文件查找是否存在类似的定义,如引用\[2\]和引用\[3\]所示。 3. 确保程序包含了正确的头文件,并且这些头文件包含了对'IFR'和'IER'这两个寄存器的定义。 4. 如果以上步骤都没有解决问题,可以考虑检查编译器和开发环境的配置,确保其正确设置。 总之,要解决"Symbol 'IFR' could not be resolved"错误,需要确保.settings文件存在,程序包含了对'IFR'和'IER'这两个寄存器的正确定义,并且编译器和开发环境的配置正确。 #### 引用[.reference_title] - *1* [CCS学习遇到的问题及解决方法](https://blog.csdn.net/qq_46404495/article/details/125339766)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [CCSIERIFR寄存器SymbolIER‘ could not be resolved](https://blog.csdn.net/booksyhay/article/details/120795087)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值