C 这个sfrw(x,x_u)宏是如何工作的(msp430)?
我刚刚在msp430f5529(TI launchpad)上遇到了一个有趣的现象。在尝试了不同的方法之后,我找到了一个解决方案,但我不明白这里发生了什么 该代码是定时器中断服务程序(ISR)的一部分。特殊功能寄存器(SFR)TA0IV应保存触发ISR的中断号的值C 这个sfrw(x,x_u)宏是如何工作的(msp430)?,c,gcc,macros,interrupt,msp430,C,Gcc,Macros,Interrupt,Msp430,我刚刚在msp430f5529(TI launchpad)上遇到了一个有趣的现象。在尝试了不同的方法之后,我找到了一个解决方案,但我不明白这里发生了什么 该代码是定时器中断服务程序(ISR)的一部分。特殊功能寄存器(SFR)TA0IV应保存触发ISR的中断号的值 1 unsigned int index; 2 3 index = TA0IV; // Gives wrong value: 19874 4 index = *((volatile unsigned int *) TA
1 unsigned int index;
2
3 index = TA0IV; // Gives wrong value: 19874
4 index = *((volatile unsigned int *) TA0IV_); // Correct value: 4
TA0IV在此处用宏定义:
5 #define sfrw_(x,x_) volatile __MSPGCC_PERIPHERAL__ unsigned int x __asm__("__" #x)
6 #define sfrw(x,x_) extern sfrw_(x,x_)
7 #define TA0IV_ 0x036E /* Timer0_A5 Interrupt Vector Word */
8 sfrw(TA0IV, TA0IV_);
编辑:更多信息 1) #是一个预处理器“stringify”操作符。您可以使用-E编译器开关来查看此操作的影响。谷歌“c stringify”获取详细信息 2) 说不上来。并不要求所有参数都被使用,显然写这篇文章的人认为他们不需要它 3) 我将尝试一下这个,但由于我没有所有的源代码或硬件,无法进行实验,我可能不会完全正确。也许离你需要的地方足够近了 首先要了解的是asm位在做什么。通常(好的,有时)当您声明一个变量(foo)时,编译器会为该变量(ie\u foo)指定自己的“内部”名称。但是,在与asm模块(或其他语言)接口时,有时需要能够指定要使用的确切名称,而不允许编译器以任何方式破坏它。这就是这个asm所做的(请参阅)。因此,当你撇开所有“定义”的废话时,你得到的是:
extern volatile __MSPGCC_PERIPHERAL__ unsigned int TA0IV __asm__("__TA0IV");
由于您发布的定义是“extern”,可能在某个地方(未显示),因此有一个名为uu TA0IV的符号正在被定义。而且,由于访问它的工作不正常,它似乎被错误地定义了
有一点需要注意的是,我没有尝试过这个,我会发现它更具可读性:
#define TA0IV_ 0x036E
inline int ReadInterruptNumber()
{
int retval;
asm volatile("movl (%c1), %0": "=rm" (retval) : "i" (TA0IV_));
return retval;
}
FWIW.2)宏的第二个值保存特殊函数寄存器的实际地址(0x036E),并且确保不会被忽略。这些sfrw宏几乎适用于每一个SFR,在大多数情况下,它们都能按预期工作(也请参阅我的原始帖子的编辑)。正如您自己所观察到的,x_“看起来不正确。”您可以通过使用-E编译来检查自己。我只是在输出中没有看到任何“0x036E”。MSGPCC显然只是影响变量的长度。由于这在其他地方有效,这表明其他地方与_TA0IV的正确定义有关。正如我提到的,上面的代码将其定义为“extern”。鉴于此代码使用“asm”创建符号名,这表明extern是在汇编代码中定义的。那么问题是,为什么您的代码找不到相同的(工作)符号?缺少依赖关系?
#define TA0IV_ 0x036E
inline int ReadInterruptNumber()
{
int retval;
asm volatile("movl (%c1), %0": "=rm" (retval) : "i" (TA0IV_));
return retval;
}