ECU:S32K146, GCC 编译器
我正在尝试执行应用说明 AN12323中描述的 A/B 固件更新过程。
我成功地使用硬编码 .ld 文件(见下文)执行从固件 A 到固件 B 的刷新,现在我想使用位置无关代码执行相同的任务。
/* Entry Point */
ENTRY(Reset_Handler)
HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x00000400;
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x00000400;
/* If symbol __flash_vector_table__=1 is defined at link time
* the interrupt vector will not be copied to RAM.
* Warning: Using the interrupt vector from Flash will not allow
* INT_SYS_InstallHandler because the section is Read Only.
*/
M_VECTOR_RAM_SIZE = DEFINED(__flash_vector_table__) ? 0x0 : 0x0400;
/* Specify the memory areas */
MEMORY
{
m_interrupts (RX) : ORIGIN = 0x00001000, LENGTH = 0x00000400
m_flash_config (RX) : ORIGIN = 0x00001400, LENGTH = 0x00000010 /*16 Bytes*/
m_got (RX) : ORIGIN = 0x00001410, LENGTH = 0x00001000 /*Global Offset Table*/
/*All Code -> example: Reset_Handler is the first code located at 0x2400 */
m_text (RX) : ORIGIN = 0x00002410, LENGTH = 0x0007DC00 - 0x1410 /*503 kB Firmware 1 partition A TODO die length von m_flash_config subtrahieren*/
/* SRAM_L Adresse_Start 0x1FFF_0000 and Adress_End 0x1FFF_FFFF*/
m_data (RW) : ORIGIN = 0x1FFF0000, LENGTH = 0x1FFFFFFF/*uses all 64kB or 65536 bytes of SRAM_L since it will be cleared when jumping*/
/* SRAM_U Adress_Start 0x2000_0000 and Adress_End 0x2000_EFFF*/
m_data_2 (RW) : ORIGIN = 0x20000000, LENGTH = 0x0000F000 /*Uses all 60kB or */
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into internal flash */
.interrupts :
{
__VECTOR_TABLE = .;
__interrupts_start__ = .;
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
__interrupts_end__ = .;
. = ALIGN(4);
} > m_interrupts
.flash_config :
{
. = ALIGN(4);
KEEP(*(.FlashConfig)) /* Flash Configuration Field (FCF) */
. = ALIGN(4);
} > m_flash_config
/* Define the .got sections */
.got :
{
. = ALIGN(4);
KEEP*(.got)
. = ALIGN(4);
} > m_got
.got.plt :
{
. = ALIGN(4);
KEEP*(.got.plt)
. = ALIGN(4);
} > m_got
/* Version is always saved at 0x4000 and can occupy 24 Bytes*/
.version 0x5000 :
{
. = ALIGN(4);
KEEP(*(.version))
. = ALIGN(4);
} > m_text
/* Model is always saved at 0x4018 directly after the version*/
.model 0x5018 : {
. = ALIGN(4);
KEEP(*(.model))
. = ALIGN(4);
} > m_text
/* The program code and other data goes into internal flash */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.init) /* section used in crti.o files */
*(.fini) /* section used in crti.o files */
*(.eh_frame) /* section used in crtbegin.o files */
. = ALIGN(4);
} > m_text
....
}
/* Entry Point */
ENTRY(Reset_Handler)
HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x00000400;
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x00000400;
/* If symbol __flash_vector_table__=1 is defined at link time
* the interrupt vector will not be copied to RAM.
* Warning: Using the interrupt vector from Flash will not allow
* INT_SYS_InstallHandler because the section is Read Only.
*/
M_VECTOR_RAM_SIZE = DEFINED(__flash_vector_table__) ? 0x0 : 0x0400;
/* Specify the memory areas */
MEMORY
{
m_interrupts (RX) : ORIGIN = 0x00081000, LENGTH = 0x00000400 /* 1024 bytes 1kB Firmware 1 Vector Table Partition A / -10 for the m_flash_config that is part of this*/
m_flash_config (RX) : ORIGIN = 0x00081400, LENGTH = 0x00000010 /*16 Bytes*/
m_got (RX) : ORIGIN = 0x00081410, LENGTH = 0x00001000 /*Global Offset Table*/
/*All Code -> example: Reset_Handler is the first code located at 0x2400 */
m_text (RX) : ORIGIN = 0x00082410, LENGTH = 0x0007DC00 - 0x1410 /*503 kB Firmware 1 partition A TODO die length von m_flash_config subtrahieren*/
/* SRAM_L Adresse_Start 0x1FFF_0000 and Adress_End 0x1FFF_FFFF*/
m_data (RW) : ORIGIN = 0x1FFF0000, LENGTH = 0x1FFFFFFF/*uses all 64kB or 65536 bytes of SRAM_L since it will be cleared when jumping*/
/* SRAM_U Adress_Start 0x2000_0000 and Adress_End 0x2000_EFFF*/
m_data_2 (RW) : ORIGIN = 0x20000000, LENGTH = 0x0000F000 /*Uses all 60kB or */
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into internal flash */
.interrupts :
{
__VECTOR_TABLE = .;
__interrupts_start__ = .;
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
__interrupts_end__ = .;
. = ALIGN(4);
} > m_interrupts
.flash_config :
{
. = ALIGN(4);
KEEP(*(.FlashConfig)) /* Flash Configuration Field (FCF) */
. = ALIGN(4);
} > m_flash_config
/* Define the .got sections */
.got :
{
. = ALIGN(4);
KEEP*(.got)
. = ALIGN(4);
} > m_got
.got.plt :
{
. = ALIGN(4);
KEEP*(.got.plt)
. = ALIGN(4);
} > m_got
/* Version is always saved at 0x4000 and can occupy 24 Bytes*/
.version 0x85000 :
{
. = ALIGN(4);
KEEP(*(.version))
. = ALIGN(4);
} > m_text
/* Model is always saved at 0x4018 directly after the version*/
.model 0x85018 : {
. = ALIGN(4);
KEEP(*(.model))
. = ALIGN(4);
} > m_text
/* The program code and other data goes into internal flash */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.init) /* section used in crti.o files */
*(.fini) /* section used in crti.o files */
*(.eh_frame) /* section used in crtbegin.o files */
. = ALIGN(4);
} > m_text
....
}
MEMORY
{
/* Flash */
/*1kB Default Vector Table for Bootloader minus the flash config that is part of the Table plus the Bootloader Check and MPU stuff that has to be performed for the Chain of Trust*/
m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x00000400
m_flash_config (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010
m_text (RX) : ORIGIN = 0x10000000, LENGTH = 0x00004000 - 4 /*16 kB Bootloader Application located at D-Flash*/
m_shared_flash (R) : ORIGIN = 0x10003FFC, LENGTH = 0x00000004 /* 4 bytes for loader entry function pointer READ ONLY*/
/* SRAM_L */
m_data (RW) : ORIGIN = 0x1FFF0000, LENGTH = 0x1FFFFFFF - 0x1FFF0000 /*uses all 64kB or 0x10000 = 65536 bytes of SRAM_L since it will be cleared anyways when jumping to firmware*/
/* SRAM_U */
m_data_2 (RW) : ORIGIN = 0x20000000, LENGTH = 0x0000F000 -4 /*Uses whole 60kB or 0xF000 = 61440 bytes of SRAM_U since it will be cleared anyways when jumping to firmware*/
m_shared_ram (RW) : ORIGIN = 0x2000EFFC, LENGTH = 0x00000004 /* 4 bytes for status variable shared with application using the last adressspace */
/*Data sheet sagt Adresse ende ist 0x2000EFFF und adresse start ist 0x20000000 aber das sind nicht 61440 bytes sondern 61399 wenn man adresse_ende - adresse_start macht*/
}
#define FIRMWARE_A_VECTOR_TABLE_ADRESSE 0x00001000
#define FIRMWARE_B_VECTOR_TABLE_ADRESSE 0x00081000
void JumpToAdresse(uint32_t StackPointerAdresse, uint32_t ProgramCounterAdresse)
{
__asm volatile("msr msp, r0");
__asm volatile ("ISB");
__asm volatile("msr psp, r0");
DISABLE_INTERRUPTS();
S32_SCB->VTOR = (uint32_t)FIRMWARE_A_VECTOR_TABLE_ADRESSE;
__asm volatile("mov pc, r1");
}
int main(void) {
uint32_t StackPointerAdress = *((volatile uint32_t*)FIRMWARE_A_VECTOR_TABLE_ADRESSE);
uint32_t ProgramCounterAdress = *((volatile uint32_t*)(FIRMWARE_A_VECTOR_TABLE_ADRESSE + 4));
JumpToAdresse(StackPointerAdress, ProgramCounterAdress);
__NO_RETURN
return 0;
}
目前正在工作。
#define FIRMWARE_A 0x1000
#define FIRMWARE_B 0x81000
#define FLASH_OFFSET FIRMWARE_B // Starting offset for the ISR vector table
#define NUM_OF_INT_VECTORS 255
uint32_t address = FLASH_OFFSET; //adress to flash the next bytes starting at flash_offset
uint16_t last_package_number = 0;
/*
* Erases whole Firmware Area, either A or B
*/
void EraseFirmwareB() {
/* Define the start and end addresses */
uint32_t start_address = flashSSDConfig.PFlashBase + FLASH_OFFSET;
uint32_t end_address;
if(FLASH_OFFSET == 0x1000){
end_address = 0x00080000;
}
else{
end_address = 0x00100000;
}
uint32_t ret;
/* Ensure the start address is at the beginning of a sector */
bool is_address_at_beginning_of_sector = (FLASH_OFFSET % FEATURE_FLS_PF_BLOCK_SECTOR_SIZE) == 0;
DEV_ASSERT(is_address_at_beginning_of_sector);
uint32_t flash_temp_address = start_address;
uint32_t lenght= (end_address-FLASH_OFFSET) / FEATURE_FLS_PF_BLOCK_SECTOR_SIZE;
//The Remainder of (end_address-FIRMWARE_B_VECTOR_TABLE_ADDRESS) % FEATURE_FLS_PF_BLOCK_SECTOR_SIZE should be 0
for(uint32_t i=0;i<lenght;i++)
{
ret = FLASH_DRV_EraseSector(&flashSSDConfig, flash_temp_address, FEATURE_FLS_PF_BLOCK_SECTOR_SIZE);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Verify the erase operation at margin level value of 1, user read */
ret = FLASH_DRV_VerifySection(&flashSSDConfig, flash_temp_address, FTFx_DPHRASE_SIZE, 1u);
DEV_ASSERT(STATUS_SUCCESS == ret);
flash_temp_address=flash_temp_address +FEATURE_FLS_PF_BLOCK_SECTOR_SIZE;
}
}
uint32_t WriteFirmwareB(MCU_UpdatingFileData *file_information) {
status_t ret;
uint32_t failAddr;
// Assuming file_information->current_package_data_length is of type size_t or similar
size_t alignment = 8;
size_t remainder = file_information->current_package_data_length % alignment;
if (remainder != 0) {
// Calculate the additional bytes needed for alignment
size_t padding = alignment - remainder;
file_information->current_package_data_length += padding;
}
/* Write some data to the erased DFlash sector */
ret = FLASH_DRV_Program(&flashSSDConfig, address, file_information->current_package_data_length, file_information->current_package_content_data);
DEV_ASSERT(STATUS_SUCCESS == ret);
//TODO use test data to check
uint8_t indddex = (file_information->upgrade_package_number -1);
/* Verify the program operation at margin level value of 1, user margin */
ret = FLASH_DRV_ProgramCheck(&flashSSDConfig, address, file_information->current_package_data_length,file_information->current_package_content_data , &failAddr, 1u);//array_of_arrays[indddex]
DEV_ASSERT(STATUS_SUCCESS == ret);
// Update the address for the next package
address += file_information->current_package_data_length;
// Update last package number
last_package_number = file_information->upgrade_package_number;
return STATUS_SUCCESS == ret;
}
这就是我所做的。
/* Entry Point */
ENTRY(Reset_Handler)
HEAP_SIZE = DEFINED(__heap_size__) ? __heap_size__ : 0x00000400;
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x00000400;
/* If symbol __flash_vector_table__=1 is defined at link time
* the interrupt vector will not be copied to RAM.
* Warning: Using the interrupt vector from Flash will not allow
* INT_SYS_InstallHandler because the section is Read Only.
*/
M_VECTOR_RAM_SIZE = DEFINED(__flash_vector_table__) ? 0x0 : 0x0400;
/* Specify the memory areas */
MEMORY
{
m_interrupts (RX) : ORIGIN = 0x00000000, LENGTH = 0x00000400 /* 1024 bytes 1kB Firmware 1 Vector Table Partition A / -10 for the m_flash_config that is part of this*/
m_flash_config (RX) : ORIGIN = 0x00000400, LENGTH = 0x00000010 /*16 Bytes*/
m_got (RX) : ORIGIN = 0x00000410, LENGTH = 0x00001000 /*Global Offset Table*/
/*All Code -> example: Reset_Handler is the first code located at 0x2400 */
m_text (RX) : ORIGIN = 0x00001410, LENGTH = 0x0007DC00 - 0x1410 /*503 kB Firmware 1 partition A TODO die length von m_flash_config subtrahieren*/
/* SRAM_L Adresse_Start 0x1FFF_0000 and Adress_End 0x1FFF_FFFF*/
m_data (RW) : ORIGIN = 0x1FFF0000, LENGTH = 0x1FFFFFFF/*uses all 64kB or 65536 bytes of SRAM_L since it will be cleared when jumping*/
/* SRAM_U Adress_Start 0x2000_0000 and Adress_End 0x2000_EFFF*/
m_data_2 (RW) : ORIGIN = 0x20000000, LENGTH = 0x0000F000 /*Uses all 60kB or */
}
/* Define output sections */
SECTIONS
{
/* The startup code goes first into internal flash */
.interrupts :
{
__VECTOR_TABLE = .;
__interrupts_start__ = .;
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
__interrupts_end__ = .;
. = ALIGN(4);
} > m_interrupts
.flash_config :
{
. = ALIGN(4);
KEEP(*(.FlashConfig)) /* Flash Configuration Field (FCF) */
. = ALIGN(4);
} > m_flash_config
/* Define the .got sections */
.got :
{
. = ALIGN(4);
KEEP*(.got)
. = ALIGN(4);
} > m_got
.got.plt :
{
. = ALIGN(4);
KEEP*(.got.plt)
. = ALIGN(4);
} > m_got
/* Version is always saved at 0x4000 and can occupy 24 Bytes*/
.version 0x54000 :
{
. = ALIGN(4);
KEEP(*(.version))
. = ALIGN(4);
} > m_text
/* Model is always saved at 0x4018 directly after the version*/
.model 0x4018 : {
. = ALIGN(4);
KEEP(*(.model))
. = ALIGN(4);
} > m_text
/* The program code and other data goes into internal flash */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
*(.init) /* section used in crti.o files */
*(.fini) /* section used in crti.o files */
*(.eh_frame) /* section used in crtbegin.o files */
. = ALIGN(4);
} > m_text
/* Section used by the libgcc.a library for fvp4 */
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} > m_text
__etext = .; /* Define a global symbol at end of code. */
__DATA_ROM = .; /* Symbol is used by startup for data initialization. */
.interrupts_ram :
{
. = ALIGN(4);
__VECTOR_RAM__ = .;
__RAM_START = .;
__interrupts_ram_start__ = .; /* Create a global symbol at data start. */
*(.m_interrupts_ram) /* This is a user defined section. */
. += M_VECTOR_RAM_SIZE;
. = ALIGN(4);
__interrupts_ram_end__ = .; /* Define a global symbol at data end. */
} > m_data
__VECTOR_RAM = DEFINED(__flash_vector_table__) ? ORIGIN(m_interrupts) : __VECTOR_RAM__ ;
__RAM_VECTOR_TABLE_SIZE = DEFINED(__flash_vector_table__) ? 0x0 : (__interrupts_ram_end__ - __interrupts_ram_start__) ;
.data : AT(__DATA_ROM)
{
. = ALIGN(4);
__DATA_RAM = .;
__data_start__ = .; /* Create a global symbol at data start. */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
__data_end__ = .; /* Define a global symbol at data end. */
} > m_data
__DATA_END = __DATA_ROM + (__data_end__ - __data_start__);
__CODE_ROM = __DATA_END; /* Symbol is used by code initialization. */
.code : AT(__CODE_ROM)
{
. = ALIGN(4);
__CODE_RAM = .;
__code_start__ = .; /* Create a global symbol at code start. */
__code_ram_start__ = .;
*(.code_ram) /* Custom section for storing code in RAM */
. = ALIGN(4);
__code_end__ = .; /* Define a global symbol at code end. */
__code_ram_end__ = .;
} > m_data
__CODE_END = __CODE_ROM + (__code_end__ - __code_start__);
__CUSTOM_ROM = __CODE_END;
/* Custom Section Block that can be used to place data at absolute address. */
/* Use __attribute__((section (".customSection"))) to place data here. */
.customSectionBlock ORIGIN(m_data_2) : AT(__CUSTOM_ROM)
{
__customSection_start__ = .;
KEEP(*(.customSection)) /* Keep section even if not referenced. */
__customSection_end__ = .;
} > m_data_2
__CUSTOM_END = __CUSTOM_ROM + (__customSection_end__ - __customSection_start__);
__rom_end = __CUSTOM_END;
/* Uninitialized data section. */
.bss :
{
/* This is used by the startup in order to initialize the .bss section. */
. = ALIGN(4);
__BSS_START = .;
__bss_start__ = .;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
__BSS_END = .;
} > m_data_2
/* Put heap section after the program data */
.heap :
{
. = ALIGN(8);
__end__ = .;
__heap_start__ = .;
PROVIDE(end = .);
PROVIDE(_end = .);
PROVIDE(__end = .);
__HeapBase = .;
. += HEAP_SIZE;
__HeapLimit = .;
__heap_limit = .;
__heap_end__ = .;
} > m_data_2
/* Initializes stack on the end of block */
__StackTop = ORIGIN(m_data_2) + LENGTH(m_data_2);
__StackLimit = __StackTop - STACK_SIZE;
PROVIDE(__stack = __StackTop);
__RAM_END = __StackTop;
.stack :
{
. = ALIGN(8);
. += STACK_SIZE;
} > m_data_2
/* Initializes stack on the end of block */
__StackTop = ORIGIN(m_data_2) + LENGTH(m_data_2);
__StackLimit = __StackTop - STACK_SIZE;
PROVIDE(__stack = __StackTop);
__RAM_START = ORIGIN(m_data);
__RAM_END = __StackTop + LENGTH(m_shared_ram);
.ARM.attributes 0 : { *(.ARM.attributes) }
/* Memory validation */
ASSERT(__rom_end <= (ORIGIN(m_text) + LENGTH(m_text)), "Region m_text overflowed!")
ASSERT(__StackLimit >= __HeapLimit, "region m_data_2 overflowed with stack and heap")
}
void EraseInterruptTableArea() {
uint32_t ret;
// Ensure the start address is at the beginning of a sector
bool is_offset_at_beginning_of_sector = (FLASH_OFFSET % FEATURE_FLS_PF_BLOCK_SECTOR_SIZE) == 0;
DEV_ASSERT(is_offset_at_beginning_of_sector);
// Erase the sector(s) in PFlash where the ISR vector table is located
ret = FLASH_DRV_EraseSector(&flashSSDConfig, FLASH_OFFSET, FEATURE_FLS_PF_BLOCK_SECTOR_SIZE);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Verify the erase operation at margin level value of 1, user read */
ret = FLASH_DRV_VerifySection(&flashSSDConfig, FLASH_OFFSET, FTFx_DPHRASE_SIZE, 1u);
DEV_ASSERT(STATUS_SUCCESS == ret);
}
#define NUM_OF_INT_VECTORS 255
uint32_t UpdateInterruptTableOffset() {
status_t ret;
uint32_t failAddr;
uint32_t ONE_P_FLASH_BLOCK_SIZE = FEATURE_FLS_PF_BLOCK_SECTOR_SIZE / 4;
uint32_t updated_block_sector_with_relocated_VTOR[ONE_P_FLASH_BLOCK_SIZE]; //This is 4096 Bytes Big one Block because of the erase
// Read the current ISR addresses
uint32_t *isr_vector_table = (uint32_t *)FLASH_OFFSET;
// Add offset to ISR addresses and store them
for (uint32_t i = 0; i < ONE_P_FLASH_BLOCK_SIZE; i++) {
if(i == 0){
updated_block_sector_with_relocated_VTOR[i] = isr_vector_table[i]; //SKIP StackPointer
}
else if(i >= NUM_OF_INT_VECTORS){ //if its beyond the interrupt table just copy the old value
updated_block_sector_with_relocated_VTOR[i] = isr_vector_table[i];
}
// else if (isr_vector_table[i] == 0) { // Skip empty entries
// updated_block_sector_with_relocated_VTOR[i] = 0;
// }
else { //add_offset
updated_block_sector_with_relocated_VTOR[i] = isr_vector_table[i] + FLASH_OFFSET;
}
}
uint8_t* bytePtr = (uint8_t*)updated_block_sector_with_relocated_VTOR;
uint32_t length = sizeof(updated_block_sector_with_relocated_VTOR);
size_t alignment = 8;
size_t remainder = length % alignment;
DEV_ASSERT(remainder == 0);
remainder = FLASH_OFFSET % alignment;
DEV_ASSERT(remainder == 0);
EraseInterruptTableArea();
/* Write updated ISR addresses to the erased DFlash sector */
ret = FLASH_DRV_Program(&flashSSDConfig, FLASH_OFFSET, length, bytePtr);
DEV_ASSERT(STATUS_SUCCESS == ret);
/* Verify the program operation at margin level value of 1, user margin */
ret = FLASH_DRV_ProgramCheck(&flashSSDConfig, FLASH_OFFSET, length, bytePtr, &failAddr, 1u);
DEV_ASSERT(STATUS_SUCCESS == ret);
return STATUS_SUCCESS == ret;
}
根据应用说明,这应该足以能够在我选择的每个内存地址处进行闪存。我以与硬编码 .ld 时相同的方式执行刷新,并且我的引导加载程序能够接收正确的堆栈指针 (PC) 和程序计数器 (0x85021)。跳转也成功了,但是在地址0x85050处崩溃了
00085020: cpsid i
00085022: mov.w r1, #0
00085026: mov.w r2, #0
0008502a: mov.w r3, #0
0008502e: mov.w r4, #0
00085032: mov.w r5, #0
00085036: mov.w r6, #0
0008503a: mov.w r7, #0
0008503e: mov r8, r7
00085040: mov r9, r7
00085042: mov r10, r7
00085044: mov r11, r7
00085046: mov r12, r7
00085048: ldr r0, [pc, #16] ; (0x8505c)
0008504a: mov sp, r0
0008504c: ldr r0, [pc, #16] ; (0x85060)
0008504e: blx r0
00085050: ldr r0, [pc, #16] ; (0x85064)
00085052: blx r0
00085054: cpsie i
00085056: bl 0x93964
0008505a: b.n 0x8505a
0008505c: vext.8 d18, d12, d0, #0
00085060: ldr r4, [pc, #692] ; (0x85318)
00085062: movs r0, r0
00085064: ldr r4, [pc, #980] ; (0x8543c)
00085066: movs r0, r0
00085068: b.w 0x85068
0008506c: eor.w r1, r1, #2147483648 ; 0x80000000
00085070: b.n 0x85078
这代表
Reset_Handler
内 Startup.S
的第一行,看起来像是 ldr r0,=init_data_bss
行:或 System_Init
Reset_Handler:
cpsid i /* Mask interrupts */
/* Init the rest of the registers */
ldr r1,=0
ldr r2,=0
ldr r3,=0
ldr r4,=0
ldr r5,=0
ldr r6,=0
ldr r7,=0
mov r8,r7
mov r9,r7
mov r10,r7
mov r11,r7
mov r12,r7
#ifdef START_FROM_FLASH
/* Init ECC RAM */
ldr r1, =__RAM_START
ldr r2, =__RAM_END
subs r2, r1
subs r2, #1
ble .LC5
movs r0, 0
movs r3, #4
.LC4:
str r0, [r1]
add r1, r1, r3
subs r2, 4
bge .LC4
.LC5:
#endif
/* Initialize the stack pointer */
ldr r0,=__StackTop
mov r13,r0
#ifndef __NO_SYSTEM_INIT
/* Call the system init routine */
ldr r0,=SystemInit
blx r0
#endif
/* Init .data and .bss sections */
ldr r0,=init_data_bss
blx r0
cpsie i /* Unmask interrupts */
bl main
我的假设是我的闪烁和跳转功能按预期工作,因为 - A:使用硬编码的 .ld 文件进行闪烁工作并且 B:我在跳转之前确认了 SP&PC,并且跳转时它始终是正确的 0x85021 地址。
如图2所示:跳转到0x85021-0x85050后跳转到的地址是0x5010,这表明它试图在这个地址中查找init_data_bss函数,这表明具有位置无关代码的全局偏移表不起作用作为预期。
我的假设是这样的。要么我的 VTOR 重定位函数错误,要么我必须在编译器内指定 -vPIC 并添加 .got 部分后手动添加更多内容。
如果有任何关于我可能遗漏的内容或为什么使用 PIC 崩溃但不使用硬编码 .ld 文件崩溃的建议,我将不胜感激。
我最初通过编译两个单独的 .bin 文件解决了该问题,每个文件都在各自的 .ld 文件中指定了硬编码的内存地址。这两个二进制文件(一个用于固件 A,一个用于固件 B)包含在一个 zip 文件中,允许我在运行时根据要求选择适当的二进制文件。
但是,NXP 提供了一些看起来更高效的解决方案,特别是对于 ARM 处理器。这些涉及设置一些额外的编译器标志以使 PIC 工作。您可以在以下资源中找到详细的说明和步骤:
NXP 社区帖子:在 S32 Design Studio 中激活位置无关代码(PIC)后的步骤是什么?
Stack Overflow 答案:如何为 ARM 处理器设置编译器标志
这些资源应该可以帮助您更深入地了解如何使用位置无关代码有效处理基于 ARM 的项目中的类似情况。