MDK对浮点支持有bug吗?

2020-01-11 18:09发布

最近调试stm32f103平台上调试pid,发现函数参或者返回值若使用float型,则总会出问题,发现传进去的参数或者返回来的的值并非本来赋的那个值,百思不得其解.但若使用指针传递则完全正常。难道使用浮点有什么特殊操作吗?
举个例子.
float pid_cal(float in)
{
float ret=0.012;
……
printf("in=%f ",in);
return ret;
}

调用函数pid_cal(2.5); 函数打印出in=xxxx.xxxx。是一个很大的值,并非2.5
同理printf("pid_val=%f ",pid_cal(3.0));打印出来也不是期望的0.012

如改成指针形式则正常如
void pid_cal(float *in,float *out)
{
float ret=0.012;
……
printf("in=%f ",*in);
*out=ret;
}

float t=2.5;
float out_val;
pid_cal(&t,&out_val);
这样使用就不会有问题.

我觉得MDK不至于这么弱智吧?有人碰到过吗?
还是我的MDK破解有问题?
之前用的MDK4.6就有这个问题,后来还特地升级到4.73,发现问题依旧
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
21条回答
szyusong@163
1楼-- · 2020-01-14 14:12
2楼正解。需要确保堆栈是8字节对齐的,否则打印输出是错误的。
szyusong@163
2楼-- · 2020-01-14 14:32
Eight-byte Stack Alignment

What is eight-byte stack alignment?
Eight byte stack alignment is a requirement of the Procedure Call Standard for the ARM Architecture [AAPCS]. This specifies that functions must maintain an eight-byte aligned stack address (for example: 0x00, 0x08, 0x10, 0x18, 0x20) on all external interfaces. In practice this requirement is met if:

At each external interface, the current stack pointer (SP) is a multiple of eight bytes.
Your OS maintains eight-byte stack alignment on its external interfaces, for example, on task switches
Eight-byte stack alignment is of particular benefit to processors supporting LDRD and STRD instructions, for example, processors based on ARM architecture v5TE and later. If the stack is not eight-byte aligned the use of LDRD and STRD might cause an alignment fault, depending on the target and configuration used.

Eight-byte stack alignment in RVCT and the ARM Compiler toolchain
In the RVCT v2.0 and above, all generated code and C library code will maintain eight-byte stack alignment on external interfaces. The generated code may not keep the stack eight-byte aligned internally, for example, in leaf functions. However all generated code will keep the stack eight-byte aligned providing that it is already correctly aligned at the entry to the function. The compiler will not generate code to correct a misaligned stack.

Please be aware that eight-byte stack alignment is not new to RVDS. ADS does maintain eight-byte stack alignment, only the alignment of double and long long has changed between ADS and RVDS. In ADS double and long long data types were four-byte aligned ("EBA4"), unless -Oldrd or __align were used. In RVCT 2.0 and later, double and long long data types are now eight-byte aligned ("EBA8"), unless --apcs /adsabi is used.

The RVCT 3.1 compiler and earlier supports the option --apcs /adsabi to compile code that is compatible with the old ADS ABI. However, this option was deprecated and finally removed in RVCT 4.0.

The ARM Compiler toolchain check eight byte stack alignment using two build attributes REQUIRE8 and PRESERVE8, these can either be true or false. These are embedded into the object files and executables generated by the tools. REQUIRE8 is used to indicate that the code requires the stack pointer to be eight-byte aligned. PRESERVE8 is used to indicate that the code preserves eight-byte stack alignment.

The assembler uses the REQUIRE8 and PRESERVE8 directives to indicate whether REQUIRE8 and PRESERVE8 build attributes should be true or false. If you omit PRESERVE8 the assembler will decide whether to set the PRES8 build attribute or not, by examining instructions that modify SP. ARM recommends that you specify PRESERVE8 explicitly. If your assembly requires the stack to be eight byte aligned, for example, an LDRD using SP, you should specify the REQUIRE8 directive.

In RVCT 2.1 and later the assembler (armasm) can generate a warning if it detects a stack access that would leave the stack not eight-byte aligned. This can be enabled by adding --diag_warning 1546 to your assembler command line.

The REQUIRE8 and PRESERVE8 build attributes set by the compiler and assembler are used by the linker to prevent functions that require eight-byte alignment calling functions that do not preserve eight-byte alignment. If this occurs the linker will generate an error, for example:

Error: L6238E: foo.o(.text) contains invalid call from '~PRES8' function to 'REQ8' function
szyusong@163
3楼-- · 2020-01-14 17:29
Compiler eight-byte alignment features

The compiler has the following eight-byte alignment features:

The Procedure Call Standard for the ARM Architecture (AAPCS) requires that the stack is eight-byte aligned at all external interfaces. The compiler and C libraries preserve the eight-byte alignment of the stack. In addition, the default C library memory model maintains eight-byte alignment of the heap.
Code is compiled in a way that requires and preserves the eight-byte alignment constraints at external interfaces.
If you have assembly language files, or legacy objects, or libraries in your project, it is your responsibility to check that they preserve eight-byte stack alignment, and correct them if required.
In RVCT v2.0 and later, and in ARM Compiler 4.1 and later, double and long long data types are eight-byte aligned for compliance with the Application Binary Interface for the ARM Architecture (AEABI). This enables efficient use of the LDRD and STRD instructions in ARMv5TE and later.
The default implementations of malloc(), realloc(), and calloc() maintain an eight-byte aligned heap.
The default implementation of alloca() returns an eight-byte aligned block of memory.

一周热门 更多>