SNSへはこちら

RAマイコンを試食(5) - クロック設定

このマイコンの特徴を記事にしていきます。まずはクロック。この設定、なんか PIC っぽくね?と思ったのは僕だけでしょうか。
...つまり、不揮発性レジスタに予め値を書き込んでおき、マイコン起動時に自動的にそれが参照されるという仕組みなんです。

オプションレジスタ

その不揮発性っていうのがオプションレジスタなんですが、これ、この間話した Flash 領域中に唐突に現れるアイツなんですよ。
ちょっとユーザーマニュアル読んでみましょうか。

所々に HOCO という文字列が見えますが、これが内蔵高速クロックです。これをオンにするというわけですねえ。
クロック周波数が選べますが、このマイコンの最高クロック周波数は 48MHz なので、48 としておきましょう。ついでに HOCO の自動発振も有効化。

すると OFS1 の設定値は 0xFFFFCEFF になります。後はこれをメインクロックとして使用するようにコードを書くだけです。

クロック構成

そもそも、HOCO を使っていない場合は何のクロックで動いているのでしょうか??ここで全部話すと面倒くさいので、一部抜粋します。

なお、クロック源を変えたとしても、分周比を未設定の場合は常に 16分周 となっています。ですのでこれも変更する必要があるってことです。

MOCO

その名も「中速オンチップオシレータ」です。周波数は 8MHz。これがデフォルトのメインクロックです。
直前で述べた分周比を適用すると、RA マイコンは何も設定していない場合、500kHz で動作しているということになりますね。おっそい。分周を 1 とすれば 8MHz になります。

STM32 とかだと「PLL に繋いで〜」とかなりますが、このマイコンには PLL はありません。まあ HOCO の内部にあるかもしれないですがね...

HOCO

「高速オンチップオシレータ」です。上のデータシートのキャプチャで示したとおり、複数発振周波数を選べます。

LOCO

「低速オンチップオシレータ」です。32.768kHz。RTC 等に使われるのがメインですが、RA マイコンでは SysTick タイマーのクロック源となっています。
僕みたいに SysTick タイマーを ms_wait 関数として使っている人からしたら、この周波数嫌ですよねぇ...でもその回避方法があるので記事最後に述べます

メインクロックの設定方法

設定方法はユーザーマニュアルにあります。それ従えば良いのですが、HOCO を用いる方法は記載されていないので具体的に記載しておきます。また、ライトプロテクションを外す必要があることに注意。

// 何も設定しないとデフォルトで 8MHzのMOCOを使用, システムクロック及び周辺モジュールクロックは16分周設定 ==> SysTickでCLKSOURCEを立てると0.5MHzで動作する
// HOCOを使うためには、SYSTEM, Flash以外にOPT1の設定が必要。

// 48MHz
void sysclk_init(void) {
    SYSTEM.PRCR.HWORD = 0xA501; // Write Enabled
    SYSTEM.SCKDIVCR.WORD = 0; // No prescaling
    SYSTEM.MEMWAIT.BIT.MEMWAIT = 1; // Set for High-spped mode

    while( !SYSTEM.OSCSF.BIT.HOCOSF ); // HOCO is ready?
    SYSTEM.SCKSCR.BIT.CKSEL = 0; // HOCO On

    FCACHE.FCACHEIV.BIT.FCACHEIV = 1; // Flash Cache Settings
    while( FCACHE.FCACHEIV.BIT.FCACHEIV );
    FCACHE.FCACHEE.BIT.FCACHEEN = 1;
    SYSTEM.PRCR.HWORD = 0xA500; // Write Disabled
}

SysTickクロックを高速にしたい!

僕は SysTick タイマーをある程度正確なディレイタイマーとして使っているのですが、Tick イベントを 1msec ごとに起こしたいんですよね。デフォルトの低速クロックを用いることで省電力化ができるんですが、如何せん切りが悪いんですよ。

そこで、SysTick タイマーのクロックを切り替えます。実は、CTRL レジスタの CLKSOURCE ビットを立てることで CPU クロックを使えるようになります
ですので、僕は以下のように設定しました。

void ms_wait(uint16_t msec) {
    SysTick->LOAD = 48000 - 1;
    SysTick->VAL = 0;
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk;
    for(uint16_t i=0; i<msec; i++) {
        while( !(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) );
    }
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}

この CLKSOURCE ビットはどのマイコンでも共通の仕様です。

これで使いやすいようにクロックの設定が完了しましたね。タイマーとか色々お楽しみください。