松山事務所の石丸です。
ベアメタル(OSが載っていないハードウェア)のRaspberry Pi 2で、組み込みソフトウェア界のHelloWorldこと、Lチカ(LEDをチカチカと点滅させること)をやってみました。

今回もまだOS開発以前なので、西永俊文「BareMetalで遊ぶ Raspberry Pi」を参考に進めました。
1日目に構築した開発環境でビルドしたバイナリが動作するのか確認するためでもあったので、C言語のソース分割はしていません。

  • startup.S: スタートアップコード
  • kernel.lds: リンカスクリプト
  • Makefile: ビルドスクリプト
  • main.c: Lチカプログラム

今回作成した4つのファイルとkernel.imgはGitHubで公開しています。
https://github.com/maruichi82/raspberry/tree/master/examples/LED_blink

スタートアップコードの作成

スタートアップコードは参考文献そのままです。

CPSR(Current Program Status Register)とスタックポインタの初期化をしてmain関数を呼び出します。
これがC言語はmain関数から実行される理由。

リンカスクリプトの作成

リンカスクリプトもほぼ参考文献通りです。

自分のようにリンカスクリプトってなに?って人は次のサイトの解説がとてもわかりやすかったです。

知られざるリンクの世界 – KOZOSプロジェクト
http://kozos.jp/documents/linker_kernelvm5.pdf

0から作るOS開発 カーネルことはじめ
http://softwaretechnique.jp/OS_Development/startup_kernel.html

Makefileの作成

Makefileもほぼ参考文献通りです。

Makefileをちゃんと書ける大人になりたいと思ったので、わからないところを調べました。

  • $@ とか $< は自動変数。それぞれターゲットファイル名、最初の依存するファイルの名を表す。
  • .c.o:.c から .o を作るという意味でサフィックスルールという。
  • .SUFFIXES.elf.img を登録しているので、.elf.img:というサフィックスルールが書ける。

トリビアなmakefile入門
http://www.jsk.t.u-tokyo.ac.jp/~k-okada/makefile/

make基礎知識
http://exlight.net/devel/make/basics.html

Lチカプログラムの実装

今回唯一わかるC言語だったのでmain.cは自分好みにアレンジしています。

main関数内のマジックナンバーはごめんなさい。どうしても意味が伝わるいい名前がつけられませんでした。47はGPIO47です。

Raspberry Piのモデルの違い

まず大事な変更点ですが、参考文献でターゲットとしている Rspberry Pi Type B と私の Raspberry Pi 2 とではハードウェアの仕様に違いがあり、次の2点の修正が必要でした。

  • 今回制御したいACT LEDがGPIO16からGPIO47に変更
  • IO物理アドレスが0x20200000から0x3F200000に変更

Raspberry Pi メモ (42) Raspberry Pi2 の非互換性
https://www.mztn.org/rpi/rpi42.html

wait

waitの実現のために参考文献では64bitのシステムタイマーを使用しているのですが、2つの32bitレジスタから値を取ったり桁上りをチェックしたりが面倒なので、64bitシステムタイマーの下位32bitだけを使用しました。

1MHzのカウンタが32bitを1周するのに

約71分かかるので500msの経過を計測するには十分だと判断し、経過時間の判定も符号なし整数の引き算なので

カウンタがラップアラウンドしても71分までならwaitできます。

はじめてのvolatile

そんな予約語があると存在は知っていましたが、初めて使って大事さを知りました。
最適化されて困るところにつけます。コンパイラの気持ちになって考えて最終的に3箇所に落ち着きました。

職業としてのプログラミング volatileで最適化を抑制する
http://proger.blog10.fc2.com/blog-entry-20.html

Tech Village 「組み込み」ならではの基礎知識 スタートアップ・ルーチンからハードウェアまで
http://www.kumikomi.net/archives/2003/05/10kumi.php?page=14

最適化されてどんなコードになっていたのか確認できればよかったのですが、今はARMアセンブラが読めないので・・・

make&run

実装が完了したのでmakeしてkernel.imgを生成します。

1日目に作成したファームウェアが起動するSDカードに、このkernel.imgをコピーして、Raspberry Piに挿し込み電源を入れます。

プログラムが動いて感動するなんて久しぶりでした。

TOP
TOP