Interface編集部(み)こと山口光樹の日記です / 日記以外のコンテンツはページ最下部に置く予定です / 取材などの内容の完全版は本誌を御覧ください / 全ページ・全ファイルともリンクはご自由にどうぞ
次なるテスト・プログラムを作成するためにGCCと格闘していたのですが,少しつまずいた所があったので備忘録代わりに記載します.今回のGCC環境で普通にグローバル変数を使おうと,
int glint; /* グローバル変数のint */
short glshort_table[5]; /* グローバル変数のshort配列(未使用) */
とint形式のグローバル変数glintを定義すると,
glint.o: In function `main':
glint.c:(.text+0x60): relocation truncated to fit: R_SH_DIR32
against symbol `glint' defined in COMMON section in glint.o
make: *** [glint] Error 1
というエラーが発生します.再配置関係の問題のようなので,mapファイルを見てみると,
.bss 0x00000000fffffffc 0x10
COMMON 0x00000000fffffffc 0x10 glint.o
0x00000000fffffffc glshort_table
0x0000000100000008 glint ←これ
グローバル変数glintを0x100000008番地に割り当てようとしています.SH-2はアドレス・バス32ビットだから0x100000008番地はありませんよ,ということをGCCに伝えなければなりません.上のmapファイルをよく見ると,COMMONセクションが.bssセクションの次で,0xfffffffcから割り当てられています.そこで.bssセクションを0xffffe000から割り当てるように,.bssの記述を.dataの後に付け加えてみます.
.data 0xFFFFE000: {
_sdata = .;
*(.data)
*(.zdata)
_edata = .;
}
.bss : {
*(.bss)
}
すると無事にコンパイルでき,実行もできました.mapファイルを見てみると,
.bss 0x00000000ffffe000 0x10
*(.bss)
COMMON 0x00000000ffffe000 0x10 glint.o
0x00000000ffffe000 glshort_table
0x00000000ffffe00c glint
0x00000000ffffe010 _end = .
0x00000000fffffffc . = 0xfffffffc
0x00000000fffffffc _sp_base = .
グローバル変数glintは0xffffe00c(SH7144Fの内蔵RAM)に割り当てられました.
今回のglintは初期値なしグローバル変数なので.bssセクションでも良いのですが,もし初期値ありグローバル変数の場合は.dataセクションに割り当てるべきでしょう.この場合は,初期値はROM上に,実際に割り当てられるアドレスはRAM上にしなければなりません.また,起動時に初期値をROMからRAMへコピーする必要もあります.この辺の事情とやり方は,7月号p.95〜に書いてあります.
不要だと思いますが,今回の.bssの問題を追試する人のために,glintのダウンロード(今回はマニュアルも何もありません).
余談:本当は*(COMMON)セクションを.dataセクション内に置こうとしたのですが,リンクは通るものの,FDTがOut of memoryエラーで通りませんでした.なんでだろう.
コンペア・マッチ・タイマ(以下CMT)割り込みを使ってみるテスト.cmt_int.motをダウンロードすると,1s周期でLEDが点滅します.
プログラム的には8/2にアップしたtrapと昨日のcmt_pollを結合したような処理内容になっています.この手の複雑なプログラムを作るときは,簡単な処理内容のものを単体で作成して,あとで結合して完成させるというのが基本ですね.
ほかには,HEWでは組み込み関数set_imask(0);でsrの割り込みマスクを設定できるのですが,GCCにはそれがないのでstartup.sで同じことを行っています.また,CMTの割り込み優先順位は15にしています.周辺デバイスの割り込み優先順位をソフトウェア的に設定できるというのは便利ですね.
コンペア・マッチ・タイマ(以下CMT)を使ってみるテスト.CMTは割り込みでもポーリングでも使えるのですが,とりあえずは簡単そうなポーリングで使ってみます.cmt_poll.motをダウンロードすると,0.25s周期でLEDが点滅します.
CMTを使う上で注意するのはモジュール・スタンバイ・コントロール・レジスタでCMTのスタンバイ・モードを解除することでしょう.最初ハマりました(笑).検索したところ,みすみロボット研究所さんの5/12のtest2.cが同様にCMTを使うプログラムだったので参考にしました(こちらは割り込み使用で,開発環境がHEW).ありがとうございます(メールで一言お礼しようと思ったのですが,メール・アドレスがちょっと見つからなかったので,ここでお礼に代えさせていただきます).CMTは計算式も簡単なので,いろいろと値をいじって,LEDの点滅周期を変えてみると理解が深まると思います.
次回は割り込み使用版の予定です.上記のtest2.cを参考にすれば,すぐ作れそうです.
A18の設定がおかしいバグがあった拙作のex_sram_testですが,HIROさんが修正版を作成されたということなのでリンクしておきます.ありがとうございます.どんどん改造してください.
遅くなりましたが,実は私の方でも直したものがあるのでアップしておきます.
GCCでプログラムを書いてみるテストと例外ハンドラを自分で書いてみるテストを兼ねて作ってみました.とくに何かの役に立つというわけではありません.
SH-2で例外処理をやってみたかったのですが,タイマ割り込みよりは簡単そうなTRAPAから挑戦してみたというものです.あと,GCC+SH-2ででasm()文を使ってC言語ソース中にTRAPAを記述してみるテストでもあります.
↓の5月7日に公開したex_sram_testをダウンロードされた方からメールをいただきました.ありがとうございます.メールを拝見すると,PFCの設定部分,PFC.PBCR2.BIT.PB6MD = 0x10; /* A18 */はPFC.PBCR2.BIT.PB6MD = 2; /* A18 */と,2を設定するのが正しいのではないかというご指摘でした.たしかにそうです.2進数で0b10(=10進数で2)と設定すべきところを,0x10と設定していた凡ミスでした.次のバージョンでは直しておきますが,速報までに.
単純に書いて読むだけでは,この手のアドレス・バス設定関係のバグは発見できないですね….これは気付きませんでした.
本業多忙につき(昨日も今日も休日出勤につき),全然SH-2基板を触れていませんが,Interface 2006年7月号でGCCも手に入ったことですし,これからも時間を見つけてSH-2基板は使っていこうと思います.その前に来月号の進行が先ですが.
HEWで新規ワークスペースを作ってソース・リスト群を自動生成し,そのまま無変更でビルドすると「0 Errors, 1 Warning」の表示とともにL1100のワーニングが出ます.
ルネサスのマニュアル「HEW生成ファイル補足説明(SH-1、SH-2、SH-2E、SH-DSP)」p.31によると,
『ビルドを行った時、「L1100 (W) Cannot find “xxx” specified in option “start”」と表示される場合には、このダイアログでxxxセクションを余分に設定してる可能性があります。その場合は、このダイアログからxxxセクションの指定を削除して下さい。なお、HEWが自動生成する設定ではCセクションを配置するようにしていますが、生成されるファイルによってはCセクションが存在せずL1100が出力される場合があります。』
だそうです.「Cセクション(定数領域)を配置するように指定しているにも関わらず,Cセクションに入れる内容がない」という意味となりますか.
気にしなくても動作することはするのですが,Cセクションを配置しないように指定するには,HEWのビルド→SuperH RISC engine Standard Toolchain→最適化リンカのタブ→カテゴリ:セクションにして,セクションの上から6番目のCクリック→編集→Cをクリック→削除,とすると0 Errors, 0 Warningsになりました.Cセクションを使うときは(多くのプログラムでは使うと予想される),削除したCセクションを復活させる必要があります…と思ったのですが,CセクションがないままCセクションを使っても「L1120 (W) Section address is not assigned to "C"」と,ワーニングだけで済みました.大丈夫かな.
面倒な場合の対症療法としては,グローバル変数としてconst int i=0;などと宣言してCセクション(定数領域)を使うという方法がありますが,ワーニングを抑え込むだけのために対症療法的なコードを入れると,あとあと後悔することとなるので勧められません.
追記:ルネサスのFAQ 104127にも記述がありますね.
hiranoyさんが開設されているblogで,SH-2基板を活用されていました.SH7144F内蔵のタイマを使うサンプルを探していて発見したのですが,2006年5月12日の日記でコンペアマッチ・タイマを使ったサンプルが掲載されていたので参考になりました.
自分用メモ:set_imask()などのSHに特化した関数は,「SuperH. RISC engine C/C++コンパイラ、アセンブラ、最適化リンケージエディタコンパイラパッケージV.9.00 ユーザーズマニュアル」の10.3.3 組み込み関数に記載あり.set_imask()(割り込みマスクの設定)はp.277.その他にもset_gbr()やsleep(),tas(),trapa(),prefetch(),macw()などのCPU依存関数もこの章.
SH-2の割り込みベクタを見ていたのですが,バス・エラー(未実装メモリ空間にアクセスしたときに発生する例外)のベクタ・アドレスがないのに今気付きました.ということで,テストしてみます.
*(unsigned int *)0x800000 = 0x12345678; prstr("write ok\n");
メモリが実装されていないアドレスということで,CS1のアドレス0x800000に対して書き込みを行っても,そのまま次の命令に進んでいます.
なお,SH-3にはバス・エラー相当のTLB保護例外があります.
月曜日の日記で,-listを指定するとリスト・ファイルが出力されると書きましたが,-list -show=sourceとするとリスト・ファイルにC言語ソース・リストも書き込まれるようになります.Cとアセンブラを見比べるには,こちらの方が便利そうです.
自分で書いたC言語プログラムがどんなアセンブリ言語に変換されているか見たいので,アセンブリ言語のソースを出力させてみよう(gcc -S相当)…と思ったものの,よく分からなかったのでリスト・ファイルを出力させてみました.
.lstファイルの中身はこんな感じです.
SH SERIES C/C++ Compiler (V.9.00.02.001) 〜中略〜 000000D0 _enable_external_sram: ; function: enable_external_sram ; frame size=0 000000D0 9241 MOV.W L69+6,R2 ; H'8620 000000D2 8421 MOV.B @(1,R2),R0 000000D4 963E MOV.W L69+4,R6 〜中略〜 00000158 _main: ; function: main ; frame size=0 00000158 BF52 BSR _init_SCI 0000015A 0009 NOP 0000015C D44B MOV.L L71+24,R4 〜中略〜
ちゃんとアセンブリ言語に落ちています.先ほどの-listオプションですが,一回[OK]をクリックすると,「-listfile="$(CONFIGDIR)¥$(FILELEAF).lst"」に変更されるようです.
しまった,昨日のex_sram_testですが,「Interface 2006年6月号のサンプル・プログラム演習3を参考にしました」とドキュメントに記載するのを失念していました(ソースリストには記載してある).次のバージョンで追記します.
基板裏面に装着する外部SRAMに正常にアクセスできるかどうかのチェック・プログラムを作ってみました.外部SRAMの初期化ルーチンの参考にもなります.
正常に動作するように作成しましたが,もし不具合があるようでしたら直します.無保証です.
私はEmacs(Windows上ではxyzzy)+Happy Hacking Keyboardな人なので,HEWのエディタをxyzzyに変更してみました.HEWの基本設定→オプションでエディタのタブ最下段の「外部エディタ」で変更できます.
ファイル名を開くときの引き数ですが,右向き三角をクリックして「ファイル名+パス名」を選択すると$(FULLFILE)という文字列が選択されるので,これでOK…と思いきや,実際にエディタを開こうとすると,「C:/Program Files/xyzzy/Settings/yamaguchi/Myファイルまたはディレクトリが見つかりません」というエラー・メッセージが出ます.Myで切れているのが何とも怪しいので,パス名に半角スペースが含まれているとマズいのか?と疑い,
$(FULLFILE)→"$(FULLFILE)"
と,ダブルクォーテーションで囲んでみたら,うまく起動するようになりました.
FDTが上記のようなエラー・メッセージを出すので何かと思ったら,ピン・ヘッダを外したまま(ジャンパをオープンにしたまま)FDTで書き込みしようとしてました.
ジャンパ・ピンを付けてFDTから再度書き込んでOK…と思ったら文字が化ける(演習7)…ので,TeraTermの通信速度を19200bpsにしてOK.
まあ私は日曜日以外は出社予定ですが….
演習1(p.111〜)の「LEDの点滅」サンプル・プログラムを書かれたとおりにビルドして,FDTでダウンロードして実行してみました.書かれたとおりに動作しました.
そこでこのプログラムを改造してみることにします.サンプル・プログラム一式は添付CD-ROMのままだとC:¥WorkSpace¥にインストールされるのですが,これはそのまま無改造で残しておきたいので(後で参照することもあるので),自分が改造するためにWorkSpace¥演習¥以下をマイドキュメント以下にコピーしました.エクスプローラで普通にコピーできるようです.その後,コピーしたプロジェクト・ファイルsh7144_1.hwsをダブルクリックしてHEWを起動すると,「プロジェクトが移動されました」という内容のダイアログが出るので,そのまま[OK]をクリックすると進めます.
正常に移動できた場合は通常のワークスペース表示が出るのですが,先ほどのダイアログが出ずに「(略)[INFORMATION] "ワークスペース情報がありません" 」というメッセージが出ることがあります.その場合はファイル→ワークスペースを閉じる,で一度閉じてから再度開くと良いようです.追試してみたのですが再現するときとしないときがあるようで,詳細は不明です.
簡単な改造として,sh7144_1.cで設定されているウェイトのfor(j=0;j<1000000;j++)の部分を1000000→4000000にしてビルド,ダウンロードしてみます.LEDの点滅速度が遅くなることを確認しました.最初のうちは,この程度の簡単な改造から始めた方が良いでしょう.
同様にprstr("")の中の文字列を変えてみます.演習1のワークスペースを閉じて,ワークスペースを開くで演習2のワークスペースを開いて編集してダウンロード.おっと,文字が化ける.演習2ではシリアルは19200bpsになっていたんだ.ハイパーターミナル(私はTeraTermを使っています)の設定を19200bpsに変更して,再度ビルド.正常に表示されました.
せっかくなのでシリアルの通信速度を384000bpsに変えてみます.p.130の表5,B0=38400のとき,n=0でPφ=24ではN=18.5くらいになります.小数は設定できないので,BRRには18を設定することにします.sh7144_1.cの35行目をコメントアウトして,以下のように変更します.
// SCI1.BRR=38; // 分周比 24MHz → 19200bps SCI1.BRR=18; // 分周比 24MHz → 38400bps
TeraTermの設定を38400bpsに変更しても正常に表示できました.
今日,気付いたこと.
続く.
各種blog検索エンジンでSH-2を検索.
いろいろヒットするようです.
今日は製品版の基板にコネクタと電源を付け,内蔵のサンプル・プログラムが走るところまで試してみました.付録基板には動作確認用として,最初からフラッシュ・メモリにA-Dコンバータの値を読み取ってシリアルから出力するプログラムが書き込まれています.そのため,プログラミングせずとも,電源とコネクタさえ付ければ,とりあえず動かして動作確認することができます.
ということで,電源とコネクタを付けて,シリアル・ケーブルをつないで電源ON.
メールアドレス:yamaguchi +@+ cqpub.co.jp (@は半角です)
DIRECT JUMP TO : Interface編集者の部屋へ / Interfaceのページへ