皆さん こんにちは。
ポンコツRustacean の moon です。
この記事は開発環境を構築することを前提にしています。
環境構築について知りたい方は こちらの記事 をご覧になってください。
このサイトは 書籍 基礎から学ぶ組込みRust を参考にしています。
今回は軽い記事ですから、さっと読むことができます。
ディレイ
今回はディレイ(遅延・待ち)の関数をつくってみます。
Delay 構造体を使って delay するのが一般的ですが、このオブジェクトを2つ作ることはできないようです。
良く以下のコードを見かけますが、 new() で core.SYST を消費してしまうため new() は一度しか使えないようです。
let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz());
また、次のように インスタンス.メソッド() のような記述が必要で、使う側の関数(メソッド)の引数にインスタンスを渡す必要があり「ちょっと、かったるい」です。
delay.delay_ms(100)
そこで単に関数を呼び出せば遅延できるようにしました。
以下のコードはHALの中身を少し改造したものです。
unsafe でポインタを使って64ビットカウンタの下位32ビットのレジスタを読んでいます。
この読み出し自体は他に影響を与えないので排他制御は不要です。
この32ビットカウンタは1マイクロ秒に一度カウントアップするため約71分でオーバーフローします。
たまたまオーバーフローする瞬間に使っても、wrapping_sub()が桁上げ分をカバーしてくれるので、msecやμsecオーダーの時間待ちをする分には全く問題なく使えます。
手軽に時間待ちが必要な場面で、ぜひ使ってみてください。
use rp_pico::hal::pac;
pub fn delay_us(mut us: u32) {
let mut start = get_counter_low();
loop {
let now = get_counter_low();
let waited = now.wrapping_sub(start);
if waited >= us {
break;
}
start = now;
us -= waited;
}
}
pub fn delay_ms(ms: u32) {
for _ in 0..ms {
delay_us(1000);
}
}
pub fn get_counter_low() -> u32 {
unsafe { &*pac::TIMER::PTR }.timerawl().read().bits()
}
GitHubにアップするまでもないので、必要ならこれをコピペして試してみてください。
お疲れさまでした。