停止臂GCC优化输出功能调用
如何让ARM GCC不优化对停止臂GCC优化输出功能调用,gcc,arm,Gcc,Arm,如何让ARM GCC不优化对halIsBlank()的调用?编译器假定mcau8IsBlank[]总是==0xFF,因此只是将调用替换为0xFF常量 我可以通过在调用函数中添加\uuuu属性((优化(0))来禁用调用函数(someFuncInAnotherFile())的优化,但最好是在被调用函数中添加一些属性(halIsBlank())(而且我尝试过的属性或关键字似乎都不起作用)?如果一个对象被声明为常量,那么任何修改它的尝试都会导致未定义的行为。编译器可以假定常量对象是常量。您明确地抛弃了数
halIsBlank()
的调用?编译器假定mcau8IsBlank[]
总是==0xFF
,因此只是将调用替换为0xFF
常量
我可以通过在调用函数中添加
\uuuu属性((优化(0))
来禁用调用函数(someFuncInAnotherFile()
)的优化,但最好是在被调用函数中添加一些属性(halIsBlank()
)(而且我尝试过的属性或关键字似乎都不起作用)?如果一个对象被声明为常量,那么任何修改它的尝试都会导致未定义的行为。编译器可以假定常量对象是常量。您明确地抛弃了数组的易失性,因此编译器可以假定它在这一点上不是易失性的
我会删除(uint8_t*)的强制转换,这似乎毫无意义。so.c
volatile static const uint8_t mcau8IsBlank[] = {0xFF}; // Value in MCU FLASH memory
// The above value may actually be modified by a FLASH Write elsewhere in the code
bool halIsBlank() {
return ((*(uint8_t*)mcau8IsBlank));
}
void someFuncInAnotherFile() {
uint8_t data[64];
data[0] = halIsBlank(); // ARM GCC is optimising away this function call
// Replacing it simply with a 0xFF constant
// ... etc
// ... transmit data
}
四、c
const unsigned char one = 0x11;
unsigned char two = 0x22;
volatile unsigned char three = 0x33;
extern unsigned char four;
unsigned int get_one ( void )
{
return(one);
}
unsigned int get_two ( void )
{
return(two);
}
unsigned int get_three ( void )
{
return(three);
}
unsigned int get_four ( void )
{
return(four);
}
GNULD链接器脚本
unsigned char four = 0x44;
结果
MEMORY
{
rom : ORIGIN = 0x10000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*)
four.o(.data) } > rom
.rodata : { *(.rodata*) } > rom
.data : { *(.data*) } > ram
}
节的反汇编。文本:
10000000 :
10000000:20001000和CS r1、r0、r0
10000004:10000009 andne r0、r0、r9
10000008 :
10000008:e7fe b.n 10000008
...
1000000c:
1000000c:2011年电影节r0,#17
1000000e:4770 bx lr
10000010 :
1000010:4b01 ldr r3,[pc,#4];(10000018 )
1000012:7818 ldrb r0,[r3,#0]
1000014:4770 bx lr
1000016:bf00 nop
1000018:20000000和CS r0、r0、r0
100001C:
100001C:4b01 ldr r3,[pc,#4];(10000024 )
1000001e:7858 ldrb r0,[r3,#1]
10000020:4770 bx lr
10000022:bf00 nop
10000024:20000000和CS r0、r0、r0
10000028 :
10000028:4b01 ldr r3,[pc,#4];(10000030 )
1000002a:7818 ldrb r0,[r3,#0]
1000002c:4770 bx lr
1000002e:bf00 nop
1000030:1000034和NE r0、r0、r4、lsr r0
10000034 :
1000034:地址0x0000000010000034超出范围。
节段的拆卸。rodata:
10000035 :
1000035:地址0x0000000010000035超出范围。
分解截面。数据:
20000000 :
20000000:地址0x000000002000000超出范围。
20000001 :
2000001:地址0x00000000200001超出范围。
因为其中一个是const,所以本地函数会进行优化,但它也是全局函数,所以会添加到flash中(以防其他对象引用它)。将其设为静态,flash中的分配就会消失
第二个是简单的旧数据。必须以这种方式构建代码,链接器在链接时添加地址
第三个是volatile global,它的处理方式与第二个相同,因为它是全局的,并且在数据中,volatile在这里没有太多作用
如果你愿意的话,四是一个解决方案。在这个文件/优化域之外定义它,编译器必须生成代码以达到未知长度才能得到它。在链接器脚本中,告诉链接器将其放置在flash中。因此,虽然它是在闪存中,从技术上讲不是读/写的,但如果你有办法写闪存,那么这将起作用
事实上,它不会,因为当你擦去闪光灯改变四,你擦去了这个。文本代码的一部分。你需要知道擦除块是什么,把这些东西放在其中一个擦除块中,你必须把它们全部保存到ram中,如果你想改变其中一个,全部保存,擦除,写回所有内容,包括任何更改的值…并且很少可以在与正在擦除的闪存相同的闪存逻辑中执行,因此可能需要一个蹦床来执行此保存、擦除、恢复例程。(更多链接器魔法和复制并跳转)
在同一优化域中,一个函数调用另一个函数很可能会将其内联,因此您希望找到一个请不要内联的命令行选项,尽管在这种情况下这没有任何意义,您希望优化并可能使小函数保持静态,这样它就可以一起消失。将常量声明为volatile显然会导致它不再放在闪存中,而是放在RAM中。现在,我已经求助于将const暴露在文件之外并直接使用它,而不是使用函数调用。如果它在flash中,那么它是一个常量,可以进行优化(在其他文件中定义它,即使在flash中,它也可能至少进行访问)。将它放在自己的文件中,就像它是全局数据一样,但在闪存中链接它。静态也没有多大意义。您可以尝试通过在另一个节中创建变量,然后将该节添加到链接器脚本中,以控制它到达的位置。但是您要求使用const,const意味着没有更改,因此volatile是无用的,优化器将优化出它可以看到的const访问。老师也照你说的做了,谢谢!使用链接器脚本可能是最好的解决方案。变量/const最初声明为0xFF,位只能通过写入来清除,因此不会发生闪存擦除。请注意此处的拼写,尤其是包含撇号的单词。这里有一些正确的拼写,加上你的帖子历史记录中的拼写错误:不(765),不(488),不能(306),不会(217),不是(148)。对于那些没有英语作为第一语言的人来说,这里有一些宽容,但是文体和故意拼错的作品违背了网站的目标,并且是故意为志愿编辑做的大量工作。您的浏览器中有拼写检查程序吗?
Disassembly of section .text:
10000000 <_start>:
10000000: 20001000 andcs r1, r0, r0
10000004: 10000009 andne r0, r0, r9
10000008 <reset>:
10000008: e7fe b.n 10000008 <reset>
...
1000000c <get_one>:
1000000c: 2011 movs r0, #17
1000000e: 4770 bx lr
10000010 <get_two>:
10000010: 4b01 ldr r3, [pc, #4] ; (10000018 <get_two+0x8>)
10000012: 7818 ldrb r0, [r3, #0]
10000014: 4770 bx lr
10000016: bf00 nop
10000018: 20000000 andcs r0, r0, r0
1000001c <get_three>:
1000001c: 4b01 ldr r3, [pc, #4] ; (10000024 <get_three+0x8>)
1000001e: 7858 ldrb r0, [r3, #1]
10000020: 4770 bx lr
10000022: bf00 nop
10000024: 20000000 andcs r0, r0, r0
10000028 <get_four>:
10000028: 4b01 ldr r3, [pc, #4] ; (10000030 <get_four+0x8>)
1000002a: 7818 ldrb r0, [r3, #0]
1000002c: 4770 bx lr
1000002e: bf00 nop
10000030: 10000034 andne r0, r0, r4, lsr r0
10000034 <four>:
10000034: Address 0x0000000010000034 is out of bounds.
Disassembly of section .rodata:
10000035 <one>:
10000035: Address 0x0000000010000035 is out of bounds.
Disassembly of section .data:
20000000 <two>:
20000000: Address 0x0000000020000000 is out of bounds.
20000001 <three>:
20000001: Address 0x0000000020000001 is out of bounds.