September 17, 2014

UARTフエール をRaspberry Piにつなぐ

UARTをSPIまたはI2C接続で4ch増やすことができるUARTフエール、またの名をシリワレールですが、Raspberry Piを使って検証を進めた結果、Raspberry Pi上のLinuxからシリアルポート(/dev/ttyMAX[0-3])として認識させることができました。ついでにUARTフエールで使ったMAX14830にはGPIOを拡張する機能もあり、Raspberry Piから(/sys/class/gpio/gpiochip240)として認識させることができました。特にLinuxのkernel driverに関する知識がかなり必要で苦労しました。以下、長々と備忘録を残しておきます。

RasPi-max14830.png
記念のスクリーンショット!

(続きをどうぞ)

まずはハード的な接続です。UARTフエールとRaspberry PiはSPIで接続します。RPi Low-level peripheralsを見て、UARTフエールとの配線をしていきます。結果、以下のようにRaspberry PiのSPI0(-CS0)につながるように配線しました。

  • (以下 UARTフエール側) <=> (Raspberry Pi側)
  • CON1-1 +3V3 <=> P1-17 (他でも可) 3.3V
  • CON1-2 GND <=> P1-25 (他でも可) GND
  • CON1-3 MISO <=> P1-21 SPI0_MISO
  • CON1-4 SPI0_SCLK <=> P1-23 SPI0_SCLK
  • CON1-5 -CS <=> P1-24 SPI0_CE0_N
  • CON1-6 MOSI <=> P1-19 SPI0_MOSI

なお僕の手元にあるRaspberry PiはModel Bで、現行品のModel B+ではないため仕様としてP1は26ピンです。

次にドライバを整備していきます。とても長い道のりです。概略としては、max14830をサポートするmax310xカーネルモジュールを作成すること、および前述のモジュールはSPIフレームワークに即しているので、その導入を簡単にするためのspi-configカーネルモジュールを作成すること、この2つが必要となります。

上記2つのカーネルモジュールを作成するにあたって、カーネルのソース、およびビルドをモジュールだけに限定するために、カーネルをビルドした際のシンボル情報をまずは入手する必要があります。後者についてはフルビルドをして回避することもできるのですが、クロスビルドをすることなくRaspberry Pi単体で完結させたいがためにフルビルドは時間がかかりすぎるため、そのような流れとしました。

カーネルのソース、シンボル情報を入手するにあたって重要となるのが、現在のシステムの状況です。uname -aをして得られる僕が試した環境は

$uname -a
Linux raspberrypi 3.12.26+ #708 PREEMPT Thu Sep 4 15:43:15 BST 2014 armv6l GNU/Linux

でした。

例えば『Raspberry Pi(Raspbian "wheezy")にM2TECH hiFaceのドライバをインストールする方法』を参考に、カーネルのソース、およびシンボル情報を入手していきます。実行した手順(ルートになっていること前提)を以下に示します。

$ cd /usr/src
$ wget https://github.com/raspberrypi/linux/archive/rpi-3.12.y.tar.gz
$ tar zvxf rpi-3.12.y.zip
$ ln -s /usr/src/linux-rpi-3.12.y /lib/modules/$(uname -r)/build

続いてシンボル情報の入手ですが、シンボル情報の更新履歴を確認しつつ、現在の自分の環境にあったものを入手します。

$ cd /usr/src/linux-rpi-3.12.y
$ wget https://raw.githubusercontent.com/raspberrypi/firmware/16ebc76904699b036f709beb65ee5ff70f83190b/extra/Module.symvers

ソース、シンボル情報の入手後に、現在のカーネルの状況にあわせた設定を取り込みます。

$ cd /usr/src/linux-rpi-3.12.y
$ zcat /proc/config.gz > .config
$ make oldconfig

これでモジュールをビルドする環境が整いました。なおモジュールはgccの4.8で作成したものでないと、後で組み込む際にシステムフリーズしてしまいました。Raspberry Piに元から入っていたのがgcc 4.7でしたので、gcc 4.8 on Raspberry Pi Wheezyを参考にgcc 4.8を入れています。

組み込むモジュール2つのうち、まずはmax310xをやっつけることにします。spi-configよりもこちらの方が少し工程が多いです。

工程が多い理由は、僕の手元のRaspberry Piのカーネルバージョン3.12.26は、現時点の最新のカーネルリリース3.16よりも古く、max310xをモジュールとしてインストールすることが想定されていないため、それを修正する必要がありました。3.16ではモジュールとしてインストール可能です。

またせっかくなので、3.16でのリリースを3.12でもコンパイルできるようにしました。違いとしては、Raspberry Pi(3.12.26+)ではCommon Clock Frameworkが無効に対し、3.16では有効になっていることを想定しているため、そのままではMAX14830のクロック源がわからずにエラーを吐いて停止してしまいます。それを回避するためにクロック源の情報をモジュールのソースに直接入れ込んでいます。

ということでパッチを適用し、モジュールのビルドの準備を以下のコマンドでします。

$ cd /usr/src/linux-rpi-3.12.y/drivers/tty/serial
$ mv max310x.c max310x.c.orig
$ wget https://raw.githubusercontent.com/raspberrypi/linux/rpi-3.16.y/drivers/tty/serial/max310x.c
$ wget https://fenrir.naruoka.org/download/embedded/raspi-3.12_max310x.patch
$ patch -u -p1 < raspi-3.12_max310x.patch

以下のコマンドでmax310xをモジュールとして組み込むことを指示します。menuconfigでは[Device Drivers] => [Character devices] => [Serial drivers] => [MAX310X support]に<M>がつくようにしてください。

$ /usr/src/linux-rpi-3.12.y
$ make menuconfig

続けてモジュールのビルド、インストールをします。

$ make prepare
$ make modules_prepare KERNELRELEASE=$(uname -r)
$ make SUBDIRS=drivers/tty/serial modules
$ make SUBDIRS=drivers/tty/serial modules_install
$ mv /lib/modules/3.12.26/extra/* /lib/modules/3.12.26+/extra/
$ rm -r /lib/modules/3.12.26
$ depmod

これでmax310xは終わりです。続けてspi-configを組み込みます。Examples on how to build various modulesにある手順とほぼ同じです。このリンクは他にもCANのモジュールを組み込みなどの便利情報があります。

$ cd /usr/src
$ git clone https://github.com/msperl/spi-config
$ cd spi-config
$ make
$ make install
$ mv /lib/modules/3.12.26/extra/* /lib/modules/3.12.26+/extra/
$ rm -r /lib/modules/3.12.26
$ depmod

これでspi-configモジュールのインストールは完了です。

上記で作成してきたmax310xおよびspi-configを有効にするには以下のコマンドを使います。

$ modprobe max310x
$ modprobe spi-config devices=bus=0:cs=0:modalias=max14830:speed=10000000:irq=0:force_release

lsmodをするとmax310xとspi-configが組み込まれていることが、またdmesgで組み込み過程をおうことができると思います。同時にシリアルポートとして/dev/ttyMAX[0-3]が、GPIOとして/sys/class/gpio/gpiochip240が作成されていると思います。

シリアルポートのテストはminicomなどで行うことができます。またGPIOのテストは

$ cd /sys/class/gpio
$ echo 242 > export
$ echo out > gpio242/direction
$ for i in `seq 1 100`; do echo $(expr $i % 2) > gpio242/value && sleep 0.2; done

とすると、UARTフエールのLEDが点滅します。

これでUARTフエールをRaspberry PiのUART拡張グッズとして使うことができるようになりました。

21:02 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク | トラックバック
このエントリーのトラックバックURL: https://fenrir.naruoka.org/mt/mt-tb.cgi/916
コメント
コメントする









名前、アドレスを登録しますか?
(次回以降コメント入力が楽になります)
  • 匿名でのコメントは受け付けておりません。
  • 名前(ハンドル名可)とメールアドレスは必ず入力してください。
  • メールアドレスを表示されたくないときはURLも必ず記入してください。
  • コメント欄でHTMLタグは使用できません。
  • コメント本文に日本語(全角文字)がある程度多く含まれている必要があります。
  • コメント欄内のURLと思われる文字列は自動的にリンクに変換されます。