停止臂GCC优化输出功能调用

停止臂GCC优化输出功能调用,gcc,arm,Gcc,Arm,如何让ARM GCC不优化对halIsBlank()的调用?编译器假定mcau8IsBlank[]总是==0xFF,因此只是将调用替换为0xFF常量 我可以通过在调用函数中添加\uuuu属性((优化(0))来禁用调用函数(someFuncInAnotherFile())的优化,但最好是在被调用函数中添加一些属性(halIsBlank())(而且我尝试过的属性或关键字似乎都不起作用)?如果一个对象被声明为常量,那么任何修改它的尝试都会导致未定义的行为。编译器可以假定常量对象是常量。您明确地抛弃了数

如何让ARM GCC不优化对
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.