AT SAMの部屋(11) XiaoでもGo!GCLK、全ジェネレータの使用状況

Joseph Halfmoon

Go言語でMCU向けのオブジェクトを生成できるTinyGoを使って Arm Cortex-M0+コア搭載、Microchip社ATSAMD21マイコンの周辺回路を探っております。前回は各クロック分配の様子を前々回はオシレータの設定を確かめました。今回はその2つの間クロックジェネレータGCLKを見てまいりとうございます。

※「AT SAMの部屋」 投稿順indexはこちら

※以下実験はMicrochip社のATSAMD21G18マイコンを搭載したSeeduino Xiaoボードで行っています。使用している tinygo のバージョンは以下です。

tinygo version 0.23.0 windows/amd64 (using go version go1.18.1 and LLVM version 14.0.0)
オシレータとGCLKの関係(復習)

今回TinyGoを使ってやっていることは、前回の「以下同文」な処理です。以下同文にしなかったのは、ATSAMDマイコンを制御する上では避けて通れない部分のためです。整理するとこんな感じ

    1. 内蔵、外付けの発振器はSYSCTRLにより制御されている(前々回
    2. 上記の発振器もしくは外部からのクロック入力はGCLK内に9本あるクロックジェネレータに入力される。(今回)
    3. クロックジェネレータの出力クロックは、GCLK.CLKCTRLレジスタの設定により各ペリフェラルに分配される(前回

今回の設定を読むとようやく、どのような素性のクロックがどこへ配られているのかそのルートが明らかになる、と。

実験に使用したGo言語ソース

実験に使用したGo言語ソースは前回CLKCTRL用に作製したものの「チョイ」直しです。前回、変則的なレジスタの読み出しを行ったので、それをそのまま踏襲しています。一点問題は、今回アクセスするGCLK.GENCTRLというレジスタは

Write-Synchronized

なレジスタであることです。書き込んだ場合には処理に一定時間かかるので、別に用意されているSYNCBUSYビットが落ちるまで待たねばなりません。ただ今回は、設定値を書き換えているわけでなく、読み出しのためにIDを部分書き込みしているだけです。そこで「待たずに」読み出してみました。動いているようです。たまたまなのかも知れないので、本来的にはSYNCBUSYビットを見た方が安全かもしれません。

package main

import (
    "fmt"
    "time"
    "runtime/volatile"
    "unsafe"
)

func dumpGENCTRL(id uint8) {
    GENCTRL_DIR8  := (*uint8)(unsafe.Pointer(uintptr(0x40000c04)))
    GENCTRL_DIR32 := (*uint32)(unsafe.Pointer(uintptr(0x40000c04)))
    volatile.StoreUint8(GENCTRL_DIR8, id)
    work := volatile.LoadUint32(GENCTRL_DIR32)
    fmt.Printf("ID=%d ", (work & 0xF))
    fmt.Printf("SRC=%d ", (work & 0x1F00)>>8)
    fmt.Printf("GENEN=%d ", (work & 0x10000)>>16)
    fmt.Printf("DIVSEL=%d\n", (work & 0x100000)>>20)
}

func main() {
    for {
        for id := 0; id < 9; id++ {
            dumpGENCTRL(uint8(id))
        }
        fmt.Println("-------------------------------")
        time.Sleep(5 * time.Second)
    }
}
実機上での結果

以下に実機上で動作させたときのUSBシリアル出力をTeratermで眺めたものを示します。

ID=0 SRC=7 GENEN=1 DIVSEL=0
ID=1 SRC=4 GENEN=1 DIVSEL=0
ID=2 SRC=4 GENEN=1 DIVSEL=0
ID=3 SRC=6 GENEN=1 DIVSEL=0
ID=4 SRC=0 GENEN=0 DIVSEL=0
ID=5 SRC=0 GENEN=0 DIVSEL=0
ID=6 SRC=0 GENEN=0 DIVSEL=0
ID=7 SRC=0 GENEN=0 DIVSEL=0
ID=8 SRC=0 GENEN=0 DIVSEL=0

上記を「解読」したテーブルを以下に掲げます。

Generator ID Source Enable
0 DFLL48M Enable
1 OSC32K Enable
2 OSC32K Enable
3 OSC8M Enable
4 XOSC Disable
5 XOSC Disable
6 XOSC Disable
7 XOSC Disable
8 XOSC Disable

つまり、TinyGoのSeeeduino Xaioのデフォルト設定のスタート状態では、

    • 9本あるジェネレータのうち使っているのは4本だけ
    • 残り5本はXOSC設定になっている(XiaoではXOSCに発振子は接続されていないので使っていない時の設定と思われる。勿論XOSCを他の発振源に変更するのは可能)

他のモジュールを呼び出した場合は「新たに使ってないよね」確認が必要だとは思いますが、余っているらしい5本を自分で書く機能で使ってしまうのはアリでしょう。ねらい目は4番5番ですかね。小型ボードで端子が少ないSeeeduino Xiaoですが、4番5番に対応する端子は外に出てるような気がします。これを使えば外部クロックの入出力も可能かも。知らんけど。やってみろよ、自分。

AT SAMの部屋(10) XiaoでもGo!GCLK.CLKCTRLレジスタを全ダンプ へ戻る

AT SAMの部屋(12) XiaoでもGo!内蔵OSCクロックをポート出力して周波数測定 へ進む