体験!マイコンボードで組込みLinux

第10回組込みボードへのさまざまな言語の導入その2]

今回は前回に続いて、軽量で組込みに適したスクリプト言語であるLuaと、拡張性の高いtclをSH7706LSRボードに導入する方法について紹介します。

Luaインタープリタの導入

Lua言語とは?

Lua言語は、Pascal言語に近い簡素な文法で多様なデータ構造を記述でき、軽量かつ実用的なインタープリタ型のプログラミング言語で、スクリプト記述によるシステムの構成管理やラピッドプロトタイピングに適しています。

Lua言語処理系の設計における基本的な思想は、言語処理系にたくさんの機能を実現するのではなく、多種多様な機能を実現するための仕組みを提供することです。やたらに多くの機能を詰め込むことなく、シンプルな処理系のままで簡単に拡張できるようにしたのがLua言語処理系の特徴です。

たとえば、通常のC言語で書かれたアプリケーションプログラムにLua言語処理系を組み込んで処理したり、C言語で書かれたモジュールをLua言語処理系に追加して機能を拡張できます。特に、組込みボードでは標準的でないローカルなハードウェア制御を目的とすることが多いので、簡単にC言語で書かれたモジュールをLua言語処理系に追加して機能を拡張できる点は、組込みボードで使ううえでのメリットです。

Lua言語はインタープリタなので、各行ごとにインタラクティブに構文解析などを行うため、実行速度の点で不利になります。そのためLua言語処理系では、少しでも実行速度を向上させるためにLua言語のコンパイラも用意されていますので、あらかじめLua言語のコンパイラでコンパイルすることにより、実行速度を向上させることができます。

導入に際して

Luaインタープリタは軽量でポータブルな言語処理系で、依存するライブラリはほとんどありませんが、2本だけあります。依存するパッケージは、履歴機能をもつラインエディタライブラリであるreadlineと、画面制御機能もつncursesライブラリです。

これらのライブラリはPC上の組込みボード用のクロスコンパイラに対してインストールを行い、そのうち共有ライブラリはSH7706LSRボードにもインストールします。Lua言語処理系のソースコードはPCの環境に依存はしていませんが、組込みボードのクロス開発環境も考慮されていません。そのため、ソースパッケージMakefileの内容を書き換えなければいけません。

readlineの導入

まず、ここではreadline-6.1を導入します。readline-6.1.tar.gzをGNUのミラーサイト等からダウンロードして適当なフォルダにコピーして展開します。コンパイル環境は以下のように構築します。

 # ./configure --prefix=/usr/sh3-linux/sh3-linux --host=sh3-linux

--prefixオプションでインストール先を指定し、--hostオプションで組込みボードのアーキテクチャを指定します。

コンパイルとインストールは以下のように行います。

 # make
 # make install

インストールはPC上の組込みボード用のクロスコンパイラに対して行いました。

Lua言語処理系はインタープリタなので、ライブラリ類はコンパイル時に実行ファイルに取り込まれるため、基本的にクロスコンパイラ上にライブラリがあればいいですが、readlineはコマンド入力を受け持つライブラリで組込みボード上でインタラクティブに動作するのでreadlineライブラリのみはSH7706LSR上に必要になります。

SH7706LSRに共有ライブラリのみインストールするには、以下のようにします。

 # cd /usr/sh3-linux/sh3-linux/lib
 # cp -a libhistory.so* [メモリカード]/lib
 # cp -a libreadline.so* [メモリカード]/lib

ncursesの導入

ここではreadline-6.1を導入しますので readline-5.7.tar.gz をGNUのミラーサイト等からダウンロードして適当なフォルダにコピーして展開します。

コンパイル環境の構築は以下のように行います。

 # ./configure --prefix=/usr/sh3-linux/sh3-linux --host=sh3-linux

--prefixオプションでインストール先を指定し、--hostオプションで組込みボードのアーキテクチャを指定します。

コンパイルとインストールは以下のようにします。

 # make
 # make install

これで、Lua言語処理系のソースファイルのコンパイルとLua処理系の実行に必要な共有ライブラリのインストールが完了しました。

Luaの導入

ここではlua-5.1.4を導入します。lua-5.1.4.tar.gz をLuaのサイト等からダウンロードして適当なフォルダにコピーして展開します。

Lua言語処理系のソースコードのコンパイルでは、組込みボードのクロスコンパイルが可能ですが、クロス開発環境も考慮されていませんので、Makefileの内容を書き換えなければいけません。Makefileの書き換えはトップフォルダとsrcフォルダで行います。

トップフォルダではインストール先の指定を行うのでSH3向けクロスコンパイラのフォルダを指定します。トップフォルダのMakefileの書き換えはリスト1のように行います。

リスト1 トップフォルダMakefileの変更点

01: # makefile for installing Lua
02:  # see INSTALL for installation instructions
03:  # see src/Makefile and src/luaconf.h for further customization
04:  
05:  # == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
06:  
07:  # Your platform. See PLATS for possible values.
08:  PLAT= none
09:  
10:  # Where to install. The installation starts in the src and doc directories,
11:  # so take care if INSTALL_TOP is not an absolute path.
12:  INSTALL_TOP= /usr/sh3-linux/sh3-linux ←変更
13:  INSTALL_BIN= $(INSTALL_TOP)/bin
14:  INSTALL_INC= $(INSTALL_TOP)/include
15:  INSTALL_LIB= $(INSTALL_TOP)/lib
16:  INSTALL_MAN= $(INSTALL_TOP)/man/man1

《以下略》

srcフォルダでは使用するコンパイラの指定を行うのでSH3向けクロスコンパイラを指定します。srcフォルダのMakefileの書き換えはリスト2のように行います。

リスト2 srcフォルダMakefileの変更点

01:  # makefile for building Lua
02:  # see ../INSTALL for installation instructions
03:  # see ../Makefile and luaconf.h for further customization
04:  
05:  # == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
06:  
07:  # Your platform. See PLATS for possible values.
08:  PLAT= none
09:  
10:  CC= sh3-linux-gcc		← 変更
11:  CFLAGS= -O2 -Wall $(MYCFLAGS)
12:  AR= sh3-linux-ar rcu		← 変更
13:  RANLIB= sh3-linux-ranlib	← 変更
14:  RM= rm -f
15:  LIBS= -lm $(MYLIBS)
16:  
17:  MYCFLAGS=
18:  MYLDFLAGS=
19:  MYLIBS=

コンパイルは以下のように行います。

 # make

実行ファイルはLua言語インタープリタであるluaと、Lua言語コンパイラであるluacの2つがあります。Lua言語単体で使う場合は以下のように実行ファイルのみSH7706LSRにコピーをします。

 # cp src/lua [メモリカード]/bin
 # cp src/luac [メモリカード]/bin

Lua言語処理系では、他の言語で書かれたプログラムにLua言語で書かれたモジュールを組込んだり、Lua言語で書かれたプログラムに他の言語で書かれたモジュールを組込むこともできるので、そのような開発を行う場合は、SH3向けクロスコンパイラにもLuaをインストールします。

 # make install

実行

Lua言語はC言語よりもどちらかというとPascal言語に近いので、Pascalを使ったことがある場合はあまり違和感はないと思いますが、C言語を常用している方は最初のうちは違和感があるかもしれません。ただ、根幹的にはC言語と同じなので、簡単なサンプルプログラムを組むことによってLua言語の流儀に慣れれば違和感なくプログラミングできると思います。

まず、SH7706LSRのLinux上でsum.luaという名称のサンプルプログラムリスト3を作成します。このプログラムは1から10までの回数を繰り返し、回数である変数nと累積である変数sumの値を順次表示させるプログラムです。

リスト3 サンプルプログラム(sum.lua)
01:  sum = 0
02:  for n = 1,10 do
03:       sum = sum + n
04:       print(string.format("n=%d sum=%d",n,sum))
05:  end

C言語での書式出力であるprintfはそのまま書式出力が可能ですが、Lua言語では出力は print関数、書式は string.format関数ということで別に分かれています。Lua言語のstring.formatの書式は、おおむねC言語のprintf関数に準じています。

ためしに、以下のようにコマンド上でリスト3のサンプルを実行してみます。

~ # lua sum.lua
n=1 sum=1
n=2 sum=3
n=3 sum=6
n=4 sum=10
n=5 sum=15
n=6 sum=21
n=7 sum=28
n=8 sum=36
n=9 sum=45
n=10 sum=55
~ #

次に、SH7706LSRのLinux上でcalc.luaという名称のサンプルプログラムリスト4を作成します。このプログラムは2つの数の入力を受けてから、その2つの値の加算と減算と乗算の結果を表示するプログラムです。

リスト4 サンプルプログラム(calc.lua)

01:  io.write("Input number1:")
02:  a = io.read("*n")
03:  io.write("Input number2:")
04:  b = io.read("*n")
05:  if b 06:      print(string.format("%d - %d = %d",a,b*(-1),a+b))
07:      print(string.format("%d + %d = %d",a,b*(-1),a-b))
08:      print(string.format("%d x (%d) = %d",a,b,a*b))
09:  else
10:      print(string.format("%d + %d = %d",a,b,a+b))
11:      print(string.format("%d - %d = %d",a,b,a-b))
12:      print(string.format("%d x %d = %d",a,b,a*b))
13:  end

ためしに、以下のようにコマンド上でリスト4のサンプルプログラムを実行してみます。

~ # lua calc.lua
Input number1:23
Input number2:17
23 + 17 = 40
23 - 17 = 6
23 x 17 = 391
~ #

tclインタープリタの導入

tcl言語の概要

PCではtcl言語はtcl/tkとして簡単にGUIアプリケーションが組める言語として、スクリプト記述によるGUIアプリケーションのラピッドプロトタイピングが可能なものとして使われています。SH7706LSRはグラフィックインターフェースを備えていないので、GUIツールキットであるtkは意味がないためtcl/tkのうちtclのみを使います。

tcl言語処理系の設計における基本的な思想は、言語処理系そのものを極力簡素にして、多種多様な機能を実現するための仕組みを提供し、多くの機能を標準提供モジュールとして標準搭載して、トータルなシステムとして多くの機能を提供するのがtcl言語処理系の特徴です。

多くの言語では演算機能というプリミティブな機能は言語仕様に含まれていますが、tcl言語では演算機能は言語仕様に含まれずexprモジュールとして提供しているように、言語処理系そのものを極力簡素にする徹底ぶりです。そのため、C言語で書かれたモジュールをtcl言語処理系に追加して機能を容易に拡張できるようになっています。

とくに組込みボードでは標準的でないローカルなハードウェア制御を目的とすることが多いので、簡単にC言語で書かれたモジュールをtcl言語処理系に追加して機能を拡張できる点は組込みボードで使ううえでのメリットです。

tclインタープリタの導入

tclインタープリタは軽量でポータブルな言語処理系で、他に依存をするライブラリはありません。tcl言語処理系のソースコードはPCの環境に依存はしてはおらず、潜在的には組込みボードのクロス開発環境にも対応は可能ですが、直接には組込みボードのクロス開発環境に対応していないので、組込みボードへの導入はちょっとした工夫が必要です。

tcl言語処理系は言語処理系そのものを極力簡素にして、多くの機能を標準提供モジュールとして標準搭載してトータルなシステムとして多くの機能を提供しているので、単純に実行ファイルやライブラリをSH7706LSRにコピーするだけは正常に動作をしません。

また、tcl言語処理系から標準提供モジュールや設定定義ファイルなどの呼び出しはインストール時のパス位置に依存しているので、PC上の組込みボード用のクロスコンパイラに対してインストールを行ったものをそのままSH7706LSRにコピーをしてもパス位置が不整合になり、tcl言語処理系そのものが正常に起動しません。

ここではtcl-8.5.9を導入します。tcl-8.5.9.tar.gzをtcl/tkのサイト等からダウンロードして適当なフォルダにコピーして展開します。

tcl/tkは多種多様なプラットホームに対応しているので、Linuxではunixフォルダの下で作業を行います。tcl/tkのクロスコンパイルをする場合、ac_cv_func_strtodとtcl_cv_strtod_buggyの環境変数を設定をあらかじめしておかなければいけません。

最初に以下のように初期設定をします。

 # cd unix
 # export ac_cv_func_strtod=yes
 # export tcl_cv_strtod_buggy=1

1回目の作業は、PC上の組込みボード用のクロスコンパイラに対して、PCのアーキテクチャでコンパイルとインストールを以下のように行います。

 # ./configure --prefix=/usr/sh3-linux/sh3-linux
 # make
 # make install
 # make clean
 # make distclean

インストールが終わったら、ソースパッケージ内の作業結果をすべてクリアしておかなければいけません。

2回目の作業は、SH7706LSRに対してPCのアーキテクチャでコンパイルとインストールを以下のように行います。

 # ./configure --prefix=[SD Card]/usr
 # make
 # make install
 # make clean
 # make distclean

ここでもインストールが終わったら、ソースパッケージ内の作業結果をすべてクリアしておかなければいけません。

3回目の作業は、PC上の組込みボード用のクロスコンパイラに対してSH3プロセッサのアーキテクチャでコンパイルとインストールを以下のように行います。

 # ./configure --prefix=/usr/sh3-linux/sh3-linux --host=sh3-linux
 # make
 # make install
 # make clean
 # make distclean

インストールが終わったソースパッケージ内の作業結果をすべてクリアしておかなければいけません。

4回目の作業はSH7706LSRに対してSH3プロセッサのアーキテクチャでコンパイルのみを以下のように行います。

 # ./configure --prefix=/usr --host=sh3-linux
 # make

SH3プロセッサに依存するものだけ、以下のようにSH7706LSRにコピーをします。

 # cp libtcl8.5.so [メモリカード]/usr/lib/
 # cp tclsh [メモリカード]/bin
 # cp tclConfig.sh [メモリカード]/usr/lib/

実行

まず、SH7706LSRのLinux上で sum.tcl という名称のサンプルプログラムリスト5を作成します。このプログラムは1から10までの回数を繰り返し、回数である変数nと累積である変数sumの値を順次表示させるプログラムです。

リスト5 tclサンプルプログラム(sum.tcl)

01:  set sum 0
02:  for {set n 1} {$n 03:      set sum [expr $sum + $n]
04:      puts [format "n = %d sum = %d" $n $sum]
05:  }

C言語での書式出力であるprintfはそのまま書式出力が可能ですが、tcl言語では出力はputsコマンド、書式はformatコマンドということで別に分かれています。tcl言語のformatコマンドの書式は、おおむねC言語のprintf関数に準じています。

ためしに、以下のようにコマンド上でリスト5のサンプルプログラムを実行してみます。

~ # tclsh sum.tcl
n = 1 sum = 1
n = 2 sum = 3
n = 3 sum = 6
n = 4 sum = 10
n = 5 sum = 15
n = 6 sum = 21
n = 7 sum = 28
n = 8 sum = 36
n = 9 sum = 45
n = 10 sum = 55
~ #

次に、SH7706LSRのLinux上で calc.tcl という名称のサンプルプログラムリスト6を作成します。このプログラムは2つの数の入力を受けてから、その2つの値の加算と減算と乗算の結果を表示するプログラムです。

リスト6 サンプルプログラム(calc.tcl)

01:  puts "Input number1:"
02:  scan [gets stdin] %d a
03:  puts "Input number2:"
04:  scan [gets stdin] %d b
05:  if {$b 06:      puts [format "%d - %d = %d" $a [expr $b * -1] [expr $a + $b]]
07:      puts [format "%d + %d = %d" $a [expr $b * -1] [expr $a - $b]]
08:      puts [format "%d x (%d) = %d" $a $b [expr $a * $b]]
09:  } else {
10:      puts [format "%d + %d = %d" $a $b [expr $a + $b]]
11:      puts [format "%d - %d = %d" $a $b [expr $a - $b]]
12:      puts [format "%d x %d = %d" $a $b [expr $a * $b]]
13:  }

ためしに、以下のようにコマンド上でリスト6のサンプルプログラムを実行してみます。

~ # tclsh calc.tcl
Input number1:
34
Input number2:
45
34 + 45 = 79
34 - 45 = -11
34 x 45 = 1530
~ #

次回は

次回は、最新版Linuxカーネルの紹介と、Lua言語とC言語との連携について解説します。

おすすめ記事

記事・ニュース一覧