【发布时间】:2014-10-30 08:36:33
【问题描述】:
我为带有ATmega2560 处理器的 avr 项目编写了一个快速的“8 位反向”例程。 我正在使用
- GNU C (WinAVR 20100110) 版本 4.3.3 (avr) / 由 GNU C 版本 3.4.5 (mingw-vista special r3)、GMP 版本 4.2.3、MPFR 版本 2.4.1 编译。
首先我创建了一个反向字节的全局查找表(大小:0x100):
uint8_t BitReverseTable[]
__attribute__((__progmem__, aligned(0x100))) = {
0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,
0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
[...]
0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
};
这按预期工作。那是我打算使用的宏,它应该只花费我 5 个循环:
#define BITREVERSE(x) (__extension__({ \
register uint8_t b=(uint8_t)x; \
__asm__ __volatile__ ( \
"ldi r31, hi8(table)" "\n\t" \
"mov r30, ioRegister" "\n\t" \
"lpm ioRegister, z" "\n\t" \
:[ioRegister] "+r" (b) \
:[table] "g" (BitReverseTable) \
:"r30", "r31" \
); \
}))
编译(或不编译)的代码。
int main() /// Test for bitreverse
{
BITREVERSE(25);
return 0;
}
这是我从编译器得到的错误:
c:/winavr-20100110/bin/../lib/gcc/avr/4.3.3/../../../../avr/bin/as.exe -mmcu=atmega2560 -o bitreverse.o C:\Users\xxx\AppData\Local\Temp/ccCefE75.s
C:\Users\xxx\AppData\Local\Temp/ccCefE75.s: Assembler messages:
C:\Users\xxx\AppData\Local\Temp/ccCefE75.s:349: Error: constant value required
C:\Users\xxx\AppData\Local\Temp/ccCefE75.s:350: Error: constant value required
我猜问题出在这里:
:[table] "g" (BitReverseTable) \
在我看来,BitReverseTable 是数组的内存位置,在编译时是固定的并且是已知的。因此它是恒定的。 也许我需要将 BitReverseTable 转换成某种东西(我尝试了我能想到的任何东西)。也许我需要另一个约束(“g”是我的最后一个测试)。我确信我使用了任何可能和不可能的东西。 我编写了一个汇编程序版本,它工作正常,但不是内联汇编代码,而是一个适当的函数,它增加了另外 6 个周期(用于调用和 ret)。
非常欢迎任何意见或建议!
【问题讨论】:
-
您是要反转表中的值,还是使用表反转值?如果是后者,为什么不将表声明为常量:
uint8_t const BitReverseTable[]?另外,为什么不简单地使用BitReverseTable[25]而不是宏呢? -
1.它必须很快,所以表格位置的计算是关闭的。 2.它是哈佛架构,几乎没有内存,所以表必须在prgmem中。我会使用 pgm_read_byte,但我需要对齐技巧来加快速度。
-
您也可以查看此解决方案(更简单且少于 20 个周期):stackoverflow.com/questions/61179846/…