2013年11月18日月曜日

SDCCによるFX2LPのFirmware開発に再挑戦 その1

(本投稿中、「&」や「>」、「\\\」といった表示がありますが、直しても直しても戻ってしまうので諦めました。それぞれ1バイト文字の&、>、¥のことです。すみません)


FX2LP(EZ-USB)を使った「変なキーボード」の制作ですが、
どうにも、フリー版のプログラムサイズの問題に引っかかってしまい。
数年前にも挑戦して挫折した、SDCCによるコンパイルに、再挑戦してみます。


まずは、pfenrirさんちの記事のサンプルをkeilでコンパイルしてみます。
pfenrirさん、ありがとうございます。勝手に使ってます。すみません。

最近のμVisionで開くと、いろいろパスが変わっていますので、修正します。
Target 1 の Source Group 1 に入っているファイルもパスが変わっていてペケ印がついていますので、これにも対応します。

Options for Tariget 'Target1' の Output タブの下部、Run User Program の1つ目に、通常、
C:\Cypress\USB\CY3684_EZ-USB_FX2LP_DVK\1.0\Bin\hex2bix -i -f 0xC2 -o bulkloop.iic bulkloop.hex
のように入れますが、このファイルの指定時にコンパイルするフォルダを指定します↓
C:\Cypress\USB\CY3684_EZ-USB_FX2LP_DVK\1.0\Bin\hex2bix -i -f 0xC2 -o .\build_by_keil\bulkloop.iic .\build_by_keil\bulkloop.hex


で、コンパイルすると、
C:\CYPRESS\USB\CY3684_EZ-USB_FX2LP_DVK\1.0\TARGET\INC\LPREGS.INC(266): error A10: ATTEMPT TO DEFINE AN ALREADY DEFINED SYMBOL
などと言われますので、その部分をコメントアウトします。

もう一度コンパイルすると、

エラーなくできました。iicファイルもできています。

他にもなんかいじくったかもしれませんが、記憶が曖昧で書けない…

はじめ、hexファイルが出来なくて困っていたんですが、projectのoptionを開いてチェックボックスのチェックを一旦外してOKしてからまた入れる、というのを繰り返したら、できました。

FX2LPにダウンロードしてまでは確認していませんが、もらってきたソースでiicファイルまで動くことが確認できました。





では、同じソースを、SDCCを使ってコンパイルしましょう。


準備:
まずは、SDCC-3.3.0 をインストールしました。

次に、mingw-get-setup.exe をインストールしました。
さらに、 C:\MinGW\bin にある mingw-get.exe を起動し、
All Packages
    MinGW
        MinGW Base System
にある、 mingw32-base のチェックボックスをクリックして、"Mark for Installation" を選び、メニュー Installation - Apply Changes を選んでインストールしました。
同様に、
    MSYS
        MSYS Base System
にある、msys-base をインストールしました。

MSYSのシェルは、
C:\MinGW\msys\1.0\msys.bat を開くと起動しました。



pfenrirさんちで公開されているヘッダファイルをまとめて一つのフォルダに保存し、makefileの中ではじめに参照するように設定します。


MSYSシェルを起動してmakefileのあるフォルダまでcdで移動して、makeコマンドを発行しました。

こんなん出ました:
sed: -e expression #2, char 17: unknown option to `s'

おそらく、makefileの
cat tempfile | sed -e 's/^+.*//g' -e 's/[^\.]*\.rel/$(BUILD_DIR)\/&/g' >> $(BUILD_DIR)/depend.inc; \
の部分から来ていると思うのですが、なんだかわかりません。

(以下、素人による原因究明過程ですんでひと目で問題点がお分かりになる方には単なる駄文長文ですね。ごめんなさい。)


ここで、このtempfileの内容を取得したものを示しますね。
fw.rel: fw.c c:/SDCC/pfenrir_inc/fx2.h c:/SDCC/pfenrir_inc/fx2regs.h \
c:/SDCC/pfenrir_inc/syncdly.h
+ c:\PROGRA~1\SDCC\bin\sdcpp.exe -nostdinc -Wall -MM -I"c:/SDCC/pfenrir_inc" -obj-ext=.rel -D__SDCC_MODEL_SMALL -DSDCC_MODEL_SMALL -D__SDCC_FLOAT_REENT -DSDCC_FLOAT_REENT -D__SDCC=3_3_1 -DSDCC=331 -D__SDCC_REVISION=8894 -DSDCC_REVISION=8894 -D__SDCC_mcs51 -DSDCC_mcs51 -D__mcs51 -D__STDC_NO_COMPLEX__ -D__STDC_NO_THREADS__ -D__STDC_NO_ATOMICS__ -D__STDC_NO_VLA__ -isystem "c:\Program Files\SDCC\bin\..\include\mcs51" -isystem "c:\Program Files\SDCC\bin\..\include" "fw.c"
periph.rel: periph.c c:/SDCC/pfenrir_inc/fx2.h \
c:/SDCC/pfenrir_inc/fx2regs.h c:/SDCC/pfenrir_inc/syncdly.h
+ c:\PROGRA~1\SDCC\bin\sdcpp.exe -nostdinc -Wall -MM -I"c:/SDCC/pfenrir_inc" -obj-ext=.rel -D__SDCC_MODEL_SMALL -DSDCC_MODEL_SMALL -D__SDCC_FLOAT_REENT -DSDCC_FLOAT_REENT -D__SDCC=3_3_1 -DSDCC=331 -D__SDCC_REVISION=8894 -DSDCC_REVISION=8894 -D__SDCC_mcs51 -DSDCC_mcs51 -D__mcs51 -D__STDC_NO_COMPLEX__ -D__STDC_NO_THREADS__ -D__STDC_NO_ATOMICS__ -D__STDC_NO_VLA__ -isystem "c:\Program Files\SDCC\bin\..\include\mcs51" -isystem "c:\Program Files\SDCC\bin\..\include" "periph.c"

「cat」はファイルの中身を表示するコマンドらしいので、続く「|」によって「sed」にファイルを渡しているようです。
なので、基本的な「sed」の使い方に則って
sed -e 's/^+.*//g' -e 's/[^\.]*\.rel/./build_by_sdcc\/&/g' tempfile > ./build_by_sdcc/depend.inc
のように書いても同じことができるはず。
やってみると、同じエラーが出ますね。

1つ目の変換指定だけにして実行すると、エラーなく動きました。
sed 's/^+.*//g'  ./build_by_sdcc/tempfile.txt > ./build_by_sdcc/depend.inc

検索文字列の指定は「^」は行頭を指すので、行頭に'+'があって、「.*」は任意の文字がゼロ個以上ということ、
置換文字列は指定されていないので見つけたら削除するとうことになります。
最後の「g」は見つけたものすべてを変換せよということらしいです。
合計すると実行結果は
fw.rel: fw.c c:/SDCC/pfenrir_inc/fx2.h c:/SDCC/pfenrir_inc/fx2regs.h \
 c:/SDCC/pfenrir_inc/syncdly.h
periph.rel: periph.c c:/SDCC/pfenrir_inc/fx2.h \
 c:/SDCC/pfenrir_inc/fx2regs.h c:/SDCC/pfenrir_inc/syncdly.h
となるのは理解出来ました。


問題の2つ目の変換指定「s/[^\.]*\.rel/./build_by_sdcc\/&/g」について。
検索文字列は、「\.」が任意の文字ではなくてピリオドそのものを指し、「[^\.]」なのでピリオドではない1文字、後ろに「*」があるので「[^\.]*」はピリオドではない長さゼロ以上の文字列、
「\.rel」は文字列'.rel'そのものを指す。合計してウィンドウズのワイルドカード的に書くと'*.rel'ということですね。
置換文字列は、あれ?どこからどこまでだ?
「./build_by_sdcc\/&」かな?でも、sedは検索文字列と置換文字列、オプションの区切りにスラッシュを使うのでこのままじゃダメな気がする。

「s/[^\.]*\.rel/\.\/build_by_sdcc\\\/&/g」にしてみたら、エラーはでなくなりました。
しかーーし、
2つ目のだけを実行したファイルを見ると
./build_by_sdcc\/fw.rel: fw.c c:/SDCC/pfenrir_inc/fx2.h c:/SDCC/pfenrir_inc/fx2regs.h \
 c:/SDCC/pfenrir_inc/syncdly.h
+ c:\PROGRA~1\SDCC\bin\sdcpp.exe -nostdinc -Wall -MM -I"c:\SDCC\./build_by_sdcc\/pfenrir_inc" -obj-ext=.rel -D__SDCC_MODEL_SMALL -DSDCC_MODEL_SMALL -D__SDCC_FLOAT_REENT -DSDCC_FLOAT_REENT -D__SDCC=3_3_1 -DSDCC=331 -D__SDCC_REVISION=8894 -DSDCC_REVISION=8894 -D__SDCC_mcs51 -DSDCC_mcs51 -D__mcs51 -D__STDC_NO_COMPLEX__ -D__STDC_NO_THREADS__ -D__STDC_NO_ATOMICS__ -D__STDC_NO_VLA__ -isystem "c:\Program Files\SDCC\bin\..\include\mcs51" -isystem "c:\Program Files\SDCC\bin\..\include"  "fw.c"
./build_by_sdcc\/periph.rel: periph.c c:/SDCC/pfenrir_inc/fx2.h \
 c:/SDCC/pfenrir_inc/fx2regs.h c:/SDCC/pfenrir_inc/syncdly.h
+ c:\PROGRA~1\SDCC\bin\sdcpp.exe -nostdinc -Wall -MM -I"c:\SDCC\./build_by_sdcc\/pfenrir_inc" -obj-ext=.rel -D__SDCC_MODEL_SMALL -DSDCC_MODEL_SMALL -D__SDCC_FLOAT_REENT -DSDCC_FLOAT_REENT -D__SDCC=3_3_1 -DSDCC=331 -D__SDCC_REVISION=8894 -DSDCC_REVISION=8894 -D__SDCC_mcs51 -DSDCC_mcs51 -D__mcs51 -D__STDC_NO_COMPLEX__ -D__STDC_NO_THREADS__ -D__STDC_NO_ATOMICS__ -D__STDC_NO_VLA__ -isystem "c:\Program Files\SDCC\bin\..\include\mcs51" -isystem "c:\Program Files\SDCC\bin\..\include"  "periph.c" 
./build_by_sdcc\/fw.rel …「\/」なんて、どんなパスだよ、ということで
「s/[^\.]*\.rel/\.\/build_by_sdcc\/&/g」とするとできました。

(ということは、「&」は検索文字列そのものを指しているみたいですね。だって、発見した'fw.rel'が消えずにあるので)

上記を合わせて、コマンドは
もとの
cat tempfile | sed -e 's/^+.*//g' -e 's/[^\.]*\.rel/$(BUILD_DIR)\/&/g' >>  $(BUILD_DIR)/depend.inc; \
から
sed -e 's/^+.*//g' -e 's/[^\.]*\.rel/\.\/build_by_sdcc\/&/g' .tempfile >> ./build_by_sdcc/depend.inc; \
になるでしょう。

 make 1> ./build_by_sdcc/make.txt 2>&1
とコマンド発行して結果を取得しましょう。

ちなみに ./build_by_sdcc/depend.inc はこんな感じです。c:/SDCC/p.....って、変なパスだなぁ。これで動くのかね?
./build_by_sdcc/fw.rel: fw.c c:/SDCC/pfenrir_inc/fx2.h c:/SDCC/pfenrir_inc/fx2regs.h \
 c:/SDCC/pfenrir_inc/syncdly.h
./build_by_sdcc/periph.rel: periph.c c:/SDCC/pfenrir_inc/fx2.h \
 c:/SDCC/pfenrir_inc/fx2regs.h c:/SDCC/pfenrir_inc/syncdly.h

makeは、sedのあとで上の depend.inc をインクルードして実行するわけですが…
なんか、sdccさんは、ソースファイルの内容がお気に召さないご様子です…
sdcc -c -V --debug --opt-code-speed --model-small -I"C:\SDCC\pfenrir_inc" -I"c:\program files\sdcc\include" -I"C:\Keil\C51\INC" -I"C:\Cypress\USB\CY3684_EZ-USB_FX2LP_DVK\1.0\Target\Inc" -I..//include -o build_by_sdcc/fw.rel fw.c
+ c:\PROGRA~1\SDCC\bin\sdcpp.exe -nostdinc -Wall -I"C:\SDCC\pfenrir_inc" -I"c:\program files\sdcc\include" -I"C:\Keil\C51\INC" -I"C:\Cypress\USB\CY3684_EZ-USB_FX2LP_DVK\1.0\Target\Inc" -I"..//include" -obj-ext=.rel -D__SDCC_MODEL_SMALL -DSDCC_MODEL_SMALL -D__SDCC_FLOAT_REENT -DSDCC_FLOAT_REENT -D__SDCC=3_3_1 -DSDCC=331 -D__SDCC_REVISION=8894 -DSDCC_REVISION=8894 -D__SDCC_mcs51 -DSDCC_mcs51 -D__mcs51 -D__STDC_NO_COMPLEX__ -D__STDC_NO_THREADS__ -D__STDC_NO_ATOMICS__ -D__STDC_NO_VLA__ -isystem "c:\Program Files\SDCC\bin\..\include\mcs51" -isystem "c:\Program Files\SDCC\bin\..\include"  "fw.c"
sdcpp.exe: fatal error: when writing output to : Invalid argument
C:/SDCC/pfenrir_inc/fx2.h:166: syntax error: token -> 'BOOL' ; column 16
心配した変なファイルパスは通っているようですね。スゴイ変な感じ。ありがたいけど。

fx2.hは、結局、
https://raw.github.com/stefanrauch/bel_projects/master/cy7/cyfx2usbuart/fx2.h
から取得したものを使用しました。

fx2.hの"BOOL"がお気に召さないのは、SDCCが"bit"を解釈してくれない(型として持ってない?)ので、
typedef bit             BOOL;
の前に、
#define bit __bit
が追加されています。"__bit"とするとわかってくれるみたいです。

さらに、
extern code BYTE   USB_AutoVector;
でエラーが出ました。
SDCCでは"__code"と書くべきらしいので、直前に
#define code __code
が追加されています。

fx2regs.hも、結局
https://raw.github.com/stefanrauch/bel_projects/master/cy7/cyfx2usbuart/fx2regs.h
を取得して使用しました。

xcode at (0xE400) hogehoge;
のようなところは
__xdata __at(0xE400) hogehoge;
と書くと良いようで、
#define at __at
#define xdata __xdata
が追加されています。


fx2sdly.hも
https://raw.github.com/stefanrauch/bel_projects/0d04410aaf9fdf08728649f722dc5bae1083dc65/cy7/softuart/fx2sdly.h
から取得して使用しました。

その他、
intrins.h
の冒頭部分を
#ifndef _nop_
#ifndef SDCC //added 2013-11-17
#define _nop_() { \
  _asm \
    nop \
  _endasm; \
}
#else//added 2013-11-17 bigin
#define _nop_() { \
  __asm \
    nop \
  __endasm; \
}
#endif//added 2013-11-17 end
#endif
としました。


makefileにある"AS = asx8051"なんですが、どうやら名前が変わったようです。
"AS = sdas8051"とすることで動きました。


fw.c の
//-----------------------------------------------------------------------------
// Interrupt Functions For SDCC
//-----------------------------------------------------------------------------
#ifdef SDCC
の下に、
#ifndef interrupt
#define interrupt __interrupt
#endif
を追加しました。

fw.c と periph.cで、
#include "syncdly.h"
をコメントアウトして
#include "fx2sdly.h"
を足しました。


他にもちょこちょこと触った気がしますが
細かくは覚えてなくて(汗)


この段階でのmakeの結果は
export PATH=/usr/bin:/usr/local/bin:$PATH; \
rm -f ./build_by_sdcc/depend.inc; \
for i in fw.c periph.c; do \
sdcc -E -MMM -I../pfenrir_inc -V  $i 1>> tempfile; \
if ! [ $? = 0 ]; then \
rm -f tempfile; \
exit 1; \
fi; \
done; \
#cat tempfile | sed -e 's/^+.*//g' -e 's/[^\.]*\.rel/./build_by_sdcc\/&/g' >> ./build_by_sdcc/depend.inc; \
sed -e 's/^+.*//g' -e 's/[^\.]*\.rel/\.\/build_by_sdcc\/&/g' tempfile > ./build_by_sdcc/depend.inc; \
cat tempfile > ./build_by_sdcc/tempfile.txt; \
rm -f tempfile
export PATH=/usr/bin:/usr/local/bin:$PATH; \
cp USBJmpTb.asm ./build_by_sdcc/; \
cd ./build_by_sdcc; \
sdas8051 -plosgff USBJmpTb.asm
export PATH=/usr/bin:/usr/local/bin:$PATH; \
cp dscr.asm ./build_by_sdcc/; \
cd ./build_by_sdcc; \
sdas8051 -plosgff dscr.asm
export PATH=/usr/bin:/usr/local/bin:$PATH; \
sdcc -V --debug --model-small --xram-loc 0xe000 --xram-size 0x200 --iram-size 0x100 -I../pfenrir_inc -o build_by_sdcc/bulkloop.hex -L ../pfenrir_lib -l ezusb build_by_sdcc/fw.rel build_by_sdcc/periph.rel build_by_sdcc/USBJmpTb.rel build_by_sdcc/dscr.rel
?ASlink-Error-Bad offset in library file ../pfenrir_lib/ezusb.lib(discon)
+ c:\PROGRA~1\SDCC\bin\sdld.exe -nf "build_by_sdcc/bulkloop.lk"
+ c:\PROGRA~1\SDCC\bin\sdld.exe -nf "build_by_sdcc/bulkloop.lk" returned errorcode 1
make: *** [build_by_sdcc/bulkloop.hex] Error 1
なんでしょうねぇ。
exusb.lib が気に入らないんでしょうか。