当社はIoTデバイス向けにi.MX9352を評価しています。私はM33コア用のアプリケーションを作成しました。これにはペリフェラルから大量のサンプルを収集する時間的責任のIO操作が含まれます。開発のために、Linuxからリモートプロックを使ってM33コードを読み込み、起動しています。コードはC言語で書かれ、MPUXpresso 26.06.00 SDKを使用しています。
コードはうまく動作するようになったのですが、今度はサンプル用の大きなバッファ(約24kB)が必要です。私はこれを静的配列として、または`malloc`で割り当てられたヒープとして追加しようと試みました。いずれにせよ、コンパイル出力では十分なRAMがあると示されているのに、私はすぐにRAMが切れてしまうようです。
作業版:
こちらは小さなバッファのビルドのメモリ情報で、**問題なく動作します*(ただしバッファは私たちの要件には小さすぎます)。
Memory region Used Size Region Size %age Used
m_interrupts: 1140 B 1144 B 99.65%
m_text: 78300 B 129928 B 60.26%
m_m33_suspend_ram: 0 B 8 KB 0.00%
m_a55_suspend_ram: 0 B 4 KB 0.00%
m_data: 48016 B 108 KB 43.42%
m_rsc_tbl: 0 B 4 KB 0.00%
build finished successfully.
ELFファイルからの情報は以下のとおりです。
readelf -l imx_m33.elf
Elf file type is EXEC (Executable file)
Entry point 0xffe0595
There are 4 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0x0ffe0000 0x0ffe0000 0x00474 0x00474 R 0x1000
LOAD 0x001478 0x0ffe0478 0x0ffe0478 0x131dc 0x131dc RWE 0x1000
LOAD 0x015000 0x20003000 0x0fff3654 0x00170 0x00170 RW 0x1000
LOAD 0x000180 0x20003180 0x0fff37e0 0x00000 0x0ba10 RW 0x1000
Section to Segment mapping:
Segment Sections...
00 .interrupts
01 .resource_table .text .ARM .init_array .fini_array
02 .data
03 .bss .heap .stack大規模な静的割り当て:
こちらは**24 kBの静的割り当てバッファ**を持つビルドのメモリとELFファイル情報です。
つまり:
static uint32_t m_sample_queue[SAMPLE_QUEUE_LENGTH]; // SAMPLE_QUEUE_LENGTH = 6000Memory region Used Size Region Size %age Used
m_interrupts: 1140 B 1144 B 99.65%
m_text: 78240 B 129928 B 60.22%
m_m33_suspend_ram: 0 B 8 KB 0.00%
m_a55_suspend_ram: 0 B 4 KB 0.00%
m_data: 72016 B 108 KB 65.12%
m_rsc_tbl: 0 B 4 KB 0.00%
build finished successfully.
### (As expected, the `m_data` section has increased in size.) ###
readelf -l imx_m33.elf
Elf file type is EXEC (Executable file)
Entry point 0xffe0595
There are 4 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0x0ffe0000 0x0ffe0000 0x00474 0x00474 R 0x1000
LOAD 0x001478 0x0ffe0478 0x0ffe0478 0x131a0 0x131a0 RWE 0x1000
LOAD 0x015000 0x20003000 0x0fff3618 0x00170 0x00170 RW 0x1000
LOAD 0x000180 0x20003180 0x0fff37a0 0x00000 0x117d0 RW 0x1000
Section to Segment mapping:
Segment Sections...
00 .interrupts
01 .resource_table .text .ARM .init_array .fini_array
02 .data
03 .bss .heap .stackLinuxでremoteprocを使ってこのバージョンを起動しようとすると起動できず、dmesgは以下のエラーを表示します。
[ +0.001258] imx-rproc remoteproc-cm33: Translation failed: da = 0xfff37a0 len = 0x117d0
[ +0.000021] remoteproc remoteproc0: bad phdr da 0xfff37a0 mem 0x117d0
[ +0.000006] remoteproc remoteproc0: Failed to load program segments: -22
[ +0.008868] remoteproc remoteproc0: Boot failed: -22クロードは、これは.bss .heap .stackの問題だと私に言った。PhysAddr が `0x0fff37a0` で、サイズが `0x117d0` になったため、このセクションが使用不可となります。`0x0fff37a0 + 0x117d0 = 0x10004f70` は、M33 コード TCM アドレス範囲0x0ffe0000 .. 0x10000000を超えています。説明は分かりにくかったのですが、私の解釈では、静的初期化は「code」セクションに記述する必要があり、「system」TCM領域(残りの128kB)には十分な空き容量があるにもかかわらず、オーバーフローが発生してしまうということです。だから、これで納得できるかもしれません。
動的(ヒープ)割り当て:
例えば。:
uint32_t *p_sample_queue = malloc(SAMPLE_QUEUE_LENGTH, sizeof(uint32_t));Cで利用可能なデフォルトのヒープサイズはわずか1 kBなので、 malloc は大きなバッファでは失敗します。
プロジェクトのCMakeを修正し、 __heap_size__を介してより大きなヒープ(32kB)を割り当てるようにしました。この__heap_size__はリンカースクリプトに渡されます。
mcux_add_linker_symbol(
SYMBOLS "__stack_size__=0x400 \
__heap_size__=0x8000 \ <---- Added
__use_shmem__=1 \
__multicore__=1 \
"
)ビルド出力とELFファイル情報:
Memory region Used Size Region Size %age Used
m_interrupts: 1140 B 1144 B 99.65%
m_text: 78240 B 129928 B 60.22%
m_m33_suspend_ram: 0 B 8 KB 0.00%
m_a55_suspend_ram: 0 B 4 KB 0.00%
m_data: 103760 B 108 KB 93.82%
m_rsc_tbl: 0 B 4 KB 0.00%
build finished successfully.
#### ELF file info: ####
readelf -l imx_m33.elf
Elf file type is EXEC (Executable file)
Entry point 0xffe0595
There are 4 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0x0ffe0000 0x0ffe0000 0x00474 0x00474 R 0x1000
LOAD 0x001478 0x0ffe0478 0x0ffe0478 0x131a0 0x131a0 RWE 0x1000
LOAD 0x015000 0x20003000 0x0fff3618 0x00170 0x00170 RW 0x1000
LOAD 0x000180 0x20003180 0x0fff37a0 0x00000 0x193d0 RW 0x1000
Section to Segment mapping:
Segment Sections...
00 .interrupts
01 .resource_table .text .ARM .init_array .fini_array
02 .data
03 .bss .heap .stackこれは問題を改善するどころか悪化させているようだ(.bss/.heap/.stackPhysAddr 0x0fff37a0、サイズ 0x193d0)。
[ +0.001320] imx-rproc remoteproc-cm33: Translation failed: da = 0xfff37a0 len = 0x193d0
[ +0.000019] remoteproc remoteproc0: bad phdr da 0xfff37a0 mem 0x193d0
[ +0.000006] remoteproc remoteproc0: Failed to load program segments: -22
[ +0.002908] remoteproc remoteproc0: Boot failed: -22ヒープ割り当てを使うことでコードセクションを小さくし、データセクションからメモリを割り当てられると思っていました。上記のビルド出力に示されている「m_data」セクションは確かに大きいです。
リファレンスマニュアルの「Code TCM」の範囲に一致する「PhysAddr」の意味がよく分かりません。本来「System TCM」領域にあるべきもの(だと思うのですが)についてもです。「VirtAddr」の下のアドレスは正しいようです。
ELF ファイルはなぜまだ .bss/.heap/.stack を配置しようとするのかPhysAddr 0x0fff37a0のデータについて、なぜランタイムヒープ割り当てを使うとこんなに大きいのでしょうか?また、「System TCM」領域に大きなバッファを割り当てる方法はありますか?
こんにちは、 @jcolebakerさん
データ/BSS/ヒープ/スタックのLMAをSystem TCMに変更することもできます。MCUXリンカースクリプトでは、データセグメントのロードアドレス(AT)をコードTCMからSystem TCMに変更し、PhysAddrも0x2000_0000に当てはまるようにします。
.data : { ... } > m_data AT> m_data /* Do not use AT> m_text */
.bss : { ... } > m_data
LMA == VMAが両方ともSystem TCMにある場合、PhysAddrは0x2000_xxxxとなり、remoteprocドライバーの{0x20000000, ..., 0x00040000}(256 KB)の範囲に一致し、remoteprocが正しく翻訳できるようにします。
よろしくお願いします、
志明
ありがとう、うまくいったよ!
なお、より大きなヒープを使用するために移動する必要があった主なセグメントは、「heap」セグメントでした。
.heap : { ... } > m_data AT> m_data