Raspberry Pi2 で 30MB/s のmicroSDカードを使うには

30MB/s の転送速度に対応している「エレコム microSDHCメモリカード(UHS-I対応) 16GB MF-RUMSD16GL」を使ったところ、なかなか安定しなかったのですが、なんとなく対策がわかってきた気がするのでブログに書いておきます。これまで、問題が起きて壊れるのはファイルに変更が発生する作業をしてから再起動するときなので、それへの対策を考えてみました。

現時点ではこれらで完全な対策になっているかはわかりません。手動でsyncをしてから再起動するなり、停止したときは問題が起きていないので大丈夫だと考えていますが、まだ十分な実績があるというわけではありません。

対策の基本は、下記です。

  • 2Aの電源を利用
  • 高速モードの設定などを追加して使用
  • 終了時にはsyncを実行してから停止

なお、ファイルが壊れて起動しないときは、microSDカードを他のLinuxマシンなどにつなげて(USBのカードリーダなどでRaspberry Piへつなげてもいいでしょう)、fsckコマンドを使えば復活するかもしれません。手元では基本的に復活しています。


カードの復活方法
最初にカードの復活方法について説明しておきます。LinuxマシンへmicroSDカードを接続してください。USBのカードリーダなどでつなげることが多いでしょうから、最初にlsusbコマンドなどで認識されているかを確認しておきましょう。その後、fdiskコマンドでmicroSDカードのディスクを確認します。Raspbianをddコマンドなどでインストールした場合は、/dev/sdc1にboot、/dev/sdc2にrootとなっているはずです(sdcではなく、sdbやsddとなる人もいるでしょう。sdの後に続く文字が何かはきちんと確認しましょう。microSDカードをつけたりはずしたりしたときに増減するデバイスを確認すればいいです)

$ sudo lsusb
$ sudo fdisk -l

最近のLinuxであれば自動マウントしてしまうので、アンマウントします。しない場合はスキップしてください。mountコマンドでマウントされているデバイスを確認し、sdc2にマウントされているものをアンマウントします。ここでは、/dev/sdc2が「/media/xxxxxxxxxxxxxxx」にマウントされていたとします。

$ sudo mount |grep sdc
$ sudo umount /media/xxxxxxxxxxxxxxx

fsckで修復します。修復するか聞かれたら、yを入力しましょう。

$ sudo fsck /dev/sdc2

これで、復旧するはずです。

基本対策
まず、電源は2Aのものを用意しましょう。出力電流が低い電源だと安定しません。また、再起動をする前にsyncを実行しましょう。

$ sudo sync

cmdline.txtで対策
/boot/cmdline.txt に高速転送対応の設定を追加します。bootは、WindowsやMacなどでも編集できるので、最初に編集しておくと良いでしょう。Raspbianを起動してから修正してもいいです。「sdhci-bcm2708.allow_highspeed=1 sdhci-bcm2708.emmc_clock_freq=500000000」を先頭へ追加しています。

変更前↓

dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

変更後↓

sdhci-bcm2708.allow_highspeed=1 sdhci-bcm2708.emmc_clock_freq=500000000 dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

***** 2015年3月10日追記:ここから *****
下記の「終了時に自動sync」については、2015年3月10日に下記を実行してからは対策不要になったようです。

$ sudo apt-get update && sudo apt-get -y upgrade
$ sudo rpi-update

ファームウェアの更新、ブートローダやファイルシステム関係の更新がされているようだったので、どれが効果があったのかはわかりませんが、ELECOMのカードも安定するようになりました。
***** 2015年3月10日追記:ここまで *****

終了時に自動sync
基本的に最新のLinuxではhalt時に自動でsyncはするはずなのですが、それがうまく適用されていない気がします。そこで、自動でsyncを実行するように、さらに追加しておきます。「/etc/init.d/do_sync」にファイルを作成します。

#! /bin/sh
### BEGIN INIT INFO
# Provides:          do_sync
# Required-Start:
# Required-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Execute the sync command.
# Description:
### END INIT INFO

PATH=/sbin:/usr/sbin:/bin:/usr/bin

do_stop () {
  /bin/sync
  /bin/sync
  /bin/sync
}

case "$1" in
  start)
	# No-op
	;;
  restart|reload|force-reload)
	echo "Error: argument '$1' not supported" >&2
	exit 3
	;;
  stop)
	do_stop
	;;
  *)
	echo "Usage: $0 start|stop" >&2
	exit 3
	;;
esac

:

次のようにして登録をします。

$ sudo chmod 755 /etc/init.d/do_sync
$ sudo update-rc.d do_sync defaults

なお、登録を解除するには下記

$ update-rc.d -f do_sync remove

ちなみに、do_syncを登録しても処理が完了してから電源が切れるのではなく、処理完了前に電源が切れている気がします(sleepなどを入れても電源が切れるまでその時間分遅くなっていないようなので)。なので、気休めにしかならないと思いますが、入れないより入れておいたほうがいいので実施しています。

終了用スクリプトを用意
/usr/local/bin/ に、次の reboot.sh、shutdown.sh、poweroff.sh コマンドを用意して、これらを使うようにします。

#!/bin/sh
sync
reboot
#!/bin/sh
sync
shutdown $@
#!/bin/sh
sync
poweroff

実行時はsudoが必要です。/usr/local/binにはPATHが通っているので、shファイルを実行可能にしておけば、そのまま呼び出せます。

$ sudo chmod 755 /usr/local/bin/*.sh
$ sudo poweroff.sh

以上です。

同じタグの記事: Linux
同じタグの記事: Raspberry Pi
同じカテゴリの記事: Linux