« 2022年1月 | トップページ | 2022年3月 »

2022.02.27

CosmoZのMCAアプリを改良中

Cosmo-Z用のMCA(マルチチャネルアナライザ)アプリを開発しています。

下のスペクトラムはNaIで40Kの放射線を8時間測ったものですが、

8h_20220228110301

任意の場所にマウスカーソルを移動してホイールすると拡大することができるようにしました。

これで気になる部分をじっくり見られます。また、ROIを設定することもできるようにしました。

Log_20220228110301

対数だけではなく、真数で表示したり(これはあまりいらないかも)、

Antilog_20220228110301

それから、MCAのスペクトラムを保存するファイルはXMLで書かれていあますが、その中に使ったトリガ条件などの測定条件を自動的に入れるようにしました。

Mcaxml

TFAの設定が少し変わると波高が変わってくるので、計測結果にも影響が出てきます。そのため、MCAのスペクトラムのファイルの中に測定条件などはできるだけ残していきたいと思います。

 

また、シェーパーのコントロール画面では、チャネルごとに設定値をコントロールしたり、設定を保存できるように改良中です。

「チャネルごと」というのがユーザインタフェースの操作性として一番難しいところです。

Upp_control

 

| | コメント (0)

2022.02.26

放射線信号処理回路(シェーパー)の効果

Cosmo-Zに搭載した、放射線用の信号処理回路の有無で、スペクトラムに違い出るかどうか試してみました。

信号処理回路というのはTFA(Timing Filter Amp)とBLR(Base Line Restorer)というもので、入ってきたパルスのノイズを若干減らしたり、パルスの幅を細くしたりします。シェーパーとも呼ばれています。

NaI+フォトマルの横に塩化カリウムの試薬を置き、バックグラウンド+K40を見てみます。下の波形のオレンジの波形はNaI+フォトマルで得られた生の波形で、茶色と赤の波形はTFAとBLRを通しています。

Nai_20220228104901

同じ波形をFPGA内で3つに分けていますが、赤と茶色の波形はディジタル信号処理をしているので、少しだけ遅れています。

Nai

これらの波形は元は同じ信号ですが、シェーパーの効果を見るため、シェーパーの有り無しでMCAのスペクトラムを比較してみることにします

  • CH1 シェーパーあり 波高弁別機の出力をカウント
  • CH2 シェーパーあり (簡易)波高弁別機の出力をカウント
  • CH3 シェーパーなし (簡易)波高弁別機の出力をカウント

波高弁別機が(簡易)かどうかというのは、簡易というほうは波高の基準値をペデスタルレベルにしているもので、簡易でないほうは、波高の基準値を0Vにしているものです。ペデスタルレベルというのは信号がない時の電圧で、一定期間のヒストグラムを作って決めています。つまり、(簡易)波高弁別機というのは、基準となるレベルが揺れています。

NaIのそばに塩化カリウムを置いて1時間測ったときのスペクトラムを示します。

まずは、シェーパーなしの状態。

Ch3

55mVのあたりでピークが見えていますが、これが40Kのものです。それより左側には特に構造は見えません。

 

次に、シェーパーありで、(簡易)波高分別機の出力を使うもの。

Ch2

25mVのあたりに、ちょっとだけピークが見えてきたかな・・・と思うのですが、あまりはっきりしません。

 

最後は、シェーパー+波高分別機によるもの。

Ch1  

 

 

25mV付近のピークの左に、とても鋭い小さなピークも見えてきています。

 

シェーパーを使うことで元の波形のノイズが減ったことでスペクトルの分解能が上がり、オレンジのスペクトルよりも赤のスペクトルのほうが分解能が向上しています。

また、今回の改良で使えるようになった波高分別機はベースラインが揺れないので、赤のスペクトルよりも茶色のほうが分解能が向上しています。

いままで見えなかった細かい構造が見えるようになってきたと言えます。

 

| | コメント (0)

2022.02.24

波形ビューとMCAのスペクトラムを同時観察

Cosmo-Zの新しいアプリをMDIアプリにして、信号の生波形と、波高値のスペクトラムを同時に見ることができるようになりました。

Mca_20220225144301

また、複数のウィンドウの中のプログラムが同時にハードウェアと通信するといろいろ問題が起きるので、窓口を一本化するように改良したら、ソフトの安定度が上がってきた。スペクトラムと波形を同時に見ても大丈夫。

K40

| | コメント (0)

2022.02.23

構造体の中のlong longは64bit境界に置かなければならない

構造体のフィールドで64bitの型は8バイト境界に置かないといけないということを忘れていて、メンバ変数が書き換わらないというバグが起きて、悩んで3時間くらい無駄にしました。

ARM 32bitのGCC(gcc-arm-linux-gnueabi)が悪いのか、通信が悪いのか、WindowsのCのプログラムが悪いのか、C#がわるいのか、こんなくだらないことで延々どデバッグしてしまいました。

ご注意を!

 

| | コメント (0)

2022.02.22

放射線用信号処理回路のコントロールパネル

放射線用の信号処理回路が再び動くようになりました。

入力した信号をTFAというアンプで鋭くしたり、ノイズを落としたりして、それをCFDというタイミングをはっきりさせる回路に通してトリガを作り、トリガを任意の時間遅らせたり延ばしたりしてゲート信号を作ったりできます。

また、台形シェーパーも使えるようにしました。

Upp

上の波形で茶色が信号波形、紫がゲート、灰色がトリガです。

パルスの大きさが規定値以下の場合はカットするLLD(Lower Limit Discri)、規定値以上の場合はカットするULD(Upper Limit Discri)
という機能もあるのですが、ULDを使う場合はLLDも反応してしまうのでゲートにディレイを設けてLLDから〇us後にULDが反応していないことでトリガを発生させるとしなければいけません。このあたりの設定をTrigger/Gate Generatorでどうにでも設定できるようにしました。

回路自体は5年くらい前に作っていたのですが、操作するためのユーザインタフェースが難しくてなかなか実用化できていませんでした。

ツマミコンポーネントを作ったことで少しは操作しやすくなったと思います。

あとは、VETOをどう作るかですね。

NIMやCAMACを並べた計測回路のアナログの配線がごちゃごちゃ嫌だったからディジタルで作ってみたのですが、ディジタルのコントロールパネルも相当にごちゃごちゃしそうです。

| | コメント (0)

2022.02.21

放射線計測用の「Shaper」をコントロールするUI

放射線計測回路には、TFAとかCFDとかいろいろあるのですが、そういった波形整形の調整をするためのコントロールパネルを作っています。

Shaper

放射線計測と一口に言っても、パルスの減衰する時定数やカウントレートは実験によってみんな違うので、アナログの場合はそれぞれ異なる回路で使って波形を整形するわけです。

その汎用的なデザインを考えているのですが、かなりごちゃごちゃしてきました。「ツマミ」コンポーネントを作ったおかげで少しはコントロールがしやすくなったと思うのですが、なかなか難しいですね。

ディジタルフィルタで構成しているのですが、計算式に時定数の逆数が入るようなところが多いため、シェーパーやポールゼロ回路の時定数を数十nsで処理しようとすると、設定値を1変えることで値が大きく変わってしまったりします。

あと、台形整形回路というのは、すぐにオーバーフローして発散します。なかなか調整が難しいです。

| | コメント (0)

2022.02.19

Cosmo-Zの新しい基板が届いた

「部品がなければ、手に入る部品で作ればよい」

という発想のもと、手に入るリニアレギュレータのLDOと、Gigabit Ether PHYで作り直した基板が届きました。

Np1068c4pcb

下の写真はレギュレータの部分。

Newreg

U42,U43,U44が新しいレギュレータです。小さいですね。

 

下の写真はKSZ9131の部分。赤い矢印が付いているのは、KSZ9031→KSZ9131の置き換えでNCになった電源端子です。もし将来的にKSZ9031しか手に入らなくなったときのために、小さなテストパッドを付けています。ここを電源につなげばKSZ9031でも使えるはずです。

Ksz9131

下の写真は作るときに基板屋さんから問い合わせがあったUSB3.0のコネクタ。

Usb3con

パッドの下に長穴のスルーホールと、すぐ右にノンスルーホールの位置決め穴があります。万が一、内層を抜くのを間違えると全面ショートするので、基板が届いたらすぐにテスターで確認しました。無事に絶縁されていました。

 

それから、昨日、Digikeyから部品一式が届きました。

Cosmozparts

備蓄していた部品と合わせて、実装に必要な部品を検品していきます。

 

| | コメント (0)

2022.02.18

Cosmo-Z Windowsアプリの開発再開

1か月ほど停滞していたCosmo-Z Windowsアプリの開発を再開しました。

まず、アプリをMDIアプリにして、波形の比較などができるようになりました。

Mdi

昔取った波形と今取った波形を比べたり、ファイルの中の波形と今取った波形を比べたりすることができるようになります。

また、放射線計測用の信号回路を再び使えるようにもしています。

下の図はTFAとBLRを使用してみたときの波形です。

Tfa

TFAはTiming Filter Ampといって、放射線用の信号処理で使われるアンプです。

放射線の検出はだいたいは「電荷」という形になります。例えば光電子増倍管の出力は光電子による電荷ですし、放射線の検出は基本的には電荷がどんどんたまっていきます。いつか飽和してしまうので、負荷抵抗を付けて電荷を電流として取り出し、そのときの電圧をアンプで増幅します。すると、

|\___|\|\__|\_

という感じの微分波形になるのですが、これを鋭くするためさらに微分するとコンデンサ-抵抗による微分回路を2回通ると波形がひずんでしまうので、その歪を打ち消すようなポールゼロ補償という補償ができるアンプが必要になります。これがTFAです。

BLRはベースラインリカバリーの略で、信号がないときにゼロになるようにオフセットを調整するものです。

こういった機能をディジタルフィルタで実現しています。

 

| | コメント (0)

2022.02.16

最新のu-boot-xlnx 2022.1をカスタムZYNQボード用にビルドする

4~5年前に「ZYNQのLinuxが動くまで」という小冊子を執筆したのですが、なにぶん4~5年前のことなので、最新のu-boot-xlnxでは少しずつ違うところが出てきてしまい、当時のやり方どおりにu-bootをビルドしようとしてもうまくいかなくなってきました。

そこで、冊子の内容をアップデートする意味も兼ねて、最新のu-boot-xlnxをビルドしてみることにしました。

 

なお、u-boot-xlnxにはXILINXの純正評価ボードであるZC702や、XILINXと密接な関係にあるZYBOやZEDといったボードに関してはあらかじめ設定ファイルが用意されているのですが、当ブログの読者層が本当に知りたいことは

「自作のZYNQボード用にどうやってU-BOOTを作ればよいか」

ということだと思いますので、この点に焦点をあてて解説していきます。

この記事では、XILINXの標準u-bootに入っていない「Zynqberry(ジンクベリー)」というRaspiberryPi形状のZYNQボードのu-bootを作ります。

Te0726_0_20220217150901

ZYBOやPYNQを卒業したい方や、自分でボードを作りたいけどPetaLinuxは使いたくないという方、中で何が起きているかを把握したいという方はぜひとも参考にしてみてください。

 

まず、u-bootを作る際に初めにやらなければならないことはUbuntu 18以上のマシンを用意することです。

UbuntuはWSL2上のUbuntuでもよいし、AWSやさくらのクラウドでもよく、もちろんバーチャルマシンでも構いません。私はUbuntu 18と20で下記の手順でu-bootがビルドできることを確認していますが、CentOSやDebianなどその他のディストリビューションのことはわかりません。

Ubuntu Linuxが用意できたらXILINXのXSDKを入れます。当方ではXSDK2018.3で確認しています。おそらく最新のVitisでもよいと思いますが試してはいません。XSDKをインストールしたら、下記のコマンドで環境をセットアップします。

$ export CROSS_COMPILE=arm-linux-gnueabihf-
$ source /tools/Xilinx/SDK/2018.3/settings64.sh

そして、Xilinxのgitからu-boot-xlnxをダウンロードして移動します。

$ git clone git://github.com/Xilinx/u-boot-xlnx.git
$ cd u-boot-xlnx

また、u-bootをコンパイルするには、以下のものが必要なので入れておきます。

$ sudo apt install build-essential
$ sudo apt install libssl-dev
$ sudo apt install bison
$ sudo apt install flex

build-essentialというのは、makeとかccなどビルドに必要なツール群です。

また、libssl-devが入っていないと、

In file included from tools/aisimage.c:9:0:
include/image.h:1133:12: fatal error: openssl/evp.h: No such file or directory
# include <openssl/evp.h>
^~~~~~~~~~~~~~~

というエラーで止まります。

Image2_20220217150701

まずはこういうエラーとの闘いが続きます。

最後のbisonとflexというのは字句解析ツールなのですが、これが入っていないと、

  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  YACC    scripts/kconfig/zconf.tab.c
/bin/sh: 1: bison: not found
scripts/Makefile.lib:222: ターゲット 'scripts/kconfig/zconf.tab.c' のレシピで失敗しました

というエラーが出てビルドに失敗してしまいます。2017年のころには求められなかったので、最近のアップデートで求められるようになったのでしょう。

また、ビルドするLinuxがUbuntu 16だと以下のエラーが出てうまくいきません。パッチを当てるなどいろいろ試したのですが、どうしてもビルドを通すことができませんでした。

HOSTLD tools/dumpimage
tools/lib/ecdsa/ecdsa-libcrypto.o: 関数 `prepare_ctx' 内:
ecdsa-libcrypto.c:(.text+0xcd): `OPENSSL_init_ssl' に対する定義されていない参照です
ecdsa-libcrypto.c:(.text+0x185): `EC_GROUP_order_bits' に対する定義されていない参照です
tools/lib/ecdsa/ecdsa-libcrypto.o: 関数 `ecdsa_check_signature.isra.3' 内:
ecdsa-libcrypto.c:(.text+0x3ad): `ECDSA_SIG_set0' に対する定義されていない参照です
tools/lib/ecdsa/ecdsa-libcrypto.o: 関数 `ecdsa_sign' 内:
ecdsa-libcrypto.c:(.text+0x497): `ECDSA_SIG_get0' に対する定義されていない参照です
ecdsa-libcrypto.c:(.text+0x4ae): `BN_bn2binpad' に対する定義されていない参照です
ecdsa-libcrypto.c:(.text+0x4c0): `BN_bn2binpad' に対する定義されていない参照です
tools/lib/ecdsa/ecdsa-libcrypto.o: 関数 `ecdsa_add_verify_data' 内:
ecdsa-libcrypto.c:(.text+0x68a): `EC_GROUP_order_bits' に対する定義されていない参照です
ecdsa-libcrypto.c:(.text+0x6d2): `EC_POINT_get_affine_coordinates' に対する定義されていない参照です
tools/lib/rsa/rsa-sign.o: 関数 `rsa_sign' 内:
rsa-sign.c:(.text+0x525): `OPENSSL_init_ssl' に対する定義されていない参照です
rsa-sign.c:(.text+0x756): `EVP_MD_CTX_reset' に対する定義されていない参照です
tools/lib/rsa/rsa-sign.o: 関数 `rsa_get_params' 内:
rsa-sign.c:(.text+0x953): `RSA_get0_key' に対する定義されていない参照です
rsa-sign.c:(.text+0x9a0): `RSA_get0_key' に対する定義されていない参照です
tools/lib/rsa/rsa-sign.o: 関数 `rsa_add_verify_data' 内:
rsa-sign.c:(.text+0xe01): `EVP_PKEY_get0_RSA' に対する定義されていない参照です
collect2: error: ld returned 1 exit status
scripts/Makefile.host:104: ターゲット 'tools/dumpimage' のレシピで失敗しました
make[1]: *** [tools/dumpimage] エラー 1

この4つが入っていれば、

$ make xilinx_zynq_virt_defconfig
$ make

で、標準構成であるxilinx_zynq_virt_defconfig用のu-bootのビルドに成功するはずです。

2017年ごろのu-bootでは、ZYBOやMicrozedなどボードごとに設定ファイルが分かれていたのですが、2022年のu-bootではzynq_virtという一つのファイルにまとまっています。まずは、環境の確認としてxilinx_zynq_virt_defconfigをビルドしてみるのがよいでしょう。

そうしたら、自分のボード用のdefconfigを作るのですが、xilinx_zynq_virt_defconfigをひな形にして、ここにzynqberry_defconfigを作りましょう。defconfigはu-boot-xlnx/configs にあります。

$ cp configs/xilinx_zynq_virt_defconfig configs/zynqberry_defconfig

コピーしてきたdefconfigを変更する場所は3か所です。

CONFIG_DEFAULT_DEVICE_TREE="zynq-zc706"
CONFIG_OF_LIST="zynq-zc702 zynq-zc706 zynq-zc770-xm010 zynq-zc770-xm011 zynq-zc770-xm011-x16 zynq-zc770-xm012 zynq-zc770-xm013 zynq-cc108 zynq-microzed zynq-minized zynq-picozed zynq-zed zynq-zturn zynq-zturn-v5 zynq-zybo zynq-zybo-z7 zynq-dlc20-rev1.0"
CONFIG_ZYNQ_GEM=y

CONFIG_DEFAULT_DEVICE_TREE="zynq-zynqberry"
CONFIG_OF_LIST="zynq-zynqberry"
CONFIG_ZYNQ_GEM=n

にします。

できれば追加しておきたい項目として、

CONFIG_IDENT_STRING=" for TE0726"
CONFIG_SYS_PROMPT="Berry> "

も付けておくと、出来上がったときに違いがわかりやすくなります。

なお、CONFIG_DEFAULT_DEVICE_TREEで指定したデバイスツリーファイルを参照して周辺装置の設定をします。CONFIG_OF_LISTを変更しないと

Device Tree Source (arch/arm/dts/zynq-zynqberry.dtb) is not correctly specified.
Please define 'CONFIG_DEFAULT_DEVICE_TREE'
or build with 'DEVICE_TREE=<device_tree>' argument

というエラーで止まります。

 

次に、defconfig内のCONFIG_DEFAULT_DEVICE_TREEで指定したzynq-zynqberryという名前のデバイスツリーを作ります。u-boot用のデバイスツリーはarch/arm/dts/に置くことになっているので、zynq-zynqberry.dtsをここに置きます。

このdtsファイルを置いたらarch/arm/dts/Makefileを編集し、324行目あたりにzynq-zynqberry.dtbがビルドされるように登録します。

最後のzynq-zybo-z7.dtbの後ろに\を置いて1行挿入すればよいでしょう。

zynq-zturn-v5.dtb \
zynq-zybo.dtb \
zynq-zybo-z7.dtb \
zynq-zynqberry.dtb
dtb-$(CONFIG_ARCH_ZYNQMP) += \

これでビルドするとu-boot.elfが出来上がります。

Image3

以下のような内容でmkboot.bifというファイルを作ります。

the_ROM_image:
{
[bootloader]fsbl_myhdf.elf
zynqberrydemo2.bit
u-boot.elf
}

別途作っておいたfsblとbitとbootgenで結合します。

bootgen -w -image mkboot.bif -o i boot.bin

でboot.binが生成されます。

このboot.binをQSPI ROMに書き込めば、自分で作成したu-bootで起動するようになるというわけです。

Kidou

Model名はデバイスツリーに書かれた名前になり、DRAMサイズもデバイスツリーで指定します。ボードごとの差異はデバイスツリーに書くのがいまどきのようです。

ただし一つだけ問題があります。このu-bootは自動で起動しないのです。

printenvで見て見ると、

bootcmd=run distro_bootcmd
distro_bootcmd=for target in ${boot_targets}; do run bootcmd_${target}; done
boot_targets=qspi jtag mmc0 mmc1 qspi nand nor usb0 usb1 pxe dhcp

となっています。bootcmdはdistro_bootcmdを呼び出し、distro_bootcmdはbootcmd_qspi、bootcmd_jtag、bootcmd_mmc0・・・などを順番に試していくというスキームなのですが、最後までLinuxが起動してくれません。

Bootfail

もちろん、u-bootのコンソールで

fatload mmc 0 0x03000000 uImage && fatload mmc 0 0x02A00000 devicetree.dtb && bootm 0x03000000 - 0x02A00000

と入力すればLinuxは起動してくれるので、上のコマンドでbootcmdを上書きしてしまいましょう。

あまりエレガントではありませんが、include/configs/zynq-common.h を書き換えます。

200行目付近にCONFIG_EXTRA_ENV_SETTINGSというマクロ定義があるので、

#define CONFIG_EXTRA_ENV_SETTINGS       \
"scriptaddr=0x20000\0" \
"script_size_f=0x40000\0" \
"fdt_addr_r=0x1f00000\0" \
"pxefile_addr_r=0x2000000\0" \
"kernel_addr_r=0x2000000\0" \
"scriptaddr=0x3000000\0" \
"ramdisk_addr_r=0x3100000\0" \
BOOTENV \
"bootcmd=fatload mmc 0 0x03000000 uImage && fatload mmc 0 0x02A00000 " \
"devicetree.dtb && bootm 0x03000000 - 0x02A00000\0"

にします。

強制的にbootcmdを書き換えて、distro_bootcmdを起動させることなく、SDカードからカーネルを読み込むことができました。

Bootok_20220217153901

これでもう、自作ボードであってもPetalinuxを使うことなく、u-bootを作成できますね。

 

| | コメント (0)

2022.02.15

今年度の損益を試算をしてみたら・・

銀行さんが、今年度の売上を教えてほしいということだったので、現時点までのデータを会計ソフトに入れて試算してみました。結果としては昨年度より大幅に売り上げダウンなのですが、不思議なことに、それほど大きな赤字にはなっていないようなのです。

  

なるほど。もともとハードウェア製品は薄利で、FPGAボードの輸入販売事業もめっちゃ薄利なので、売上が減っても利益はそれほど減らないんですね。利益率の低い商売をしていると、売上が減っても利益も減らないとは目からうろこでした。喜んでいられるわけではありませんが・・

今年一年、どうやって食べてきたのかと疑問に思ってしまいますが、わずかにMITOUJTAGの売上があったことと、ほんのちょびっと請け負いをしたことで、生き延びていられたようです。

 

どのみち半導体不足でモノもつくれないし、海外製のボードを輸入しようにも製造されないので、どうしようもありません。

FPGA評価ボードというシノギも、もう終わりに近づいているのでしょう。

今、まだ体力が残っているうちに新しい事業に進まなければいけませんね。

| | コメント (0)

2022.02.13

KSZ9031RNXの代替品

Cosmo-ZではGigabitEtherのPHYとしてKSZ9031RNXというのを使ってきました。昔はMicrelで今はMicrochipです。

Oct_20220219143301

最初はKSZ9021RNXで検討していたようなのですが、KSZ9021RNXはIOが3.3V固定だったのでZYNQのMIOには合わず、KSZ9031RNXに乗り換えたような形跡があります。

さて、そのKSZ9031RNXですが、部品難により入手できなくなってきてしまいました。一昨年くらいから欠品の兆候が出ていたので最後の12個をMicrochipのオンラインストアで買ったのですが、それも前回のCosmo-Z製造で使い切ってしまいました。

部品が手に入らなくなったら同等機能の新製品が出ていて、メーカーは新製品のほうの生産に全力を注いでいる可能性があります。

KSZ9031RNXについてはKSZ9131RNXという新製品が出ていたので、半年ほど前に100個買っておきました。それが、今活きようとしています。

Ksz90319131

ピン配置的な違いは14番ピンがNCかDVDDLかという違いだけであるので、新しく作るボードでは14番ピンをNCにすればよさそうです。

 

いまではKSZ9131も納期1年待ちなので、買える時に買っておいて本当に良かったと思います。

部品がなければ、今ある最新の部品で基板を作り直すくらいの覚悟でないとやってられませんね。

 

| | コメント (0)

2022.02.12

ZynqberryをOpenVPNクライアントにする

昨日のブログで、自宅と会社のPCをOpenVPNクライアントにして拠点間接続する話を書きましたが、この方法にはいくつかの問題点がありました。

第一に、OpenVPNはWindowsではパブリックネットワークになります。外から通信されるにはWindowsのファイアウォールを開けなければなりませんが、パブリックネットワークのファイアウォールを筒抜けにするのは抵抗感があります。

第二に、拠点間通信の踏み台にするにはWindowsにルーティングをさせなければなりません。できないことはないのだと思いますが、ワークステーションとして使用しているPCにルータの役割をさせるのは気が進みません。

最後に、WindowsにOpenVPNクライアントという新しいソフトウェアを入れなければなりません。あまりインストールするソフトは増やしたくありません。

 

そういうわけで小型の組み込みLinuxマイコンをOpenVPNのクライアントにしてVPNを構築したいと思います。今どき、どこの誤家庭にも1台や2台はZYNQの評価ボードが余っていると思いますので、それを使ってOpenVPNのクライアントをインストールしてアクセスできないかと考えました。私はZynqberryを選びました。なぜならばZynqberryはRasPiと同じ形状なのでケースに納めて安全に使えるからです。(別にRaspberryPiでもいいのですが動くやつが家にありません)

Openvpn_zynqberry

まず、「Zynqberryを入手したら最初に行う10のステップ(前編)」に記した手順で、Ubuntu 18をインストールします。

次にopenvpnをインストールします。

# apt install openvpn

そして、クラウド内に立てたOpenVPNのサーバ上で、

./easyrsa build-client-full zb1 nopass

を行い、zb1.keyとzb1.crtを作ります。keyファイルは~/easy-rsa/pki/private 内に、crtファイルは~/easy-rsa/pki/issued 内に作られます。

「zb1」というのはただの識別用の名前なのでなんでも構いません。これと、/etc/openvpn/にある ca.crt の3つのファイルを合わせて、SCPか何かでZynqberry上に転送します。

Zynqberry上では

# sudo cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/client 

を実行してひな形から/etc/openvpn/client.confを作ります。そしてこのファイルを編集します。

# sudo emacs /etc/openvpn/client.conf

変更すべき箇所は、サーバ名、certファイルの名前、keyファイルの名前、それからTLS-AUTHを使用しない場合はその行をコメントアウトすることだけです。

  • remote <サーバのIPアドレス> 1194
  • cert zb2.crt
  • key zb2.key
  • #tls-auth ta.key 1

最後に、サーバの/etc/openvpnフォルダにzb1ファイルを作ります。

ifconfig-push 10.8.0.14 10.8.0.13
iroute 192.168.1.0 255.255.255.0

zb1配下に192.168.1.0/24というネットワークがあることと、zb1のIPアドレスを10.8.0.14にすることを指定しています。

これで準備が整いました。

# sudo systemctl start openvpn@client

か、confファイルとcertファイルとkeyファイルとca.crtを結合したzb1.ovpnファイルを作って、

# sudo openvpn --config zb1.ovpn

で起動してもよいでしょう。

しかし、起動に失敗するのです。エラーの原因を

sudo journalctrl -xe

で見てみるるか、

openvpn --config zb2.ovpn

で起動すると、

ERROR: Cannot open TUN/TAP dev /dev/net/tun: No such file or directory (errno=2)

というエラーが出ているのが確認できます。errno=19の場合もあります。

ここで見つからないと言われている/dev/net/tunというのは何かというと、トンネリングネットワークデバイスのドライバのようです。なぜ/dev/net/tunがないかというと、ZynqberryのLinuxのカーネルコンパイルのときに入れていなかったからです。組み込み用OSなのでできるだけ軽くしたのだと思います。

出来上がっているカーネル(uImage)に追加でモジュールを組み込むには、カーネルのコンパイルをやり直さなければなりませんが、それには現在のLinuxのカーネルのコンフィグ状態がどうなっているのかを調べる必要があります。

/proc/config.gz という特殊ファイルに現在のカーネルを作る際に使ったコンフィグがあるので、

# gunzip -c < /proc/config.gz > config

で、configファイルを取り出すことができます。

また、ホストPCにLinux構築環境をセットアップします。使用しているカーネルは4.9.0-xilinxです。(4.9.0以降のバージョンだと/dev/xdevが使えなくなるので、後のバージョンは避けたい)

このconfigファイルをLinuxをコンパイルするためのマシン(カーネルビルド用マシン)のLinux構築フォルダにコピーしておきます。

カーネルビルド用のLinuxにログインしたら

export CROSS_COMPILE=arm-linux-gnueabihf-
source /opt/Xilinx/SDK/2017.2/settings64.sh

でgccへのパスを通し、

make ARCH=arm xilinx_zynq_defconfig

でXILINX ZYNQのデフォルトコンフィグを呼び出し、Zynqberryから抽出したconfigファイル(/proc/config.gzの中身)を.config という名前にしてこのディレクトリにある.configと置き換えます。

Config

.configがコンフィグの正体です。.configを置き換えたら、

make ARCH=arm menuconfig

でメニューコンフィグを開きます。

Device Drivers→Network device supportの中にUniversal TUN/TAP device driver supportというのがいるので、これを*にします。

Enable_ap

make ARCH=arm UIMAGE_LOADADDR=0x8000 uImage

でコンパイルが行われ、10数分すると完了します。./arch/arm/boot/uImageというファイルが出来上がっているので、このuImageをZYNQ起動ディスクの第一パーティションにあるuImageと置き換えれば完了です。

置き換えたカーネルで起動すると、/dev/net/tunが出来ていて、

Tun

# sudo systemctl start openvpn@client

で、OpenVPNのクライアントを起動することができるようになります。

ip aコマンドで見ても

Ipa

ちゃんとIPアドレスが振られているのが分かります。

 

なお、電源ON時に自動的に起動するようにするには、systemctl enableを使います。

$ sudo systemctl enable openvpn@client
Created symlink /etc/systemd/system/multi-user.target.wants/openvpn@client.service → /lib/systemd/system/openvpn@.service.

これで自宅LAN内にOpenVPNのアクセスポイントが設置でき、会社からPINGを飛ばすことも、自宅内のPCのファイルにアクセスすることもできるようになりました。

Ping_from_office

File

クラウド内のOpenVPNサーバへのログインは証明書必須のSSHにしておけばいいし、OpenVPNのセキュリティはTLS-AUTHを有効にすれば高められるので、今までよりもセキュリティが強固になったのではないかと思います。デメリットは毎月2000円~3000円のコストがかかることです。

Openvpn_zynqberry

なお、スループットはAmazonのAWSもさくらのクラウドでやってもほぼ同じで40Mbpsくらいでした。OpenVPNクライアントはWindowsPCでもZynqberryでもほとんど変わりません。OpenVPN自体はかなり軽いようです。

同じことをRaspberry Piでも何でもできると思いますが、余っているLinuxボードがあったらぜひ有効活用してみてください。

カーネルをコンパイルしなおして/dev/net/tunを有効にしたカーネルは下記のリンクからダウンロードできます。

ダウンロード - uimage

 

 

| | コメント (0)

2022.02.11

OpenVPNで自宅と会社のネットワークを接続する

これまでは、自宅のルータのVPN機能を使って会社やモバイル端末から自宅のネットワークにつないでいたのですが、

V4

自宅がIPv6に切り替わったことで、ルータに付属していたVPN接続が使えなくなったのと、ルータのファイアーウォールがタコなので安全にポートを開けられなくなったため、そろそろIPv6時代に対応した方法を真面目に考えなければならなくなりました。

なお、会社はレンタルオフィスを借りていて、レンタルオフィスの事業者がファイアーウォールを設置しているので外からは入れません。だから会社をVPNサーバにするということはできません。

やり方としては、AmazonのAWSかさくらのクラウドを借りて、その中にOpenVPNのサーバを立てておいて、自宅と会社の両方からアクセスするということになります。

Openvpn

しかも、接続したPCを踏み台にして、会社の中にあるファイルサーバや組み込み機器に対して自宅からアクセスできるようにもしたいわけです。「自宅から会社にアクセスする」だけ、「会社と自宅のPC間で通信する」だけ、という設定ならば例は見つけることができるのですが、接続した先のPCを踏み台にしてそこからアクセスを広げるとなると見つけにくくなります。

いろいろなサイトを見ながらOpenVPNのセットアップを理解するまでに丸1日かかりましたが、そういった設定もできるようになってきました。

やり方としては、

  1. openvpnとeasy-rsaをインストールする
  2. 認証局を作って、サーバ証明書や鍵などをいろいろ作る
  3. サーバの設定ファイル(server.conf)を作る
  4. クライアント証明書を作る
  5. ccdフォルダを作り、クライアントごとのサブネットの設定やIPアドレス固定を行う
  6. クライアント設定ファイルと鍵を一つにしてovpnファイルを作り、Windows版クライアントに読み込ませる

という手順でできました。

やり方をメモとして残しておきます。

OpenVPNとeasy-rsaのインストール

# sudo apt install openvpn easy-rsa

でopenvpnとeasy-rsaをインストールします。

# sudo emacs /etc/sysctl.conf

で、net.ipv4.ip_forward = 1のコメントを外して有効化する。

# sudo sysctl -p

で設定を有効化する

認証局を作って、サーバ証明書や鍵などをいろいろ作る

make-cadirというコマンドはディレクトリを作るだけではなく、easyrsaコマンドが使えるようにいろいろなファイルをコピーしたりシンボリックリンクを張ったりするコマンドです。このディレクトリに移動してCA局(CRTファイル)を作り、サーバ証明書(server.crt、server.key)、DH鍵(dh.pem)を作ります。

# make-cadir ~/easy-rsa
# cd easy-rsa
# ./easyrsa init-pki
# ./easyrsa build-ca nopass
# sudo cp pki/ca.crt /etc/openvpn
# ./easyrsa build-server-full server nopass
# sudo cp pki/issued/server.crt /etc/openvpn
# sudo cp pki/private/server.key /etc/openvpn
# ./easyrsa gen-dh
# sudo cp pki/dh.pem /etc/openvpn
# ./easyrsa gen-crl

作ったserver.crt、server.key、dh.pem、ca.crtのファイルを/etc/openvpnにコピーしました。

サーバの設定ファイル(server.conf)を作る

ひな形から持ってきてカスタマイズします。

# sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
# sudo gunzip /etc/openvpn/server.conf.gz
# sudo emacs /etc/openvpn/server.conf

server.confでカスタマイズすべき場所は、

ca ca.crt ← 上で作ったca.crtのファイル名に合わせる
cert server.crt ← 上で作ったserver.crtのファイル名に合わせる
key server.key ← 上で作ったserver.keyのファイル名に合わせる
dh dh.pem ← 上で作ったserver.pemのファイル名に合わせる
push "route 192.168.1.0 255.255.255.0" ← 自宅、拠点、会社のサブネットのアドレス
push "route 192.168.2.0 255.255.255.0" ← 自宅、拠点、会社のサブネットのアドレス
client-config-dir ccd ← CCD機能を有効にする
route 192.168.1.0 255.255.255.0 ← 自宅、拠点、会社のサブネットのアドレス
route 192.168.2.0 255.255.255.0 ← 自宅、拠点、会社のサブネットのアドレス
client-to-client ← クライアント間通信を有効にする
;tls-auth ta.key 0 # This file is secret ← 今はまだTLS-AUTHのセキュリティは使わない

です。

クライアント証明書を作る

以下のコマンドでクライアント証明書を作りますが、sudoは必須です。sudoを付けないとエラーが出るだけでなく、pki/reqフォルダにファイルが残ってしまい、sudoを付けても同じユーザ名で鍵が作れません。

# sudo ./easyrsa build-client-full jitaku nopass
# sudo ./easyrsa build-client-full kaisha nopass

作りたいクライアントの数だけ行います。

これで~/easy-rsa/pki/privateフォルダの中に、<クライアント名>.keyが作られます。

ccdフォルダを作り、クライアントごとのサブネットの設定やIPアドレス固定を行う

ccdというのは、クライアントごとのサブネットの設定やIPアドレス固定を行うもののようで、/etc/openvpn/ccdフォルダに拡張子なしのクライアント名のファイルを作ります。

まず、

# mkdir /etc/openvpn/ccd
# sudo /etc/openvpn/ccd/jitaku

で自宅用の設定ファイルを作ります。ファイルの中身は

ifconfig-push 10.8.0.26 10.8.0.25 ← クライアントに割り当てられるIPと、ゲートウェイのアドレス
iroute 192.168.3.0 255.255.255.0 ← クライアントが持っているネットワークの範囲

としておきます。アドレスの末尾は26、25としていますが何でもよいわけではなく、4n+2、4n+1の値になるようにします。0~3は使えません。

同様に会社用のccdファイルも作ります。

# sudo /etc/openvpn/ccd/kaisha

ファイルの中身はさほどのとは少し変わります。

ifconfig-push 10.8.0.22 10.8.0.21
iroute 192.168.5.0 255.255.255.0

これで、自宅PCと会社PCのIPを固定することができます。

クライアント設定ファイルと鍵を一つにしてovpnファイルを作り、Windows版クライアントに読み込ませる

OpenVPNのクライアントは、Linux版のクライアントとWindows版のクライアントで設定ファイルの扱いがだいぶん違います。

Linux版では/etc/openvpn/client/client.confにクライアント設定ファイルを書いておいて

# sudo systemd start openvpn-client@client 

で起動するか、ovpnファイルを作って

# sudo openvpn --config <設定名>.ovpn

で読み込みます。Windows版ではほぼovpnファイルを使う方法の一択です。

ovpnファイルというのは何かというと、client.confファイルと、CA、KEY、CRTファイルを一つに結合したもので、以下のようなスクリプトで作ります。

mkovpn.sh

#!/bin/bash
ca_path=./pki
key_path=./pki/private
crt_path=./pki/issued
if [ $# -ne 2 ]; then
echo "mkovpn.sh HEADER CLIENT" 1>&2
exit 1
fi
header=$1
target=$2
cat $header
echo '<ca>'
grep -A 30 'BEGIN CERTIFICATE' "$ca_path/ca.crt"
echo '</ca>'
echo '<key>'
cat "$key_path/$target.key"
echo '</key>'
echo '<cert>'
grep -A 30 'BEGIN CERTIFICATE' "$crt_path/$target.crt"
echo '</cert>'

このファイルを作ってchmod 755 で実行権限を付けて、

./mkovpn.sh ovpn_head jitaku > jitaku.opvn

のようにして使います。

ovpn_headというのはclient.confファイルのコメントを除いたシンプルな設定ファイルで、

client
dev tun
proto udp
remote <サーバのIPアドレス> 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
key-direction 1
cipher AES-256-GCM
auth SHA256
verb 3

です。TLS-AUTHを使わない場合は、

tls-auth ta.key 1

を書かないようにします。

上記のスクリプトを実行するとovpn_headの後に鍵や証明書が埋め込まれたファイルができ、Windows版のOpenVPN GUIで読み込ませると接続することができます。

Connected

AmazonのEC2ではデフォルトでSSHしかポートを開けていないので、インバウンドのUDP 1194を開くようにセキュリティのコントロールパネルを設定するのを忘れないようにしてください。

Windowsのファイアウォールが悪さをする?

こうやって出来上がったのが下の図のネットワークです。

Kousei2

OpenVPNは、Windowsではパブリックネットワークにされてしまいます。自宅から会社PCにアクセスするにはファイアウォールのパブリックを無効にしなければなりません。(もしくはパブリックネットワーク経由でのファイルとプリンタの共有を許可する)

Disablepublic

ところが不可解なことが起きました。会社PCのIPアドレスは192.168.2.2、OpenVPN側のアドレスは10.8.0.10ですが、自宅PC(192.168.1.4)からは10.8.0.10にはアクセスできるのに192.168.2.2にはできないのです。

PINGを飛ばしてみてみると、10.8.0.10にアクセスしたときには応答が返るのですが、192.168.2.2にアクセスしたときには返りません。

Packet

Windowsのファイアウォールが悪さをしているようなのですが、ファイアウォールを全部無効にしても通らないし、ブロックしたというログもありません。ルーティングテーブルを見ても192.168.1.0/24のサブネットのゲートウェイはOpenVPNを向いているので問題はないはずなのですが、なぜなのでしょう。

 

| | コメント (0)

2022.02.10

自宅がIPv6になったらレンタルルータRX-600KIがおかしくなっていた

プロバイダから「IPv6に切り替わります」というメールが来て、自宅に帰るとルータがおかしなことになっていました。

ルータはNTTからレンタルしているRX-600KIなのですが、いままで基本設定→接続先設定にIPv4とIPv6の両方があったのが、IPv4 PPPoEだけになっていて、しかもIPv4 PPPoEのボタンがすべてグレーアウトしていて設定も変更もできなくなっていました。

Ipv4_gray

詳細設定の部分にもIPv4パケットフィルタがなくなています。

Shousai

私の家庭では子供のネット時間を制限するため、DHCPのIP固定とIPフィルタリングを活用していたのですが、それができなくなってしまいました。

IPv6フィルタは全体的に効きが甘いように感じます。設定してもすぐにフィルタされるわけではなく、効き始めるまでに少しのタイムラグがあるように感じます。それに、Windows PCは一時IPv6アドレスというのを使って通信するので、毎日変わるアドレスに追従してフィルタを変更するのは大変だし、一時IPを禁止してしまうとIPアドレスが完全に固定されてしまうのでプライバシー的な問題もあります。

Ipv6filter

IPv4のフィルタがなくなってしまったのは、LAN側にはIPv4を割り当てていてもIPoEで外に出るときにIPv6に変換してしまうから、IPv4のフィルタは不要ということなのでしょうか。

そのうえ、RX-600KIがVPNサーバになれたのがIPv6になってからできなくなってしまったのがきついです。

 

RX-600KIのIPv6フィルタには、ファイアーウォール機能の有効/無効と、セキュリティレベルの高度/標準という選択があります。これは有効-高度にしておかなければなりません。

ファイアーウォールを「無効」をにするとIPv6フィルタ機能全体が使えなくなります。セキュリティレベルを「標準」にするとフレッツ網内の別の家庭からのパケットを受け入れるようになってしまうそうです。

そのため、特定のマシンに対して特定のポートだけを開けておくといったことをしようとしても、IPv6ではRX-600KIのファイアーウォールではじかれてしまうので、今後はできなくなります。

ただ、IPv4でいろいろやりたい人のためにRX-600KIには謎の管理画面があって、以下のアドレスからアクセスできるようになっています。

http://192.168.1.1:8888/t/

T1

このIPv4設定をクリックすると、次のような画面になります。

T2

IPv4パケットフィルタ設定を開くと、ちゃんとIPv4フィルタがありました。

T3

静的NAPTも設定できるようですし、高度な設定の中のIPv4の一時停止の機能停止をチェックすると、IPv4ルータに戻ります。

T4

メイン画面に戻ると、IPv4 PPPoEが復活していました。

T5

ただ、IPv6もPPPoEと書かれていて待機中となっているので何か不安です。

T6

IPv4フィルタもVPNサーバ機能も復活していました。

T7

IPv6の確認サイトで試してみるとIPv6接続で外とつながっているので、IPv4とIPv6の2セッション張れているのかもしれません。

T8

ただ、子供たちから無線LANがつながらないというクレームが来たのでLAN内で何かの問題があるのかもしれません。「IPv4の一時停止」というチェックボックスの意味もよくわからないし、IPv6オンリーの環境だとfast.comで測って90Mbps出ていたのが10M以下になってしまうことがあったり安定しません。

やはり、IPv6オンリーの環境にしつつ外から家のPCや組み込み機器を外からアクセスできるような環境を構築する必要が出てきました。

| | コメント (1)

2022.02.09

クリアな電圧を作るリニアレギュレータの代替品を探す

アナログ・ディジタル・ミックスド・ソリューションではマイナスの電源を作るため、また、クリアなプラス電源を作るためにリニアLDOを使います。

私が好んで使ってきたLDOは、プラスの電源はTPS73625、マイナスの電源はTPS72325です。これらを使うと±2.5Vで400mAと、-200mAのクリアな電源が作れます。しかもSOT-23-5という小さいパッケージです。

しかし、昨今の半導体不足の影響でこれらのLDOの入手は困難になってきました。TPS73625はまだ何とかなるのですがTPS72325は壊滅的です。そこで、現時点で入手可能な負電源でパッケージの小さいものを探してみました。

現時点で入手可能な負電源TPS72325の代替品は、ADP7182です。ADP7182は様々な固定電圧バージョンと可変電圧バージョンがありますが、在庫数を見ると可変電圧バージョンのADP7182の在庫量が27万個と圧倒的に大量です。

Adp7182

このようなご時世なので固定電圧バージョンで回路を作るよりも、可変電圧バージョンを買っておいて用途に応じて電圧を設定したほうがよいのではないかと思います。

性能の比較ですが、

  • ADP7182・・PSRR 66dB@10kHz、Noise 18uV RMS、200mA、2013年製。537円
  • TPS72325・・PSRR 65dB@1kHz、Noise 60uV RMS、200mA、2003年製。465円

とADP7182に軍配が上がります。やはり10年後に作られたICだからでしょうか、性能はADP7182のほうが良いです。

 

ついでに正電源のLDOも比較してみます。正電源は比較的在庫があるのですが、まずは固定電圧2.5Vで2mm×2mmのものから比べてみます。

  • TPS73625・・PSRR 37dB@1kHz、Noise 30uV RMS、400mA、2003年製。309円
  • LP5912-2.5・・PSRR 75dB@1kHz、Noise 12uV RMS、500mA、2016年製。184円
  • TPS73525・・PSRR 68dB@1kHz、Noise 13.2uV RMS、500mA、2018年製。241円
  • TPS7A2625・・PSRR 52dB@1kHz、Noise 300uV RMS、500mA、2018年製。132円
  • TPS7A1125・・PSRR 64dB@1kHz、Noise 93.9uV RMS、500mA、2018年製。176円

となりました。いろいろなシリーズがあるのですが、LP5912-2.5がベストでTPS73525が次点でした。TPS7AシリーズはノイズもPSRRもあまりよくないようです。

 

結論を言うと、古い電源ICが見つからない場合は、基板を変更する覚悟で新しい電源ICを探してみましょう。SOTのような足があるパッケージではなく、CSPのほうが放熱がよくリニア電源には向いています。メーカー的にも新しいICや、携帯やスマホに使われるICのほうを優先的に作っているのかもしれません。

ICの在庫がない場合には、この機会に最新のICで基板を設計しなおすのがよいのではないかと思います。

 

| | コメント (0)

2022.02.08

Efinity Trion T20のJTAG書き込みでCRESET_NとSS_Nが必要な理由

Efinity Trion T20ではJTAG書き込みの際に、TCK,TDI,TMS,TDO以外にCRESET_NとSS_Nという2つの信号が必要になります。

Creset

この原因を考えてみました。

AN038には、SSをGNDに落とすように書かれています。

An038schem

コンフィグ期間中、TEST_Nは常にHでなければならないようです。別のドキュメントにはTEST_Nは常にプルアップにされているので、Hで構わないのだと思われます。

SS_Nは、ドキュメントによってSS_NとSSという表記が混在していますが同じものと思われます。実際の波形を見てみると、SSをLにした状態でCRESETをH→L→Hにしているのがわかります。

Scope_91_20220211154801

このSSをLにするという理由については明確には書かれていませんが、AN006によればCRESET_Nが1になったときのSS_Nの状態をサンプリングして、0ならばSPI Passive Modeでコンフィグすると書かれています。

Reason_ss_l

SPI Active Modeというのは、FPGAがSPIの信号を出してSPI ROMからデータを取ってくるモード。

SPI Passive Modeというのは、外にあるマイコンからFPGAにコンフィグデータを送り込むモードです。

つまり、JTAGモードでコンフィグする時にはSPIコンフィギュレーションが走らないようにPassive Modeに入れておいた状態で、JTAGの信号を流しこむのだと考えられます。

Efinixの開発環境「Efinity」は中身がPythonで書かれていて、ソースコードがすべて含まれています。そのため、プログラムを解析したり書き換えたりすることができます。Programmerに関しては下記のプログラムで動いているようです。

C:\Efinity\Programmer\2021.1\pgm\bin\efx_pgm\ftdi_program.py

1240行目の

gpio.open_from_url(url,direction=payload["direction"])
sleep(0.003)
gpio.write_port(payload['init_val'])
sleep(0.003)
gpio.write_port(payload['step_1_val'])
sleep(0.003)
gpio.write_port(payload['step_2_val'])
sleep(0.003)
gpio.close()
gpio = None

をコメントアウトすると、JTAGコンフィグ前にCRESET_NやSS_Nを遷移させるのを止めることができます。

CRESET_NやSS_NがHのままだとJTAGコンフィグしてもFPGAが起動しないことが確認できました。

また、ProgrammerがCRESET_NとSS_Nを動かさなくても、人間がピンセットでSS_NをGNDにショートにしてRESETボタンを押せばJTAGコンフィグできることを確認しました。

プログラム自体はSS_Nを常にLにすることを意図しているのだと思いますが、gpio.close()を実行するとCRESET_NとSS_Nは解放されてHに戻ります。結局、SS_Nはプログラミングの間は常にLにする必要はなく、CRESET_NがL→Hに遷移するときだけLにすればよいのだということがわかりました。

また、ftdi_programming.pyを解析した結果、JTAG書き込みのシーケンスは以下のようになっていることが判明しました。

  • 3ms待ち
  • SS=L、CRESET_N=0
  • 3ms待ち
  • SS=L、CRESET_N=1
  • 3ms待ち
  • SS=L、CRESET_N=1
  • 3ms待ち
  • gpioを閉じる ← ここでSS_LはHに戻る
  • TAP RESET
  • TAP IDLE
  • 0.1秒待ち
  • PROGRAM命令送信
  • SHIFT_DRステートへ遷移
  • ファイルを読み込む
  • 640bitの0を書き込む(制御回路が初期化に必要な時間を与えるため)
  • 4096bit単位でファイルを送信。先頭から順に送り込むが、各バイトの内容はビットリバースする。
  • ファイルをすべて送ったら、4096bit単位の端数に0を詰めて送る。
  • 0.1秒待つ
  • ENTERUSER命令送信
  • Shift_DRに遷移して'0'を100bit送信
  • IDCODE命令送信
  • TAP RESET
  • 0.2秒待つ

送る単位は4096でも1000でも、なんでもよいようです。ここはFTDIのFIFOが溢れない量ということで決められているようです。

不思議なのは、ENTERUSERを実行した後の次の命令がIDCODEでなければならないことです。BYPASSだとコンフィギュレーションに失敗してしまうのです。この原因はまた後日解析することにします。

 

| | コメント (0)

2022.02.07

Efiniryのバージョンの違いとTrion書き込みの成否

EfinityのバージョンによってT20へのJTAG書き込みができたりできなかったりするのではないかと思い、調査を行いました。

 

最新のEfinity v2021.2.323のProgrammerでは、JTAGに切り替えただけでクラッシュします。

これはPythonのプログラムがJTAG Chain Fileに書かれたidcodeを読み込むことをしているのですが、そのファイルが読み込まれていないとれ外を発生させるからです。File→InportChainFileでJTAG Chain File(xmlファイル)を読み込めばJTAGに切り替えることはできるのですが、書き込み時にクラッシュします。またxmlファイルの各行の先頭にスペースがあるとXSD Standardに準拠していない旨のエラー(?)が出たり、求めているストライクゾーンが狭すぎるようです。

V2323

↑このあとクラッシュする

 

1つ前のEfinity v2021.1.165と2つ前のv2020.2.299ならばT20にJTAGに書き込めます。

V2020_2299

 

3つ前のEfinity v2020.1.140ではFTDIを認識しません。

V2020_1140

なお、プログラミングツールにFTDIを認識させるにはZadigを使って2つのポートのドライバをlibusb-win32に置き換える必要があります。

Two_driver

JTAGポートにつながっているのは片方のはずなのですが、なぜなんでしょうね?

 

結局のところ、安定して書き込めるのはv2021.1.165と2つ前のv2020.2.299に付属のProgrammerです。

 

| | コメント (1)

2022.02.06

MITOUJTAGからTrion T120への書き込みはできたが、T20はできない

MITOUJTAGからEfinix Trion T120BGA576への書き込みができるようになりました。

T120_program

Development Kitに元から付いているUSBポートをUSB-JTAGとして使えるのでJTAGケーブルを用意する必要はありません。バウンダリスキャンもそれなりに動くようになったので、書き込み後のI/Oの状態を見ることもできます。

T120の書き込みはデータシートどおりのシーケンスで行けました。

 

しかしながらT20への書き込みはできません。

EfinityのGUIのプログラマでSVFファイルを作ろうとすると、

ERROR: Export SVF feature is disabled for AN08/AN20 bitstreams

というエラーを吐いてしまいます。

Gui_svf

EfinityはPythonで書かれていてソースコードが見れるようになっているので、このエラーを吐くPythonコードを探して見ると、

if idcode in ["0x00000000", "0x00210A79"]:

と書かれています。T8~T20のデバイスに対してはSVFファイルをエクスポートさせないようになっていると解釈できます。

GUIのProgrammerではSVFが作れなかったのですが、それならコマンドラインのツールなら何とかできないかと思い、やってみました。

MS-DOSプロンプトを開き、

D:\Efinity\2021.2\bin>setup.bat

を実行します。

次に、D:\Efinity\2021.2\pgm\bin\efx_pgm へ移動し、以下のコマンドを打ちます。

python38 export_bitstream.py hex_to_svf D:\naitou\T20EvalBoard\outflow\new_project.bit D:\naitou\T20EvalBoard\outflow\test.svf

これで、D:\naitou\T20EvalBoard\outflow\にあるnew_project.bitからtest.svfを生成できます。

出来上がったSVFファイルは下記のような感じです。

TRST OFF;
TRST OFF;
ENDIR IDLE;
ENDDR IDLE;
STATE RESET;
STATE IDLE;
FREQUENCY 1E6 HZ;
TIR 0;
HIR 0;
TDR 0;
HDR 0;
//
// Check idcode
SIR 4 TDI (3);
SDR 32 TDI (00000000) TDO (00220A79) MASK (ffffffff);
//
// Enter programming mode
SIR 4 TDI (4);
//
// Begin bitstream
//
ENDDR IDLE;
HDR 0;
TDR 0;
SDR 1000 TDI (5C162E2696EA506CAC4C620C4C2A045CA6C6966EA6225076F6964E2A045C9E3696B6866250264E86F64236866EA20C4C2A3AAEF62E9686763A5C22045C2EC6A656F64E0A50504C4C0C4C048CAC5C8C8C5C0C8C04EC0C0446A6620476F6B2045C26A62E864EA676A6E2500C2C8C748C740C4C0C4C045C76F696CE4EA66A);
SDR 1000 TDI (5050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050500C045CCA2A9242FA22A22222820A508C04);
SDR 1000 TDI (8C600028C600028C600028C600028C600028C600028C600028C6000DF34A000900180823100C000000000000000000800000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000070C40F24B12CFFF6C445168505050505050);
・・・
(中略)
・・・
SDR 1000 TDI (0904020100804020100804020100804020100804020000100804020100804020100804020100804020100804020000100804020100804020100804020100804020100804020000100804020100804020100804020100804020100804020000100804020100804020100804020100804020100804020000100804020100);
SDR 200 TDI (10080402010080402010080402010080402010080402000010);
// Extra clock ticks in SDR state
SDR 1000 TDI (0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
SDR 1000 TDI (0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
SDR 1000 TDI (0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
//
// Enter user mode
SIR 4 TDI (7);
RUNTEST 100 TCK;
//

このようなSVFファイルが出来上がるのですが、IDCODEが間違っていますね。T20BGA256のIDCODEは00220A79ではなく、00210A79であるはずです。

IDCODEの相違については--idcodeオプションで変更することもできますし、SVFファイルを手動で書き換えてもよいでしょう。

最初のSDRの行の末尾を見てみると、

・・696CE4EA66A

で終わっていますが、これはnew_project.bitの先頭が

56
65
72
73
69

なので、ビットリバースしたものだとわかります。つまり、bitまたはhexを読み込んで、ビットリバースさせたものをTDIから順に送り込めばよいのでしょう。

しかしながら、このSVFファイルを送り込んでもT20のコンフィギュレーションは成功しませんでした。T120では成功するのに、なぜでしょうね。GUIツールではT8~T20はSVFを生成させないようにしていたので、このように生成したSVFファイルには何かの欠陥があるのかもしれません。

 

さて、コマンドラインでPythonのツールを動かすことができたので、コマンドラインのプログラマ ftdi_program.py なら書き込みができるかもしれないと思い、試してみました。

FTDIのポートを指定する--urlオプションの書き方は、ftdi://ftdi:2232h:FT3SWU4A/1 と書けばよいようです。同じパラメータを--aurlにも指定します。FT3SWU4AはFT2232Hのシリアル番号です。

しかし、書き込みは失敗でした。

Command_programmer

 

T20BGA256には、Efinity Programmerからも、コマンドラインからも、SVFファイルからも書き込めないのです。

いったい、どうすればよいのでしょう!!?

 

| | コメント (0)

2022.02.05

Trion T120のバウンダリスキャンがおかしい件

T20のバウンダリスキャンができるようになったのでT120評価ボードでも同様にやってみました。

結果としては、相変わらず異常です。

Bscan_20220206183001

状況としては、

  • 出力ピンと入力ピンが逆になっている
  • IO_DDR_mem_data_11などいくつかのピンで、入力・出力が激しく入れ替わっている

です。LEDチカチカしか動かしていないので、DDRの入力と出力が入れ替わるとは考えられません。なお、SVFプレイヤーを使って調査してみたところではT120ではBoundary Scan Cellの順序が逆転しているということないようでした。

 

さて、EfinixのサポートページにあるBSDLファイルのページを見て見ると、なんと!BSDLファイルがアップデートされているのです。

Bsdl_files

T20 BGA256のBSDLファイルのバージョンが3.0になっていて、見比べてみると

Bsdl_diff

私がブログでBoudary Scan Cellの順序が逆だと指摘したのが2月3日ですが、Efinixがその修正版を出してきたのが2月4日です。Efinixの中の人がこのブログを見ているということはないと思うので偶然だと思いますが・・。本当に偶然日付が同じだったのだと思います。

もし私のブログを見ていたたとしたら、

attribute INSTRUCTION_CAPTURE of T20_FBGA256 : entity is "0001";

の間違いも直っていたと思います。この間違いは相変わらず修正されないままでした。

さて、T120のほうは、なんと、バウンダリスキャンレジスタの長さが変更されている!!!!!

Len_changed

T120_FBGA576-v2.0.bsdではバウンダリスキャンレジスタの長さが1542だったのが、T120_FBGA576-v3.0.bsdでは1471に変わっています。これって、致命的な間違いですね。正しくバウンダリスキャンできるわけがない。

本当の長さはいくつなのかを調べるために以下のようなSVFを実行してみます。

STATE IDLE;
SDR 32 PRINT;
SIR 4 TDI (2);
SDR 2000 TDI (00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000001
) PRINT;

1ビットの1がどこに出てくるかを調べるというわけです。

結果は、

00000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000A49249B6DB6DB6DB6D349B6DA6DB
6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D
B6DB6DB6DB6DB6DB6DB49B6DB4C00000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000001A69B6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C0
000200069B0000000000000000000000000000000090004B60000000000000000000000000000000
00000000000000000000

と、1471ビット分押し出されて出てきたので、正しいバウンダリスキャンレジスタの長さは1471です。

もちろん、0x5555とか55aaとかいろいろなデータを流してみて推定するのですが、ここではわかりやすくするために1としています。

新しくなったBSDLファイルを使ってバウンダリスキャンをしてみたのですが、結果は残念なことにすべてのピンの入力と出力が反転しているように見えました。

Bscan_30

SAMPLEモードにしてバウンダリスキャンセルをひたすらダンプしてみると、

2022/02/04 19:12:51 Line 2 : TDO(captured)='5'
2022/02/04 19:12:51 Line 13 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB6C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001369B6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C000020006DB0000000000000000000000000000000090004B6000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:51 Line 15 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB4C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B6DB6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C0000200069B0000000000000000000000000000000090004B6000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:52 Line 17 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB4C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001A6DB6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C0000200049B000000000000000000000000000000009000C92000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:52 Line 19 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB6C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B6DB6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C0000200069B000000000000000000000000000000009000C92000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:52 Line 21 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D36DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB6C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B69B6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C0000200049B000000000000000000000000000000009000CB2000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:52 Line 23 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB6C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000126DB6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C0000200049B000000000000000000000000000000009000CB2000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:52 Line 25 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D36DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB4C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001269B6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C0000200049B000000000000000000000000000000009000C96000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:53 Line 27 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB4C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000126DB6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C0000200069B000000000000000000000000000000009000C96000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:53 Line 29 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349B6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB6C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000126DB6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C000020006DB000000000000000000000000000000009000CB6000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:53 Line 31 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D36DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB6C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001369B6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C0000200069B000000000000000000000000000000009000CB6000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:53 Line 33 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349B6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D36DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB4C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001269B6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C000020004DB000000000000000000000000000000009000592000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:53 Line 35 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D36DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB4C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001A69B6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C000020006DB000000000000000000000000000000009000592000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:54 Line 37 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB6C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B6DB6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C0000200049B0000000000000000000000000000000090005B2000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:54 Line 39 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB4C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001A6DB6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C000020006DB0000000000000000000000000000000090005B2000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:54 Line 41 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349B6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB6C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001369B6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C0000200049B000000000000000000000000000000009000596000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:54 Line 43 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB4C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001269B6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C000020006DB000000000000000000000000000000009000596000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:54 Line 45 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349B6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D36DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB4C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B69B6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C0000200069B0000000000000000000000000000000090005B6000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:55 Line 47 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB4C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001A69B6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C0000200049B0000000000000000000000000000000090005B6000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:55 Line 49 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349B6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB4C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B69B6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C000020006DB000000000000000000000000000000009000D92000000000000000000000000000000000000000000000000000'
2022/02/04 19:12:55 Line 51 : TDO(captured)='000000000000000000249249B6DB6DB6DB6D349A6DA6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6D36DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB49B6DB4C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001269B6DB6DB6DB6C00200000802AAAAAEAAAFEAA00C0000200069B000000000000000000000000000000009000D92000000000000000000000000000000000000000000000000000'

となっています。

LEDのチカチカに合わせて変化する点を探してみると下記の部分ですが、bit206に相当します。

Changing_point

4B6=010 010 110 110
C92=110 010 010 010
CB2=110 010 110 010
592=010 110 010 010

バウンダリスキャンセルは3bitなので上のように区切ります。これらはIO_GPIOB_RXP06、IO_GPIOB_RXN05、IO_GPIOB_RXN04、IO_GPIOB_RXP04に対応したセルで、左から、output、control、inputの値です。

出力ピンなのにcontrolは常に'1'なのでdisvalは'0'のはずですが、BSDLファイルにはdisvalは'1'と書かれています。この間違いはT120_FBGA576-v3.0.bsdでも直っていないように見えます。

試しにこのdisvalを'0'に書き換えてみると正しくスキャンできるようになるし、入力ピンの値も読めるようになりました。

Scan_ok_20220206193201

結論としては、

  • T120_FBGA576-v3.0.bsdで採用されたとおり、バウンダリスキャンセルの長さは1471である
  • BSDLファイルのdisvalを0に書き換えないと、I/Oの入出力が逆になってしまう

だいたいのピンの方向は正しく見えるようになったのですが、今度は逆にクロックの入力ピンが見えなくなってしまいました。disvalはやはり1が正解なのかもしれない。

ただ、似たようなバグはSpartan-6にもあったので、もしかしたらXILINXから引き抜かれた設計者が同じバグを作りこんでしまったか!?

そうだとすると、コンフィグ前とコンフィグ後で挙動が変わるはずです。いずれ試してみることにします。

 

| | コメント (0)

2022.02.04

Efinity Trionの開発環境Efinityを使ってみた

Trionの開発をチュートリアルに従ってやってみました。

まず、開発環境のIDEが下の画面のような構造なのですが、ツールバーの左の×ボタンを押すとIDEが終了してしまいます。それに論理合成のメッセージなどが流れる「コンソール」という領域が激しく邪魔です。

Efinifyide

UIが使いにくいだけなら、何とか我慢ができたかもしれません・・

 

Development KitのサンプルデザインはEfinityのWebサイトからダウンロードできるのですが、T20BGA256ボードとT120BGA576ボードのチュートリアルのダウンロードは下記の図のリンクです。

Download_tutorial

さて、これでダウンロードして解凍すると以下のようなファイルが出てきます。

T20_tutorial

このフォルダを指定してEfinityで開くとプロジェクトが開けます。

しかし、このプロジェクトはピン定義が行われていないのでBitStreamが出来ません。Efinityでピン定義をするやり方はわかりにくいのですが、IDEのメインメニューからTools→Open Interface Designerをやるか、ツールバーの

Openinterfacedesigner

のボタンを押します。

Interface Designerが開いたら、チュートリアルのとおりにピン定義を行います。

Interfaceediter

このツールはお世辞にも使いやすいとは言えませんが、動作はします。出来上がったピン定義のファイルは<プロジェクト名>_peri.xmlという名前で保存されます。このXMLファイルをテキストで編集すればピン定義が楽にできるかというと、そうではなくて、

    <efxpt:gpio_info device_def="T20F256">
<efxpt:gpio name="Dataout[0]" gpio_def="GPIOR_104" mode="output" bus_name="Dataout" is_lvds_gpio="false" io_standard="3.3 V LVTTL / LVCMOS">
<efxpt:output_config name="Dataout[0]" name_ddio_lo="" register_option="none" clock_name="" is_clock_inverted="false" is_slew_rate="false" tied_option="none" ddio_type="none" drive_strength="3"/>
</efxpt:gpio>

という感じのXMLファイルになっていて、E12とかA14みたいなピン番号ではなく、GPIOR_104というFPGAの端子名になっているので手作業で書き換えていくのは困難だと思われます。

基本的にはGUIツールで設定するしかないのですが、isfファイルからインポートできるという情報もあります。(https://twitter.com/aoi87/status/1489551347523665920)

T20 Development Kitに関しては、T20EvalBoardSolution.zipというファイルが中に含まれていて、これを解凍すると、チュートリアルを行った後の状態のファイルが出てくるので、その中からnew_project.peri.xmlをコピーしてくるというのも手段の一つです。
Solution

大事なことなので繰り返しますが、「Development Kitに関しては、~Solution.zipというのはピン定義された完全なプロジェクト」のようです。

※1 ただし、T20EvalBoardSolutionは Running Debugger Step 0 fail. See exit code and exit status いうエラーが出て論理合成が通りません。使うのは_peri.xmlのみ、コピーしてくればいいでしょう。

※2 プロジェクトのフォルダに日本語(マルチバイト文字?)が入るとダメなようです。プロジェクトが他のインスタンスで使われいるというようなエラーが出て論理合成が走りません。

ツールはいろいろグダグダしていますが、論理合成結果はさらにグダグダしています。

BitStreamをはじめ、Efinityが生成するファイルはoutflowというフォルダにできるみたいですが、BitStreamのファイルとHexファイルのサイズが全く同じなんですね。中身も全く同じです。

Outflow

そして、このBitファイルとHexファイルの中身は、1バイトずつ16進で書かれていて1バイトずつ改行されているのです。

Hex

これを見たとき、なんだか怒りを感じました。

EfinityのProgrammerで書き込もうとしたのですが、ここで3つほど問題があります。

  1. デバイスドライバがちゃんと用意されていないのでlibusbを使え
  2. libusbのインストールにはZadigという謎ツールを使え
  3. ZadigはVID=0403 PID=6010のドライバをlibusbに変えてしまうから、そのポートではFTDIのドライバが使えなくなること

Zadig

評価キットに乗っているUSB-JTAGのICはFTDIのFT2232HだからMPSSEが使えるのに、わざわざlibusbに置き換えるというデグレーションを強制されるのです。

それに、このZadigというのは非常に危険なツールでUSB関係のデバイスドライバを何でも置き換えてしまいます。本来はデバイスやデバイスドライバの開発者向けのツールなのでFPGAの開発をしたい一般ユーザが使うべきツールじゃありません。マウスのドライバをlibusbに置き換えてしまって、マウスが使えなくなり、大変苦労しました。本当にZadigはやめたほうがいい。

Zadig2

FT2232Hを使っているとUSBのデバイスが2つ見えるわけなのですが、Interface 0かInterface 1のどちらがJTAGになっているのか(もう一方はUARTか?)、わからないのです。それでもこの危険なツールを使わないとプログラミングできないので仕方がないのですが・・

私としては、FT2232HをMPSSEで接続して、TrionをJTAGコンフィグできるツールを作りたい。

最後の極めつけはEfinity Programmerでbitファイル(またはhexファイル)を読み込んで、JTAGモードに切り替えるとクラッシュします。

Efinityprogrammer

何のエラーメッセージも出さずに静かにクラッシュします。

Efinityをインストールしたフォルダのbin\efinity_pgm.batにプログラマを起動するバッチファイルがあるので、ここから起動してJTAGモードに切り替えると、

Pgmerr

そのためJTAG書き込みは一度も成功していません。

 

SPI ROMに書き込むのは1度だけ成功しましたが、とにかく安定性が悪すぎます。

致命的なバグとしては、

  • BitStreamが生成されない(bitファイルの中身はHEXファイル)
  • bitまたはHEXを書き込もうとするとProgrammerがクラッシュする

ということでした。

もう少し何とかしてほしいです。

<<追記 2022.2.6>>

JTAG書き込みでクラッシュする件の原因がわかりました。幸いなことにEfinityのIDEはPythonで書かれているようで、クラッシュしている個所を突き止めることができました。

D:\Efinity\2021.2\pgm\bin\efx_pgm\main_window.py の1021行目

try:
idcode = self.read_idcode(None, 1)
self.cb_chip_num.addItem('0x%08x' % int(idcode))
except ValueError as exc:
self.logger.debug(str(exc))
self.cb_chip_num.addItem('Default')

のidcodeが正しい値が入らないようなのですが、おそらく、このidcodeというのはJTAG Chain File (xml)の中に書かれたIDCODEの値です。ですから、この値が正しく取得できないとクラッシュするようです。

 

Efinity Programmerで書き込む前に、以下のようなJTAGチェーンの構造を記したXMLファイルを作っておきます。

<?xml version="1.0"?>
<chain>
<device chip_num="1" id_code="0x00220a79" ir_width="4" istr_code="1100" />
</chain>

上のid_codeの部分はデバイスに応じたIDCODEを記述します。そして、Programmerが起動したら、File→Import JTAG Chain Fileで上のXMLファイルを読み込んで、次にBitStreamを読み込みます。

Pgmr_20220206171501

この状態でJTAGモードを選択するとクラッシュしないようでした。

それでもJTAGで書き込もうとするとクラッシュします。まだ、何かが足りないようです。

| | コメント (0)

2022.02.03

Trion T20のバウンダリスキャンの問題を解決した

それではMITOUJTAGを使ってTrion T20のJTAGを解析していきます。

Do_svf

ここではBSDLファイルに記載されているIRやDRの長さが信用できないものと仮定して、IRやDRの長さを求めるというレベルのデバッグを行います。

MITOUJTAGのSVFプレイヤーを起動して、下記のとおり打ち込みます。

STATE RESET;
SIR 64 TDI (FFFFFFFFFFFFFFFF) PRINT;
SIR 64 TDI (FFFFFFFFFFF0FFFF) PRINT;

上の「PRINT」というのはSVF自体にはない命令で、MITOUJTAGのSVFプレイヤーで拡張されたものです。取得したTDOのビット内容を表示するというものです。このSVFを実行すると、

2022/02/03 15:53:14 Line 2 : TDO(captured)='FFFFFFFFFFFFFFF5'
2022/02/03 15:53:14 Line 3 : TDO(captured)='FFFFFFFFFF0FFFF5'
2022/02/03 15:53:14 SVFの実行が完了しました

IRの長さを64と仮定してFFFFF・・・を送っています。こうすると、万が一変な命令コードを送っていたとしても全部のビットが1なのでBYPASSになって、IRの長さを安全に測れるというわけです。

出てきた結果は下4桁が"0101"でした。途中で"0000"をはさむとその"0000"は4ビットシフトして出てくるので、IRの長さは4bitで、平常時のIR CAPTURE CODEは0101で間違いないでしょう。しかし、電源投入後1回目のIRの値は"1111"になるので、XXX1にするのが正しいのだと思われます。

次に、

STATE RESET;
SIR 4 TDI (3) PRINT;
SDR 64 TDI (FFFFFFFFFFFFF5aF) PRINT;

を実行して、IDCODEが正しく取得できるかどうかを試してみます。3というのがIDCODEのコマンドです。

結果は、

2022/02/03 16:07:37 SVFの実行が完了しました
2022/02/03 16:08:00 Line 2 : TDO(captured)='5'
2022/02/03 16:08:00 Line 3 : TDO(captured)='FFFFF5AF00210A79'

で、正しいIDCODEが得られ、長さは32bitでした。

そして、次のコードを実行します。これはSAMPLE/PRELOADコマンド(2)を実行し、100msごとに700ビットのデータを取得して画面に表示します。

STATE RESET;
SIR 4 TDI (2) PRINT;
SDR 700 TDI (F) PRINT;
RUNTEST IDLE 100000;
SDR 700 TDI (F) PRINT;
RUNTEST IDLE 100000;
SDR 700 TDI (F) PRINT;
RUNTEST IDLE 100000;
SDR 700 TDI (F) PRINT;
RUNTEST IDLE 100000;
SDR 700 TDI (F) PRINT;
RUNTEST IDLE 100000;
SDR 700 TDI (F) PRINT;
RUNTEST IDLE 100000;
SDR 700 TDI (F) PRINT;
RUNTEST IDLE 100000;
SDR 700 TDI (F) PRINT;
RUNTEST IDLE 100000;
SDR 700 TDI (F) PRINT;
RUNTEST IDLE 100000;
SIR 4 TDI (F) PRINT;

結果は、

2022/02/03 16:09:51 Line 3 : TDO(captured)='00034003D20DB6DB6DB4D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB69B69B6DB6DB6DB6DB6DB6DBEED6DB6DB6DDADB6DB6D24DB6DB6DB6DB6DB6DD003680000000000000000000000000000000000000001'
2022/02/03 16:09:52 Line 5 : TDO(captured)='00034003D20DB6DB6DB4D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB69B69B6DB6DB6DB6DB6DB6DBEC06DB6DB6DDADB6DB6D24DB6DB6DB6DB6DB6DDB6B680000000000000000000000000000000000000001'
2022/02/03 16:09:52 Line 7 : TDO(captured)='00034003D20DB6DB6DB4D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB69B6DB6DB6DB6DB6DB6DB6DBEC06DB6DB6D80DB6DB6D24DB6DB6DB6DB6DB6D816B680000000000000000000000000000000000000001'
2022/02/03 16:09:52 Line 9 : TDO(captured)='00034003D20DB6DB6DB4D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB69B6DB6DB6DB6DB6DB6DB6DBEED6DB6DB6DD0DB6DA6D24DB6DB6DB6DB6DB6D8002680000000000000000000000000000000000000001'
2022/02/03 16:09:52 Line 11 : TDO(captured)='00034003D20DB6DB6DB4D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB69B6DB6DB6DB6DB6DB6DB6DBEED6DB6DB6DDADB6DB6D24DB6DB6DB6DB6DB6DDB6B680000000000000000000000000000000000000001'
2022/02/03 16:09:53 Line 13 : TDO(captured)='00034003D20DB6DB6DB4D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB69B6DB6DB6DB6DB6DB6DB6DBEC06DB6DB6D80DB6DA6D24DB6DB6DB6DB6DB6D8B6A680000000000000000000000000000000000000001'
2022/02/03 16:09:53 Line 15 : TDO(captured)='00034003D20DB6DB6DB4D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB69B6DB6DB6DB6DB6DB6DB6DBEED6DB6DB6D80DB6DB6D24DB6DB6DB6DB6DB6D8003680000000000000000000000000000000000000001'
2022/02/03 16:09:53 Line 17 : TDO(captured)='00034003D20DB6DB6DB4D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB69B69B6DB6DB6DB6DB6DB6DBEED6DB6DB6DDADB6DB6D24DB6DB6DB6DB6DB6DDB42680000000000000000000000000000000000000001'
2022/02/03 16:09:53 Line 19 : TDO(captured)='00034003D20DB6DB6DB4D26DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB6DB69B6DB6DB6DB6DB6DB6DB6DBEC06DB6DB6D80DB6DA6D24DB6DB6DB6DB6DB6DDB6A680000000000000000000000000000000000000001'

でした。

わかりにくいので右端のほうを見て見ると、右の42文字は変化しておらず、その左から5bit程度が変化していることがわかります。

Bit168

DB6A、BD03、D002・・・と変化しているようでした。

この部分はbit168に対応するのですが、BSDLファイルを見て見ると168bit目はIO_GPIOL_48でC3番ピンの割り当てでした。

Bsdl168

もしかするとLSBとMSBの順序が逆になっているかもしれないと思い、665-168=497なので、497bit目から見てみるとビンゴ!

"489 (BC_2, IO_GPIOR_155, output3, X ,490 , 1, Z)," & -- PAD 164
"490 (BC_2, *, control, 1)," &
"491 (BC_2, IO_GPIOR_155, input, X)," & -- PAD 164
"492 (BC_2, IO_GPIOR_156, output3, X ,493 , 1, Z)," & -- PAD 165
"493 (BC_2, *, control, 1)," &
"496 (BC_2, IO_GPIOR_156, input, X)," & -- PAD 165
"495 (BC_2, IO_GPIOR_157_PLLIN, output3, X ,496 , 1, Z)," & -- PAD 166
"496 (BC_2, *, control, 1)," &
"497 (BC_2, IO_GPIOR_157_PLLIN, input, X)," & -- PAD 166

ここにGPIOR_156がありました。GPIOR_157はクロック入力のようなので、ここが遷移しているのは入力ピンだからのようです。

 

そして、BSDLファイルを修正して、0と665を入れ替えたものを作り、それを読み込んでスキャンしてみると・・

Allinput

LEDの端子の位置は正しくなったものの、入力端子として扱われています。

その理由はBSDLの番号をひっくり返したのに対応するccellの値を変えていなかったからです。番号を反転させてccellも入れ替えると、ようやく正しくバウンダリスキャンができるようになりました。disvalの値が違っているのではないかと思ったのですがdisvalは正しいようです。

Correct_scan

E8、H13、L13が入力状態でチカチカしているのですが、H13とL13は50MHzのクロック入力とPLL入力、E7は74.25MHzのクロック入力だからです。

BSDLファイルに記載されたBSRのMSBとLSBを入れ替えることで正しくバウンダリスキャンができるようになります。

公式が出しているBSDLは12/14/2018にリリースされてから3年経っているので、いままでバウンダリスキャンした人は今まで一人もいなかったのかもしれないと思うと、バグ報告を出すのがワクワクしてきます。

 

| | コメント (0)

2022.02.02

Efinix Trion T20とT120のDevelopment Kitを試す

Efinix Trionの評価ボードを購入しました。EfinixというのはXILINXも出資している振興FPGAベンダで、TrionとTitaniumというFPGAを販売しています。性能はTitaninumのほうがTrionより上のようです。

購入したのはTrion T20のボードとT120のボード。Trion T20 BGA256 Development Kitと、Trion T120 BGA576 Development Kitです。

Triondevkit

 

Trionの統合開発環境(Efinity IDE)やBSDLファイルをダウンロードするにはユーザ登録が必要で、ボード箱の裏面に書かれているシリアル番号を入れると登録できるようです。

シリアル番号が承認されるには20時間くらいかかるので、使いたいときに登録するのではなく、買ったらすぐに登録したほうがよいでしょう。

登録が完了するとメールが送られてきて、開発ソフトやBSDLファイルがダウンロードできるようになります。

Bsdls

この評価ボードにはFT2232Hが乗っていて、FTDIのMPSSEのピン配置でUSB-JTAGを実現しています。

Usbjtag

そのため、MITOUJTAGをつないで、ケーブルにMPSSEを選択するだけで接続ができるはずです。

Select_mpsse

デバイスの自動認識を行うと、未定義のデバイスとして認識されます。

Unknown_device

そこで、Trion T20のBSDLファイルをダウンロードしてきて、画面にドラッグ&ドロップで落とします。

Addbsdl

新規のデバイスとして登録されるために「はい」を押します。

これで自動認識してみると無事に認識はされるのですが、

Detected

スキャンをしようとしてみると、エラーが出ます。

Error

エラーの原因は、取得されたデバイスのIR CAPTUREの値が違っているためです。

Devprop

 

最初にキャプチャされたIRは1111なのですが、BSDLファイルには0001と書かれています。

attribute INSTRUCTION_CAPTURE of T20_FBGA256 : entity is "0001";

T20_FBGA256.bsdの555行目を

attribute INSTRUCTION_CAPTURE of T20_FBGA256 : entity is "XXX1";

に書き換えて再度、BSDLファイルを登録して自動認識させます。

これで認識はするようになるのですが、バウンダリスキャンをしてみると、やはりおかしい。

LEDの動きに連動してA2、B3、C4、D5あたりのピン(下の図で赤枠で囲った部分)動いているのですが、

Bscan_20220203153201

回路図を見ると、LEDにつながっている信号はD14、E13、G13、F14、N14、N16、P15、M14なんですよね。

Leds

Schem_20220203153501 

Schem2_20220203153601

ロジアナモードで見てみても、A2、B3、C4、D5あたりが動いています。

Logana

 

T20がおかしいのかもしれないので、T120の評価ボードでも試してみました。

T120

T120もIR CAPTUREのコードをXXX1に書き換えることで自動認識とチェックが通るようになりますが、バウンダリスキャン結果は正しくなさそうな結果でした。

T120scan_20220203154001

JTAGロジアナで見ると、多くの端子で入力/出力の方向が切り替わっています。

Loganat120

これは、おそらくバウンダリスキャンセルの位置が合っていない状況が考えられます。

 

というわけで、Trionをバウンダリスキャンする上で見つかった問題点は2つです。

  • BSDLファイルに記述されたIR CAPTUREの値が正しくない
  • バウンダリスキャンの結果が出てくるセルの値がおかしいように見える

T20はバウンダリスキャンセル長が666なのですが、もしかすると、BSDLファイルに記載されているMSBとLSBが逆になっているのかもしれません。

明日、より詳しく調査してみます。

 

| | コメント (0)

2022.02.01

高速パルス発生回路の完成

ついにできました。

立ち上がり時間400psの高速パルスで同軸ケーブルを駆動できる回路です。

Highspeed_pulse

ADCMP553の出力にトランジスタ付けてエミッタフォロアで出力したものです。エミッタフォロアは常に49.9Ωの負荷抵抗をいつも駆動するようにしておいて、出力はコンデンサでDCをカットして取り出します。

 

この出力をオシロで測るときにはオシロの入力をDC 50Ωモードにしておきます。

パルスの全体は下の図のように矩形波ですが、

Trig01uf

立ち上がり部分は約400ps

Trig01ufrise

立下りは約500psと、

Trig01uffall

ほぼ目的通りの性能が出ました。

これなら反射の測定にピッタリです。

| | コメント (0)

« 2022年1月 | トップページ | 2022年3月 »