我有一个问题如何最优雅地解决与微控制器的离散 IO 检查相关的以下问题:
.c 文件的内容:
struct transfers {
uint32t *RegisterAddr;
uint8_t RegBit;
};
static const struct transfers DIO[] = {
{ REGA_ADDR, 3},
{ NULL, 1},
{ NULL, 12},
{ REGB_ADDR, 2},
{ NULL, 7},
{ REGC_ADDR, 5},
{ REGD_ADDR, 1}
};
inline uint32t Dinputs(const uint8_t n){
uint32_t DIO_Data = 0;
uint32_t RegData;
for (uint8_t i = 0; i < n; i++) {
if (DIO[i].RegisterAddr != NULL) RegData = *DIO[i].RegisterAddr;
if ((RegData & (1 << DIO[i].RegBit)) == 0) DIO_Data |= (1 << i);
}
return DIO_Data;
}
void testfunction(void) {
uint32_t DIO_Data = Dinputs(N_USED);
}
使用 --O3 --funroll-loops 编译后的预期结果应进行速度优化,例如以下等效的 testfunction C 代码,前提是 N_USED 定义为 7 并且 REGx_ADDR 也定义为有效寄存器地址:
uint32_t DIO_Data = 0;
uint32_t RegData;
RegData = *REGA_ADDR;
if ((RegData & (1 << 3)) == 0) IO_Data |= (1 << 0);
if ((RegData & (1 << 1)) == 0) IO_Data |= (1 << 1);
if ((RegData & (1 << 12)) == 0) IO_Data |= (1 << 2);
RegData = *REGB_ADDR;
if ((RegData & (1 << 2)) == 0) IO_Data |= (1 << 3);
if ((RegData & (1 << 7)) == 0) IO_Data |= (1 << 4);
RegData = *REGC_ADDR;
if ((RegData & (1 << 5)) == 0) IO_Data |= (1 << 5);
RegData = *REGD_ADDR;
if ((RegData & (1 << 1)) == 0) IO_Data |= (1 << 6);
我将 GCC 编译器用于 ARM v7。当使用上述由 testfunction 调用的内联函数 Dinputs 时,这是否按预期工作,并具有优化的机器代码输出?是否有可能强制 Dinputs 函数的展开和内联?不是很重要,但出于好奇:由于上述示例中的结构传输 DIO 仅由展开的内联函数使用,因此编译器没有必要将此数据接管到目标文件的数据部分。什么是预期的行为。这个?
我不想在我的项目中使用等效代码的原因是,如果 N_USED 在编译时应在 0 到 7 的范围内(在此示例中),并且使用其他 DIO 的变体,这将需要许多额外的预处理器命令通过只交换表格而不是任何代码来更容易地定义表格。