Raspberry PiでLinuxのブート周りをいろいろといじっているうちに、
MicroSDのパーティション情報が認識されなくなりました。
何かの拍子にMicorSDのデータを壊したかなと思い、Raspberry Pi OSのイメージを再度書き直してみるも状況は変わらず。
いくつか調べてみると、USB接続のSDカードリーダに問題があったようでした。
2つSDカードリーダを用意して、同じMicroSDを読んだ結果が以下です。
■ 壊れたSDカードリーダ
1$ sudo hexdump -C /dev/sdb | head 200000000 ba b8 00 10 8a 90 b8 00 b0 b8 00 00 8a 98 8a 80 |................| 300000010 bb ba 00 38 bb 00 02 b9 00 02 b3 a0 aa 21 02 00 |...8.........!..| 400000020 00 ba ba 03 38 00 31 0b 83 82 10 81 ba ba 03 31 |....8.1........1| 500000030 b3 ab 12 b0 02 b0 01 bb 00 38 b2 80 8a 30 01 8b |.........8...0..| 600000040 08 02 89 13 aa 00 38 00 00 ab ba 00 00 00 00 00 |......8.........| 700000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 8* 9000001b0 00 00 00 00 00 00 00 00 39 a0 91 29 00 00 00 00 |........9..)....| 10000001c0 01 00 08 03 a0 bb 00 20 00 00 00 00 08 00 00 03 |....... ........| 11000001d0 a0 bb 83 3b a0 bb 00 20 08 00 00 20 83 01 00 00 |...;... ... ....|
■ 正常なSDカードリーダ
1$ sudo hexdump -C /dev/sdc | head 200000000 fa b8 00 10 8e d0 bc 00 b0 b8 00 00 8e d8 8e c0 |................| 300000010 fb be 00 7c bf 00 06 b9 00 02 f3 a4 ea 21 06 00 |...|.........!..| 400000020 00 be be 07 38 04 75 0b 83 c6 10 81 fe fe 07 75 |....8.u........u| 500000030 f3 eb 16 b4 02 b0 01 bb 00 7c b2 80 8a 74 01 8b |.........|...t..| 600000040 4c 02 cd 13 ea 00 7c 00 00 eb fe 00 00 00 00 00 |L.....|.........| 700000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 8* 9000001b0 00 00 00 00 00 00 00 00 3d e4 95 29 00 00 00 00 |........=..)....| 10000001c0 01 40 0c 03 e0 ff 00 20 00 00 00 00 08 00 00 03 |.@..... ........| 11000001d0 e0 ff 83 3f e0 ff 00 20 08 00 00 60 c7 01 00 00 |...?... ...`....|
SDカードのデータ線は4bitなので、4bit単位で化けている部分を探すと以下の規則性です。
つまり、3bit目が化けているので、DATA2の信号線に何らかの問題が出ていると考えられます。
前後のデータに依存性があるわけではなく、ランダムにDATA2がHighになっているようです。
化けるときは常にHighになる方向なので、どこかで短絡している可能性があるのかなとは思います。
MicorSDの端子ではDATA2の近くにVCCは見当たらないので、基板上かコントローラの中で何らかの問題が発生しているのでしょうか。
かなり古いもので、十分役に立ってくれたので、これは捨てようと思います。
再現性の低い問題ではなく、わりとわかりやすい壊れ方してくれたのはありがたいことでした。
あけましておめでとうございます。
今年もよろしくお願いいたします。
今年のお正月は2年ぶりの帰省ができて、楽しみのおおい正月でした。
改めて感じるのは、家で過ごした正月は普段と何ら変わらず、気が休まらないですね。
気軽に旅行など行ける世の中が早く来てほしいです。
昨年は今まで経験したことのないイベントが多かったです。
正直、胃の痛いことも多くありましたが、
思い返してみると無事こなせていたのでよかった。
また、ほとんど日記に書かなくなっていますが、
技術的な面でも以前より面白いことができてるのではと思ってます。
今年は目先のことだけでなく、10年先のことを見据えた考えをしていきたいですね。
もっと躍進できるよう、がんばっていこうと思います。
話の発端はmuninのプラグインを作っていたことです。
home以下に配置したスクリプトをシンボリックリンクでpluginsディレクトリにシンボリックリンク張って、読み込ませようとしていました。
が、これがどうやっても読み込まれない。
perlのスクリプトの中身を追っていくと、以下のような感じになってさっぱりな状況。
・muninを通して-x, -fやstatの結果、エラーとなる
・別途perlスクリプトを書いて同じことを行うと問題ない
パーミッションを疑っていたけれども、それも違うような…と思っていろいろと試行錯誤している中、
そういえばsystemdでこのスクリプトが動いていることを思い出す。
initスクリプトの顔してたから、systemdのことを忘れていたんですね。
で、systemdの設定見たら確かにProtectHomeなるオプションが有効になっている。
オプションを無効にしてrestartしたら意図通りの実行ができるようになった。
うーん、そんなオプションあったとはね。。。
いままで使って無線APの動作がいろいろと怪しかったので、WN-DX2033GR を購入しました。
ax に対応したものも候補として考えたけど、性能を求めるとあまり安くないし、そもそも対応したクライアントを持っていない。
ルータとしての機能も不要(APとして使わない)ので、アンテナの本数と値段(と、特定のメーカを除外)を考えてこれになりました。
今日になってPCから無線に接続すると、一瞬DHCPから設定されるデフォルトGWが何故か無線APのものになっていることが判明。
Wiresharkで調べるとDHCPの応答がWN-DX2033GRと本来のGWの2箇所から返ってきている…。
本来のGWのほうが遅れてDHCPの応答を返すため、たまたまうまくいっていた模様。
確かに、WN-DX2033GRのステータスを見ると、APモードで動かしているのにDHCPサーバは「有効」の表示になっている。
ただ、APモードなのでDHCPサーバの有効・無効の設定も存在しない。
おそらく、セットアップの手順で不具合を踏んだのかなと推測し、初期化して設定をし直し。
今回は、ちゃんとDHCPサーバは「無効」の表示となりました。一体何だったんだろうか。
Linux Kernel 5.12ではpreemption modelの動的変更が実装されています。
この機能を試してみます。
■ 前準備
以下のconfigを有効にします。
ここでは省略しますが、どちらも他の設定に依存した設定値になっているので、間接的に設定が必要です。
Ubuntu 20.04(x86_64)の場合は、PREEMPTを有効にすることで上記が有効になりました。
■ 動的にpreemption modelを変更する
方法としては2つあります。
今回は後者の方法を試してみます。
まずcatで現在の設定の確認。
これをCONFIG_PREEMPTと同じpreemption modelに変更します。
とりあえず変わることはわかりました。
■ 何かがおかしい?
本来はここで動作検証をするところなのですが、
試してみても挙動がまったく変わらず、何かがおかしい?
一つ気になるのがDEFINESTATICCALLでpreemptscheduleは登録しているものの、
staticcallで呼び出しているところが見つからない。
https://elixir.bootlin.com/linux/v5.12/source/kernel/sched/core.c#L5264
PREEMPTDYNAMICがstaticcallの機能の上で成り立っているため、
static_callで呼び出さないとダメだと思うんだけどな。もう少し調べてみよう。
以下の環境で試していきます。
ビルド環境とターゲット環境を兼用しても大丈夫です。
今回は、VMに割り当てられるリソースが少ないので別途ビルド環境を用意しています。
ターゲットとするカーネルは5.12とします。
ビルド環境にて、メインラインのカーネルをチェックアウトします。
configはUbuntu 20.04のものを使用します。
ターゲット環境からビルド環境へ転送します。
1target$ scp /boot/config-5.4.0-72-generic 192.168.10.44:~/linux/.config
configはdefconfigから生成する方法もありますが、
ドライバの有無や機能の有無にも関連してくるため、
ひとまずはディストリビューションのものを試すのが無難だと思います。
カーネルのバージョンが5.4から5.12へ変わるため、
oldconfigで不足しているconfigを設定します。
1build$ make oldconfig
数十〜百単位で項目が聞かれますが、とりあえず試すだけであれば
全部デフォルト値(つまりEnter押しっぱなし)で十分だと思います。
一点だけ、CONFIGSYSTEMTRUSTED_KEYS はデフォルト値を削除して空欄にする必要があります。
署名済みカーネルモジュールを生成するためのキーみたいですが、
この点はどういう仕組になっているのかよくわかってないです。
make menuconfig でメニューを表示し / で検索します。
1build$ make menuconfig
次にビルドします。
細かくはカーネルビルドして、モジュールビルドして…とか手順はありますが、
今回そこが目的ではないので以下でまとめてビルドしてしまいます。
1build$ make -j4 bindeb-pkg
ビルドが完了すると以下のファイルが出力されます。
これをターゲットに転送して、インストールします。
1target$ sudo dpkg -i linux-*.deb
完了したらrebootします。
立ち上がったらunameでカーネルのバージョンが上がっていることを確認します。
あけましておめでとうございます。
普段の年末なら実家に帰ったりして、ちょっと普段と雰囲気が変わって"お正月"な感じがでますが、
今年はずっと家にいたため、あまりお正月感が出ずでした。
でも、その分考えることややりたいことは進んだので良かったかな。
そんな中で今年の目標を考えてみました。
あれこれ考えながら、以下のあたりでいきます。
やることをうまく分解・組み立てして、実現に向けて頑張っていこうと思います。
今年も1年ありがとうございました。
COVID-19でいろいろと変化の多かった年でしたが、3点ほど今年の印象的な出来事を上げてみます。
■ 3月頃からリモートワークを続けてます
3月頃から続けてリモートワークをしています。
良い点としては、(COVID-19はあまり関係ないですが)子供がいると何かあったときに対応しやすく、
その点は非常に良かったかな。
一方で一時期は常にリモートでも良いのかなと思い、実際そういう時期も2ヶ月近くあったけど、
実際にやってみると中々すべてをリモートでというのは難しいなと感じました。
特に人と人とのやり取りの中では、直接会うほうが進めやすいというケースがありますね。
■ Linux Kernelをいじる業務が増えました
以前からそんな感じのことはしていたのですが、今年は特に集中的にやってます。
ソースコードを上から下まで読み込んで、いろいろと手を加えたりとか、
バグを出したりとかしていて、奥深いところまで理解が進んだのかなおと思ってます。
特にアーキテクチャ依存部の実装や一部のドライバの実装には詳しくなったと思います。
また、自分の手でOSを動かせるっていうのはやっぱり面白いですね。
■ 万年筆にはまりました
以前からプラチナ万年筆のプレピーという万年筆を使っていました。
ただ、ペン先の歩留まりが悪いのか、数本買って書き味の選別をしてみたり、
(一本300円ぐらいなので)自分でルーペでみながらヤスリで調整とかしていました。
じゃあ、ペン先が金の万年筆だとどうなのか?というのが発端で、
センチュリーの太字と細字を半年間隔ぐらいで購入してしまい、はまりました。
使ってみた感想は期待通りか、ちょっと下回るぐらいかなぁ。。。
太字はぬらぬら感が良かったんですが、細字はかりかり感が出てしまうのがちょっと微妙なところでした。
こういう時期でなければ、ペンクリニックに持っていって調整をしてもらうの良いとは思ってます。
次に気になってくるのは、他のメーカーだとどうなのかなとか思っていて、
また少し経ったら買いたくなっちゃう気がします。。。
逆にうまくいかなかったな点は以下の2点。
■ 英語がおざなりになってきている
話す機会が圧倒的に減ってきているのが良くないかな。
読み、書きは普段から少しはするものの、もうちょっと量を増やしていきたいですね。
そういえば、2月にTOEIC S/Wを受けたことをこれを書きながら思い出しました。
定期的にテストを受けながら目標設定していくつもりが、
この状況下(特に2月の回を最後に中止になったり、人数制限がかかったりしていた)ですっかりおろそかになっていました。
■ 自分の作りたいものがうまく進んでいない
目下はAVRの書き込み基板を作っています。
それを応用して広げていきたいなと考えているのですが、
単に書き込み基板(とそのファームウェア)を実装するのに時間がかかってます。
時間がまだあると思っちゃうんだろうけど、サクッと終わらせたいところです。
こんな感じの1年でした。
それでは、来年も良いお年をお迎えください。
Raspberry Pi W Zero をセットアップした。
MH-Z19(詳細は12月1日の日記参照)を使って、CO2濃度を測れるようにする。
以前やったときは、Raspberry Pi 4 を使っていて、普段仕事をする部屋で稼働している。
時系列でグラフを見ていると相対的に空気が悪い事がわかるので、
空気を入れ替えるタイミングが分かるのが良いかな。
今回セットアップしたものは、リビングに設置して測定予定。
昨晩のこと。開栓したワインが何かカビ臭い(乾いた雑巾のような匂い)。
保管期間が長くて酸化したのともまた違った感じで、飲むのもツライ感じ。
そういえばソムリエがコルクを確認するのはこういう理由だったような、と思い
調べてみるとブショネとというらしい。
うーん、でも本当にそうなのか…?
少し置いてみてもカビ臭いのは抜けない。
あと、念のためvinicaでレビュー見てみて、そういうワインなのか調べてみる。
フルーティーでスパイシー…全くそんな感じしない。やっぱりおかしい。
今まで感じたことのない匂いだし、まぁそうなんだろうな。
さらに調べてみると、販売元によっては交換をしてくれるみたい。
今回買ったところはその対応をしてくれるところで、
連絡をしてみたところ返金をしてもらえることになった。良かった。
ワインって毎回味が変わるものだし、こういうのも含めて面白みなのかなと。
ただ、最初にこんなワインにあたったら嫌だろうな…。飲み慣れててもこの匂いはきつい。
この日もう一本開けてみたけど、前の匂いの印象が残ってて全然進まなかった。
AVRでSPIのデバッグの続き。ようやく理由がわかった。
Slave Selectの信号が入力になっていて、かつ、Lowに入力されている状態になっていて、SPIの回路が動作していなかった。
仕様書確認して、信号の方向を出力にした場合は回路側が影響を受けないということなので、ひとまず出力にして対策。
特に他のデバイスはつないでいない状態であれば、出力にしてしまってもひとまずは問題ない。
他のデバイスを接続する可能性を考えると、外でpull upしておくのが良かったな。。。次回修正しよう。
あと、SPIのMOSI、MISOの接続を間違えていることにも気づいた。
Master Out Slave Input(MOSI)なので、MasterとSlave間で同じ端子をつなぐのが正しい。
つい、UARTのRX, TXの感覚でクロスで接続してしまった…。
基板をカットして配線し直そう。
CO2センサとして使っているMH-Z19を購入しようと、数日前からaliexpressをちらほらと見ているんだけど、
在庫や値段の動きがちらほらある感じがする。
どうせすぐに使うものでもないし、何かのセールのタイミングで良いかなとか考えていただけど、
値上がり傾向な感じもしてたため、購入することにした。ちょうど年末年始に届く予定。
AVRでSPIを使いたいと思っていじってるんだけど、うまくいかない。
ライタと信号を共有しているので、それが原因かなとか思って外してみるも、これも効果なし。
プログラムが間違っているのかもだけど、仕様書の通りの手順でやってるだけなんだよね…。
うーん、また時間をあけて考えてみよう。。。
今日は休暇だったので、家でいろいろと作業。
以前aliexpressで買ったMH-Z19をようやく動かしてみる気になり、
コネクタをはんだ付けしたりしてRaspberry Piに接続できるようにした。
Pythonのライブラリを使って、特に問題もなくセンサの値が取得できた。
グラフを見ていると在室状況によって変動するので面白い。
あとはこの値から部屋の中の換気が適切かどうか判断したい。
今回少し工夫したのは、ストレージへの書き込み回数を減らすこと。
1秒おきにロギング&グラフ出力をするようにしていて、
そのまま出力するとSDカードの書き込み回数上限に達してしまう可能性があり、
代わりにramfsに出力するようにしてram上で完結させるようにした。
再起動するとログも飛ぶものの、過去のデータは無くても良いかな。
必要なら1日おきとかにバックアップ取れば良さそう。
やらないと…と先延ばしにしていたサーバのアップデート、ようやく完了。
今回はOSをDebian 10にしました。
railsで動いているアプリケーションも何とか6.0にしました。
ところどころ動かないところは諦めたりとかしましたが、
主要なものはあまり手を入れずに動かせて良かったです。
基板を作成してみました。
昨日FusionPCBで発注、そんなに急ぎではなかったのでShigapore Postで配送にしました。
3週間後ぐらいに届くのが楽しみです。
今回作った基板は、USBで接続をして、UART、I2C、GPIOをそれぞれコネクタから出します。
メインはUSB-シリアル変換として使うため、ついでに今後その他のIOで遊ぼうと思っています。
最初、いろいろなところで使えると良いなと思い、MCP2221Aを表面実装とDIPとそれぞれ切り替えて使えるよう設計していました。
ただ、USBの基板設計ガイドラインを確認していて、明確には書いてないものの分岐はダメな気がしてきてやめました。
表面実装とDIP、どちらかは未実装になるので動作としての影響はないのですが、分岐していることで反射の影響とか受けそうだなぁ…と。
ということで、表面実装だけ残してあとはすべて削除。すっきりとした基板になりました。
今さらAVRの書き込み基板を作ってます。
ワンボードにAVRを2個乗っけて、モニタ用(マスタ)とプログラム実行用(スレーブ)のそれぞれで使用して、
PCからUSB1本でプログラムの書き込みから実行までできるような基板です。
基板の詳細についてはまた別の機会に書くことにして、早速失敗に気づいたので、まずはそちらから…。
UARTからデータの送受信をするプログラムを作成して実行してみるも、何かうまく行かない。
オシロで見てみるとボーレート自体は問題なさそうだし…って、なんでマイナスの電圧が?というので気づきました、レベル変換入れてない…。
そういう設計でも(仕様通りなら)良かったんですが、少なくとも今使っているUSBシリアル変換はRS-232Cのレベルでしか受けてくれません(なので仕様通りじゃない)。
こういうときのため、以前にMAX232を使ったレベル変換基板を作ったので、それを使ってみることに。
が、これもこれでよく調べてみると、この基板は電源をマイコン側から取るようになっている(当然RS-232Cのコネクタにも電源はないので、MAX232を動かすための電源が取れない)。
今回作った基板は添付の画像のようにRX, TX, GNDの3線しか出していません(ここにVCCがあれば解決する問題だった)。うーん…ダメじゃん。
そうなるとCMOSレベルで受けられる、USBシリアル変換を買うか、あるいは作るかになりそうです。
Raspberry Pi 4b (4GB model)を購入しました。
秋月のセットを購入。
いろんなところで売っているのでどこで買ってもよいんだけど、
電子部品を買う必要があり一緒に通販で購入しました。
当面の用途はローカルのDNSリゾルバにすること。
ルータがEDNS0に対応していないためGoogleのDNSを使っているのですが、
いくらレスポンスが早いと言っても、やっぱりローカルでDNSは持ちたい。
あと、ローカルに常時電源入ったデバイスがほしかったというのも理由。
買うときに少し悩んだのが発熱がどうなのかという点。
早速購入直後の状態で確かめてみたところ、以下の通りでした。
ちょっと高いかな…。
ちなみに、1コアだけCPUに負荷をかけると以下の通り。
室温が23度の条件で上記なので、夏場は厳しいかも…。
ちなみに、Power Management の状況を確認したところ、idle時は600MHz、
一方で高負荷時は1.5GHzで動作している。
気休めにヒートシンクはつけてみたものの、あまり変わらず…。
うん、何となくそんな気はしていた。
運用してみてあまりにも酷ければ、ファンをつけることも考えよう。
必要な設定項目を設定。
GUIは停止して、SSHは常時起動に変更。
最後にバージョンを確認。
kgdbを使ったLinux Kernelのデバッグ方法をまとめてみました。
この説明は以下の内容を元にして、具体的な手順を説明したものです。
kgdb, kdb の使い方と、カーネルデバッガーの内部
https://sites.google.com/site/kandamotohiro/linux/kgdb
まずはカーネルの設定を確認。以下の通りに設定をします。
ビルドして起動できることを確認します。
ホストとターゲットは2本のUARTで接続します。
1本はカーネルログの出力確認、breakコマンドの入力、シェルの操作を行うために使用します(以降の説明ではUART0)。
もう1本はkgdbの通信用に使用します(以降の説明ではUART1)。
UARTが1本しかないケースは、SSHで代替することもできます。
ただし、この場合、任意のタイミングでbreakをかけられないことと、カーネルログの出力が確認できないため、あまりおすすめはしないです。
カーネルの引数にkgdbwait, kgdbocを追加します。
kgdbwaitは、カーネル起動時にkgdbの接続を待ちます。
kgdbocはUART経由でgdbに接続することを指定します。kgdbocには使用するttyとボーレートを設定します。
以下はUART1に対して、115.2kbpsのボーレートを設定しています。
1kgdbwait kgdboc=ttyS1,115200
またカーネルログの出力先は以下のとおりUART0に対して設定します。
1console=ttyS0,115200
カーネルを起動して、以下の表示が出るとkgdbの接続待ちの状態になります。
ホストからターゲットのカーネルに対して、gdbでアタッチします。
ビルドしたvmlinuxをgdbで読み込みます。
ターゲットがロードしたカーネルがzImageの場合でも、シンボル情報が必要になるためvmlinuxをロードします。
1$ arm-linux-gnueabihf-gdb vmlinux
次にkgdbocでUART1に対してアタッチします。
以下はホストの/dev/ttyUSB2とターゲットのUART1が接続されている例です。
接続に成功すると以下のようにbreakpointで停止します。
ほとんどの操作はgdbと同様に行うことができます。
以下によく使う操作を記載します。
ブレークポイントを設定&実行を再開する
手順はgdbと同様です。
以下はuio_readにブレークを設定する例です。
1(gdb) b uio_read 2Breakpoint 1 at 0x803d910c: file drivers/uio/uio.c, line 812. 3(gdb) c 4Continuing. 5[New Thread 1172] 6[New Thread 1135] 7[New Thread 1143] 8[New Thread 1146] 9[New Thread 1152] 10[New Thread 1153] 11[New Thread 1167] 12[Switching to Thread 1172] 13 14Thread 42 hit Breakpoint 1, uio_read (filep=0x839f9240, buf=0x7ef96c20 "", count=4, ppos=0x83bdff80) at drivers/uio/uio.c:812 15812 { 16(gdb)
任意のタイミングでブレークをかける(つまり実行を停止して、gdbで操作できる状態にする)には、ホストからUART0に対してSysRq + gを入力します。
ホストからUART0への接続にscreenを使っている場合には、Ctrl-a -> b -> gでSysRq + gの入力できます。
SysRq +g を受け付けるとUART0には以下のように表示されます。
1# sysrq: SysRq : DEBUG
gdbは以下のようにブレークがかかります。
カーネルのconfigを一部設定変更したいと思って、menuconfigを探してみるもなかなか見つからないことが多い。
.configをテキストでざっと見つつ、メニューの階層を推測して…といままでやってたんですが、
実はmenuconfig上で検索できることを知りました。これはすごく便利。
やり方は、menuconfigのUIで"/"を入力すると検索ができます。
例えば、MAGIC_SYSRQを探した結果は以下の通り。
左側に(3)や(4)などの数字が出ているので、それに対応するキーを押すとジャンプできます。
またselected byやdependsが書かれているので、ここからどういう条件でそのメニューが有効になるか、確認ができます。
あけましておめでとうございます。今年もよろしくお願いいたします。
毎年恒例の目標をまとめてみたました。今年の目標は以下の通り。
2020年もがんばっていきたいと思います。
気づくと一年間日記を書いていませんでした。。。
年末なので今年の振り返り。
仕事や家庭などいろいろとありました。
トータルで見れば充実した一年だったのかなぁと思います。
さて、新年に立てた目標は…と見返すと、あまり課題の設定方法が良くなかった気がします。
どちらも具体的な成果にはなっていないものの、自分の中では少しづつできてきてるのかな(笑)
今年も一年ありがとうございました。来年もよろしくお願いいたします。