2406042_ja-JP

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

2406042_ja-JP

2406042_ja-JP

LPC55S69: CPBOOT/CPUCTRL/CPUCFGシーケンスを完全に検証したにもかかわらず、コア1が起動しない

LPC55S69: ブートシーケンスが完全に検証されているにもかかわらず、コア1が実行を開始しない(MCMGRと手書きレジスタ書き込みの両方で同様に失敗する)。

環境

  • ボード:LPC55S69-EVK(LPCXpresso55S69)、LPC55S69JBD100
  • IDE:MCUXpresso IDE v25.6 [ビルド136] [2025-06-27]
  • OS:Linux(openSUSE)
  • ツールチェーン:GNU ARM Embedded(バンドル)、GCC 14.2.1
  • デバッグプローブ:オンボードLPC-Link2、LinkServerバックエンド
  • 使用されたSDKコンポーネント:driver.flexcomm、driver.mailbox、ミドルウェア.マルチコア.mcmgr_lpc55s69、freertos_kernel + cm33_non_trustzone_port (マスターのみ)

概要

コア0(マスター、cm33_core0)は正常に動作します。コア 1 (スレーブ、cm33_core1、ロール M33SLAVE) は、 2 つの別々のクリーンルーム プロジェクト ビルド ( 1つは手書きのレジスタ シーケンス、もう 1 つは NXP 独自の MCMGR ミドルウェアを使用) において、レジスタ レベルとメモリ レベルでブート シーケンスのすべての要素が独立して正しいことが検証されているにもかかわらず、自身の main () の最初の命令さえ実行しないようです。どちらの試みも、全く同じ行き詰まりに陥った。

独立機関によって正しいと検証された内容

試み1 ― 手書きのブートシーケンス

  • SYSCON->CPBOOT は、組み込みスレーブイメージの実際のリンカ確認済みアドレスに設定されます(objdump -h section VMA で検証し、nm シンボルアドレスと照合します。0x0 に解決されるシンボルではなく、実際のゼロ以外の組み込み位置です)。
  • SYSCON->CPUCTRL は、書き込み解放直後に 0x08 (CPU1CLKEN ビット 3 セット、CPU1RSTEN ビット 5 クリア) として読み戻され、インバンドでキャプチャされました (書き込みを実行した関数によって共有メモリに書き込まれ、後で古い可能性のあるデバッガ セッションを介して読み取られたものではありません)。
  • SYSCON->CPUCFGビット2(CPU1ENABLE)がセットされていることを確認(0x04)
  • 確認されたブートアドレスのベクターテーブルは独立して有効性を検証:初期スタックポインタが正しく計算されました(Core 1のSRAM領域の上部)、リセットベクターアドレスはnmの実際のResetISRシンボルと一致しています(ターゲットアドレスを分解して本物で妥当なCortex-M起動コードを見つけたことで確認:cpsid i →SystemInit() → data_init/bss_initループ → cpsie i → __main → _initio → アプリケーション main())
  • 両方のコアで独立してコンパイルされた.mapファイルにおいて、共有メモリ構造体が同一の物理アドレスに解決されることが確認されました。ファイル
  • Core 1のプライベートSRAM/スタック領域がCore 0の領域と重複していないことを確認しました(別の物理SRAMバンクに移動済み)。
  • 埋め込まれたスレーブイメージの.dataを確認しましたセクション (ゼロ初期化されていないグローバル変数) は、コア 0 のライブ メモリ内に配置されません (INSERT BEFORE .data を使用したカスタム リンカー スクリプト フラグメントが必要)。デフォルトのリンカースクリプトにはobjcopyで名前変更されたマルチコアセクションの配置ルールがなく、そうでなければ「孤立セクション」としてコア0のSRAMに配置されてしまうため。

上記すべてにもかかわらず、Core 1 の main() の最初の行として書き込まれた診断値 (共有され、正しくアドレス指定されていることが確認されたメモリ内) は、初期値から変化しません。

試行2 — NXPのmcmgr_lpc55s69ミドルウェアを使用した新規プロジェクト

レジスタ書き込みを手書きで行う代わりに、MCMGR_Init() / MCMGR_StartCore() / MCMGR_TriggerEvent() を使用してゼロから再構築し、レジスタシーケンスに誤りがないかを確認しました。

  • mcmgr_internal_core_api_lpc55s69.cを直接読んでください:mcmgr_start_core_internal()が正しいSDKマクロ(SYSCON_CPUCTRL_CPU1RSTEN_MASKなど)を使ってCPBOOT→CPUCTRLシーケンス→同じCPUCFGを実行していることを確認しました。
  • MCMGR_Init() (main() から呼び出される) は MCMGR_EarlyInit() / mcmgr_early_init_internal() を呼び出さないことが分かりました。後者は独立した公開関数であり、ソースコードのコメントには「(SystemInitHook の起動シーケンス内で)リセットエントリのできるだけ近くで呼び出されることを意図している」と記載されているが、生成されたプロジェクトではこれを自動的に接続する仕組みは何もない。SystemInitHook() は汎用デバイス起動ファイルでは __attribute__((weak)) であり、デフォルトでは空のスタブになります。
  • 両方のコアで独自の SystemInitHook() オーバーライドを追加し、mcmgr_early_init_internal(MCMGR_GetCurrentCore()) を呼び出しました。.mapで確認済みこのオーバーライドが、両方のプロジェクトで実際の関数(弱いスタブではない)としてリンクするファイル。
  • 試行1のすべての修正を再適用および再確認しました(反復的な再構築全体にわたる埋め込みアドレスの安定性、.dataセクションのリダイレクトは、同じリンカーフラグメント技術を使用し、コア1のSRAMの再配置、CPUCFG/CPBOOT/CPUCTRLレジスタの値はすべて試行1の結果と同一です。
  • MCMGR_BUSY_POLL_COUNTデフォルトで定義されていないため、mcmgr.cではMCMGR_StartCore(..., kMCMGR_Start_Synchronous)ブロックが タイムアウトなしで 使えます内部待機ループ (while (s_mcmgrCoresContext[coreNum].state)!= kMCMGR_RunningCoreState)) は、mcmgr.h のマクロの条件付きコンパイルを直接読み取ることで確認されました。

結果:全く同じ結果。コア0がMCMGR_StartCore()内で永久にブロックされる。診断用共有メモリ値(両方のコアの.mapで同じアドレスが確認されました)ファイルは、真に共有されたSRAMバンク内にあり、.noinitCore 1のmain()の最初の実行可能行として文字通り書かれ、初代値の0を離れません。

質問

CPUCFG、CPBOOT、およびCPUCTRLはすべて、リファレンス実装(mcmgr_internal_core_api_lpc55s69.c)と全く同じように読み取られます。ブートアドレスに埋め込まれたイメージが、正しくリンクされたCortex-Mバイナリであることが独立して確認されていますが、この 部分でCore 1の命令フェッチを開始するために、これら3つのレジスタ書き込みだけではキャプチャされない追加のステップが必要でしょうか?

具体的には:

  • LPC55S69(どのリビジョンでも可)において、CPBOOT/CPUCTRLベースのセカンダリコアブートに影響を与える既知のシリコンエラーはありますか?
  • Core 1の起動には、アプリケーションレベルのレジスタシーケンスに加えて、デバッグプローブレベルのアクション(例:この部分で列挙された2番目のSWDデバイスを対象としたSWDアタッチャ/リボン)も本当に必要なのでしょうか?これは、NXP自身のマルチコアSDKの例(例:)freertos_message_buffers_secondary_core)をIDEsの通常の単一プロジェクト「Debug」フローでデバッグすると、Core 1は別のLaunch グループ設定なしで正常に起動しているように見えます。これは、MCUXpressoのデバッグ起動自体がアプリケーションコードだけではトリガーできない追加ステップを行っている可能性を示唆しています。
  • これら3回の書き込み間に、参照mcmgr_internal_core_api_lpc55s69.cに反映されていない最小遅延、順序制約、または追加のレジスタ(例えば電力/クロック領域)があるのでしょうか?実装?

プロジェクトファイル一式(.mapファイル)を提供いたします。ファイル、またはご要望に応じた最小限の複製プロジェクトを提供いたします。

LPC55xxRe: LPC55S69: Core 1 never starts despite fully verified CPBOOT/CPUCTRL/CPUCFG sequence

解決済み — 根本原因は、Core 1 の起動失敗ではなく、私自身の診断における偽陰性でした

後で同じ症状のThreadを見つけた方のために解決策を投稿します。

実際の根本原因

このプロジェクトのどのバージョンにおいても、コア1は常に正常に起動し、動作していました。問題はCPUCFG/CPBOOT/CPUCTRL、ベクターテーブル、メモリ配置、あるいはブートシーケンス内の他のいずれにもなかった。問題は、コア1が何も実行していないように見えた、私自身の診断ツールのバグだった。

私は小さな共有メモリ構造体を使用していました(__attribute__((section(".noinit.$SRAM4"))))コア1によって書き込まれ、コア0によって読み込まれ、起動の進行状況を監視する。この手法は、プロジェクトで生成されたリンカスクリプトが実際にSRAM4という名前の領域を定義している場合にのみ、真の共有メモリに実装されます。私がゼロから作成したウィザードプロジェクトはその領域を定義していたので、その技術は構造的に機能していましたが、後にNXPの作業中のhello_world例プロジェクト(異なる名前の領域、Ram1/rpmsg_sh_memを使ったもので、SRAM4ではなく異なる名前の領域)の上にバージョンを構築した際、同じ属性が静かに各コアのprivate.noinitに移行しましたエラーを発生させる代わりにメモリに記録する。Core 0とCore 1はそれぞれ「shared」構造体の独自のコピーを読み書きしていましたが、コンパイラやリンカは何も問題がないと警告しませんでした。

最終的な結果:私の診断では、2 つの独立したブート実装 (手書きの CPUCFG/CPBOOT/CPUCTRL レジスタと NXP 独自の MCMGR ミドルウェア) と複数のプロジェクト構成にわたるすべてのテストで 0 (進行なし) が報告されました。これは、コア 1 が実際に実行されているかどうかに関係なく、2 つのコアがそもそも同じメモリ アドレスを参照していなかったためです。

実際にどのように発見されたか

NXPの動作するhello_worldサンプルをそのままコピーし、既存の、変更されていない、動作確認済みのmain.cに診断書き込みのみを追加することで、(交換するのではなく)、オンボードLEDでCore 1が本当に全シーケンスを実行していることを視覚的に確認できましたが、共有メモリカウンタは依然として0と表示されていました。その矛盾(実行の物理的証拠と診断の否定)が、コア1ではなく診断自体が壊れていることを露呈させました。セクション名をプロジェクトの実際の領域(.noinit.$SRAM4 ではなく .noinit.$rpmsg_sh_mem)に一致するように修正したところ、すぐに正しい増加値が生成されました。

LPC55xxでマルチコアブートをデバッグしている他の人への教訓

コア間共有メモリに .noinit.$ セクション属性を使用する場合は、別のプロジェクトで動作した名前 (SRAM4 など) を想定するのではなく、その特定のプロジェクトで生成された _Debug_memory.ld に対して領域名を確認してください。ここで不一致が発生すると、ビルド警告もリンクエラーもランタイム障害も発生せず、完全にサイレントに失敗します。そして、実際のブート失敗と全く同じ症状が現れます(レジスタ/ベクタテーブルレベルのデバッグではすべて正常にチェックされます。なぜなら、実際の問題は完全に診断レイヤーにあるからです)。

以前の投稿を読んでくださった皆様、ありがとうございました。CPUCFG/CPBOOT/CPUCTRL/ベクターテーブルの検証作業は無駄ではありませんでした。それらがすべて正しかったことが確認できたことで、最終的に調査対象が未検証の最後の要素である診断メカニズム自体へと絞られました。

Re: LPC55S69: Core 1 never starts despite fully verified CPBOOT/CPUCTRL/CPUCFG sequence

アップデート:問題はアプリケーションコードではなく、プロジェクトやリンカーの設定に特定しました

投稿後、決定的なテストを実施したところ、この可能性が大幅に絞り込まれました。

テスト:NXP独自の未修正マルチコアサンプルは、このハードウェアで正常に動作しますか?

LPCXpresso55S69 用に multicore_examples/hello_world (プライマリ + セカンダリ) を新規にインポートし、完全に変更を加えず、そのままデバッグしました。

結果:うまくいった。オンボードのRGB LEDは、500ms点灯/500ms消灯の規則的な点滅パターンで動作します。これは、同じボードに書き込んだ自分のプロジェクトと直接比較することで確認済みです(自分のプロジェクトではLEDが消灯、変更されていないサンプルではLEDが点滅、自分のプロジェクトを再書き込みすると再びLEDが消灯)。これは決定的です: まさにこのボード、プローブ、IDEのインストールでデュアルコア実行が可能です。

テスト:例のアプリケーションコードは私のプロジェクトの設定内で動作しますか?

問題が自分のアプリケーションコードにあるのか、プロジェクトのビルド/リンク設定にあるのかを区別するために、動作中の例のセカンダリコアmain.cをコピーしました。app.h、および hardware_init.cそのまま(バイト単位、未修正)で自分のスレーブプロジェクトに組み込まれ、自分のアプリケーションコードを完全に置き換えました。

結果:LEDは点滅しない。元のサンプルプロジェクトでは正常に動作する、全く同じで変更されていないNXPコードが、私のプロジェクト構成内でビルドするとCore 1の起動に失敗します。

これが証明すること

問題はアプリケーションレベルのコードではありません(すでに2回確認されています。手書きレジスタ実装とMCMGRベースの実装で、そして今回は3回目はそのサンプルのソースファイルで確認されています)。私のプロジェクトのマルチコアリンカー設定/メモリ領域構成が、動作するサンプルとどのように異なっているかという点に特有の問題があり、私はできる限り正確に一致させようと努力したにもかかわらず、それが起こってしまいました。

  • MCMGR_StartCore() の後、CPUCFG、CPBOOT、CPUCTRL はすべて意図どおりに読み戻されます。
  • 埋め込みイメージのベクトルテーブルは、独立して検証され、有効であることが確認されています(正しいスタックポインタ、実際のResetISRシンボルと一致する正しいリセットハンドラアドレス)。
  • マスターメモリ領域はRAM領域(PROGRAM_FLASHではない)に設定されており、これはCore 1のイメージをフラッシュではなくRAMに埋め込むという動作例のアプローチと一致しています。
  • コア1のプライベートメモリはコア0のプライベートメモリと重複しません

構造上の違いが1つ見つかりましたが、まだ解決していません。動作例のセカンダリコアプロジェクトの.cprojectには、PROGRAM_FLASHメモリ領域のオーバーライドがまったく含まれていません。これは、動作例のセカンダリコアプロジェクトの.cprojectに、PROGRAM_FLASHメモリ領域のオーバーライドがまったく含まれていないためです。(カスタムRAM由来の領域は2つのみ)。私がゼロからウィザードで作成したスレーブプロジェクトには、再配置された PROGRAM_FLASH を含む 3 つの領域があります。その領域を完全に削除しようとすると(動作する例に正確に一致させるため)、MCUXpressoのMCU設定ページ(NullPointerException: this.mcuPage is null)がクラッシュし、IDEのツールがフラッシュ領域が定義されていないプロジェクトを快適にサポートしていないことを示唆しています。これが作業中の例の正確な設定を手作業で照合するのが難しい理由かもしれません。

質問

マスターの「M33SLAVE」役割+マルチコアリンカー設定以外に、SDKのhello_world例と同じ動作状態にするプロジェクトをゼロから作るために必要な特定のマルチコアプロジェクト構成はあるのでしょうか?それともMCUXpresso IDE v25.6.136に既知の制限やバグがあるのでしょうか?マルチコアLPC55S69プロジェクト用のプロジェクトウィザードで、サンプルプロジェクトファイルがウィザードでは再現できない方法で回避しているものはありますか?

両プロジェクトの完全な.cprojectファイルを喜んで共有します。必要に応じて直接比較するためのファイル。

Tags (1)
No ratings
Version history
Last update:
Wednesday
Updated by: