Pico三昧(57) ラズパイPico2:RP2350、RISC-V プラットフォームタイマ

Joseph Halfmoon

前回はHWスピンロックを試用。処理系が「時々」使うことがあるらしい機能を勝手に直接利用して前回はタマタマ動作しましたが、その後、案の定マズイ場合にも遭遇。そゆときは番号変えると動くかも。さて今回はRISC-Vのプラットフォームタイマを読み出してみます。RISC-VといいつつRP2350ではArmコアでも読めるみたい。

※Pico関係投稿一覧は こちら 『Pico三昧』は一覧の末尾付近にひっそりと。

※Pico2対応のMicroPython処理系(バイナリ、uf2形式)は以下のURLからダウンロード可能です。

https://micropython.org/download/RPI_PICO2/

※動作確認に使用しているMicroPython処理系は以下です。

MicroPython-1.24.0-riscv–with-newlib4.3.0

上記はRISC-Vコア用のバイナリですが、Arm用でも同様に動くかと(確かめてないケド。)

RISC-Vプラットフォームタイマ

RISC-Vプラットフォームタイマは64ビットの長周期のタイマです。システムに唯一無二の時間の基準を与えるためだと思われますが、RISC-V搭載のシステムで必要とされているハードウエアのようです。ラズパイPico2搭載のRP2350においては、コアがRISC-Vの時だけでなく、Armを選択していてもこのタイマは利用可能となってるみたい。

唯一無二ということでコア0とコア1の間に1個だけ存在し、どちらからも読み出し可能。万が一タイミングがぶつかった場合は良きに計らってくれるみたい。また、セキュア、ノンセキュアの区別なく唯一無二。

今回試してみたところでは、ノンセキュアで走っているMicroPython(RISC-V)上から、セキュア側のアドレス使って読み取ることができてます。

今回実験のMicroPythonコード

前回実験のHWスピンロックを使ったコードが危ない(条件不明だがHWスピンロックの0番が処理系に使われていることがあるみたい)ことを経験したので、コンサバに_Threadモジュール内のlockを使用して実験してます。

import time, machine, _thread
from micropython import const

SIO_BASE = const(0xd0000000)
SIO_NONSEC_BASE = const(0xd0020000)
MTIME = const(0x1b0)
MTIMEH = const(0x1b4)

def taskA():
    global lock
    cnt = 0
    while cnt < 3:
        lockP = lock.acquire(1, -1) #wait lock forever
        if not lockP:
            print("Task A can not get the lock.")
            return
        rvth = 1
        while rvth != machine.mem32[SIO_BASE + MTIMEH]:
            rvth = machine.mem32[SIO_BASE + MTIMEH]
            rvtl = machine.mem32[SIO_BASE + MTIME]
        print("Task A RISC-V platform timer: {0:08x}{1:08x}".format(rvth, rvtl))
        lock.release()
        time.sleep(0.5)
        cnt += 1
    _thread.exit()

def taskB():
    global lock
    cnt = 0
    while cnt < 5:
        lockP = lock.acquire(1, -1) #wait lock forever
        if not lockP:
            print("Task B can not get the lock.")
            return
        rvth = 1
        while rvth != machine.mem32[SIO_BASE + MTIMEH]:
            rvth = machine.mem32[SIO_BASE + MTIMEH]
            rvtl = machine.mem32[SIO_BASE + MTIME]
        print("Task B RISC-V platform timer: {0:08x}{1:08x}".format(rvth, rvtl))
        lock.release()
        time.sleep(0.5)
        cnt += 1

def main():
    global lock
    lock = _thread.allocate_lock()
    print("RISC-V platform timer test:")
    _thread.start_new_thread(taskA, ())
    taskB()

if __name__ == "__main__":
    main()

異なるコアで実行されている2つのTaskから、RISC-Vプラットフォームタイマを読み出してその値を表示してます。実体は同じタイマであるので、どちらから読んでも順番通りに段々大きな数になっていく筈。

実機実験結果

上記のソースをPico2上で走らせた様子が以下に。RVptimerRead

まあ順番通りのようだね。

Pico三昧(56) ラズパイPico2:RP2350、HWスピンロックの試用 へ戻る

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です