代码之家  ›  专栏  ›  技术社区  ›  Anthony

GDB不会在断点上停止并继续

  •  0
  • Anthony  · 技术社区  · 4 年前

    我是嵌入式编程的初学者,所以为了学习,我试图使用一个极简主义程序。我尝试执行以下程序。
    我的环境:

    • arm none eabi gcc(15:9-2019-q4-ubuntu1)9.2.1 20191025(发布)[arm/arm-9-分支版本277599]
    • gdb multiarch GNU gdb(Ubuntu 9.1-0ubuntu1)9.1
    • 打开片上调试器0.10.0
    • STM32F3Discovery -ARM Cortex-M4

    main.c

    int main(void)
    {
    }
    
    
    __attribute__((section(".isr_vector"))) void Reset_Handler(void)
    {
    
      char * my_pointer = (char *)0x20000000;
      *my_pointer = 42;
      main();
      while(1) {
    
      }
    }
    

    stm32.ld

    MEMORY
    {
        FLASH : ORIGIN = 0x08000000, LENGTH = 256K
        RAM : ORIGIN = 0x20000000, LENGTH = 48K
    }
    
    start = Reset_Handler;
    ENTRY(Reset_Handler)
    
    SECTIONS
    {
        .isr_vector :
        {
        *(.isr_vector)
        } >FLASH
        .text :
        {
        *(.text)
        } >FLASH
    }
    

    所有内容都使用以下命令编译: arm-none-eabi-gcc -mthumb -march=armv7e-m -mcpu=cortex-m4 -nostdlib -Tstm32.ld -g -o main.elf main.c .
    这个程序什么也不做,它只是试图让它运行并在内存中写入一些东西。

    使用OpenCD和GDB,我将程序加载到板上,以下是我得到的结果 layout asm 在GDB。

    |  >0x8000000 <Reset_Handler>       push    {r7, lr}                                                                          │
    │   0x8000002 <Reset_Handler+2>     sub     sp, #8                                                                            │
    │   0x8000004 <Reset_Handler+4>     add     r7, sp, #0                                                                        │
    │   0x8000006 <Reset_Handler+6>     mov.w   r3, #536870912  ; 0x20000000                                                      │
    │   0x800000a <Reset_Handler+10>    str     r3, [r7, #4]                                                                      │
    │   0x800000c <Reset_Handler+12>    ldr     r3, [r7, #4]                                                                      │
    │   0x800000e <Reset_Handler+14>    movs    r2, #42 ; 0x2a                                                                    │
    │   0x8000010 <Reset_Handler+16>    strb    r2, [r3, #0]                                                                      │
    │   0x8000012 <Reset_Handler+18>    bl      0x8000018 <main>                                                                  │
    │   0x8000016 <Reset_Handler+22>    b.n     0x8000016 <Reset_Handler+22>                                                      │
    │   0x8000018 <main>                push    {r7}                                                                              │
    │   0x800001a <main+2>              add     r7, sp, #0                                                                        │
    │   0x800001c <main+4>              movs    r3, #0                                                                            │
    │   0x800001e <main+6>              mov     r0, r3                                                                            │
    │   0x8000020 <main+8>              mov     sp, r7                                                                            │
    │   0x8000022 <main+10>             pop     {r7}                                                                              │
    │   0x8000024 <main+12>             bx      lr
    

    我的程序似乎是在闪存的开头加载的,我在Reset_Handler上启动,但我无法一步一步地运行,我甚至不确定程序是否正在运行。 如果我添加断点或使用 step 我得到:

    (gdb) b 11
    Breakpoint 1 at 0x8000006: file main.c, line 11.
    (gdb) continue
    Continuing.
    Note: automatically using hardware breakpoints for read-only addresses.
    

    我已经阅读了以下问题/答案,但这没有帮助。我想我的程序的链接无效,或者我可能在没有初始化的情况下什么都做不了。

    注意:我可以在板上运行一个非常简单的汇编程序并对其进行调试,但嵌入式C&连接部分是相当新的。

    0 回复  |  直到 4 年前
        1
  •  2
  •   0___________    4 年前

    你的代码根本错误。

    首先

    __attribute__((section(".isr_vector"))) void Reset_Handler(void)
    

    错了。flash的开头是向量表的默认位置,而不是处理程序代码。

    矢量表有特定的格式,必须遵循:

    前4个字节是初始堆栈指针值

    第二个4字节是重置处理程序例程代码的地址。

    接下来的32位字是其他异常和中断处理程序的地址。

    MEMORY
    {
        FLASH : ORIGIN = 0x08000000, LENGTH = 256K
        RAM : ORIGIN = 0x20000000, LENGTH = 48K
    }
    
    start = Reset_Handler;
    ENTRY(Reset_Handler)
    
    _RAM_END = ORIGIN(RAM_START) + 48K; 
    
    SECTIONS
    {
        .isr_vector :
        {
        *(.isr_vector)
        } >FLASH
        .text :
        {
        *(.text)
        } >FLASH
    }
    

    然后是C文件。

    extern uint32_t _RAM_END;
    
    void Reset_Handler(void);
    
    void __attribute__((section(".isr_vector"))) (*vector_tabler[])(void) = {(void (*)(void))&_RAM_END, Reset_Handler};
    
    int main(void)
    {
    }
    
    
    void Reset_Handler(void)
    {
    
      char * my_pointer = (char *)0x20000000;
      *my_pointer = 42;
      main();
      while(1) {
    
      }
    }
    

    顺便说一句,我建议你在开始做非常低级的事情之前先阅读一下文档。我建议在获得足够的知识和经验进行修改(或从头开始编写新的)之前,使用STM32提供的启动文件和链接器脚本。