RX660ソフトアップデートについて

度々お世話になっております。
GAと申します。

以前から、RX660のFW開発を行っているのですが、
現在、ソフト上から自身を書き換える、ソフトアップデートの処理を作成しております。
そのデバッグの際に、コードフラッシュの領域のイレース後と、書き込みを行った後に、
同じ領域を読み出して(Char配列にダンピングし、)動作を確認しようとしているのですが、
イレース処理後も、書き込み処理後もダンピングされたデータに変化がありません。
そこで、二点、どうしても自分で解決できなかった疑問点があります。
どちらか片方でも構いませんので、ご存じでしたらお教えいただけますと幸いです。
①そもそも、コードフラッシュ領域のデータを、配列等にダンピングして確認するという方法は可能なのでしょうか。
 イレースやブランクチェック等を許可するレジスタは見受けられるのですが、読み出しを許可するレジスタ等が無く、
 アドレス番地の指定さえしてあげれば、読み出せる認識だったのですが、これは正しい認識でしょうか。
②ハードウェアマニュアルを参考に、ブロックイレースとブロックライトの処理を作成致しました。
 現状、処理自体は動いており、無限ループ等に陥っている様子もありません。
 下記に開発環境と該当部分のソースを記載させていただきます。
 このやり方で、目的としているコードフラッシュ領域への書き込みは可能でしょうか。

[開発環境]
ソフト:CS+ for CC V8.11.00 [30 Nov 2023]
デバッガー:E2 Lite
対象:RX660 (R5F56609EDFP#10)

[該当ソース]
先に定数部を記載します
(定数部抜粋)

#define FACI    (*(volatile struct st_faci    __evenaccess *)0x7e0000)
//FACIコマンド発行領域レジスタ 自作


typedef struct st_faci

{

    union

    {

        unsigned int UINT;

        struct

        {

            unsigned char BYTE1:1;//発行領域4バイト分

            unsigned char BYTE2:1;

            unsigned char BYTE3:1;

            unsigned char BYTE4:1;

        }BYTE;

    }FACI_BYTE;

} st_faci_t;

#define FLASH   (*(volatile struct st_flash  __evenaccess *)0x8C294)//フラッシュレジスタ スマートコンフィグレータで作成

typedef struct st_flash {

    char           wk100[2];

    union {

        unsigned char BYTE;

        struct {

            unsigned char :6;

            unsigned char FLWE:2;

        } BIT;

    } FWEPROR;

    char           wk0[7794397];

    unsigned long  UIDR0;

    char           wk1[108];

    unsigned long  UIDR1;

    unsigned long  UIDR2;

    char           wk2[11812];

    union {

        unsigned char BYTE;

        struct {

            unsigned char CFAE:1;

            unsigned char :2;

            unsigned char CMDLK:1;

            unsigned char DFAE:1;

            unsigned char :3;

        } BIT;

    } FASTAT;

    char           wk3[3];

    union {

        unsigned char BYTE;

        struct {

            unsigned char CFAEIE:1;

            unsigned char :2;

            unsigned char CMDLKIE:1;

            unsigned char DFAEIE:1;

            unsigned char :3;

        } BIT;

    } FAEINT;

    char           wk4[3];

    union {

        unsigned char BYTE;

        struct {

            unsigned char :7;

            unsigned char FRDYIE:1;

        } BIT;

    } FRDYIE;

    char           wk5[23];

    union {

        unsigned long LONG;

        struct {

            unsigned long FSADDR:32;

        } BIT;

    } FSADDR;

    union {

        unsigned long LONG;

        struct {

            unsigned long FEADDR:32;

        } BIT;

    } FEADDR;

    char           wk6[72];

    union {

        unsigned long LONG;

        struct {

            unsigned long :16;

            unsigned long FRDY:1;

            unsigned long ILGLERR:1;

            unsigned long ERSERR:1;

            unsigned long PRGERR:1;

            unsigned long SUSRDY:1;

            unsigned long DBFULL:1;

            unsigned long ERSSPD:1;

            unsigned long PRGSPD:1;

            unsigned long :1;

            unsigned long FLWEERR:1;

            unsigned long :6;

        } BIT;

    } FSTATR;

    union {

        unsigned short WORD;

        struct {

            unsigned short KEY:8;

            unsigned short FENTRYD:1;

            unsigned short :6;

            unsigned short FENTRYC:1;

        } BIT;

    } FENTRYR;

    char           wk7[2];

    union {

        unsigned short WORD;

        struct {

            unsigned short KEY:8;

            unsigned short :7;

            unsigned short FPROTCN:1;

        } BIT;

    } FPROTR;

    char           wk8[2];

    union {

        unsigned short WORD;

        struct {

            unsigned short KEY:8;

            unsigned short :7;

            unsigned short SUINIT:1;

        } BIT;

    } FSUINITR;

    char           wk9[2];

    union {

        unsigned char BYTE;

        struct {

            unsigned char :7;

            unsigned char FLOCKST:1;

        } BIT;

    } FLKSTAT;

    char           wk10[15];

    union {

        unsigned short WORD;

        struct {

            unsigned short CMDR:8;

            unsigned short PCMDR:8;

        } BIT;

    } FCMDR;

    char           wk11[30];

    union {

        unsigned short WORD;

        struct {

            unsigned short :8;

            unsigned short PEERRST:8;

        } BIT;

    } FPESTAT;

    char           wk12[14];

    union {

        unsigned char BYTE;

        struct {

            unsigned char :7;

            unsigned char BCDIR:1;

        } BIT;

    } FBCCNT;

    char           wk13[3];

    union {

        unsigned char BYTE;

        struct {

            unsigned char :7;

            unsigned char BCST:1;

        } BIT;

    } FBCSTAT;

    char           wk14[3];

    union {

        unsigned long LONG;

        struct {

            unsigned long :13;

            unsigned long PSADR:19;

        } BIT;

    } FPSADDR;

    char           wk15[4];

    union {

        unsigned short WORD;

        struct {

            unsigned short :15;

            unsigned short ESUSPMD:1;

        } BIT;

    } FCPSR;

    char           wk16[2];

    union {

        unsigned short WORD;

        struct {

            unsigned short KEY:8;

            unsigned short PCKA:8;

        } BIT;

    } FPCKAR;

} st_flash_t;

#define BLK_SIZE    128                 // 1ブロックサイズ

#define DATSIZE     BLK_SIZE+6          // 一回のデータ送信サイズ

(処理部)
int BlockErase( int block )
{
    int status, n;
    bool Endflg = false;
    n=0;
    FLASH.FSADDR.BIT.FSADDR =  ERASEBLOCK[block].bit;
    do
    {
        if(FLASH.FSTATR.BIT.FRDY == ON)
        {
            FACI.FACI_BYTE.UINT = 0x20;
        //  WaitTimer( 80 );
            FACI.FACI_BYTE.UINT = 0xD0;
            Endflg = true;
        }
        else{}
    }while(Endflg == false);
    Endflg = false;
    do
    {
        if(FLASH.FSTATR.BIT.FRDY == ON)
        {
            Endflg = true;
            if (FLASH.FASTAT.BIT.CMDLK == ON)
            {
                status = 0;
            }
            else
            {
                status = 1;
            }
        }
        else if(FLASH.FSTATR.BIT.FRDY == OFF)
        {
            if(n >= 60)
            {
                Endflg = true;
                status = 1;
                ForceEndCmd();//FACI強制終了コマンド処理 今回は実行していないので、割愛
            }
            else { n++;}
            WaitTimer(1);
        }
    }while(Endflg == false);
    return status;
}

int ProgBlock( UCHR* Waddr )
{
    UCHR*   dataAddr;
    UCHR    ReWrite[BLK_SIZE + 2], WriteData[BLK_SIZE + 2];
    SUCHR   program_data[DATSIZE + 2];
    int     n, prgStatus, i,ErrCount;
    bool    Loopflg,Loopflg2;
    Loopflg = false;
    Loopflg2 = false;
    ErrCount=0;
    for(i=0;i<DATSIZE+2;i++)
    {
        program_data[i] = 0x00;//デバッグ確認用に全て0で埋めた書き込みデータを用意する
    }
    i=0;

    dataAddr = ( UCHR* )( &program_data[3] );//元々の書き込みデータが、配列上の三番目となるため
    for ( i = 0; i < BLK_SIZE; ++i, ++dataAddr )
    {
        WriteData[i] = ReWrite[i] = *dataAddr;
    }
    FLASH.FPROTR.WORD = 0x5501;
    FLASH.FWEPROR.BIT.FLWE = 0x1;   //フラッシュライトイレーズ許可 0b01
    FLASH.FENTRYR.WORD = 0xAA01;
    FLASH.FSADDR.BIT.FSADDR =  Waddr;
    FACI.FACI_BYTE.UINT = 0xE8;
    FACI.FACI_BYTE.UINT = 0x80;
    FACI.FACI_BYTE.UINT = WriteData[3] + WriteData[4];
    n=1;
    do
    {
        FACI.FACI_BYTE.UINT = WriteData[3+(2*n)]+WriteData[4+(2*n)];
        if(n==80-1)
        {
            FACI.FACI_BYTE.UINT = 0xD0;
            Loopflg = true;
        }
        else if (FLASH.FSTATR.BIT.DBFULL == ON)
        {
            while(Loopflg2 == false)
            {
                ErrCount++;
                WaitTimer(4);
                if(FLASH.FSTATR.BIT.DBFULL == OFF)
                {
                    ErrCount = 0;
                    Loopflg2 =true;
                }
                else if (ErrCount == 4)
                {
                    ForceEndCmd();
                    Loopflg = true;
                    Loopflg2 = true;
                    prgStatus = -1;
                }
            }
        }
        n++;
    }while(Loopflg == false);
    Loopflg = false;
    while(Loopflg == false)
    {
        if(FLASH.FSTATR.BIT.FRDY == 1)
        {
            Loopflg = true;
        }
        else
        {
                ErrCount++;
                WaitTimer(8);
                if(ErrCount == 4)
                {
                    Loopflg = true;
                    ForceEndCmd();
                    prgStatus = -1;
                }
        }
    }
    if(FLASH.FASTAT.BIT.CMDLK == ON)
    {
        prgStatus = 0;
    }
    else
    {
        prgStatus = -1;
    }
    return prgStatus;
}


Parents
  • 下記リプライ上にてお話しさせて頂いていた通り、イレース後、コードフラッシュへの書き込みの処理を確認しております。
    その際に、FACIコマンド領域に書き込みを行っても、FCMDRレジスタから読み出せるデータが変化しない状態になりました。
    具体的には、データプログラム時の0xE8を書き込んだ後、0x80を書き込むはずなのですが、この0x80が読み出せず、
    データ書き込み後の0xd0も書き込み後、読み出せない状態です。
    (
    CMDRレジスタが直前に書き込んだ0xE8、PCMDRレジスタが0xd0でイレースコマンドの時のままとなっております)

    また直接関係があるかは分かりませんが、FRDYフラグが立たず、書き込みが完了しません。
    下記リプライ上で出た、
    FPROTRレジスタ設定やFSADDRに書き込むアドレス等を確認しましたが、意図したものとなっています。
    (設定忘れや、アドレスの書き込みが出来ていないような状態ではありませんでした)

    お忙しいところ恐れ入りますが、何卒お知恵をお借り出来ますと幸いです。

Reply
  • 下記リプライ上にてお話しさせて頂いていた通り、イレース後、コードフラッシュへの書き込みの処理を確認しております。
    その際に、FACIコマンド領域に書き込みを行っても、FCMDRレジスタから読み出せるデータが変化しない状態になりました。
    具体的には、データプログラム時の0xE8を書き込んだ後、0x80を書き込むはずなのですが、この0x80が読み出せず、
    データ書き込み後の0xd0も書き込み後、読み出せない状態です。
    (
    CMDRレジスタが直前に書き込んだ0xE8、PCMDRレジスタが0xd0でイレースコマンドの時のままとなっております)

    また直接関係があるかは分かりませんが、FRDYフラグが立たず、書き込みが完了しません。
    下記リプライ上で出た、
    FPROTRレジスタ設定やFSADDRに書き込むアドレス等を確認しましたが、意図したものとなっています。
    (設定忘れや、アドレスの書き込みが出来ていないような状態ではありませんでした)

    お忙しいところ恐れ入りますが、何卒お知恵をお借り出来ますと幸いです。

Children
  • GAさま

    >この0x80が読み出せず、

    FACI「コマンド」としては、0xE8(書き込み)コマンドなので、E8が読み出せれば、コマンド受け付け状態で

    0x80, データ…

    はコマンドでは無いので、FCMDRには入らないと思います。

    FACIのアクセスの場合、書き込みデータは2バイト単位でのアクセスとなると思います。

    手元に、RX660のボードが無かったので、とりあえず別なマイコン(RX66N)ですが、(エラー処理とかタイムアウトとか一切無い、書き込みに必要なコマンドを列挙しただけですが)、単純にFACIレジスタにコマンド+データサイズ(0x40)+データ+終了コード(0xD0)を送っただけで、上手く書き込みは出来ている様に見受けられます。

    ※RX660の場合は、データサイズは0x80(256バイト単位での書き込み)

    RX660の場合は、ロックビットのプロテクト解除

    FLASH.FPROTA.WORD = 0x5501;

    が必要かも知れません。(必要無いかも知れません。)

  • tfさん

    ご回答ありがとうございます。
    また、RX66Nでの書き込み処理のご展開ありがとうございます。
    こちらを参考に処理を組み直した所、デバッグ中のステップ実行でのみ、0x80一回分の書き込みは出来るようになりました。
    (書き込み後、書き込みを行った領域を読み出した所、char128個分のデータのみ、0xffから更新されておりました。)
    書き込み自体が出来るようになったのはデータの受け渡し用にunsigned shortのアクセスを追加したことが要因かと思われます。
    また、ロックビットのプロテクト解除につきましては、書き込み処理の関数を呼び出す前に、
    FLASH.FPROTR.WORD = 0x5501;で設定しておりました。

    現状、上記処理をループで複数回呼び出し、
    コードフラッシュ領域の必要な範囲内(0xFFF20000~0xFFFFFFFF)全てに
    書き込みを行おうとしているのですが、
    最初の0x80一回分の書き込み終了後にアドレスをずらして書き込みを開始すると、
    コマンドロックがかかってしまい、その次の書き込みを行うことが出来ません。
    (1回目書き込み完了、2回目書き込み途中でコマンドロック、3回目以降が書き込み不能となります。)
    コマンドロックをCMDLKで確認し、コマンドロックが確認された場合のみ、0xB3をFACIに書き込み、強制終了を行うように
    処理を変更しましたが、今度は書き込み自体が上手くいかない状態となってしまいました。
    コマンドロックが発生している為、何かしらのエラーが出ていないか確認したところ、
    FLASH.FPESTATに0x02=ロックビット以外の原因によるプログラムエラーとなっておりました。
    現在、このプログラムエラーを引き起こす原因を探っているところでございます。

    下記に現状の書き込み処理に使用している関数二つを記載します。
    気になった点や気が付いた点等ございましたら、ご展開いただけますと幸いです。


    /*-----------------------------------------------------------
    機能 :フラッシュROMの指定領域書込み
    引数 :ULNG startAdr: 書込み開始アドレス
    :ULNG endAdr : 書込み終了アドレス
    戻り値 :正常:(0)/異常:(-1)
    -----------------------------------------------------------*/
    int ProgRom( ULNG startAdr, ULNG endAdr )
    {
    //startAdr = 0xFFF20000 endAdr = 0xFFFFFF7F (0xFFFFFFFF-0x80 = 0xFFFFFF7F)
    unsigned long addr = 0;
    int i;

    for ( addr = startAdr; addr < endAdr; addr += BLK_SIZE )
    //BLK_SIZE = 0x80=128
    {
    if ( ProgBlock( addr ) != 0 )
    {
    return -1;
    }
    }
    return 0;
    }
    /*-----------------------------------------------------------
    機能 :1ブロック書込み
    引数 :UCHR* Waddr:
    戻り値 :正常:(0)/異常:(-1)
    -----------------------------------------------------------*/
    int ProgBlock( UCHR* Waddr)
    {
    UCHR* dataAddr;
    UCHR ReWrite[BLK_SIZE + 2], WriteData[BLK_SIZE + 2];
    SUCHR program_data[DATSIZE + 2];//DATSIZE = BLK_SIZE+6 = 128+6=134
    int n, prgStatus, i,ErrCount;
    bool Loopflg,Loopflg2;
    Loopflg = false;
    Loopflg2 = false;
    ErrCount=0;
    UCHR hogechar =0;
    unsigned long hogelong = 0;
    unsigned int hogeint = 0;
    unsigned long addr_memo = 0;
    //UCHR = unsigned char ,SUCHR= static unsigend char

    //書き込み用の疑似データ作成
    for(i=0;i<DATSIZE+2;i++)
    {
    program_data[i] = i;
    }
    i=0;

    dataAddr = ( UCHR* )( &program_data[1] );
    for ( i = 0; i <= BLK_SIZE; ++i, ++dataAddr )
    {
    WriteData[i] = ReWrite[i] = *dataAddr;
    }

    FLASH.FSADDR.BIT.FSADDR = Waddr;
    addr_memo= FLASH.FSADDR.BIT.FSADDR;//デバッグ時のアドレス確認
    do
    {
    WaitTimer(1);
    }
    while(FLASH.FSTATR.BIT.DBFULL == ON);

    FACI = 0xE8;
    WaitTimer(80);//nop()80回分
    FACI = 0x80;
    //#define FACI (*(volatile unsigned char *)0x7e0000)

    //デバッグ用のステータス確認
    hogechar = FLASH.FASTAT.BYTE;
    hogelong = FLASH.FSTATR.LONG;

    FACI_S = (unsigned short)WriteData[2] | ( ((unsigned short)WriteData[1]) <<8 );
    //#define FACI_S (*(volatile unsigned short *)0x7e0000)

    //デバッグ用のステータス確認
    hogechar = FLASH.FASTAT.BYTE;
    hogelong = FLASH.FSTATR.LONG;

    n=1;
    do
    {
    FACI_S = (unsigned short)WriteData[(2*n)+1] | ( ((unsigned short)WriteData[2*n]) <<8 );

    if(n==BLK_SIZE-1)
    {
    FACI = 0xD0;
    FACI_command_chk(0xD0);//FLASH.FCMDR.BIT.CMDRの値と渡した値との比較関数
    Loopflg = true;
    hogechar = FLASH.FASTAT.BYTE;
    hogelong = FLASH.FSTATR.LONG;
    if(hogechar == 0x10)
    {
    hogeint = FLASH.FPESTAT.WORD;
    }
    }
    else if (FLASH.FSTATR.BIT.DBFULL == ON)
    {
    while(Loopflg2 == false)
    {
    ErrCount++;
    WaitTimer(4);
    if(FLASH.FSTATR.BIT.DBFULL == OFF)
    {
    ErrCount = 0;
    Loopflg2 =true;
    hogechar = FLASH.FASTAT.BYTE;
    hogelong = FLASH.FSTATR.LONG;

    }
    else if (ErrCount == 4)
    {
    ForceEndCmd();
    Loopflg = true;
    Loopflg2 = true;
    prgStatus = -1;
    hogechar = FLASH.FASTAT.BYTE;
    hogelong = FLASH.FSTATR.LONG;

    }
    }
    }
    n++;
    }while(Loopflg == false);
    Loopflg = false;
    while(Loopflg == false)
    {
    if(FLASH.FSTATR.BIT.FRDY == 1)
    {
    Loopflg = true;
    }
    else
    {
    hogechar = FLASH.FASTAT.BYTE;
    hogelong = FLASH.FSTATR.LONG;
    ErrCount++;
    WaitTimer(80);
    if(ErrCount == 4)
    {
    Loopflg = true;
    ForceEndCmd();
    prgStatus = -1;
    }
    }
    }
    n=0;
    prgStatus = 0;
    hogechar = FLASH.FASTAT.BYTE;
    hogelong = FLASH.FSTATR.LONG;

    return prgStatus;
    }

  • BLK_SIZE = 0x100; //256

    でうまく行くんじゃないでしょうか。

    2バイト単位で、0x80(128)なので、アドレスは0x100(256)バイトずつ進める必要があります。

  • tfさん
    ご回答ありがとうございます。
    BLK_SIZEがいろいろな箇所で使用している定数でしたので、取り急ぎ、
    for ( addr = startAdr; addr < endAdr; addr += BLK_SIZE )を
    for ( addr = startAdr; addr < endAdr; addr += 256 )に変更して動作を確認しました。
    ProgBlock()内のFACI = 0xD0;にブレイクポイントを置いて動作を確認したところ、コマンドロックがかからない状態となりました。
    (30回分程度確認しましたが、コマンドロックはされていなかったです。)
    その後ダンピングされたデータも意図されているデータとなっておりました。
    ただ、ブレイクポイントを外し、
    ProgBlock()や ProgRom()をステップオーバーなどで実行した場合、
    (書き換え関数処理内で一度も止めずに実行した場合)
    ダンピングされるデータが全て0xffとなっておりました。
    フラッシュへの書き込み処理が追い付いていない可能性を考え、
    FACI=0xD0;の後に、100回程度の_nop()命令を実行し、
    書き込み処理待ちをさせてみたのですが、今度は8バイト毎に書き換えられたデータと
    0xffを繰り返すようなデータとなりました。
    (0x00,0x01....0x08,0xff,0xff....0xff,0x09...のような規則的に書き換えたデータと0xffを繰り返すようなものとなりました)

    書き換え処理という点だけ見ると出来ているようなので、あとは0xD0を書き込んでからの処理のどこかに問題が残っているだけだとは思うのですが、
    今までステップ実行と止めない実行で結果に差が出たことが無かったため、困惑しております。
    もし、似たような事例をご存じでしたら、お教えいただけますと幸いです。

  • 連続書き込みもやってみましたが、

    FACI = 0xD0;

    while (FLASH.FSTATR.BIT.FRDY != 1) //Readyを待つ
    {
      __nop();
    }

    //書き込み(2回目)

    FLASH.FSADDR.LONG = 0xfff80100;

    FACI = 0xE8;
    FACI = 0x80;

    for(i=0; i<128; i++)
    {
      while (FLASH.FSTATR.BIT.DBFULL != 0)
      {
        __nop();
      }
      FACI2 = (unsigned short)wdata[i*2] | (((unsigned short)wdata[i*2+1]) << 8);
    }

    で問題無く、2回目も書き込みが出来ています。

    単純に、0xD0(書き込みコマンドの終わり)書き込み後、コマンド受け付け状態(FLASH.FSTATR.BIT.FRDY==1)を待つだけでうまく行かないでしょうか。

    (256バイトの書き込みに、電気的特性の所に記載がありますが、typで0.4ms掛かります。(maxは7.2ms)nopで待つのは良い方法ではないと思います。)

  • tfさん
    ご回答ありがとうございます。
    先ほど、FACI = 0xD0;後にwhile (FLASH.FSTATR.BIT.FRDY != 1) で
    待機するような仕組みを導入しまして、無事、ブレイクポイント無しでも書き込みが確認出来ました。
    コードフラッシュ領域の全域を番地をずらしつつ読み込んでみたのですが、
    全て意図したデータとなっておりました。とりあえず一安心です。
    ありがとうございました。


    改めまして、数日間にも渡り、私の拙い質問から的確にご対応いただき、
    本当にありがとうございます。
    おかげで予定通りに事が進められそうです。