AT SAMの部屋(13) XiaoでもGo!XOSC32K、32Kクリスタルの発振ON

Joseph Halfmoon

前回ATSAMD21G18の内蔵OSCの出力を空いているクロックジェネレータを経由して外部端子に出力してみました。そのとき気になったのは「Xiaoボード、外付け32Kの振動子積んでたよね、使ってないの?」という件。今回はお休みしていたらしいXTALに活を入れて起動し、前回同様の方法で周波数を確認してみます。使えるの?

Go言語ソースをマイコン上でも使えるようにできるTinyGoを使わせていただいてSeeduino Xiaoボード上で自主トレ中です。

ここまでの調査結果をまとめると、Seeduino Xiaoボード上でTinyGoを使って生成したオブジェクトを走らせた場合、デフォルトでは内蔵OSCが生成するクロックばかり使われているようでした。内蔵の32Kオシレータの生成するクロックを測ってみると精度はイマイチ?(イマ2くらい?)

Xiaoボードの実装面はメタルの蓋が被っているので直接見ることができないのですが、回路図を見る限り外付けの32.768kHzの発振子も接続されております。ハードウエアが存在するのであれば使わない手はないというビンボー根性にて今回は外付け32Kを起動してみました。

※32kHzクロックとそのRTCでの歩度調整機能については第15回ご参照ください。(2022/06/07 追記)

Xiaoボードの回路図

Xiaoボードの回路図は以下のサイト(日本語)の下の方にリンクがあり、ダウンロード可能です。

Seeduino Xiaoをはじめよう

今回使用するXTAL(と思われるデバイス。直接見てません)部分の回路図を引用させていただきます。こんな感じ。

XOSC32SCH

実験に使用中のXiaoボードの周辺

第8回で作成したブレッドボードの回路をそのまま実験に使っております。前回説明しましたとおりMicrochip社ATSAMD21G18のクロックジェネレータ出力は、設定によっては外部出力ができます。今回は発振させたXOSC32Kの出力をクロックジェネレータ5番に接続、そして PA11_A3_D3端子から外部に出力させます。外部には外付けのLEDが取り付けられてますが周波数を測る分には問題ない、と。xiao23LC512_Schematic

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

実験に使用したソースが以下に。XOSC32を発振させて外部出力するだけでは「寂しい」ので、おとなりの赤色LEDには自主的にLチカしていただき、また、main()関数にも無駄に標準出力に値を垂れ流してもらっています。

※2022/06/03 FIX

package main

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

func enableXOSC32() {
    XOSC32K := (*uint16)(unsafe.Pointer(uintptr(0x40000814)))
    // NO WRTLOCK, STARTUP 1sec(0x5), AAMPEN, EN32K, XTALEN=1(XTAL), ENABLE=1
    volatile.StoreUint16(XOSC32K, 0x052E)
    time.Sleep(time.Millisecond * 1200)
}

func setGGEN5out(src uint32) {
    PMUX8  := (*uint8)(unsafe.Pointer(uintptr(0x41004435)))
    PCFG8  := (*uint8)(unsafe.Pointer(uintptr(0x4100444B)))
    PDIR32 := (*uint32)(unsafe.Pointer(uintptr(0x41004408)))
    GGENSTATUS8 := (*uint8)(unsafe.Pointer(uintptr(0x40000c01)))
    GENCTRL32   := (*uint32)(unsafe.Pointer(uintptr(0x40000c04)))
    GENDIV32    := (*uint32)(unsafe.Pointer(uintptr(0x40000c08)))
    //set PA11 Function H(7)
    tmp8 := volatile.LoadUint8(PMUX8)
    volatile.StoreUint8(PMUX8, (tmp8 & 0x0F) | 0x70)
    //set PMUXEN, clear other bits
    volatile.StoreUint8(PCFG8, 0x01)
    //set PA11 OUTPUT
    tmp32 := volatile.LoadUint32(PDIR32)
    volatile.StoreUint32(PDIR32, tmp32 | 0x00000800)
    //set GEN5 DIV=0
    volatile.StoreUint32(GENDIV32, 0x00000005)
    //set GEN4 GENCTRL
    tmp32 = 0x00090005 | ((src & 0x1F) << 8)
    volatile.StoreUint32(GENCTRL32, tmp32)
    for {
        if (volatile.LoadUint8(GGENSTATUS8) & 0x80) == 0 {
            break
        }
    }
}

func blinkRedLED() {
    led := machine.D2
    led.Configure(machine.PinConfig{Mode: machine.PinOutput})
    for {
        led.Low()
        time.Sleep(time.Millisecond * 500)
        led.High()
        time.Sleep(time.Millisecond * 500)
    }
}

func main() {
    var counter int = 0
    enableXOSC32()
    setGGEN5out(5) //SRC=0x05 XOSC32K
    go blinkRedLED()
    for {
        counter++
        fmt.Println(counter)
        time.Sleep(5 * time.Second)
    }
}
実験結果

XiaoボードのD3端子(PA11_A3_D3)を観察したものが以下に。測定につかっているDigilent Analog Discovery2の精度もありますが、32.775kHz。微妙な数字ですな。前回の内蔵OSC32Kよりは一桁くらい精度がよくなってますが、本当にこの数字であるとRTC(実時間時計)に使うと結構残念な結果になりそうです。まあね、この頃のIoTデバイスだとNTPで補正するからみたいな運用もありかもしれないけれども。

WaveFormXOSC32

そんなこんなで外付け発振子、わざわざ動かすこともないってこと?ホントか?

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

AT SAMの部屋(14) XiaoでもGo! machine.TCC1使用、PWM出力 へ進む