Kyoto Maker

Software & Hardware Laboratory Found In Kyoto, 2015.

HelioボードからSound Blasterで音が鳴るようにする

はじめに

今回は、Sound Blaster Play!をHelioボードに接続して音が鳴るようにしてみます。 大まかな作業としては、サウンドドライバを有効にしたカーネルをビルドして、SDカードにあるカーネルとDevice Tree Blobファイルの更新です。 中々うまくいかず試行錯誤しました。 今回の内容はFPGAとは関係無いですが、将来的に、FPGAで生成した信号を再生するのに活用しようと考えています。

f:id:fixme:20150118153414j:plain

準備

以下を用意します。

Sound Blasterは最新のものではなく、Linuxでの動作実績がある古めのものを使うことにしました。IntelEdisonボードで接続できた方がいるので、たぶん大丈夫だろうと考えました。

f:id:fixme:20150118153345j:plain

HelioのUSBポートがMini Bタイプなので、そのままではSound Blaster Play!が接続できません。 そこで、USB変換ケーブルを使って接続できるようにします。(間違ってMicro Bタイプの変換ケーブルを買ってしまい失敗しました。注意してください。また、最近はMicroタイプが主流のようで、家電量販店では見つかりませんでしたのでAmazonで購入しました。)

f:id:fixme:20150118153513j:plain

SDカードの読み書きがUbuntu仮想マシンからだと厳しそうなので、ネイティブマシンを用意します。 ビルド環境としてサポートされている、Ubuntu 12.04をセットアップします。

SDカードにはHelioでLinuxが起動するようにしたイメージを書き込んでおきます。以前、Linuxをブートできるようにした時のものを使用します。

カーネルのビルド

Helioの標準カーネルでは、Sound Blasterを動作させるデバイスドライバカーネルに組み込まれていません。 ですので、カーネルのビルドが必要です。 また、これからC言語Sound Blasterを操作したいため、カーネルにOpen Sound System APIを組み込みます。

GSRD v13.1 - Using Yocto Source Packageに書かれている手順に従ってビルド環境を作ります。

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install sed wget cvs subversion git-core coreutils unzip texi2html  texinfo libsdl1.2-dev docbook-utils gawk python-pysqlite2 diffstat help2man  make gcc build-essential g++ desktop-file-utils chrpath libgl1-mesa-dev  libglu1-mesa-dev mercurial autoconf automake groff libtool xterm
$ wget http://releases.rocketboards.org/release/2013.11/gsrd/src/linux-socfpga-gsrd-13.1-src.bsx
$ chmod +x linux-socfpga-gsrd-13.1-src.bsx
$ sudo ./linux-socfpga-gsrd-13.1-src.bsx
$ source ~/yocto/altera-init ~/yocto/build

カーネルのオプション設定を変更するため、以下を実行します。すると、新しい端末が起動し、変更メニューの画面が表示されます。

$ bitbake -c menuconfig -f virtual/kernel

以下を選択して、カーネルに組み込みます。

Device Drivers
 <*> Sound card suppor
  <*> Advanced Linux Sound Architecture
   <*> OSS Mixer API
   <*> OSS PCM (digital audio) API
   [*]  OSS PCM (digital audio) API - Include plugin system

設定を保存したら、カーネルをビルドします。

$ bitbake virtual/kernel

ビルドが完了すると、~/yocto/build/tmp/deploy/images以下にカーネル(zImage)が生成されます。 他にもファイルが色々ありますが、今回使うのはzImageだけです。

$ ls -l ~/yocto/build/tmp/deploy/images
[...]
-rw-r--r-- 1 fixme fixme   3351368  1月 18 11:04 zImage-1.0-r1-socfpga_cyclone5-20150118015746.bin

ビルドしたカーネルがサウンドドライバを組み込んでいるかざっくりした方法ですが確認してみます。zImageの方ではなく、圧縮していないカーネル(vmlinux)に対してstringsをかけてみます。カーネルのオプションを変更しないでビルドしたものと比較しても、明らかな違いが見られます。(vmlinux-1.0-r1-socfpga_cyclone5-20150118011738はカーネルのオプションを変更せずにビルドしたものです)

$ strings vmlinux-1.0-r1-socfpga_cyclone5-20150118015746 | grep snd | head -10
snd.cards_limit
snd.major
snd_disconnect_release
snd.slots
snd_timer.timer_tstamp_monotonic
snd_timer.timer_limit
snd_pcm_update_hw_ptr0
snd_pcm.maximum_substreams
snd_pcm.preallocate_dma
snd_rawmidi.amidi_map
$ strings vmlinux-1.0-r1-socfpga_cyclone5-20150118011738 | grep snd
msgsnd
msgsnd  
msgsnd  Td
3TCP: snd_cwnd is nul, please report this bug.

SDカードへのzImageの上書き

SDカードをマウントします。使用したマシンでは、以下のようにパーティションを認識してました。GSRD v13.1 - SD Cardの「SD Card Layout」の説明にある3つのパーティションが、mmcblk0p1~mmcblk0p3に対応します。

$ cat /proc/partitions 
major minor  #blocks  name

   8        0  312571224 sda
   8        1  308653056 sda1
   8        2          1 sda2
   8        5    3915776 sda5
  11        0    1048575 sr0
 179        0    7761920 mmcblk0
 179        1     512000 mmcblk0p1
 179        2    1536000 mmcblk0p2
 179        3      10240 mmcblk0p3

また、以下のようにマウントされています。

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1       290G   11G  265G   4% /
udev            1.9G  4.0K  1.9G   1% /dev
tmpfs           376M  904K  375M   1% /run
none            5.0M     0  5.0M   0% /run/lock
none            1.9G  7.8M  1.9G   1% /run/shm
/dev/mmcblk0p1  500M  3.5M  497M   1% /media/4628-37EE
/dev/mmcblk0p2  1.5G  162M  1.3G  12% /media/6e7ece6c-7d4f-43c3-89bc-4f9e228befce

ビルドしたzImageをSDカードに上書きします。試した環境では、zImageはSDカードの1つ目のパーティション(/dev/mmcblk0p1)にあるので、/dev/mmcblk0p1のマウント先である/media/4628-37EE/にzImageが存在します。GSRD v13.1 - SD Cardの「Updating Individual Elements on the SD card」が参考になりました。

$ cp ~/yocto/build/tmp/deploy/images/zImage-1.0-r1-socfpga_cyclone5-20150118015746.bin /media/4628-37EE/zImage

SDカードへのDevice Tree Blobの上書き

zImageの上書きだけでは、実はカーネルが起動しません。(ここで何度も試行錯誤してようやく答えにたどり着きました) Helio Prebuild Imagesで提供されているhelio.dtbで上書きする必要があります。SDカードに書き込まれている既存のdtbファイルのファイル名はsocfpga.dtbなので、helio.dtbをそのまま書き込むとうまくいかないことに注意します。

$ ls -l /media/4628-37EE/
合計 3160
-rw-r--r-- 1 fixme fixme   20584  9月  4 16:27 socfpga.dtb
-rw-r--r-- 1 fixme fixme     125  9月  4 16:27 u-boot.scr
-rw-r--r-- 1 fixme fixme 3202824  1月 18 10:27 zImage

以下の通り、dtbファイルを上書きします。

$ wget http://www.rocketboards.org/pub/Projects/HelioPrebuildImages/helio.dtb
$ cp helio.dtb /media/4628-37EE/socfpga.dtb

アンマウントしてからSDカードを取り出します。

$ sudo umount /dev/mmcblk0p1
$ sudo umount /dev/mmcblk0p2

なぜDevice Tree Blobの上書きが必要なのか (2015/01/24 追記)

考え方としては、以下でおそらく間違っていないと思います。

これを試した時は、Linux Kernel 3.13のSDカードイメージを使用していました。 一方、yoctoで自前でビルドしたカーネルのバージョンは3.9。 そして、Helio Prebuild Imagesは3.9向け。 なので、自前でビルドしたカーネルを動作させるには、カーネルと同一バージョンで作成されたDevice Tree Blobが必要になります。

Linuxの起動

SDカードをHelioに挿入して、電源を入れます。そうすると、Linuxが起動します。確認すると、uname -aの結果がビルドした日時になっていて、確かに自前でビルドしたカーネルで起動できています。

root@socfpga:~# uname -a
Linux socfpga 3.9.0 #2 SMP Sun Jan 18 10:58:42 JST 2015 armv7l GNU/Linux

Sound Blaster Live!の接続

用意しておいたUSB変換ケーブルを使って、HelioのUSB 2.0 OTG Port (J6)にSound Blaster Live!を接続します。

f:id:fixme:20150118153414j:plain

Linuxを起動した状態で接続しても認識しないようなので再起動してみます。

Linuxの再起動後、以下のコマンドを実行すると、Sound Blasterが認識されていることを確認できました。

root@socfpga:~# lsusb
Bus 001 Device 002: ID 041e:30d3 Creative Technology, Ltd Sound Blaster Play!
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

動作確認

カーネルのオプションの設定で「OSS PCM (digital audio) API」を有効にしました。 なので、/dev/dsp経由で音が鳴るようになっています。

試しに、適当なデータを/dev/dspに書き込んでみます。すると、「ビ!」っというような音が鳴ります。他にも適当なバイナリファイルを/dev/dspに書き込むと激しいノイズ音が流れます。

root@socfpga:~# echo aaaaaaaaa > /dev/dsp
root@socfpga:~# cat some.binary.file > /dev/dsp

動作確認としては、これで終わりです。あとは、/dev/dspに対して適切にオーディオデータを書き込んで楽しむのみです。

おわりに

うまくいくか不安でしたが、無事Sound Blasterを認識させて音を鳴らすことができました。 今後は、FPGAで生成した信号を鳴らしてみたいです。 Helioで音を鳴らしたい方の参考になれば幸いです。