〜 フリーCコンパイラ SDCC を使おう (Windows編)〜

はじめに

 PICの開発環境はメーカーのMicrochip Technology Inc. よりフリーのIDEが提供されています。しかしながらアーテクチャーが独特のものでプログラム 開発はアセンブリ言語が主流のような気がします。サブルーチンコールのネストが 8段までだとか、バンクやページを切替えてのアドレッシング等、他のマイコンに比較して Cコンパイラを作る上でもまた使う上でも制約があることを感じてなりません。
 とは言っても、非常に魅力のあるデバイスであることは間違いありません。とっつき難さは ありますが、安価でフラッシュ搭載でSDIPパッケージもあるので電子工作などには もってこいですね。

 さて、本題です。PIC用Cコンパイラはほとんどが有償です。PIC関連の書籍でもC言語で 開発を.. などありますが、有償のCコンパイラを使用したものです。 個人が手を出すにはいささか立ち止まってしまうのが現状ではないでしょうか?
そのためにちょっと癖があってもアセンブラを余儀なく使うことになります。

 でも世の中にはスゲー技術者もいて、フリーのPIC用Cコンパイラを作るプロジェクトが あります。SDCC : Small Device C Compiler がそのプロジェクトです。

 2004/12/25現在、SDCCのPIC対応はまだ完全ではなく、私でも手を出せるデバイスでもある PIC16F84, PIC16F84Aのミッドレンジ(PIC14)においてはコンパイルが通りません。

 ですが、三岩幸夫氏が雑誌「Software Desigen」 の2004年7月号〜10月号の「Linuxパワーアップ講座」で詳しく対応方法を解説して下さいました。 これが非常に目からウロコで、早速 NetBSD、Windows環境でPIC16F84(A)に対応さえてリビルド させてみました。おかげさまで案外すんなりとできて、PIC16F84Aにてタイマ割り込みの ハンドラも含めて確認ができました。感謝しております。

 ということで、まだ PIC16F84,PIC16F84Aの2デバイスしか対応していませんが、 Windowsの実行ファイルをアップしたいと思います。ソースも後日アップする予定です。
 それでは、SDCCでPICをお楽しみ下さい。。。

ダウンロード

 2004/12/25にsourceforgeよりcvsで獲得したソースにPIC16F84, PIC16F84A を対応させたSDCCです。
 Windows2000(SP4)上で、VC++6.0(SP5)でビルドしました。

インストール

 本家のSDCCはインストーラーが(NSISで)作成されていますが、 私が配布するセットにはインストーラーはありません。
 ビルドして必要なものだけをアーカイブしてるだけすので適当な場所に展開して下さい。
以下、C:\ に展開したものとして進めます。

 C:\sdcc 以下に bin, include, lib, doc ができるはずです。

  1. 環境変数 PATH に c:\sdcc\bin を追加します
  2. 環境変数 SDCC_HOME に c:\sdcc を設定します
  3. 環境変数 SDCC_INCLUDE に c:\sdcc\include を設定します
 以上で SDCC のインストールは完了です。

アセンブラやリンカのインストールはお済み?

 既にMPLABや、gputilsをイントールしている場合は読み飛ばして下さい。
 アセンブラはMicrochip Technology Inc.純正の MPLAB IDE v7.00又は、 GNU の gputils で確認済みです。 何れかをインストールしておく必要があります。
 Windows環境ならおそらくMPLABを使用されている方が多いかと思いますが、sdccの吐く アセンブリソースに対してデフォルトのリンカ・スクリプトそのまま使うと リンカがエラーを出すことがあります。リンカ・スクリプトを修正すればOKです。
一方、gputilsは今のところ程よく適応してくれているようですんなり通ります;-)
 最後にPATHを通していることも確認しておいて下さい。

サンプルビルド

 手っ取り早くサンプルソースで確認してみましょう。 すごく手抜いてるソースですが、確認ということで...
  1. gputilsを使う場合

  2.  sdccに gpasm, gplink まで通しもらって foo.hex を得ます。
     リンカスクリプトは 16f84a.lkrをそのまま使用します。別途用意はしていません。
    C:\home\sdcc> sdcc -V -mpic14 -p16f84a foo.c
    Processor: 16f84a
    + c:\sdcc\bin\sdcpp.exe -nostdinc -Wall -std=c99 -DSDCC=1 -DSDCC_MODEL_SMALL -DSDCC_pic14 -D__pic14 -I"c:\sdcc\include" -I"c:\sdcc\include\pic14" -I"c:\sdcc\bin\..\include\pic14" -I"c:\sdcc\include" -I"c:\sdcc\bin\..\include" "foo.c"
    + C:\gputils\bin\gpasm.exe -c "foo.asm"
    + C:\gputils\bin\gplink.exe -o foo.ihx "foo.o"
    message: using default linker script "C:\gputils\lkr\16f84a.lkr"

    [sdccのオプションの説明]

    -V
    処理の詳細を表示します
    -mpic14
    ミッドレンジ(1ワード=14bit長)のPICを指定します.
    -p16f84a
    デバイスにPIC16F84A を指定します。

  3. MPASMを使う場合

  4.  MPASMを使用する場合、sdccはアセンブリソースを吐くまでが仕事です。
    それ以降は、MPASM, MPLINK を使用します。ということで、sdcc はアセンブリ ソースを出力した時点で終了させます。そのためにオプション -S を指定しておきます。
     mplink に指示するリンカスクリプトはこれ用に作成したものです。デフォルトの リンカスクリプトではエラーになります(ベクタはベクタとして0x0〜0x5まで使うように しないとエラーを吐くようだ。実情問題はないのだが..。sdccが吐くアセンブリソースは 後方の0x04から始まる割り込みベクタには*よく皆がするように*そこからハンドラコード を記述しているため vectors ではなくてpage になっている。そこをmplinkは厳しくしているようだ)。
    C:\home\sdcc> sdcc -S -V -mpic14 -p16f84a foo.c
    Processor: 16f84a
    + c:\sdcc\bin\sdcpp.exe -nostdinc -Wall -std=c99 -DSDCC=1 -DSDCC_MODEL_SMALL -DSDCC_pic14 -D__pic14 -I"c:\sdcc\include" -I"c:\sdcc\include\pic14" -I"c:\sdcc\bin\..\include\pic14" -I"c:\sdcc\include" -I"c:\sdcc\bin\..\include" "foo.c"
    C:\home\sdcc> mpasmwin /q /o foo.asm
    C:\home\sdcc> mplink foo.lkr foo.o /m foo.map /o foo.hex /v
    MPLINK 3.90, Linker
    Copyright (c) 2004 Microchip Technology Inc.
    Errors : 0
    Warnings : 0

    MP2COD 3.90, COFF to COD File Converter
    Copyright (c) 2004 Microchip Technology Inc.
    Errors : 0
    Warnings : 0

    MP2HEX 3.90, COFF to HEX File Converter
    Copyright (c) 2004 Microchip Technology Inc.
    Errors : 0
    Warnings : 0


PIC Writer

 上記の両サンプルのhexファイルをPIC Writerで書き込んで動作確認しました。 私が使用したライタは秋月電子AKI-PICプログラマ Ver.3 および Ver.4で 書き込んで動作することを確認しました。
 最近は、USB・シリアル変換ケーブルまで あるので232CコネクタがないノートPC等でもUSBがあれば使えるようです。安価なので 持っておくと便利ですね。IO DATA の USB-RSAQ2や、 ストロベリーリナックスのUSB⇔シリアル変換モジュールも OKのようですが価格面では秋月の方が魅力あります;-)

マニュアル

 sdccのマニュアルは 使い方だけでなく、ソースを眺める上でも非常に重要な情報も記載されています。
是非、一読されたし。

PIC用Cソースのコーディング留意点

 どうしても組み込み用マイコンのCソース記述となると、ある意味マイコン依存する コーディングも必要となってくる。これが著しくなると可搬性が低下するので避けたいの だがそうわけにもいかない。。
 通常はこいった方言的な記述は #pragma を多用するんだろうでども、sdccは #pragmaも 使うけど、パーサーまで届くような文法(仕様)もある。  PIC16F84A を例に紹介します。
  1. __CONFIGの書き方

  2. int at 0x2007 __config = _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF;

  3. SFRのビットアサイン(PORTA,PORTB等)

  4. 例えば、RA3(PORTAのbit3) に LED1 を割り当てるような場合。

    BIT_AT(PORTA_ADDR,3) LED1;

    とすると、0,1の代入でポート出力が可能になります。

    LED1 = 1;

    ここは、PicAntCなどよりは気が利いています。
    SDCCのこの仕掛けは吐き出したアセンブリソースを見るとすぐわかります。BIT_AT(..)は、 (アドレス<<3 | bit位置) として`_LED1'を定義しています。(Cでのシンボルはアセンブリソース 以降はprefixにアンダースコア`_'が付与されます)。アドレスとbit位置を一定数(ID)に エンコードしているわけです。

    _LED1 EQU ( (0x05<<3)+2)

    で、ポートLED1に 1 を出力するアセンブリソースは、アドレスとbit位置にデコードして、 「BSF アドレス,bit位置」の命令を吐いています。そして、注目する点はマメに(ある意味無駄に..) バンクを切り替えていることです。これらは最適化のやる仕事として割り切って、現状は 十分満足させてくれます。

    ; LED1 = 1;
    BCF STATUS,5
    BSF (_LED1 >> 3), (_LED1 & 7)

  5. 割り込みハンドラの記述

  6. void timer(void) interrupt 0
    {
    /* body */
    }

その他

 デバイス固有のヘッダファイル(ex: pic16f84a.h)は、sdccが同梱しているPerlスクリプト inc2h.pl を利用して生成します。
 MPLABや gputils をインストールしたらアセンブラ用のインクルードファイルが同梱されて いますが、これを inc2h.pl に通すとヘッダファイルができるように配慮されています。
 しかし、Windows環境ではこのPerlスクリプトは通りません。PC-UNIX等で作成するのも もちろんありですが、Windows環境用に inc2h.pl を変更しました。sdccのアーカイブに 含めています。sdcc/include/pic14/inc2h.pl です。
 このPerlスクリプトは、MPLAB の インクルードファイルを使用するように変更しています。 インクルードファルのデフォルトパスは、C:\Program Files\Microchip\MPASM Suite にしています。 必要あればこのパスを変更してください。(手抜いています)
使用方法です。
D:\hogehoge> C:
C:\>cd \sdcc\include\pic14
C:\sdcc\include\pic14> jperl inc2h.pl 16f84a > pic16f84a.h
 (※)当然ですが、事前でにPerl(JPerl)をインストールしておく必要があります。


2004/12/25
2004/12/29 mod

Copyright(C) 2004 masu, All rights reserved.
massun.masumoto@nifty.ne.jp