まるでトランジスタ!? 2ピンで制御するEEPROMを試した【AT21CS01】
先日、非常に興味深い製品が秋月電子通商に入荷しました。
Microchip社製のEEPROM, AT21CS01 [1]。1KBit(128Byte)で40円です。
興味深いのはそのパッケージ。なんとSOT23-3です。なんだこれは。
電源とGNDと通信線かなーなんて思っていたら、ピンアサインを見て二度びっくり。
GND
とSI/O
の実質2ピンしかありません。お前電源どっから取ってきてるんだ……
なんとプルアップされた通信路から電力をチャージして通信するよう。なんだその非接触ICカードみたいな……
これまた珍妙奇怪、実に面白そうなチップに出会ってしまいました。
ということで今回は、こちらのEEPROMをRaspberry Pi Picoで動かしてみたいと思います。
成果物
はじめに今回の成果物を示します。
汎用的に使いたかったので、Pico C/C++ SDKを使い、CMakeのFetchContent[2]でインポートできるライブラリとして仕上げました。
セキュリティレジスタの読み書きにはまだ非対応ですが、後々作り込んでいく予定です。
チップ概要
チップの概要を整理します。
内部構造
チップはメインメモリアレイとセキュリティレジスタと呼ばれるふたつの領域を持っています。
秋月電子の商品説明にあった
偽造防止に役立つ一意のシリアル番号
とは、セキュリティレジスタ先頭に書き込まれているもののはずです。
書き込み可能な領域はゾーン単位でロックできるようですが、データシートを見る限りこれは恒久的なものであり、アンロックするコマンドは用意されていないようです。
あまりにもテストしづらいので、今回はロックについては触れません。
ユースケース
しかしこのチップ需要が謎です。軽く調べた限り2ピンで通信できるという点がミーム的に扱われている情報はいくつかヒットするのですが、肝心のユースケースがイマイチよくわかりません。
公式の実装例[3]によれば
Some application examples include analog sensor calibration data storage, ink and toner printer cartridge identification, and management of after-market consumables.
使用例としては、アナログセンサーの校正データの保存、インクカートリッジの識別、アフターマーケット消耗品の管理などが挙げられます。
とのこと。継続的に電源が供給されない部品について、その識別や認証(?)に使うことを想定しているようです。なるほど。
通信プロトコル
通信プロトコルにはSingle Wire Interface[4] が採用されているようです。物理層?電気信号?のレベルでは1-Wire に似ていますが、データの形式はI²Cの方が近い気がします。
SWIでは以下に示す種類の信号が用いられます:
- リセット/探索応答
- 論理「0」(
ACK
)/論理「1」(NACK
) - 開始/終了条件
共通
デバイスとマスタとの間で行われるすべての通信は、マスタがバスをLレベルに保持することによって開始されます。デバイスが勝手に応答することはないため、データの読み出しを行う際は マスタがコマンドを送信 → デバイスが応答 → マスタがデータを要求 → デバイスが応答 ……と繰り返す必要があります。ちょっと面倒です。
また、バスはプルアップしておく必要があります。プルアップ抵抗の値域は電源電圧によって異なりますが、今回は1kΩを使いました。
リセット/探索応答
デバイスのリセットは以下のフローで行われます。
- バスを
時間Lに保持します。これによりデバイスが放電され、リセットされます。t_{RESET} - バスを解放し、
時間待機します。このタイミングでデバイスが起動し、復帰します。t_{RRT} - 最後にバスを
時間Lに保持し、解放します。これを受け取ったデバイスは、バスがLになってからt_{DRR} 時間の間、バスをLに保持(=ACK)します。t_{DACK}
マスタはバスを解放してから一定時間(
ACK
) / 論理「1」(NACK
)
論理「0」(1ビットのデータのやり取りは
マスタからデータを送信する際、0
または肯定(ACKnowledge)を送る場合は 1
または否定(NotACKnowledge)を送る場合は
デバイスからデータを受け取る場合は 0
を返す場合は最大 1
を返す場合はなにもしません。
マスタはバスを解放してから一定時間(0
を、Hであれば1
を返したと判定することができます。
開始条件/終了条件
通信は常に 開始条件 で始まり 終了条件 で終了します。これらはそれぞれ
制御の流れ
先述の通り、マスタとデバイスとの間でやり取りされるデータはI²Cによく似ています。
共通
データを受け取った側は応答(ACK
/NACK
)を返す必要があります。
マスタがデータを送信した場合はデバイスが、マスタの指示に従いデバイスがデータを返した場合はマスタが、それぞれ応答を返します。
デバイスアドレスの送信
通信開始時、マスタはデバイスアドレスバイトを送信します。これには、オペコード、スレーブアドレス、そして読み書きを示すフラグが含まれます。
オペコードはデバイスに対して行う操作を示します。メインメモリにアクセスする場合は0x0A
、メーカIDを取得する場合は 0x0C
を指定します。
「スレーブアドレス」は発注時に指定でき、工場出荷時に書き込まれる値のようです。商品説明を見る限り、秋月から購入した場合は0b000
です。
スレーブアドレス0
のデバイスに対してメインメモリへの読み出しアクセスを行う場合のデバイスアドレスバイトは以下のようになります。
自身に対するデバイスアドレスバイトを正常に受け取ったデバイスはACK
を返します。
ややこしいですが、これはデバイスが勝手に行うわけではありません。マスタはデバイスアドレスを送信したのち、デバイスに対して1bitの受信を要求する必要があります(これで2時間溶けた)。
メモリアドレスの送信
次にアクセス先のメモリアドレスを送信します。1Kbitなのでアドレス空間は7bitですが、横着せず8bit送信する必要があります(最上位ビットは読み捨てられます)。
メモリアドレスを受け取ったデバイスはACK
を返します。
書き込み
単純に1byte送信するだけです。
AT21CS01は最大8byteのデータを一つのサイクル内で書き込むことができます(ページ書き込み)。書き込みサイクル終了後は
読み出し
デバイスに対し8回データの受信を要求します。これで対象のアドレスに格納された1byteのデータを読み出すことができます。読み出しが完了したら、マスタから要求停止を意味するNACK
を送信します。
こちらも一つのサイクル内で複数バイトのデータを読み出すことができます。書き込みと異なり、一度に読み出せるデータ量に制限はありません(たぶん)。
複数のデータを一度に読み出す場合は1byteごとにACK
を送信し、最後のデータを読み出したところでNACK
を送信します。
開始条件・終了条件
ひとつの処理の前後には開始条件及び終了条件を挟む必要があります。
実装
これら仕様をRaspberry Pi Picoに落とし込んでいきます。
PIOアセンブリ
マイコン側が結構速い(125MHz)ので sleep_us
と gpio_set
でなんとかできないかと思っていたのですが、デバイスの出力を読み出す時間
公式サンプルに1-Wireの実装例が載っていた[5]ので、これを参考にしています。
(PIOに不慣れなこともあり、かなり無駄なことをしている気がします……)
CPUとのインタフェース
実装にあたり大きな課題の一つとなったのがPIOとCPUとのI/Fです。PIOの命令メモリは非常に小さく、複雑な動作を任せることはできません。しかしCPUリソースを占有するような設計ではPIOのメリットが薄くなりますし、割込み等で通信が不安定になるリスクも出てきます。
最終的に、以下のような分業体制を取りました。
- CPUが開始条件を送信する
- CPUが32bitのコマンドをTX FIFOに送る
- PIOがそれを解釈し、リセット/1byte読出し(
ACK
orNACK
)/1byte書込み のいずれかを行う- バス解放後にI/Oを読み、ISRにシフトインする
- 1byteのやりとりが終わったら、ISRの内容をRX FIFOに送る
- CPUがRX FIFOから処理結果を受け取る
- CPUが終了条件を送信する
これにより、最低限1byteのデータを確実に(CPUリソースに依存せず)送受信できます。
動作の様子
ライブラリ同梱のサンプル[6]を動かしている様子です(あらかじめ適当なデータを書き込んでいます)。
おわりに
ここまで読んでいただきありがとうございました。
AT21CS01、SOT23という見た目のインパクトもあり、通信路を電力供給に使うという仕様のインパクトもあり、それなりに話題になったような気がします(少なくとも私のTLは沸きました)。
通信プロトコルも知らないまま衝動買いしてデータシートとにらめっこしながら遊ぶのはなかなか良い経験になったかなと思います。
買ってそのままにしてしまったRaspberry Pi Picoもたっぷり活用できたので大満足です。
皆さんも、2ピンのEEPROM、試してみてはいかがでしょうか。
それでは。
push noblock
-
MicrochipTech/SWI-Connector-Demo: Hardware authentication demo using Microchip’s single-wire AT21CS01 EEPROM. ↩︎
-
What is Single Wire Interface (SWI) Protocol? - Developer Help ↩︎
-
pico-examples/pio/onewire/onewire_library/onewire_library.pio at master · raspberrypi/pico-examples ↩︎
-
swi_eeprom/samples/dump_eeprom.c at v0.1.0 · Enchan1207/swi_eeprom ↩︎
Discussion