我试图通过大型平台抽象库(PAL)将多个基于硬件的产品移植到资源有限(即千字节计数 )的小型embedded式系统中。
目前的PAL有一个简单的getRegister()
函数,它返回一个特定产品的寄存器地址。 例如,假设产品名为coconut
和pineapple
,代码将如下所示:
#include "headers/Include/coconut.h" #include "headers/Include/pineapple.h" enum prodType { PROD_COCONUT = 0, PROD_PINEAPPLE, PROD_MAX, PROD_INVALID = (-1) }; uint64_t getRegister(enum prodType prod, int regName) { uint64_t r = 0; switch (prodType) { case PROD_COCONUT: switch (regName) { case REG_BASE: r = COCONUT_REG_BASE; break; case REG_CORE: r= COCONUT_REG_CORE; break; } break; case PROD_PINEAPPLE: switch (regName) { case REG_BASE: r = PINEAPPLE_REG_BASE; break; case REG_CORE: r= PINEAPPLE_REG_CORE; break; } break; default: // Error. break; } return r; }
我想改变这个函数是一个简单的编译时macros,因此getRegister(PROD_COCONUT, REG_BASE)
只是查看一个值表并返回相应的寄存器值。 原因是,如果我知道一个平台只支持coconut
,我可以使用macros来不包含其他产品(即pineapple
)的标题,并减less程序的大小。
到目前为止,我正在考虑这样的事情:
enum regs { REG_BASE = 0, REG_CORE, REG_MAX, REG_INVALID = (-1) }; struct keyValPair { int idx; enum reg; uint64_t val; }; struct keyValPair tableCoconut[] = { { 0, REG_BASE, COCONUT_REG_BASE }, { 1, REG_CORE, COCONUT_REG_CORE }, };
所以,我想能够做一些索引到表中的效果,以便tableCoconut[REG_BASE]
返回COCONUT_REG_BASE
, 在O(1)
时间返回一个值,而不必在表中迭代/search。 理想情况下,这是一个编译时的macros扩展,而不是一个真正的函数调用。
是否有(简单/干净)的方式来实现一些中间映射,以便:
keyValPair
结构( 可选 )中删除idx
variables。 O(1)
(即不基于search的查找)的映射( 必需 )? 这是假设寄存器值是不连续和唯一的? 我正在考虑使用几年前的一些类似的问题 ,但是不能完全用macros来得到这种双射分离的连续映射。 我试图也许通过macros和##
操作创build一个自动递增索引值通过与预处理器的##
连接操作创build一个中间索引与一个前缀附加到REG_BASE
/ REG_CORE
。
并非所有的产品都有相同的寄存器。 BANANA_REG_CORE
中可能没有提供条目的banana
产品。
假设你的枚举从0开始,然后从那里依次上升,你可以使用枚举值直接索引到一个数组中,并检索你想要的值。 虽然这可能不会发生在编译时,数组查找是O(1),所以它应该是快速的。
所以你可以像这样构建一个数组:
uint64_t tableCoconut[] = { COCONUT_REG_BASE, COCONUT_REG_CORE };
和tableCoconut[REG_BASE]
或tableCoconut[REG_CORE]
会给你你想要的值在O(1)。
您可以进一步扩展以考虑多个产品:
uint64_t tableAll[2][2] = { { COCONUT_REG_BASE, COCONUT_REG_CORE }, { PINEAPPLE_REG_BASE, PINEAPPLE_REG_CORE }, };
并执行O(1)查找,如tableAll[PROD_COCONUT][REG_BASE]
或tableAll[PROD_PINAPPLE][REG_BASE]