0

stm32f4 チップ用のカスタム リンカー スクリプトがあり、ほとんどが機能しています。アプリケーションの起動と実行、グローバル配列と変数は正しく初期化されますが、グローバル オブジェクトは正しく初期化されません。

__init_array の代わりに ctor の使用法への言及をいくつか見つけましたが、それらは古い方法論のようです。

LD に次のセクションを追加しました。

. = ALIGN(4);
.preinit_array     :
{
  PROVIDE_HIDDEN (__preinit_array_start = .);
  KEEP (*(.preinit_array*))
  PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
. = ALIGN(4);
.init_array :
{
  PROVIDE_HIDDEN (__init_array_start = .);
  KEEP (*(SORT(.init_array.*)))
  KEEP (*(.init_array*))
  PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
. = ALIGN(4);
.fini_array :
{
  PROVIDE_HIDDEN (__fini_array_start = .);
  KEEP (*(SORT(.fini_array.*)))
  KEEP (*(.fini_array*))
  PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH

および完全な起動スクリプト:

extern unsigned long _data_flash;
extern unsigned long _data_begin;
extern unsigned long _data_end;
extern unsigned long _bss_begin;
extern unsigned long _bss_end;
extern void (**__preinit_array_start)();
extern void (**__preinit_array_end)();
extern void (**__init_array_start)();
extern void (**__init_array_end)();


inline void static_init()
{
  for (void (**p)() = __preinit_array_start; p < __preinit_array_end; ++p)
    (*p)();

  for (void (**p)() = __init_array_start; p < __init_array_end; ++p)
    (*p)();
}

void reset_handler(void)
{
  unsigned long *source;
  unsigned long *destination;

  // default zero to undefined variables
  for (destination = &_bss_begin; destination < &_bss_end;)
  {
    *(destination++) = 0;
  }

  // Copying data from Flash to RAM
  source = &_data_flash;
  for (destination = &_data_begin; destination < &_data_end;)
  {
    *(destination++) = *(source++);
  }


  SystemInit();

  static_init();

  // starting main program
  main();

  while(1)
  {
    ; //loop forever, but we should never be there
  }
}

ST の公式スタートアップ スクリプトが、適切に動作するように黒魔術 (およびおそらく独自仕様) を実行している可能性はありますか?

別のコンパイラを使用すると、この同じコードが適切に機能するようになったので、コードの問題を除外します。

編集:いくつかのデバッグの後、私は試しました:

printf("preinit %32x %32x\r\n", __preinit_array_start, __preinit_array_end);
printf("init %32x %32x\r\n", __init_array_start, __init_array_end);
printf("preinit2 %32x %32x\r\n", *__preinit_array_start, *__preinit_array_end);
printf("init2 %32x %32x\r\n", *__init_array_start, *__init_array_end);

その戻り値:

preinit 080506E9 080506E9<\r><\n>
init 080506E9 00000000<\r><\n>
preinit2 BB4FF8E9 BB4FF8E9<\r><\n>
init2 BB4FF8E9 20000418<\r><\n>

これは非常に興味深いです。「__init_array_end」がなぜかキープされていないようです。

4

1 に答える 1

0

アドレスが間違って__init_array_end__いることがわかったので、リンカ スクリプトを詳しく調べて、Atollic Studio for C++ で使用されているバリアントを試すことにしました。(以前のリンカー スクリプトは st 標準ペリフェラルの例から取られたことに注意してください)

動作中のリンカー スクリプトとの違いは、主に、属性がなく、ヒープを初期化する方法が異なること.bssと、NOLOAD.data>RAM AT> FLASH>RAM

于 2018-05-25T14:49:50.647 に答える