マルチコアプロジェクトにおける追加MPU領域の設定 私は基本的に2つのSDKsのサンプルを組み合わせたプロジェクトを作っています。私はRT1170-EVKB SDKのバージョン26.09.00を使っています。このプロジェクトのアイデアは、マルチコアの例とLVGLの例を取り、M7コアがグラフィックスを実行し、その後プログラムを実行するM4コアと通信することです。そのために、SDKsの例を挙げました: freertos_message_buffers(プライマリとセカンダリの両方)をベースプロジェクトとして使用します。その後、lvgl_guider_cm7プロジェクトのコードやドライバーファイルをコピー&ペーストして、ゆっくりとグラフィックを追加しています。 私はlvgl_guider_cm7 mcux_config.hを保持しています同じファイルにしてPXPとVGLiteを使ったようにします。そのためには、フレームバッファをキャッシュ以外の場所に配置する必要があります。SDKの例で使われている共有メモリも非キャッシュに配置する必要があります。こうなると、ディスプレイにアーティファクト(本来あるべきでないオブジェクトに小さな線が入る現象)が発生します。 __USE_SHMEMプリプロセッサを外すことで直せますが、当然ながらマルチコア通信が失敗します。原因はBOARD_EarlyConfigMPU関数にあると考えています。関数の中には、次のような部分があります。 #elif defined(__MCUXPRESSO)
#if defined(__USE_SHMEM)
extern uint32_t __base_rpmsg_sh_mem;
extern uint32_t __top_rpmsg_sh_mem;
uint32_t nonCacheStart = (uint32_t)(&__base_rpmsg_sh_mem);
uint32_t size = (uint32_t)(&__top_rpmsg_sh_mem) - nonCacheStart;
#else
extern uint32_t __base_NCACHE_REGION;
extern uint32_t __top_NCACHE_REGION;
uint32_t nonCacheStart = (uint32_t)(&__base_NCACHE_REGION);
uint32_t size = (uint32_t)(&__top_NCACHE_REGION) - nonCacheStart;
#endif このセクションでは、__USE_SHMEMプリプロセッサに基づいて、共有メモリまたは通常の非キャッシュのいずれかの非キャッシュを定義します。関数のさらに下では、MPU領域を次のように宣言しています: volatile uint32_t i = 0;
...
while ((size >> i) > 0x1U)
{
i++;
}
if (i != 0)
{
/* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */
BOARD_EARLY_ASSERT(!(nonCacheStart % size));
BOARD_EARLY_ASSERT(size == (uint32_t)(1 << i));
BOARD_EARLY_ASSERT(i >= 5);
/* Region 10 setting: Memory with Normal type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_NONCACHE, nonCacheStart);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, i - 1);
} 今度は、MPU内の両方の領域を定義して、LVGLがアーティファクトなしで動作し、rpmsgメッセージバッファが通信できるようにしたいと考えています。私の記憶領域は以下の通りです: 私が試みたのは、上記のコードを修正して両方のMPUリージョン定義を実行することでした。例えば: #elif defined(__MCUXPRESSO)
extern uint32_t __base_NCACHE_REGION;
extern uint32_t __top_NCACHE_REGION;
uint32_t nonCacheStart = (uint32_t)(&__base_NCACHE_REGION);
uint32_t nonCacheSize = (uint32_t)(&__top_NCACHE_REGION) - nonCacheStart;
#if defined(__USE_SHMEM)
extern uint32_t __base_rpmsg_sh_mem;
extern uint32_t __top_rpmsg_sh_mem;
uint32_t rpmsgShmemStart = (uint32_t)(&__base_rpmsg_sh_mem);
uint32_t rpmsgShmemSize = (uint32_t)(&__top_rpmsg_sh_mem) - rpmsgShmemStart;
#endif この方法だと、通常の非キャッシュ領域は常に定義され、共有メモリ領域は使用される場合にのみ定義される。MPUのリージョン定義を次のように修正しました: volatile uint32_t i = 0;
...
while ((nonCacheSize >> i) > 0x1U)
{
i++;
}
if (i != 0)
{
/* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */
BOARD_EARLY_ASSERT(!(nonCacheStart % nonCacheSize));
BOARD_EARLY_ASSERT(nonCacheSize == (uint32_t)(1 << i));
BOARD_EARLY_ASSERT(i >= 5);
/* Region 10 setting: Memory with Normal type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_NONCACHE, nonCacheStart);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, i - 1);
}
#if (__USE_SHMEM)
i = 0;
while ((rpmsgShmemSize >> i) > 0x1U)
{
i++;
}
if (i != 0)
{
/* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */
BOARD_EARLY_ASSERT(!(rpmsgShmemStart % rpmsgShmemSize));
BOARD_EARLY_ASSERT(rpmsgShmemSize == (uint32_t)(1 << i));
BOARD_EARLY_ASSERT(i >= 5);
/* Region 16 setting: Memory with Normal type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_SHMEM, rpmsgShmemStart);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 1, 0, 0, 0, 0, i - 1);
}
#endif この作業を行う際に、board.h 内に追加の MPU 領域用のマクロを作成しました。こんな感じで: #define BOARD_MPU_REGION_SHMEM (16) /* rpmsg shared memory */ これらの変更を加えたことで、LVGLはアーティファクトなしで描画できるようになったが、マルチコア通信は依然として失敗する。マルチコア通信を動かすM4Threadにブレークポイントを設けました。時には最初にメッセージを受信したことを通知してトリガーされますが、メッセージデータが誤っているため、そのメッセージデータに関連するコードは実行されません。ブレークポイントが数回トリガーされると、それ以降は二度とトリガーされなくなります。 このプロジェクトを実行するために、MPU領域の定義など、何か見落としている点はありますか? Re: Multicore Project setup of an additional MPU region 変更はプライマリコアにのみ適用されました。プライマリコアはBOARD_EarlyConfigMPUを実行し、セカンダリコアはBOARD_ConfigMPUを実行するため、セカンダリコアの機能には、プライマリコアに変更を加えた動作が既に含まれています。以下は、セカンダリコアがハードウェア初期化時に実行する処理の一部です。 #elif __CORTEX_M == 4
void BOARD_ConfigMPU(void)
{
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
...
#elif defined(__MCUXPRESSO)
extern uint32_t __base_NCACHE_REGION;
extern uint32_t __top_NCACHE_REGION;
uint32_t nonCacheStart = (uint32_t)(&__base_NCACHE_REGION);
uint32_t nonCacheSize = (uint32_t)(&__top_NCACHE_REGION) - nonCacheStart;
#elif defined(__ICCARM__) || defined(__GNUC__)
...
#endif
#if defined(__USE_SHMEM)
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
...
#elif defined(__MCUXPRESSO)
extern uint32_t __base_rpmsg_sh_mem;
extern uint32_t __top_rpmsg_sh_mem;
uint32_t rpmsgShmemStart = (uint32_t)(&__base_rpmsg_sh_mem);
uint32_t rpmsgShmemSize = (uint32_t)(&__top_rpmsg_sh_mem) - rpmsgShmemStart;
#elif defined(__ICCARM__) || defined(__GNUC__)
...
#endif
#endif そして関数の後半では次のようになります。 uint32_t i = 0;
/* Only config non-cacheable region on system bus */
assert(nonCacheStart >= 0x20000000);
...
while ((nonCacheSize >> i) > 0x1U)
{
i++;
}
if (i != 0)
{
/* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */
assert(!(nonCacheStart % nonCacheSize));
assert(nonCacheSize == (uint32_t)(1 << i));
assert(i >= 5);
/* Region 0 setting: Memory with device type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_NONCACHE, nonCacheStart);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, i - 1);
}
#if defined(__USE_SHMEM)
i = 0;
while ((rpmsgShmemSize >> i) > 0x1U)
{
i++;
}
if (i != 0)
{
/* The MPU region size should be 2^N, 5<=N<=32, region base should be multiples of size. */
assert(!(rpmsgShmemStart % rpmsgShmemSize));
assert(rpmsgShmemSize == (uint32_t)(1 << i));
assert(i >= 5);
/* Region 1 setting: Memory with device type, not shareable, non-cacheable */
MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_RPMSG_SHMEM, rpmsgShmemStart);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 2, 0, 0, 0, 0, i - 1);
}
#endif どちらのプロジェクトも、プリプロセッサで__USE_SHMEMが定義されています。以下は、セカンダリコアのメモリ構成です。 他に何か見落としている点があるのでしょうか?それとも、私の変更方法が間違っているのでしょうか?メインプロジェクトの設定にある「リンカースクリプトの管理」セクションに何か追加する必要はありますか?機会があれば、EVK-Bボード上で動作するプロジェクトの.zipをアップロードして、問題を確認したり再現したりできると思います。 Re: Multicore Project setup of an additional MPU region こんにちは、 @CMoran さん。
あなたの理解は理にかなっていますが、あなたが言及した変更がCM7とCM4の両方のコアに適用されたかどうかは明確ではありませんでした。各コアにはboard.hの定義があり、そこで、それぞれがMPUの独自の構成を使用して、初期ハードウェア初期化時にセットアップを行います。ご指摘の変更がプライマリコアのみに適用された場合、コアがメモリ領域を均等に扱わない可能性があり、その結果、このような予期せぬ動作が発生すると考えられます。
変更が両方のコアに適用され、MPU設定が一致していることを確認してください。また、両方のプロジェクトのプリプロセッサ定義で__USE_SHMEMが設定されていることも確認してください。 Re: Multicore Project setup of an additional MPU region こちらが.zipファイルですその中には、M7およびM4プロジェクトが含まれている。修正しても結局うまくいかなかったので、修正前の状態のままにしておきました。この例では、ターミナルを開いて中央のボタンを押すと、m7コアとm4コアの両方からメッセージが表示されます。画面上を移動する設定アイコンには、説明されているように多数の不具合が発生しています。 m7プロジェクトから__USE_SHMEMプリプロセッサを削除すると、設定アイコンの不具合は解消されますが、マルチコア通信が失敗します。 上記で適用した変更を加えることで設定アイコンも修正されますが、マルチコア通信は失敗します。 このデモで使用されているスクリーンはRK055HDMIPI4MA0です。 Re: Multicore Project setup of an additional MPU region 残念ながら、新しいメモリ領域定義を作成する前に: #define BOARD_MPU_REGION_SHMEM (16) /* rpmsg shared memory */ 私は単に、キャッシュ以外の用途で定義済みのメモリ領域を再利用していただけです。 #define BOARD_MPU_REGION_NONCACHE (10) /* Noncacheable space in application */ そして、私も同じ結果になった。非キャッシュ領域に合わせて、新しいメモリ領域の定義を10に変更しました。コア同士の通信はうまくいかなかった。 ブレークポイントを使用して両方のコアでrpmsg共有メモリの開始位置とサイズを確認しましたが、両方とも正しい開始位置(0x20340000)とサイズ(0x10000)でした。両方のコアのARM_MPU_RASR()関数の4番目のパラメータを1に変更し、その領域が「共有可能」であることを示すようにしました。相変わらず成果は出ていない。あなたかチームメンバーの方に時間があれば、私のプロジェクトのコードを別の返信に投稿しましたので、ご覧ください。試せばいいアイデアが尽きかけています。 Re: Multicore Project setup of an additional MPU region こんにちは、 @CMoran さん。
わかった。最初の返信に戻りますが:
あなたは、メモリ領域の新しい定義を作成したと述べました。
#define BOARD_MPU_REGION_SHMEM (16) /* rpmsg shared memory */
しかし、ARM_MPU_RBAR() の定義では、MPU_RBAR_REGION_Msk が使用されており、これは 15 と定義されています。
#define MPU_RBAR_REGION_Msk (0xFUL /*<< MPU_RBAR_REGION_Pos*/)
CM7では、地域の数を16と定義しており、0~15の番号が付けられている。
つまり、実際にはリージョン0を設定しているのです。 Re: Multicore Project setup of an additional MPU region こんにちは、 @CMoran さん。
プロジェクトをビルディングし、その結果生まれた.ldのメモリ領域を分析した後、LVGLのフレームバッファとマルチコアメッセージバッファが、非連続した物理メモリであるためマージできない別々のメモリ領域に配置されている領域が見えます。
LVGLフレームバッファ用のNCACHE_REGION(アドレス0x81000000、16MB、SDRAM内)
マルチコアメッセージバッファ用のrpmsg_sh_mem(アドレス0x20340000、64KB、OCRAM内)
とはいえ、MPUリージョン7は現在、キャッシュ可能なノーマルメモリとして0x20300000〜0x2037FFFF KB(512KB)をカバーしており、この範囲にはrpmsg_sh_mem領域も含まれます。これにより、共有メモリがキャッシュ可能になり、あなたが見ているようなコア間通信エラーが発生する可能性があります。リージョン7のサイズを縮小して、すでにキャッシュできないリージョン3にrpmsg_sh_memが落ちるようにすることは、既存ドライバのMPUレベルの変更なしにメッセージバッファの適切な機能を確保する簡単な解決策かもしれません。 Re: Multicore Project setup of an additional MPU region こんにちは、 @EdwinHzさん あなたの提案を少し試してみました。MPUのリージョン7(OCRAM2)を512KBから256KBに変更しました。 /* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(BOARD_MPU_REGION_OCRAM_B, 0x20300000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB); __USE_SHMEM プリプロセッサを削除した後、rpmsg_sh_mem は MPU 領域 3 にフォールスルーしますが、これは既にキャッシュ不可として定義されています。私が作成したデモは、意図したとおりに動作するようになりました。
View full article