2021年12月02日: debian 11でネットワーク(e1000e)が動作しない
2018年09月09日: 5次,7次,9次,11次のB-スプライン曲線
2017年11月13日: MSP430 LaunchPadとVirtualBox
2016年10月19日: configureのGTK+のチェックでエラー
2016年09月11日: 秋月の800x480のHDMIディスプレイにRaspberry PIをつなぐ
2016年01月04日: fsprotect再び
2015年09月01日: マザー入れ替えで、シグナルのキャッチに失敗する
2015年08月30日: 無線ルータにリフレクタを
2015年08月06日: 無線ネットワーク不調
「OK」「Cancel」ボタンの位置 [プログラム]
xfconf-query -c xsettings -p /Gtk/DialogsUseHeader -s false
を実行します。 なお、Ubuntuだと
gsettings set org.gnome.settings-daemon.plugins.xsettings overrides "{'Gtk/DialogsUseHeader':<0>}"
debian 11でネットワーク(e1000e)が動作しない [プログラム]
debian 9→debian 10(buster)は、さほど問題はありませんでした。が、
debian 10(buster)→debian 11(bullseye)で、「大問題」が発生しました。
ネットワークが動かない。このマシンのマザーボードはI219-Vで、このボード上のネットワークのドライバはe1000eということなのですが、ドライバがロードされません。
dmesgで見てみると
The NVM Checksum Is Not Valid
と表示されていて、ドライバをロードしていません。
ググってみると、次のページなどがヒットします。
https://datyotosanpo.blog.fc2.com/blog-entry-220.html
解決策は大まかに2種類、
A. Intel製のNVMセットユーティリティを使って、NVMのChecksumを正しい値に直す
B. Intel製のドライバソースをNVMのChecksumを無視するように変更してコンパイルして入れる
で、まずAから試しましたが、NVMに書き込めないというエラーでダメでした。
で、Bを試したら、e1000eドライバのソースが、kernelのバージョン(backportで5.10を入れていた)と一致せず、コンパイルエラーになりました。
相変わらず、絶好調です、kernelもdebianも。
なので、私は、かつてのシリアルドライバでのバグを自分で修正していたときのように
debianのkernelのソースパッケージを取得、修正、コンパイルしてドライバ(モジュール)を入れ直す
ことにしました。
これだとkernelをアップデートするたびに同じことを繰り返さなければならないので「とても面倒」なのですが、一番安心な方法なのです。
まったく同じ状態のkernelのソースを使うのですから、コンパイルエラーもでませんし、ロードも必ずできます。
ただし、kernelをコンパイルしますので、コンパイルのためのツールのインストールがとても大変で注意が必要です。
まず次のような感じで修正用ディレクトリを作って、そこで作業します。
mkdir e1000e-ignore-nvm-error
cd e1000e-ignore-nvm-error
apt-get source --compile linux-image-....
で、足りないツール(パッケージ)が表示されるので、インストールします。
apt install 足りないパッケージ...
します。おおっと、余計なパッケージまで指定して「現在のlinux-kernelを削除するのか?」って聞かれてしまいましたよ。
もちろん、それはダメです。余計なパッケージの指定を削除して apt install して、 apt-get source --compile ...していると、ダウンロード、パッチ、コンパイルが始まりました。メッセージが出力されていきますが、
なんじゃこの速さは!? と思ってtopコマンドでみると、全コアでgccしてました。makeも並列実行できるようになっているからですが、コア+HTがあると、かなりすごい状態になりました...
で、パッケージまで作られてしまいますが、終了まで待ちます。
終了したら、問題の
drivers/net/ethernet/intel/e1000e/nvm.c
の
e1000e_validate_nvm_checksum_generic(...)
関数の中を、 return 0 だけ残してコメントアウト(削除)します。
一応、念のため、linuxソースのトップディレクトリで、
make clean
してから、再度
apt-get source --compile linux-image-....
して終了まで待ちます。
修正されたのが、どこかにありますが、どこだったかな。
find . -name 'e1000e.ko'
で見つけましょう。
見つかったら、正規の場所へコピー。念のため、もとのドライバ(e1000e.ko)は名前を変えて残しておくのがよいでしょう。
cp e1000e.ko /lib/modules/カーネルのバージョン/kernel/drivers/ethernet/intel/e1000e/
そして、initramfs内にもe1000e.koが取り込まれているようですので、initramfsをアップデートします。
update-initramfs -u
これで再起動してネットワークが動作するようになりました。
後日、もう少し調べてみると、
https://newbedev.com/how-to-repair-the-checksum-of-the-non-volatile-memory-nvm-of-intel-ethernet-controller-i219-v-of-an-asus-laptop
が見つかりました。ただし、
ethtoolを使うため、e1000eが正常に動作するカーネルが必要
ということで、一時的に古いカーネルからブートして使うなどをしなければなりません。
(私は、上記の改造したドライバを使いました)
ですが、こいつもダメでした。
ethtool -E eno1 magic 0x0d4f8086 offset 0x10 length 0x01 value 0xff
Cannot set EEPROM data: Invalid argument
うーむ、このマザーボード上のe1000eは、どうやってもNVMを書き換えられないようです。
5次,7次,9次,11次のB-スプライン曲線 [プログラム]
なお、ここでいう「n次」とは、B-スプライン曲線の中で計算するtの最高次数がnであるものとします。
まず、個人的には、以下の2つのページをおすすめします。
そして、5次から11次の結果については、「フューチャー・ホームページ」の「B-スプライン関数」のページの計算プログラムをベースにします。
フューチャー・ホームページのB-スプライン関数:
http://www1.u-netsurf.ne.jp/~future/HTML/bspline.html
Wikipedia(英語):
https://en.wikipedia.org/wiki/B-spline
まず、3次のB-スプライン曲線ですが、先程のフューチャー・ホームページ内に記述されています。
そこのプログラムのCoefficent(double t)が、3次のB-スプラインの計算の中心部分です。
で、5次ですが、これは、英語のWikipediaの方をみて、あれこれ試して調べた結果がこれです。変数tのかわりにuを使っています。
なお計算には、MAXIMAを使いました。
次に7次ですが(偶数次数は計算していません)、以下のとおりとなります。
(クリックで別ウィンドウで表示します)
9次は以下のとおりです。一部約分されている分母があることに注意してください。
(クリックで別ウィンドウで表示します)
11次は以下のとおりです。これも一部約分されている分母があることに注意してください。
(クリックで別ウィンドウで表示します)
最後に、3次から11次でどう変わるかを示します。
フューチャー・ホームページのプログラムでの点P0からP4で各次B-スプラインで描画した結果です。
(DrawSpline(Graphics g, double t)内でのfor文jの範囲は次数に応じて増やしてください)
描画にはgnuplotを使ったので、Y座標の上下が逆になっています。
MSP430 LaunchPadとVirtualBox [プログラム]
Energiaにしろ、CCS7にしろ、64bitOS専用です。
なので、私はVirtualBoxに64bitOSを入れて、そこにMSP430の開発環境をインストールして使っています。
しかしながら、VirtualBoxだと、USBの問題を片付けなければなりません。
VirtualBoxから、ホストに接続されたUSBデバイスを操作するには
(a) VirtualBoxでUSB2.0,3.0を扱うためには、ホスト側にExtension Packをインストールしなければならない
(b) それが何のデバイスかをホストが知っていなければならない
CCS7をインストールするとして、
(a)のExtension Packの方は、VirtualBoxのサイトからダウンロードしてインストールすればよいです。
(b)の方は、MSP430のCCS7/etc/udev/rule.d/71-ti-permissions.rulesを追加して、/etc/init.d/udev restartすればよいです(が、実は、それだけではダメでした)。
これらをして、MSP430のサンプルコード(出荷時に書き込まれているもの)をTIのサイトからダウンロードして、CCSでimportしてビルドしました。
ホストに接続したLauchPadを、ホストが認識したことを確認して、VirtualBoxの方でそのUSBデバイスを有効にすると、ゲストの64bitOSが認識しました。
CCSの設定で、デバッガ(ICEの設定)をそれに変更し、ビルドしてダウンロードしてデバッグに入ります。
が、アラートが出て、「LaunchPadの方の『eZ-FET on-board emulator』のファームウェアを更新する必要がある」と言われてしまいました。
なんとなく「update」ボタンを押してしまったら、... 緑と赤のLEDが点灯したまま止まってしまいました。数分待ったでしょうか、エラーメッセージがでました。updateに失敗!!! え? LaunchPadがいきなりゴミになった!?
こんな状態になることは少なからずあることなので、当然回復させるための手段があるはずですが、どうやるのでしょう?
まず、LaunchPadのUSBケーブルを一度抜いて挿し直してみます。当然、デモプログラムも動きません。
ホストもUSBデバイスを正しく認識できていません。USBデバイスとしては認識していますが、71-ti-permissions.rulesにあるデバイスではないので不明なデバイスとなり、(b)ができないため、VirtualBoxで使用できない(ゲストOSで使用できない)、ということです。
LaunchPadのeZ-FET on-board emulatorが初期化されたため、71-ti-permissions.rulesにはない、MSP430の素のUSBデバイスになっているようです。なら、これを71-ti-permissions.rulesに追加してやったらどうでしょうか? dmesgの出力をみて、VendorとProductのIDを追加してやります。
SUBSYSTEM=="usb",ENV{DEVTYPE}=="usb_device",
ATTRS{idVendor}=="2047",ATTRS{idProduct}=="0203",MODE:="0666"
そして、CCS7を起動して、デバッグしようとすると、「LaunchPadの方の『eZ-FET on-board emulator』のリカバリが必要」というので、リカバリすると、赤のLEDが不規則に点滅し、しばらくして、デバッガが起動しました。おお、ゴミからLaunchPadに戻ったよ。
続けて、CCSでソースレベルデバッグができることを確認しました。
これでやっと本来のプログラムへ進むことができます。やれやれ。
configureのGTK+のチェックでエラー [プログラム]
ちょっと特殊な問題でしたが、 pkg-config がおかしな挙動をする、ということで、書いておきます。
linuxで、GUIのあるアプリをビルドしようとして、configureすると
checking for GTK+ - version >= 2.6.0... no
*** Could not run GTK+ test program, checking why...
*** The test program failed to compile or link. See the file config.log for the
*** exact error that occured. This usually means GTK+ is incorrectly installed.
(以下、GTK 1.2.7も3.0.0もチェックでnoになる)
で、「GTKがない」と言われてしまいます。
でも、GTK+パッケージは、2.xも3.0もインストール済みなのです。なんで?
前から、このエラーでコンパイルできなかったものがあったし、ということで、今回、解決するまで調査することにしました。
configureをいじって調べていくと、GTK+のチェック部分で、
pkg-config gtk+-2.0で、どちらも1 (エラー)が返ってくるという、とんでも仕様。はぁ?
pkg-config --uninstalled gtk+-2.0
とりあえず、configureがこの先でやることを試そうとして
pkg-config gtk+-2.0 --cflagsしたら、
libpng 16がインストールされているべきなのにないからエラーだよんとか表示されてました。
ググって調べてみると
http://www.linuxquestions.org/questions/slackware-14/fail-to-compile-wireshark-4175510119/
に、libpng14がないと、エラーすることがあるというのを見つけました。
同じ理由かも?
/libや/usr/libを調べてみると、
libpng12はインストールされてたけど、libpng16は入ってません。
なんでかなー...
記憶の彼方を探ると、
libping12でないと動作しない「重要な何か」があったから、固定したような、そうでないような。
とにかく、ま、libpng16をいれましょう。
sudo apt-get install libpng-devで、どこに入れたんですか?
/lib/i386-linux-gnuには、libpng12のままで、16はありません。はて?
/usr/lib/i386-linux-gnuに12と16(1.6)が同居してました。
こんなめちゃくちゃなインストールでいいのでしょうか...
とりあえず、
pkg-config gtk+-2.0 --cflagsが動くようになりました。
やれやれ、これで、今までどうしてもconfigureできなかったやつらがコンパイルできるようになります。
秋月の800x480のHDMIディスプレイにRaspberry PIをつなぐ [プログラム]
設定は、
http://akizukidenshi.com/download/ds/akizuki/raspberry.pdf
にありますが、config.txtに以下を追加せよ、とあります。
hdmi_group=2しかしながら、最近のRaspbianだと、この表示ではボケボケで使い物になりません。
hdmi_mode=14
hdmi_cvt = 800 480 60 6 0 0 0
結論から先に言うと
hdmi_mode=87にすればOKです。
ググって調べると、同じようなLCDで別のパラメータを与えているページがあったので、
まず、基本のページ
https://www.raspberrypi.org/documentation/configuration/config-txt.md
を調べると
hdmi_group=2のときは、
hdmi_mode=14
848x480 60Hzになってしまいます。でも、LCDは800だったはず。
原因はこれですね。横のピクセル数が間違ってる、というわけです。
で、正しい(800x480 60Hz)値は、というと、...
なんと、その表の中にはありません。
はて?
基本のページのhdmi_cvtのところを読むと、
「hdmi_modeの表に合うのがなければ、hdmi_cvtで定義可能」
とあります。なるほど。
hdmi_cvt = 800 480 60 6 0 0 0は、
800x480 60Hz、アスペクト比 15:9、マージンなし、プログレッシブ(インターレースでない)、ReducedBlankではない
です。
さらに、基本のページのその先には、800x480 60Hzの例がありました。
「group 2 mode 87」で新しいモード(800x480 60Hz、音声付き)を作るには
hdmi_cvt=800 480 60 6と書け、とあります。
hdmi_group=2
hdmi_mode=87
hdmi_drive=2
なるほど。
以上のことから、
hdmi_mode=87に設定すれば、正しく表示できることが分かります。これで、ちゃんと表示されるようになりました。
RaspberryPiとBeagleBoneBlackの世界は、アップデートが激しいので、このページの情報も古くなるときがくるでしょうが、そのときは、基本のページ
https://www.raspberrypi.org/documentation/configuration/config-txt.mdを見て、最新の情報を得て修正してください。
fsprotect再び [プログラム]
で、早速使ってみました。SD上のrootfsはext4フォーマットになっています。
tune2fs -i0 -c0 -m0 /dev/mmcblk0p1
したあと、uEnv.txtのcmdlineに「fsprotect ro」を追加して再起動しました。
ふむ。問題なさそうです。
...と思ったのですが、その後、丸1日、「なぜprotectしてくれずに書き込みやがるのか」という大問題にぶつかることになりました。
そうです、linuxがrootfsに「書き込む」のです。しかしながら、書き込んだ形跡をfindで探しても見つかりません。また書き込んで削除したらディレクトリの日付が変わるはずなので、そういうことでもないようです。
調査対象をファイルシステム全体に広げると、見つかりました。ちょうど1バイトだけ変更されていました。
それは、ファイルシステムの先頭から1401バイトめでした。
何が書き込まれた(変更された)のか? それを知るには、まず、ext4の構造(レイアウト)を知らなければなりません。
ext4の構造は
https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout
などにあります。
1024バイトまでが Group0 paddingで、次からsuperblockになっています。
1401バイトは、superblockの中です。superblockの1401-1024=377バイトめ、つまり、0x179バイトめは
0x178 __le64 s_kbytes_written Number of KiB written to this filesystem over its lifetime.の下位から2バイトめです。
「このファイルシステムへ書き込んだKiB数」だということですから、「間違いなく書き込んでいます」。protectしてくれてません。はて?
なお、このs_kbytes_writtenは、「ext4をマウントした後では」、sysfsから読むことができます。たとえば、
cat /sys/fs/ext4/mmcblk0p1/lifetime_write_kbytes
とすればわかります。さらに、これを下記のように直接/dev/mmcblk0p1から読むこともできますが、この場合、注意すべき点があります。
dd if=/dev/mmcblk0p1 bs=1024 count=2 | hexdump -C |grep 0000570
注意点は、「ReadWriteでマウントしているとき」、実際にファイルシステムへ書き込んでも、この値は「変わりません」。アンマウントするときに、ここへ書き込まれるようです。
さて、誰かが書き込んでいるわけですが、それがなかなか分かりませんでした。
まず、書き込みが、起動時なのか終了時なのかについては、他のマシンでSDカード上のrootfsのlifetime_write_kbytesを調べることにより、「起動時」と分かりました。
起動時のどこでしょうか? initramfs内でしょうか? fsprotectの前でしょうか? fsprotect時でしょうか?
initramfs(/boot/initrd.img-*)をgunzip+cpio展開して、中を調べていくと...
ひょっとして!? fsckしてからマウントするようになっています。もっともそれはUN*X時代からの流儀で、突然の電源断などのあとでは、そのfsckが大活躍したものです。/fastboot というファイルがあると、/etc/fstabでfsckするように設定されていもfsckを行いません。ただ、/etc/fstabは、通常rootfs上にありますので、rootfsについては、カーネルの起動パラメータ(fastboot)で指定するようです。
(書き込まない)ReadOnlyのrootfsに対してfsckを実行することが正しいのかどうかについては、NANDのデータ保持期間など議論があるところでしょうが、ともかく、このfsckを「止める」ことにします。
uEnv.txtのcmdlineにfastbootを追加して、結局、「fsprotect ro fastboot」の3つを追加しました。
また、起動時にfsckをしないため、他のPC上でfsck -fをして問題ないのを確認してから、BeagleBoneBlackに差し込んで起動しました。
そして、
cat /sys/fs/ext4/mmcblk0p1/lifetime_write_kbytes
を見たあと、再起動して、再度
cat /sys/fs/ext4/mmcblk0p1/lifetime_write_kbytes
したとき、同じ値になっていることを確認しました。
今回の検討点としては、
- initramfs内のスクリプトで、ReadOnlyのrootfsに対してfsckを実行して書き込みをするのが正しいのかどうか
- 一般的にReadOnlyのrootfsに対してfsckを実行して書き込みをすることが正しいのかどうか
個人的には、
- ReadOnlyのrootfsについては、まず、fsck -nで書き込まずエラーの有無を調べる。
エラーがあったときは、fsckを行うか、起動中止するか、のいずれかを
「なんらかの方法で選択して」行うようにする。
今回の問題では、「起動するときにだけ」SDに書き込むので、もしも基本24時間稼働であれば、再起動は半年〜1年に1回くらい(経験的な値)なので、書き込む回数としてはまったく問題がない程度でしょう。
マザー入れ替えで、シグナルのキャッチに失敗する [プログラム]
ところが、入れ替えてFX8350のマザーになったマシンで動いているプログラムが、SIGHUPの受信に失敗して、プログラムが停止してしまいました。なんじゃこりゃ。
はて、なんででしょう... あ、こいつ、ビルドするのに -march=native を使ったんだっけ。
となると、ソースからリビルドです。プログラムをリビルドすると、問題なくSIGHUPを受信できます。
うーむ、プログラムを少しでも速く動かさなければならなかったので、-march=nativeとしたのですが、良し悪しですね。マザーを変えたので、いずれプログラムをリビルドするべきなのはわかっていましたが、「すぐにでも」やらないと、シグナルがちゃんと動かないなんてのは知りませんでした。まさかと思いますが、ひょっとして、計算結果も間違ってたりするのでしょうか... こ、怖い...
無線ルータにリフレクタを [プログラム]
前回、「無線ネットワーク不調」のため無線ルータを入れ替えましたが、まだときどき数分間だんまりになってしまう状況でした。
ひょっとして混線?
WiFi ExplorerやinSSIDerとは言わないまでも、何らかの調べるツールが必要だなーと思いました。
無線ルータにその機能はなかったので、昔、買っておいたWiFiのUSBアダプタを引っ張りだしてきました。Ralinkのチップが載っているものですが、これはファームウェアをダウンロードしなくてはならず、以前はlinuxで動かすのに割と手間がかかっていたものです。が、現在のlinuxでは、ファームウェアダウンロードの仕組みが統一的に組み込まれて、non-freeで必要なパッケージをapt-getすれば普通に使えてしまうようになりました。こういう正しい進化は実に望ましい進化ですね。
で、そのWiFiアダプタを使って、WiFi関連のコマンドを調べていると、「ふむ、これは自分で書けそうだ」という気になったので、perlで書いてみました。よくあるGUIでなく、「テキスト画面にグラフを出す」方向で。コンソール上でも使えるので、却って便利かも? (負け惜しみ:-)。
結局のところ、
iw wlan0 scan
の出力を加工するだけなので、SSIDを出さないステルスAPでの通信は表示されません。ま、いいか。
いくつかのポイントがありました。
- rfkill unblock 0 などで、ハードやソフトでの使用禁止を解除しなければならない場合がある
私の使っている別のノート内蔵のWiFiモジュールだと、iwconfig wlan0 txpower offが、rfkill block 0と同様な動作のようでした。
いつもtxpower offしていたので、これが必要でした。 - ifconfig wlan0 up したときに、ファームウェアがダウンロードされて、WiFiアダプタが動き出す
ファームウェアがダウンロードされるまでは、WiFiアダプタは実質的には動作しません。 - WPA2はRSNと表示されている
iw wlan0 scanの出力の中に、WPAという表記はあるのに、WPA2という表記がありませんでした。
代わりにRSNというのがあって、ググってみると、こいつがWPA2のことでした。 - 同じチャンネルに複数のSSIDがある
同一のAPから出力されているものだけでなく、別のAPから同一チャンネルで出力されているようです。
おそらく、その2つ(以上)のAPが離れているために混線していないのでしょう。 - cursesでなく、tputを使った
画面を消さずに左上にカーソルを移動するだけですが。tputなんてコマンドがあったんだー。
別に混んでないなー。別のところ(窓際)だと、ほぼ全チャンネルが使用状態だったりしたのですが...Sun Aug 30 00:54:59 JST 2015
Ch: . 8 . 7 . 6 . 5 . 4:SSID;name/E,+APs
1:+ :l******user/2,game/E
2:
3:
4:+++8+++7+ :aterm-******-g;WR8750N/2,-gw/E
5:+ :auhome_******/2,-W/E
6:
7:
8:
9:
10:
11:+++8 :aterm-******-g;WR9500N/2,-gw/E
12:
13:
私が使っているのは8チャンネルですが、ここは使われていないようにみえます。
となると、おそらく私と同じようにステルスAPで通信している人がいるのかもしれません。
あるいは、ステルスAPなので、空きチャンネルと思って通信を開始する機器があるのかもしれません。
後者だとすると、SSIDをブロードキャストするようにしてやればよいのですが、それは思案のしどころ。
チャンネルを変えるのもひとつの手ですが... 11a/11acへ移るのも考えましたが、まだ機器が高い。
有線部分の無線置き換えのための無線機器を、最近はイーサネットコンバータと呼ぶらしいです。知らんかったー。
で、リフレクタのページを見つけました。早い話、中華鍋をAPの後ろに置く、というもの。パラボラですな。
円弧のもの、放物線状のもの、鍋など、いろいろとありましたが、まぁ簡単に自作できるもので試してみたとこです。
http://www.freeantennas.com/projects/template2/index.htmlこれは、ロッドアンテナにぴったりのもので、200円無線ルータにはちょっと合わないのですが、紙なので、ちょっと細工して取り付けました。
で、結果は... 少しマシになったような「気がします」。
もし、これが効果ないのなら、導波管を考えています。
2.4GHzは波長が12.5cmくらいなので、やや大きくなってしまいますが、ダンボールとアルミホイルで作れるでしょう。
通信距離は、直線でコンクリートの壁を挟んで1mくらい。なので、リフレクタよりも導波管のほうがきっとよいでしょう。
他所への漏れ電波も減りますし、逆に入ってくるの(混信)も減るはずですから。
無線ネットワーク不調 [プログラム]
以前RaspberryPiやBeagleBoneBlack作ったLANの無線路ですが、不通になりました。
再起動してみたり、RaspberryPiに戻してみたりしましたが、ダメでした。
で、無線ルータを入れ替えたところ、復活しました。
ま、210円の無線ルータですしね。
たくさん予備を買っておいてよかった、というところです。
さて、取り外した(壊れたはずの)無線ルータですが、念のため
何が壊れたのかを確認しようとして、チェックしてみると…
ちゃんとつながります。あれっ?
あ、でも、パケットロスが多すぎのうえ、無線ルータの向きを変えると通信できなくなりました。
ははぁ、どちらかの電波の出力が弱いのでしょうね。でなければ、電波の受信部のアンプが壊れたか。
最近の暑さを考えると、出力段のトランジスタが熱暴走などで壊れた可能性が高そうです。
電波の出力状態を調べれば、多分、どちらが壊れているのか、確認できるでしょう。