fenrirさんのおかげでbulkloopをSDCCコンパイルできました。
ホストプログラムで動作確認しました。
ありがとうございます!
ただ、、、何かお知恵があれば拝借したい件があります。
bulkloopのソースに少しでも変更を加えると、Windowsで認識されなくなります。
例えば、periph.cの
EXTAUTODAT2 = EXTAUTODAT1;
ここを
EXTAUTODAT2 = EXTAUTODAT1+10;
にするとダメです。
(KEILだと動くのですが、、、)
SDCCでは、2つ以上の引数がある時はグローバル変数で渡す、という制約があるらしいのは分かっているのですが、それ以外に何か制約があれば教えていただけないでしょうか。
ちょっとあつかましいですが、よろしくお願いいたします。
Hirataさん、こんにちは。お役に立てたようで何よりです。
問題の件ですが、コンパイルは通るのですよね?申し訳ないのですが原因はよくわかりません。
sdcc、たまに動作しないコードを吐くことがあります(バグ?)ので、コードの配置を変えてみる、またはバイナリレベルで+10ありとなしの比較をされてみると何かわかるかもしれません。
fenrirさん、アドバイスありがとうございます。
最終的には動作しました。
上記の場合ですと、変更したTD_poll()関数の最後にnopを入れるとWindowsに認識されるようになりました。(コードサイズ依存というか、SDCCが自動でつける初期化ルーチンの先頭アドレスに制約があるような気がしてなりません)
fw.cとperiph.cはあまりさわらない方が良いみたいですね~。
何がともあれ、SDCC&FX2LPで遊ぶ事が先です:-)
ちなみに、お役に立つかどうか分かりませんが、私の方ではドライバはUusbd.sysで動かしています。バルク転送はできました。
でも、ファームの転送までやる時間がなさそうです。すいません。
お久しぶりです。社会人になってすっかりご無沙汰してました。
FX2のSDCC対応うまくいったようでなによりです。
私は謝辞をいただくほどのことは何もしてないですよ(汗)
こちらこそ、ソースコードを参考にさせていただきます。
ちなみに私は携帯電話メーカに就職しました。
早く設計に携わりたい!
>hamaさん
いえいえ、動作報告があるのとないのとでは、やはりモチベーションが全然違いますよ(笑)、ありがどうございます。
携帯電話メーカですか、面白い製品を期待しています、がんばってください!
はじめまして。
私もSDCCでコンパイルできるようになりました。
ありがとうございました。
私はFX2LPを使って、PC間のデータ転送をするような回路を
作っているのですが、私が書いたオリジナルソースも
コンパイルでき、問題なく動作できるようになりました。
感謝感謝です。
Hirataさんがおっしゃったように、
Windowsで認識できなくなる現象に遭遇しました。
mapファイルを覗いて、現象とつき合わせたのですが、
external_startupのアドレスが奇数番地だと認識されて、
偶数番地だと認識されなくなるようです。(なぜ?)
しょうがないので、コンパイル後、偶数番地になった場合は
意味のないレジスタ設定の命令を入れて再コンパイルし、
奇数番地になるようにしています。
(苦肉の策ですが・・・)
yukiさん、こんにちは。
お役に立てようでなりより & 貴重な報告ありがとうございます。偶数番地ですか、何かいい方法ないですかね。HEXフォーマットは単純なので、コンパイル後、適当なスクリプトでチェックをかけて処理するというのが意外と便利な解決策かな、と考えています。
私もfenrirさんのサンプルのおかげでbulkloop,pingnakをSDCCコンパイルして動作確認出来ました。多謝。
ターゲットはFX2LPです。
external_startup問題ですが、コードを追加して行くと同じ現象に遭遇しました。
ただ、私の場合は偶数番地だと動作して奇数番地だと駄目でしばらくすると番地に関係なく動作するようになりました。
おそらくスタックかなにかがオーバフローしてエラーを起こしているのではないかと思い、
現在はSDCCのコンパイルオプションをつかってスタック位置を変えてトライしています。
追加したオプション
--code-size 0x3000 --xram-loc 0x3000 --xram-size 0x1000 --xstack-loc 0xe200
訂正します。
その後いろいろやっていると、奇数番地で動作し偶数番地だとUSBを認識しなくなりました。
スタック指定のオプションも効いているのかどうかわからないような。
もう少しはっきりしたことがわかったらまた報告致します。
8051のスタックポインタが8bitしかなくしかもメモリの
後ろに向かって伸びるなんて知りませんでした。
勉強不足でお恥ずかしい限りです。
やっと原因が見えてきたような気がします。
どうもdscr.asmで定義している_DeviceDscrなどが偶数番地に
割り当てられてないとenumerationに失敗するようです。
そういえばwindriverの体験版が生成するFX2LP用のテンプレートで
パイプの数を減らしたときに_FullSpeedConfigDscrの位置を
調整するために1byteのダミーデータが入れてありました。
どう探してもSDCCには.align疑似命令が無いようですし
最初にmain()のあるモジュールをリンクしなければならないと
いう制約があるので、fw.relの次にdscr.relをリンクするように
してその次に呼び出すモジュールで試行錯誤するようにしたことで
プログラムを変更するたびに動作したりしなかったりする現象は
収まりました。
コンパイラの信頼性を疑っていたりしたのですが、SDCC自体は
結構良く出来ているような気がします。
>kmさん
fenrirです。大変貴重な情報ありがとうございます。なんとなく変数足して動いたり動かなかったりする謎が、ようやく解けたような気がします。偶数番地に_DeviceDscrが配置されなければならないというのは8051というよりかはEZUSBの仕様なのでしょうか。マイコンにはやはり『御作法』があるものが多いようですね。
申し訳ありません。
.evenが使えるというのは早とちりだったようです。
確認が間違っていました。
コンパイラは.even疑似命令を受け付けるけれども
リンカが認識しないので出力には反映されないというのが
正解みたいです。
.even 疑似命令を使って少し楽が出来る方法を思いつきました。
お騒がせついでに情報を追加させて下さい。
.even 疑似命令はソースモジュールの中で位置を調整しますが
リンカはそれを無視します。
そのため、ソースモジュールの先頭アドレスが奇数ならば
.evenに続くシンボルの位置は必ず奇数になります。
それならば..
(1) main()のあるソース(fw.c)の最後の関数に .even 疑似命令を追加する
(例)
void resume_isr(void) interrupt WKUP_VECT
{
EZUSB_CLEAR_RSMIRQ();
// alignment end of fw.c
_asm;
.even
nop; // comment out this if needed
_endasm;
}
(2)リンカスクリプトテーブル(dscr.rel)がfw.relの後にリンクされるよう配置する。
(3)一度コンパイルしてマップファイルを確認し必要ならばnop命令を
コメントアウトしてシンボル_DeviceDscrが偶数番地になるようにする。
これでfw.c中の関数を修正しても_DeviceDscrの位置は偶数のままになります。
>kmさん
コメントありがとうございます。そうですか、リンカでは認識されないのですか、残念です。なかなか楽はできないようになっているみたいですね(笑)。
はじめまして、JUNと申します。
初めてなのに、長文ですいません。m(_ _)m
まずFX2LPのCPUにCypressのフレームワークをKeilを使って元々のBulkLoopのテストをコンパイルしました。リンクは0x1400からコードスタートで、Keilコンパイラではデバイスも再認識され、ホスト側のBulkテストもうまく動作することを確認しました。
次にこのサイトを大いに参考にさせていただき、SDCCでコンパイルして動作させようとしています。このサイトにもとづいてSDCCでライブラリも含め、そのKeilのBulkLoopのテストをコンパイル、リンクしました。ところが、新しいデバイスをロードしようとして、私のPCの環境ではホスト側が途中で暴走してしまう始末です。(他のCPU環境では、不明なデバイスとなる)
仕方ないので、まずは、このサイトにあるfenrirさんのソースに全て置き換え、ライブラリを生成し、Bulkloopを動作させようと、がんばったのですが、同じ現象でした。
ただfenrirさんとの開発環境の大きな違いは、私の場合は、WindowsのCygwinだということです。そして妙なことに、fenrirさんの生成したbulkloop.hexそのままだと、暴走せずにちゃんとエニュメレーションを行い、デバイス名も出てくるのです。
どうも新しくロードしたプログラムのデバイスディスクリプタがちゃんと認識されてないか、そもそも、ちゃんと初期化されてメインのプログラムに飛んでいってないのかなー、なんて混乱状態になってしまっています。(T-T)
そもそも8051のアーキテクチャで33番地、43番地、53番地がベクタジャンプのコードがはいっていて、なおかつ、そこがデータエリアとしても読み書きされる、という自体、こんなの大丈夫って気がするもんで。
ハードウェアのマニュアルを何回見ても、その仕組みがよくわからなかった.....(;^_^A
0-80Hまでって、コードメモリとデータメモリと2重のメモリをもっている、と考えれば納得いくのだけれど、そういう記述はありませんでしたから。
とにかくこんな迷えるプログラマに何かアドバイスをいただければとお邪魔したしだいです。^^;
よろしくお願いいたします。
(なおソースプログラムの方は、ここのサイトのをベースにコメントを参考にして修正していきました)
>JUNさん
こんにちは。まずこちらの環境ですが、JUNさんと同じCygwin上のsdccで作業しています。当時の状況をよく覚えていないのですが、bulkloopを作ったときの環境は、確かソースからセルフビルドした少し古めのsdccでコンパイルしたと思います(sdccの最新版は2.6.0ですから2.4.0あたり?)。
現在2.5.6でコンパイルしなおしてみたところ、こちらでもbulkloopが動かない現象に遭遇していますので、ちょっと検討してみます。お役に立てずすいません…。
fenrirさん、さっそくのご返事ありがとうございます。
こちらでも今いろいろやっていますので、いい知らせがあればお伝えしますね。
USBのStreamscopeを使ったり、LED表示させたりして、
fw.c内の
if(TD_Suspend())
からちゃんと返って来ないことに気づきました。
(TRUEで返しているのに、FALSEとみなしている)
そしたら、このTD_Suspend()の定義がBOOLでExtern宣言されているのに気づいたので、
#define BOOL BYTE
の定義を下記の位置に移動しました。
//-----------------------------------------------------------------------------
// Prototypes
//-----------------------------------------------------------------------------
#ifdef SDCC
#define BOOL BYTE
#define GPCR2 FALSE
#define bmFULLSPEEDONLY FALSE
#endif
void SetupCommand(void);
void TD_Init(void);
void TD_Poll(void);
BOOL TD_Suspend(void);
BOOL TD_Resume(void);
・・・・・・・・・・・・・・・・・
この修正だけで、うまく動作するようになりました。
いろいろこのサイトは本当に役に立ちました。
ありがとうございます。
>JUNさん
こちらでもご指摘の修正を施した後sdcc2.6.0でテストしてみた結果、認識するようになりました。
リンカの辺りを疑ってmapファイルばかり眺めていたのですが、実信号を見たほうがよかったですね。大変勉強になりました、本当にありがとうございます。
なおダウンロードファイルは修正したものに切り替えました。以後落とされる方は問題ないと思いますが、なにかありましたらまたここに書き込んでくださるとうれしいです。
はじめまして、kurihiroと申します。
FX2LPの評価ボードを入手しまして、早速、本ページを参考にして、コンパイル、認識等、問題なく済ませることができました。ありがとうございます。
しかしながら、評価ボードのLED等を使用しようと思ったところ、Keilでは問題なく制御できるI2Cがらみがどうも動作しません。
調べてみると、割り込みルーチンはmain()と同じファイルにないといけないのに、I2Cの割り込みルーチンがEZUSB.libにあるためと分かりました。
マニュアルによるとmain()のあるファイルに割り込みルーチンのプロトタイプだけあればいいということなので、fw.cの最後に、
void i2c_isr(void) interrupt I2C_VECT;
を追加することで対策できました。
以上、報告させていたただきます。
>kurihiroさん
情報ありがとうございます。実のところEZUSB.libの動作検証はあまりしていなかった(汗)ので、動作報告を戴けてうれしい限りです。
>kurihiroさん
ありがとうございます。
また、ここのサイトが役に立ちました。
メインを含まない、別のところにINT0_VECTの処理を書いたのに、割り込みベクタを作ってくれてないので、
インターネットで調べていて、また、ここにいきついて解決したのでした。
ただ、今も確認しましたが、kurihiroさんの言うように、マニュアルにちゃんと記載してあったんですね。
うーん、その意味では、わからないことがあったら、原点に戻れ、って言うことか。
(^-^;
そうそう、割り込みベクタといえば、データ領域と割り込みベクタが
0~100Hでは重なっているところを使う恐れがあって、
コードとデータがちゃんぽんになってるエリアって、
8051のアーキテクチャではどうなっているのか、
いまだに疑問が残ったままです。
(コードとデータのメモリエリアはアドレスは同じでも全然別?
->でもHEXファイルにはデータのロードやコードの区別はないから、
結局、同じ、データとしてコードも書き込まざるを得ない?)
うーん、わからないなー(SFRのエリア領域だけは別個なのはわかってるのですが)
(^ヘ^;
SDCCはうまくそんな領域を回避してデータを割り当ててるとは思えないし....
>JUNさん
そういえばご質問に返答するのを忘れていました。回答になっているかはわかりません(笑)が、僕の理解を書いてみます。
一般的に、プロセッサではリセット等の割り込みが発生するとあらかじめ決められたアドレスから命令を読み取り実行を開始する仕組みになっていると思います。この決められたアドレス領域がいわゆる割り込みベクタというもので、このような仕組みを実現するためには、割り込みベクタには実行する命令が存在しなければなりません。つまり、割り込みベクタと重なるように、コンパイラが定めるコード領域(<-命令が格納される部分という意味での)は設定されていてる必要があると思います。
しかしJUNさんの思われているとおり、その割り込みベクタにコードやデータがぐちゃぐちゃ書いてあると割り込みベクタとして機能しないと思います。そこで、割り込みベクタにはjmp命令(指定したアドレスに飛んでそこから命令を実行する)だけを書いておいて、割り込みによって実際に行われる命令は同じコード領域であっても割り込みベクタとは別のアドレスに配置されているという手口をとっていると思います。またデータについては、静的(static)なものはコード領域とは別に確保した領域に割り当てられ、動的(ローカル変数など)なものはこれまたコード領域とは違うスタック領域から確保されることになっているので、割り込みベクタとかぶる心配はないと思います。
この方法はマイコンのコンパイラには常套手段だと思いますので、おそらくsdccでもデフォルトで割り込みベクタをうまく回避してメモリ割り当てをしていると考えられます。いかがでしょうか。
fenrirさん、ご返事遅くなりすいませんでした。
m(_ _)m
私もいろいろ絶対アドレスが割り付けられたアセンブリリスト(.rstファイル)を見たのですが、
そのようなことは配慮されてる気配はありませんでしたね。(^-^;
以前、評価版の8051のシミュレートで逆アセンブリリストをとったとき気が付いたのですが、
どうも、コードとデータは別々に違った内容が表示されていたので、
なんかやっぱり別々の空間としてとらえられている感じがします。
なおこれと関係がないのですが、SDCCのマニュアルの4.1.1のpdataアクセスに関して、
xdataの初期化とからんで、個々のCPUごとに_XPAGEのアドレスを設定しておかないと、
ちゃんと初期化を行わない、という記述がありました。
マップファイルを見ると、デフォルトではA0(SFRのP2ポート)でしたが、
Cypressでは本来0x92(MPAGEポート)を割り当てないといけないのです。
今まで、ある程度、プログラムは動いていたので、よし、としていたのですが、
結構、こういう細かい配慮も必要ですね。(^-^;
なおこの情報は「USB-MSD-RD KeilからSDCCへの移植」に書かれていました。
http://www.chiaki.cc/Timpy/rev50-keil2sdcc.html
はじめまして。
現在市販されているEZUSB FX2LPについては、資料が少なく、初心者がUSBプログラミングをするには困難を覚えることが多いのです。さらに、lpを使っていても、ソフトはfx2のままというのが、書籍にも多いのです。cypressのapiやツール類がlpで大きく変更されているのに、それに対応しないのはおかしいと思っています。
その意味で、貴サイトは大いに参考となります。
sdccはz80用に使って以来、愛着があるので、
これでプログラミングができることは、ありがたいことです。
とはいっても、USBプログラミング自体が敷居が高いので、ぼつぼつ慣れていきたいと思います。
>きゅうる村さん
はじめまして。コメントありがとうございます、またご参考にして戴けて光栄です。
資料の少なさについては同意です。FX2LPは最近秋葉原(秋月)でも買えるようになりましたし、参考文献がこれから増えてくることを期待したいものです。8051系でsdccのバグには何度かなかされたことがありますが、z80のsdccはどうでしょうか。
はじめましてarms22と申します。
何点か気になったのでコメントします。
1._DeviceDscr
Setup Data Pointerレジスタに書き込めるアドレスはWORD境界である必要があります。
取り合えず絶対アドレス指定でプログラムの後ろの方に配置しておけばOKかな。
2.interrupt 0
sdccで、main()のあるファイルにexternしなければinterrupt番号が重複していてもOK。
またUSB関連のinterruptはmain()のあるファイル(fw.c)にexternしないほうが良いと思います。
USB関連の割り込み関数がベクタに追加されてしまいます。
3.__interrupt_vectのサイズ
sdccでmain()のあるファイルで#pragma noivとしてもリセットベクタだけは生成されるみたいです。
またベクタテーブルはinterupt 0からinterupt N(最大値)までしか生成されないので
Nがマイコンの割り込み数以下なら割り込みベクタに通常コードが配置されてしまいます。
Nを最大値にした割り込み関数を用意するか、
ベクタテーブルは自前で用意したほうがいいみたいです。
>arms22さん
情報ありがとうございます。EZUSB系からは離れて時間が経ってしまったので、当時の稚拙さが皆さんに災いしていなければと願う一心です。
最近またFX2とは別の8051系MCUを使い出したのですが、やはりsdccにお世話になっています。sdccのマニュアル、読めば読むほど奥が深いですね。
> 補足ですが、Development Kitの中のFX2LP向けbulkloop(Examples/FX2LP/Bulkloop/bulkloop.Uv2)をKeilでビルドしようとすると、
>
> *** FATAL ERROR L220: INVALID INPUT MODULE
> というエラーがでてできませんでした。
FX2用の開発ツールと、FX2LP用の開発ツールとでは、
付属するKeilのバージョンが違います。
SETUP_FX2LP_DVK_1004.exe
Keil V2.10
EZ-USB_devtools_version_261700.zip
Keil V2.38j
objとlibはそれぞれのバージョンで互換性はないようで、
FX2LPのサンプルは、Keil V2.38jでビルドする必要があるようです。
バージョンが逆でした
SETUP_FX2LP_DVK_1004.exe
Keil V2.38j
EZ-USB_devtools_version_261700.zip
Keil V2.10
ですね。
>chirariさん
情報ありがとうございます、コメント返すのが遅くなってしまい申し訳ありません。
どうりでコンパイルがうまくいかないわけですね。ライブラリの形式もバージョンによって互換性がないというのは初めて知りました。
ferrirさん、ご無沙汰です。hangです。
古いレスへのコメントで恐縮ですが、肝心な事が抜けているようですので....。.evenも重要ですが。
xdata variableの初期化で路頭に迷っている方がいらっしゃるかもしれません。
SDCCのインストール時は、xinitがハードウェアを利用するセットアップ初期化になっています。
EZ-USB FX2ではこれをDUAL_DPTR使用に変更する必要があります。
SDCCのlibフォルダーを探すと、crtxinit.asmが見つかりますので、これを自分のフォルダーにコピーし、ファイル内のDUAL_DPTR=0をDUAL_DPTR=1に変更します。
このアセンブリオブジェクトをリンクします。
初めて使用される方は、これで悩む事が多いと思います。
hangです。長い事EZ-USBに触っていなかったので忘れていました。
__mcs51_genXRAMCLEAR::もIOCを介したハードアクセスになっていますので、crtxclear.asmも書き直す必要があります。
これは、練習問題ですね。
おそらく、皆さんの初期不安定の原因は、スタートアップで、デスクリプターテーブルやプログラムを壊しているからだと思われます。
>hangさん
情報ありがとうございます。
色々と気になって調べてみたのですが、この問題についてはsfr at 0x92 _XPAGE;が適切な位置で定義されていればDUAL_DPTR=1とせずとも解消される問題なのでないかと考えています。というのもFX2(LP)はXdataアクセス用に、8051の伝統的なアクセス方法であるP2ポートを使う方法ではなく、専用のレジスタ0x92(FX2LPのデータシートではMPAGEと表記)を用いる方法を使っており、コンパイラもこれを考慮して_XPAGEが指定されている場合にスタートアップルーチンもその指示に従うように思われます( http://sdcc.sourceforge.net/doc/sdccman.html/node104.html )。こちらで公開しているプログラムも_XPAGEのsfrはヘッダfx2regs.hで定義していますので、大丈夫ではないかと考えています。
fenrirさん こんにちは。hangです。
あっと、そうでしたか。
ただ、先ほどnoICE for 8051で確認しましたら、スタートアップは、P2を使用されていた事と、プログラムはStringDescripterを参照できない、xdata変数の初期化ができない状況でした。
古いソースなので、それが原因かな?
SDCCは最新Stable版です。
どなたか、追検証していただければ幸いです。
ちょっと忙しくて8051には手が回らないもので ^^);
hangです。失礼。途中で送信しました。
上記不具合は、スタートアップにSDCCオリジナルを使用した場合で、当然、手を加えた場合は安定に動作します。
で、再度、修正スタートアップをリンクし正常な事を確認しました。
またまた hangです。フー一服。
ARMやdsPICで忙しく、なかなか8051に触れる機会がなかったのですが、最近感じるのは、EZ-USB FX2のカリスマ性ですね。
EZ-USB FX2+FPGAは最強のように思います。
Xilinx USBⅡ等に使用されているように、海外ではヒットしているのに、国内の寂しさは、SDCCアプリのサポート不足が原因ですかねぇ。
と、このテーマはここの話題ではありませんでした。
失礼!
>hangさん
たびたびコメントありがとうございます。そうですね、追試が必要ですね。
ところで8051+sdccといえば、FX2以外にもSilicon LaboratoriesのC8051シリーズ(こちらは1クロック1命令で速い!!)を愛用しているのですが、C8051では_XPAGEを定義しておけばXdataが確実に初期化がされています。うーん。
>fenrirさん
正確に記述すればよかったようです。唸らせてしまいました。
古いソースでXPAGEが入っていませんでした。
確かに、XPAGE宣言で解決します。
fenrirさんの作成されたヘッダーファイルがSDCCスタンダードという事になります。
意外と、オプティマイズさんやらあちこちのソースを拾い集めてプログラムを開始するとこの手のバグに陥りますので、問題確認の意味として御勘弁を。
>hangさん
確認がとれたようで、ほっとしております。色々と組み合わせて作っているうちにわけがわからなくなることは、僕もよくあります(笑)