度々お世話になっております。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 // 一回のデータ送信サイズ
#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];
unsigned char CFAE:1;
unsigned char :2;
unsigned char CMDLK:1;
unsigned char DFAE:1;
unsigned char :3;
} FASTAT;
char wk3[3];
unsigned char CFAEIE:1;
unsigned char CMDLKIE:1;
unsigned char DFAEIE:1;
} FAEINT;
char wk4[3];
unsigned char :7;
unsigned char FRDYIE:1;
} FRDYIE;
char wk5[23];
unsigned long LONG;
unsigned long FSADDR:32;
} FSADDR;
unsigned long FEADDR:32;
} FEADDR;
char wk6[72];
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;
} FSTATR;
unsigned short WORD;
unsigned short KEY:8;
unsigned short FENTRYD:1;
unsigned short :6;
unsigned short FENTRYC:1;
} FENTRYR;
char wk7[2];
unsigned short :7;
unsigned short FPROTCN:1;
} FPROTR;
char wk8[2];
unsigned short SUINIT:1;
} FSUINITR;
char wk9[2];
unsigned char FLOCKST:1;
} FLKSTAT;
char wk10[15];
unsigned short CMDR:8;
unsigned short PCMDR:8;
} FCMDR;
char wk11[30];
unsigned short :8;
unsigned short PEERRST:8;
} FPESTAT;
char wk12[14];
unsigned char BCDIR:1;
} FBCCNT;
char wk13[3];
unsigned char BCST:1;
} FBCSTAT;
char wk14[3];
unsigned long :13;
unsigned long PSADR:19;
} FPSADDR;
char wk15[4];
unsigned short :15;
unsigned short ESUSPMD:1;
} FCPSR;
char wk16[2];
unsigned short PCKA:8;
} 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;
if (FLASH.FASTAT.BIT.CMDLK == ON)
status = 0;
else
status = 1;
else if(FLASH.FSTATR.BIT.FRDY == OFF)
if(n >= 60)
ForceEndCmd();//FACI強制終了コマンド処理 今回は実行していないので、割愛
else { n++;}
WaitTimer(1);
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;
FACI.FACI_BYTE.UINT = WriteData[3+(2*n)]+WriteData[4+(2*n)];
if(n==80-1)
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();
Loopflg2 = true;
prgStatus = -1;
n++;
}while(Loopflg == false);
while(Loopflg == false)
if(FLASH.FSTATR.BIT.FRDY == 1)
WaitTimer(8);
if(ErrCount == 4)
if(FLASH.FASTAT.BIT.CMDLK == ON)
prgStatus = 0;
return prgStatus;
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) で待機するような仕組みを導入しまして、無事、ブレイクポイント無しでも書き込みが確認出来ました。コードフラッシュ領域の全域を番地をずらしつつ読み込んでみたのですが、全て意図したデータとなっておりました。とりあえず一安心です。ありがとうございました。
改めまして、数日間にも渡り、私の拙い質問から的確にご対応いただき、本当にありがとうございます。おかげで予定通りに事が進められそうです。