Probe 構造体
Probe 構造体は、物理的なプローブをコード上で表したものです。利用可能なプローブを一覧表示するには、Lister 構造体を使用します。
これは、プローブの物理パラメータを設定し、セッションを生成し、さらに SWV トレースやハードリセットなどのプローブ固有の特別な機能を使用するために使われます。
そのため、コアアーキテクチャ固有ではない機能を探しているのであれば、Probe 構造体を確認するのが最も適切です。
ボックス化されたトレイトオブジェクトからプローブを開くことも可能ですが、これは通常ユーザーにとってはあまり有用ではありません。開発者としては、独自のプローブを実装する場合にこれが必要になります。
最善なのは、接続されているプローブを一覧表示し、使いたいものを開くことです。とはいえ、たいていの場合は 1 つしかないでしょう。
// 利用可能なすべてのデバッグプローブの一覧を取得します。let lister = Lister::new();
let probes = lister.list_all();
// 見つかった最初のプローブを使用します。let probe = probes[0].open()?;これで、プローブが提供できるすべての機能にアクセスできます。すべてのプローブが同じ機能を提供するわけではないため、一部の呼び出しは失敗を示す Result を返す場合があります。
// プローブ経由で接続されたターゲットをハードリセットします。probe.target_reset()?;
// デバッグプロトコルを選択します。デフォルトは SWD です。probe.select_protocol(WireProtocol::Swd)?;
// 選択したターゲットにアタッチします。let session = probes[0].attach("nRF52")?;これで、次の作業を進めるための Session の準備ができました。::attach() 呼び出しをもう少し詳しく見てみましょう。チップ名を渡す以外にも、チップを選択するためのさまざまな引数を渡せます。
Session 構造体
Session は、Probe から Chip への確立済みの接続です。 このセッションは、コアの一覧表示やコアへのアタッチに使用できます。 また、ターゲットのプロパティを読み取ることもでき、いくつかの内部処理を支えるためにも使われます。 おそらく、Session を使うのはコアにアタッチするときだけになるでしょう。
/// すべてのコアを一覧表示して出力します。let cores = session.list_cores();println!("{:?}", cores);
/// コアにアタッチします。let core = session.core(0);Core 構造体
Core は、おそらく最も頻繁にやり取りすることになる構造体です。 この Core 構造体を使うと、CPU と、CPU からアクセス可能なメモリを操作できます。
前のセクションでは、コアにアタッチする方法を学びました。 場合によっては、手早くコアの操作にアクセスしたいことがあります。 そのためにあるのが Session::auto_attach() です。 これを使うと、最初に Probe を開かなくても Core にアタッチできます。 接続されているプローブを開こうとし、可能な限り適切に Core を選択します
let session = Session::auto_attach("chip_name")?;let core = session.core(0)?;Core にアタッチすると、任意のタイミングで Core を停止できます。Core::halt() 関数 はコアが停止するまで待機し、その際には許容される最大待機時間を指定する必要があります。
core.halt(Duration::from_ms(100))?;コアが停止しているかどうかを手動で確認することもできます。これは、想定外の状態では halt と run を安全に呼び出せない可能性があるためです。そのため、コアが停止しているかどうかを確認したくなることがあります
let is_halted = core.core_halted()?;CPU を命令単位でシングルステップ実行することもできます
core.step()?;あるいは、そのまま Core を実行させることもできます
core.run()?;もちろん、Core をリセットすることもできます
core.reset()?;リセットを機能させるために、場合によっては実行状態である必要がある点に注意してください。 これはソフトリセットであり、多少の癖や制約が伴うことがあります。 ハードリセットについては Probe 構造体を確認してください。
もちろん、CPU レジスタを操作することもできます
let reg = core.read_core_reg(0x00)?;core.read_core_reg(0x00, reg | 0x42)?;ハードウェアブレークポイントも使用できます
// たいていの場合、ブレークポイントを設定したくなるでしょう。core.set_hw_breakpoint(address)?;
// もちろん、ブレークポイントを解除することもできます。core.clear_hw_breakpoint(address)?;もちろん、CPU だけを操作できても十分ではありません。そのため、CPU から物理的にアクセス可能なメモリにアクセスすることもできます。
// レジスタを読むのに便利なように、単一のワードを読み取れます。let value = core.read_word_32(address)?;
// Flash の内容を読む場合は、たいていブロックメモリアクセスを使いたくなるでしょう。let mut buffer = [0; 1337];core.read_32(address, &mut buffer)?;
// 読み出すだけでは物足りないので、データを書き込むこともできます。let value = 42;core.write_word_32(address, value)?;
// そして、こちらもブロックアクセスです。let buffer = [0; 42];core.write_32(address, &buffer)?;probe-rs は大きなメモリ要求に対してバッチ処理を行い、最大速度になるよう最適化するはずです。