セイコーエプソンの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リセットがかけられた。なるほど・・・。

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

FM3マイコンのUSBホスト機能のHIRQレジスタ

富士通だったけどいつのまにかSpansionになっていたFM3マイコンのUSBホスト機能をいじっていたら、デバイスコネクト割り込み(HIRQ->CNNIRQ)やディスコネクト割り込み(HIRQ->DIRQ)が、クリアしたつもりなのにまた割り込みがかかったり、とりこぼしたり、妙なことになっていた。

HIRQレジスタはbitbandでビットアクセスしてクリアしていたのだが、
FM3 ペリフェラルマニュアル 通信マクロ編 の 正誤表 というエラッタが出ていて・・・

ホスト割り込みレジスタ(HIRQ)はバイトでアクセスしてください。
HIRQレジスタの各ビットの説明の追加部分:
リードモディファイライト時、本ビットは 1 が書き込まれます

あっ、それでおかしくなるのね…。
バイトアクセスするように書き直したら、大人しくなった。

関係ないけど、FM3のMFSは、I2Sが出来たらよかったのになあ。

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モジュールは。

STM32のI2CのSMBAL(SMBus Alert)

STM32のI2CモジュールのSMBAL(SMBus Alert)信号線は、CR1 SMBUS bitを1にしてSMBusモードにしたときだけ使われるのかと思っていたら、
どうも、CR1 SMBUS bit=0のI2Cモードでも、I2CをPEするとI2Cモジュール用に切り替えられてしまって、他の用途に使えないみたい?

それに気づかずSMBALの端子を別用途に使ってしまっていたので、しかたなくソフトでI2C駆動するハメになってしまった…