我正在开源环境中使用arm-none-eabi-gcc v4.9.3 为ARM stm32 微 Controller 编译C 代码。 代码无需编译器优化即可正常运行(gcc -g -O0 ...)。
当我启用哪怕最轻微的优化(gcc -g -O1 ...)时,链接器定义的变量的地址都会更改。
文件内存.ld
register_cortexm3_ACTLR = 0xe000e008;
...
MEMORY
{
rom (rx ) : ORIGIN = 0x08000000, LENGTH = 256K
ram (rxw) : ORIGIN = 0x20000000, LENGTH = 64K
sram_bitband (rw ) : ORIGIN = 0x22000000, LENGTH = 32768K
peripheral (rw ) : ORIGIN = 0x40000000, LENGTH = 1024K
peripheral_bitband (rw ) : ORIGIN = 0x42000000, LENGTH = 32768K
sram (rwx) : ORIGIN = 0x60000000, LENGTH = 1048576K
ram_external (rwx) : ORIGIN = 0x60000000, LENGTH = 1048576K
code (rwx) : ORIGIN = 0x60000000, LENGTH = 1048576K
device_external (rw ) : ORIGIN = 0xa0000000, LENGTH = 1048576K
private_peripheral (rw ) : ORIGIN = 0xe0000000, LENGTH = 1024K
vendor_memory (rw ) : ORIGIN = 0xe0100000, LENGTH = 523264K
}
SECTIONS
{
/* Section for variables mapped onto registers */
.peripherals (OVERLAY) :
{
. = ALIGN(4);
*(.peripherals)
} >peripheral
.private_peripherals (OVERLAY) :
{
. = ALIGN(4);
*(.private_peripherals)
} >private_peripheral
...
文件register_cortexm3.h
typedef struct {
unsigned DISMCYCINT : 1;
unsigned DISDEFWBUF : 1;
unsigned DISFOLD : 1;
unsigned reserved1 : 13;
unsigned reserved2 : 16;
} __attribute__( ( __packed__ ) ) register_cortexm3_actlr_t;
...
文件register_cortexm3.c
void check_same( volatile void* Address1, volatile void* Address2 ) {
if ( Address1 != Address2 )
{ Assert_Halt_EC( ec_InvalidImplementation ); }
}
volatile register_cortexm3_actlr_t register_cortexm3_ACTLR
__attribute__( ( section( ".private_peripherals" ) ) );
void register_cortexm3_prepare() {
// checking for correct linker script settings
check_same(&( register_cortexm3_ACTLR ), ( volatile void* ) 0xe000e008);
}
当启用优化时,上述比较失败,因为在 check_same() 函数内部,根据 gdb,第一个参数是 0xe0000000(其内存部分的起始地址):
Breakpoint 1, Assert_Halt_EC (ErrorCode=ErrorCode@entry=ec_InvalidImplementation) at ttc-lib/ttc_basic.c:65
65 void Assert_Halt_EC( volatile ErrorCode_e ErrorCode ) { // block endless
(gdb) up
#1 0x08004440 in check_same (Address1=Address1@entry=0xe0000000, Address2=Address2@entry=0xe000e008) at ttc-lib/ttc_basic.c:58
58 { Assert_Halt_EC( ec_InvalidImplementation ); }
(gdb) up
#2 0x080034f6 in register_cortexm3_prepare () at ttc-lib/register/register_cortexm3.c:40
40 Assert_SameAddress( &( register_cortexm3_ACTLR ), ( void* ) 0xe000e008 );
(gdb) x &( register_cortexm3_ACTLR )
0xe000e008: 0x00000000
正如您在最后一个 gdb 输出行中看到的,gdb 知道 register_cortexm3_ACTLR 的正确地址。
这是 gcc 错误还是功能? 如何解决这个问题?
最佳答案
我不确定为什么优化会对此产生任何影响,但基本问题是您给出了符号 register_cortexm3_ACTLR
的两个不同且相互冲突的定义。链接描述文件中的一个定义表示它位于任何节中的地址 0xe000e008,而 C 代码中的另一个定义表示它位于 .private_peripherals
节的某个偏移处。
您需要选择其中之一。如果您希望变量位于链接描述文件中给定的地址处,请使用 extern
来引用它。像这样的东西:
extern volatile register_cortexm3_actlr_t register_cortexm3_ACTLR;
关于c - gcc 在优化期间更改映射变量的地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34032021/