2015年1月31日土曜日

bossac で Arduino Due に書き込む

Mac OS X Mavericks のターミナルで Arduino Due にプログラムを書き込む方法です。
getting-started_flash.bin をフラッシュメモリに書き込んでみます。

stty -f /dev/cu.usbmodem1411 1200
/Applications/Arduino.app/Contents/Java/hardware/tools/bossac -U false -p cu.usbmodem1411 -e -w -v -b getting-started_flash.bin -R

bossac で Arduino Due に書き込む前に stty コマンドで通信速度を 1200 bps に設定するのがミソです。これをやらないと "No device found on cu.usbmodem1411" というエラーが出てしまいます。

サンプルプログラムの準備

ちなみに、書き込むための bin ファイルは ASF (Atmel Software Framework) に付属のサンプルプログラムを GCC でビルドしました。ダウンロードページに "ASF standalone archive for GCC (makefile-based) ..." というリンクがありますので、そこからダウンロードして展開します(執筆時点での最新版が 3.20.1 でした。以下 ~/Downloads/xdk-asf-3.20.1 に展開したとします)。

$ export PATH=$PATH:/Applications/Arduino.app/Contents/Java/hardware/tools/gcc-arm-none-eabi-4.8.3-2014q1/bin/
$ cd ~/Downloads/xdk-asf-3.20.1/sam/applications/getting-started/sam3x8e_arduino_due_x/gcc
$ make
/Applications/Xcode.app/Contents/Developer/usr/bin/make all PROJECT_TYPE=flash
CC      common/services/clock/sam3x/sysclk.o
MKDIR   common/services/serial/
CC      common/services/serial/usart_serial.o
MKDIR   common/utils/interrupt/
...
$ ls *.bin
getting-started_flash.bin getting-started_sram.bin

まず Arduino IDE 付属の GCC コマンドへのパスを通します。
パスを通したら展開したソースコードの sam/applications/getting-started/sam3x8e_arduino_due_x/gcc に移動します。
最後に make を実行すると、カレントディレクトリに getting-started_flash.bin が出力されるはずです。

ASF には Arduino Due で使えるサンプルプログラムが幾つか入っています。以下のように探せます。

$ cd ~/Downloads/xdk-asf-3.20.1/sam
$ find . -name Makefile | grep arduino
./applications/getting-started/sam3x8e_arduino_due_x/gcc/Makefile
./drivers/adc/adc_example/sam3x8e_arduino_due_x/gcc/Makefile
./drivers/adc/adc_temp_sensor_example/sam3x8e_arduino_due_x/gcc/Makefile
./drivers/adc/adc_threshold_wakeup_example/sam3x8e_arduino_due_x/gcc/Makefile
./drivers/chipid/chipid_example/sam3x8e_arduino_due_x/gcc/Makefile
./drivers/dacc/sinewave_example/sam3x8e_arduino_due_x/gcc/Makefile
./drivers/gpbr/unit_tests/sam3x8e_arduino_due_x/gcc/Makefile
...

2015年1月19日月曜日

同じval++;でもaddになったりincになったり。

最近GCCのビルドをたくさんやってるなかで気づきました。
int val = 0;
val++;
という単純なC言語プログラムでさえ、i386向けのGCCとi686向けのGCCで出力されるバイナリが違うことを。

違うのは変数のインクリメントでした。i386向けGCCは
inc dword [ebp-4]
を出力しました。一方でi686向けGCCは
add dword [ebp-4], 1
を出力したのです。

addの方がバイナリが大きくなるのですが、なぜi686向けはそちらを選択したのか。僕はその理由を知りません。不思議です。

2015/01/20追記
Twitterで良い記事を紹介していただきました。
この記事によれば、inc/dec命令でストールが発生するアーキテクチャがあるそうな。そこで、そういうアーキテクチャではincの代わりにaddを使うんだそうです。
x86アーキテクチャの闇は深い。

2015年1月16日金曜日

Python の exit(), sys.exit(), os._exit() の違い

Python には 3つの似たようなプログラム終了用の関数があります。
exit(), sys.exit(), os._exit()です。
これらの違いを簡単に調べてまとめてみました。

ものぐさな人へ


  • インタラクティブシェルを終了するには exit()
  • スクリプトの中でメインプロセスを終了するには sys.exit()
  • fork() した子プロセスを終了するには os._exit()


exit([code=None])

site モジュールにより、プログラムの起動時に自動的に追加される定数。
exit 自体が表示されると画面に "Use quit() or Ctrl-D (i.e. EOF) to exit" のようなメッセージを表示し、
exit() と呼び出すと、終了コードを伴って SystemExit 例外を投げる不思議なオブジェクト。

sys.exit() にも言えるが、例外を投げるだけなので、その外側で例外を捕捉してシステムを終了させないようにすることも可能。

sys.exit([arg])

終了コードを伴って SystemExit 例外を投げる関数。
つまり、上で紹介した exit() と呼び出し時の挙動は同じ。

os._exit(n)

終了ステータス n でプロセスを終了する。
これは exit(), sys.exit() と違って、例外を投げるのではなくプロセスを終了させる。
os._exit() は fork() された後の子プロセスを終了させるときに使うのが標準的。