MSP430 上寄存器的按位运算符,无需取消引用
Bitwise operator on registers on MSP430 without dereferencing
我使用的是 MSP430G2553,TI 在 headers 中定义了一些我正在使用的辅助代码 (msp430g2553.h)。例如,如果我想设置端口 1 的 GPIO 引脚 0 的方向,我可以写
P1DIR |= BIT0;
出于好奇,我查看了 P1DIR 的定义方式。我发现
SFR_8BIT(P1DIR);
其中 SFR_8BIT 定义为
#define SFR_8BIT(address) extern volatile unsigned char address
所以我们得到
extern volatile unsigned char P1DIR
P1DIR 的值在 link 时被添加并且定义为(在 linker 脚本中):
P1DIR = 0x0022;
最后我们得到
extern volatile unsigned char 0x0022;
所以对我来说 P1DIR 是一个指针,这意味着我们应该
取消引用它。但在所有文档中,我看到他们直接在
P1DIR 而不是 *P1DIR。这怎么可能?
编译器将 P1DIR 视为一个变量,正如您正确跟踪的那样,它对 P1DIR 的看法如下:
extern volatile unsigned char P1DIR
这是一个地址在别处定义的变量。在这种情况下,可能在将在 link 步骤中使用的标准库中。
在 linking 步骤中,变量的地址被解析,P1DIR 从它被定义为 0x22 的地方获取。
这种变量需要在特定地址上,因为它需要在该端口的定义地址上。
您可以在 MSP430 文档中查看每个端口的地址(其中说明 P1DIR 位于 0x22)
这个...
extern volatile unsigned char P1DIR
... 将 P1DIR
声明为 volatile unsigned char
,而不是指向一个的指针。这样的对象进行按位运算是没有问题的
我也倾向于认为您误解了 linker 脚本。你说
The value of P1DIR is added at link time
,但虽然我不知道所讨论的特定 linker 脚本语言,但它是一种 link 语言。当然,如果脚本包含 ...
P1DIR = 0x0022;
... 那么就是定义对应于该符号的地址,而不是 C-language 意义上的值。这与存储在那里的值的类型无关。 linking 的全部意义在于将地址与符号相关联。
据推测,0x0022
是I/O端口的地址。当程序读取 P1DIR
的值时,它正在从该地址读取一个值,因此从端口读取一个值,这可能会暴露状态寄存器或类似寄存器的值。它不是在读取地址本身。
我使用的是 MSP430G2553,TI 在 headers 中定义了一些我正在使用的辅助代码 (msp430g2553.h)。例如,如果我想设置端口 1 的 GPIO 引脚 0 的方向,我可以写
P1DIR |= BIT0;
出于好奇,我查看了 P1DIR 的定义方式。我发现
SFR_8BIT(P1DIR);
其中 SFR_8BIT 定义为
#define SFR_8BIT(address) extern volatile unsigned char address
所以我们得到
extern volatile unsigned char P1DIR
P1DIR 的值在 link 时被添加并且定义为(在 linker 脚本中):
P1DIR = 0x0022;
最后我们得到
extern volatile unsigned char 0x0022;
所以对我来说 P1DIR 是一个指针,这意味着我们应该 取消引用它。但在所有文档中,我看到他们直接在 P1DIR 而不是 *P1DIR。这怎么可能?
编译器将 P1DIR 视为一个变量,正如您正确跟踪的那样,它对 P1DIR 的看法如下:
extern volatile unsigned char P1DIR
这是一个地址在别处定义的变量。在这种情况下,可能在将在 link 步骤中使用的标准库中。
在 linking 步骤中,变量的地址被解析,P1DIR 从它被定义为 0x22 的地方获取。
这种变量需要在特定地址上,因为它需要在该端口的定义地址上。
您可以在 MSP430 文档中查看每个端口的地址(其中说明 P1DIR 位于 0x22)
这个...
extern volatile unsigned char P1DIR
... 将 P1DIR
声明为 volatile unsigned char
,而不是指向一个的指针。这样的对象进行按位运算是没有问题的
我也倾向于认为您误解了 linker 脚本。你说
The value of P1DIR is added at link time
,但虽然我不知道所讨论的特定 linker 脚本语言,但它是一种 link 语言。当然,如果脚本包含 ...
P1DIR = 0x0022;
... 那么就是定义对应于该符号的地址,而不是 C-language 意义上的值。这与存储在那里的值的类型无关。 linking 的全部意义在于将地址与符号相关联。
据推测,0x0022
是I/O端口的地址。当程序读取 P1DIR
的值时,它正在从该地址读取一个值,因此从端口读取一个值,这可能会暴露状态寄存器或类似寄存器的值。它不是在读取地址本身。