Closed elfmimi closed 2 years ago
追記:
SWD の RESCUE_DP によってリセットをかけると SIO および SPINLOCK の部分もリセットされます。 あるいは、AP 経由で SPINLOCK にアクセスして強制的に開放することでもスタックを回避できます。
とりあえず対処療法いれてしまうことにしましょうか。 rust-dap-rp2040
のutilあたりに実装しておいて、各ボードの init
の先頭で呼ぶのでいいかな。
プルリクを用意しますね。
よろしくお願いします!
非常にややこしい話なのです。 実際には cortex-m-rtic の問題のような気もします。 あるいは、ブートコードが面倒を見てくれてもいい気がします。
RP2040 の場合、
#[cortex_m_rt::entry]
ではなく#[rp2040_hal::entry]
あるいは 同じ意味ですが#[rp_pico::hal::entry]
を使うことが提案されています。何が違うかというと、 critical_section のための SPINLOCK の初期化(=強制的な開放) を行うようになっていることです。
cortex-m-rtic を使うと、 entry マクロの代わりに app マクロを使うことになるので、SPINLOCK の初期化が行われません。
現在の rust-dap の実装では、 critical_section を利用していないように思いますが、 cortex-m-rtic は、デフォルトで cs: bare_metal::CriticalSection というメンバを init::Context に含んでいるようです。
何故これを気にしているかというと、 defmt-rtt が critical_section を利用しているためです。
デバッグに便利なので defmt-rtt を rust-dap に組み込んで開発に使っているのですが、 稀に何も出力されずにスタックしてしまう事があります。その原因が SPINLOCK の未初期化であることが分かっています。
RP2040 は、SYSRESETREQ をしても SPINLOCK の部分は、ハードウェア的にリセットがかからないということも分かっています。
対処療法としては、 rust-dap の init() の先頭に、以下の部分のコピペを挿入する方法があります。 https://github.com/rp-rs/rp-hal/blob/83b990ee30ec970adf0de68eff0cde4cae69db6c/rp2040-hal-macros/src/lib.rs#L19-L24
※ SPINLOCK31 が critical_section 用として使われている様子です。