Armadilloフォーラム

ユーザーLED1が起動後に消灯

kubo

2021年6月7日 14時08分

お世話になります。久保と申します。

4ヶ月程使用しているArmadillo G3の1台が、動作が突然止まったようで、その時原因や対策について検討しておりますので、アドバイスなどいただければと思います。
既に現所は電源再投入して復帰しているので、ログなどは取得できない状態ですが、LEDの状態が、以下のようになっていることだけは確認できました。

電源再投入前
ユーザーLED1・・・消灯       点灯
WWAN LED ・・・点滅(待機状態)  点滅(通信状態)

電源再投入後
ユーザーLED1・・・点灯
WWAN LED ・・・点滅(通信状態)

※ユーザーLEDはプログラムから制御は行っておりません

デフォルトで、Linux起動でユーザーLED1が点灯になると思いますが、どのような要因で消灯になりえるのでしょうか?
また、この状態になった時に、再起動等で自動で復帰させたいのですが、どのような方法をとることが可能でしょうか?
Linux起動していない状態だとすると、ソフト側で対処できることがないように思っております。

お手数をおかけいたしますが、どうぞよろしくお願いいたします。

コメント

kubo

2021年6月7日 14時21分

お世話になります。久保と申します。
すみません。誤記がありました。LEDの状態としては、以下のような状態が正しいです。

電源再投入前
ユーザーLED1・・・消灯
WWAN LED ・・・点滅(待機状態)

電源再投入後
ユーザーLED1・・・点灯
WWAN LED ・・・点滅(通信状態)

お手数をおかけいたしますが、どうぞよろしくお願いいたします。

at_mitsuhiro.yoshida

2021年6月8日 18時07分

吉田です。

この状況を再現できなかったのですが、
ユーザー LED1 は Linux 動作中は点灯いたしますので、
なんらかの理由で Linux は終了動作を実施していますが、
3G/LTE モデムの電源オフ処理は実施していない状況に
陥ったのではないかと推測します。

現象発生時の syslog など、何か情報は残っていませんでしょうか。

kubo

2021年6月9日 15時24分

お世話になります。久保と申します。

ご返信大変ありがとうございます。
ログですが、遠隔地での本番運用のため、overlayで動作させており、現場判断で復帰を優先しログを取る前に電源再投入する形となり、電源再投入後のログしか残っていない状態です。
overlayでも何か情報が残るようなものがあればよいのですが。

ユーザー側ではLED制御はしていない場合は、ユーザーLED1が消灯となる条件は、Linux終了時のみという理解であっているでしょうか?
としますと、その場合は、ウォッチドッグリセットかかってほしいところですが(ウォッチドッグはデフォルト設定から変えていません)・・・

お手数をおかけし、申し訳ありませんが、どうぞよろしくお願いいたします。

at_shinya.koga

2021年6月13日 10時57分

アットマークテクノの古賀です。

久保さん:
>ご返信大変ありがとうございます。
>ログですが、遠隔地での本番運用のため、overlayで動作させており、現場判断で復帰を優先しログを取る前に電源再投入する形となり、電源再投入後のログしか残っていない状態です。
>overlayでも何か情報が残るようなものがあればよいのですが。
>
>ユーザー側ではLED制御はしていない場合は、ユーザーLED1が消灯となる条件は、Linux終了時のみという理解であっているでしょうか?

「Linux が停止したが 3G/LTE モデムの電源オフ処理を実施していない」という状況の他、Linux がサスペンドした場合も、

>>>ユーザーLED1・・・消灯
>>>WWAN LED ・・・点滅(待機状態)

という LED 点灯状態になります。つまり、何らかの原因で、Linux がシャットダウンシーケンスを開始して、電源オフ直前で動作停止してしまったか、あるいは、サスペンドしてしまった可能性があります。

>としますと、その場合は、ウォッチドッグリセットかかってほしいところですが(ウォッチドッグはデフォルト設定から変えていません)・・・

上記いずれの場合も、ウォッチドッグを停止していますので、リセットがかからないのです。

kubo

2021年6月15日 8時59分

お世話になります。久保と申します。

ご回答大変ありがとうございます。
ユーザーアプリ側では、Linuxのシャットダウンやサスペンド、リブートなどOS操作の処理は何もないです。手動での操作も行っていません。
そのため、ユーザーアプリ以外のところで、何かしらの要因により、Linuxの動作が停止という状況になったものと推測しています。
ただ、この場合も、ウォッチドッグリセット以外の方法でもよいので、自動で復帰できる手段などはございませんでしょうか。

OSが起動していないためと思いますが、外からはアクセスできない状態で、現場で直接電源再投入するしか今のところ対処ができない状態です。

お手数をおかけいたしますが、どうぞよろしくお願いいたします。

at_shinya.koga

2021年6月21日 11時34分

アットマークテクノの古賀です。

久保さん(2021年6月15日 8時59分):
>ご回答大変ありがとうございます。
>ユーザーアプリ側では、Linuxのシャットダウンやサスペンド、リブートなどOS操作の処理は何もないです。手動での操作も行っていません。
>そのため、ユーザーアプリ以外のところで、何かしらの要因により、Linuxの動作が停止という状況になったものと推測しています。
>ただ、この場合も、ウォッチドッグリセット以外の方法でもよいので、自動で復帰できる手段などはございませんでしょうか。
>
>OSが起動していないためと思いますが、外からはアクセスできない状態で、現場で直接電源再投入するしか今のところ対処ができない状態です。

Armadillo-IoT G3 で、ソフトウェアだけの対応により、サスペンド後に自動リセットさせるには、ブートローダー(u-boot)と Linux カーネルの改変が必要です。予期しないサスペンドで停止した場合に自動リセットさせる方法、および、予期しないシャットダウンが起きた場合に自動再起動させる方策としては、次のものが考えられます。

・Linux がサスペンドした場合の自動リセット
 CPU (i.MX7 Dual) 内蔵のウォッチドッグタイマー(WDT)が、CPU のスリープ中も動作継続する設定にする。この対応には、ブートローダーと Linux カーネルの改造が必要。
 i.MX7 Dual の WDT の、WDOG_WCR レジスタの WDZST ビットを、リセット時の 0 のままにしておくと、CPU がスリープ状態(low power mode)になっても動作継続し、WDT のカウントダウンタイマーの満了時(約2分後)に WDT リセットします。この WDZST ビットは、write-once only であり、一度 1 にすると、CPU がリセットまたは電源オフ・オンするまで 1 のままになります。WDZST ビットが 1 の場合、CPU がスリープすると WDT も動作停止するため、サスペンド中に WDT リセットしません(※通常は、そちらの方が適切な動作ですが)。
 ブートローダーと Linux カーネルのソースコードで、WDOG_WCR レジスタの WDZST ビットを 1 にしているのは、それぞれ次の箇所です:

 - ブートローダー
  uboot_[version]/drivers/watchdog/imx_watchdog.c で実装されている hw_watchdog_init() の中の、次の行:

val |= WCR_WDZST;

 - Linux カーネル
  linux-4.9-x1-[version]/drivers/watchdog/imx2_wdt.c で実装されている imx2_wdt_setup() の中の、次の行:

val |= IMX2_WDT_WCR_WDZST;

これらをどちらもコメントアウトして、それぞれビルドして出来たブートローダー(u-boot-x1.bin)と Linux カーネル(uImage)を Armadillo-IoT G3 に書き込んで起動したあと、'echo mem >/sys/power/state' でサスペンド状態にすると、WDT リセットで再起動するようになることを確認しました。

・Linux がシャットダウンした場合の自動再起動(1)
 Linux がシャットダウンして CPU (i.MX7 Dual) の電源がオフになった場合、自動で電源をオンして再起動させるには、ソフトウェアマニュアルの「14.3 RTCによる制御」に記載している、RTC アラーム割り込みによる電源オン機能を利用できます:
https://manual.atmark-techno.com/armadillo-iot-g3/armadillo-iotg-g3_pro…
 この機能と、systemd-halt.service によるシャットダウン時スクリプト(/lib/systemd/system-shutdown/ に配置)を組み合わせ、シャットダウン時に RTC アラームを設定することで、シャットダウン後に自動再起動できるでしょう:
https://www.freedesktop.org/software/systemd/man/systemd-halt.service.h…
https://armadillo.atmark-techno.com/forum/armadillo/3900
 ただし、この方策が機能するのは、シャットダウン動作が正常に完了して、シャットダウンシーケンスの最終段階において、Linux カーネルが Armadillo-IoT G3 搭載の BMIC を GPIO 制御して電源オフされた場合です。「ユーザーLED1・・・消灯、WWAN LED ・・・点滅(待機状態)」の状態で停止していた場合、シャットダウンシーケンスが正常に完了せず、途中で止まっていた可能性があります。その場合、i.MX7Dual が電源オフされておらず、この方策では回避できない可能性が高いです。

・Linux がシャットダウンした場合の自動再起動 (2)(シャットダウンシーケンスが途中で止まった場合)
 Linux がシャットダウン動作を開始したものの、何らかの要因でシャットダウンシーケンスが途中で止まってしまった場合、ユーザープロセスは全て終了したものの、CPU は電源オフされず、また、他のカーネルスレッドも動作継続してしまい、その結果、ウォッチドッグタイマーをリフレッシュする動作も継続する、という状況が起こり得ます。その場合、通常動作が停止しているのに WDT リセットが起きない、という状況に陥ってしまいます。そのような場合には、自動再起動する手立てがありません。
 そのような状況は、通常起こり得ませんが、もし発生した場合にも自動再起動できるようにするためには、WDT ドライバを改変しないといけません。Armadillo-IoT G3 の WDT ドライバでは、ユーザーランド(アプリケーション)が WDT リフレッシュの役割を行うようにして、アプリケーションが WDT リフレッシュできなくなったら WDT リセットする、という仕組み(Watchdog driver の ioctl API)には対応していないため、この方策を使う場合は、WDT ドライバの改変が必要です:
https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html

以上、予期しないサスペンドやシャットダウンが起きた場合に、ソフトウェアの対応で自動再起動させる方策として考えられるもの三つです。
もし参考になりましたら幸いです。

kubo

2021年6月22日 14時41分

お世話になります。久保と申します。

ご丁寧な対応大変ありがとうございます。
もう少しだけご教授いただければと思います。

・Linux がサスペンドした場合の自動リセット
→現場のG3の設定や初期状態ではパワーマネジメントが有効か無効か把握できていないのですが、カーネルコンフィギュレーションのパワーマネジメント設定が無効になっている場合には、サスペンドになることはない=予期しないサスペンドで停止ということにはならない、と言うことができるものでしょうか?
それとも、設定有無に関わらず、予期しないサスペンドは発生しえるものでしょうか?

・Linux がシャットダウンした場合の自動再起動(1)
> ただし、この方策が機能するのは、シャットダウン動作が正常に完了して、シャットダウンシーケンスの最終段階において、Linuxカーネルが Armadillo-IoT G3 搭載の BMIC を GPIO制御して電源オフされた場合です。「ユーザーLED1・・・消灯、WWANLED・・・点滅(待機状態)」の状態で停止していた場合、シャットダウンシーケンスが正常に完了せず、途中で止まっていた可能性があります。その場合、i.MX7Dualが電源オフされておらず、この方策では回避できない可能性が高いです。
→この方法では回避できない可能性が高いという情報からも見送りたいと思います。

・Linux がシャットダウンした場合の自動再起動(2)(シャットダウンシーケンスが途中で止まった場合)
→ちょっと話が変わるかもしれませんが、マニュアルには、「WDOG ドライバーの終了処理では、タイムアウト時間をWDOG の最大値である128 秒に設定します。」とあり、linux-4.9-x1-[version]/drivers/watchdog/imx2_wdt.cのimx2_wdt_shutdownを見てもimx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);で128に設定されているようです。
これは、シャットダウンシーケンスが止まったとしても、128秒でウォッチドッグリセットがかかるということではないのでしょうか?
つまり、シャットダウンシーケンスが途中で止まったとしても、ウォッチドッグリセットはかかるはずと理解をしましたが、それが誤っているでしょうか?

お手数をおかけいたしますが、どうぞよろしくお願いいたします。

at_shinya.koga

2021年6月22日 18時59分

アットマークテクノの古賀です。

久保さん:
>ご丁寧な対応大変ありがとうございます。
>もう少しだけご教授いただければと思います。

以下、順にコメントします。

>>・Linux がサスペンドした場合の自動リセット
>→現場のG3の設定や初期状態ではパワーマネジメントが有効か無効か把握できていないのですが、カーネルコンフィギュレーションのパワーマネジメント設定が無効になっている場合には、サスペンドになることはない=予期しないサスペンドで停止ということにはならない、と言うことができるものでしょうか?

そうですね。そのはずです。
Linux カーネルのサスペンド動作は、電源管理機構によって実行されますが、サスペンド動作は、カーネルコンフィグレーションの 'SUSPEND' が有効な場合(デフォルトでは有効)にしか初期化されず、実行されないはずです。カーネルのソースでいうと、以下の箇所です:
https://github.com/atmark-techno/linux-4.9-at/blob/master/kernel/power/…
https://github.com/atmark-techno/linux-4.9-at/blob/master/arch/arm/mach…

>>・Linux がシャットダウンした場合の自動再起動(1)
>>ただし、この方策が機能するのは、シャットダウン動作が正常に完了して、シャットダウンシーケンスの最終段階において、Linuxカーネルが Armadillo-IoT G3 搭載の BMIC を GPIO制御して電源オフされた場合です。「ユーザーLED1・・・消灯、WWANLED・・・点滅(待機状態)」の状態で停止していた場合、シャットダウンシーケンスが正常に完了せず、途中で止まっていた可能性があります。その場合、i.MX7Dualが電源オフされておらず、この方策では回避できない可能性が高いです。
>→この方法では回避できない可能性が高いという情報からも見送りたいと思います。

了解しました。

>・Linux がシャットダウンした場合の自動再起動(2)(シャットダウンシーケンスが途中で止まった場合)
>→ちょっと話が変わるかもしれませんが、マニュアルには、「WDOG ドライバーの終了処理では、タイムアウト時間をWDOG の最大値である128 秒に設定します。」とあり、linux-4.9-x1-[version]/drivers/watchdog/imx2_wdt.cのimx2_wdt_shutdownを見てもimx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);で128に設定されているようです。
>これは、シャットダウンシーケンスが止まったとしても、128秒でウォッチドッグリセットがかかるということではないのでしょうか?

いえ。シャットダウンシーケンスと、ウォッチドッグタイマーのリフレッシュは、それを実行するアクティビティ(スレッド)が異なりますので、シャットダウンシーケンスが停止しても、カーネル全体がフリーズする状況にならない限り、ウォッチドッグタイマーのリフレッシュ動作は継続するのです。

>つまり、シャットダウンシーケンスが途中で止まったとしても、ウォッチドッグリセットはかかるはずと理解をしましたが、それが誤っているでしょうか?

はい。上述したように、シャットダウンシーケンス動作と、ウォッチドッグタイマーのリフレッシュ動作は独立していますので、シャットダウンシーケンスだけが停止した場合には、ウォッチドッグリセットがかからないのです。

Armadillo-IoT G3 の場合、先のコメントで書いた「シャットダウンシーケンスの最終段階において、Linux カーネルが Armadillo-IoT G3 搭載の BMIC を GPIO 制御して」というのは、カーネルのソースの、次の箇所にある bmic_poweroff_do_poweroff() です:
https://github.com/atmark-techno/linux-4.9-at/blob/master/drivers/power…
この bmic_poweroff_do_poweroff() で、
gpiod_direction_output(reset_gpio, 1);
の行の前に無限ループを追加して電源オフせずに停止するようにしても、ウォッチドッグリセットは、かかりません。

ここで、ウォッチドッグのリフレッシュを行うのは、カーネルのソースの、次の箇所にある imx2_wdt_ping() です:
https://github.com/atmark-techno/linux-4.9-at/blob/master/drivers/watch…

imx2_wdt_ping() と bmic_poweroff_do_poweroff() の中で、dump_stack() の呼び出しを行うようにして、コールスタックをログ出力させると、それぞれ、次のような呼び出し関係になっていることが分かります:

# コールスタックなので、最初の呼び出しは、一番下です。

・imx2_wdt_ping()
->imx2_wdt_ping()
->__watchdog_ping()
->watchdog_ping_work()
->process_one_work()
->worker_thread()
->kthread()

・bmic_poweroff_do_poweroff()
->bmic_poweroff_do_poweroff()
->SyS_reboot()

これを見ると、二つの関数は、それぞれ別のスレッドによって実行されていることが分かります。imx2_wdt_ping() の方は、カーネル内部のスレッド(カーネルスレッド)で、bmic_poweroff_do_poweroff() は、reboot システムコールです。これは、systemd がシャットダウン動作の最後に実行します。各々を実行するスレッドが別なので、シャットダウンシーケンスの実行が途中で停止しても、imx2_wdt_ping() の呼び出しは定期的に行われて、ウォッチドッグリセットが起きない、という状況が起こり得るのです。

いかがでしょうか?

kubo

2021年6月24日 12時03分

お世話になります。久保と申します。
丁寧なご対応重ねてお礼申し上げます。

サスペンドについて了解しました。問題が発生した案件ではサスペンドは使っていないので、無効にすることとしたいと思います。

シャットダウンのウォッチドッグリセットについても了解しました。丁寧なご説明ありがとうございます。大変助かります。
ただ、となると、対策するにはウォッチドッグドライバの改変してアプリ側からリフレッシュということになるかと思いますが、ちょっとハードル高いです。
シャットダウンシーケンスが途中で止まった場合の対処としては、シャットダウン開始時(imx2_wdt_shutdown)に128 秒に設定後は、imx2_wdt_pingでリフレッシュされないようにするということでもよさそうな気もしますが、もしご見解などお聞かせいだけるようでしたら幸いです。

どうぞよろしくお願いいたします。