2021.09.21

Cosmo-ZとNaIで、ポジトロンのピークを見る

陽電子を放出する18F の放射線源が手に入ったので、NaIシンチレータ+PMTをCosmo-Z (Mini) につないで測ってみることにしました。

まず最初の感想として、すげー!のひとこと。

いままで宇宙線ばかり見てきたけれど放射性同位元素はやっぱり違う。シンチレータを近づけると毎秒20万カウント。家の中に帰って来るだけでカウント数が跳ね上がる。宇宙線やコンクリからのバックグラウンドが毎秒80カウントくらいしか出ていなかったので、いままで見たことのないカウント数。イベントカウンタを32bitにしておいてよかった。

まずは、18Fのない状態。4時間程度測っています。見えているのは40Kのピークのみ。

40k

次に、かなり遠い場所に18Fがある場合。1046秒測定。

18f_1

新たに表れたのが511keVのピークでしょう。

ここまでの解析はオフライン解析だったので、Cosmo-ZのFPGAを入れ替えてリアルタイムに見えるようにしてみます。

まず、18Fの線源から1メートルくらい離したときの計測。計測時間は178秒。

Direct_1

次に直近まで近づけたとき。わずか25秒でこのカウント数。うひょ。

Direct_2

さて、よくみるとピークの位置がすこし右側にずれています。

これはなんだろうということで生の波形を見てみると、パイルアップが多く起きていました。

Pileup

パイルアップが起きない程度に離さないとピークの位置がずれますね。

あと、1us程度の幅の信号を80MHzでサンプリングしているのでノイズによるガタガタが目立ちます。波高値のみを見ているのでMCAのピークの幅が増えるという精度が悪化の原因になっているはずです。

そういうわけでTiming Filter AmpとBaseLineRecovererをONにしてみました。

Tfablr

波形がつるつるになってノイズが減っているわけですが、積分回路に通してこの波形をつくっているわけなので時系列的に見れば全体を平均化した値からピーク値を推定していることになるのでしょう。

TFAとBLRをONにしてMCAで測ってみたスペクトラムです。

Tfablr2

少しだけ半値幅が減ったような気がしますが、パイルアップは消せません。

Cosmo-Zの次の目標としては、カウントレートが高い場合にパイルアップを消すためのフィルタを作るということと、リアルタイムMCAの使い勝手を向上させることだと思います。

 

さて、だいぶん一通りデータが取れたので、夜9時ごろの我が家の放射線のスペクトルを見てみます。

511keVと1461keVのピークがはっきりわかります。NaIの較正ができそうですね。

Tfablr3

最後に翌朝に家の中を取ったものです。18Fの半減期は100分程度なので、翌朝にはほとんど残っていませんでした。

Nextmorning

1日でほとんどすべて消えるというのも素晴らしいですね。

 

| | コメント (0)

2021.09.17

ZYNQのLinuxのハードウェア初期化用にsystemdで起動するサービスを作る

TCP/IPのリモート接続を待つサーバプログラムの起動や、ZYNQのハードウェアの初期化を行うためのプログラムを、これまで/etc/rc.localに書いてきましたが、rc.localに書くのは現在のLinuxでは非推奨であるようです。

やりたいことは2つあって、1つ目はTCP/IPのサーバを起動すること。もう一つはLinuxの起動時に1回だけ初期化を行うことです。TCP/IPのサーバなんかは予期せず停止した場合に再起動してくれるとありがたいです。それぞれ、cszserverとcszinitというサービスを作ることにします。

こういったことをするのにsystemdとかsystemctlといった仕組みを使うのがモダンな方法なので、その方法を調べてみました。

最初にやることはスクリプトを作ることです。

まず、TCP/IPのサーバプログラムのcszserverという実行ファイルがあって、これを起動するためのスクリプトを/opt/cszserver.shに作ります。

#!/bin/bash
/usr/local/bin/cszserver 1069

次に、1回だけ起動するスクリプトを/opt/cszinit.shとして作ります。

#!/bin/bash
/bin/chmod 666 /dev/uio0
/bin/chmod 666 /dev/uio1
/bin/echo enabled > /sys/devices/soc0/amba/e0000000.serial/tty/ttyPS0/power/wakeup
/home/share/autorun

cszinit.shでは、UIO(ユーザIOドライバ)を、一般ユーザでも使えるように実行権限を設定しているのと、ZYNQの低消費電力モードからの復帰機能を有効にしていること、それから、/home/share/autorunというスクリプトを起動しています。

シェルスクリプトファイルを作ったら実行権限を設定します。

$ chmod 755 /opt/cszserver.sh chmod 755 /opt/cszinit.sh

次に、/etc/systemd/system/にサービスの設定ファイルを書きます。

まずは、繰り返し起動したいサービスの定義、/etc/systemd/system/cszserver.service を書きます。

[Unit]
Description = Cosmo-Z API relay server
[Service]
ExecStart = /opt/cszserver.sh
Restart = always
Type = simple
[Install]
WantedBy = multi-user.target

この意味ですが、ExecStartでは先ほど作った起動スクリプトを指定し、Restart=alwaysでは、停止したら自動再起動することを指定します。type=simpleやWantedByの設定は深く考えなくてよいでしょう。

次に1回だけ起動したサービスの定義、/etc/systemd/system/cszsinit.service を書きます。

[Unit]
Description = Cosmo-Z initialize
[Service]
ExecStart = /opt/cszinit.sh
Restart = no
Type = oneshot
[Install]
WantedBy = multi-user.target

ExecStartと、RestartとTypeのところが異なります。

こうして/etc/systemd/systemの下に.serviceファイルを作ったら、

# systemctl list-unit-files --type=service | grep csz

でcszが付くサービスの一覧を表示させてみます。

root@cszmini:~# systemctl list-unit-files --type=service | grep csz
cszinit.service disabled
cszserver.service disabled

設定ファイルを作っただけなのでdisabledとして表示されました。

これらのサービスを有効にするにはsystemctl enable cszserverとsystemctl enable cszinitを実行します。

systemctl enable <サービス名>を実行するとシンボリックリンクが作成されます。

root@cszmini:~# systemctl enable cszserver
Created symlink /etc/systemd/system/multi-user.target.wants/cszserver.service → /etc/systemd/system/cszserver.service.
root@cszmini:~# systemctl enable cszinit
Created symlink /etc/systemd/system/multi-user.target.wants/cszinit.service → /etc/systemd/system/cszinit.service.

そして、 systemctl start  cszserver と systemctl start cszinit を実行すれば、これらのサービスが起動します。

rebootしても自動的に起動するようになります。

systemdに登録して嬉しいことは、システムにちゃんとサービスとして登録されているため、systemctl status で表示されて「しっかりした製品だなという印象」を与えられること、

Cszserver

それから、サービスが予期せず停止してもすぐに再起動してくれることです。ためしにkill -9 でシグナルを送ってみるとすぐに再起動してくれます。

この自動再起動という特徴は、ハードウェアの監視や、リソースの管理プログラムを作る場合にはかなり重要です。

まとめると、

  • /opt あたりにサービスのシェルスクリプトを作って、実行権限を付与する
  • /etc/systemd/system/<サービス名>.service を作る
  • systemctl enable <サービス名> でインストールされる
  • systemctl start <サービス名> で起動される

ということです。.serviceファイルの中の書き方次第で、強制再起動にもワンショットにもすることができます。

 

| | コメント (0)

2021.09.11

WindowsがLinuxマシンのMDNSで遅くなる原因?

組み込みLinuxのマシンの名前を「ホスト名.local」で解決しようとして1秒待たされる原因は、どうやらLinuxが返すMDNSのパケットの違いにあることがわかってきました。

 

ZYNQの組み込みLinuxに対するPINGを無線LANでやってみしたところ、なんと、この1秒待たされる現象が発生しないことがわかりました。次の図はPINGを打ったときのパケットの解析です。Windowsマシンは最初、IPv4とIPv6の双方で、IPv4アドレスとIPv6アドレスを調べようとして4個のqueryを出しています。

Avahiwifi0

それに対してLinuxマシンは

  • IPv4パケットに乗せたIPv4アドレス
  • IPv4パケットに乗せたIPv6アドレス
  • IPv6パケットに載せたIPv6アドレス

という3つのresponseを返しています。

この3つ目のレスポンスが帰ると即座にPINGのパケットが出始めます。

 

一方、同じ組み込みLinuxのマシンでも有線LANでつないだ場合は、「IPv6パケットに乗せたIPv6アドレス」の応答が出てこないのです。

Wiredlanresponse

これゆえWindowsはgetaddrinfo()で1秒間のタイムアウトをするまで待たされるのだと思われます。

 

では、Linuxのavahi-daemonが有線LANでバグっているのかというと、そういうわけではなさそうです。Linux側でtcpdumpをしてみると、

01:20:38.768658 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 A (QM)? cszmini.local. (31)
01:20:38.770990 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 1/0/0 (Cache flush) A 192.168.1.12 (41)
01:20:38.771974 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 A (QM)? cszmini.local. (31)
01:20:38.774358 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:20:38.776324 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:20:38.777309 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 1/0/0 (Cache flush) AAAA fe80::11:10ff:fe00:2201 (53)
01:20:38.789419 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 A (QM)? cszmini.local. (31)
01:20:38.792155 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 A (QM)? cszmini.local. (31)
01:20:38.794569 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:20:38.796814 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:20:39.803426 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 A (QM)? cszmini.local. (31)
01:20:39.805998 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 1/0/0 (Cache flush) A 192.168.1.12 (41)
01:20:39.809007 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 A (QM)? cszmini.local. (31)
01:20:39.811748 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:20:39.813931 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:20:39.816796 IP 192.168.1.4 > cszmini: ICMP echo request, id 1, seq 16515, length 40
01:20:39.818957 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 1/0/0 (Cache flush) AAAA fe80::11:10ff:fe00:2201 (53)
01:20:39.821750 IP cszmini > 192.168.1.4: ICMP echo reply, id 1, seq 16515, length 40

と、IP6でcszminiがソースになっているものがありません。

一方、無線LANのほうもtcpdumpしてみると、

01:23:44.921998 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 A (QM)? cszmini.local. (31)
01:23:44.924618 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 1/0/0 (Cache flush) A 192.168.1.10 (41)
01:23:44.927949 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 A (QM)? cszmini.local. (31)
01:23:44.930494 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:23:44.933371 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:23:44.934356 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 2/0/0 (Cache flush) AAAA 240b:10:ae21:3f00*****, (Cache flush) AAAA 240b:10:ae21:3f00:***** (81)
01:23:44.936394 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 A (QM)? cszmini.local. (31)
01:23:44.937727 IP6 cszmini.mdns > ff02::fb.mdns: 0*- [0q] 2/0/0 (Cache flush) AAAA 240b:10:ae21:3f00*****, (Cache flush) AAAA 240b:10:ae21:3f00:***** (81)
01:23:44.940091 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 A (QM)? cszmini.local. (31)
01:23:44.942336 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:23:44.944420 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
01:23:44.946751 IP6 fe80::*************** > cszmini: ICMP6, neighbor solicitation, who has cszmini, length 32
01:23:44.949187 IP6 cszmini > fe80::***************: ICMP6, neighbor advertisement, tgt is cszmini, length 24

となっていて、IPv6のパケットでMDNSを返しているんですね。 

ネットワークの問題でパケットがロスしているわけではなくて、有線LANでは本当にIPv6のパケットが出ていなかったのです。

マジか?と思ってip aしてみると、

root@cszmini:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
link/sit 0.0.0.0 brd 0.0.0.0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 02:11:10:00:22:01 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.12/24 brd 192.168.1.255 scope global dynamic eth0
valid_lft 3069021764sec preferred_lft 3069021764sec
inet6 fe80::11:10ff:fe00:2201/64 scope link
valid_lft forever preferred_lft forever

特に問題はなさそうなのですが、MACアドレスがプライベートMACアドレスなのが気になります。そのせいかIPv6のアドレスにはリンクローカルなアドレスしかありません。試しに02:11:10:00:22:01という設定を00:11:10:00:22:01に変更してみたところ、リンクローカルではないIPv6アドレスが生成されるようになって、

root@cszmini:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1
link/sit 0.0.0.0 brd 0.0.0.0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 10:11:10:00:22:01 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.14/24 brd 192.168.1.255 scope global dynamic eth0
valid_lft 3068829252sec preferred_lft 3068829252sec
inet6 240b:10:ae21:3f00:1211:10ff:fe00:2201/64 scope global dynamic mngtmpaddr noprefixroute
valid_lft 3068829252sec preferred_lft 3068829252sec
inet6 fe80::1211:10ff:fe00:2201/64 scope link
valid_lft forever preferred_lft forever

PING -6 cszmini.localとやってみたところ、IPv6でのMDNSもちゃんと返していることがわかりました。

02:43:58.853565 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31) // 1度目のQUERY
02:43:58.855804 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
02:43:58.855992 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 1/0/0 (Cache flush) AAAA 240b:10:ae21:3f00:1211:10ff:fe00:2201 (53)
02:43:58.859651 IP6 cszmini.mdns > ff02::fb.mdns: 0*- [0q] 1/0/0 (Cache flush) AAAA 240b:10:ae21:3f00:1211:10ff:fe00:2201 (53)
02:43:58.888202 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31) // 2度目のQUERY
02:43:58.890554 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
02:43:59.893692 IP 192.168.1.4.mdns > 224.0.0.251.mdns: 0 AAAA (QM)? cszmini.local. (31) // 3度目のQUERY
02:43:59.896185 IP6 fe80::***************.mdns > ff02::fb.mdns: 0 AAAA (QM)? cszmini.local. (31)
02:43:59.898695 IP6 cszmini.mdns > ff02::fb.mdns: 0*- [0q] 1/0/0 (Cache flush) AAAA 240b:10:ae21:3f00:1211:10ff:fe00:2201 (53)
02:43:59.901480 IP6 240b:10:ae21:3f00:*************** > cszmini: ICMP6, echo request, seq 178, length 40
02:43:59.904150 IP6 cszmini > 240b:10:ae21:3f00:***************: ICMP6, echo reply, seq 178, length 40
02:43:59.907243 IP cszmini.mdns > 224.0.0.251.mdns: 0*- [0q] 1/0/0 (Cache flush) AAAA 240b:10:ae21:3f00:1211:10ff:fe00:2201 (53)
02:44:00.908804 IP6 240b:10:ae21:3f00:*************** > cszmini: ICMP6, echo request, seq 179, length 40
02:44:00.910919 IP6 cszmini > 240b:10:ae21:3f00:***************: ICMP6, echo reply, seq 179, length 40

ただし、これを直してもWindowsのgetaddrinfo()が1秒待つ動作は治りませんでした。上のパケットキャプチャを見てもQUERYを3回も発行しています。IPv6のMDNSが返らないからというわけではなさそうです。まだ何か見落としているところがあるのでしょう。

もしかすると、あまりにも早く返ってきたMDNSのレスポンスは見れないのかもしれません。

そしてMACアドレスがプライベートアドレスならIPv6のMDNSを返さないというavahi-daemonの動作も十分に怪しいのですが、Windowsのgetaddrinfo()はNETBIOSやIPv4のMDNSなど他の手段でアドレスが得られているのに、わざわざIPv6のMDNSレスポンスが得られるまで1秒待つ動作も相当にムダで謎であると思えます。

結局のところ根本原因はわかりませんでしたが、TCP/IPのプログラムを組む時にはIPv4しか使わないと決めているなら、getaddrinfo()の際にAF_INETを指定してIPV4に限定してしまったほうがよいでしょう。

 

| | コメント (0)

2021.09.10

WindowsでTCP/IPのプログラムを作ったときに名前解決を早くする

昨日の実験の結果では、WindowsのTCP/IPプログラミングではローカルネットワーク上のホスト名を名前解決をしようとしたときに、getaddrinfo()で1秒待たされてしまっていました。

長い間の試行錯誤の末、この「名前解決で1秒待たされる動作」を解決する方法がわかりました。

普通にgetaddrinfoを使ったプログラムは、

struct addrinfo hints, * res;
memset(&hints, 0, sizeof(hints));
int err = getaddrinfo(host, NULL , &hints, &res);

のようになります。

getaddrinfo()にはこれといってオプションがないように見えるのですが、よく見たらhintsという引数があって、どんな体系のアドレスで解決するかのヒントを与えることができるようです。

これには全部ゼロである構造体を入れてもよいのですが、hints.ai_family = AF_INET;と指定すると、1秒待たされる動作をしなくなることがわかりました。

struct addrinfo hints, * res;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
int err = getaddrinfo(host, NULL , &hints, &res);

これは、AF_INET、つまりIPv4の範囲内で名前解決をしなさいとヒントを与えているわけです。

デバッガで実行してみると

Ipv4

29ミリ秒でgetaddrinfoが終了しています。

このような指定をしてもMDNSのパケットはIPv4とIPv6の両方で出るのですが、AAAAレコードの問い合わせをしなくなります。

Ipv4_2

逆に、AF_INET6だけを指定するとAAAAレコードでの問い合わせだけが出るようになって1秒待たされます。

実はわざわざプログラムを組まなくてもPINGコマンドで同様の実験ができます。

PING -6 ホスト名

とやると、AAAAレコードを使ったIPv6アドレスの解決のみを行い、

PING -4 ホスト名

とやると、Aレコードを使ったIPv6アドレスの解決のみを行います。

 

つまり、Windowsは、ZYNQ Linuxのavahi-daemonが返したMDNSのレスポンスの何かが気に入らなくて1秒間タイムアウトしていたと考えられます。

根本的な解決はまだですが、getaddrinfoの前にIPv4で解決する

hints.ai_family = AF_INET;

を付けるだけで、getaddrinfo()で待たされる時間が大幅に減り、アプリの起動時間が短縮できました。

続く

| | コメント (0)

2021.09.09

WindowsでTCP/IPのプログラムを作ったときに名前解決が遅い

ZYNQで組み込みシステムを作って、Windowsで作ったプログラムからネットワーク経由でコントロールしたい場合に、アプリを作ることになりますがが、ホスト名の名前解決で1秒くらい待たされる現象が起きていました。

状況としては、

  • ターゲットはZYNQ(ARM)で動作するLinuxの組み込みシステム。Ubuntu 18.04LTS。IPv6有効
  • ターゲットLinuxでは、mDNS用にavahi-daemon、NetBIOS用にnmbdを実行
  • ホストPCはWindows 10
  • ホストとターゲットは同一ネットワークの有線LANで、遅延は極めて少ない
  • DNSサーバは立てていない

です。

こういう環境で、Windowsのプログラムから組み込みLinuxをネットワーク越しでコントロールしようとすると、プログラムの起動時に名前解決で1秒ほど固まってしまうのです。

 

TCP/IPのプログラムを作る際に、ホスト名をIPアドレスに変換する名前解決にはgetaddrinfo()を使いますが、Visual Studioのデバッガでステップ実行してみるとgetaddrinfo()で1秒ほど待たされていることがわかりました。

このgetaddrinfo()は、"cszmini"みたいなホスト名から192.168.1.12のようなIPアドレスに変換してくれます。

Getaddrinfo

getaddrinfo()はプログラムの起動時に必ず実行するので、1秒間ひっかかるような動作をしてしまいます。

 

自作プログラムの固まる箇所はgetaddrinfo()にあることがわかったのですが、どうやら普通にpingを打つだけでも同様に最初に1秒間固まることがわかってきました。

しかしながらpingで固まるのは最初のICMPの送信が始まる前なので、PINGの遅延時間に表示されません。

Ping

おそらくPINGというシステムツールも、中ではgetaddrinfo()を呼び出しているのでしょう。getaddrinfo()のほかにGetAddrInfoEx()というAPI関数もあるのですが、結果は同じでした。要するにWindowsの名前解決では、ローカルネットワークで隣にある機械の名前解決に必ず1秒待たされるのです。

MS-DOSプロンプトを開いてping cszminiと打って、Wiresharkでパケットをキャプチャして調べてみると、DNS、mDNS、NETBIOSと3つの方法で調べていることがわかります。

Dns

上のパケットで何が起きているかを説明しますと、

  • WindowsからデフォルトゲートウェイにDNSで「cszmini.ドメイン」を知らないかを問い合わせ
  • ローカルのネットワークにIPv4のMDNSで「cszmini.local」のホストがいないかをAレコード(IPv4)問い合わせ
  • ローカルのネットワークにIPv6のMDNSで「cszmini.local」のホストがいないかをAレコード(IPv4)問い合わせ
  • ローカルのネットワークにIPv4のMDNSで「cszmini.local」のホストがいないかをAAAAレコード(IPv6)問い合わせ
  • 192.168.1.12のターゲットからレスポンスあり
  • デフォルトゲートウェイから「cszmini.ドメイン」という名前のホストは、ネットワークの外にはないと返事
  • NetBIOSでCSZMINIがいないか問い合わせ
  • 再びローカルのネットワークにIPv4とIPv6のMDNSで「cszmini.local」のホストがいないかをAレコード(IPv4)およびAAAAレコード(IPv6アドレス)問い合わせ
  • NetBIOSでの返事あり
  • 再びローカルのネットワークにIPv4とIPv6のMDNSで「cszmini.local」のホストがいないかをAレコード(IPv4)およびAAAAレコード(IPv6アドレス)問い合わせ
  • MDNSでの返事あり

という感じでした。PINGを起動したときから名前解決が走っているのですが、このプロセスが終了するまでに1.03秒かかっていることがわかります。しかもMDNSではすぐにAレコードとAAAAレコードを返している(17番と19番)のですが、Windowsはこれを無視してしまっています。

上の過程では、デフォルトゲートウェイに向けてDNSを送っていてわかりにくいので、DNSとPINGに絞ってみます。

Windowspingpacket_20210912002101

PING開始時にMDNSを使って「cszmini.local」がいないかどうかを調べているのですが、1.37秒付近で名前解決を開始して、実際にPINGが飛んでいるのは2.39秒なので、名前解決で1.02秒待っていることがわかります。おそらく、MDNSのタイムアウトが1秒になっているのでしょう。

このようにターゲット機器がMDNSでホスト名を返しているし、NetBIOSでもホスト名を返しているのですが、Windowsのgetaddrinfo()は1秒ほど待つようになっていて、極めて体感速度が遅く感じられてしまうのです。

続く

| | コメント (0)

2021.08.24

USB Type-Cの徹底解説^H^H解析(2)

市販のUSB3.0対応のA-Cケーブルを切って確認した結線図を示します。なお、GNDとD+/D-は省略しています。プルアップ抵抗はUSB Type-Cの黒い部分に入っているようです。

Typec3_20210824195801

2ペアある高速差動信号は、TX1/RX1側を使うか、TX2/RX2側を使うかはケーブルによってさまざまで両方のタイプがあります。TX1/RX1を使うほうはCC1とVBUSの間にプルアップ抵抗が入っています。

いずれもUSB 3.0のType A-Cケーブルは、TX1/RX1かTX2/RX2のどちらか一方の配線しか使っていません。使っている側のCCをプルアップ、使っていない側のCCは無接続でした。

なので、デバイス側(自作機器)で片側しかつながない場合、ケーブルの裏表が一致すればうまく通信できますが、

Typec4_20210824195101

裏返ってしまうと高速差動通信ができなくなってしまいます。

Typec5

USB2.0のD+/D-は接続されているのでUSB2.0では通信可能です。

裏返った場合、CCのプルダウンが無接続になるので、ホストがしっかりしていれば電力を供給してくれないかもしれません。私が試した環境ではType-A Cで変換していて所詮はType-Aなので電力は供給してくれますが、Type-C Type-Cでつなぐとダメかもしれませんね。

結論を言うと、

  • USB3.0に対応したデバイス(機器)を作る場合は、片側だけ結線しておくのはダメ
  • ちゃんとマルチプレクサ(スイッチャ)を使って両方をつなぐべき

特定の顧客向けの機器で「速度が出なければ裏返してください」で許してくれるならば片側結線でもいいんじゃないかと思いますが、市販する装置を作る場合はちゃんとマルチプレクサを使いましょう。

問題は、今の半導体不足の世の中でUSB 3.0のマルチプレクサが手に入るかどうかなんですよね・・・

 

| | コメント (0)

2021.08.23

USB Type-Cの徹底解説^H^H解析(1)

トラ技2020年2月号にUSB Type-Cの徹底解説という特集がありますが、これを読んでも、USB Type-Cの使い方が全然わからないので、自分で調べることにしました。

私が本当に知りたいことは「USB3.0 SuperSpeedで動くType-Cのターゲット側を自作する場合の結線方法」なのですが、トラ技を読んでもケーブルの作り方と、USB2.0機器の結線方法、USB3.0のEZ-USB FX3をType-Bで使う記事はあるのですが、本当に知りたかったことは書いてありませんでした。(せっかくEZ-USB FX3を使うならば、FX3のターゲットボードを自作してType-Cのコネクタを乗せるくらいのことはしてほしかったのですが・・・)

さらに、もっと知りたいことは、「USB 3.1 Type-C 機器を作るに場合には、マルチプレクサは絶対に使わなきゃいけないのか?」ということです。

直結するのはNGだとしても、片側だけつないでおけばなんとかならないだろうか・・ということです。だいいち、世の中のUSBホストなんてほとんどがType-Aで、変換ケーブルかましてType-Cにしているわけですから、高速差動配線なんて所詮片側しか使っていないんです。

 

というわけで、秋葉原に行って使えそうなアイテムを買ってきました。

Typec1_20210824182401

USB 3.0のType-A C変換ケーブル、秋月のUSB Type-C変換基板、USB 3.0のType-B C変換ケーブルです。

秋月の変換基板はこれ。(ピンヘッダは付けていません。)

Akitypec

千石で買った変換ケーブルの中で、Type-BとCの変換というのがあって、これがすごく役立ちました。

Typec2_20210824182401

どう役立ったかというと、ケーブルをバラします。

Typec3_20210824182401

そしてUSB 3.0のType-Bが出ているFPGA評価ボードに挿して、どこに配線がつながっているかを調べます。

Typeb

 

次にUSBケーブルのType-C側を秋月の変換基板に挿して、配線の色と端子の照合を行います。

Typec4

結果は

赤:VBUS 黒:GND 緑:D+ 白:D- 青:RX2- 黄色:RX2+ 橙:TX2+ 紫:TX2- 透明:GND

でした。

CC2とVBUSの間には56kΩくらいの抵抗が入っているようです。

 

ケーブルの結線が分かったので、切断したケーブルのType-Bの側を変換基板に挿して動かしてみると・・・見事に失敗!

  • Type-Cをある側にしたときには、USB認識されず
  • Type-Cを裏返したときには、USB 2.0の速度しか出ない

でした。

もしやと思い、TXとRXを入れ替えてみると見事に動きました。(TXとRXをクロスしなければならないとは・・💦。Type-B-Cだから、か)

Typec6

速度もちゃんと346MByte/sとか、SuperSpeedの速度が出ています。

Typec7

ただしUSB Type-Cのコネクタを裏返すと、48MByte/sぐらいにまで落ちてUSB2.0になってしまいました。

それから、ケーブルのちょっとした状態の違いでUSB3.0の通信が不安定でエラーが頻発するときがあります。変換基板の配線が高速差動信号を考慮していないのが原因ではないかと思われます。

以上の結果から、市販の変換ケーブルの結線がどうなっているか、自作機器をどうすればよいかがわかってきました。

続きは明日のブログで!!

| | コメント (0)

2021.08.22

Gitlabをやめ、Githubに移行した

特電ではいくつかのプロジェクトをgitで管理していて、某サーバ業者で借りたVPS上にgitlabを立ててリモートにレポジトリをアップロードして複数の人で共有していました。

ただ、gitlabは結構重いのでそこそこのランクのサーバが必要になるし、そもそも従業員がいないのでリモートで管理する必要がないので、gitlabのサーバを手放すことにしました。

gitlabからgithubに移行する際には、

git clone --mirror https://<旧サーバ上のURL>/<レポジトリ名>.git

と、mirrorを付けてcloneする。(これをするとHEADとかいうファイルが作られるらしい)

それからgithubで新しいレポジトリをprivateで作り、

cd <レポジトリ名>.git
git remote remove origin
git remote add --mirror=push origin https://github.com/<新しいレポジトリ名.git>

をやってremoteを設定しなおす。もしくは、

git remote set-url origin https://github.com/<新しいレポジトリ名.git>

でremoteを設定しなおして、 

git push

で新レポジトリにアップロード。

という手順でよいのかなと思います。

より高度な機能やissueなどを使っている人はこれだけでいけるのかどうかわかりませんが、私の場合はあまり高度なことをしていないので、更新履歴も含めて全部アップロードできたようです。

githubに移行したとはいっても、やはりgitは、更新履歴を見るツールとしてしか使っていません。

ローカルPCと社内RAIDのファイルが絶対のマスターなんですよね。なぜならば、ファイルの作成日付を重要な情報として使っているからです。gitに上げた瞬間から作成日付がなくなってしまうのがどうしても許せないので、gitにすべてをゆだねる気にならないのです。

 

| | コメント (0)

«USB 3.1をType-Cにする方法のお勉強