🤒

リンカスクリプトでSRAMを整理整頓

2022/02/02に公開

環境

  • マイコン
    STM32mp157 (CM4 side)
  • IDE
    STM32CubeIDE(1.8.0)

発生したエラー

私のように何も考えずにでかいメモリ空間をグローバル領域で確保すると、
以下のエラーに遭遇することがある。(再)

  • エラーメッセージ
arm-none-eabi\bin\ld.exe: region `SRAM2_data' overflowed by 24256 bytes

これは、SRAM2 の容量が不足しているというエラー。(デジャブ)

対処

焦らず、まずはバッファを減らしてリンクを通してSRAMの残量を確認する。[1]

今回確保したい領域は 68kbyte × 2枚。
この環境では、SRAM1、SRAM2 に分割して展開するしかない。
よって、リンカスクリプトで対処する。

まず、メモリ定義を確認する。

MEMORY
{
  RETRAM_interrupts (xrw)  : ORIGIN = 0x00000000,  LENGTH = 0x00000600
  SRAM1_text        (xrw)  : ORIGIN = 0x10000000,  LENGTH = 128K
  SRAM2_data        (xrw)  : ORIGIN = 0x10020000,  LENGTH = 128K
  SRAM3_ipc_shm     (xrw)  : ORIGIN = 0x10040000,  LENGTH = 64K
  SRAM4             (xrw)  : ORIGIN = 0x10050000,  LENGTH = 64K
}

SRAM1 にバッファ領域を確保したいので、分かりやすく、
新しくSRAM1_data を定義する。
SRAM1_data に領域を割り当てた分を、SRAM1_text から差し引いて定義する。

MEMORY
{
  RETRAM_interrupts (xrw)  : ORIGIN = 0x00000000,  LENGTH = 0x00000600
-  SRAM1_text        (xrw)  : ORIGIN = 0x10000000,  LENGTH = 128K
+  SRAM1_text        (xrw)  : ORIGIN = 0x10000000,  LENGTH = 40K
+  SRAM1_data        (xrw)  : ORIGIN = 0x1000A000,  LENGTH = 90K
  SRAM2_data        (xrw)  : ORIGIN = 0x10020000,  LENGTH = 128K
  SRAM3_ipc_shm     (xrw)  : ORIGIN = 0x10040000,  LENGTH = 64K
  SRAM4_data        (xrw)  : ORIGIN = 0x10050000,  LENGTH = 64K
}

続いて、バッファを所望のSRAM に配置する設定みたいなのを書いていく。

まず、バッファ用のセクション[2]を定義して、バッファにつけてやる。

今回は buffer0、buffer1 と定義した。
んで、buffer0 はSRAM1_data に、
buffer1 は SRAM2_data に配置することにした。

まず、リンカにセクションを定義する。

  } >SRAM1_text	
  __DATA_END = __DATA_ROM + (_edata - _sdata);
  text_end = ORIGIN(SRAM1_text) + LENGTH(SRAM1_text);
  ASSERT(__DATA_END <= text_end, "region SRAM1_text overflowed with text and data")

+  /* initialize buffer0 */
+  .buffer0 :
+  {
+    . = ALIGN(4);
+    KEEP (*(.buffer0*))
+    . = ALIGN(4);
+  } >SRAM1_data
・・・
・・・
  } >SRAM2_data	
+  /* initialize buffer1 */
+  .buffer1 : 
+  {
+    . = ALIGN(4);
+    KEEP(*(.buffer1*))
+    . = ALIGN(4);
+  } >SRAM2_data
・・・

次に、バッファの定義部でセクションを付与する。

・・・
volatile uint32_t __attribute__((__section__(".buffer0"))) __attribute__((used))  au32buffer0[BUFFER_LEN] = {0x00};
volatile uint32_t __attribute__((__section__(".buffer1"))) __attribute__((used))  au32buffer1[BUFFER_LEN] = {0x00};
・・・

今回は、SRAM1_text に展開されている .data セクションは無視して SRAM1_data を定義した。
少々強引かもしれない。もし気に入らないなら、SRAM1_bufferのように、
バッファ用のメモリ定義として記述するのもアリだと思う。

また、セクションの定義を挿入する位置も大事。
リンカスクリプト上の . はリンカでシンボルを集めるごとに
インクリメントされていくので、集める順に記載する必要がある。

これでビルドしてみる。

ktkr!!!!!!!

脚注
  1. 訓練された人は、このようなイケてるGUI でなく *.list や *.map で確認する ↩︎

  2. バッファをリンカで集めるための印みたいなもの。 ↩︎

Discussion