SNSへはこちら

Atmel SAMでLチカ(SysTick)

前回のクロック設定に引き続き、ひとまずマイコンの登竜門、Lチカをしていきましょう。

...とはいっても、このマイコンは ARM なので、サクッと終わってしまいます。

SysTickタイマの設定

毎度おなじみ、SysTick です。ここでは割り込みを入れずにカウントしたいと思います。早速ですが、1msec ウェイトをするプログラムを示します。

// CPU clock is divided by 1
void ms_wait(uint16_t msec) {
    SysTick->LOAD = 48e6 / 1e3 - 1;
    SysTick->VAL = 0;
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
    for(uint16_t i=0; i<msec; i++) {
        while( !(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) );
    }
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
}

どうやら SysTick のクロックは CPU からの分周無しで接続されているようです。よって、1msec タイマーとするために 1000(1e3)で割っておきました。

レジスタの打ち方

ちょっと一癖あります。普通のマイコン通り、構造体ポインタを使えば良いのですが、ちょっと独特です。
例えば PM というクロック供給関連のペリフェラルにある APBCSEL レジスタにアクセスしたい時は PM->APBCSEL.reg.reg が必要です。これはルネサス系マイコンの .BYTE.WORD に対応するものです。更に、レジスタのビットに直接アクセスしたい時は PM->APBCSEL.bit.APBCDIVというふうに .bit をつければいいです。これもルネサス系マイコンでは .BIT で表現されますね。

これとは別に、同じペリフェラルでも動作モードの違いを書く必要があるというクセがあります。例えばシリアル通信をするペリフェラルの1つである SERCOM0です。SPI 通信で使う時は SERCOM0->SPI.BAUD.reg というように SPI を記述し、I2C で使う時は SERCOM0->I2CM.BAUD.reg と記述します。
他にも、タイマーである TC でも、「TC3 の 16bit カウント動作時の CTRLA レジスタ」は TC3->COUNT16.CTRLA.reg となります。げえぇっ。

更に更に、今回使う PORT にもクセがあります。IO ポートには PAx や PBx がありますが、まずここで PAx を Group[0] として見ます。同じように PBx は Group[1] です。この時に DIR レジスタにアクセスしたいなぁとなった時は PORT->Group[0].DIR.reg になります。う〜〜ん、分かりづらい。
他にも、PORT でピンのマルチプレクシング設定やプルアップの設定を行うレジスタ(PINCFG)は各ポートごとに独立したレジスタになっていますから、PORT->Group[0].PINCFG[9].reg と書く必要があったり...結構大変です。

今回は Lチカ だけなので設定自体はだいぶ楽です。

PORT

いわゆる GPIO です。他のマイコン(STM32 とか)ではこのペリフェラルに対してクロック供給をすることが必要でしたが。このマイコンではデフォルトでオンのため、設定が不要です。ですのでいきなりポート設定に入ってしまいます。

今回は PA15 (24番pin) でチカチカさせたいと思います。

入出力方向

LED をチカチカさせるためには OUTPUT とする必要があります。データシートを見ながらそのコードを書いてみると以下のようになるでしょう。

PORT->Group[0].DIR.reg |= (1 << 15); // output

もちろんこれで良いです。ただ、データシートをよく見ると SET 用、 CLEAR 用のレジスタがわざわざ用意されているので、

PORT->Group[0].DIRSET.reg = (1 << 15); // output

としたほうが簡単っちゃ簡単です。

データ出力も同様で、High を出すために

PORT->Group[0].OUT.reg |= (1 << 15);

としても

PORT->Group[0].OUTSET.reg = (1 << 15);

としてもいいです。なお、この SET 用レジスタは PORT のみにあるようです。

さらに、今回は LED をチカチカするので 1秒ごとに出力を反転させたいです。そのためにうってつけのレジスタがあって、OUTTGL(Output Toggle) です。これを使えばスマートにかけますね。

そんな訳で、Lチカのプログラムを以下に示します。sysclk_init は前回の記事を参考にしてください。