STM32H5を使ってみる3 -待ち受ける初見殺しの罠たち-

20240516追:
秋月さんよりNUCLEO-H563ZI販売開始です!!
20240516追:



クリスマス直前ですがわずかな時間を見つけて少しでもSTM32H5を使った
記事を書き残していきます…その先に何があるのかわからなくとも…!
すでにFatFsのSTM32H5への移植例はアップロードしておりますので今回も
これをもとに解説を進めていきますよぅ!


今回は基本中の基本、GPIOのほかにCortex-M33というかSTM32H5を使う人の
所見殺しポイントの回避とかを紹介してまいります。


●GPIOのレジスタがちょっと合理化

これはSTM32L5からなのですがGPIO出力のビットセット/リセットのレジスタ
(BSRR/BRR)が別々のアドレスに設定されております。

これは何気に良い改良だと思います。STM32F1とかの古い品種では上位16bit
がBRRで下位16bitがBSRRでひとまとまりになっており、HALに振り回されて
非常に使いづらくオーバーヘッドも多いので実行速度・コードサイズ的に
とても不利な代物でした。

で、ねむいさんは例えばSTM32F4のHALライブラリを使った作例とかではこんな
感じの構造体を作ってキャストしなおしてアクセスする手法でGPIOのビット
セット&リセットを簡潔にやってきましたが、たまにソースコードちゃんと
読まない方々からBRRなんてないからこのプログラムは動かないのでは?とか
質問もらうのですがほんとにBRRが定義されてないのならそもそもビルド通らん
やろうがぁああああ!!ちゃんとstm32f4xx_hal_conf.hの一番下のところ読めや
あああぁぁあぁあ!!!11!1

はぁはぁ…失礼…話を戻しますがSTM32H5・STM32L5以降ではそういう
小手先の手間も省けてBRR/BSRRられるようになりましたので安心です♥


●ビルド途中でGCCがセグメンテーションフォルトして死ぬ

なんでやねん
どうしたらよいのだ私は…
具体的に言うとGCC12でstm32h5xx_hal_dma_ex.cを最適化レベル-O2以降で
コンパイルしたらセグフォ死します…何やっても先に進めません

ねむいさんより先にSTM32H5触れた方も所見殺しの罠にかかっておられ
ました…
やはり初物はエラッタからライブラリに至るまで罠が満載…


ねむいさんは苦しみ紛れに屁をこいたような対策でセグフォ死の罠を
回避を行うことで対策しております。ちなみに現在リリースされている
GCC13では対策されて-O2にしても落ちなくなったので安心です☆

ねむいさんはSTM32H5のDMA対応ですっっごく時間食われましたがその半分
くらいはセグフォ問題で捕まりました…F**K!


●DACを使用したりUniqueIDを読みだそうとしたらHardFaultって死ぬ
だからなんでやねん
L5だと全く問題なかったのに…!


その理由はUIDレジスタのアドレスの変更に理由があります。
STM32L5ではこれらのレジスタは0x0BFA0590だったのですがSTM32H5では
0x08FFF800以降に変更されており、このアドレス領域はフラッシュメモリが
存在するアドレス(0x08000000)と同じであり命令実行を前提としている
そうなので普通の使い方ではIキャッシュを有効にすると思いますが有効に
してUIDレジスタがある0x08FFF800にアクセスした瞬間に命令領域にデータ
アクセスしようとしたと判断されてHardFaultして死にます!


もっと凶悪なのがHALライブラリのDACライブラリ中でパッケージデータを
判別して使用するチャネルを設定するコードがあり、そのパッケージを判別
するレジスタも0x08FFF800以降に存在するので何も対策してないと上記の例と
同じようにHardFaultして容赦なく死にます!!

STM32のフォーラムでは罠にかかった犠牲者がすでにちらほら出ております…


で、対策なのですがMPUを使用して0x08FFF800あたりのアドレスを読み出し
オンリー&命令実行禁止設定にしてあげればよいです。具体的には下記の
コードになります。

static void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct;
MPU_Attributes_InitTypeDef MPU_AttributesInit;

/* Configure region for UID,PACKAGE,FLASHSIZE and other registers */
/* Disable MPU */
HAL_MPU_Disable();

/* Define readonly access via MPU */
MPU_AttributesInit.Number = MPU_ATTRIBUTES_NUMBER0;
MPU_AttributesInit.Attributes = MPU_NOT_CACHEABLE;
HAL_MPU_ConfigMemoryAttributes(&MPU_AttributesInit);

MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x08FFF800UL; /* UID ADDRESS and others */
MPU_InitStruct.LimitAddress = 0x08FFFFFFUL;
MPU_InitStruct.AccessPermission = MPU_REGION_ALL_RO;
MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Enable MPU (any access not covered by any enabled region will cause a fault) */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}



なお、マニュアルにもあらかじめMPU使っておけよと匂わせておりますが
こんなん初見で絶対わかりませんよぅ!!!
人にソースコードよく見ろと言っておきながら自分のことは棚に上げて
言うのもアレですがマニュアル相当読み込まないとマジで気づきません。

STM32L5から特に何も考えずスライド移植したら罠にかかって爆死する
パタンがH5では多いので気を付けましょう(経験者バイアス)
それとこうならないようにマニュアルはちゃんと読みましょうorz

20240205追:
STM32H5の地雷踏まないようなMPU設定の仕方が公式で
ようやく公開されています…最初から公表しろ〜〜〜〜!!!!!!

20240205追:




そんなわけでいくつもの罠が待ち受けているSTM32H5ですがこれからも
未知の罠が待ち受けているでしょう。しかしアーリーアダプタな戦士たちは
それに臆せず果敢に進んでいくのです…!!


そして先にも紹介しましたがFatFsのSTM32H5への移植例はおきぱですでに
公開しております
。ちょっと気が早いですが先行して2024年版に更新
しておりますのでヨロシク!!

Go to top of page