Knowledge
   

OAKS16-MINIと戯れる


2004/08/22

お買い物…OAKS16-MINI

OAKS16-MINI
20040822P00.JPG実は、ここ一週間、オークス電子ルネサスのホームページからマニュアルをダウンロードして眺めていたんですが、OALS16-MINI、1つ買ってみました。購入先は、ROBO-ONEにもエントリーされているチャーリーさん会社です。

考えてみるとOAKS16-MINI、なんとなくですが、AKI-H8/3664より安くてパフォーマンスがいいような気がします。I/O数はほぼ同じ(1本だけOAKS16-MINIの方が多い)ようですし、ROMはH8/3664の倍、クロックもちょっと速いです。

今回、フルキット(テスト用マザーボードからコンパイラ、本体、電源まで一通りついている)を購入したので、5000円越えましたが、CPUボード単体でみたら1500円ぐらいです。またフルキットも、秋月で出ている「H8/3664開発キット」より1000円ほど高いのですが、電源も同梱されているので、比較しても高いものではないと思います。

ただ、箱の写真には、「LCDがついたボード」が載っていますが、中身には含まれていませんので、要注意です。事前に、オークス電子からマニュアルを落とせれますので、これでチェックしておけばわかることなのですが、オプションです。でも、「無いと思っていた」のに、「箱にLCDの写真がついていて、FullKitと書いてあった」ので、ちょっと期待してしまいました。

OAKS16-MINIのピン

20040822P01.JPG - 16,297BYTES 20040822P02.JPG - 10,541BYTES

さて、「あのボードについているピンは、特殊なものなのではないだろうか?」ということがずっと気になっていたんですが、手元にあった秋月で購入した26Pのものと比較してみたら、ぱっと見とか、挿してみた感じとかはそんなに差はありませんでした。手持ちの部品でも使えそうです。

次期コアにしようかどうか、まだそこまでは考えていませんが、最近、だいぶマイコンプログラミングに慣れてきましたので、「ローコスト、ハイパフォーマンス」なものがあれば、いろいろ試して、公開していきたいと思っています。ま、まずはコテ試しに、LEDの点滅でもやってみることにします。

 

2004/08/28

OAKS16-MINIのFull Kit組み立てました。

隙間が多すぎて心が落ち着かない…
20040828P00.JPG - 20,779BYTES20040828P01.JPG - 31,838BYTES

ようやく組み立てました。やっぱ、サラリーマン、どうしても作業は週末になってしまいます。SIPHA COREとかと比べるとものすごく密集度が低いので、どうも心が落ち着きません。きっと、自作コアでサイズにこだわっている方はみんな同じかと。

組み立ては、説明書どおりなんですが、1つだけ替えました。CPUボードのピンフレームをつけるところ、裏をよく見たら、3列全部パターンがつながっていました。というわけで、2列のピンフレームをつけてみました。手元に50Pがあれば楽だったんですが、無かったので、40Pと10Pを2つずつ、削ってつけています。

ピンフレームって、どうして縦方向にきっちり並べられないんでしょうね〜。縦方向に密着してつけるときは、いつも削ってから載せています。

で、これをどう使うかといいますと…(使うかどうかは、実は、全然考えていないんですが…)

20040828P02.JPG - 26,318BYTES20040828P03.JPG - 26,840BYTES

ピンヘッダのほうに電線くっつけて、こんなコネクタのような物を作っておけば、テスト用にCPUのそばから直に信号が取り出せるようになります。

もし、便利そう!と思われた方はトライしてみてください。はい。

というわけで、デバッガ経由でプログラム実行できました。明日は、いよいよ、モニタプログラムをつぶして「ROM書き」しようと思います。さて、この基板、どんな風に使っていきましょう。

 

2004/08/29

OAKS16-MINIでフラッシュROM書き込み

フラッシュROM書き込みテスト完了
昨日、デバッガ経由でのプログラム実行ができましたので、今日は、張り切って、ROM書きにチャレンジしました。TMを使って、「プロジェクトの新規作成」から「Flash Starterで書き込み」までやりましたので、簡単にレポートします。

前提としては、OAKS16-MINI付属の、「Man_miniFullKit.pdf」に従って一通りの作業が終わっているものとします。また、実際に実行したプログラムですが、サンプルにあった「mini1.c」を修正して使っています。

■プロジェクトの新規作成とデバッガで実行
TMをインストールすると、「TMユーザーズマニュアル」というのも一緒にメニュー登録されますので、「クイックツアー」(まつしろさんより)を読みながら、新しいプロジェクトを作ります。「アイテムの編集」−「アイテムの追加」にてソースファイルを追加します。この場合、これから作るファイル名でも構いません。

20040829P00.JPG - 19,741BYTES 20040829P01.JPG - 22,432BYTES

次に、「Man_miniFullKit.pdf」の7.1.2.を読むと、「STARTUPファイルはCDからコピーして云々」とあるので、よくわからないのですがCDからコピーします。KD30を使わない場合は不要かもしれません。

そしてプログラムを書きます。今回は、軽く勉強ということで、mini1.cを、sfr26.hにあわせて書き換えたものを使いました。このsfr26.hというヘッダファイル、M16C/26のレジスタ定義等が定義されているヘッダーファイルです。H8/3664とかやられている方ですと、「3664.h」とか言うとわかりやすいでしょうか?

※追記:以下のソースコードですが、後で"sfr26.h"を見直していたら、p7_addr.byteはp7へ、pd7_addr.byteはpd7に#defineされていました。よって、main()関数の中は、特に修正は不要であることに気づいてしまいました。

//--------------------------------------------------------------------------------------
//  ファイル名: LedBlink.c
//  内容:       LED点灯(LED2,3を交互に点灯 ソフトウエイト)
//               OAKS16KITのmini1.cを基本として、sfr26.hを使用するように変更
//--------------------------------------------------------------------------------------

// インクルードファイル
#include    "sfr26.h"

//    プロトタイプ宣言
void _main(void);

//    マクロ定義
#define LED2_on    0xdf             // LED2(p75)点灯
#define LED3_on    0xef             // LED3(p74)点灯
#define LED_off    0xff             // LED消灯

main(){
    unsigned long i;

    p7_addr.byte = LED_off;         // ポート7出力H(LED消灯)
    pd7_addr.byte = 0xff;           // ポート7方向出力

    for(;;)
    {
        p7_addr.byte = LED2_on;     // LED2点灯
        for(i=0x4ffff;;){           // 時間待ち(ソフトウエイト)
            i--;
            if(i==0) break;
        }
        p7_addr.byte = LED3_on;     // LED3点灯
        for(i=0x4ffff;;){           // 時間待ち(ソフトウエイト)
            i--;
            if(i==0) break;
        }
    }
}
      

後はビルドして、とりあえずデバッガ(KD30)でテストしてみましょう。LEDがmini1.cと同じようにチカチカ点滅するはずです。

■TMにMOTファイル作成の設定を追加
さて、どうやってMOTファイルを作成するかというと、「Man_miniFullKit.pdf」の「6.3.8.プロジェクトエディタ概要」をよく読むと、<アイテム情報ビュー>の説明のところに、「Dflashstart(フラッシュROMに書き込むためのソフト)で使用するモトローラsフォーマットのファイルを作成するためのコマンドです。」という説明があります。これを見て「うむ、きっとこれを追加すればいいに違いない」と思って追加してみました。

アイテムの編集」−「コマンド」を選択すると、次のウィンドウが表示されます。これには、ビルドの最後に実行されるコマンドが記述されています。

「新規」ボタンを押して、ここに、「$(LMC) $(LMCFLAGS) $(OUTDIR)\$(ABSFILE)」を追加します。

これでビルドすると、拡張子が「mot」のファイルができあがります。これを「Flash Starter」で書き込めばOKです。

20040829P02.JPG - 18,743BYTES

■SAKURAエディタ
実は、主にSAKURAエディタを使っているのですが、これをTMに登録する場合、行番号の指定も入れると便利です。ビルドでエラーが出た場合、ビルドのウィンドウからダブルクリックしてジャンプすると、ソースファイルを開いて、該当行までジャンプしてくれますので、なかなか便利です。TMの「オプション」で、「EDIT TOOL」にエディタを登録し、その時に、Parameterに「%F -Y=%L」を指定しましょう。

■最後に
最後に、またデバッガを使う予定があるのでしたら、モニタプログラムを書き込みましょう。CD-ROMの「\oaks_mini\Monitor」にあります。これをFlash Starterで書き込めばOKです。

 

2004/08/30

TMの.tmkファイル 

.tmkを眺めていたら
昨日、motファイルの作成、書き込みに無事成功したわけですが、TMでプロジェクトを生成すると自動的にできる「.tmk」というファイル、よく眺めていたら、いわゆる「makefile」のようです。よくみたら、「t」の「mk」…名前で気づきなさい〜と言われてしまいそうですが、あまり詳しくないんで…はい。

というわけで、昨日、motファイルのために追加した「$(LMC) $(LMCFLAGS) $(OUTDIR)\$(ABSFILE)」ですが、.tmkファイルの上のほうに、$(LMC)の定義が書いてありました。「LMC30」というプログラムです。ビルドすると、

「LMC30 -L 出力ディレクトリ\ほにゃらら.x30」

というコマンドラインとして実行されると思います。試しては無いですけど、コマンドライン派の方は、よかったらお試しください。

ところで、TWO LEGSさんのところで、「OAKS16-MINIで遊ぶ」というコンテンツが追加されています!おおっ。オークス電子でテクニカルニュースがあるんですね!早速チェックしてみよう。さらに…ネコの顔が丸くなっています。え?え?いつから丸くなってました???(前のも捨てがたい…)

 

2004/09/02

UART1でシリアル通信

OAKS16-MINIのサンプルmini5.c
どこから手をつけていこうかな〜といろいろ考えていたんですが、まずはシリアル通信をやってみることにしました。UART0に新しいコネクタをつけようかなと思ったんですが、手持ちが無かったので、練習がてらサンプルのmini5.cをUART1用に変更してみました。

シリアル通信速度の設定
シリアル通信速度の設定は、転送速度レジスタ・UiBRGにするのですが、mini5.cについているコメントを読むと、

20,000,000/19,200/16 - 1
(Clock/bps/16) - 1

とあります。20,000,000は20MでCPUクロック、19,200は転送速度、じゃあ、この「/16」はいったいなんなんだ〜?ハードウェアマニュアルを読んでも、周辺クロックを使用するようなことは書いてありますが、「1/16」なんてのはでてきません。

そういうものと覚えておけばいいのかな〜?と悩んでいたら、TWO LEGSのわたなべさんがヘルプしてくれまして、手元のマニュアルでも確認してみました。転送速度レジスタのところには書いてないのですが(そもそも、これが原因)、「rjj09B0033_m16chm.pdf」のP118のブロック図をよく見ると、「UiBRG」の前に、「1/16」と書いてある箱があるのを発見しました。そして、遂に!P133に「fj/16(n+1)」の計算式を見つけたのです。ふうふうふう。大変でした。きっと、わたなべさんからの書き込みが無ければ、一生、「そういうもんだ」とあきらめていたに違いないです。

よし、これで、「u0mr」とかを「u1mr」に変更すればOK!(UART0とUART1は、たぶん同じ機能)

そう簡単にはいきませんでした。

割り込みベクタテーブル???
mini5.cというサンプル、受信に割り込みを使っているのですが、これのテーブルを書き換えないといけないようです。GDLを使っていると、このあたり、何にも気にしませんでした。「じゃあなぜ気が付いたか?」といいますと、まず、ソースファイルを眺めていて、「このreceive()って関数、割り込み関数みたいだけど、マイコンはどうやってこの関数の位置を知るんだろう???」と思い始めました。そして、あとは「grep」攻撃。で、「sect30.inc」に書いてあるのを発見しまして、他のサンプルも確認して確信しました。

ロボットやり始めの頃、ちょっと秋月電子で扱っているコンパイラを触った時に、そんなようなことがあったような気がしました。というわけで、「sect30.inc」に書いてある

  .lword  dummy_int    ; uart2 receive(for user)(vector 16)
  .lword  dummy_int    ; uart0 transmit(for user)(vector 17)
  .glb    _receive     ;
  .lword  _receive     ; uart0 receive(for user)(vector 18)
  .lword  dummy_int    ; uart1 transmit(for user)(vector 19)
  .lword  dummy_int    ; uart1 receive(for user)(vector 20)
      
こんなふうに修正します。
  .lword  dummy_int    ; uart2 receive(for user)(vector 16)
  .lword  dummy_int    ; uart0 transmit(for user)(vector 17)
  .lword  dummy_int    ; uart0 receive(for user)(vector 18)
  .lword  dummy_int    ; uart1 transmit(for user)(vector 19)
  .glb    _receive     ;
  .lword  _receive     ; uart1 receive(for user)(vector 20)
      

これによって、M16マイコンは、receive()という関数が、UART1の受信割り込みになっていることを知るわけです。「sect30.inc」を眺めていたら、一通りの割り込みが書いてありますので、必要に応じて書き換える必要がありますね。

よく考えてみると、これって、マイコンプログラミングをしていたらあたりまえのことなんですよね?う〜む。いやいや、何事も勉強勉強!

 

2004/09/06

OAKS16-MINIで割り込み無しシリアル通信

うぅ、夏ばて?
夏ばてかな〜。先週の出張から帰ってきてから、調子がイマイチ。みなさんはお元気ですか?

OAKS16-MINI、引き続き、シリアル通信です。新しいものをやるのは、実に楽しいです。でも、オークス電子さん、こういう誰でも作りそうなものは、サンプルライブラリみたいな形で用意しておいた方が、よく売れると思います(ひょっとして、もうある???)それか販売してる方とか…最近、OAKS16-MINIも取り扱っている、チャーリーさんとことかでやってくれないかなぁ〜。

シリアル通信の初期化方法
というわけで、まずは初期化ルーチンです。今回の目標は、割り込み無し、通信速度は2400、4800、9600、19200、38400、57600をサポートすることです。最初は9600bpsぐらいまででいいかなって思ったんですが、KOのシリアル無線機が2400bpsみたいなので、これもできるようにしてみました。

それでは、先日の式で、転送速度レジスタにセットする値を計算してみます(四捨五入してます)。

式は、(20,000,000/速度/16-1)ですね。

57600 = 21
38400 = 32
19200 = 64
9600  = 129
4800  = 259
2400  = 520

うむ。4800bpsと2400bpsは255をオーバーしてしまいました。転送速度レジスタ(UiBRG)は、8ビットですから、セットできません。う〜ん。どうしましょう。てぃろりろりん♪送受信制御レジスタ(UiC0)で、f1sioを使用しているのを、f8sioにすれば、さらに1/8になりますから、それでOKです。

というわけで、4800、2400bpsの場合は、こんな式になります。

20,000,000/速度/16/8-1 (f8sioを使用する)

でも、これはプログラムで切り替えることにします。というわけで、まずは、転送速度を定義します。ついでに、GDLに慣れてしまっているので、_BYTEと_WORDも定義してしまいました。

typedef	unsigned short	_WORD;
typedef	unsigned char	_BYTE;

typedef enum {
    BPS2400  = 521,
    BPS4800  = 260,
    BPS9600  = 130,
    BPS19200 = 65,
    BPS38400 = 33,
    BPS57600 = 22
} RSCbps;

はたと、「H8/3664の時みたいに、charが実はunsignedとかでハマることは無いだろうか?」と心配になりました。どうやら予感的中です。M16もunsignedみたいです。ま、でも、わかっていればそれまでなので、気を取り直して、今回作った初期化ルーチンです。ポイントは、渡された値をチェックして、f1sioかf8sioを再設定するようにしてみました。

void RSCinit( RSCbps tBps )
{
    u1mr = 0x05;                        //  送受信モ−ドレジスタ 内部クロック、非同期、
                                        //  8ビット、パリティなし、スリープなし

    if( tBps > 0xFF ){
        u1c0 = 0x11;                    //  送受信制御レジスタ クロックはf8SIO
        u1brg = (_BYTE)( tBps/8 - 1 );  //  CLKが1/8になるので、BRGも1/8にする。
    }
    else{
        u1c0 = 0x10;                    //  送受信制御レジスタ クロックはf1SIO
        u1brg = (_BYTE)( tBps - 1 );    //  転送速度レジスタ
    }

    u1c1 = 0x05;                        //  送受信制御レジスタ1 送受信許可
}

送信処理
送信は、mini5.cだと、いきなり送信バッファレジスタにいれてまして、結構強引な感じですので、今回は、ジェントルマンに、ちゃんと送信可能かどうかをチェックしてから送信バッファレジスタに入れることにします。しかし、ここでハタと困った。

2つ、同じ意味と思われるフラグが存在します

送受信制御レジスタ0の「送信レジスタ空フラグ(UiC0/TXEPT)」と、送受信制御レジスタ1の「送信バッファ空フラグ(UiC1/TI)」は、説明文は違うのですが、どうやら動作は同じようです。ただ、割り込み要因として指定できるのはTXEPTの方みたいなので、こっちの方が由緒正しいのかもしれません。試しに、両方やってみたのですが、どちらも結果は同じでした。

void RSCsend( _BYTE bData )
{
    while( ti_u1c1 == 0 );      //  ti_u1c1が1になるまで(バッファが空)待つ
    u1tb = (_WORD)bData;        //  送信バッファレジスタにセット
}

受信処理
んでは、受信処理の方、行ってみたいと思います。mini5.cでは、割り込みを使って受信処理をしていましたが、今回は、「割り込みを使わない」のが目的なので、やはり、レジスタで状態チェックをして受信バッファレジスタからデータを取り出すようにします。 これには送受信レジスタ1の「受信完了フラグ(UiC1/RI)」をチェックしていればいいみたいです。というわけで

_BYTE RSCrecv( void )
{
    _WORD   wData;

    while( ri_u1c1 == 0 );              //  受信完了が1になるまで待つ
    wData = u1rb;                       //  受信バッファから取り出す。
    return((_BYTE)( wData & 0xFF ));
}
      

ふむ。これでOKって感じです。今回、バッファチェックは、それぞれの処理中に書いていますが、これを、チェックルーチンとして独立させると「受信待ちせずに、データがある時だけ受信する」という処理ができます。SIPHA COREでも、送受信両方とも、このような使い方をしています。

こんなんでいいのかな???間違ってたら教えてくださいね〜。

で、この後、まだ未解決のよくわからない問題にブチあたるのであった。う〜ん。また後日。

いや、文字列送信関数RSCputs( char* )なんてのを作ってね、RSCputs("abc....")って書いてみたらコンパイルで警告(far pointer (implicitly) casted by near pointer)がでるんですよ。んで、よくわかんないんで、RSCputs( const char* )にしてたら出なくなったんですが、端末に表示されるはずのデータが表示されないわけです。う〜む。現在、調査中です。

 

2004/09/09

続・OAKS16-MINIで割り込み無しシリアル通信

送信処理続編
前回、シリアル通信の送信処理で、「2つ、同じ意味と思われるフラグが存在します。」ということを書きましたが、メカトロ仙術のほりさんからの助言でやっと理解できました。プログラム側からみると、「送信レジスタ」の手前に「送信バッファレジスタ」が存在するということです。

ハードウェアマニュアル(rjj09B0033_m16chm.pdf)の「図13.2 UARTi 送受信部ブロック図」をよく見ると、「UiTB(送信バッファレジスタ)」から「送信レジスタ」データが転送され、そこからデータが送信されている図画描いてあります。つまり、送信処理は、プログラムから「送信バッファレジスタ」にデータを書き込み、それが「送信レジスタ」に転送され、そこからシリアル化されて送信されるわけですね!

そんなわけで、送受信制御レジスタ0の「送信レジスタ空フラグ(UiC0/TXEPT)」は、実際にデータを完全に送りきった場合にフラグがセットされ、送受信制御レジスタ1の「送信バッファ空フラグ(UiC1/TI)」は、「送信バッファレジスタから送信レジスタにデータが転送された時」にセットされるということみたいです。図で書くと、次のような感じでしょうか。

プログラム
処理

送信バッファ
レジスタ

送信
レジスタ
UiC1/
TI
UiC0/
TXEPT
動作
Step 1 'A'を送信 プログラムで、'A'を送信する処理開始
Step 2 'A' 送信バッファレジスタに'A'をセット
Step 3 'A' 送信レジスタに、転送されて送信開始。
Step 4 送信完了されてレジスタが空

そんなわけで、「UiC1/TI」をチェックして送信バッファレジスタにデータを設定すると、「データは送っているとは限らないけど、プログラムからみたら、新データを設定していいタイミング」で設定することになり、「UiC0/TXEPT」をチェックして送信バッファレジスタにデータを設定すると、「完全にデータを送りきった後のタイミング」で設定することになりますね。

実際、送信レジスタが空であれば、Step 2からStep 3は一瞬だと思いますし、プログラムでのフラグチェックも、シリアル通信速度から見ればぐっと速いので、一番確実そうな「UiC0/TXEPT」でのチェックで送信するようにしようと思います。なんとなくもったいないのですが、ベーシックなものとしては良さそうです。文字列送信とかでスピードが気になることがあったら、連続データ送信用に別途用意すればいいかと思います。というわけで、割り込み無しの送信処理は、

void RSCsend( _BYTE bData )
{
    while( txept_u1c0 == 0 );   //  txept_u1c0が1になるまで(送信レジスタが空)待つ
    u1tb = (_WORD)bData;        //  送信バッファレジスタにセット
}

としておくことにします。

と、書いていたら、TWO LEGSのわたなべさんからもフォローの記事が…みなさん、ありがとうございます〜。

 

2004/09/15

nearとfarポインタ

2004/09/06のTOPICの最後にボソボソっと書いた、「関数に文字列を渡すのに警告が出て、あげくの果てに渡されていない模様」みたいな話ですが、未だに解決してなかったりします。たぶん、コンパイラのクセだと思うんで、解決すれば早いんでしょうけど…。

というわけで、ちょっとシンプルなコードを作ってみました。デバッガ前提なので、シリアル出力処理はつけていません。

#include	"sfr26.h"

void main( void );
void strCopy( char* szDest, char* szSrc );

char szWorkG[32];

void strCopy( char* szDest, char* szSrc )
{
    int	nCnt;
    for( nCnt = 0; szSrc[nCnt] != '\0'; nCnt++ ){
        szDest[nCnt] = szSrc[nCnt];
    }
    szDest[nCnt] = '\0';
}

void main( void )
{
    char szWorkL[32];

    strCopy( szWorkG, "ABC" );
    strCopy( szWorkL, "ABC" );
    strCopy( szWorkG, szWorkL );

    while( 1 );
}

これをコンパイルすると、無情にも、

[Warning(ccom):StringSetTest.c,line 21] far pointer (implicitly) casted by near pointer
   ===>         strCopy( szWorkG, "ABC" );
[Warning(ccom):StringSetTest.c,line 22] far pointer (implicitly) casted by near pointer
   ===>         strCopy( szWorkL, "ABC" );

といわれます。さらに、デバッガで動作を追いかけてみると、思ったような値がstrCopy()のszSrcに入ってないようです。警告を読むと、なんかnear pointerのところに、far pointerを無理やり入れてしまったようです。このnearとfar、直訳で「近い」と「遠い」という意味でなんのことやら?ですが、実はポインタ(データや関数のアドレスを指す変数)には2種類あるようで、nearは2バイト - FFFFのアドレス空間を指せる、farは4バイトだけど実は3バイトで 0 - FFFFFFのアドレス空間を指せるポインタになります(わたなべさん、説明ありがとうございました)。で、ハードウェアマニュアルを読むと、RAMは前の方、ROMは後ろの方にあって、ROMがfar pointerなようです。対して、RAMは前の方なのでnear pointerになると。

これをコードで意識するとなると、結構、大変な気がするのですが、みなさんどうされているんでしょうか?例えば、strcpy()のコピー元って、"ABC"と渡したい時もあれば、文字列を編集して渡す(RAM上の変数)こともあるわけです。どうしたらいいんでしょう?悩んだあげく、コンパイルオプションを試してみることにしました。

-ffar_RAM

「RAMデータのデフォルト属性をfarにします。」というオプションです。意味が良くわかりませんが、それっぽいので、試してみることにしました。どうやってTM上でコンパイルオプションを変えるのか、わからなかったので、makeファイル(〜.tmk)のCFLAGSの行を直接編集しました。

リビルド〜!

何か、深そうなもの変更した時は、何はともあれリビルドしましょう。

StringSetTest.c 21 Warning (ln30): .\StringSetTest.r30 : '_szWorkG' value exceed 0FFFFFH
StringSetTest.c 21 Warning (ln30): .\StringSetTest.r30 : '_szWorkG' value exceed 0FFFFFH
StringSetTest.c 23 Warning (ln30): .\StringSetTest.r30 : '_szWorkG' value exceed 0FFFFFH
StringSetTest.c 23 Warning (ln30): .\StringSetTest.r30 : '_szWorkG' value exceed 0FFFFFH
Warning (ln30): .\StringSetTest.r30 : 'bss_FE' data exceed 0FFFFFH

う、また難しそうなものが…。0FFFFFHを越えているぅ???う〜む、なんか違うっぽい…。

 

2004/09/16

nearとfarポインタ、相変わらず悩んでいますが…

いろいろ考えていたんですが、なんか、根本的に理解しないといけない部分がある(ようは知らないコトがある)ような気がしてきました。というわけで、オークス電子さんがアップされている、自習用テキストを読み始めました。今はOAKS16プログラミングテキストの方を読んでいます。ふむふむ。NC30が管理するセクションがウンたらかんたら。何はともあれ、環境(クセとか決り文句)を覚えて慣れないとね!

ところで、デバッガでデバッグするのって、フラッシュROMの書き込み回数にカウントされるのかな?素朴な疑問です。

 

2004/09/17

nearとfarポインタ、いよいよ解決かな?デバッガで変数チェック

_farですよ、_far
いずみかわさんからのヒント、わたなべさんからの助言から、"_far"なるものが必要では?ということがわかってきた今日この頃ですが、ハタと思ったことがありました。

「標準関数はどのように定義されているんだろう?」

NC30は、標準関数ライブラリが用意されているので、このヘッダを覗いてみることに。探してみると「MTOOLS\INC30」にヘッダが入っていました。

char _far * strcpy(char _far *s1, const char _far *s2);

う、ここにそう書いてあるではないか…。先に、こういうところからチェックすればよかった…。みなさん、すいません。わたなべさんのいわれるように、"far"は、"_far"なんですね。うむうむ。というわけで、宣言を修正(ついでにヘッダファイルに書いてあるように、変数名を書かないタイプに修正)して、実体の方も修正して…と。

void strCopy( char _far *, const char _far * );
        :
void strCopy( char _far *szDest, const char _far *szSrc )
{
        :

りびるど〜!
ほとんど呪文のように…

 あ、ビルドできました。

よし、デバッガで確認だ!strCopy()を呼び出しているところでブレークポイントを仕掛けて

「りせっとよぉぉしぃ、ごぉぉぉっ!すてっぷ、すてっぷ、すてぇ〜っぷぅぅぅ!」

お、いいですね。ちゃんとデータが設定されるようになりました。よし、これでまた一歩、この環境へ馴染みました。というわけで、明日は、シリアル通信プログラムに戻ることにします。

みなさん、どうもご指南ありがとうございます〜!

というわけでデバッグのやり方・変数内容チェック
と、喜んでいる様子をお伝えするだけでは、申し訳ないので、デバッグ方法についてのお話です。デバッガを起動すると、まず、Program Windowという画面が出てきます。この画面で、「View」ボタンを押すと、表示するソースファイルの指定をすることができます。

20040917P00.JPG - 24,922BYTES 20040917P01.JPG - 5,710BYTES

はい、ここで、表示するソースファイルを指定します。

20040917P02.JPG - 11,352BYTES

で、ソースファイルが表示されたところで、変数を選択状態にして、右クリックメニューを表示し、「Add C Watch...」を選択すると、「C Watch Window」が開き、変数が追加されます。もちろん、「C Watch Window」をあらかじめ開いておいて、「Add」操作で開いても構いません。

20040917P03.JPG - 15,789BYTES 20040917P04.JPG - 9,545BYTES

「文字列データじゃわからない〜」ってことはありません。この「C Watch Window」で変数を選択してダブルクリックすると、中身を見ることができます。よくできてる、うんうん。

20040917P05.JPG - 30,243BYTES

というわけで、先ほど修正したソースコードで、ステップ実行させた時の変数表示です。思ったとおりの値が入っていることがわかります。

20040917P06.JPG - 32,551BYTES

また、このように、グローバルなデータだけではなく、ローカルなデータも表示することができます。

20040917P07.JPG - 35,079BYTES

ふぅぅ、長かった〜。でも、偉大なる第一歩!

 

2004/09/23

OAKS16-MINIで割り込み無しシリアル通信・送信

送信処理、結局こうなりました。
え〜、OAKS16-MINIネタを書くのは久しぶりですが、送信バッファレジスタの意味もわかり、また、_farの謎がわかり、無事、ビルド完了となったのですが、連続したデータ(要は文字列)を送信したら、変なデータが出てきてしまいました。1文字ずつ送ると問題無いんですが、連続して送ると、「ABCDEFG」が、「ADF???」みたいな感じで、データが飛び飛びになってしまいます。書いたプログラムは、以前お見せしましたこれです。

void    RSCsend( unsigned char bData )
{
    while( txept_u1c0 == 0 );        //  送信レジスタが空になるまで待つ
    u1tb = (_WORD)bData;             //  送信バッファレジスタにセット
}

んで、考えたんですが…実は、「送信バッファレジスタから送信バッファに送る速度は、実は超高速ではない」のではないか?と推測しています。良く考えてみれば、送信レジスタが空になったからといって、送信バッファレジスタにデータ突っ込むのは紳士じゃないですね〜。

ということは、「送信レジスタ空フラグ(UiC0/TXEPT)」と、送受信制御レジスタ1の「送信バッファ空フラグ(UiC1/TI)」の両方をチェックしてやるのがベスト!ということになるのですが、ま、そこまではいいかな?ということで、送信バッファレジスタをチェックするだけにしておきます。

void    RSCsend( unsigned char bData )
{
    while( ti_u1c1 == 0 );           //  送信レジスタが空になるまで待つ
    u1tb = (_WORD)bData;             //  送信バッファレジスタにセット
}

今は、puts()とかgets()とかを作っていますので、もう少しテストができてきたら、まとめてアップします。
(やりだめしていた家のこととか、仕事とか忙しいのもあるんですが、実はH8/3664の方もいじっているので進みが遅いというのはヒ・ミ・ツ)

 


SISO-LAB Knowledge