「ソフテックだより」では、ソフトウェア開発に関する情報や開発現場における社員の取り組みなどを定期的にお知らせしています。
さまざまなテーマを取り上げていますので、他のソフテックだよりも、ぜひご覧下さい。
ソフテックだより(発行日順)のページへ
ソフテックだより 技術レポート(技術分野別)のページへ
ソフテックだより 現場の声(シーン別)のページへ
ソフテックでは、組み込みソフトウェア開発をおこなっています。
組み込みソフトウェアは、ターゲットシステム専用に開発された基板上に搭載されたCPU(MPU:Micro Processing Unitと呼ばれることもあります)で動作する、特定システム専用のソフトウェアです。
CPUを搭載して製品化されたシステムは、数年経過すると使用しているCPUが生産中止になることがあります。
このような場合は、新しいCPUを選定して、新しい基板を開発することになります。
初期の開発から再開発までの期間が長く空けば、技術の進歩によりCPUの性能が高くなり、価格が安くなっていることが多々あります。
このため、CPUなどの部品の見直しをおこないます。
しかし、ソフトウェアは劣化しないため、新しいCPUに変わっても、初期に開発したソフトを流用してシステム開発をする、ソフトウェアの移植(Portingとも呼びます)が求められます。
ソフテックでは創立時から組み込み用ソフトの開発をしているため、上記のような相談を頂くことがあります。
今回は、ソフトウェア開発側から見た、移植作業のポイントについて書きます。
マイコンの中にはタイマやシリアル通信など様々なペリフェラル(peripheral:周辺装置)が実装されています。
しかし、このペリフェラルもCPUにより違いがあるため、ソフトを移植する際には、そのペリフェラルに合わせて、修正する必要があります。
弊社で開発する最近のマイコン用ソフトでは、アプリケーション(非ハードウェア依存部分)とドライバ(ハードウェア依存部分)を分離して開発しています。
上記の構造にすることにより、ハードウェアが変わっても理論的にはドライバ部分を修正するだけで、アプリケーション部分の移植に対応できます。
しかし、10年前のソフトウェアはアプリケーションとドライバが分かれていないことが多々あります。
理由は、プログラム(メモリ)サイズやCPU性能というハード的な制約が強かったためです。
10年前はROMやRAMが高価であり、移植性やメンテナンス性よりプログラムやメモリの使用効率を上げて、ハードウェアのコストを落とすことを優先していました。
また、CPUの処理能力も低く、その限られた処理能力で出来るだけ多くの処理をするために、プログラムの高速化も優先された部分です。
これを実現するために、アプリケーションとドライバを分離して、将来を見越すというよりは、今の仕様を満たすために職人芸的なプログラムを作っていました。
このようなソフトを移植しようとした場合に、ソフトの解析が難しく容易に対応できない状況が発生してしまいます。
作業ボリュームを検討する際には、ソフトウェア構造を見切ることが重要となります。
ソフテックでターゲットにするマイコンの変化を見ると、10年前の主流は8BitCPUであり、5年前には16BitCPUになり、最近は32BitCPUとなっています。
8Bitや16Bitという数字は、CPUが処理するデータサイズ(レジスタサイズ)の単位です。
C言語などの高級言語でプログラムを開発していると、コンパイラが上記の違いを吸収してくれるため、ほとんど意識することはありません。
しかし、移植する際には、この違いにより思わぬ落とし穴が待っていることがあります。
C言語にはint型(Integer:整数型)と呼ばれる、データの領域を確保する宣言文があります。
int型はCPUのレジスタサイズ分のデータ領域を確保する宣言で、以下のようになります。
16BitCPU:16Bitの領域を確保
32BitCPU:32Bitの領域を確保
上記のようにint型でデータを確保していると、CPUの種類により確保されるデータ領域のサイズが変わることになります。
このデータサイズが変わることで、問題になる例を挙げます。
(0x0 - 0xffff)という引き算をした場合に16BitCPUでは0x0001(16Bitのデータ)という答えになります。しかし32BitCPUでは0xffff0001(32Bitのデータ)という答えになります。
この引き算の結果を0x0001になることを期待したプログラムを記述していると、その期待どおりに動作しないため、不具合が発生します。
このような問題は、プログラムの記述としては問題ないように見えるため、見落としやすい問題です。
また、16Bitで表現できるデータでも、int型でデータ領域を確保するために、32Bit分の領域を確保してしまい、メモリの使用量が16BitCPUで動作していたプログラムより大幅に増加することになります。
このような問題は、マイコンの動作やコンパイラのことを理解していなければ、事前に対応するのが難しく、経験が浅い社員ほど見落としやすい問題です。
CPUのメモリ管理方法はビックエンディアンとリトルエンディアンという方式が存在します。
これは複数バイト(16Bit以上のデータ)を使って1つのデータを表現する場合のメモリへのデータ格納方法の違いです。
以下にビックエンディアンとリトルエンディアンのメモリ格納イメージを示します。
この違いは、コンパイラが吸収してくれるため、通常は意識する必要ありませんが、通信をおこなっているような場合に問題が発生することがあります。
RS-232Cなどのシリアル通信では、1バイト単位でデータを送信します。
送信データを作成する場合に、複数バイトをメモリに書き込み、送信時に1バイトずつ上位バイト、下位バイトの順番で送信すると、ビックエンディアンとリトルエンディアンの違いにより、送信されるデータが異なることになります。
このような部分は、通信以外にもフォントデータの扱いなどでも発生するため、元のプログラムの作り方によっては、大きな変更が発生する可能性もあります。
エンディアンはCPUにより異なるため、CPU選定の際に、元のシステムで動作していたCPUと同じエンディアンのCPUを選択することで、このようなリスクを回避することが出来ます。
古いシステムでは、アセンブラを使ってプログラムが開発されている場合があります。
アセンブラはCPUに依存する言語であるため、CPUが変わると流用できません。
このため、既存のアセンブラを参考にプログラムを作り直す必要が出てきます。
このレベルの変更になると、新規の開発と変わらない作業となります。
解析作業などを実施する分だけ、新規開発以上の開発時間が必要な場合もあります。
ソフトウェアから見た移植に関するポイントの一例を挙げました。
ソフトウェアやCPUの知識がない方には、難しい内容だったと思います。
移植作業は元にするソフトの影響を大きく受けますが、新規開発時にソフトの移植を意識していれば、移植時に発生する問題を軽減することはできます。
ソフトウェアは劣化しないという視点から見ると、流用される可能性は高いと考えるべきで、職人芸的なソフトよりも、移植性やメンテナンス性が求められる時代になっています。
今回、挙げた例が、これから移植作業をする人や、新規開発をする人に参考にして頂ければと思います。
(T.O.)
関連ページへのリンク
関連するソフテックだより