问题描述
armcc.exe V5.06 (750) 请让我知道为什么一旦 val16 溢出并变得小于 start_count,标记为错误的代码就不起作用。循环不再退出。
HAL_GetTick() 返回 uint32_t(或 int)
unsigned short start_count;
unsigned short val16;
unsigned short result;
start_count = HAL_GetTick();
//This does not work
do
{
val16 = HAL_GetTick();
result = val16 - start_count;
}
while ((val16 - start_count) < 100); //this part does not work correctly
//when val16 overflows
//This works! same code logic
do
{
val16 = HAL_GetTick();
result = val16 - start_count;
}
while (result < 100);
`
解决方法
首先 - 不要在没有特殊需要的情况下使用较短的类型,因为它通常会在 32 位 RISC 目标上增加额外的开销。
第一个 while 不起作用,因为算术是使用整数而不是无符号短值完成的,给出了意想不到的结果:)。这里有一个演示程序:
unsigned HAL_GetTick(void)
{
static unsigned tick = 65535 - 5;
return tick++;
}
int main(void)
{
unsigned short val16;
unsigned short result;
unsigned short start_count;
start_count = HAL_GetTick();
//This does not work
do
{
val16 = HAL_GetTick();
result = val16 - start_count;
printf("%d %d\n",(val16 - start_count) < 100,(val16 - start_count));
}
while ((val16 - start_count) < 100); //this part does not work correctly
//when val16 overflows
//This works! same code logic
do
{
val16 = HAL_GetTick();
result = val16 - start_count;
}
while (result < 100);
}
第二个循环使用 unsigned short 类型,并且在计算结果时不会隐式转换。
现在是使用 ARM Cortex 内核的非本机整数的问题。
示例程序:
volatile uint32_t tick;
uint32_t HAL_GetTick(void)
{
return tick;
}
void foo(void)
{
unsigned short val16;
unsigned short result;
unsigned short start_count;
start_count = HAL_GetTick();
//This works! same code logic
do
{
val16 = HAL_GetTick();
result = val16 - start_count;
}
while (result < 100);
}
void bar(void)
{
uint32_t val16;
uint32_t result;
uint32_t start_count;
start_count = HAL_GetTick();
//This works! same code logic
do
{
val16 = HAL_GetTick();
result = val16 - start_count;
}
while (result < 100);
}
和结果代码:
foo:
ldr r1,.L9
ldr r2,[r1]
lsl r2,r2,#16
lsr r2,#16
.L6:
ldr r3,[r1]
sub r3,r3,r2
lsl r3,#16
lsr r3,#16
cmp r3,#99
bls .L6
bx lr
.L9:
.word tick
bar:
ldr r2,.L15
ldr r1,[r2]
.L12:
ldr r3,[r2]
sub r3,r1
cmp r3,#99
bls .L12
bx lr
.L15:
.word tick
如您所见,使用 16 位整数的版本效率低于使用 32 位本机大小整数的版本。