CPU実験室

誰も見向きもしない古いCPUをいじって動かしてみようというプロジェクトです

EEPROM書込み

NS揃いにはなりませんが、ROMを準備していたEEPROM:HN58V65Aに換装して動作確認してみます。

EEPROMならばボード上で電気的消去、書込みはできますが一番最初は別のシステムで書込みをしておかなければならないので自作のROMライタにデバイス追加しました。

ホスト側プログラムはデバイス選択を追加するのみです

f:id:O3I:20211204185704j:plain

変更の実体はROMライタ側ファームウェアになりますが、いままでデバイスを追加するたびに拡張を繰り返してきたためコーディングが非常に汚くなってます。最初に良かれと思って何段にも階層化して下請け処理を抽象化・隠蔽化したのですがプログラムが大きくなるにつれ下請け処理の詳細仕様が判らなくなり、似たようなルーチンを派生して作っていったら依存関係や関数名も変数名もぐちゃぐちゃになってしまったのでこの際整理しようと思います。

先ずはなるべく外部関数を呼ばずにベタで処理を書いて見通しを良くしてみました。例えばEEPOMの書込みルーチンは長くなりますが書込み範囲を指定してこれだけ呼べば書き込みが完了します。

int eep_program(long *parm)
{
    int rtn=0;
    unsigned char db,db0;
    unsigned char *src,*dst;
    unsigned long i,len;
    unsigned char adrh,adrm,adrl;
    /*    indicator    */    
    ctrl_sreg(LED_WRITE,ON);
    ctrl_sreg(rom.socket,ON_ORG);            
    /*    parameter    */    
    src=ADRS_BUFTOP+parm[1];
    dst=ADRS_ROMTOP+parm[2];
    len=rom.size;
    /*    mount    */
    set_vcc(conv_vcc(rom.v_vcc));
    enable_vreg();
    wait_ms(10);
    enable_vcc(rom.pin_vcc);    
    /*    data write    */
    for(i=0;i<len;i++){
        db0=*src;
        if(db0!=0xff){
            /*    address set    */
            sep_adrs(dst,&adrh,&adrm,&adrl);
            set_ctrlpin(OFF,OFF);
            ROMW_ADR0 = adrl;
            ROMW_ADR1 = (unsigned char)(adrm | 0xc0);    /* pin1=1 /WE =1 */
            ROMW_ADR2 = 0xF0;    
            /*    data out    */
            ROMW_DRCW = 0x88;             /* PA=out PB=out PCH=in PCL=out */
            ROMW_DR0 = db0;
            set_ctrlpin(OFF,ON);
            /*    write pulse    */
            wait();
            ROMW_ADR1 = (unsigned char)(adrm | 0x80);    /* pin1=1 /WE =0 */
            wait_10us( (unsigned int)(rom.pw_pgm/10) );
            ROMW_ADR1 = (unsigned char)(adrm | 0xc0);    /* pin1=1 /WE =1 */
            set_ctrlpin(OFF,OFF);
            /* busy check    */
            wait_10us(1000);                /* wait 10ms    */        
            /*    verify    */
            ROMW_DRCW = 0x9a;             /* PA=in PB=in PCH=in PCL=out */
            set_ctrlpin(ON,ON);
            wait();
            db=(unsigned char)ROMW_DR0;
            if(db != db0){
                rtn= -1;
                break;
            }
        }
        dst++;
        src++;
    }

    /*    remove    */
    set_ctrlpin(OFF,OFF);
    ROMW_ADR0 = 0x00;
    ROMW_ADR1 = 0x00;    
    ROMW_ADR2 = 0x00;
    ROMW_CNTR = 0x00;
    disable_vcp();

    /*    indicator    */
    ctrl_sreg(rom.socket,OFF);    
    ctrl_sreg(LED_WRITE,OFF);    
    error_proc(rom,rtn);
        
    return rtn;
}

これと同じようにROM種別XXXごとにXXX_READ(読出し),XXX_PROGRAM(書込み),XXX_VERIFY(ベリファイ),XXX_ERASE(消去),XXX_ERASE_CHK(消去チェック)関数を用意してあとから共通部分をくくりだせばコードは読み易くなりそうです。

f:id:O3I:20211204185648j:plain

HN58V65Aは一般的な2764とほぼピンコンパチ、書き込む手順も同等と見做せます。27ピンの/PGMがそのまま/WEに。1ピンのVppに加える高電圧が不要となりそのピンが書き込み中を示す/BUSY出力になります。

ROMライタのソケット1ピンはVppとアドレスA15が多重化されオープンコレクタでドライブするので/BUSYの読み取りはハード的にできません。データビットのトグルでBUSYを検出するアルゴリズムもありますがここは無条件に10ms待ちとしています。(プログラムコードの朱書き部分)

 

書込み中の/BUSYピンの挙動を見てみると実際には5msくらいで終了しているので書込みサイクルをもう少し短縮できそうですが、それほど大きいサイズの書込みをするわけではないのでこれで良しとしておきます。

f:id:O3I:20211204185933j:plain