激活 A/B 交换的位置独立代码(PIC)后有哪些步骤?

问题描述 投票:0回答:1

ECU:S32K146, GCC 编译器

我正在尝试执行应用说明 AN12323中描述的 A/B 固件更新过程。

我成功地使用硬编码 .ld 文件(见下文)执行从固件 A 到固件 B 的刷新,现在我想使用位置无关代码执行相同的任务。

我做了什么:

固件 A 的硬编码链接器文件

/* 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

 ....
}

固件 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 = 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*/
}

具有基本 JMP 功能的简约引导加载程序

#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;
}

目前正在工作。

  1. 我首先刷新 0x1000 硬编码固件
  2. 然后我刷新引导加载程序。
  3. 我启动我的应用程序,首先进入引导加载程序,然后从那里进入 Firmware_A 0x1000,然后从那里开始更新过程,使用以下方法刷新我的硬编码 .ld 0x81000 .bin:
#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;

}
  1. 之后我只需更改引导加载程序代码,使其跳转到固件 B(使用 0x81000)而不是固件 A 。一切正常!我确认使用了调试器!

我的目标是现在激活位置独立代码,这样 .ld 文件就不必进行硬编码

这就是我所做的。

  1. 激活-fPIC。项目 -> 属性 -> C/C++ 构建 -> 设置 -> 其他 -> 标记/激活位置独立代码 (-fPIC)(适用于所有配置和 C/C++ 编译器)
  2. 更改了 .ld 文件内从地址 0x0000_0000 开始的中断表,因为 PIC 现在处于活动状态。
  3. 我手动添加了全局偏移部分(got,plt),因为编译器抱怨该部分不存在。
 /* 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")
}
  1. 刷新后,我执行向量表 (VTOR) 重定位,其中为中断表的每个条目添加固件 B 偏移量,第一个条目(即堆栈指针)除外。
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 文件崩溃的建议,我将不胜感激。

c++ c arm bootloader firmware
1个回答
0
投票

我最初通过编译两个单独的 .bin 文件解决了该问题,每个文件都在各自的 .ld 文件中指定了硬编码的内存地址。这两个二进制文件(一个用于固件 A,一个用于固件 B)包含在一个 zip 文件中,允许我在运行时根据要求选择适当的二进制文件。

但是,NXP 提供了一些看起来更高效的解决方案,特别是对于 ARM 处理器。这些涉及设置一些额外的编译器标志以使 PIC 工作。您可以在以下资源中找到详细的说明和步骤:

NXP 社区帖子:在 S32 Design Studio 中激活位置无关代码(PIC)后的步骤是什么?

Stack Overflow 答案:如何为 ARM 处理器设置编译器标志

这些资源应该可以帮助您更深入地了解如何使用位置无关代码有效处理基于 ARM 的项目中的类似情况。

© www.soinside.com 2019 - 2024. All rights reserved.