簡體   English   中英

memory開頭分配的成員變量

[英]Member variable allocated at start of memory

我正在嘗試在使用 gcc 編譯的 STM32 設備上使用 c++。該設備加載代碼並開始執行它,但在寫入任何成員變量時出現硬故障。

我可以看到 GDB 成員變量存儲在 memory 的開頭(具體為 0x7),當然 STM32 硬故障在第一次寫入該位置時出現。

我可以看到,除非我在 main 中聲明一個變量(在最終的 elf 文件中使用 readelf),否則不會生成 BSS 部分。

成員變量不應該放在bss里嗎?

我正在使用-nostdlib -mcpu=cortex-m0plus -fno-exceptions -O0 -g編譯和鏈接。

linker 腳本是:


ENTRY(start_of_memory);

MEMORY {

    rom (rx)  : ORIGIN = 0x08000000, LENGTH = 16K
    ram (xrw) : ORIGIN = 0x20000000, LENGTH = 2K

}

SECTIONS {

    .text : {
        *(.text)
    } > rom

    .data : { 
        *(.data)
        *(.data.*)
    } > ram

    .bss : { 
        *(.bss)
        *(.bss.*)
        *(COMMON)
    } > ram

}

readelf的output(沒有聲明變量,只有object的用法):

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x8000000
  Start of program headers:          52 (bytes into file)
  Start of section headers:          76536 (bytes into file)
  Flags:                             0x5000200, Version5 EABI, soft-float ABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         1
  Size of section headers:           40 (bytes)
  Number of section headers:         14
  Section header string table index: 13

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        08000000 010000 0005a8 00  AX  0   0  4
  [ 2] .rodata           PROGBITS        080005a8 0105a8 00005c 00   A  0   0  4
  [ 3] .ARM.attributes   ARM_ATTRIBUTES  00000000 010604 00002d 00      0   0  1
  [ 4] .comment          PROGBITS        00000000 010631 000049 01  MS  0   0  1
  [ 5] .debug_info       PROGBITS        00000000 01067a 000a93 00      0   0  1
  [ 6] .debug_abbrev     PROGBITS        00000000 01110d 0003b8 00      0   0  1
  [ 7] .debug_aranges    PROGBITS        00000000 0114c5 000060 00      0   0  1
  [ 8] .debug_line       PROGBITS        00000000 011525 000580 00      0   0  1
  [ 9] .debug_str        PROGBITS        00000000 011aa5 000416 01  MS  0   0  1
  [10] .debug_frame      PROGBITS        00000000 011ebc 000228 00      0   0  4
  [11] .symtab           SYMTAB          00000000 0120e4 000640 10     12  86  4
  [12] .strtab           STRTAB          00000000 012724 000344 00      0   0  1
  [13] .shstrtab         STRTAB          00000000 012a68 00008f 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  y (purecode), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x010000 0x08000000 0x08000000 0x00604 0x00604 R E 0x10000

 Section to Segment mapping:
  Segment Sections...
   00     .text .rodata 

There is no dynamic section in this file.

There are no relocations in this file.

There are no unwind sections in this file.

Symbol table '.symtab' contains 100 entries:

Main(初始化平台可能不使用任何變量):

int main(void) {

    init_platform(SPEED_4_MHz);

    gpio testpin(GPIO_A, 5);
    testpin.dir(MODE_OUTPUT);

    while (1) {

        testpin.high();
        wait();
        testpin.low();
        wait();
    }

    return 0;
    
}

更新#1:

向量表在memory開頭,sp和msp初始化成功。

(gdb) p/x *0x00000000
$2 = 0x20000700
(gdb) p/x *0x00000004
$3 = 0x80000f1
(gdb) info registers
sp             0x20000700          0x20000700
lr             0xffffffff          -1
pc             0x80000f6           0x80000f6 <main()+6>
xPSR           0xf1000000          -251658240
msp            0x20000700          0x20000700
psp            0xfffffffc          0xfffffffc

在 GPIO class 的構造函數上放置斷點,我可以看到變量位於 0x00000XXX

Breakpoint 2, gpio::gpio (this=0x7, port=0 '\000', pin=5 '\005') at gpio.cpp:25
25              mypin = pin;
(gdb) p/x &mypin
$6 = 0xb

我試圖讓 mypin 成為一個公共成員變量(是私有的),沒有做任何改變。

開始認為C++需要動態分配。

地址0x7在 ROM 的初始向量表中,不可寫。

不幸的是,您沒有用於填充向量表的部分,因此此代碼永遠不會起作用。 您似乎也沒有堆棧,這是放置gpio成員的地方(因為它是在 function 中定義的,沒有 static 關鍵字)。

首先采用作為 STM32Cube package 的一部分提供的 linker 腳本,然后(如果必須的話)一次稍微修改它,直到你破壞它。 然后你就會知道你弄壞了什么。 編寫這樣一個天真的 linker 腳本並期望它在微控制器上運行是不合理的。

當然,STM32 在第一次寫入該位置時會出現硬故障。

如果您嘗試寫入 FLASH,STM32 不會“出錯”。它不會產生任何影響。

您需要在 FLASH memory 的開頭有一個向量表。它必須包含最小有效堆棧指針地址和固件入口點。

您的 linker 腳本和代碼(我知道您不使用任何 STM 提供的啟動代碼)遠遠不夠。

我的建議:

  1. 使用 STM32Cube 創建項目。
  2. 然后看看應該怎么做
  3. 有了這些知識,你就可以開始重新發明輪子了

實際問題不在 linker 腳本中,在啟動代碼中或在 gcc 中,而是在我使用 GDB 啟動程序的方式中。

我正在通過批處理文件啟動 GDB

toolchain\bin\arm-none-eabi-gdb.exe ^
    -ex "target remote 127.0.0.1:3333"  ^
    -ex "load"  ^
    -ex "b main" ^
    -ex "b unmanaged_isr_call"  ^
    -ex "b hard_fault_isr"  ^
    -ex "j main" binaries\main.elf

問題是最后一條指令j main 將腳本更改為:

toolchain\bin\arm-none-eabi-gdb.exe ^
    -ex "target remote 127.0.0.1:3333"  ^
    -ex "load"  ^
    -ex "b unmanaged_isr_call"  ^
    -ex "b hard_fault_isr"  ^
    -ex "set $pc = &main" binaries\main.elf

成功了。

我嘗試了這種啟動程序的新方法,因為我將所有內容重寫為 C,並且在局部變量上遇到了同樣的問題。 我還注意到我在啟動時看到的第一個地址(是 main+OFF)和向量表中的主地址之間有一點偏移,所以我試圖從 gdb 命令行中刪除跳轉指令。 GDB 在 main 開始之前啟動了一些,可能缺少我在其中定義的局部變量的 POP。 這樣做也使問題在 C++ 中消失,class 現在工作正常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM