HCS08 FLASH書き込み 地獄のリベンジ編 [HCS08]
#259
ならばこれでどうだ!
HCS08のアセンブラの出来に関しては、もう知らんよ!。
/****************************************************************/
/* FLASH ROM書き換え処理 */
/* ポインタ型を無理やり整数型で扱って気持ちの悪いところを修正 */
/* アセンブラで記述し直し */
/* Copyright (c) せくすぃ部長 since 2007/09/18 */
/****************************************************************/
#include "derivative.h" /* include peripheral declarations */
#include <string.h>
#define Page_Erase ((unsigned char(*)(volatile unsigned char *, unsigned char))(pgm))
#define Program_Byte ((unsigned char(*)(volatile unsigned char *, unsigned char))(pgm))
/****************************************************************/
/* 特定のFLASH領域に書き込み/消去を行う */
/* Copyright (c) せくすぃ部長 since 2007/09/18 */
/****************************************************************/
volatile static unsigned char flash_era_wrt( volatile unsigned char *adr, unsigned char data )
{
#asm
PSHA ;
LDA #0x10 ; FACCERRが立っているかチェックする
BIT _FSTAT ; FACCERRが立っているかチェックする
BEQ _NEXT_01 ; 立っていない時は_NEXT_01にブランチ
ORA _FSTAT ; FACCERRが立っているならクリアして置く
STA _FSTAT ; 書き戻し
_NEXT_01: ; 該当する領域にデータを代入する。
PULA
STA ,X
; コマンド書き込み。最初はERASEコマンド
LDA #0x40
STA _FCMD
; FCFBEFに1を書き込み
LDHX @_FSTAT ;
LDA ,X ; FCFBEFを1にする
ORA #0x80 ; FCFBEFを1にする
STA ,X ; 書き戻し
BRN _NEXT_02 ; 4バスサイクル消費する※修正
_NEXT_02 :
NOP
; FACCERRとFVIOLがエラーでない事を確認する
LDA ,X
AND #0x30 ; FACCERRとFVIOLの該当bit
BEQ _NEXT_03 ; 立っていない時は_NEXT_03にブランチ
LDA #0xff ; 戻り値を0xffにする※修正
RTS
; FCCFが0の間はコマンド処理中
_NEXT_03 :
LDA ,X
AND #0x40 ; FCCFの該当bit
BEQ _NEXT_03 ; 0の間は_NEXT_03にブランチ
#endasm
return 0;
}
/****************************************************************/
/* 文字列をFLASH領域に書き込む */
/* Copyright (c) せくすぃ部長 since 2007/09/18 */
/****************************************************************/
int FlashCopy( void *adr, void *data, unsigned short size )
{
unsigned char temp;
char *ptr = (char *)data;
volatile unsigned char pgm[ 46 ];
/*フラッシュ書き込みコードのコピー*/
(void)memcpy( pgm, flash_era_wrt, sizeof(pgm) );
pgm[ 0x11 ] = 0x20; /*コマンドをbyte writeコマンドに変更する*/
/*フラッシュ書き込み*/
for( ; size > 0; size-- )
{
if( *ptr != 0xff )
{
temp = Program_Byte( (volatile unsigned char *)adr, *ptr );
if( temp == 0xff ) return (-1);
}
((char *)adr)++;
ptr++;
}
return 0;
}
/****************************************************************/
/* 引数のアドレスが存在するブロックを消去する */
/* Copyright (c) せくすぃ部長 since 2007/09/18 */
/****************************************************************/
int FlashErase( void *adr )
{
unsigned char temp;
volatile unsigned char pgm[ 46 ];
/*フラッシュ消去コードのコピー*/
(void)memcpy( pgm, flash_era_wrt, sizeof(pgm) );
/*フラッシュ消去*/
temp = Page_Erase( (volatile unsigned char *)adr, 0x00 );
if( temp == 0xff ) return (-1);
return 0;
}
/****************************************************************/
/* Copyright (c) せくすぃ部長 since 2007/09/18 */
/****************************************************************/
気になったところをいくつか。
> ORA _FSTAT ; FACCERRが立っているならクリアして置く
> STA _FSTAT ; 書き戻し
ORAは、不要です。ORAがあるとすべてのフラグがクリアされてしまいます。
> LDA ,X ; FCFBEFを1にする
> ORA #0x80 ; FCFBEFを1にする
> STA ,X ; 書き戻し
これも同じです。
# ということは、オリジナルのプログラムも変なのか?
> JMP _NEXT_02 ; 4バスサイクル消費する
> _NEXT_02 :
この関数はFLASHに展開されるから、絶対アドレスJUMPはまずいでしょう。私のお勧めは、以下の3バイトです。
> BRN *
> NOP
by のりたん (2007-09-21 12:50)
> この関数はFLASHに展開されるから、絶対アドレスJUMPはまずいでしょう。
ぬあ!本当だ、うっかりしていた。nopを4つ並べるよりも低コストな命令見つけた!と浮かれていてそればっかりになっていた。
なんで動いたんだ?。
FSTATはビット操作命令が使えないので、うーんそうすると関係ない所をマスクして書き戻さないといけないのか?。
> # ということは、オリジナルのプログラムも変なのか?
そう言えば気になる点も有る。
オリジナルはマシン語だからコメントアウトされているCソースをコンパイルして動かした時、0xffの書き込みで失敗していたんですよね。別に0xffなら書き込む理由がないので、条件式で避けるようにしていたんですが。
※マシン語で動かしている時はこれが無かった。
by hamayan (2007-09-21 13:46)