/home/tnishinaga/TechMEMO

日々行ったこと、面白かったことを書き留めます。

go言語コンパイラをソースからビルドする

go言語コンパイラのビルド方法が,半年前に触ったときと違ったので,現在の方法をメモっておく.

環境

  • Fedora 21 x86_64
  • Golang 1.4.2 ( c62b003eba484d54c2707b379d29240e5367e98f )

インストール方法

ソースのクローン

半年前はmercurialで管理していた気がするが,いつの間にかgitに移っていた. リポジトリgoogle codeのものとgithubのものがあるが,後者はミラーリポジトリなので,前者からクローンする.

$ cd ~/
$ git clone https://go.googlesource.com/go

ビルド済みGo言語コンパイラのインストール

ここからが半年前と違うところ.

以前はgoコンパイラが既に入っているかいないかにかかわらず, ~/go/src/ 以下で all.bash を実行するだけで,go言語コンパイラをビルドできたような記憶がある. しかし,今は all.bash を実行すると,以下のように ~/go1.4 にgo言語(v1.4)の実行環境を入れるよう怒られる.

$ ./all.bash 
##### Building Go bootstrap tool.
cmd/dist
ERROR: Cannot find /home/tnishinaga/go1.4/bin/go.
Set $GOROOT_BOOTSTRAP to a working Go tree >= Go 1.4.
./make.bash: line 121: /home/tnishinaga/go1.4/bin/go: No such file or directory

そのため,go1.4の実行環境を落としてきて ~/go1.4 に置く. go言語コンパイラの実行環境は,以下から持ってこられる.

$ mkdir tmp
$ wget https://storage.googleapis.com/golang/go1.4.2.linux-amd64.tar.gz
$ tar zxvf go1.4.2.linux-amd64.tar.gz -C tmp/
$ mv tmp/go ~/go1.4

go言語コンパイラのビルド

後は普通に all.bash を実行するだけ.

$ cd ~/go/src/
$ ./all.bash

ビルドが終わったあとは, .bashrc などに

export GOROOT=$HOME/go
export PATH=$PATH:$GOROOT/bin

と書いておくと,ビルドしたgo言語コンパイラにパスが通って使えるようになる.

以上.

Raspberry Pi 2さわってみた

f:id:tnishinaga:20150207145351j:plain

Raspberry Pi 2が届いたので、とりあえず使用感・性能・消費電流について簡単にチェックしてみました。

使用感

かなり快適です。感動しました。

Raspberry Pi 1はCUIですら反応が遅く、デスクトップを起動すると遅すぎてとても使えないレベルでした。

しかし、Raspberry Pi 2は違います。 最初のraspi-config画面の時点から、動作が軽快です。 Raspberry Pi 1ではLocale設定などを行おうとすると、1アクションに10秒ほど待たされましたが、Raspberry Pi 2ではほとんどありません。

GUIを起動しても動作は快適。 ブラウザもすぐ立ち上がりますし、2,3枚ウィンドウ開いても軽快に動作します。

この使用感で4000円程度なら、日常で使う管理コンソールマシンとして、またはVNCクライアントマシンなどの用途に、十分使えるレベルだと思います。

性能

UnixBenchとLinpackで簡単にベンチマークをとってみました。 Raspberry Pi 1との比較は行っていないので、 どなたか比較結果の作成をよろしくお願いします。

UnixBench


Benchmark Run: 4 CPUs; 1 parallel process

Time: 03:32:52 - 04:01:10; 28m 18s

System Benchmarks

Test Score Unit Time Iters. Baseline Index
Dhrystone 2 using register variables 2961984.8 lps 10.0 s 7 116700.0 253.8
Double-Precision Whetstone 497.9 MWIPS 10.0 s 7 55.0 90.5
Execl Throughput 370.2 lps 29.9 s 2 43.0 86.1
File Copy 1024 bufsize 2000 maxblocks 74390.2 KBps 30.0 s 2 3960.0 187.9
File Copy 256 bufsize 500 maxblocks 21577.5 KBps 30.0 s 2 1655.0 130.4
File Copy 4096 bufsize 8000 maxblocks 193781.0 KBps 30.0 s 2 5800.0 334.1
Pipe Throughput 172660.3 lps 10.0 s 7 12440.0 138.8
Pipe-based Context Switching 31772.9 lps 10.0 s 7 4000.0 79.4
Process Creation 1279.5 lps 30.0 s 2 126.0 101.6
Shell Scripts (1 concurrent) 1186.8 lpm 60.1 s 2 42.4 279.9
Shell Scripts (8 concurrent) 332.4 lpm 60.2 s 2 6.0 554.0
System Call Overhead 412119.5 lps 10.0 s 7 15000.0 274.7
System Benchmarks Index Score: 174.0


Benchmark Run: 4 CPUs; 4 parallel processes

Time: 04:01:10 - 04:29:41; 28m 31s

System Benchmarks

Test Score Unit Time Iters. Baseline Index
Dhrystone 2 using register variables 11810261.3 lps 10.0 s 7 116700.0 1012.0
Double-Precision Whetstone 1989.9 MWIPS 10.0 s 7 55.0 361.8
Execl Throughput 1332.2 lps 29.9 s 2 43.0 309.8
File Copy 1024 bufsize 2000 maxblocks 116037.8 KBps 30.0 s 2 3960.0 293.0
File Copy 256 bufsize 500 maxblocks 32386.9 KBps 30.0 s 2 1655.0 195.7
File Copy 4096 bufsize 8000 maxblocks 305329.3 KBps 30.0 s 2 5800.0 526.4
Pipe Throughput 686642.0 lps 10.0 s 7 12440.0 552.0
Pipe-based Context Switching 122410.7 lps 10.0 s 7 4000.0 306.0
Process Creation 2840.9 lps 30.0 s 2 126.0 225.5
Shell Scripts (1 concurrent) 2660.6 lpm 60.1 s 2 42.4 627.5
Shell Scripts (8 concurrent) 351.6 lpm 60.3 s 2 6.0 585.9
System Call Overhead 1572755.6 lps 10.0 s 7 15000.0 1048.5
System Benchmarks Index Score: 438.3

Linpack

消費電流

アイドル時

f:id:tnishinaga:20150207155113j:plain

4コア100%使用時(Linpack実行時)

f:id:tnishinaga:20150207155137j:plain

各結果の感想

性能

Linpackを用いたRaspberry Pi 2の性能結果は、単体で1G FLOPSの結果が出ました。

以前、計算工学ナビさまの記事で、Raspberry Pi 1 Type B+を16台つなげた際の結果は2.66G FLOPSでした。 なので単純に考えれば、Raspberry Pi 2 1台はRaspberry Pi 1 Type B+ 6台分の性能が得られています(通信コストなどは考慮していないので、正確な比較結果ではありません)。

消費電流

Raspberry Pi 1 Type B+の消費電流は、アイドル時とCPU100%使用時どちらも変わらず200mAでした(USB接続なし。LAN接続あり)

Raspberry Pi 2はアイドル時で+30mA、CPU100%使用時は+300mA程度増えています。 これに加えてUSB機器などを接続すると、消費電流は1Aを超えるでしょう。

よって、Raspberry Pi 2を用いる際は、2A出力のACアダプタを使用したほうが、安全だと思います。

おわりに

Raspberry Pi 2は以前に比べ性能が上がり、実用レベルになりました。 これからRaspberry Piを初められるかたはぜひRaspberry Pi 2を…とすすめたいところですが、Raspberry Pi 2はペリフェラルマニュアルや回路図をまだ見つけられていない(まだ公開されていない?)ので、ちょっと不安です。

ペリフェラルマニュアル等が公開されたら、また調べて本を書いたりしたいと思います。

WindowsでARMCCを用いてmbedライブラリをビルドする

LPC812をmbedライブラリを用いて開発したかったので、mbedライブラリのビルド方法を調べました。

事前準備

  • Python2.xのインストールとパスの設定
  • Keil MDK-ARM v5のインストール

インストール方法

基本は高橋さんの記事のとおりですが、少々変更点があります。

mbedのビルドをOS X上で行う - Qiita

Windows上でARMCCを用いてビルドするに必要なこと

LPC812のビルドはARMCC(Keil MDK-ARMに入ってるコンパイラ)以外ではできません。 よって高橋さんの記事を参考に、以下のビルドコマンドでビルドを行います。

$ python workspace_tools\build.py -m LPC812 -t uARM

しかし、以下のエラーが出てビルドができません。

[WARNING] Using default settings. Define your settings in the file "workspace_tools/private_settings.py" or in "./mbed_settings.py"
Building library CMSIS (LPC812, uARM)
[Error 2] 指定されたファイルが見つかりません。

Completed in: (0.01)s

  Build failures:
  * uARM::LPC812

-vオプションを付けて問題の詳細を確認し、printデバッグで調べたところ、どうやらコンパイラの場所指定がおかしいことがわかりました。 もう少し調べてみると、mbedライブラリではMDK-ARM v4を前提としており、加えてデフォルトではMDK-ARMではなく、スタンドアローンなARMCCを用いるようになっていました。

当該ファイルは workspace_tools\settings.py です。 これをMDK-ARM v5を用いるよう、以下のように書き換えます。

diff --git a/workspace_tools/settings.py b/workspace_tools/settings.py
index 3444f86..23090c1 100644
--- a/workspace_tools/settings.py
+++ b/workspace_tools/settings.py
@@ -30,13 +30,14 @@ ROOT = abspath(join(dirname(__file__), ".."))
 BUILD_DIR = abspath(join(ROOT, "build"))
 
 # ARM
-armcc = "standalone" # "keil", or "standalone", or "ds-5"
+armcc = "keil" # "keil", or "standalone", or "ds-5"
 
 if armcc == "keil":
-    ARM_PATH = "C:/Keil_4_54/ARM"
-    ARM_BIN = join(ARM_PATH, "BIN40")
-    ARM_INC = join(ARM_PATH, "RV31", "INC")
-    ARM_LIB = join(ARM_PATH, "RV31", "LIB")
+    #ARM_PATH = "C:/Keil_4_54/ARM"
+    ARM_PATH = "C:/Keil_v5/ARM"
+    ARM_BIN = join(ARM_PATH, "ARMCC", "bin")
+    ARM_INC = join(ARM_PATH, "ARMCC", "include")
+    ARM_LIB = join(ARM_PATH, "ARMCC", "lib")
 
 elif armcc == "standalone":
     ARM_PATH = "C:/Program Files/ARM/armcc_4.1_791"

あとは再度、以下のコマンドを実行すればビルドが完了します。

$ python workspace_tools\build.py -m LPC812 -t uARM

mbed LPC1768でWatchDogTimerを扱う

mbed LPC1768でWDTを使う方法を調べたので、備忘録として記す。

リファレンス

WDTとは

Watch Dog Timer、直訳で番犬タイマー。 マイコンの暴走や無限ループに陥った際、強制的にリセットをかける機構。

WDTはカウントダウンタイマーである。値がセットされるとカウントダウンを開始し、0になるとマイコンをリセットさせる。 この機能を活かして、マイコンの動作を監視する。

以下、監視の手順を簡単に説明する。 監視対象のプログラムに、一定時間以内にWDTのカウンタを再セット(タップ)する処理を入れる。すると、正常に動作している間はWDTが0になる前にタップが行われるため、WDTによるリセットはかからない。 しかし、マイコンの暴走や無限ループなどの理由によりWDTへのタップが行われなくなった場合、WDTのカウンタが0となり、強制リセットが行われる。

register description

以下、LPC1768のWDTに関するレジスタとその説明を記す。

Name Description
WDMOD WDTのモード設定とステータス確認用レジスタ
WDTC タイムアウト値設定レジスタ
WDFEED 0xAAの後に0x55を書き込むと、WDTCにセットした値がWDTのカウンタにセットされる
WDTV 現在のWDTカウンタ値を確認するレジスタ
WDCLKSEL WDTのクロックソースを選択するレジスタ

WDMOD

Bit Symbol Description
0 WDEN WDTを有効化する。1の場合はWDT実行中。
1 WDRESET WDTによる強制リセットを有効化する。1にすると有効となる
2 WDTOF WDTのタイムアウトフラグ。WDTによるリセットが行われると1になる。自動でクリアされないので、ソフトウェアでクリアする
3 WDINT WDT割り込みフラグ。読み込み専用
31:4 - 予約

WDENとWDRESETは一度設定すると、その後ソフトウェアからは無効化できない。

WDTは独立して動作する。そのため、デバッグ等で動作を止める場合、WDEN,WDRESETがともに1となっているとWDTによるリセットがかかり、デバッグができない。

WDTC

WDTのカウンタ値をセットする。 初期値は0xFFとなっている。

最小値はT_WDCLK * 256 * 4 (T_WDCLK = 1 / WDTクロックソースの周波数 ) 最大値は書かれていないため 0xffffffff と予想する。

WDFEED

ここに0xAA,0x55が書き込まれると、WDTCにセットされた値がカウンタにリロードされる。 つまり、WDTのタップ操作になる。

WDTV

現在のWDTカウンタの値を表示する。 ただしカウンタとの同期に6 WDCLKサイクル、加えて6 PCLKサイクルかかるため、実際のクロックの値に比べてWDTVの値は古くなる。

Name Description
WDCLK WDTのクロックソースから供給されるクロック
PCLK ペリフェラルクロック

WDCLKSEL

Bit Symbol Description
0:1 WDSEL クロックソースを設定する。詳細は後述
30:2 - 予約
31 WDLOCK 1を書き込むとWDTのクロックソースをロックできる。一度ロックされると、リセットがかかるまでクロックソースが変更不可となる。

WDSELは0x00~0x10をセットすることでクロックソースを設定できる。

Value Description
0x00 内蔵RCオシレータ
0x01 ペリフェラルクロック
0x02 RTCオシレーター
0x03 予約

プログラム例

mbed LPC1768でWatchDogTimerの動作を確認するコード

Macでmbedをデバッグする方法についてのまとめ

mbed Advent Calendar 2014の11日目です。

まえおき

mbedとの関わり

f:id:tnishinaga:20141211171140j:plain

現在私はmbedのプログラムを アセンブリ言語でコードをゴリゴリ実装して、バグを作っては治すを繰り返す日々をおくっています。

デバッガは必須

アセンブリ言語はCに比べて低級な言語なので、コーディング中に混乱して、バグを作ることが多いです(主観的発言)。 よくあるバグとしては、メモリ破壊、スタック破壊、リターンアドレスのpop忘れ、etc……。 簡単なデバッグ方法としてはprintfを用いたデバッグがありますが、今回はアセンブリで実装しているため、printfを挟むのは少々コストが大きいです。

そこで活躍するのがデバッガです。 このデバッガがあれば、プログラムを1命令ごと、レジスタの値を監視しながらデバッグすることができます。 これによりprintfでは調査しづらい細かな処理を追うことが可能となり、デバッグの効率を格段に上げることができます。 よって、デバッガは必須なのです。

mbedのデバッグ機構

f:id:tnishinaga:20141211171149j:plain

mbedの一部の製品には、メインのマイコンの他に、mbed interfaceと呼ばれる機能を持ったマイコンがついています。 このmbed interfaceはCMSIS−DAPデバッガとしての機能を持っているため、このmbed interfaceを持った一部の製品は、それ単体でデバッグを行うことができます。

f:id:tnishinaga:20141211172046p:plain

※ CMSIS-DAPの説明は特殊電子回路株式会社さまの「CMSIS-DAPって何?」を参照してください。

Macでmbedデバッグ

前置きが長くなりましたが、本題です。 Macでmbedのデバッグを行いましょう。

プログラムのエクスポート

mbedはプログラムをオンラインでコンパイルするという、画期的なシステムを採用しています。 しかし、このオンラインのシステムはコンパイルは出来ますが、デバッグを行うことができません。 デバッグのためにはオンラインのコードをローカルに保存し、オフラインコンパイル環境を用いる必要があります。 この方法については以下のページを参照し、「Exporting to GCC ARM Embedded」でGCC用のコードをエクスポートしてください。

デバッグ環境の整備

私は普段はMac OS Xを用いています。Windows機も所持していますが、もっぱらゲーム専用機としてしか使っていません。

残念なことに、ARM社謹製の統合開発環境 MDK-ARMは、現状Windows専用ソフトウェアです。 そのためMac環境ではライセンス料が云々の前に、使うこと自体ができません。 それでもなんとかMacで開発を行うため、GNUのフリーな環境を用いて開発環境・デバッグ環境を整えます。 その方法は以前ブログ記事にまとめたので、こちらを参照してください。

Tips: GNU開発環境でのアセンブリ利用時の注意

GNUな開発環境とMDK-ARMでは、アセンブリコードの書き方が異なるため、アセンブリコードの互換性がありません。 そのため、アセンブリで開発する際は、デバッガの使えないオンライン上で完結させるか、WindowsでMDK-ARMを用いて開発を行うか、もしくはオンラインへ戻ることを諦めてGNUな書き方を行うかを判断する必要があります。

私は青mbedのプログラムフラッシュが豊富であり、MDK-ARMを用いずともメモリが足りているので、GNUツールで開発することにしました。 オンラインへの復帰は、開発が完了した後に手動でアセンブリコードを書きなおして行う予定です。

GDBの操作方法(簡易説明)

GDBを用いてデバッグする方法を、簡単に説明します。

GDBサーバーへの接続

(gdb) target remote localhost:3333

プログラムのmake

(gdb) make

プログラムのロード

(gdb) load

なお、以前ロードしたプログラムと新しくロードするプログラムに差異がある場合は、後述のdisplayの設定が削除されます。 breakpointの設定は残ります。

状態の表示

displayコマンドを用いると、レジスタやメモリの値を逐次表示することができます。 自分のおすすめは以下。

(gdb) display/i $pc
(gdb) display/x $r0
(gdb) display/x $r1
(gdb) display/x $r2
(gdb) display/x $r3
(gdb) display/x $r4
(gdb) display/x $r5
(gdb) display/x $r6
(gdb) display/x $r7
(gdb) display/x $r8
(gdb) display/x $r9
(gdb) display/x $r10

これでプログラムカウンタの指すアセンブリコードを表示しつつ、レジスタr0~r10までの値を16進数で確認できます。

再実行

(gdb) continue

プログラムカウンタの指す場所から処理を再開します。 後述のbreakpointに引っかかるまで止まらないので注意してください。 強制的に止めたい場合はCtrl+Cを入力します。

breakpoint

(gdb) breakpoint *0x0000a410

特定のアドレスにbreakpointを仕込んで、その位置で処理を止めることができます。 上記のコマンドでは、プログラムカウンタがメモリアドレス0x0000a410になった時、処理を止めることができます。

なお、本来condition等を用いれば変数の値が変化した際に止める……ということができますが、pyOCDの環境で使ったらpyOCDがハングしました。 再現性の確認等ができていないので、バグ報告は行えていません。

1命令実行

(gdb) stepi
(gdb) nexti

アセンブリでは1命令ごと実行する必要があるため、 C言語のstep命令はstepi、next命令はnextiとなります。

おわりに

以上、Macでmbedをデバッグする方法についての簡易デバッグ説明でした。 デバッグ時にgdbサーバーを建てるため使用したpyOCDをもう少し活用すると、より柔軟なデバッグも可能ですが……今回はここまで。 要望があれば、PyOCDを使ってHard Fault原因を探る方法を、再度advendカレンダーに書こうかとおもいます。

緩募

  • ARMマイコン発売から現在までのシェア情報の書かれた資料
  • mbed発売から現在までのシェア情報の書かれた資料

次の人

次はjksoftさんです。よろしくおねがいします。

MacにPyOCDをインストールする方法について

先日mbed用のコンパイル環境を作る方法を解説した際、PyOCDのインストール方法については省略した。

その理由はPyOCDがLinuxWindowsにしか対応しておらず、Linux上でのインストールは特に問題なく行えたからだ。 しかし調べてみると、最近はPyOCDがMacでも動くようになっていた。

そこで早速Mac環境にインストールを試みたが、本家の説明だけではうまくいかなかったので、正しいインストール手順を備忘録として記す。

pipのインストール

PyOCDはpython2動作するので、python2の環境を揃える必要がある。 この環境を整えるため、まずはpipをインストールする。

$ sudo easy_install-2.7 pip

Cythonのインストール

PyOCDをMacで使用するために必要な cython-hidapi は、Cythonに依存しています。 そのため先にCythonをインストールする必要があります。

$ sudo pip install Cython

cython-hidapiのインストール

残りは一見、PyOCDのREADME通りのようにみえる。 しかしcython-hidapiのインストールスクリプトには setup-mac.py を選択する必要があるという罠がある。

$ brew install hidapi
$ git clone https://github.com/gbishop/cython-hidapi.git
$ cd cython-hidapi
$ sudo python2.7 setup-mac.py install

PyOCDのインストール

やるだけ

$ git clone https://github.com/mbedmicro/pyOCD
$ cd pyOCD/
$ sudo python setup.py install

TODO

公式リポジトリのREADMEにプルリクエストを投げる。

mbedのC++コードからCやアセンブラの関数を呼び出す

GCCを用いてC++のファイルからCやアセンブラで定義した関数が呼び出せない問題に引っかかったので、解決方法を記す。

解決方法

ヘッダなどでの関数定義に、以下のように "C" を入れるだけ。

extern "C" void hoge(void);

これだけでCやアセンブラの関数を呼び出すことができるようになる。

進捗

この問題の解決に3日かかりました。