Moiz's journal

プログラミングやFPGAなどの技術系の趣味に関するブログです

Raspberry Piのベアメタル環境からSDCARDにアクセスする(SPIモード編)

はじめに

Raspberry Piのベアメタル環境からSD CARDをアクセスする方法について、限定的ながらある程度成功したので紹介します

周辺機器アクセスはベアメタルの鬼門

ベアメタルというのはOSなしの環境なので、当然ながらプログラミングにあたって各種OSの便利な機能を使うことができません。その中には当然、周辺機器のアクセスも含まれます。
そんな中ベアメタルで周辺機器にアクセスしようとする場合、

  1. ベアメタルで動作するライブラリを見つける
  2. 自分で何とかする
  3. 他の代替手段を探す

といった対策が必要になります。このうち1は一番簡単ではあるのですが、そもそも見つからない、見つかっても自分の目的と微妙に違う、ドキュメントが少ない、などの状況に出会うことがあり、常に万全の状態で使えるとは限りません。実際私が以前OSを移植した時は、Raspberry Piのフォーラムで見つけたSDCARDアクセスコードを許可を得て使わせてもらったのですが、その後バグの存在を指摘されたにもかかわらず動作の詳細が不明なため完全には修正することができませんでした。 また、3は逃げに近いのでなるべく避けたいところです。そうなった場合、「自分でなんとか」しようとするわけですが、次に出会う問題点がベアメタル特有のドキュメントの少なさです。場合によっては情報がまったく無く、詰んでしまう事もめずらしいことではありません。もちろんガチ勢の場合、既存のソフトのリバース・エンジニアリングや対象デバイスの解析などを駆使してどうとでもしてしまうわけですが、われわれ一般人にはかなりつらいところです。

Raspberry PiのSDCARDコントローラー(EMMC)はドキュメントが微妙

数ある周辺機器の中でもストレージは最も基本的なものです。これにアクセスできなければとたんにできる事の範囲が極端にせまくなってしまいます。
Raspberry Piの場合メインのストレージは言わずとしれたSDCARDで、Raspberry PiのCPU(BCM2835)にはEMMC(External Mass Media Controller)というIPが搭載されており、SDCARDとのアクセスをサポートしてくれます。そのEMMCの使い方は、と探してみるとBCM2835 ARM PeripheralsマニュアルにEMMCの項が見つかります(P.65 5 External Mass Media Controller)。
ここで、これは楽勝か?と思いつつ読み進めていくと、どうも勝手が違い読みにくいことに気が付きます。記述が断片的でどのように設定すればばSDCARDにアクセスできるのかわかりません。さらに読みすすめるとこのような文に出会います。

For detailed information about the EMMC internals please refer to the ArasanTM document SD3.0_Host_AHB_eMMC4.4_Usersguide_ver5.9_jan11_10.pdf but make sure to read the following chapter which lists the changes made to ArasanTM’s IP.

どうやらEMMCの使い方はArasanのドキュメントに書いてあり、BCM2835のマニュアルにはそこからの差分しか載っていないようです。記述が断片的なのはそういう理由があったわけです。 それでは、と、Arasanのドキュメントを探すと見つかりません。どこにも見つかりません。インターネット上をさんざん探しましたが、どうやら非公開のようです。やられた...。

まとめると

  • SD CARDへのアクセスが必要
  • BCM2835のEMMCの情報が必要
  • ArasanのIPの情報が必要
  • ArasanのIPのマニュアルは非公開
  • 詰んだ

困りました。

SDCARDのピンはGPIOにつながっている

このように途方にくれながらRaspberry Piのスキマティクスを見ているとSDCARDのピンはGPIOにつながっている事に気が付きました。 f:id:uzusayuu:20180520131226p:plain このあたり専用ピンにつながっているUSBとは事情が違うわけです。さて、ここでこんな考えが頭にうかびます。

「GPIOにつながっているんなら、GPIO経由でソフトでアクセスできるんじゃね?」

これは何も無茶な考えではなく、マイコンなどでは普通に行われる方法です。たとえばCQ出版の「フラッシュ・メモリ・カードの徹底研究」にはソフトウエアコントロールでMMCにアクセスする方法が、同社の「FPGAスタータ・キットで初体験!オリジナル・マイコン作り」にはNIOSからSD CARDにアクセスする方法が記載されています。 やるべきことは、

  1. EMMCを止める
  2. GPIO48から53を、ALT0(EMMC)からInputまたはOutputにつなぎ替える
  3. ソフトウェアからGPIOを制御しSDCARDをSPIモードにする
  4. 同様にソフトウェアでSDCARDの初期化を行う
  5. 同様にSDCARDからの読み出し、書き込みを行う

以上です。ソフトウェアは上記の2書籍に例があるので参考にしつつすすめる事ができます。また、SDCARD自体のコントロールについては、SDのスペック(SD Specifications Part 1 Physical Layer Simplified Specification)に十分な内容の情報があります。なんとかなりそうですね。

SDCARDにアクセスできた、が...

詳細は次回に譲るとして、試行錯誤のすえ、SDCARDの初期化と読み書きアクセスに成功しました。次の図は、SDCARDのFAT領域をベアメタル環境で読みだして、ファイルのリストを表示した結果です f:id:uzusayuu:20180520132857p:plain

今回のデモプログラムはgithubにて公開してあります。

github.com

ただ、ここで大問題があります。
どうやら、次のスペックの記述によると、SDモードからSPIモードへの変更は電源投入後の一回しかチャンスがないようです。SDのスペックの7 SPIの最初の項7.1 Introductionに次のような記述があります。

The interface is selected during the first reset command after power up (CMD0) and cannot be changed once the part is powered on.

Raspberry Piは本体のROMに記録されているブートロジックが最初のブートローダーをSDCARDから読み出すので、この時点でSDCARDはSDモードに設定されています。したがってSPIモードに変更し直すことはできないという事のようです。(痛恨)。 デモプログラムではユーザーにカードの抜き差しをしてもらうことでこの問題点を回避していますが、ちょっと実用的ではありません。やはりSDモードでのコントロールを考えないといけないようです。

あともうひとつ、ソフトウェアコントロールでシリアル通信なので読み・書き・コントロールすべて遅いです。デモではルートディレクトリのファイルを表示するのに1分くらいかかっています。*1

まとめ

以上、Raspberry Piのベアメタル環境からGPIO経由でSPIモードでSDCARDにアクセスすることにある程度成功したので報告しました。 実用性はあまりありませんが、SDCARDにコントロールIPをはさまず直接アクセスできるので、SDCARDの動作を理解するのには役に立つのではないかと思います。 次回以降、処理の詳細について説明したいと思います。

*1:これはさすがにちょっと遅すぎるので、どこか他の部分に問題があるのかもしれません。そのうちどこが本当にボトルネックになっているか調べてみたいと思います。

プロセッサの中のプロセッサとインストラクション・セットの多様性

プロセッサの中にも多数のプロセッサがいる

最近出版された「コンピュータ・アーキテクチャ 定量的アプローチ 第六版」に新設された第7章のドメイン・スペシフィック・アーキテクチャ(DSA)の章を読んでいたところ、面白い記述があった。まず前提としてライセンスの面倒さなどから、DSAには独自のRISCプロセッサを導入して、コンパイラやライブラリを移植することが多いという前置きのあとで、このように書かれている。

One AMD engineer estimated that there were 12 instruction sets in a modern microprocessor! (あるAMDのエンジニアの見積もりでは最近のマイクロプロセッサには12種類のインストラクションセットが含まれているという)

AMDのエンジニア、最近の、という言葉からおそらくRyzenやその関係のプロセッサではないかと思うが、実際にどのプロセッサなのかかは定かではない。 私自身も半導体の会社で働いているのでSOCに*1はメインのCPU以外にも多数のプロセッサが搭載されていることは事実として知ってはいたが、12種類のインストラクションというのは随分多いと感じる。なにしろインストラクション・セットが12種類ということは、搭載されているプロセッサは少なくとも12個以上で、そのうち命令が異なるものが12個ある、ということだ。 しかし同時に、いや大規模なSOCならそれくらいあってもおかしくないぞ、とも思う。

プロセッサ中のプロセッサの例

こういったSOCの中にメインのCPU以外に含まれるプロセッサというのは、内部の制御用だったりハードウェアの動作の一部または全部を引き受けたりするものなので、基本的にエンドユーザーやアプリケーション作成者からは見えないようになっている。したがって開発関係者以外には、仕様も場合によっては存在自体も隠されていることが多いのだが、ときどきその存在が表に現れる。

まず例としてAMD自身がEPYC中にX86とは別のプロセッサをセキュリティ用に搭載していることを発表している。

pc.watch.impress.co.jp

記事中「ARMのCortex-A5をセキュリティエンジンとして搭載しており、OSインディペンデントなセキュリティを提供する。」とある。つまり、EPYCにはOS上の操作しかしない一般ユーザーからは見えないプロセッサが最低でも一個搭載されていることになる。当然このプロセッサ用の開発環境、ライブラリ、OSはメインCPUとは別に作られ、チップの開発チームやパートナーのみに提供されているのだろう。

また、Tensilica*2のXtensa DSPは、Wikipediaの記述を信用するなら、PS4のプロセッサや、AMDのAPUなどに採用されているようだ。

Tensilica - Wikipedia

AMD TrueAudio - Wikipedia

これはWikipediaの記述だが、私自身もXtensaがオーディオ用として他のSOCに採用された例を見ているし、Tensilicaによるとこれまでに1400以上の採用実績があるということなので、多数のSOCで搭載されているのはおそらく間違いない。

ip.cadence.com

AMD以外に目を向けると、以前私も開発に関わっていた携帯用SOCのOMAPの画像処理プロセッサにはARMのCoretex-Mが制御用として搭載されていた。

http://www.ti.com/pdfs/wtbu/OMAP4470_07-05-v2.pdf

http://www.ti.com/lit/wp/spry242/spry242.pdf

OMAPシリーズにはこの他に画像処理アクセラレータのiMX、さらには当然ながらTIのDSPも搭載されており、GPUと合わせて今流行りのHeterogeneous Computingの先駆けを進んでいたと言っていいだろう。このあたりはTI自身が公開している上記の資料に詳しい。

ISAの多様性とRISV-V

ここで例にだしたのはセキュリティ、オーディオ、あとは画像処理という3種類のIPだが、現代のSOCにはこれ以外にも多種多様のIPコアが含まれている。 ちょっと考えただけでネットワーク、ディスプレイ、USB、電源管理、ストレージ、などなど。それぞれに専用のIPがありそれぞれ制御が必要な事を考えると、いくつかには専用プロセッサが搭載されていると推測するのは大きく間違ったことではないだろう。IPごとに必要な機能に過不足ないプロセッサを採用することを考えると、それぞれインストラクションが異なるということは十分にありそうな話だ。そうなれば最初の「最近のマイクロプロセッサには12種類のインストラクションセットが含まれている」という話もあながち大げさというわけではなさそうだ。さらに考えると、このプロセッサ群は当然コンパイラやライブラリーと一緒に提供され、多くの場合OSが動作しているはずだ。またデバッガなどの開発支援環境も当然それぞれ存在するのだろう。こういった想像は、これまで複数の会社でSOC開発に関わってきた私自身の過去の経験ともそんなに乖離していない。

また、SOCというと携帯や組み込み機器の中に入っているもの、というイメージがあるのかもしれないが、実は最近のPCのCPUはほとんどの場合SOCだ。 これはタブレット型や2in1タイプはもちろんのこと、ラップトップ、さらには多くのデスクトップまであてはまる。こういったPCに搭載されるCPUは、電源やUSB、メモリインターフェースといった昔からある機能はもちろんのこと、オーディオ、ビデオ、カメラ、などなど、PCに必要な機能の多くをオンチップで搭載している。例えば最近のノートPC用のチップを考えると、ダイ上の面積的に一番大きいのは大概GPUで、X86のコードを実行するいわゆるCPUと呼ばれる部分の面積はさらに残りの部分の半分ほどの事が多い(実際の面積比はSKUによって大きく異なります)。つまり、CPUの占める面積は意外なほど小さいのだ。

そして、残ったの面積は多数のIP*3が占めている。我々が普段使っているPCのCPUには、私達が存在も知らずアクセスすることもできないプロセッサが多数搭載されていて、その上で専用のコードやOSがユーザーの意志とはまったく関係なしに動きまわっている可能性が高いわけだ。

そう考えると、x86系とARM系の寡占化が極まったと考えられているCPUのインストラクションセットも、実は意外なほどの多様性を備えていることがわかるだろう。同様に、CPUの構造(マイクロアーキテクチャ)や、その上で動作するアセンブラ、OS、また開発に使用するコンパイラなども同様に多様なのだ。

では、これからもその多様性が広がっていくか?と考えると、少し疑問が残る。まず、明らかな問題として無駄が多い。たった一つのSOCを開発するのに12個も開発環境を用意し、それぞれノウハウもスキルベースも異なるコードを開発しメンテナンスするのはどう考えてもコスト高だ。さらに、一個一個のプロセッサに割ける人員も時間も予算も限られるので一つ一つが十分に洗練されていない、という可能性も出てくる。当然、ちょっと数を減らそうか、という話はでてくるはずだ。

ここで最初の「コンピュータアーキテクチャ」に話を戻すと、この本では「だからRISC-V*4」を使おう、という主張になっている。統一されたインストラクション、共通の開発環境を使えばこういったムダが一層されるわけだ。

さて、私自身はこれを読んだあとも「そううまくいくかね?」と思っていたのだが、先日こんなニュースが飛び込んできた。

www.itmedia.co.jp

このヘネシー氏は「コンピュータアーキテクチャ」の著者の一人。もう一人のデビッド・パターソン氏もGoogleに在籍していることを考えると、今後GoogleRISC-Vに力を入れてくることは予想に難くない。そうなると、意外とRISC-Vが広がってインストラクションセットの多様性を終焉させる、ということもありえないわけではないのかな、という気がしている。

さて、どうなりますかね?

*1:システムオンチップ, SoCとも

*2:現在はCadenceの一部

*3:Intellectual Property、半導体分野では機能ブロックやその設計資産を示す

*4:RISC-VはオープンでフリーなCPUインストラクションセット。最近盛り上がりをみせている

「実践コンピュータビジョン」の全演習問題をやってみた、というブログを書いた

夏頃にオライリージャパンの「実践コンピュータビジョン」という本を読み、全演習問題に挑戦しました。もともとこのブログにそのことを書こうと思っていたのですが、はてなブログでは大量のコードが出てくる記事を書くのがなんともおっくうで、延ばし延ばしになってきました。

先日思い立って、コードなどを書くのに楽なQiitaの方でそのことをブログに書きました。まとめ一つと、各10章に対応するエントリー、合計11本です。

 

qiita.com

qiita.com

qiita.com

qiita.com

qiita.com

qiita.com

qiita.com

qiita.com

qiita.com

qiita.com

qiita.com

ブログが分散するのは管理も大変だし、あまり好ましくないんですが、はてなでブログでコード挿入するのが面倒なのはなんともならず。いまさらはてなダイアリー表記に戻す気にもならず。

衣類乾燥機を修理してみたよ

衣類乾燥機が壊れた

先日衣類乾燥機が突然動作しなくなった。

パネルやモーターなどは普通に動いていて排気口からは風も出てくるが、温度が上がらず当然衣類もまったく乾かない。買ったのは四年前で当時入ったショップの延長保証も1年前に切れている。さて困った。買い換えか。

直し方をWEBで調べる

どうせ買い替えするのなら、最後遊びだと思って修理に挑戦してみよう。そう思ってWEBを検索すると多数衣類乾燥機の修理例がでてくる。さすがDIYの国アメリカ。後で書くが、乾燥機の構造自体も修理を前提として作っているような節がある。

どうやら、『一見普通に動作してそうなのに温度が上がらない』という場合の典型的な故障箇所は、ヒーターユニットかヒューズらしい。Youtubeに私が使っている製品とほぼ同じ機種について、詳細な点検方法と修理方法がアップされていた。

www.youtube.com

たぶんこれなら自分で直せそうだと判断し、早速分解にかかる。

分解!

工学系のステロタイプよろしく、私は分解が好きだ。大好きだ。

物をばらして中がどう動作するのか調べるのはわくわくする。そして良く壊す。今回はもともと壊れているので、さらに壊してもたいした損害じゃ無いから気が楽だ。そんなわけでどんどん分解していく。

手ぶれが酷くて申し訳ないが、これが元の姿。

f:id:uzusayuu:20171002122955j:plain

上部及び前面パネルとドアを外したのがこちら。

f:id:uzusayuu:20171002123013j:plain

これを見ればわかると思うが、かなーり大雑把な構造だ。日本のメーカーが日本向けに作ればサイズは2-3割小さくなるのではないかと思う。おそらくアメリカ向けの製品はサイズや機能よりも直しやすさ(部品の入手性含めて)が重視されているのだろう。

さてこのドラムを外すととうとうヒーターユニットとご対面だ

f:id:uzusayuu:20171002123054j:plain

雑!、というのが正直な感想だが、おかげで修理ができるので文句をいう筋合いもないだろう。コネクタを外してマルチメーターでヒーターの抵抗をしらべると無限大とでた。これでヒーターの故障に間違いないだろう。

修理

ヒーターユニット部分の蓋を外してみるとこんな感じのヒーターユニットが入ってた。

f:id:uzusayuu:20171002124744j:plain

子細に点検すると、あった。

f:id:uzusayuu:20171002123130j:plain

見事に切れてる。これじゃ温度が上がるわけが無い。早速交換部品をアマゾンで購入。$20を切る値段だった。安い。

左が故障したヒーターユニット、右が新品。

f:id:uzusayuu:20171002124404j:plain

新しいヒーターユニットの取り付け。

f:id:uzusayuu:20171002123034j:plain

一応導通と絶縁を確認して、後は、ドラムやパネルを一個一個元に戻していくだけ。最後に電源を戻し、試運転、無事動作しました。

まとめ

服が乾かない!の第一報から修理まで3日で済んだ。金銭面でずいぶん安く済んだのはもちろんのこと、修理を頼無にせよ新品を買うにせよおそらくは2週間くらいはかかっただろうと考えると、時間の節約という面でもずいぶんDIY修理のメリットはある。(日本みたいに次の日配達据え付けとかならいんだけどね...。)

今回衣類乾燥機を分解して思ったのは、アメリカ向けの家電は、機械自体も部品の入手性も、あと、情報の入手性も、修理がしやすいようにできている、ということ。その分最新の機能だとか、コンパクト性だとか、電力効率だとかは手薄になっているのかもしれない。おそらく日本の日本向けの製品とは思想が違うのだろう。なんにせよ、面白かった。(あと、ちゃんと直って良かった。)

ラズベリーパイ版Haribote OSのビルド環境とインストール方法

だいぶ間があいてしまいましたが、ラズベリーパイ用Haribote OSのビルド方法について紹介します*1

PC環境はUbuntu 16.04を想定していますが、他のバージョンのUbuntu又は、他のLinuxでも同様にビルドできると思います。

2017.10.13追記: Raspberry Pi上のStretch上で試してみたところ同様の手順でビルドできるようです。gccのバージョンは6.3.0でした。*2

 

ラズベリーパイ版Hariboteのビルド

ラズベリーパイに移植したHaribote OSはGithubに公開してあります。

github.com

”Clone or download"からzipをダウンロードします。(もちろんgitを使ってリポジトリをクローンしてもかまいません。その場合は当然ながらgitをインストールして、githubsshで接続する設定をしておく必要があります。)zipファイルは作業フォルダーに展開しておきます。Ubuntuなら右クリックから"Extract Here"で展開できます。

ビルドにはクロスコンパイル用のライブラリーが必要なのでインストールします。Ubuntuならクロスコンパイル用のライブラリーは次のコマンドで簡単にインストールできます。

sudo apt-get install gcc-arm-none-eabi

他のディストリビューションでは他の方法でインストールする必要があるかもしれません。こちらのCambridgeのOSのコースの開発環境構築方法が参考になるとおもいます。

Computer Laboratory – Raspberry Pi: Downloads

これでビルドできるはずです。やってみましょう。

展開したフォルダの最上位階層でMakeします。

make all

これで、Hariboteフォルダ内にkernel.img、binフォルダ内にアプリケーションのバイナリ(.out)ファイルが作られるはずです。

起動用SDカードの準備

次にRaspberry Piの起動用SDCARDを用意します。一旦起動したSD CARDはHariboteをビルドするたびに使いまわしができるので、この項はSD CARD毎に一回やっておけばすみます。

Raspberry Piは以下のファイルをブートローダーとして使用します。RPiHariboteではいずれもRaspbianなどの起動フォルダに含まれているものを流用します。

bootcode.bin

start.elf

これらのファイルがkernel.imgをロードして OSが立ち上がります。RPiHariboteはこのkernel.imgを置き換えることで起動します。

まずSDCARDを用意します。容量はRaspbianがインストールできるサイズ(4GB程度以上のSD/SDHC)なら問題ありません。また、Zeroで動作させる場合はMicro SDを使用します。Raspbianをインストールする際にデータはすべて消えてしまうので、それでも構わないSDCARDを使用ください。

次にRaspbianのツールを用いてRaspbianをSDCARDにインストールします。こちらにオフィシャルのインストラクションがあります。

www.raspberrypi.org

イメージのダウンロードはこちらです。Raspbian自体は使わないので、今回はサイズの小さいRaspbian Stretch Liteをダウンロードして、解凍します。

Download Raspbian for Raspberry Pi

同様にEtcherをダウンロードして、解凍して実行します。

etcher.io

先ほど解凍したRaspbian Liteのイメージ(今回の場合"2017-09-07-raspbian-stretch-lite.img")を選択し、対象のSDCARDが選択されていることを確認したら、Flashをクリック。

f:id:uzusayuu:20170910034749p:plain

ここまではRaspbianの起動ディスク作成と同じですので、もし何か上手く動作しない場合はWebを検索すればいくらでも情報が出てくると思います。

次の項に進む前にいったんこの状態で起動し正常に動作することを確認しておきます。一度起動させて置かないと正常にHariboteが動作しないようです。

インストール

作成した起動ディスクのBootフォルダの方の中身をみてみると、kernel.imgというファイルがあります。ラズベリーパイ用Hariboteはこのファイルを置き換えることで実行されます。

まず、もともとのkernel.imgをkernel.bakなどにリネームします。

次に、先ほどビルドしたフォルダから haribote\kernel.imgをここにコピーします。(最上位階層のkernel.imgはgithubからダウンロードしたものです。これでも動作はしますが、先ほどビルドしたものとは異なります)。

次に、bin\以下のファイルをkernel.imgと同じフォルダにコピーします。アプリケーションの.outファイルも、アプリケーション内で使用するデータ類(.org, .fnt, .txt)もすべてコピーします。結果はこのようになると思います。

f:id:uzusayuu:20170910040644p:plain

もし、config.txtに何か設定が必要な場合は設定しておく必要がありますが、ほとんどの場合はそのままで良いと思います。*3

あとは、SD CARDをイジェクトして、対応しているラズベリーパイ(Model B+、又はZero。他の機種では動作確認されていない)に差し込み、起動。うまく行けばすぐにコンソールが表示されるはずです。

f:id:uzusayuu:20170909134412j:plain

 これで、Raspberry Pi用のHariboteをビルドして実行できました。

 

 

 

 

 

*1:実をいうと最近Linuxの環境を別のPCに移したので環境再構築の備忘録なのですが

*2:以前Jessie上で試した時はエラーがでてコンパイルできなかったように記憶しています。何か変わったのかもしれません

*3:私の環境ではconfig.txtにディスプレイの設定を加えないと綺麗に表示されないが、これはディスプレイが特殊なため