我有32位寄存器,其中包含用作位掩码的字段,例如:
#define BM_TEST_FIELD 0x000F0000
我需要一个宏,允许我将寄存器(由其地址定义)的字段(由其位掩码定义)设置为给定值。以下是我想到的代码:
#include <stdio.h>
#include <assert.h>
typedef unsigned int u32;
/*
* Set a given field defined by a bit-mask MASK of a 32-bit register at address
* ADDR to a value VALUE.
*/
#define SET_REGISTER_FIELD(ADDR, MASK, VALUE) \
{ \
u32 mask=(MASK); u32 value=(VALUE); \
u32 mem_reg = *(volatile u32*)(ADDR); /* Get current register value */ \
assert((MASK) != 0); /* Null masks are not supported */ \
while(0 == (mask & 0x01)) /* Shift the value to the left until */ \
{ /* it aligns with the bit field */ \
mask = mask >> 1; value = value << 1; \
} \
mem_reg &= ~(MASK); /* Clear previous register field value */ \
mem_reg |= value; /* Update register field with new value */ \
*(volatile u32*)(ADDR) = mem_reg; /* Update actual register */ \
}
/* Test case */
#define BM_TEST_FIELD 0x000F0000
int main()
{
u32 reg = 0x12345678;
printf("Register before: 0x%.8X\n", reg);/* should be 0x12345678 */
SET_REGISTER_FIELD(®, BM_TEST_FIELD, 0xA);
printf("Register after: 0x%.8X\n", reg); /* should be 0x123A5678 */
return 0;
}
有没有更简单的方法来完成这件事?
编辑:特别是,我正在寻找一种减少运行时计算要求的方法。有没有一种方式让预处理器计算所需左移的数量?
MASK & -MASK
来仅保留最低位的 1。 - AnT stands with Russia