前回の続編です。今日の内容はすべて GitHub リポジトリに上げていますのでご自由にお使いください。
ちょっと進化した
前回ので十分にLチカ、その他楽しめると思うんですが、実際に書かれた方はわかると思います。ウザい書き方があるんですよね。
GPIOA.MODER = GPIOA.MODER or (1 shl 0)
これです。普通C言語だったら GPIOA.MODER |= (1 << 0);
ってサクッと書けますよね。これじゃあ長ったらしいです。
かと言って Nim 標準のモジュールでこういう感じのないのかというと、まああるっぽいんですが所望のものとは違っていて、しかもテンプレートではなくプロシージャなので組み込みにはなぁ...ということで見送りました。ええ、自作しましたとも。
てなわけで、ビットを立てる、ビットが立っているか確認する、等々のテンプレートを作りました。一部のみの抜粋です。
template bit*[T: SomeInteger](n: varargs[T]): T =
var ret: T = 0;
for i in n:
ret = ret or (1 shl i)
ret
template bset*[T, U: SomeInteger](reg: T, n :varargs[U]) =
reg.st reg.ld or cast[T](bit(n))
template bitIsSet*[T, U: SomeInteger](reg: T, n: U): bool =
(reg.ld and cast[T](bit(n))) != 0
う〜〜んマーベラス。それでこれがどうマーベラスかというと、例えば次の16ビットめがクリアされている間に待つという処理。
while SysTick.CTRL.bitIsClr(16): discard
ほら、いいでしょう?英語に書いてみますよ。
While SysTick.CTRL bit is clear, which is 16, discard.
文になっているというのがお分かりいただけると思います。美しい。日本語しても思いますが、
SysTick.CTRL において 16ビットめがクリアされている間、処理を捨てよ
というわけです。こんな感じでテンプレートをいくつか書き加えました。
スタートアップルーチン
また、これまでアセンブリに頼っていた(というか IDE のものをそのまま引っ張ってきただけのでライセンス的に怪しい)のですが、Nim でフルスクラッチで書くことにより自己満足感を得ることが出来ました。ただ、以下の理由でベクタテーブルは出来ていません。
- ベクタテーブル自体は作れる。
- 初期値を指定すればグローバルスコープで値が代入された状態でコンパイルされる。
- しかし、何故かプロシージャのポインタを入れた瞬間にC言語の関数内で代入される仕様に変わってしまう
ということで完全には無理ですが、ここは Nim 側の後々のアップデートに期待するとしましょう。
割り込みできた
できました。{.exportc.}
プラグマを付けると良いということです。これは Nim のプロシージャをC言語で使うための名前指定方法で、ARMの場合プロシージャ名の後ろに変なハッシュ文字列を付けずにそのままCのコードを吐くということになってるので(多分)、割り込み関数を作る際に必須というわけですね。
とまあ以上になります。