これまでの経緯以前、GD32H7 でネットワーク機能を有効化する試みをしたことがある。最終的な製品プロジェクトではこのチップを使わなかったため、評価だけ行って、そのままお蔵入りにしていた。当時の現象はこうだ。公式サンプルと完全に同じライブラリ、ペリフェラル設定、呼び出し順序、操作方法を使っていたにもかかわらず、私が行ったのは、公式の Keil プロジェクトを cmake-gcc プロジェクトに置き換えたことだけだった。問題は、公式サンプルはコンパイルして書き込めばすべて正常に動くのに、私のプロジェクトではどうやっても ping が通らなかったことだ。私は lwip というネットワークライブラリや ETH ペリフェラルについては知識が本当に乏しく、GD のサポートでも原因を突き止められなかった。原因要するに、GD32H7 では次のような設定が必要になる。0x0000 から始まるアドレス領域全体をバックグラウンド設定として MPU で保護し、その上で後続の MPU 設定ブロックで実際の設定を行う。Cmpu_region_init_struct mpu_init_struct; /* disable MPU */ ARM_MPU_Disable(); mpu_init_struct.region_number = MPU_REGION_NUMBER0; mpu_init_struct.region_base_address = 0x00000000U; mpu_init_struct.instruction_exec = MPU_INSTRUCTION_EXEC_NOT_PERMIT; mpu_init_struct.access_permission = MPU_AP_NO_ACCESS; mpu_init_struct.tex_type = MPU_TEX_TYPE0; mpu_init_struct.access_shareable = MPU_ACCESS_SHAREABLE; mpu_init_struct.access_cacheable = MPU_ACCESS_NON_CACHEABLE; mpu_init_struct.access_bufferable = MPU_ACCESS_NON_BUFFERABLE; mpu_init_struct.subregion_disable = 0x87; mpu_init_struct.region_size = MPU_REGION_SIZE_4GB; mpu_region_config(&mpu_init_struct); mpu_region_enable(); /* enable MPU */ ARM_MPU_Enable(MPU_MODE_PRIV_DEFAULT); 問題はどのようにして発生したのかGD32H7 のマニュアルの1.3 メモリマップに記載されている。0x0000 0000〜0x0007 FFFF は ITCM RAM(共有 RAM 由来)として割り当てられているが、この領域はコード領域にも分類されている。その意図は今のところあまり理解できていない。とにかく、コアの動作中にこの領域が RAM 領域と見なされるため、読み書きされる可能性がある。参考資料によると、この点は GD 公式のエラッタにも、どのマニュアルにも記載されていない。もちろん、公式サンプルでもこの設定をしていないことが多い。そうでなければ、私が以前 gcc コンパイルに変更した時点で、すべて正常に動作していたはずだ。この記述があるのは、ST 公式が出している、しかもチップのマニュアルではなく touchgfx というグラフィックライブラリのマニュアルだけだ。M7 プロセッサでは、外部メモリへの投機的アクセスを防ぐ必要がある。防がなければ、高レイテンシやシステムエラーの原因となり得る。STM32H7R/S の場合、これはメモリにアクセスする AXI マスターに影響し、グラフィック性能を著しく低下させる。 MPU は、アクセス可能なアドレス範囲を制御することで、投機的な読み出しアクセスを防げる。最も簡単な方法は、メモリ領域全体を含むバックグラウンド領域を使用し、「強順序・実行禁止」に設定してアクセスを制限することだ。 バックグラウンド領域はデフォルトのリージョン ID-1 に定義すべきである。他のすべてのリージョンの優先順位はこれより高くなるためだ。その後、アクセスが必要なメモリ領域には、適切な設定を施した他の MPU リージョンを定義する。STM32H7R/S では最大 16 個のリージョンを定義できる。 つまり、これは M7 コアの原設計に元々ある欠陥であり、私が STM32H7 で問題に当たらなかったのは、ST 公式がチップを作る際に何らかの手段で問題を回避していたか、あるいは単に偶然ぶつからなかっただけのことだ。参考資料(備忘録)GD32H7 への NEXTDUO 移植の問題GD32H7��ֲNEXTDUO�������� - ��Ƭ�� - Ӳ��Ƕ��ʽ��̳ - Powered by Discuz!����GD32H759im�ϲ���Ӳ���硶V7-2402_ThreadX NetXDUO TCP Server����ֲThreadx+Netxduo����ֲ��֮�������������⣺1��Dcache�����������ӣ�mpu����Ҳû����[mw ... GD32H7��ֲNEXTDUO�������� ,Ӳ��Ƕ��ʽ��̳forum.anfulai.cnDiscuz! Team and Comsenz UI TeamGD32H757ZMT6 は Flash/Load image のレイアウトが変わっただけで、プログラムの動作安定性に明確な差が出た����: GD32H757ZMT6 ���� Flash/Load image ���ֱ仯�����������ȶ��Ծͳ������Բ��졣 - STM32H7 - Ӳ��Ƕ��ʽ��̳ - Powered by Discuz!# GD32H757ZMT6 �����ܷ�/��������˵��## 1. �������оƬ�ͺţ�GD32H757ZMT6��ǰ�������Ϊ��ͬһӲ����ͬһ���̴��롢ͬһ���뻷���£����� Flash/Load im ... ����: GD32H757ZMT6 ���� Flash/Load image ���ֱ仯�����������ȶ��Ծͳ������Բ��졣 ,Ӳ��Ƕ��ʽ��̳forum.anfulai.cnDiscuz! Team and Comsenz UI Team
GD32H7 の MPU 備忘録——0x0000 アドレス領域の設定について
これまでの経緯
以前、GD32H7 でネットワーク機能を有効化する試みをしたことがある。最終的な製品プロジェクトではこのチップを使わなかったため、評価だけ行って、そのままお蔵入りにしていた。
当時の現象はこうだ。公式サンプルと完全に同じライブラリ、ペリフェラル設定、呼び出し順序、操作方法を使っていたにもかかわらず、私が行ったのは、公式の Keil プロジェクトを cmake-gcc プロジェクトに置き換えたことだけだった。問題は、公式サンプルはコンパイルして書き込めばすべて正常に動くのに、私のプロジェクトではどうやっても ping が通らなかったことだ。
私は lwip というネットワークライブラリや ETH ペリフェラルについては知識が本当に乏しく、GD のサポートでも原因を突き止められなかった。
原因
要するに、GD32H7 では次のような設定が必要になる。0x0000 から始まるアドレス領域全体をバックグラウンド設定として MPU で保護し、その上で後続の MPU 設定ブロックで実際の設定を行う。
問題はどのようにして発生したのか
GD32H7 のマニュアルの1.3 メモリマップに記載されている。
0x0000 0000〜0x0007 FFFF は ITCM RAM(共有 RAM 由来)として割り当てられているが、この領域はコード領域にも分類されている。その意図は今のところあまり理解できていない。とにかく、コアの動作中にこの領域が RAM 領域と見なされるため、読み書きされる可能性がある。
参考資料によると、この点は GD 公式のエラッタにも、どのマニュアルにも記載されていない。もちろん、公式サンプルでもこの設定をしていないことが多い。そうでなければ、私が以前 gcc コンパイルに変更した時点で、すべて正常に動作していたはずだ。この記述があるのは、ST 公式が出している、しかもチップのマニュアルではなく touchgfx というグラフィックライブラリのマニュアルだけだ。
つまり、これは M7 コアの原設計に元々ある欠陥であり、私が STM32H7 で問題に当たらなかったのは、ST 公式がチップを作る際に何らかの手段で問題を回避していたか、あるいは単に偶然ぶつからなかっただけのことだ。
参考資料(備忘録)
GD32H7 への NEXTDUO 移植の問題
GD32H757ZMT6 は Flash/Load image のレイアウトが変わっただけで、プログラムの動作安定性に明確な差が出た