LinuxでCAmiDionをコンパイル

半年ほど前、Windowsのトラブルに見舞われてUbuntu Linuxに乗り換えたのを機に、CAmiDionの開発環境であるArduino IDEもLinuxで動かす羽目になったわけですが、

数々の壁にぶち当たりました。

主な壁

【USBデバイス】
Windows: COM0のような名前だったUSBデバイス名
→ Linux: /dev/ttyUSB0とかになり、しかもそのパーミッションがないと使えないのでdialupグループに自分のLinuxユーザ名を追加し、一旦ログアウトする、といった対応が必要だった。

【Arduinoスケッチ・ライブラリの引っ越し】
Windows: C:/User/ユーザー名/ドキュメント/Arduino/
→ Linux: ~/Arduino/

【Git環境】
引っ越したArduinoディレクトリがローカルGitリポジトリを兼ねている。このリポジトリにステージやコミットできるだけでなく、リモートGitリポジトリの認証を通すためsslの秘密鍵と公開鍵を作って、push/pullもできるようにする必要がある。
https://git-scm.com/downloads/guis で選んでgiggleとgit-colaをインストール。git-colaが比較的使いやすい印象。

【I2CLiquidCrystal】
コンパイルが通らなかったので原因を調べたら、なんとI2CLiquidCrystalで#includeしているArduino.hの先頭のAが小文字になっていた。あのぉ、これだと Windows では通用しても、ファイル名が case sensitive な Linux では通用しませんから!! Windowsしか使ってない人がやらかしがちなミスでした。

【PROGMEM】
コンパイルが通ってもWarningもいっぱい出たので一つ一つ調べていくが…
なんか、2017年頃にPROGMEMの使い方に仕様変更があった模様。

【性能劣化対策】
スケッチを流し込んでみたら…なんだこれ!めちゃ遅い!

CAmiDion で使っている音源ライブラリ PWMDAC_Synth では、高頻度な割り込み周期で Interrupt Service Routine すなわち ISR() 内でPWMのパルス幅を絶えず更新して波形を出力するので、ここの処理は極力速くしなければならないのに…

最適化(optimization)に関する gcc や g++ のコンパイルオプションの問題?と思って

~/.arduino15/pachages/arduino/hardware/avr/1.8.2/platform.txt

に書かれたコンパイルオプションを -Os (サイズ優先の最適化)を速度優先の -O2 とか -O3 とかに変えてみたが、通常ならフラッシュメモリに書き込まれるコンパイル済み機械語プログラムのサイズが75%を少し超えるくらいなのに、120%とか200%とかサイズオーバー状態になり、書き込みができず。

そこで、ソース(スケッチ)を見直して、ここを参考に可能な限り const 指定をつけるようにして、コンパイラに思いを伝えようと頑張ったわけだが…効果はいまひとつだ…

ISR()で呼ばれるところだけ inline __attribute__((always_inline)) を付けても元のパフォーマンスを回復できず。

しばらく悩んだわけだが…

新型コロナウイルス(COVID-19)騒動で僕もついに4月8日から在宅勤務になり、

しかも風雨が強かった4月13日の夜。夕方のポケ活もたいしてできない中、

検索していたら、決定的な解決策をStackOverflowで発見!

How to change optimization level of one function?(一つの関数の最適化レベルを変更するには?)

これを参考に ISR() から呼ばれる関数だけ最適化レベルを変えてみたら…

static byte __nextPulseWidth() __attribute__ ((optimize(3)))

それだけでも劇的に速くなった!!
効果はばつぐんだ!元のパフォーマンスと同じか、それをちょっと超えるくらいの感触!

これと同じような指定は #pragma でもできる。

#pragma GCC push_options
#pragma GCC optimize ("-O2")
void 速度の最適化が重要な関数() {
:
:
}
#pragma GCC pop_options

要するに、Arduinoの設定で全体に適用するのではなく、関数ごととかクラスごとに最適化レベルを変えれば、サイズオーバーすることなく、タイムクリティカルなところだけ速度最適化ができるというわけ!

これでようやく元のCAmiDionの性能を、Linux上のコンパイルで再現することができるようになりました!!

半年ほど経ってようやく!

ということでPWMDAC_SynthとCAmiDionのソースをリポジトリに上げました。
https://ja.osdn.net/users/kamide/pf/
なんか性能が落ちたなーと思ったらぜひお試しください。

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中