オミクロン株が若干不穏な気配ですが、今年は久しぶりに北海道に帰省しました。でも次の帰省はいつになるやら……。COVID-19 の動向次第ですね。
今までは帰省時期に飛行機に乗るとほぼ必ずインフルエンザをもらっていたのですが、今年は風邪一つ引きませんでした。道行く人が全員マスクを着ける、というのは本当に伝染病予防に効くんですね。マスクの効果を疑っていたわけではないですけど、思った以上の効果が出ていて驚いています。
Windows 電卓は浮動小数点数を扱えます。10^9999 から 10^-9999 という非常に大きい数から、小さい数まで扱えます。
単精度浮動小数点数の最小値は 10^-38(正規化数)もしくは 10^-45 程度、倍精度浮動小数点数でも最小値は 10^-308 (正規化数)もしくは 10^-324(非正規化数)程度ですから、IEEE 754 準拠の浮動小数点数型ではなさそうです。
Windows 電卓で 1 - 1.e-204 - 1 を計算した結果
そのためか少し変わった桁落ちの挙動を示します。同じ程度の大きさの数同士の演算(例: 1.e-9999 + 1.e-9999 = 2.e-9999)であれば桁落ちしませんが、大きい数と小さい数を演算(例: 1 - 1.e-204 - 1 = -9.807971461541689e-149)すると激しく桁落ちします。
実は Windows 10 の電卓のソースコードは GitHub に公開されていて(GitHub のプロジェクトへのリンク)、誰でも見ることができます。MIT ライセンスで、2019年に公開されたそうです。Windows の標準アプリがオープンソースになっているなんて、調べるまで知りませんでした。
利用方法は簡単で Git clone したあと、Visual Studio で src ディレクトリの下にある Calculator.sln を開くだけです。私のノート PC が非力なせいか、ビルドは非常に遅いですね……。
デバッグする際は、設定を「マネージド+ネイティブ」にしておかないと、ネイティブコードを実行している部分のデバッグが全くできず、ブレークポイントなどが無視されるので注意が必要です。
コードのありかとデバッグ方法がわかったところで、Windows 電卓のコードを調べます。桁落ちはどこで発生しているでしょうか?
先ほど示した 1 - 1.e-204 - 1 という演算の場合、CalcManager プロジェクトの RatPack/rat.cpp の addrat() 関数にて trimit() を呼んでいる箇所で桁落ちが発生します。
//calculator/src/CalcManager/Ratpack/ratpak.h
typedef uint32_t MANTTYPE;
...
//-----------------------------------------------------------------------------
//
// NUMBER type is a representation of a generic sized generic radix number
//
//-----------------------------------------------------------------------------
#pragma warning(push)
#pragma warning(disable : 4200) // nonstandard extension used : zero-sized array in struct/union
typedef struct _number
{
int32_t sign; // The sign of the mantissa, +1, or -1
int32_t cdigit; // The number of digits, or what passes for digits in the
// radix being used.
int32_t exp; // The offset of digits from the radix point
// (decimal point in radix 10)
MANTTYPE mant[];
// This is actually allocated as a continuation of the
// NUMBER structure.
} NUMBER, *PNUMBER, **PPNUMBER;
#pragma warning(pop)
//-----------------------------------------------------------------------------
//
// RAT type is a representation radix on 2 NUMBER types.
// pp/pq, where pp and pq are pointers to integral NUMBER types.
//
//-----------------------------------------------------------------------------
typedef struct _rat
{
PNUMBER pp;
PNUMBER pq;
} RAT, *PRAT;
//calculator/src/CalcManager/Ratpack/rat.cpp
void addrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision)
{
PNUMBER bot = nullptr;
if (equnum((*pa)->pq, b->pq))
{
// Very special case, q's match.,
// make sure signs are involved in the calculation
// we have to do this since the optimization here is only
// working with the top half of the rationals.
(*pa)->pp->sign *= (*pa)->pq->sign;
(*pa)->pq->sign = 1;
b->pp->sign *= b->pq->sign;
b->pq->sign = 1;
addnum(&((*pa)->pp), b->pp, BASEX);
}
else
{
// Usual case q's aren't the same.
//★b を変更できないので見づらい書き方になっているが、通分して加算している
//★pa = pa->pp / pa->pq = A / B, b = b->pp / b->pq = C / D とおくと
DUPNUM(bot, (*pa)->pq); //★bot = B
mulnumx(&bot, b->pq); //★bot = BD
mulnumx(&((*pa)->pp), b->pq); //★pa = AD / B
mulnumx(&((*pa)->pq), b->pp); //★pa = AD / BC
addnum(&((*pa)->pp), (*pa)->pq, BASEX); //★pa = (AD + BC) / BC
destroynum((*pa)->pq);
(*pa)->pq = bot; //★pa = (AD + BC) / BD
trimit(pa, precision); //★★この呼び出しで桁落ち★★
// Get rid of negative zeros here.
(*pa)->pp->sign *= (*pa)->pq->sign;
(*pa)->pq->sign = 1;
}
#ifdef ADDGCD
gcdrat(pa);
#endif
}
Windows 電卓は内部では RAT 型(struct rat 型)で数値を保持しています。RAT は分子 pp と分母 pq の 2つの NUMBER 型で構成された有理数を表す型です。
有理数の加算は小学校で習った通りで、通分して足します。大きな数+小さな数で通分すると、非常に仮数部(構造体の mant、mantissa: 仮数の意味)が長くなってしまいます。例えば 1 + 1.e-9999 だと仮数部が 9511 要素もある int32_t の配列になります。trimit() は一定以上の仮数を切り落とす役目を果たします。
加算の桁落ちを削除した Windows 電卓で 1 - 1.e-204 - 1 を計算した結果
桁落ちを防止したければ trimit() の呼び出しを削れば良いです。しかし不思議なことに完全に trimit() を削除すると Windows 電卓が起動しなくなります。
桁落ちを防止すると起動しなくなる理由は、Windows 電卓はなぜか起動時に CCalcEngine のコンストラクタにて 10^100 を計算しているからです。
Windows 電卓は x^y を x^y = exp(y * ln(x)) で求めているので、log の実装を見ましょう。ソースコードは exp.cpp の _lograt() です。見たところ、十分に小さい項までテイラー展開を続けるアルゴリズムのようです。
//calculator/src/CalcManager/Ratpack/exp.cpp
void _lograt(PRAT* px, int32_t precision)
{
CREATETAYLOR();
createrat(thisterm);
// sub one from x
(*px)->pq->sign *= -1;
addnum(&((*px)->pp), (*px)->pq, BASEX);
(*px)->pq->sign *= -1;
DUPRAT(pret, *px);
DUPRAT(thisterm, *px);
n2 = i32tonum(1L, BASEX);
(*px)->pp->sign *= -1;
do
{
NEXTTERM(*px, MULNUM(n2) INC(n2) DIVNUM(n2), precision);
TRIMTOP(*px, precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR();
}
桁落ちを一切なくすとループが終わらなくなってしまいます。変数 thisterm が 0 にならないとループを抜けないところを見ると、ループ条件の SMALL_ENOUGH_RAT がバグっているような気もするんですが……、これ以上の深追いはやめておきます。
他にも √ の計算も非常に遅くなります。パフォーマンスと実用性のバランスから trimit() は必須といえるでしょう。
結論から先に書いておくと、高速道路合流の速度問題が解決されていたので、そのメモです。
問題の説明の記事は、プロパイロット2.0の実現で浮かび上がった、高速道路の制限速度問題【岩貞るみこの人道車医】 - レスポンス(Response.jp)、などいろいろ出ているので、詳細はお任せするとして。
簡単に言うと、SAE レベル 3 以上、つまり機械が人の代わりに運転するタイプの自動運転では、法規上の最高速度に問題があります。普段の道路でも最高速度 60km/h で走っている人はあまりいなくて、それも問題なんですけど、そこはさておき。当初、問題として取り上げられていたのが、高速道路への合流でした。
最高速度は道路交通法施行令という法律で定められていて、高速道路の加速車線の制限速度は一般道同様に 60km/h でした。ご存じのとおり、高速道路の本線は 100km/h なので、法律を守って運転すると、次のようになります。
追突の危険性があるのと、本線で急加速せざるを得ない、ギクシャクした運転になってしまいます。
これは昔から存在していた法律上のおかしな点なんですが、人間が運転する場合はあえて法律(=加速度車線の最高速度制限)を無視し、取り締まり側も厳密なことは言わず見逃す、というゆるい運用で問題を避けてきました。しかし自動運転車まで法律を無視する?それは本当に正しいのか??と問題が再燃したわけです。
引き続き運用でごまかすのも辛いでしょうし、この問題はどうやって直すのかな?と思っていたんですが、どうやら法律の方を直したみたいです。
第四章の二 高速自動車国道等における自動車の交通方法等の特例 (最高速度) 第二十七条 最高速度のうち、自動車が高速自動車国道の本線車道又はこれに接する加速車線若しくは減速車線を通行する場合の最高速度は、次の各号に掲げる自動車の区分に従い、それぞれ当該各号に定めるとおりとする。 一 次に掲げる自動車 百キロメートル毎時 ★★↑60km/h から 100km/h に変わった★★ イ 大型自動車(三輪のもの並びに牽引するための構造及び装置を有し、かつ、牽引されるための構造及び装置を有する車両を牽引するものを除く。)のうち専ら人を運搬する構造のもの ロ 中型自動車(三輪のもの並びに牽引するための構造及び装置を有し、かつ、牽引されるための構造及び装置を有する車両を牽引するものを除く。)のうち、専ら人を運搬する構造のもの又は車両総重量が八千キログラム未満、最大積載重量が五千キログラム未満及び乗車定員が十人以下のもの ハ 準中型自動車(三輪のもの並びに牽引するための構造及び装置を有し、かつ、牽引されるための構造及び装置を有する車両を牽引するものを除く。) ニ 普通自動車(三輪のもの並びに牽引するための構造及び装置を有し、かつ、牽引されるための構造及び装置を有する車両を牽引するものを除く。) ホ 大型自動二輪車 ヘ 普通自動二輪車 二 前号イからヘまでに掲げる自動車以外の自動車 八十キロメートル毎時
自動運転の実現に向けて、継続して警察庁にて話し合いが持たれている(自動運転・自動走行 各種有識者会議等 - 警察庁)ので、今後も法律改正されていくことでしょう。
正月寒いなか放置しすぎたせいか車のバッテリーが死にました。テスターで電圧測ると 2.3V で室内灯すら点きません。またバッテリー交換コースかなー。
メモにあるだけでも2007年 11月 17日、2013年 3月 20日、2016年 7月 24日、2020年 7月 28日にバッテリー交換しています。次で 5回目です。
車に乗る頻度が激減した理由は明確です。東京はあらゆる場所が「車で来るな!」とおっしゃるからです。それでも車で行くと
のどれかです。行く気がしませんのよ〜……。
デスクトップ PC の部品のいくつかは昔の PC から引き継いで使っています。なかでも ATX 電源は交換を怠りがちですが、いざ壊れると起動しなくなるだけでなく、巻き添えで CPU やマザーボードまで故障する可能性もあって故障が怖い部品です。トラブルに遭う前に、予防的に交換します。
買ったのは CoolerMaster V650 GOLD V2(MPY-650V-AFBAG-JP, 650W)です。ヨドバシで 14,000円くらいでした。ちらっと他店の値段を見たら 11,000円くらいでした。ヨドバシは PC パーツがやや高いのかも?
今までは CoolerMaster SilentPro M600(RS-600-AMBA-D3, 600W)を使っていました。Core2 Quad マシンの時代(2009年〜)から使っていましたから、ほぼ付けっぱなしで 13年使ったようです。CoolerMaster の電源は優秀ですね。これからも応援してます。
2020年 10月の旭化成の半導体工場、火災事故調査報告書が出ていた(報告書へのリンク)ので読んでみました。人に犠牲がなかったのは良かったなと思いますが、報告内容はなかなか衝撃的でした。
通常の部屋と違い、クリーンルームは強力なダウンフローがあるし、天井と床下で繋がってる点は特殊です。クリーンルーム火災なんてレアな事例、積み上げもなさそうです。火災まで視野に入れると、設計めっちゃ難しそうですね……。
メモ: 技術系?の話は Facebook から転記しておくことにした。
ハチミツ入りの飴を食べていたら、パッケージに
「はちみつを使用していますので1歳未満の乳児には食べさせないでください。」
と警告があることに気づきました。ハチミツを乳児に与えてはいけないのは、比較的有名な話(ハチミツによる乳児のボツリヌス症 - 消費者庁)だと思います。飴の形に加工されていてもやはりダメなのでしょうか?
乳児ボツリヌス症の原因はハチミツに含まれるボツリヌス菌の芽胞です。ボツリヌス菌「食品衛生の窓」 - 東京都福祉保健局によると、ボツリヌス菌の芽胞は熱に強く、殺菌には 120℃ 4分間の加熱処理が必要です。
ハチミツ入りの飴の話に戻ると、
なるほど、殺菌するタイミングがなさそうです……。
通常の鍋では、水の沸点(100℃)を超える加熱処理は不可能ですが、圧力鍋を使った場合はどうでしょう?我が家の圧力鍋、パール金属 H-3551(メーカーサイトへのリンク)をみると、高圧側 100kPa、低圧側 60kPa とあります。
120℃ の飽和水蒸気圧は 198.7kPa のため、大気圧+100kPa = 約 200kPa とすると、沸点は 120℃まで達します。したがって圧力鍋のロックピンが上がり、圧力が規定値に達したときから、4分間以上加熱することで「一般のご家庭でもボツリヌス菌の芽胞は倒せる」と思われます。やるじゃないか、圧力鍋さん。
とはいえ圧力が必ず 200kPa まで達する保証はありませんし、そもそも圧力鍋は殺菌装置ではないので、過信は禁物です。加熱後はちゃんと冷蔵して早めに食べましょう。
圧力鍋が凄いことはわかりましたけど、飴を圧力鍋で煮込むわけにはいきませんから、やっぱりハチミツ入りの飴を乳児にあげてはいけません。
我が家の圧力鍋は圧力切り替え式でゲージ圧(大気圧 = 0kPa とする記法)で「低圧 60kPa」「高圧 100kPa」となっています。なぜこの数字なんでしょう?
正直に言って設定の意味を理解していなかったんですが、昨日の日記で飽和水蒸気圧曲線(添付の写真、Wagner の式から導出)を見ていて、設定の意味に気付きました。
グラフの圧力軸はゲージ圧ではなく、絶対圧です。沸点は大気圧を 100kPa として、ゲージ圧+100kPa で概算しました。
これはもう見たままですね。10℃刻みです。とてもわかりやすいですね。ゲージ圧 150〜160kPa(絶対圧 250〜260kPa)の鍋もありますが、さらに上の約 130℃設定(実際は 127℃くらいか)を意味します。
調理器具ですから、温度は切り良く、覚えやすく、メーカーが作りやすい設定値を選んでいるはずです。当然と言えましょう。
こんなにわかりやすく考慮してくれているにも関わらず、当のユーザーたる俺ときたら……。全く設定の意味を理解せずに「常に高圧の一択」ですからね。メーカーの設計者は泣いてしまいますね。
メモ: 技術系の話は Facebook から転記しておくことにした。一部加筆。
目次: RISC-V - まとめリンク
昨年、秋月で買って放置していた、怪しい中華製の SPI 接続ディスプレイ(MSP2807)がやっと動きました。制御用のホストとして SiFive HiFive1 を使いました。OS は Zephyr という RTOS を使っています。
HiFive1 では Linux が動かないのも理由の一つではありますが、SPI の制御だけなら Zephyr がちょうど良い規模感でしょう。大掛かりなアプリを動かしたければ、別のハード(HiFive1 は RAM がたった 16KB しかない!)と Linux を持ってきた方が良いでしょう。
SiFive HiFive1(黒い方)と SPI 接続ディスプレイ MSP2807(赤い方)
写真のとおり、画面が点灯して書き換えもできた(青と緑の縞模様を描いている)ので、リセット、コマンドとデータは送れているようです。ホスト → ディスプレイの接続は合っていると思われます。
しかし、ディスプレイ側から何か読み出そうとすると ALL 0 になり何も読めません。ホスト ← ディスプレイの接続をどこかで間違えているのかな……??未だに理由がわからず直せないままです。
このディスプレイは ILITEK ILI9341 という液晶のドライバー IC を使っています。ホストとの接続は何パターンか存在するのですが、
が全く書いていないため、どのモードで動いているのか良くわかりません。イケてねえなあ。おそらく 4-wire モード(SPI + コマンドかデータか示す GPIO 1つ)だと思われますが、確かめようがないです……。
メモ: 技術系の話は Facebook から転記しておくことにした。加筆。
正月、北海道から帰ってきて車の様子を見たら、完全にバッテリーが上がっていました。気づいたのはちょっと前(2022年 1月 10日の日記参照)くらいです。セルモーターは微塵も動かず、そもそもリモコンキーも効きません。ドアはカギで開けました。ドアを開けても室内灯すら点きませんね……。
今まで何度となくバッテリーをダメにしてきた悲しい経験から、これはバッテリー交換コースだと確信しました。またかよー。
JAF に来てもらう間、暇だったのでバッテリーの電圧を測りました。電圧は 2.16V でした。これは乾電池でしたっけ??正常な車のバッテリーは 12V 前後(セル電圧 2V 程度 x6 セル)であり、放電終止電圧は 10V 前後(セル電圧 1.8V 程度 x6 セル)です。2.16V がいかに論外な状態であるか、おわかりいただけるかと思います。
バッテリーから流れる電流も測りました。電流はほぼ流れていないか、クランプメーターの検出限界以下と思われます。余談ですが、このクランプメーターはゼロ点が狂ってきたようで、何も繋がず、ゼロ点補正なしだと -0.31A になってしまいます。直し方がわからない。
JAF さんにエンジンかけてもらった後に電流を測りました。やはり電流はほぼ流れておらず、充電されているように見えません。バッテリーが死んでいるのか、エンジン始動直後のせいか?どっちでしょうね?
バッテリーの液量インジケーターは元々どうなっていたのかわからなくて、正常か異常か判別できませんでした。
仮に液量が正常でも、過放電でサルフェーション現象が発生して電極が死んでいる(=充電ができない=次止めたらエンジンが掛からない)でしょうから、素直にバッテリー交換に行きますか。
近所のイエローハットまで 20分くらい走って、エンジンを切ってみたところ、電圧は 11.8V となっていました。ん?充電されている?もしかしてバッテリーは生きてたのかな?
このまま帰ってまたバッテリーが上がったり、旅先で立ち往生されるのは困るため、潔くバッテリーを交換しました。当たり前ですが交換後は 12.6V と元気な電圧になっていました。
バッテリーは今載っているものと全く同じものを買いました。特に変更する理由もないし。はー、こんなことで 35,000円の出費は痛いな……。
メーターを見ると、エラー Er IUが出てました。なんじゃろ?これ??
Facebook で会社の皆さまに教えていただいたところ、統合ユニットの通信エラーが発生したときに記録されるエラーとのこと。ずっと出続けていて気になりますけど、普通に走れて実害もなさそうなので、しばし放っておこうと思います。
SiFive の HiFive1 というボード(SiFive のサイトへのリンク)をデバッグするときは、HiFive1 のオンボード USB-JTAG を使うことが多いと思います。
非常に便利ですが USB 接続ゆえに近くに PC が必要です。PC を作業机の横に置けば何の問題もないんですけど、我が家の場合は諸事情でちょっと困った配置になっています。
PC を作業机の横に持ってくる手も考えましたが、悪あがきとして Raspberry Pi 3 で OpenOCD を実行してサーバー代わりにしてみました。結果から言うと、思っていたよりうまく動いてくれました。嬉しい、Raspberry Pi 偉い。
各機器の接続関係はこんな感じです。各ソフトに改造は不要です。GDB の TCP 経由でデバッグできる機能と、OpenOCD の GDB server として振る舞う機能の合わせ技で実現できます。
(通常) PC の GDB <-(TCP local 接続)-> PC の OpenOCD <-(USB)-> HiFive1 (今回) PC の GDB <-(TCP 接続)-> Raspberry Pi 3 の OpenOCD <-(USB)-> HiFive1
こんな変な使い方まで想定内とは驚きです。GDB も OpenOCD も良くできています。
Raspberry Pi 3 では OpenOCD を実行します。
$ ./src/openocd -c 'bindto 0.0.0.0' -f tcl/interface/jlink.cfg -f ./tcl/board/sifive-hifive1-revb.cfg Open On-Chip Debugger 0.11.0+dev-00551-gaad871805 (2022-01-16-22:30) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html Warn : Interface already configured, ignoring Info : J-Link OB-K22-SiFive compiled Nov 22 2019 12:57:38 Info : Hardware version: 1.00 Info : VTarget = 3.300 V Info : clock speed 4000 kHz Info : JTAG tap: riscv.cpu tap/device found: 0x20000913 (mfg: 0x489 (SiFive Inc), part: 0x0000, ver: 0x2) Info : datacount=1 progbufsize=16 Info : Disabling abstract command reads from CSRs. Info : Examined RISC-V core; found 1 harts Info : hart 0: XLEN=32, misa=0x40101105 Info : starting gdb server for riscv.cpu.0 on 3333 Info : Listening on port 3333 for gdb connections Info : Found flash device 'issi is25lp032' (ID 0x0016609d) Ready for Remote Connections Info : Listening on port 6666 for tcl connections Info : Listening on port 4444 for telnet connections Info : JTAG tap: riscv.cpu tap/device found: 0x20000913 (mfg: 0x489 (SiFive Inc), part: 0x0000, ver: 0x2) Warn : keep_alive() was not invoked in the 1000 ms timelimit. GDB alive packet not sent! (1606 ms). Workaround: increase "set remotetimeout" in GDB Info : JTAG tap: riscv.cpu tap/device found: 0x20000913 (mfg: 0x489 (SiFive Inc), part: 0x0000, ver: 0x2) Warn : keep_alive() was not invoked in the 1000 ms timelimit. GDB alive packet not sent! (1523 ms). Workaround: increase "set remotetimeout" in GDB Info : JTAG tap: riscv.cpu tap/device found: 0x20000913 (mfg: 0x489 (SiFive Inc), part: 0x0000, ver: 0x2) Warn : keep_alive() was not invoked in the 1000 ms timelimit. GDB alive packet not sent! (1599 ms). Workaround: increase "set remotetimeout" in GDB Info : JTAG tap: riscv.cpu tap/device found: 0x20000913 (mfg: 0x489 (SiFive Inc), part: 0x0000, ver: 0x2) Warn : keep_alive() was not invoked in the 1000 ms timelimit. GDB alive packet not sent! (1610 ms). Workaround: increase "set remotetimeout" in GDB Warn : Error writing to GDB socket. Dropping the connection. Info : dropped 'gdb' connection Info : accepting 'gdb' connection on tcp/3333 Info : JTAG tap: riscv.cpu tap/device found: 0x20000913 (mfg: 0x489 (SiFive Inc), part: 0x0000, ver: 0x2) Warn : keep_alive() was not invoked in the 1000 ms timelimit. GDB alive packet not sent! (1614 ms). Workaround: increase "set remotetimeout" in GDB
PC 側から monitor reset を実行すると「1,000ms 以内に返事が来ない!タイムアウトしたぞ!」という Warning ログが頻発します。HiFive1 の反応が遅いのか、Raspberry Pi 3 の判断が遅いのか、どちらかよくわかりません。両方かな……?
PC では GDB を実行します。例では Zephyr のバイナリを送っていますが、Zephyr 以外でも手順は同じです。
$ riscv64-zephyr-elf-gdb build/zephyr/zephyr.elf GNU gdb (crosstool-NG 1.24.0.378_e011758) 9.2 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=x86_64-build_pc-linux-gnu --target=riscv64-zephyr-elf". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from build/zephyr/zephyr.elf... (gdb) target remote 192.168.1.106:3333 Remote debugging using 192.168.1.106:3333 0x00001004 in ?? () (gdb) monitor reset halt JTAG tap: riscv.cpu tap/device found: 0x20000913 (mfg: 0x489 (SiFive Inc), part: 0x0000, ver: 0x2) keep_alive() was not invoked in the 1000 ms timelimit. GDB alive packet not sent! (1615 ms). Workaround: increase "set remotetimeout" in GDB
GDB もタイムアウトがどうのこうのと怒っています。特に異常動作はしないので放っておいても良いですけど、邪魔であればメッセージのおススメ通りに set remotetimeout の値を伸ばすと良いでしょう。
基本的には以上です動きました良かったね!で終わりなんですけど、Raspberry Pi 3 の dmesg を見ていたら見慣れないエラーが出ていたのでメモしておきます。
[ 253.885123] usb 1-1.5: new full-speed USB device number 6 using dwc_otg [ 254.021413] usb 1-1.5: New USB device found, idVendor=1366, idProduct=1051, bcdDevice= 1.00 [ 254.021440] usb 1-1.5: New USB device strings: Mfr=1, Product=2, SerialNumber=3 [ 254.021475] usb 1-1.5: Product: J-Link [ 254.021490] usb 1-1.5: Manufacturer: SEGGER [ 254.021505] usb 1-1.5: SerialNumber: 000979016829 [ 254.023795] cdc_acm 1-1.5:1.0: ttyACM0: USB ACM device [ 254.027758] cdc_acm 1-1.5:1.2: ttyACM1: USB ACM device [ 254.031278] usb-storage 1-1.5:1.5: USB Mass Storage device detected [ 254.032081] scsi host0: usb-storage 1-1.5:1.5 [ 254.875197] Under-voltage detected! (0x00050005) ★★★★これと★★★★ [ 255.037642] scsi 0:0:0:0: Direct-Access SEGGER MSD Volume 1.00 PQ: 0 ANSI: 4 [ 255.038948] sd 0:0:0:0: Attached scsi generic sg0 type 0 [ 255.043115] sd 0:0:0:0: [sda] 21829 512-byte logical blocks: (11.2 MB/10.7 MiB) [ 255.052887] sd 0:0:0:0: [sda] Write Protect is off [ 255.052914] sd 0:0:0:0: [sda] Mode Sense: 0b 00 00 08 [ 255.055179] sd 0:0:0:0: [sda] No Caching mode page found [ 255.055202] sd 0:0:0:0: [sda] Assuming drive cache: write through [ 255.148361] sda: [ 255.166356] sd 0:0:0:0: [sda] Attached SCSI removable disk [ 259.035120] Voltage normalised (0x00000000) ★★★★これ★★★★
このエラーは Raspberry Pi 3 と HiFive1 の USB 端子を接続したときに出現します(私の環境だと接続のたびに必ず発生)。電力供給ラインである USB の VBus 端子電圧が下がっているという意味ですかねえ……?可能性としては HiFive1 が起動時だけ一気に大電力を消費することが考えられますが、深追いしておらず真相はわかりません。
HiFive1 の JTAG を使う際は J-Link の設定(tcl/interface/jlink.cfg)を使えば OK です。しかし SEGGER J-Link の JTAG 箱が見当たらないのに、なぜこの設定で動くのか若干気になりました。調べたら納得だったのでメモしておきます。
回路図を見るとマイコンで USB-JTAG 変換を実現しています。USB 端子は NXP MK22FN128VLH10(MK22FN128VLH10 Product Information - NXP)に接続されており、この IC から JTAG の信号(TDI など)が出ています。JTAG の信号線は SiFive FE310 に接続されています。
なぜ突然 NXP のマイコン IC が出てくるのか?J-Link はどこから来た??と思いきや、実はこれ SEGGER J-Link のオンチップ JTAG、J-Link-OB というシリーズの 1つで使われているマイコンです(参考: J-Link OB Debug Probe - SEGGER)。SEGGER J-Link は専用の IC があるわけではなく、NXP や ST のマイコンで実現しているんですね、なるほど。
カタログ上は Cortex-M/Cortex-A 用となっていますが、これは SEGGER 独自の機能が使えるか使えないかを表しているのでしょう。JTAG は 4つの信号線(TMS, TCK, TDI, TDO)で JTAG のプロトコルを理解するデバイスが相手であれば良くて、CPU の種類は特に気にしないはず……。
管理者: Katsuhiro Suzuki(katsuhiro( a t )katsuster.net)
This is Simple Diary 1.0
Copyright(C) Katsuhiro Suzuki 2006-2021.
Powered by PHP 5.2.17.
using GD bundled (2.0.34 compatible)(png support.)