[Android] Bluetoothが勝手にOFFになって困ってる人用のアプリ

私の使っている Androidスマホが、Bluetooth が 勝手に OFF になっていることがある。

車に乗り込んだときなど、車の(カーナビの)ハンズフリーに自動的に接続していてほしいので、Bluetoothは常にONにしておきたい。

それで私は常にBluetoothはON状態にしてるんだけど、でも、私の使ってる端末がへんなのか、なぜか、勝手に Bluetooth が OFF になっていることが、よく、あるのです。
(BluetoothをONにしてあるのに) 端末の電源を再投入したときなど、高確率で、OFF になってしまう。
映画見る時などは電源を切るので、帰りに電源を入れて車に乗って…しばらくしてからハンズフリーにつながってないのに気づいたりする。

なんで勝手にOFFになるのか…原因を調べるのもめんどくさいので、
「定期的にBluetoothがOFFになってないか調べて、OFFになっていたら、ONにする」アプリを作りました。

bton (ビートン)

…私以外に使う人いるだろうか?

セイコーエプソンのRTCをAndroidで使う場合

EPSONのRTCで、Linuxカーネルソースツリーにドライバが入っていないチップでも
セイコーエプソン製リアルタイムクロックモジュール用Linux Driverダウンロードページ
があったので、Androidでも簡単に使えるかと思ったら、甘かった。

セイコーエプソン提供のドライバで一応RTCとして動作はするのだが、Androidでは “wake up capable” でないと使えない。セイコーエプソン提供のドライバはそうなっていない。(linux-3.10.101 を見たが、ソースツリーに入っているEPSON RTCのドライバもそうなっていない)

(”wake up capable” でないRTCは、alarmtimer でRTCとして登録されない。
kernel/time/alarmtimer.c : alarmtimer_rtc_add_device() で device_may_wakeup() かどうかチェックしている)

この結果、「起動時にはRTCから読み出した時刻がシステム時計に反映される(ここまではLinuxカーネルがやってる仕事なので)が、Android上で(android.os.SystemClock.setCurrentTimeMillis()を使用して)(※このメソッドは特権が必要なので通常のAndroidシステムでは一般のアプリからは使えない)時計をセットしてもそれがRTCに書き込まれない」という事象が起きる。

RTCドライバをいじって、といっても1行追加しただけだが、 probe() の際に

device_init_wakeup(&client->dev, 1);
(※I2C RTCの場合)

をしてやるとalarmtimerがRTCとして登録してくれるので、AndroidからもRTCに書き込めるようになり、一応この問題は無くなる。
でもよく調べてないのでこれだけで大丈夫かわからない。ちゃんと修正しないといけないだろうけど・・・。

なお、こういうドライバは他にも kernel/driver/rtc 内にいくつもあるので注意が必要。
rtc-ds1307.c (DS1307, DS3231 等のドライバ) など(rtc-ds1307.c は、割り込みピンを使う場合は、大丈夫なのかもしれない?)

FM3マイコンのWDT

Spansionに譲渡されたと思ったらSpansionはCypressに吸収されて今後どうなるのか不安も感じる元富士通セミコンダクタのFM3マイコンですが、

これのWDT、タイマアンダーフローでいきなりリセットする、という設定ができないようだ。
タイマスタートビットと割り込み許可ビットが兼用で、リセット許可ビットを単独で立ててもタイマはスタートされないので、リセットだけかけたい、という設定ができない。

タイマスタート兼割り込み許可ビットと、リセット許可ビットを立てておくと、

1回目のタイマアンダーフローで割り込みがかかる
(その際タイマはオートリロードされまたカウントダウンが開始される)
2回目のタイマアンダーフローでリセットがかかる

WDTでリセットしたい場合はどうするのか?
ロードレジスタには、希望するインタバル値 / 2 を設定しておいて、
WDTタイマ割込エントリを用意して、そこではWDT割り込みをクリアすればいい?

しかし、WDT割り込みをクリアするには、WDTクリアするしか方法がないようだ。
WDTクリアをすると・・・1回目のアンダーフローだったっていうこともクリアされてしまって・・・ただ単にWDT割り込みが周期的にかかる状態となり、リセットはかからない。

なんだよこれ。

じゃあ、リセットかけたい場合はWDT割り込みを無視するしかないのか?
でもそうすると2回目のアンダーフローまでの間、WDT割り込みかかりっぱなしになるでしょ?その間、無駄なフリーズ状態時間じゃないの?

割り込みマスクしようにも、HWWDTの割り込みベクタ、NMIと兼用だしなあ・・・
どうなってんのかなこれ?

データシートの「動作例」には、WDTタイマ割り込み発生後にロードレジスタのインタバル値を小さい値に書き換えてやればあまり遅滞なく次のアンダーフローが発生してリセットがかかるよ!的な示唆が含まれているように思える例が書かれているが、ロードレジスタを書き換えるとWDTタイマ割込はクリアされる、とも、データシートには書いてあるんですけど(少なくともHWWDTのほうは)。だから動作例の動作はしないとおもうんですけど。

SWWDTは割り込みが不要なら無視することもできるから、HWWDTは最後の手段的にしておいて、通常はSWWDTも併用しろってことなのかな??

追記。データシートに、ロードレジスタに0を書き込めばすぐに割り込みがかかる、と書いてあった。割り込みハンドラでそうすれば、実質的には遅滞なくWDTリセットがかけられた。なるほど・・・。

(でもやっぱり動作例は間違ってるんじゃないの?)
(でもやっぱり割り込みは使わずにいきなりリセットかけられるようにしてほしかったなあ・・・)

Androidシステムのビルドにかかる時間

4年くらい前のマシンに、1~2年くらい前に買ったSSDを足した、
ubuntu 14.04.2 LTS マシンでの Android 4.4.2のビルドにかかる時間。

CPU Core i5 2500 (2nd GEN Core i 32nm 3.3/3.7GHz 4コア4HT 6MB TDP95W)
メモリ DDR3 16GB
SSD Samsung 840EVO 750GB

ccache使用 make -j8
1回目 40分程度
2回目以降 16分程度

このくらいでもまあガマンできるけど、2回目以降10分以下になるとうれしい気がする。
でもあまり投資したくない。
6コアCPUの値段をちょっと調べる…高いなあ…

追記。このマシンのメモリを試しに32GBにして
make -j32 等、してみたが、速くはならなかった。

追記。このマシンのCPUを Core i7 3770 (3rd GEN Core i 22nm 3.4/3.9GHz 4コア8HT 8MB TDP77W)
にして(メモリは32GB) make -j32 してみたが、 ccache使った2回目が13分になった程度だった。

… このマシンのCPUとメモリへの投資はあんまし意味がなかったようだ。とほほ。ていうか最初の構成がバランスとれてた感じ。

STM32のI2Cはよくわからん

I2Cで1バイトのレジスタリードをするとき、通常は

START → スレーブアドレス(W)送信(W/ACK) → サブアドレス送信(W/ACK) → START(リスタート) → スレーブアドレス(R)送信(W/ACK) → レジスタデータ読み出し(withoutACK) → STOP

とするが、

START → スレーブアドレス(W)送信(W/ACK) → サブアドレス送信(W/ACK) → STOP → START → スレーブアドレス(R)送信(W/ACK) → レジスタデータ読み出し(withoutACK) → STOP

としないとデータが出てこないへんなデバイスがあった(デバイスメーカ自らこのようにしてくれと公言)

で、これを STM32の I2C で使おうとしたら、、、レジスタデータ読み出しまではできるようだが、そのあとなんかへんなシーケンスにはまってしまうみたいで、以後動かなくなってしまう。
(SDAがLのままになってしまい、それでI2Cモジュールは他からI2Cバスを占有されてると思ってしまうみたい?)

I2CモジュールをいったんDISABLEにしたり、SWRSTビットがあるのでそれでソフトウェアリセットしようとしてみても、できない。
しょうがないので、I2Cモジュールを使うのをあきらめて、ソフト駆動でI2Cして逃げるはめになってしまった・・・。

よくわからんなーSTM32のI2Cモジュールは。