« F1みたいなロボット競技 | トップページ | ボーダーライン »

2019年1月 5日 (土)

MPU(メモリ保護ユニット)続き

stm32で、Cortex-MのMPUを使って、スタックオーバーフローを
検出する方法について。

armの提供するドキュメントを参照すると、Cortex-Mコアに存在する
(チップベンダ依存だけど)MPUを使うと、最小32バイト単位のエリアを
アクセス禁止エリアに設定できるとある。

これを使って、スタティックエリアの最後か、想定するスタックの上限に
アクセス禁止エリアを作った上で、
MPUのメモリ管理ハンドラへの割り込みを許可する。

これで、アクセス禁止エリアへのアクセスを、ソフトウエアで処理できる。

ペリフェラルの初期設定は、

    SCB->SHCSR = (1 << 16);       //メモリフォルト許可
                                                  (許可しないとハードフォルトとして処理される)
    MPU->RBAR = 0x20002010;     //保護エリア先頭アドレス+イネーブルビット
    MPU->RASR =                      //保護エリアアトリビュート指定(サイズなど)
         (0 << 24) |
        (4 <<  1) |
        (1 <<  0) |
        0;
    MPU->CTRL =       //メモリ管理イベント許可
        (1 << 2) |
        (1 << 1) |
        (1 << 0) |
        0;

で、アドレス0x20002000から、32バイトが
アクセス禁止エリアとして指定される。

このエリアを読み書きすると、メモリ保護違反イベントが発生して
ベクタテーブルのオフセット0x10にある
アドレスに分岐するので、こちらもハンドラを記述する。

void MemManage_Handler(void){

    __ASM volatile ("bl    main");       

}

CFSRの当該ビットをクリアできれば、元の処理に戻れそうな
気がするんだけど、なぜかクリアできない...
ので、仕方なく、無条件ジャンプで、main()へ戻っている。


このコードでは、普通の変数初期化が実行されないので、
通常リセットとの区別は簡単に付けられる。

(適当なスタティック変数をメモリ保護エラーフラグにしておいて、
起動直後に参照する。

色々なサンプルコードを当たると、ハードフォルトや
今回のようなメモリ保護違反での例外処理時は、
元の処理に復帰せず、ブレークポイントを設定して、
whike(1)の無限ループで停止する例ばかり出てくる。

まあ、スタックオーバーフローしているような状況で
処理を戻して如何にする?のも確かだ。

これで、まあなんとか、ソフトウエアのオーバーヘッド
無しで、スタックオーバーフローを検出できるようには
なったようだ。

------

MPUでなくて、DWTを使えば、もっとうまく実装できそうなんだけど、
こっちはなんだかうまく行かない。

色々ドキュメントを当たっているんだけど、
コア部分なので、チップベンダの資料にはほとんど記述が無い。

そもそもarmのドキュメントは、なかなか不親切だ(日本文も英文も)

まあ、実装するかどうはチップベンダ依存なので、
armのドキュメントがそっけないのも分かるけど、
もうちょっと何とかならないかなあ。

検索しても、あんまりいい情報にめくり合わない。
質問は色々ヒットするんだけど、ロクな回答がない。

------

まあ、チップベンダはコアのペリフェラルを手厚くサポートしても
得るもの少ないだろうし、需要はマルチプラットフォームの
デバッガなんかを開発しているベンダーくらいかなあ。

あんまり深追いしても、アレな気がしてきては居るんだけど、
DWTなんかは面白そうな機能が用意されているようだし、
stm32のCortex-M4は、コアのペリフェラルも
結構実装されているようなので、使いこなしたい気もしている。

|

« F1みたいなロボット競技 | トップページ | ボーダーライン »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: MPU(メモリ保護ユニット)続き:

« F1みたいなロボット競技 | トップページ | ボーダーライン »