「 linux 」一覧

PowerVR SGX*** のカーネルドライバのソースコード


結構触っていない期間が長くなってしまいましたが MIPS Creator CI20 の最近の様子はどうだろうと思って調べてみました。http://elinux.org/MIPS_Creator_CI20 にアクセスしてみたら、実は既にこのボードって3世代くらいになっているようです。形的には最新の世代の正方形に近いものがいいなぁと思ってます。しかし未だに日本の発売はなさそうで、残念。

今の最新では Debian 8 の環境開発が進んでいるようで、SGXドライバが使えないという話は昔の話となりつつあるような感じです。そして自分が使っていたシステムイメージなどは CI20_Distros_Legacy のページに行ってしまっていました。
そしてこのページには Debian 8 Jessie 部分で、”Graphics acceleration will not work (the powervr drivers currently don’t work with xorg 1.16).” なんて記載が残ってました。現行のページでは release note にもそんな話は見当たらないので、そこそこ使えたりするんじゃないでしょうか。そのうち時間できたら試してみるかもしれません。

その一方で驚いたのが CI20_Dev_Zone のページです。こちらは通常は覗くことがないかもしれません。自分もたまたま発見したのですが、このページの後半で Linux Kernel のビルドに関しての説明があるあたりで驚きました。
 それが “Building GPU Kernel Module from sources” という部分です。 PowerVR の SGX のドライバは今まではバイナリ提供でソース類を明かさなかったのですが、コレを見るとカーネル部分のドライバソースも公開されているようです。これらに関してはこちらの CI20-SGX_kernel_moduleのページのようです。ここでは 3.0.8 でも 3.18 カーネルでも対応してるっぽいです。

 ちょっと興味があったので中身を開けてみたら、 pvrsrv のソースっぽいものがあったり、各PowerVR のチップ(sgx530, sgx535, sgx543, sgx544, sgx540)といったもののレジスタのヘッダがあったりととてもおもしろい気がします。このあたりのチップは他の組込ボードでも使われているケースがあるので、割と使えるものな気がしています。

OpenGL も動くグラフィックスドライバがソースコード付きの公開というのは自分は初めて見た気がします。これはとても興味深いですね。(ただしOpenGLの解釈部分などはここじゃないようですが)


Ubuntu で USBシリアルケーブルを使う 続編


前回は minicom でつながるのを確認しました。あれからそもそも Raspberry Pi だったらシリアルコンソールで操作も可能だったことを思い出して、そちらでも確認をと思ったので今回のメモを書いてます。
Raspbery Pi は Raspberry Pi 2 のことをさしています。またシリアル出力を有効化する詳細な手順と、一般ユーザーでもシリアルを使えるようにする手順については今回省略させていただきます。一般ユーザーでも使えるようにする方法は以前の日記を参照してください。

ツール: gtkterm

GUIもあるターミナルソフトです。これをインストールしてみました。

デフォルト設定を作ることができ、ここでデバイスのパラメータを指定することができます。GUIから起動させる場合にはデフォルト設定を使った方が便利な気がします。
ubuntu-serial-1
コンソールであれば起動のオプションで指定も可能です。省略すればデフォルト設定が使われるようです。
ubuntu-serial-2

ツール: screen

コンソール作業では割とおなじみらしい screen です。

使い方はオプションにデバイスらのパラメータを入れます。

ubuntu-serial-3
screen の終了のさせ方は知らないとわからないので注意。
”Ctrl+a”, ”k”と押します。

終了確認が問われるので “y” をタイプして終了します。
ubuntu-serial-4

起動時のログなど

Raspberry Pi の起動時からシリアルをつないであったとき、以下のように動いてました。
ubuntu-serial-5


USBシリアルケーブルを買った(PL2303のやつ)


Raspberry Pi 2 との接続のためにお遊びで USB シリアル変換ケーブルを買ってみたのですが、 Windows 8.x 以降ではいろいろな問題のために使えないというシロモノでした。普段の環境は Windows7 だったりするので問題に直面しているわけではないですが、今後のことも考えて対策を考えてみました。
 その結果が Ubuntu で使用する!です。こちらならばドライバの問題はなさそうなので。今回はその設定についてメモしておこうと思います。 続きを読む


Jetson TK1をSDカード起動にする


Jetson TK1のシステムや作業領域としてSDカードを使用するように切り替えました。
容量の問題とか書き換え回数制限とか気にしてです。SDカードならシステム破壊するようなことをしても、交換可能ですし、バックアップもやりやすそうですし、メリットが多くあると思います。

準備

ここではVMware上の Ubuntu 14.04 で作業しました。
必要なファイル群をNVIDIAから入手します.

Tegra124_Linux_R19.3.0.armhf.tgz2
Tegra_Linux_Sample-Root-Filesystem_R19.3.0_armhf.tbz2

そしてこれを適当なところに展開して、コマンドを実行します。
これらの作業コマンドを以下に示しておきます。

$ wget https://developer.nvidia.com/sites/default/files/akamai/mobile/files/L4T/Tegra124_Linux_R19.3.0_armhf.tbz2
$ wget https://developer.nvidia.com/sites/default/files/akamai/mobile/files/L4T/Tegra_Linux_Sample-Root-Filesystem_R19.3.0_armhf.tbz2
$ tar xpf Tegra124_Linux_R19.3.0_armhf.tbz2
$ cd Linux_for_Tegra/rootfs
$ sudo tar xpf ../../Tegra_Linux_Sample-Root-Filesystem_R19.3.0_armhf.tbz2
$ cd ../
$ sudo ./apply_binaries.sh

書き込み

ファイル群が準備できたので、これをSDカードに書き込みます。
手元のカードリーダーでSDカードを装着して確認したところ、/dev/sdb として認識しているようでした。各自の環境ではこのあたりが変わると思いますので、適宜読み替えて下さい。

SDカードがフォーマットされたところで、データを書き込みます。

Jetson TK1をUSB(microUSBのほう)でLinux環境と繋いでリカバリーモード起動させます。
リカバリーモードに入るには、Recoveryスイッチを押しながら、Resetスイッチを押します。

リカバリーモードに入った後で、Linux環境で以下のコマンドを実行します。
念のため、認識できているか lsusb で確認しています。
リカバリーモードに入っているときには、画面に何も出力されないので…。

というように表示されて、正常に書き込まれるとJetson TK1が再起動されます。

fastboot.bin というバイナリが送られているようですし、方式としてはfastbootのほうでしょうか。
19.3バージョンからは、U-BOOTもサポートされたとありましたし、そのうち試してみたいところです。

再起動後、SDカードを挿さないままだと、起動が途中で止まるはずです。
止まったことを確認したら、SDカードを挿入してみます。
うまくいけば、ここから起動シーケンスが再開されていくと思います。
(画面が出ないようなら、リセットして試してみましょう)

初期設定など

Jetson TK1が無事にSDカードから起動できたら、初期設定をしておきます。
タイムゾーンは Asia/Tokyo を選択して時刻を合わせておきます
(実際にはRTCは、電源OFFでリセットされちゃうんですが・・・)
他にもリポジトリの設定とか。

コマンドが見つからなかった場合のヘルプ(どのパッケージに入ってるのか)を出すための設定.

最後に使用量を確認しておきます。
SDカードが16GBの物を使っているのでこんな感じでした。

デフォルトの eMMCに入っている時には 8GBほどのパーティションだったと思います。
上記のように15Gが表示されていますし、無事にSDカードのシステムが使われているように思います。

感想とか

最後に感じたことを1つ。
安物SDカードだとか、クラスの低いものを使っていると、操作に引っかかりをよく感じます。
気になる人は、ちゃんとした高速なものを使用するようにしましょう。

最後に

元の起動に戻す方法は、リカバリーモードにして以下のコマンドを実行します。


cygwinでクロスコンパイラのmake


ARM用クロスコンパイラのビルド(Windows8+Cygwin)
を参考にCygwinでクロスコンパイラのビルドをしてみました。
さすがに全部入りの状態なので、cygwinのインストールには時間がかかりました。

確かにgccのビルドまで成功までいけたのですが、thread modelがsingleに。
これをposix となるように –enable-threads=posix とするとgccのmake時にエラーとなってしまいうまくいかず…。

というエラー行が発端なので、pthread.hが正しく読み込めていないんだろうと思います。
(ファイルはあるけど中身がおかしい?)

Windowsでクロスコンパイラの準備から始めるのはちょっと大変なのがわかりました。


cygwinでcrosstool-ngのmake


クロスコンパイラなどのクロスツールチェインを作るためのツールとして、crosstool-ngが便利です。
Ubuntuなどではこれを利用してクロス環境を整えるのがとても手軽だと思っています。
今回はそのcrosstool-ngをWindowsのcygwinで生成できないかを試してみました。

そもそも、crosstool-ng は http://crosstool-ng.org/ で入手できます。
これを cygwin で使用するためには以下のパッチを適用します。このパッチはここで紹介されていましたが、パッチファイルがダウンロードできないようだったので、ここにテキストとして貼り付けておきます。

このパッチを適用してmakeする例としてはこんな感じで。

実際に動かす際には、Windowsのファイルシステムにおいて大文字小文字を区別するように変更する必要があるようです。
レジストリの次の場所を書き換えます。

実行とまとめ

/opt/cross/bin/ct-ng が実行可能状態になっていると思います。
あとはパスを通して実行できるように下上で、 ct-ng menuconfig や ct-ng build でツールチェインのビルドが可能だと思います。ただし、手元の環境ではどうもgccのmake途中でエラーになってしまいうまくいきませんでした。設定関連がわるい可能性があるので、それは調査中です


クロスコンパイラgccのビルド -成功編


ようやくクロスコンパイラ gccをmakeすることに成功しました。
JetsonTK1をターゲット想定なので、デフォルトで hard float を使用するようにしたかったので、その設定となるようにしています。
早速その手順をここに書いておきたいと思います。

makeinfoのバージョンが5以降だとエラーになるようなので、それ以前のものをインストールしておきます。

$ sudo apt-get install ncurses-dev gawk
$ tar xvzf texinfo-4.13a.tar.gz 
$ cd texinfo-4.13a
$ make
$ make install

gccに必要な他のライブラリを用意しておきます。

これらをとりあえず作業ディレクトリにダウンロードしておきます。

binutilsを準備

$ export CROSSTOOL=$HOME/cross-toolchains
$ export TARGET=arm-linux-gnueabi
$ export SYSROOT=$CROSSTOOL/$TARGET/sysroot

$ cd cross
$ tar xjf binutils-2.23.2.tar.bz2
$ mkdir -p binutils-2.23.2/build
$ cd binutils-2.23.2/build
$ ../configure --target=$TARGET --prefix=$CROSSTOOL --with-sysroot=$SYSROOT
$ make -j3 && make install

gmpの準備

$ cd ../..
$ tar xjf gmp-5.1.1.tar.bz2
$ mkdir -p gmp-5.1.1/build
$ cd gmp-5.1.1/build
$ ../configure --prefix=$CROSSTOOL
$ make -j3 &&  make install

mpfrの準備

$ cd ../..
$ tar xjf mpfr-3.1.2.tar.bz2
$ mkdir -p mpfr-3.1.2/build
$ cd mpfr-3.1.2/build
$ ../configure --prefix=$CROSSTOOL --with-gmp=$CROSSTOOL
$ make -j3 && make install

mpcの準備

$ cd ../..
$ tar xzf mpc-0.8.2.tar.gz
$ mkdir -p mpc-0.8.2/build
$ cd mpc-0.8.2/build
$ ../configure --prefix=$CROSSTOOL --with-gmp=$CROSSTOOL --with-mpfr=$CROSSTOOL
$ make -j3 
$ sudo make install

1st gccのmake

$ cd ../..
$ tar xjf gcc-4.8.2.tar.bz2
$ mkdir gcc-4.8.2/build1
$ cd gcc-4.8.2/build1
$ export CFLAGS_FP="--with-float=hard --with-fpu=vfp --with-arch=armv7-a"
$ ../configure --target=$TARGET --prefix=$CROSSTOOL \
  --without-headers \
  --without-ppl \
  --with-newlib \
  --disable-decimal-float \
  --disable-shared \
  --disable-threads --disable-libssp \
  --disable-libgomp --disable-libmudflap \
  --disable-libquadmath --disable-libatomic \
  --disable-sanitizer --disable-nls \
  --disable-libstdc++-v3 \
  --with-gmp=$CROSSTOOL \
  --with-mpfr=$CROSSTOOL \
  --with-mpc=$CROSSTOOL \
  --enable-languages=c \
  --with-mode=thumb \
  $CFLAGS_FP

$ make -j3
$ make install

2nd gccのための準備

1st gccが生成されている場所へパスを通しておきます。

$ export PATH=$PATH:$CROSSTOOL/bin

カーネルヘッダを準備します。

$ cd ../..
$ tar xjf linux-3.2.35.tar.bz2
$ cd linux-3.2.35
$ make mrproper
$ make headers_install ARCH=arm CROSS_COMPILE=${TARGET}- INSTALL_HDR_PATH=$SYSROOT/usr

glibcのヘッダの準備です。

$ cd ..
$ tar xzf eglibc-2_13.tar.gz
$ cd eglibc-2_13
$ cp -r ports libc
$ mkdir build
$ cd build
$ BUILD_CC=gcc CC=${TARGET}-gcc CXX=${TARGET}-g++ \
  AR=${TARGET}-ar \
  RANLIB=${TARGET}-ranlib \
  ../libc/configure \
    --prefix=/usr \
    --with-headers=${SYSROOT}/usr/include \
    --host=$TARGET \
    --disable-profile \
    --without-gd \
    --without-cvs \
    --enable-add-ons \
    --with-mode=thumb \
    $CFLAGS_FP

$ make install-headers install_root=$SYSROOT install-bootstrap-headers=yes
$ make csu/subdir_lib
$ mkdir -p ${SYSROOT}/usr/lib
$ cp csu/crt1.o csu/crti.o csu/crtn.o ${SYSROOT}/usr/lib
$ ${TARGET}-gcc -nostdlib -nostartfiles -shared -x c /dev/null -o ${SYSROOT}/usr/lib/libc.so
$ ln -sv ${CROSSTOOL}/lib/gcc/${TARGET}/4.8.2/libgcc.a ${CROSSTOOL}/lib/gcc/${TARGET}/4.8.2/libgcc_eh.a

2nd gccのmake

$ cd ../..
$ mkdir gcc-4.8.2/build2
$ cd gcc-4.8.2/build2 
$ ../configure \
  --target=${TARGET} \
  --prefix=${CROSSTOOL} \
  --with-sysroot=${SYSROOT} \
  --disable-libssp --disable-libgomp --disable-libmudflap \
  --disable-shared \
  --with-gmp=${CROSSTOOL} \
  --with-mpfr=${CROSSTOOL} \
  --with-mpc=${CROSSTOOL} \
  --enable-languages=c \
  --with-system-zlib \
  --with-mode=thumb \
  ${CFLAGS_FP}
$ make -j3 all-gcc
$ make install-gcc

これで作成したgccでglibcを作成することになります.

glibcのmake

$ cd ../..
$ rm -rf eglibc-2_13\build
$ mkdir -p eglibc-2_13\build
$ cd eglibc-2_13\build
$ BUILD_CC=gcc \
  CC=${TARGET}-gcc \
  CXX=${TARGET}-g++ \
  AR=${TARGET}-ar \
  RANLIB=${TARGET}-ranlib \
  ../libc/configure \
      --prefix=/usr \
      --with-headers=${SYSROOT}/usr/include \
        --host=${TARGET} \
        --disable-profile \
        --without-gd \
        --without-cvs \
        --enable-add-ons \
        --with-mode=thumb \
	${CFLAGS_FP}
$ make -j3
$ make install install_root=$SYSROOT

3rd gccのmake

作成したglibcを参照するようなgccをmakeしていきます

$ cd ../..
$ mkdir -p gcc-4.8.2/build3
$ cd gcc-4.8.2/build3
$ ../configure \
  --target=${TARGET} \
  --prefix=${CROSSTOOL} \
  --with-sysroot=${SYSROOT} \
  --disable-libssp --disable-libgomp --disable-libmudflap \
  --disable-libquadmath \
  --with-gmp=${CROSSTOOL} \
  --with-mpfr=${CROSSTOOL} \
  --with-mpc=${CROSSTOOL} \
  --enable-languages=c,c++ \
  --with-system-zlib \
  --enable-nls \
  --enable-threads=posix \
  --enable-multilib \
  --enable-c99 \
  --with-mode=thumb \
  ${CFLAGS_FP}
$ make -j3
$ make install

これで完成です。


クロス向けのgdbを用意する


前回はターゲット上で作成しましたが、今回は開発ホスト想定のUbuntu上でターゲット向けのgdbを準備します。
ここでのターゲットはARM(32bit)でEABIHF(hard float)を想定しています。まぁJetson TK1想定です。

※ Ubuntuではarm向けのツールチェインをインストール済みであるとします。apt-get等でインストールしておいて下さい。

まずはxmlで必要になってくるので expat をインストールしておきます。

sudo apt-get install libexpat1-dev

gdbを本家サイトからダウンロードしてきて、展開します。また、buildディレクトリを作ってmake作業を行います。
他のユーザーに影響を与えないようにするため、 ホーム以下の host-tools にインストールされるようにしてみました。

$ tar xzf tar gdb-7.8.tar.gz
$ mkdir gdb-7.8/build
$ cd gdb-7.8/build
$ ../configure 
 --prefix=/home/appuser/host-tools \
 --target=armv7l-unknown-linux-gnueabihf \
 --with-expat --disable-nls \
 --disable-sim --disable-install-libbfd \
 --program-prefix=arm-linux-gnueabihf-

ここで –with-expatをつけてmakeしないと、XML読み込めていないエラーが発生するようです。
これをつけない場合、下記にしめすようなエラーが一緒に消えました!

Remote 'g' packet reply is too long:
09ea1180ffffffff009500000000000000000000000000000000100000000
(ゼロの連続なので省略)

このエラーはリモートのgdbserverに接続した際に出ていたものです。
gdbが用意できたことで、Ubuntu環境の中からgdbでデバッグすることが可能になりました。


gdbをターゲットでビルドしてみた


先日のARM開発環境をというネタからの流れではあるものの随分と手こずっています。手こずっているのはgccやglibcなどの
クロス環境のツールチェインのmakeでして、今のところ失敗の連続です。
 それで寄り道をして gdbserver をmakeしてみようと思います。ターゲット環境で gcc が使用可能な状態であることが条件です。幸いにして、Jetson TK1 は最初からgccが使用可能で、gdbもあるのであまりこの必要性は感じませんが、gdbserver を用意しておくことは開発時において貢献してくれそうです。

準備

gdb(gdbserver)だけではコンパイルできないので依存関係にある物をインストールしておきます。

$ sudo apt-get install texinfo
$ wget http://ftp.gnu.org/gnu/gdb/gdb-7.8.tar.gz
$ wget ftp://ftp.gnu.org/gnu/termcap/termcap-1.3.1.tar.gz

$ tar xzf termcap-1.3.1.tar.gz
$ tar xzf gdb-7.8.tar.gz

$ cd termcap-1.3.1
$ mkdir build
$ cd build
$ ../configure
$ make
$ sudo make install
$ cd ../..

コンパイルとインストール

gdb(gdbserver) をmakeします。

$ cd gdb-7.8
$ mkdir build
$ cd build
$ ../configure --prefix=/home/ubuntu/tools/debugger
$ make
$ make install

/home/ubuntu/tools/debugger/bin/gdbserver の場所にインストールされます。都合が悪い場合には prefixの値を変更して下さい。

動作テスト

別のUbuntu環境で arm linux eabihf対応の gdb を用いて、gdbserver に接続して動作確認をします。
手っ取り早くやるためには、UbuntuでLinaro gcc-linaro-arm-linux-gnueabihf-4.7 をダウンロードして展開し、この中のgdbを使用しました。
他にも
sudo apt-get install gcc-arm-linux-gnueabi
sudo apt-get install gcc-arm-linux-gnueabihf

とかやったのですが、うまく対象の gdb をいれることができなかったためです。
また、linaroのパッケージの物が 32bit のものだったので、下記のコマンドを入力して 32bit のものが動作するようにしています。

sudo apt-get install lib32z1 lib32ncurses5 lib32bz2-1.0

これら、昔は apt-get install ia32-libs でインストールしていましたが、今(14.04)は上記のようにやるような感じでした。

今回のターゲットは Jetson TK1 だったのですが、無事にホストPCからgdbコマンドを実行しつつ、ソースコードデバッグができるところまでを確認しました。
注意点としては、当然ですが EABIのgdbではうまく動作しません。ターゲットのABIにあわせたシロモノが必要になります(だから今回はEABIHF となっています


クロスコンパイラgccのビルドがうまくいかない


ARMターゲットのプログラムをコンパイルするための、クロスコンパイラを自前でmakeしようと試行錯誤していますがうまくいきません。色々と調べてみて、1つ解決したかと思えば次また止まり、最終的にできあがったコンパイラでは正常に実行できるelfが出来上がらずといったところです。
折角なので、やってみたことを記録として残しておこうと思います。これでも誰かの参考になったら幸いです。

その1

gmp
mpfr
mpc
gcc
binutils
newlib

これらを用意してmakeしていきます。
gmp,mpfr,mpcらがgccで必要とするらしく・・・。またこれら出来上がった場所を LD_LOAD_LIBRARY に追加して soを参照できるようにしてみました。
というのも、gccのmake過程で GCC_NO_EXECUTABLES エラーがでてしまい・・・解決するかと思ったのですが。so解決しても結局解消することは不可能でした。また –disable-dlopenも試してみたのですがこれもまたNG

その2

export TARGET=arm-eabi
export PREFIX=/usr/local/gnu
configure –prefix=$PREFIX –target=$TARGET –enable-interwork –enable-multilib –enable-languages=c –with-newlib –disable-shared –disable-thread –without-headers –disable-libssp

これでgccを makeしてみるとうまくいった.ただし期待したシロモノができない。
理由は arm-eabi だったから。今ほしいのは eabihf の ABI
arm-linux-gnueabihf をターゲットとしてmakeさせると、エラーが発生。GCC_NO_EXECUTABLES 問題解決できず終了。

その3

どうやら gccのコンパイル過程で makeinfo が問題となっているよう。
apt-get install texinfo で makeinfo も片付くが、バージョンが問題になっている模様。新しいバージョンだとgccのmake過程でエラーが発生してしまう。
そこで、 makeinfo のバージョンを 5.0未満にすべく、古い物をソースからインストールしてみた。4.13あたりでチャレンジした。
これでgccのmakeはうまくいくようになるが、別の問題が発生。

arm-linux-gnueabihf のABIでパッチ当てたりしてmakeしてみるものの 失敗。armアセンブラが解釈できない何かでglibcの生成で失敗。
なお、 http://keropo.hatenadiary.com/entry/2013/04/14/232244 を参考にして eabi ならばうまくgccが生成できるところまではこぎ着けた。すごく参考になりました。

まとめ

クロスコンパイラgccを準備するのは非常に大変。
外部から提供される or 同梱されているならばそれを使うのが吉です。自力で用意してやろうとか欲を出すと、これに相当時間を取られそうです。
とはいえ、あまりにあまりな結果だったので他の方法もまだ探してみたいと思います。