在 CMSIS 中,为啥位域位置是“unsigned int”,而掩码基数是“unsigned long int”?

Posted

技术标签:

【中文标题】在 CMSIS 中,为啥位域位置是“unsigned int”,而掩码基数是“unsigned long int”?【英文标题】:in CMSIS, why are bitfield positions 'unsigned int' but the mask base 'unsigned long int'?在 CMSIS 中,为什么位域位置是“unsigned int”,而掩码基数是“unsigned long int”? 【发布时间】:2021-08-27 03:24:06 【问题描述】:

这是来自 ST CMSIS 标头的示例:

#define USART_ISR_TC_Pos              (6U)
#define USART_ISR_TC_Msk              (0x1UL << USART_ISR_TC_Pos)

在 CMSIS 标头中,位域位置 (_Pos) 以 unsigned int 类型的十进制整数常量的形式给出,未移位的掩码为 unsigned long int

为什么它们都没有指定为unsigned long int

【问题讨论】:

可能是因为如果您使用的是 64 位系统,则位置在 0..63 之内,适合 unsigned int 范围,而 &lt;&lt; 的结果可能会超出 unsigned int 的范围,因此它应该是UL(可以是32位或64位,取决于系统)。 &lt;&lt; 的右边只是要移位的位数,人类更喜欢十进制(“第 4 位”)。但是你可以在任何基础(八进制,十六进制)中做到这一点。当然这应该是一个正数。 unsigned int 需要能够至少保持 2^16。这可能有点短视,但我无法想象一台机器不足以描述unsigned long 中的位数。并且在移位操作中使用任何大于位数的值都会导致未定义的行为。因此,即使是 unsigned char 也足够了。 【参考方案1】:

    位位置:寄存器中的位置不能超过31,C中的任何整数类型都可以保存。甚至没有理由不签署该职位。

    面具。由于 C 标准要求的最小unsigned int 大小不足以容纳 32 位值,因此必须将其声明为 unsigned long。 CMSIS 作者不知道您将使用的编译器,因此他们使用 minimal 充分类型。

【讨论】:

【参考方案2】:

没有明显的原因。我非常怀疑这些库是否打算与 8 或 16 苦味剂共享,这是唯一合理的解释。

Cortex M 将是 32 位,32 位 int 和 32 位 long。最重要的是 32 位硬件外围寄存器。因此,即使long 是 64 位,将掩码移到寄存器范围之外也是毫无意义的。

U 后缀足以防止未定义的行为在有符号操作数上左移。其他草率的库使用错误的 1 &lt;&lt; n 样式,所以也许 1UL 是纠正该错误的快速修复 - 1U 本来可以正常工作。

【讨论】:

以上是关于在 CMSIS 中,为啥位域位置是“unsigned int”,而掩码基数是“unsigned long int”?的主要内容,如果未能解决你的问题,请参考以下文章

为啥位字节序是位域中的一个问题?

位域 (Bit field)

内存对齐分配策略(含位域模式)

C程序中 : 冒号的作用是啥?

CMSIS-RTOS 信号量

为啥用MDK4.2版本的时候编译正常,用4.6版本就出问题了。