CS+ for CC のデバッグ・ツールについて

最近、マイコンを触り始めたものです。

CS+ for CC で RL78/G14 の R5F104LE(64pin)、アプリケーション(CC-RL)でプロジェクトを作成している状態です。

以下のような簡単なプログラムを main.c に書いています。

#include "iodefine.h"

static void intit(void);
#pragma interrupt intit(vect = INTIT, bank = RB1)

void main(void) {
// インターバルタイマの割り込み許可
ITMK = 0;
__EI();

// 低速オンチップ・オシレータ・クロックを供給
OSMC |= 0x10;

// クロックの供給許可
RTCEN = 1;

// LED0 の設定
PM1_bit.no7 = 0; // 出力モード
P1_bit.no7 = 1; // 消灯

// 100ms 間隔で動作開始
ITMC = 0x8000 + (15000 / 1000) * 100 - 1;

while(1);
}

void intit(void) {
static int count = 0;

if (10 == count) {
P1_bit.no7 = !P1_bit.no7;
count = 0;
} else {
++count;
}
}

この状態でデバッグ・ツールとして RL78 EZ Emulator を選択し、CC-RL (ビルド・ツール) のプロパティからリンク・オプションタブの、デバイス > デバッグ・モニタ領域を設定する を 「はい」にした状態でビルド&デバッグ・ツールへダウンロードを押すと、以前はソースファイルに対してステップオーバー実行などが出来ていたのに、逆アセンブル上でしかできなくなってしまいました。
現在のPC位置を示す黄色くなる行も逆アセンブルにしか表示されず、ソースファイルにはPC位置を示すものも表示されず、アドレス欄も空欄です。
何か設定を変えてしまったのだと思いますが、どこの設定を直せばソースファイル上でのステップオーバー実行ができるでしょうか。

よろしくお願いします。

Parents
  • あれこれするより新しくプロジェクトを作成してプログラムをコピペした方が解決が速いと思います。
  • cafe_rene.zip

    チョコです。

    solさんがやられている方法は、初心者にはあまりお勧めできません。

    RL78には、コード生成機能があり、GUIで使用したい内蔵周辺機能を指定すると、必要なプログラムが生成されるので、面倒な初期設定が完了した状態でmain関数が起動します。

    ただし、WDTが有効になってしまうので、そこは禁止することをお勧めします。

    とは、いえ、せっかくなので、solさんのプログラムを実際にやってみました。

    RL78/G14 の R5F104LE(64pin)でRL78 EZ Emulator ということなので、テセラさんから販売されていた

    RL78/G14 Stick スターターキットで検証してみました。

    CS+CCで新しいプロジェクトを作成し、main.cに提示されたプログラムを埋め込んで、リンクオプションをスレッドになるように設定して

    実際にビルドしてRL78/G14 Stick スターターキットにダウンロードしてみました。

    結果は全く問題なくステップ実行もできました。(ただし、最後はwhile(1)のループになるので、その先は無意味ですが。)

    使用したプロジェクトのzipファイルを添付しておきます。

     

  • チョコです。

    追加情報です。

    かふぇルネには、私が投稿した初心者向けの「チョコさんのRL教室」というものがあります。

    http://japan.renesasrulz.com/cafe_rene/b/rl78-classroom

     

    今はトップページの左側のナビの一番下になってしまっていますが、ここの内容が役に立つのではないかと思います。

  • 今回は、あれこれいじってしまった後の既存のプロジェクトを何とかしたかったです。
    試していただき、ありがとうございました。
  • 以前、見させていただいて、一通りやってみた覚えがあります。
    コード生成の機能は確かに便利なのですが、他のマイコンを使用する際にはこの統合開発環境が使えるとは限らず、データシートから読み解く技能を身につけなければならないので、できるだけデータシートを見ながら手書きして試しています。
  • チョコです。
    >データシートから読み解く技能を身につけなければならないので、できるだけデータシートを見ながら手書きして試しています。

    それは、いいのですが、今のプログラムの構成はどうかと思います。
    ほとんどのMCUは一つの端子に複数の機能が割り当てられ、リセットが解除された時点では、殆どアナログ入力かデジタル入力になっています。この状態が長く続くとトラブルの原因になることが考えられます。そのため、端子の設定をできるだけ早く行う必要があります。
    リセットが解除されると通常スタートアップ・ルーチンが起動し、C言語のプログラムを動かすための準備をしてからmain関数をスタートさせます。しかも、スタートアップ・ルーチンでは、最初に使用する内蔵周辺機能の初期設定を行い(その中でも、ポート設定は最初の方)、その後に変数の初期化を行うことで、端子が入力(ハイ・インピーダンス状態)をできるだけ早く解消するようになっています。
    組み込み用途では、ここらをきちんと考えて処理すべきです。
  • タイマーやポートの設定する前に割り込み許可してるのも宜しくない感じですね。
  • そうなんですね…
    全く知りませんでした。
    どうするのが正解か、コード生成を見て確認して、なぜその順番なのかを調べる形で解決していくのが適切でしょうか?
  • そうなんですね、どういう順番でやるべきなのか全くわからないのですが、正しい順番というのはどうすれば分かりますか。
  • チョコです。

    >どうするのが正解か、コード生成を見て確認して、なぜその順番なのかを調べる形で解決していくのが適切でしょうか?

    既にあるプログラムを参照するのが一般的で、コード生成(ある意味ルネサスの推奨)も一つの方法です。
    ルネサスが準備しているサンプルコードも初期化に関してはコード生成を使っているようです。
Reply
  • チョコです。

    >どうするのが正解か、コード生成を見て確認して、なぜその順番なのかを調べる形で解決していくのが適切でしょうか?

    既にあるプログラムを参照するのが一般的で、コード生成(ある意味ルネサスの推奨)も一つの方法です。
    ルネサスが準備しているサンプルコードも初期化に関してはコード生成を使っているようです。
Children
  • 分りました。

    その方法で調べていきたいと思います。

    試しに、LED0 (P17) を SW1 (P75) が押されている間点灯、そうでないとき消灯するというプログラムを書くための初期プログラムを、コード生成を使って作ってみました。

    以下の設定の上、コード生成を行いました。

    ・端子割り当て設定 = 初期状態のまま確定

    ・P17 = 出力

    ・P75 = 入力、内蔵プルアップ

    ・ウォッチドッグ・タイマ動作設定「使用しない」

    hwinit 関数でハードウェアに関する初期化をしているのかな、と考えました。

    特に、ポートの初期化はこの部分だということもわかりました。

    void R_Systeminit(void)

    {

       PIOR0 = 0x00U;

       PIOR1 = 0x00U;

       R_CGC_Get_ResetSource(); // リセットフラグの取得

       R_CGC_Create(); // クロック動作周波数の初期化?

       R_PORT_Create(); // ポートの初期化

       IAWCTL = 0x00U;

    }

    3つほど質問があります。

    ①リセット時の値が保証されているものに対してもわざわざ初期化しているのはなぜでしょうか。

    例えば、PIOR0 (周辺I/O リダイレクション・レジスタ0) は、リセット信号の発生により, 00H になります。とデータシートに記載がありますが、わざわざ代入しているようです。

    ②IAWCTLは、不正メモリ・アクセス検出制御レジスタ、とのことで、ポート機能、割り込み機能などの制御レジスタにライト可能かどうかを設定することができるもののようでした。

    これが0であれば、その機能は無効なので、ライト可能となる、というのは分かりました。

    でもそれって、やるなら一番最初にしないといけないのではと思ったのですが、なぜ最後にあるのでしょうか。

    ③ void R_PORT_Create(void) の中身は以下のようになっていました。

    P1 = _00_Pn7_OUTPUT_0;
    PU7 = _20_PUn5_PULLUP_ON;
    PM1 = _01_PMn0_NOT_USE | _02_PMn1_NOT_USE | _04_PMn2_NOT_USE | _08_PMn3_NOT_USE | _10_PMn4_NOT_USE |
    _20_PMn5_NOT_USE | _40_PMn6_NOT_USE | _00_PMn7_MODE_OUTPUT;
    PM7 = _01_PMn0_NOT_USE | _02_PMn1_NOT_USE | _04_PMn2_NOT_USE | _08_PMn3_NOT_USE | _10_PMn4_NOT_USE |
    _20_PMn5_MODE_INPUT | _40_PMn6_NOT_USE | _80_PMn7_NOT_USE;

    この順番(ポートの値の初期化→ プルアップ抵抗の有効化→ ポートモードの設定)である必要はありますか?

    また、そうであれば、なぜかを教えてください。

    また、この順番である必要があるのかどうかは、どうやって判断すれば良いでしょうか。(順番を入れ替えてバグが起きればわかりやすいのですが…)

     

    以上、よろしくお願いします。

  • チョコです。

    >例えば、PIOR0 (周辺I/O リダイレクション・レジスタ0) は、リセット信号の発生により, 00H になります。とデータシートに記載がありますが、わざわざ代入しているようです。

    これは、ほかの値に設定するときに、値だけを設定すればいいように、わざわざ初期値と同じ値を設定しているものと考えられます。
    ②についても同じ理由でここに設定があります。最初にないのはリセットで全て許可になっているからと、禁止する前に設定を完了させておくためです。実は、他のスレッドにありましたが、ここで禁止するのは、別の問題があります。(初期設定は終了していても割り込みの制御は内蔵機能を起動するときにも行いますが、そこが引っかかってしまいます。)

    >この順番(ポートの値の初期化→ プルアップ抵抗の有効化→ ポートモードの設定)である必要はありますか?
    ポートモード設定よりは、ポートの出力ラッチの設定が先である必要があります。そうしないと、出力ポートをハイで初期化しないといけないときにポートの出力ラッチのロウが出力されてしまい、ポートにヒゲが出力されてしまいます。
    スレッドの最初の書き込みでは、順番が逆になっていました。これでは、ステップ実行で最初に一瞬LEDが点灯するのが分かったはずです。通常実行させても、もしかしたらLEDが薄く点灯するのが観測できたかもしれません。こんなことで分かることもあります。
  • チョコです。
    追加でコメントします。

    >hwinit 関数でハードウェアに関する初期化をしているのかな、と考えました。
    その通りです。このhdwinitはスタートアップ・ルーチン(cstart.asm)から呼び出されています。アセンブラの時代からhdwinit がハードウェアの初期化を行っています。その名残か、CS+で新しいプロジェクトを作成したときにhdwinit .asmが生成され、_hdwinitという空のサブルーチンが入っています。
    コード生成するとr_systeminit.cの中にhdwinit関数が存在し、そこからR_Systeminit関数を呼び出して、そこで初期化を行っています。

    >R_CGC_Create(); // クロック動作周波数の初期化?
    使用するクロックによって異なります。RL78は、基本的にHOCO(高速内蔵発振クロック)です。その周波数はオプション・バイトで決められます。ここでは、ここでは、クロック発振用端子の設定や高速システムクロックを使うときの処理や、サブシステム・クロックなどをメインに処理しています。

    >R_CGC_Get_ResetSource(); // リセットフラグの取得
    これは、お勧めできません。コード生成でリセット要因の読出しは禁止しておくことを推奨しています。
    これは、コード生成のブービートラップの一部です。R_CGC_Get_ResetSource()関数では、リセット要因をローカル変数にセットしているだけです。この関数から戻ってきた段階でリセット要因レジスタはクリアされてしまっています。(たとえ、ローカル変数の値をグローバル変数に格納しても、その後のスタートアップ・ルーチンで変数領域が初期化されてしまうので意味がありません。
    それよりは、チェックを外して、全部自分で処理するのが正解です。

    >この順番(ポートの値の初期化→ プルアップ抵抗の有効化→ ポートモードの設定)である必要はありますか?

    追加ですが、「プルアップ抵抗の有効化」は最後の方がいいかもしれません。ここでやると、出力ポートで使用するときにHi-Z→ Hi → 正規の出力値となります。Hi-ZをLowと認識すれば、Lowが初期値のときにヒゲが出ます。ただし、プルアップ抵抗をONにしてもすぐにはHiにはならないので、連続した処理では影響は考えなくてもいいですが。

    ついでに、入力ポートに対するビット操作は要注意です。ここらは、マニュアルにも記載されているので、確認してみてください。
  • ①、②
     なるほど。
     ここさえ変えれば設定できるように、一応書いてあるみたいな感じですね。


     1. ヒゲというのは、一瞬混じるノイズデータのような意味でしょうか。
     2. 入力モードの状態で入出力ポートへ書き込んだ場合、
      > 転送命令により, 出力ラッチに値を書き込めます。しかし, 出力バッファがオフしていますので, 端子の状態は変化しません。
      > 一度出力ラッチに書き込まれたデータは, もう一度出力ラッチにデータを書き込むまで保持されます。
      > また, リセット信号が発生したときに, 出力ラッチのデータはクリアされます。
      との記述を見つけました。
      この記述が理解できないのですが、出力ラッチと、出力バッファがよく分かっていないからです。
      ・入出力ポートへ書き込み = 入出力ポートのレジスタへ書き込み
      ・ラッチは入力の値を特定のタイミングで保持する回路のこと
      ・入出力ポートのレジスタに書き込まれたデータは、特定のタイミングで出力ラッチにコピーされる
      ・出力バッファ???
      ・出力バッファがONの時は、出力ラッチの値が出力される。
      ・出力バッファがOFFの時は、端子の状態は変化しない。
     ということでしょうか。
     特に出力バッファがよくわかりませんが、出力するかどうかのフラグみたいなものですか?
  • > hdwinit, clock, reset
    わかりました。理解できました。

    > port
     Hi-Z とは、何でしょうか…?
     他は分かりました。
     > 出力モードに設定したビットは, プルアップ抵抗オプション・レジスタの設定にかかわらず, 内蔵プルアップ抵抗は接続されません
     との記載があるので、ここは問題ないのかな?と思っていました。

    > 入力ポートに対するビット操作は要注意
     確認して、仕組みも理解できました。
     ありがとうございます。
  • チョコです。
    >特に出力バッファがよくわかりませんが、出力するかどうかのフラグみたいなものですか?
    例えば、P17で見てみます。
    G14のマニュアルの「2.1.8 64ピン(コード・フラッシュ・メモリ16 KB~64 KB)」でP17をみると端子タイプが「8-1-8」となっています。
    そこで、「2.4 端子ブロック図」で、端子タイプ「8-1-8」を見ると、「図2 - 18 端子タイプ8-1-8の端子ブロック図」に記載されています。
    このブロック図の左側の中央から少し上に「出力ラッチ」とかかれた四角があります。これがP17として書き込んだときにデータが書き込まれるレジスタです。

    その右側にP-chとN-chのトランジスタが上下に接続され、真ん中からその右の◎(これが端子を示します)に接続されていますが、この部分が出力バッファです。
    出力ラッチと出力バッファの間は論理回路を介して接続されているので、PM(ポート・モード)レジスタが出力(0)になっていると、出力ラッチに設定された値が端子に出力されます。RL78はトランジスタの数を抑えるために、兼用機能を含めた論理回路になっていますが、基本はPMが0で出力バッファがオンして出力ラッチの値が端子に出力され、PMが1なら出力バッファはオフしているので、端子には出力されません。
    PMレジスタが出力(0)になっているとP17を読むと、右側のセレクタ(台形で示される)を介して出力ラッチの値を読むことができます。(左側のPMSレジスタで制御されるセレクタは安全機能で、PMレジスタの設定によらず、端子の状態を読めるようになっています。通常は右側のセレクタの出力が選択されています。)
  • チョコです。
    >Hi-Z とは、何でしょうか…?
    ハイ・インピーダンスのことです。
    データを出力していないので、入力モードと同義になります。
  • ありがとうございました。
    まだまだ回路図は全然読めないですが、出力ラッチの意味については分かりました。
    出力バッファの意味については、なんとなくわかりました。
    このくらい分かれば、なんとなくいいかな、と思っています。
    ありがとうございました!