ラズピコ クロックについて浅く掘る

ラズピコ クロックについて浅く掘る

皆さん こんにちは。

そう言えばラズピコのクロックについて全く理解していないなぁと思い、少々かじってみることにしました。

RP2040のクロック系統図

ラズピコのマイコン RP2040 のクロック系統図を以下に示します。

ラズピコには 12MHz の水晶振動子が実装されていて、これをPLLで逓倍して、125MHz のシステムクロックを生成しています。
USB向けには 48MHz のクロックが生成されます。

図の右側にペリフェラルがあります。

例えば ADC には clk_adc 、USB には clk_usb と書かれていてペリフェラルのクロックソースが区別されています。

これらがラズピコではどのくらいの周波数に設定されているのか見てみましょう。

せっかくですからコードを書いて確認してみることにします。

プロジェクトの作成

以下の設定でプロジェクトを作成します。

Project Name: picoClocks
Library Options の HW clocks をチェックする
Console Options の Console over UART をチェックする
IDE Options の Create VSCode project をチェックする
Debugger: は PicoProbe を選択する

VSCodeを起動する

起動後、何かファイルが開いてたら File – Close Folder で閉じた後、File – Open Folder から picoI2c のフォルダーを辿って選択します。

こちらの環境では C:\Users\m3925\Documents\Pico\pico-project-generator\picoI2c です。

m3925の部分は皆さんのユーザー名に置き換えてください。

vscode関連の json ファイルは前回作成済のプロジェクトのものをドラッグ&ドロップでコピー&ペーストすると楽です。

ソースコードを書く

picoClocks.c を以下の通りに編集します。

#include <stdio.h>

#include "hardware/clocks.h"
#include "pico/stdlib.h"

#define CLOCK_ITEMS 11

int main() {
    char clk_str[CLOCK_ITEMS][20] = {"clk gpout0", "clk gpout1", "clk gpout2",
                                     "clk gpout3", "clk ref",    "clk sys",
                                     "clk peri",   "clk usb",    "clk adc",
                                     "clk rtc",    "clk count"};
    uint32_t clocks[CLOCK_ITEMS] = {0};

    stdio_init_all();
    puts("Hello, Clocks!");

    for (int i = 0; i < CLOCK_ITEMS; i++) {
        clocks[i] = clock_get_hz((enum clock_index)i);
        printf("%s = %dMHz\n", &clk_str[i][0], clocks[i] / 1000000);
    }

    return 0;
}

PC側の準備

I2C通信の動作確認用として Tera Term を使います。
API関数がうまく動作したか否かなどの結果をUARTのputs()やprintf()でログ出力するようにしてみました。

Tera Termをお持ちでない方は こちら からダウンロードしてお使いください。

インストール後、 Tera Term を起動し、シリアルポートでPicoprobeのCOMポートを選択します。

もしCOMポートが複数ある場合には、Picoprobe以外の通信ケーブルをはずしてデバイスマネージャーでCOMポート番号を確認しておきます。

起動後、設定メニューのシリアルポートから以下の設定を行います。

スピート : 115200
データ : 8 bit
パリティ : なし
ストップビット : 1
フロー制御 : none

(設定値からスピードだけ変更すれば良いはずです)

コードの説明

下調べをしてわかったことなのですが、stdio_init_all()の中で clocks_init()という関数が呼ばれ、各ペリフェラル等のクロックソースが設定されます。

構造体の定義のヘッダで以下のように enum 定義されていて、clock_get_hz()関数で これらを読み出してクロックの設定値を確認することができました。


enum clock_index {
    clk_gpout0 = 0,     ///< GPIO Muxing 0
    clk_gpout1,         ///< GPIO Muxing 1
    clk_gpout2,         ///< GPIO Muxing 2
    clk_gpout3,         ///< GPIO Muxing 3
    clk_ref,            ///< Watchdog and timers reference clock
    clk_sys,            ///< Processors, bus fabric, memory, memory mapped registers
    clk_peri,           ///< Peripheral clock for UART and SPI
    clk_usb,            ///< USB clock
    clk_adc,            ///< ADC clock
    clk_rtc,            ///< Real time clock
    CLK_COUNT
};

ただ、 clk_gpout0 ~ 3 が何に使われるものなのか良くわかりませんでした。

clock_get_hz()

第1引数:enum定義された clock_index を指定します。
戻り値:その要素の周波数[Hz]

動作させてみる

それでは F5キーを押してプログラムを動作させてみます。
Tera Term に読み込んだクロックが表示されれば成功です。
成功した様子の画像を貼っておきます。

皆さんは クロックの確認ができましたか。
お疲れさまでした。

Clocksカテゴリの最新記事