Cypress EZ-USB FX3(CYUSB3014)はファームウェアを格納するためにSPI ROMを使うことができます。
このSPI ROMにはいままでAdesto(現Dialog)のAT25SF041Bなどを使っていたのですが、昨今の半導体不足のためか、それともディスコンなのか、入手が難しくなってきました。
DigikeyでもRSでもMouserでもChip1でも、幅の細いSOIC8の物が見つかりません。
DigikeyにはAT25XE041BというROMならば大量にあるのですが、これを使うことはできるでしょうか?
AT25SFとAT25XEは何となく型番が似ているので行けそうな気がする!と思い、AT25XEを使ってArtix-7ボード24台と、Kintex-7のPCIeボード2台を製造してしまいました!!!

いざ電源を入れてファームウェアを書き込んでみると・・・
起動しない。
なんてことだー。やはりAT25XEだとEZ-USB FX3は起動しないのか???
途方に暮れてデータシートをじっくり読みました。
どうやらAT25XEはデフォルトですべてのセクタにプロテクトがかかっているので、書き込めなかったようです。
さて、CypressのEZ-USB FX3でSPI ROMに書き込むには、CypressからCyControl.exeというのが用意されています。

CyControl.exeはROM書き込み用のファームウェアとしてCyBootProgrammer.imgという「I2C/SPI ROM書き込み用ファームウェア」をいったんRAM上にロードして書き込んでいます。ファームウェアが2段階になるわけです。
そのため、CyBootProgrammer.imgのソースを見つけてきて、AT25XEならばUnprotectの処理を行うようなコードを追加した新たなファームを作って置き換えればよいということになります。
CyBootProgrammer.imgのソースですが、おそらく、EZ-USB FX3 SDKの中にある \1.3\firmware\basic_examples\cyfxflashprog でしょう。ベンダIDとプロダクトIDが04b4:4720で同じです。
AT25XEのUnprotect Sectorのやり方には2通りあって、一つはセクタごとにUnprotectを行う方法、もう一つはGlobal Unprotectを行う方法です。セクタごとのUnprotectはコマンド39hの後にアドレス(3バイト)を送ればよいようなのですが、セクタの構成とかを調べるのが大変です。
やはり、おすすめはGlobal Unprotectです。ステータスレジスタ1に00hを書き込むだけでOK。コマンドとしては01h 00hです。これを行うためにファームウェア内に次のような関数を作ります。
void UnprotectAT25XE()
{
uint8_t buf[8];
buf[0] = 0x9f; /* Read IDCODE */
CyU3PSpiSetSsnLine (CyFalse);
CyU3PSpiTransferWords (buf, 1, 0, 0);
CyU3PSpiTransferWords (0, 0, buf, 4);
CyU3PSpiSetSsnLine (CyTrue);
buf[0] = 0x05; // Read status command
CyU3PSpiSetSsnLine (CyFalse);
CyU3PSpiTransferWords (buf, 1, 0, 0);
CyU3PSpiTransferWords (0, 0, buf, 1);
CyU3PSpiSetSsnLine (CyTrue);
if((rom_id[0] == 0x1f) && (rom_id[1] == 0x44) && (rom_id[2] == 0x02)) // AT25XE041Bならば
{
buf[0] = 0x06; // Write Enable
CyU3PSpiSetSsnLine (CyFalse);
CyU3PSpiTransferWords (buf, 1, 0, 0);
CyU3PSpiSetSsnLine (CyTrue);
buf[0] = 0x01; // Write Status Register
buf[1] = 0x00; // Global Unprotect
CyU3PSpiSetSsnLine (CyFalse);
CyU3PSpiTransferWords (buf, 2, 0, 0);
CyU3PSpiSetSsnLine (CyTrue);
buf[0] = 0x05; // Read status command
CyU3PSpiSetSsnLine (CyFalse);
CyU3PSpiTransferWords (buf, 1, 0, 0);
CyU3PSpiTransferWords (0, 0, buf, 1);
CyU3PSpiSetSsnLine (CyTrue);
}
}
この関数をcyfxflashprog.cのCyFxFlashProgSpiInit()の後で呼び出せばOKです。SPIの初期化完了後にIDCODEを調べてAT25XE041ならば即座にGlobal Unprotectを行うようになります。

Cypress Ez Suiteでビルドするとcyfxflashprog.imgという名前のファイルが出来上がっているので、これをCyBootProgrammer.imgにリネームすればCyControl.exeで自動的に読み込んでくれます。

自作のFX3書き込みアプリでロードして、自作アプリ中からFX3のROMを書き換えてみてもいいでしょう。

◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇
おまけですが、こういったSPI ROMのデバッグを行うには、ベンダリクエストを発行できたほうが便利です。
CyControl.exeではどうやってSPI ROMに書き込んでいるかというと、まずDownloadUserIMGtoSPIFLASH()を呼び出してDownloadUserIMGtoSPIFLASH()の中ではWriteToSPIFlash()を呼び出していて、WriteToSPIFlash()の中ではEp0VendorCommand()を呼びだしています。
DownloadUserIMGtoSPIFLASH() → WriteToSPIFlash() → Ep0VendorCommand()
最終的にはEP0VendorRequest()に行きつきます。ユーザプログラムからEP0VendorRequest()を呼び出せれば何でもできるのですが、CyUSB.dllの中にあるCyFX3Deviceクラスでprivateにされているため見えません。
本来はこの関数を使うとEndPoint0に自由なコマンドを発行してEZ-USB FX3のファームウェアと直接通信できるのですが・・・。こんな便利な関数をprivateにしておくのは勿体ないのでpublicにしてしまいましょう。
CyUSB.dllのソースコードを見つけてきて、CyFX3Devices.csの93行目
private bool Ep0VendorCommand(ref byte[] buf, ref uint buflen, bool IsFromDevice, byte ReqCode, uint Value)
というけしからん行を
public bool Ep0VendorCommand(ref byte[] buf, ref uint buflen, bool IsFromDevice, byte ReqCode, uint Value)
にしてビルドします。
こうして出来上がったCyUSB.dllを使うとベンダリクエストが使えるようになります。

私はSPI ROMのIDCODEやStatusの読み出しとしてコード0xc5を割り当て、チップイレースに0xc7を割り当てました。

結論を言うと、AT25XEはデフォルトで全セクタがプロテクトされているという鬼畜仕様だけど、プロテクト解除してあげれば普通のSPI ROMとして使えるようになるということです。
半導体不足の世の中でSPI ROMがなかなか入手しづらいので、EZ-USB FX3のファームウェア格納にAT25XEが使えるようになるのはよいことだと思います。
半導体メーカーさんは、独自の色を出さなくていいから、業界標準のを作ってください。どうかお願いします。
<m(__)m>
最近のコメント