为什么__libc_init_array会导致异常?

2019-07-14 17:30发布

经过很长一段时间试图调试为什么我的STM32F446RE微控制器的简单闪烁代码无法正常工作后,我在启动组件文件中发现了一条我正在链接到它的行,导致异常将微控制器推入无限循环异常处理程序。
这是主要代码:
  1. <font size="4">.syntax unified
  2.   .cpu cortex-m4
  3.   .fpu softvfp
  4.   .thumb

  5. .global  g_pfnVectors
  6. .global  Default_Handler

  7. /* start address for the initialization values of the .data section.
  8. defined in linker script */
  9. .word  _sidata
  10. /* start address for the .data section. defined in linker script */  
  11. .word  _sdata
  12. /* end address for the .data section. defined in linker script */
  13. .word  _edata
  14. /* start address for the .bss section. defined in linker script */
  15. .word  _sbss
  16. /* end address for the .bss section. defined in linker script */
  17. .word  _ebss
  18. /* stack used for SystemInit_ExtMemCtl; always internal RAM used */

  19. /**
  20. * [url=home.php?mod=space&uid=2666770]@Brief[/url]  This is the code that gets called when the processor first
  21. *          starts execution following a reset event. Only the absolutely
  22. *          necessary set is performed, after which the application
  23. *          supplied main() routine is called.
  24. * @param  None
  25. * @retval : None
  26. */

  27.     .section  .text.Reset_Handler
  28.   .weak  Reset_Handler
  29.   .type  Reset_Handler, %function
  30. Reset_Handler:  
  31.   ldr   sp, =_estack      /* set stack pointer */

  32. /* Copy the data segment initializers from flash to SRAM */  
  33.   movs  r1, #0
  34.   b  LoopCopyDataInit

  35. CopyDataInit:
  36.   ldr  r3, =_sidata
  37.   ldr  r3, [r3, r1]
  38.   str  r3, [r0, r1]
  39.   adds  r1, r1, #4

  40. LoopCopyDataInit:
  41.   ldr  r0, =_sdata
  42.   ldr  r3, =_edata
  43.   adds  r2, r0, r1
  44.   cmp  r2, r3
  45.   bcc  CopyDataInit
  46.   ldr  r2, =_sbss
  47.   b  LoopFillZerobss
  48. /* Zero fill the bss segment. */  
  49. FillZerobss:
  50.   movs  r3, #0
  51.   str  r3, [r2], #4

  52. LoopFillZerobss:
  53.   ldr  r3, = _ebss
  54.   cmp  r2, r3
  55.   bcc  FillZerobss

  56. /* Call the clock system intitialization function.*/
  57.   bl  SystemInit   
  58. /* Call static constructors */
  59.       bl __libc_init_array
  60. /* Call the application's entry point.*/
  61.   bl  main
  62.   bx  lr   
  63. .size  Reset_Handler, .-Reset_Handler

  64. /**
  65. * @brief  This is the code that gets called when the processor receives an
  66. *         unexpected interrupt.  This simply enters an infinite loop, preserving
  67. *         the system state for examination by a debugger.
  68. * @param  None     
  69. * @retval None      
  70. */
  71.     .section  .text.Default_Handler,"ax",%progbits
  72. Default_Handler:
  73. Infinite_Loop:
  74.   b  Infinite_Loop
  75.   .size  Default_Handler, .-Default_Handler
  76. </font>
复制代码
导致异常的行是:/* Call static constructors */      bl __libc_init_array这导致微控制器跳转到最终导致异常的函数,从而跳转到Default_Handler无限循环。您可能会注意到,此次通话后直接__libc_init_array进入我的入口点main。如果我bl __libc_init_array完全评论我的程序实际上工作正常; 它跳进main并继续运行代码以使我的LED闪烁。
我做了一ARM-none-eabi-objdump -D blink.elf > blink.list' to see what __libc_init_array件事。这是功能:
  1. <font size="4">08000608 <__libc_init_array>:
  2. 8000608:   e92d4070    push    {r4, r5, r6, lr}
  3. 800060c:   e59f6064    ldr r6, [pc, #100]  ; 8000678 <__libc_init_array+0x70>
  4. 8000610:   e59f5064    ldr r5, [pc, #100]  ; 800067c <__libc_init_array+0x74>
  5. 8000614:   e0656006    rsb r6, r5, r6
  6. 8000618:   e1b06146    asrs    r6, r6, #2
  7. 800061c:   13a04000    movne   r4, #0
  8. 8000620:   0a000005    beq 800063c <__libc_init_array+0x34>
  9. 8000624:   e2844001    add r4, r4, #1
  10. 8000628:   e4953004    ldr r3, [r5], #4
  11. 800062c:   e1a0e00f    mov lr, pc
  12. 8000630:   e12fff13    bx  r3
  13. 8000634:   e1560004    cmp r6, r4
  14. 8000638:   1afffff9    bne 8000624 <__libc_init_array+0x1c>
  15. 800063c:   e59f603c    ldr r6, [pc, #60]   ; 8000680 <__libc_init_array+0x78>
  16. 8000640:   e59f503c    ldr r5, [pc, #60]   ; 8000684 <__libc_init_array+0x7c>
  17. 8000644:   e0656006    rsb r6, r5, r6
  18. 8000648:   eb000104    bl  8000a60 <_init>
  19. 800064c:   e1b06146    asrs    r6, r6, #2
  20. 8000650:   13a04000    movne   r4, #0
  21. 8000654:   0a000005    beq 8000670 <__libc_init_array+0x68>
  22. 8000658:   e2844001    add r4, r4, #1
  23. 800065c:   e4953004    ldr r3, [r5], #4
  24. 8000660:   e1a0e00f    mov lr, pc
  25. 8000664:   e12fff13    bx  r3
  26. 8000668:   e1560004    cmp r6, r4
  27. 800066c:   1afffff9    bne 8000658 <__libc_init_array+0x50>
  28. 8000670:   e8bd4070    pop {r4, r5, r6, lr}
  29. 8000674:   e12fff1e    bx  lr
  30. 8000678:   08000aac    stmdaeq r0, {r2, r3, r5, r7, r9, fp}
  31. 800067c:   08000aac    stmdaeq r0, {r2, r3, r5, r7, r9, fp}
  32. 8000680:   08000ab4    stmdaeq r0, {r2, r4, r5, r7, r9, fp}
  33. 8000684:   08000aac    stmdaeq r0, {r2, r3, r5, r7, r9, fp}</font>
复制代码
但我并不流利的装配,所以我真的不知道它想要完成什么或产生什么。除了我的main.c之外,我唯一包含的其他源文件和启动程序集是system_stm32f4xx.c由cubeMX生成的(SystemInit调用的地方),但它没有调用函数__libc_init_array。那么这个__libc_init_array功能来自哪里?为什么它会导致异常(将我的micro踢到异常处理程序)?以及如何防止这种情况(除了明显编写我自己的启动程序集而不包括无关的自动生成的文件)?这是我用来构建代码的makefile:
  1. #-{ Project Relative Paths }----------------------------------------------------

  2. # executables, intermediate objects, and libraries.
  3. BIN= ./binary
  4. # program source files
  5. SRC= ./source
  6. # on-architecture specific header files
  7. BHD= ./header
  8. # architecture/device specific files
  9. ARC= ./architecture
  10. # pre-compiled libraries that the project will link against
  11. LIB= ./library

  12. #-{ Compiler Definitions }------------------------------------------------------

  13. #include directories
  14. INC= $(ARC)/CMSIS/inc
  15.      $(ARC)/HAL/inc
  16.      $(ARC)/inc
  17.      $(header)

  18. INC_PARAMS= $(INC:%=-I%)

  19. # Compiler
  20. CC = arm-none-eabi-gcc

  21. # Device specific flags [1]
  22. # -mcpu=cortex-m4 sets target CPU
  23. # -mthumb tells gcc to compile to thumb2 instructions
  24. DFLAGS = -mcpu=cortex-m4 -mthumb

  25. # Compiler flags
  26. CFLAGS = $(DFLAGS) -g -c -Wall -Wextra

  27. #-{ Linker Definitions }------------------------------------------------------

  28. # Linker
  29. LD = arm-none-eabi-gcc #same as compilter but uses different flags

  30. # Path to linker script #linking script
  31. LSCRIPT = $(ARC)/STM32F446RETx_FLASH.ld

  32. # Linker flags
  33. LFLAGS = -T $(LSCRIPT) --specs=nosys.specs

  34. # Object copy (for converting formats)
  35. OBJCOPY = arm-none-eabi-objcopy
  36. OFLAGS = -O ihex
  37. OFLAGSbin = -O binary

  38. #-{ Programming/Debugging Definitions }-----------------------------------------

  39. # Debugger
  40. DBG = arm-none-eabi-gdb

  41. # OpenOCD
  42. OCD = openocd

  43. # Debug/programming interface configuration file
  44. INTRF = /usr/local/share/openocd/scripts/interface/stlink-v2-1.cfg
  45. # Target device configurations file
  46. OCDTARGET = /usr/local/share/openocd/scripts/target/stm32f4x.cfg
  47. OCDBOARD = /usr/local/share/openocd/scripts/board/st_nucleo_f4.cfg

  48. #-{ Build Rules }---------------------------------------------------------------

  49. # Final binaries
  50. HEX = $(BIN)/blink.hex
  51. ELF =  $(BIN)/blink.elf
  52. binfile = $(BIN)/blink.bin

  53. # All intermediate object files
  54. OBJ = $(BIN)/blink.o $(BIN)/boot.o $(BIN)/init.o

  55. #-- These rules for the final binaries will usually not require modification

  56. # Convert the ELF into intel hex format
  57. $(HEX): $(ELF)
  58.     $(OBJCOPY) $(OFLAGS) $(ELF) $(HEX)

  59. #convert the ELF into binary format
  60. $(binfile): $(ELF)
  61.     $(OBJCOPY) $(OFLAGSbin) $(ELF) $(binfile)

  62. # Link all intermediate objects into a single executable
  63. $(ELF): $(OBJ)
  64.     $(LD) $(LFLAGS) $(OBJ) -o $(ELF)

  65. #-- These rules will vary depending on the program being built

  66. # Compile the main file
  67. $(BIN)/blink.o: $(SRC)/blink.c $(ARC)/CMSIS/inc/stm32f4xx.h
  68.     $(CC) $(CFLAGS) $(INC_PARAMS) $(SRC)/blink.c -o $(BIN)/blink.o

  69. # Compile the reset handler
  70. $(BIN)/boot.o: $(ARC)/CMSIS/src/startup_stm32f446xx.S
  71.     $(CC) $(CFLAGS) $(INC_PARAMS) $(ARC)/CMSIS/src/startup_stm32f446xx.S -o $(BIN)/boot.o

  72. #compile the post-reset, pre-main, system handler
  73. $(BIN)/init.o: $(ARC)/CMSIS/src/system_stm32f4xx.c
  74.     $(CC) $(CFLAGS) $(INC_PARAMS) $(ARC)/CMSIS/src/system_stm32f4xx.c -o $(BIN)/init.o


  75. #-{ Utility Rules }-------------------------------------------------------------

  76. # OpenOCD command to program a board
  77. program: $(HEX)
  78.     [url=home.php?mod=space&uid=1361969]@sudo[/url] -E $(OCD) -f $(INTRF) -f $(OCDTARGET) -c "program $(ELF) verify reset exit"

  79. # OpenOCD command to load a program and launch GDB
  80. debug: $(ELF)
  81.     @(sudo -E $(OCD) -f $(INTRF) -f $(OCDTARGET) &);
  82.     $(DBG) $(ELF) -ex "target remote localhost:3333; load";
  83.     sudo kill $(OCD)

  84. # Build the entire program
  85. all: $(HEX) $(binfile)

  86. # Delete all of the generated files
  87. clean:
  88.     rm $(OBJ) $(HEX) $(ELF) $(binfile)

  89. # Delete all intermediate object files
  90. tidy:
  91.     rm $(OBJ)
复制代码
除了blink.c我使用system_stm32f4xx.c哪个有system_init函数。

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。