我刚刚在 msp430f5529(TI launchpad)上遇到了一个有趣的现象。在尝试了不同的方法之后,我找到了解决方案,但我不明白这里发生了什么。
此代码是定时器中断服务例程 (ISR) 的一部分。特殊功能寄存器(SFR)TA0IV应该保存触发ISR的中断号的值。
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_);
第 5 行第一个宏的这一部分有什么作用?
asm("__"#x)
为什么第 5 行宏的右侧没有“x_”?
最后一个也是最重要的问题:为什么第 4 行的常规类型转换可以按预期工作,而第 3 行的类型转换却不能?
顺便说一句,我使用 gcc-4.7.0。
<小时/>编辑:更多信息
9 #define __MSPGCC_PERIPHERAL__ __attribute__((__d16__))
最佳答案
1) # 是预处理器“字符串化”运算符。您可以使用 -E 编译器开关查看其影响。谷歌“c stringify”了解详细信息。
2) 不能说。并不是要求所有参数都被使用,而且显然无论谁写了这个都决定他们不需要它。
3)我会尝试一下这个,但由于我没有所有源代码或硬件并且无法进行实验,所以我可能不会完全正确。也许足够接近您所需要的。
首先要了解 asm 位的作用。通常(好吧,有时)当您声明变量(foo)时,编译器会为该变量分配自己的“内部”名称(即_foo)。然而,当与 asm 模块(或其他语言)交互时,有时您需要能够指定要使用的确切名称,不允许编译器以任何方式破坏它。这就是这个 asm 正在做的事情(参见 Asm Labels )。所以当你抛开所有 #define 废话时,你得到的是:
extern volatile __MSPGCC_PERIPHERAL__ unsigned int TA0IV __asm__("__TA0IV");
由于您发布的定义是“extern”,大概在某个地方(未显示),因此有一个名为 __TA0IV 的符号正在被定义。由于访问它无法正常工作,因此它似乎正在被 MIS 定义。
需要注意的是,我还没有尝试过这个,我会发现这更具可读性:
#define TA0IV_ 0x036E
inline int ReadInterruptNumber()
{
int retval;
asm volatile("movl (%c1), %0": "=rm" (retval) : "i" (TA0IV_));
return retval;
}
FWIW。
关于c - 这个 sfrw(x,x_) 宏如何工作(msp430)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24066842/