我已经在使用-O3
,所以我一般认为我不能做得更好,但是生成的程序集仍然非常适合时序要求。例如,是否有一种方法可以告诉avr-gcc
将非速度关键的代码排除在速度关键的部分之外?
if (READY)
{
ACKNOWLEDGE();
SETUP_PART1();
SETUP_PART2();
//start speed-critical section
SYNC_TO_TIMER();
MINIMAL_SPEED_CRITICAL_CODE();
//end speed-critical section
CLEANUP();
}
对-O3
优化的程序集清单(.lss
文件)的单调乏味的阅读显示,SETUP_PART2();
已重新排序为介于SYNC_TO_TIMER();
和MINIMAL_SPEED_CRITICAL_CODE();
之间。这是一个问题,因为它增加了在速度关键部分不需要的时间。
我不想将关键部分本身制作得比需要的时间长,因此我不愿意放松优化。 (导致此问题的相同动作也可能是使最终版本在可用时间内适合您的原因)那么我怎么能告诉它“此行为”需要保持简洁,整洁,但仍要对其进行充分优化?
我以前使用过内联汇编,所以我确定我可以再次弄清楚如何在C和C之间进行通信,而不必完全占用或破坏寄存器等。但是如果我愿意,我宁愿坚持使用100%C可以,让编译器弄清楚如何不对其自身运行。
不是我要找的直接答案,但是我发现了一些可行的方法。因此,从技术上讲,这是一个XY问题,但我仍将直接回答上述问题。
这是我最终要做的:
void __attribute__((noinline)) _fast_function(uint8_t arg1, uint8_t arg2)
{
//start speed-critical section
SYNC_TO_TIMER();
MINIMAL_SPEED_CRITICAL_CODE(arg1, arg2);
//end speed-critical section
}
void normal_function(void)
{
if (READY)
{
ACKNOWLEDGE();
SETUP_PART1();
SETUP_PART2(); //determines arg1, arg2
_fast_function(arg1, arg2);
CLEANUP();
}
}
这将对速度要求苛刻的东西放在一起,而且靠自己。它也增加了一些开销,但是这超出了我可以负担得起的快速部分。
原始代码是这样的:
uint8_t data[3];
uint8_t byte_num = 3;
while(byte_num)
{
byte_num--;
uint8_t bit_mask = 0b10000000;
while(bit_mask)
{
if(data[byte_num] & bit_mask) WEIRD_OUTPUT_1();
else WEIRD_OUTPUT_0();
bit_mask >>= 1;
}
}
新代码如下:
#define WEIRD_OUTPUT(byte,bit) \
do \
{ \
if((byte) & (bit)) WEIRD_OUTPUT_1(); \
else WEIRD_OUTPUT_0(); \
} while(0)
uint8_t data[3];
WEIRD_OUTPUT(data[2],0b10000000);
WEIRD_OUTPUT(data[2],0b01000000);
WEIRD_OUTPUT(data[2],0b00100000);
WEIRD_OUTPUT(data[2],0b00010000);
WEIRD_OUTPUT(data[2],0b00001000);
WEIRD_OUTPUT(data[2],0b00000100);
WEIRD_OUTPUT(data[2],0b00000010);
WEIRD_OUTPUT(data[2],0b00000001);
WEIRD_OUTPUT(data[1],0b10000000);
WEIRD_OUTPUT(data[1],0b01000000);
WEIRD_OUTPUT(data[1],0b00100000);
WEIRD_OUTPUT(data[1],0b00010000);
WEIRD_OUTPUT(data[1],0b00001000);
WEIRD_OUTPUT(data[1],0b00000100);
WEIRD_OUTPUT(data[1],0b00000010);
WEIRD_OUTPUT(data[1],0b00000001);
WEIRD_OUTPUT(data[0],0b10000000);
WEIRD_OUTPUT(data[0],0b01000000);
WEIRD_OUTPUT(data[0],0b00100000);
WEIRD_OUTPUT(data[0],0b00010000);
WEIRD_OUTPUT(data[0],0b00001000);
WEIRD_OUTPUT(data[0],0b00000100);
WEIRD_OUTPUT(data[0],0b00000010);
WEIRD_OUTPUT(data[0],0b00000001);
除了删除循环代码本身之外,这还用直接访问替换了数组索引,并用常量替换了变量,每个常量都提供自己的加速。
而且它仍然无法适应现有时间。 但是确实合适!:)