Моя общая цель — иметь возможность вычислить контрольную сумму с помощью встроенного периферийного устройства CRC, чтобы я мог убедиться, что двоичный файл был правильно записан на плату. У меня есть рабочий скрипт Python, который просто копирует то, что делает периферийное устройство CRC, и затем я передаю его в файл .bin, чтобы получить контрольную сумму.
Пытаясь заставить мой скрипт работать, я заметил, что между разделами .isr_vector и разделами .text есть 8 байтов пространства, которые не совпадают между флэш-памятью и самим двоичным файлом. При отладке чипа все эти 8 байтов имеют размер 0xFF, но в двоичном виде они равны 0x00. Я знаю, что по умолчанию чип использует все 1, поэтому у меня есть смутное представление, почему они разные (или, по крайней мере, я так думаю), но я не знаю, почему вообще существует это пространство.
Большую часть вчерашнего вечера я провел, играя со сценарием компоновщика, перемещая флаги выравнивания и играя со значениями заполнения/дополнения. Использование «FILL(0xFF);» не влияет на это пространство, равно как и установка «=0xFF» в конце раздела. Флаги выравнивания перемещают объекты, но не оказывают никакого влияния на пространство. Мне удалось заполнить его (а также окончательно убедиться, что мой сценарий соответствует периферийному устройству CRC), вставив «BYTE (0xFF);» 8 раз в конце раздела, но мне это кажется хакерским обходным путем.
Что это за пространство, почему оно там, как мне от него изящно избавиться, будут ли за это последствия?
Мой скрипт компоновщика с моим хакерским исправлением. Если удалить строки 29-38, появится «пробел». Первоначально он был сгенерирован CubeIDE, но с тех пор я довольно долго над ним ковырялся. Это мой первый значимый набег на сценарии лайков, поэтому, возможно, я делаю что-то ужасно неправильно.
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of RAM */
/* Usedd to generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* required amount of heap */
_Min_Stack_Size = 0x400; /* required amount of stack */
_code_size = SIZEOF(.isr_vector) + SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.ARM);
vector_size = SIZEOF(.isr_vector);
/* Specify the memory areas */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 128K
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
KEEP(*(.isr_vector)) /* Startup code */
/* These are the 8 bytes that "fix" the problem, without these the space is filled with zeros */
BYTE(0xFF);
BYTE(0xFF);
BYTE(0xFF);
BYTE(0xFF);
BYTE(0xFF);
BYTE(0xFF);
BYTE(0xFF);
BYTE(0xFF);
} >FLASH =0xEE
/* The program code and other data goes into FLASH */
.text : ALIGN(4)
{
BYTE(vector_size);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH =0xEE
/* Constant data goes into FLASH */
.rodata : ALIGN(4)
{
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
} >FLASH =0xEE
.ARM (READONLY) : ALIGN(4)
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH =0xEE
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> FLASH
/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM
/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 :
{
*(.ARM.attributes)
}
}
Вот начало моего кода. Он также в основном создан CubeIDE с некоторыми небольшими изменениями.
.syntax unified
.cpu cortex-m4
.fpu softvfp
.thumb
.global g_pfnVectors
.global Default_Handler
/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
.equ BootRAM, 0xF1E0F85F
/**
* @brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* @param None
* @retval : None
*/
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
ldr r0, =_estack
mov sp, r0 /* set stack pointer */
/* Call the clock system initialization function.*/
bl SystemInit
/* Copy the data segment initializers from flash to SRAM */
ldr r0, =_sdata
ldr r1, =_edata
ldr r2, =_sidata
movs r3, #0
b LoopCopyDataInit
CopyDataInit:
ldr r4, [r2, r3]
str r4, [r0, r3]
adds r3, r3, #4
LoopCopyDataInit:
adds r4, r0, r3
cmp r4, r1
bcc CopyDataInit
/* Zero fill the bss segment. */
ldr r2, =_sbss
ldr r4, =_ebss
movs r3, #0
b LoopFillZerobss
FillZerobss:
str r3, [r2]
adds r2, r2, #4
LoopFillZerobss:
cmp r2, r4
bcc FillZerobss
/* Call static constructors */
bl __libc_init_array
/* Call the application's entry point.*/
bl main
LoopForever:
b LoopForever
.size Reset_Handler, .-Reset_Handler
/**
* @brief This is the code that gets called when the processor receives an
* unexpected interrupt. This simply enters an infinite loop, preserving
* the system state for examination by a debugger.
*
* @param None
* @retval : None
*/
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler
/******************************************************************************
*
* The minimal vector table for a Cortex-M4. Note that the proper constructs
* must be placed on this to ensure that it ends up at physical address
* 0x0000.0000.
*
******************************************************************************/
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
.word WWDG_IRQHandler
.word PVD_PVM_IRQHandler
.word RTC_TAMP_LSECSS_IRQHandler
.word RTC_WKUP_IRQHandler
.word FLASH_IRQHandler
.word RCC_IRQHandler
.word EXTI0_IRQHandler
.word EXTI1_IRQHandler
.word EXTI2_IRQHandler
.word EXTI3_IRQHandler
.word EXTI4_IRQHandler
.word DMA1_Channel1_IRQHandler
.word DMA1_Channel2_IRQHandler
.word DMA1_Channel3_IRQHandler
.word DMA1_Channel4_IRQHandler
.word DMA1_Channel5_IRQHandler
.word DMA1_Channel6_IRQHandler
.word 0
.word ADC1_2_IRQHandler
.word USB_HP_IRQHandler
.word USB_LP_IRQHandler
.word can_isr
.word can_isr
.word EXTI9_5_IRQHandler
.word TIM1_BRK_TIM15_IRQHandler
.word TIM1_UP_TIM16_IRQHandler
.word TIM1_TRG_COM_TIM17_IRQHandler
.word TIM1_CC_IRQHandler
.word TIM2_IRQHandler
.word TIM3_IRQHandler
.word TIM4_IRQHandler
.word I2C1_EV_IRQHandler
.word I2C1_ER_IRQHandler
.word I2C2_EV_IRQHandler
.word I2C2_ER_IRQHandler
.word SPI1_IRQHandler
.word SPI2_IRQHandler
.word USART1_IRQHandler
.word USART2_IRQHandler
.word USART3_IRQHandler
.word EXTI15_10_IRQHandler
.word RTC_Alarm_IRQHandler
.word USBWakeUp_IRQHandler
.word TIM8_BRK_IRQHandler
.word TIM8_UP_IRQHandler
.word TIM8_TRG_COM_IRQHandler
.word TIM8_CC_IRQHandler
.word 0
.word 0
.word LPTIM1_IRQHandler
.word 0
.word SPI3_IRQHandler
.word UART4_IRQHandler
.word 0
.word TIM6_DAC_IRQHandler
.word TIM7_IRQHandler
.word DMA2_Channel1_IRQHandler
.word DMA2_Channel2_IRQHandler
.word DMA2_Channel3_IRQHandler
.word DMA2_Channel4_IRQHandler
.word DMA2_Channel5_IRQHandler
.word 0
.word 0
.word UCPD1_IRQHandler
.word COMP1_2_3_IRQHandler
.word COMP4_IRQHandler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word CRS_IRQHandler
.word SAI1_IRQHandler
.word 0
.word 0
.word 0
.word 0
.word FPU_IRQHandler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word RNG_IRQHandler
.word LPUART1_IRQHandler
.word I2C3_EV_IRQHandler
.word I2C3_ER_IRQHandler
.word DMAMUX_OVR_IRQHandler
.word 0
.word 0
.word DMA2_Channel6_IRQHandler
.word 0
.word 0
.word CORDIC_IRQHandler
.word FMAC_IRQHandler
.size g_pfnVectors, .-g_pfnVectors
/*******************************************************************************
*
* Provide weak aliases for each Exception handler to the Default_Handler.
* As they are weak aliases, any function with the same name will override
* this definition.
*
*******************************************************************************/
.weak NMI_Handler
.thumb_set NMI_Handler,Default_Handler
.weak HardFault_Handler
.thumb_set HardFault_Handler,Default_Handler
.weak MemManage_Handler
.thumb_set MemManage_Handler,Default_Handler
.weak BusFault_Handler
.thumb_set BusFault_Handler,Default_Handler
.weak UsageFault_Handler
.thumb_set UsageFault_Handler,Default_Handler
.weak SVC_Handler
.thumb_set SVC_Handler,Default_Handler
.weak DebugMon_Handler
.thumb_set DebugMon_Handler,Default_Handler
.weak PendSV_Handler
.thumb_set PendSV_Handler,Default_Handler
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
.weak WWDG_IRQHandler
.thumb_set WWDG_IRQHandler,Default_Handler
.weak PVD_PVM_IRQHandler
.thumb_set PVD_PVM_IRQHandler,Default_Handler
.weak RTC_TAMP_LSECSS_IRQHandler
.thumb_set RTC_TAMP_LSECSS_IRQHandler,Default_Handler
.weak RTC_WKUP_IRQHandler
.thumb_set RTC_WKUP_IRQHandler,Default_Handler
.weak FLASH_IRQHandler
.thumb_set FLASH_IRQHandler,Default_Handler
.weak RCC_IRQHandler
.thumb_set RCC_IRQHandler,Default_Handler
.weak EXTI0_IRQHandler
.thumb_set EXTI0_IRQHandler,Default_Handler
.weak EXTI1_IRQHandler
.thumb_set EXTI1_IRQHandler,Default_Handler
.weak EXTI2_IRQHandler
.thumb_set EXTI2_IRQHandler,Default_Handler
.weak EXTI3_IRQHandler
.thumb_set EXTI3_IRQHandler,Default_Handler
.weak EXTI4_IRQHandler
.thumb_set EXTI4_IRQHandler,Default_Handler
.weak DMA1_Channel1_IRQHandler
.thumb_set DMA1_Channel1_IRQHandler,Default_Handler
.weak DMA1_Channel2_IRQHandler
.thumb_set DMA1_Channel2_IRQHandler,Default_Handler
.weak DMA1_Channel3_IRQHandler
.thumb_set DMA1_Channel3_IRQHandler,Default_Handler
.weak DMA1_Channel4_IRQHandler
.thumb_set DMA1_Channel4_IRQHandler,Default_Handler
.weak DMA1_Channel5_IRQHandler
.thumb_set DMA1_Channel5_IRQHandler,Default_Handler
.weak DMA1_Channel6_IRQHandler
.thumb_set DMA1_Channel6_IRQHandler,Default_Handler
.weak ADC1_2_IRQHandler
.thumb_set ADC1_2_IRQHandler,Default_Handler
.weak USB_HP_IRQHandler
.thumb_set USB_HP_IRQHandler,Default_Handler
.weak USB_LP_IRQHandler
.thumb_set USB_LP_IRQHandler,Default_Handler
.weak can_isr
.thumb_set can_isr,Default_Handler
.weak EXTI9_5_IRQHandler
.thumb_set EXTI9_5_IRQHandler,Default_Handler
.weak TIM1_BRK_TIM15_IRQHandler
.thumb_set TIM1_BRK_TIM15_IRQHandler,Default_Handler
.weak TIM1_UP_TIM16_IRQHandler
.thumb_set TIM1_UP_TIM16_IRQHandler,Default_Handler
.weak TIM1_TRG_COM_TIM17_IRQHandler
.thumb_set TIM1_TRG_COM_TIM17_IRQHandler,Default_Handler
.weak TIM1_CC_IRQHandler
.thumb_set TIM1_CC_IRQHandler,Default_Handler
.weak TIM2_IRQHandler
.thumb_set TIM2_IRQHandler,Default_Handler
.weak TIM3_IRQHandler
.thumb_set TIM3_IRQHandler,Default_Handler
.weak TIM4_IRQHandler
.thumb_set TIM4_IRQHandler,Default_Handler
.weak I2C1_EV_IRQHandler
.thumb_set I2C1_EV_IRQHandler,Default_Handler
.weak I2C1_ER_IRQHandler
.thumb_set I2C1_ER_IRQHandler,Default_Handler
.weak I2C2_EV_IRQHandler
.thumb_set I2C2_EV_IRQHandler,Default_Handler
.weak I2C2_ER_IRQHandler
.thumb_set I2C2_ER_IRQHandler,Default_Handler
.weak SPI1_IRQHandler
.thumb_set SPI1_IRQHandler,Default_Handler
.weak SPI2_IRQHandler
.thumb_set SPI2_IRQHandler,Default_Handler
.weak USART1_IRQHandler
.thumb_set USART1_IRQHandler,Default_Handler
.weak USART2_IRQHandler
.thumb_set USART2_IRQHandler,Default_Handler
.weak USART3_IRQHandler
.thumb_set USART3_IRQHandler,Default_Handler
.weak EXTI15_10_IRQHandler
.thumb_set EXTI15_10_IRQHandler,Default_Handler
.weak RTC_Alarm_IRQHandler
.thumb_set RTC_Alarm_IRQHandler,Default_Handler
.weak USBWakeUp_IRQHandler
.thumb_set USBWakeUp_IRQHandler,Default_Handler
.weak TIM8_BRK_IRQHandler
.thumb_set TIM8_BRK_IRQHandler,Default_Handler
.weak TIM8_UP_IRQHandler
.thumb_set TIM8_UP_IRQHandler,Default_Handler
.weak TIM8_TRG_COM_IRQHandler
.thumb_set TIM8_TRG_COM_IRQHandler,Default_Handler
.weak TIM8_CC_IRQHandler
.thumb_set TIM8_CC_IRQHandler,Default_Handler
.weak LPTIM1_IRQHandler
.thumb_set LPTIM1_IRQHandler,Default_Handler
.weak SPI3_IRQHandler
.thumb_set SPI3_IRQHandler,Default_Handler
.weak UART4_IRQHandler
.thumb_set UART4_IRQHandler,Default_Handler
.weak TIM6_DAC_IRQHandler
.thumb_set TIM6_DAC_IRQHandler,Default_Handler
.weak TIM7_IRQHandler
.thumb_set TIM7_IRQHandler,Default_Handler
.weak DMA2_Channel1_IRQHandler
.thumb_set DMA2_Channel1_IRQHandler,Default_Handler
.weak DMA2_Channel2_IRQHandler
.thumb_set DMA2_Channel2_IRQHandler,Default_Handler
.weak DMA2_Channel3_IRQHandler
.thumb_set DMA2_Channel3_IRQHandler,Default_Handler
.weak DMA2_Channel4_IRQHandler
.thumb_set DMA2_Channel4_IRQHandler,Default_Handler
.weak DMA2_Channel5_IRQHandler
.thumb_set DMA2_Channel5_IRQHandler,Default_Handler
.weak UCPD1_IRQHandler
.thumb_set UCPD1_IRQHandler,Default_Handler
.weak COMP1_2_3_IRQHandler
.thumb_set COMP1_2_3_IRQHandler,Default_Handler
.weak COMP4_IRQHandler
.thumb_set COMP4_IRQHandler,Default_Handler
.weak CRS_IRQHandler
.thumb_set CRS_IRQHandler,Default_Handler
.weak SAI1_IRQHandler
.thumb_set SAI1_IRQHandler,Default_Handler
.weak FPU_IRQHandler
.thumb_set FPU_IRQHandler,Default_Handler
.weak RNG_IRQHandler
.thumb_set RNG_IRQHandler,Default_Handler
.weak LPUART1_IRQHandler
.thumb_set LPUART1_IRQHandler,Default_Handler
.weak I2C3_EV_IRQHandler
.thumb_set I2C3_EV_IRQHandler,Default_Handler
.weak I2C3_ER_IRQHandler
.thumb_set I2C3_ER_IRQHandler,Default_Handler
.weak DMAMUX_OVR_IRQHandler
.thumb_set DMAMUX_OVR_IRQHandler,Default_Handler
.weak DMA2_Channel6_IRQHandler
.thumb_set DMA2_Channel6_IRQHandler,Default_Handler
.weak CORDIC_IRQHandler
.thumb_set CORDIC_IRQHandler,Default_Handler
.weak FMAC_IRQHandler
.thumb_set FMAC_IRQHandler,Default_Handler
Я использую MSYS2 GCC версии 14.1.0 для компиляции и связывания микроконтроллера STMG4.
Я использую make для сборки, команда make запускает ссылку:
gcc -O0 -g3 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -Wall -MMD -fdata-sections -ffunction-sections ${INCLUDE_FLAGS} -DSTM32G431xx -DUSE_HAL_DRIVER -T "${LINKER_SCRIPT}" --specs=nano.specs -Wl,-Map=${OUTPUT_DIR}${SOFTWARE_VERSION}.map -Wl,--gc-sections -Wl,--start-group -lc -lm -Wl,--end-group -Wl,-static ${addprefix ${OBJECT_DIR}, ${OBJECTS}} -o ${OUTPUT_DIR}${SOFTWARE_VERSION}.elf
Это файл карты после удаления практически всего кода, кроме показанной ранее стартовой сборки, пустой основной функции и пустой функции SystemInit (вызываемой в строке 40 файла стартовой сборки). Что-то, что я сделал, удалив весь остальной код, кажется, решил мою проблему, хотя я до сих пор не понял, почему.
0x20008000 _estack = (ORIGIN (RAM) + LENGTH (RAM))
0x00000200 _Min_Heap_Size = 0x200
0x00000400 _Min_Stack_Size = 0x400
0x000002ac _code_size = (((SIZEOF (.isr_vector) + SIZEOF (.text)) + SIZEOF (.rodata)) + SIZEOF (.ARM))
0x000001d8 vector_size = SIZEOF (.isr_vector)
.isr_vector 0x08000000 0x1d8
*(.isr_vector)
.isr_vector 0x08000000 0x1d8 build/obj/startup_stm32g431kbtx.o
0x08000000 g_pfnVectors
.text 0x080001d8 0xd4
*(.text)
*(.text*)
.text.__libc_init_array
0x080001d8 0x48 C:\...d\libc_nano.a(libc_a-init.o)
0x080001d8 __libc_init_array
.text.main 0x08000220 0x10 build/obj/main.o
0x08000220 main
.text.SystemInit
0x08000230 0xe build/obj/main.o
0x08000230 SystemInit
*fill* 0x0800023e 0x2 ee
.text.Reset_Handler
0x08000240 0x50 build/obj/startup_stm32g431kbtx.o
0x08000240 Reset_Handler
.text.Default_Handler
0x08000290 0x2 build/obj/startup_stm32g431kbtx.o
0x08000290 RTC_Alarm_IRQHandler
0x08000290 EXTI2_IRQHandler
0x08000290 TIM8_TRG_COM_IRQHandler
0x08000290 TIM8_CC_IRQHandler
0x08000290 DebugMon_Handler
0x08000290 TIM1_CC_IRQHandler
0x08000290 HardFault_Handler
0x08000290 USB_HP_IRQHandler
0x08000290 CORDIC_IRQHandler
0x08000290 SysTick_Handler
0x08000290 PendSV_Handler
0x08000290 NMI_Handler
0x08000290 EXTI3_IRQHandler
0x08000290 I2C3_ER_IRQHandler
0x08000290 EXTI0_IRQHandler
0x08000290 I2C2_EV_IRQHandler
0x08000290 FPU_IRQHandler
0x08000290 TIM1_UP_TIM16_IRQHandler
0x08000290 UsageFault_Handler
0x08000290 ADC1_2_IRQHandler
0x08000290 SPI1_IRQHandler
0x08000290 TIM6_DAC_IRQHandler
0x08000290 TIM8_UP_IRQHandler
0x08000290 DMA2_Channel2_IRQHandler
0x08000290 DMA1_Channel4_IRQHandler
0x08000290 USART3_IRQHandler
0x08000290 TIM4_IRQHandler
0x08000290 DMA2_Channel1_IRQHandler
0x08000290 I2C1_EV_IRQHandler
0x08000290 DMA1_Channel6_IRQHandler
0x08000290 UART4_IRQHandler
0x08000290 DMA2_Channel4_IRQHandler
0x08000290 TIM3_IRQHandler
0x08000290 RCC_IRQHandler
0x08000290 DMA1_Channel1_IRQHandler
0x08000290 Default_Handler
0x08000290 RTC_TAMP_LSECSS_IRQHandler
0x08000290 FMAC_IRQHandler
0x08000290 EXTI15_10_IRQHandler
0x08000290 TIM7_IRQHandler
0x08000290 UCPD1_IRQHandler
0x08000290 I2C3_EV_IRQHandler
0x08000290 EXTI9_5_IRQHandler
0x08000290 RTC_WKUP_IRQHandler
0x08000290 PVD_PVM_IRQHandler
0x08000290 SPI2_IRQHandler
0x08000290 MemManage_Handler
0x08000290 can_isr
0x08000290 SVC_Handler
0x08000290 DMA2_Channel5_IRQHandler
0x08000290 CRS_IRQHandler
0x08000290 DMA1_Channel5_IRQHandler
0x08000290 USB_LP_IRQHandler
0x08000290 EXTI4_IRQHandler
0x08000290 RNG_IRQHandler
0x08000290 TIM1_TRG_COM_TIM17_IRQHandler
0x08000290 DMA1_Channel3_IRQHandler
0x08000290 WWDG_IRQHandler
0x08000290 LPUART1_IRQHandler
0x08000290 DMA2_Channel6_IRQHandler
0x08000290 TIM2_IRQHandler
0x08000290 COMP1_2_3_IRQHandler
0x08000290 EXTI1_IRQHandler
0x08000290 USART2_IRQHandler
0x08000290 I2C2_ER_IRQHandler
0x08000290 DMA1_Channel2_IRQHandler
0x08000290 TIM8_BRK_IRQHandler
0x08000290 FLASH_IRQHandler
0x08000290 BusFault_Handler
0x08000290 USART1_IRQHandler
0x08000290 SPI3_IRQHandler
0x08000290 I2C1_ER_IRQHandler
0x08000290 LPTIM1_IRQHandler
0x08000290 DMAMUX_OVR_IRQHandler
0x08000290 USBWakeUp_IRQHandler
0x08000290 SAI1_IRQHandler
0x08000290 DMA2_Channel3_IRQHandler
0x08000290 COMP4_IRQHandler
0x08000290 TIM1_BRK_TIM15_IRQHandler
*(.init)
*fill* 0x08000292 0x2 ee
.init 0x08000294 0x4 C:/.../crti.o
0x08000294 _init
.init 0x08000298 0x8 C:/.../crtn.o
*(.fini)
.fini 0x080002a0 0x4 C:/.../crti.o
0x080002a0 _fini
.fini 0x080002a4 0x8 C:/.../crtn.o
0x080002ac . = ALIGN (0x4)
0x080002ac _etext = .
.glue_7 0x080002ac 0x0
.glue_7 0x080002ac 0x0 linker stubs
.glue_7t 0x080002ac 0x0
.glue_7t 0x080002ac 0x0 linker stubs
.vfp11_veneer 0x080002ac 0x0
.vfp11_veneer 0x080002ac 0x0 linker stubs
.v4_bx 0x080002ac 0x0
.v4_bx 0x080002ac 0x0 linker stubs
.iplt 0x080002ac 0x0
.iplt 0x080002ac 0x0 C:/...\libc_nano.a(libc_a-init.o)
.rel.dyn 0x080002ac 0x0
.rel.iplt 0x080002ac 0x0 C:/...\libc_nano.a(libc_a-init.o)
.rodata
*(.rodata)
*(.rodata*)
.ARM 0x080002ac 0x0
0x080002ac __exidx_start = .
*(.ARM.exidx*)
0x080002ac __exidx_end = .
0x080002ac _sidata = LOADADDR (.data)
.data 0x20000000 0x0 load address 0x080002ac
0x20000000 . = ALIGN (0x4)
0x20000000 _sdata = .
*(.data)
*(.data*)
0x20000000 . = ALIGN (0x4)
0x20000000 _edata = .
.igot.plt 0x20000000 0x0 load address 0x080002ac
.igot.plt 0x20000000 0x0 C:/...\libc_nano.a(libc_a-init.o)
0x20000000 . = ALIGN (0x4)
.bss 0x20000000 0x0 load address 0x080002ac
0x20000000 _sbss = .
0x20000000 __bss_start__ = _sbss
*(.bss)
*(.bss*)
*(COMMON)
0x20000000 . = ALIGN (0x4)
0x20000000 _ebss = .
0x20000000 __bss_end__ = _ebss
._user_heap_stack
0x20000000 0x600 load address 0x080002ac
0x20000000 . = ALIGN (0x8)
[!provide] PROVIDE (end = .)
[!provide] PROVIDE (_end = .)
0x20000200 . = (. + _Min_Heap_Size)
*fill* 0x20000000 0x200
0x20000600 . = (. + _Min_Stack_Size)
*fill* 0x20000200 0x400
0x20000600 . = ALIGN (0x8)
/DISCARD/
libc.a(*)
libm.a(*)
libgcc.a(*)
.ARM.attributes
0x00000000 0x30
*(.ARM.attributes)
.ARM.attributes
0x00000000 0x22 C:/.../crti.o
.ARM.attributes
0x00000022 0x34 C:/...\libc_nano.a(libc_a-init.o)
.ARM.attributes
0x00000056 0x34 build/obj/main.o
.ARM.attributes
0x0000008a 0x21 build/obj/startup_stm32g431kbtx.o
.ARM.attributes
0x000000ab 0x22 C:/.../crtn.o
OUTPUT(build/VERSION0/VERSION0.elf elf32-littlearm)
LOAD linker stubs
LOAD C:/...\libc.a
LOAD C:/...\libm.a
LOAD C:/...\libgcc.a
.debug_frame 0x00000000 0x7c
.debug_frame 0x00000000 0x2c C:/...\libc_nano.a(libc_a-init.o)
.debug_frame 0x0000002c 0x50 build/obj/main.o
.debug_info 0x00000000 0x8a
.debug_info 0x00000000 0x5a build/obj/main.o
.debug_info 0x0000005a 0x30 build/obj/startup_stm32g431kbtx.o
.debug_abbrev 0x00000000 0x79
.debug_abbrev 0x00000000 0x55 build/obj/main.o
.debug_abbrev 0x00000055 0x24 build/obj/startup_stm32g431kbtx.o
.debug_aranges 0x00000000 0x50
.debug_aranges
0x00000000 0x28 build/obj/main.o
.debug_aranges
0x00000028 0x28 build/obj/startup_stm32g431kbtx.o
.debug_rnglists
0x00000000 0x32
.debug_rnglists
0x00000000 0x19 build/obj/main.o
.debug_rnglists
0x00000019 0x19 build/obj/startup_stm32g431kbtx.o
.debug_macro 0x00000000 0xac9
.debug_macro 0x00000000 0x1b build/obj/main.o
.debug_macro 0x0000001b 0xaae build/obj/main.o
.debug_line 0x00000000 0xce
.debug_line 0x00000000 0x53 build/obj/main.o
.debug_line 0x00000053 0x7b build/obj/startup_stm32g431kbtx.o
.debug_str 0x00000000 0x2e0b
.debug_str 0x00000000 0x2dcf build/obj/main.o
.debug_str 0x00002dcf 0x3c build/obj/startup_stm32g431kbtx.o
0x7c (size before relaxing)
.comment 0x00000000 0x43
.comment 0x00000000 0x43 build/obj/main.o
0x44 (size before relaxing)
.debug_line_str
0x00000000 0x60
.debug_line_str
0x00000000 0x60 build/obj/startup_stm32g431kbtx.o
После этого не компилируйте и не компонуйте одной командой! Запустите objdump для промежуточных файлов (особенно файлов запуска), чтобы увидеть, что они содержат, и его выравнивание.
Кроме того, ваша команда ссылки выводит файл карты, как насчет редактирования вопроса, чтобы включить его?
«BYTE(vector_size)» — это просто какой-то мусор, который я случайно оставил там, когда пытался разобраться самостоятельно. Насколько я могу судить, на самом деле он ничего не делает, поэтому я удалил его снова. Я компилирую отдельно в своем make-файле, я просто повторно использую команду gcc для вызова ld. Понятия не имею, хорошая это практика или нет. Я беспокоюсь, что моя работа не будет в порядке, включая файл карты, потому что в нем слишком много служебной информации. Если вам нужен конкретный фрагмент или если без него просто невозможно ответить, я возьму, продезинфицирую его и опубликую.
@Sonny Если вы беспокоитесь о конфиденциальности, можете ли вы воспроизвести эту проблему с помощью проекта, в котором есть только код запуска и функция main()
, которая ничего не делает?
@pmacfarlane Я, конечно, могу попробовать!
Я добавил как можно большую часть файла карты. У меня исчерпан лимит символов, поэтому мне пришлось вырезать то, что, как я надеюсь, не имеет значения. Не обращайте внимания на пути к файлам, ни один из них не является правильным после того, как я их все вырезал.
По какой-то причине удаление всего кода, похоже, очистило пустое пространство, которое я видел (когда я также удалил 8 «BYTE (0xFF)»).
Кажется, он с удовольствием прикрепил .text.__libc_init_array
к 0x1d8
. Это делает это с вашей обычной сборкой? Возможно, по неизвестным причинам ему требуется .text.main
на границе 16 байт.
@pmacfarlane Нет, только когда я собираю его без инструкций «BYTE (0xFF)» и с сокращенным кодом.
Что это за пространство, почему оно там, как мне от него изящно избавиться, будут ли за это последствия?
.text : ALIGN(4)
Это устанавливает раздел по новому адресу ALIGN(4). Между ними не определены данные. При выводе в двоичный файл неопределенное пространство по умолчанию равно 0x00. Если вы создали «ihex» или другой формат вывода, пробел будет просто пропущен.
Что-то, что я сделал, удалив весь остальной код, кажется, решил мою проблему, хотя я до сих пор не понял, почему.
Если вы измените код так, чтобы isr_vector
совпадало с 2**4, эффективного пробела не будет.
Существует несколько решений.
isr_vector
дополняется до выравнивания следующего раздела text
. Вы можете использовать ALIGN
(или FILL
, но ALIGN
сделает математику за вас).isr_vector
в начале текста и удалите раздел isr_vector
. Функции уже должны быть выровнены компилятором. Выравнивание разделов — это другой уровень.Бонус: _user_heap_stack и _data имеют . = ALIGN(8)
и . = ALIGN(4)
в начале. Они ничего не делают. Файл компоновщика ._user_heap_stack:ALIGN(8)
и .data:ALIGN(4)
выполнит эту задачу.
Связанный:
isr_vector
довольно неэффективно увеличивает время загрузки.Также имеется ошибка во встроенном модуле CRC STM32. Если вы его используете, я могу показать код, который исправляет его для использования стандартного алгоритма CRC.
Во-первых, размер вектора не умещается в байт, поэтому BYTE(vector_size) определенно не содержит того, что вы ожидаете, возможно, оно равно нулю. После этого вы, вероятно, получите 3 или 7 байтов заполнения для правильного выравнивания следующего объекта, который будет помещен в .text.