| ホーム |     私の電子工作作品集

144. 簡易 S-RAM チェッカー (8 bit)

[ 初公開日:2013年6月17日 ]

 最近、Yahoo!オークションに少しばかりはまっており、安く落札した各種サイズのスタティック RAM が、どんどんと溜まってきました。

 Yahoo!オークションで落札するのはいいのですが、果たしてこれらの RAM は生きているのでしょうか? ・・・ もし不良品であればそんなゴミばかりをいくら集めてもまったく意味がありません。

 そこで、各種メモリサイズに対応できる RAM チェッカーを、PICで作ることにしました。 2K バイト、8K バイト、32K バイト、64K バイト、128K バイトの5種類に対応した仕様です。


ケースに収納 ( 2016/1/26 更新 )

 本機は、長い間、左上写真に示すようにプリント基板のままにしてありましたが、この度、右上写真のようにケースに収納しました。

 プリント基板のままで使用していると、何と言っても埃っぽくなってくることと、本機の性格上、頻繁に使用するわけでもないので、 使用しないときの保管性が悪くなることがあげられます。

 今まで、本機のために何か良いケースはないものか、と常に思ってはいたのですが、なかなか思わしいものが見つからずにいました。 そこで "CPUの創りかた TD4" で使用した物と同じ、"フリーケース A5 L8998 (サナダ精工株式会社)" を この作品のケースとしてはどうか、と思って使用してみました。

 ただ、本機を収納するだけではケースサイズが大き過ぎるので、同種のチェッカー "簡易 S-RAM チェッカー (1 bit/4 bit)" と同居させることにしました。

重大なバグを修正 ( 2018/6/23 更新 )

 本機で SRAM のチェックをしている最中に、PIC の PORTB と入力データの制御用バスバッファ 74HC541 の出力、および SRAM のデータバスと出力データの制御用フリップフロップ 74HC574 の出力が、 それぞれデータ衝突を起こしているという重大なバグがあることが分かりました。 ハードウエアの一部修正とともにプログラムの修正でデータ衝突を起こさないように対処しました。 詳細は、プログラムの項の 該当の説明 を参照してください。

全チェックパタン自動実行の機能追加 ( 2018/7/7 更新 )

 4つのすべてのチェック方法を実施する場合には、DIP スイッチを操作することなくタクトスイッチの簡単な操作だけで、すべてのチェック方法を自動的に実施できる機能を追加しました。 詳細は、プログラムの項の 該当の説明、機能概要と使用法の項の 機能追加 を参照してください。

■ 回路図 ■

( 2018/6/23 更新 )

 上記の回路図は、プログラムバグの修正に伴うハードウエアの変更と、その他数点の見直しをした変更後のものに差し替えてあります。 変更前の旧回路図(StaticRamChecker4x.gif)も参考のために こちら に残しておきます。 旧回路図では、 LCDの E端子、すなわちPICの RD0 ポートに 47KΩのプルダウン抵抗が付いていましたが、何の目的で付けたのか8年も経った今となっては私自身でも謎です。 間際らわしいので削除しました。

| 回路図 (StaticRamChecker.CE3) | ページトップ |

■ 回路の検討 ■

当初、本装置のハードウエア設計をするに当たって、PIC16F877A だけでは I/O数が足りないため、 昔からの古い知識と在庫がいっぱいあると言う単純な理由から、PPI 8255A で I/O数を増やそうと安易に回路に組み込みました。 そしてプリント基板も完成させました。

ところが、いざプログラムを組みだしてから始めて気がつきました。 ・・・ PIC では 8255A は使えない ・・・ 当然ながら 8080A/8085A で 使用するような使い方はできないのです。 8255A を制御するための A0, A1, /CS, /RD, /WR 信号等を、PIC のプログラムで いちいち作り出してやらなければなりません。

がっくりきました。 このままのハードウエアでは、PIC → 8255A → Flip-Flop IC → RAM と、かなり面倒な過程のプログラムに なってしまいます。 もう一度考え直しです。 そして最も手抜きな方法で解決することにしました。 一応完成しているプリント基板には あまり手を加えたくありません。

8255A を ICソケットから抜いてしまい、その後の入出力の信号線を回路図中の ・・・ 線のように直結してしまう、と言うものです。 プログラムも PIC → Flip-Flop IC → RAM の制御でよくなりました。 次に配線を施したフラットケーブル用の ICソケットコネクタの 写真を示します。 8255A 用 ICソケットに差し込みます。


また、本装置では電源供給に、スイッチングレギュレータ等の DC+5V 出力を、直接供給するようにしてしまいましたが、 これはどちらかと言うと失敗でした。 それは RAM の Vcc 電源をトランジスタでスイッチングしているため、当然ながら 0.6V 程度の 電圧降下が起こります。 結果として、RAM のチェックにはあまり影響はなかったようですが、チェッカーとして感心できません。 電圧降下分を上乗せした電圧をスイッチングのトランジスタに与えるべきです。

本装置には DC+9V または DC+12V を供給し、本装置内で一般 IC用の DC+5V と、RAM 用の電圧降下分を上乗せした電圧を作り出すべきです。 次に、それらを考慮した電源部の回路図を参考までに示しておきます。



本装置のチェックに要する所要時間を正確に測定するためには、BUSY 信号が出力されている時間を測定すればいいのですが、そのまま 単純に外部に引き出したのでは少々心許ないし、プリント基板にも空きエリアがありましたので気休めにバッファを入れておきました。

また、その時間測定には "長時間ストップウオッチ/タイマー" を使用するのですが、そちらへの 電源供給も簡単に行なえるように、プリント基板上に供給用の電源端子も設けておきました。


| ページトップ |

■ ケース外観と内部の様子 ■

 冒頭でも述べたように、本機の "簡易 S-RAM チェッカー (8 bit)" と 姉妹機の "簡易 S-RAM チェッカー (1 bit/4 bit)" を、同一ケース内に同居させました。 ケース内の上部約 1/3 に位置する部分に "簡易 S-RAM チェッカー (1 bit/4 bit)" を、その下部の約 2/3 に位置する部分に "簡易 S-RAM チェッカー (8 bit)" を収納しました。

 下の写真からも分かるように、ケース内の上下スペースには空きがなくいっぱいいっぱいですが、本機の右横には中途半端なサイズのスペースが 空いています。 どちらのチェッカーも、プリント基板の左横側に電源供給の DCジャックが取り付けてありますので、ケース内に収めたときに プリント基板の左側にはスペースを空けられません。 (ケースの左側面には、それぞれの電源供給用のプラグが挿入できるように、 ○穴が開けてある)

 そこで、この中途半端なサイズのスペースの有効利用方法が特にありませんので、写真(黒色部分)のように、とりあえず導電スポンジを 敷き詰めておきました。 これは、被測定用 S-RAM の一時的な退避場所に使用することを想定しています。 あとは本機を使用しないときに、 電源供給用の小型スイッチングACアダプタをこのスペースに収納しておく、くらいの利用方法しか思い付きません。

ケース正面の斜め上から見たところ ケース背面の斜め上から見たところ
ケース左側面の斜め上から見たところ ケース右側面の斜め上から見たところ
蓋をあけてケース内部を真上から見たところ ( 拡大 ケース裏面を真上から見たところ

| ページトップ |

■ 機能概要と使用法 ■

  • 本装置は、今となっては既にレガシーなデバイスとなってしまった、8ビット幅のスタティックRAM (種類:2Kバイト、8Kバイト、32Kバイト、64Kバイト、128Kバイト)のメモリチェックを 行なうのを目的とする。

  • 本装置は、電源スイッチをオンすると、"ピポッ" と起動ブザー音を出力後、液晶(LCD)にスタート メッセージとして、次の文字列が約3秒間表示される。 また同時に、BUSY(黄)、OK(緑)、NG(赤)の各 LED を、 約1.5秒間細かく交互に点滅させて、点灯チェックも行う。
    		"StaticRamChecker"
    		"   ( 8 bit )    "
    
           

  • その後、次のメッセージに切り替わって約1.5秒間表示され、その後には無表示が約1.5秒間続く。
    		"    ver.x.xx    "
    		"  by m.yamamoto "
    


  • やがて無表示の後、次のような SRAM タイプの選択メッセージが表示され、初期値として 2K が選択されて、 その直前の空白 " " の位置がブリンク表示されている。 また同時に、"ピポッ" とブザー音を出力してユーザに 選択の注意を喚起する。
    		"Type?_  2K    8K"
    		" 32K   64K  128K"
    


  • これはユーザからのスイッチの入力待ちの状態を表し、←(LEFT)/ →(RIGHT)スイッチ の操作によって、 自由に SRAM タイプの選択を行なうことができる。 すなわちこのスイッチ操作によって "ポッ" というブザー音とともに ブリンク位置が移動し、今ブリンクしている直後の SRAM タイプが選択されていることになる。



  • SRAM タイプを選択したなら、次に ENTER スイッチ を押下することによりその選択が決定され、次のチェックの スタート促進メッセージが表示される。この時にもユーザの注意を喚起するため、"ピポッ" とブザー音を出力する。
    		"<xxK>   Start?_ "		; xxK 位置に選択された RAM タイプが入る
    		"                "
    


  • そしてその後、ENTER スイッチ が押下されればそのまま SRAM チェックがスタートすることになるが、もしここで 何らかの理由により SRAM タイプの選択を変更したい場合には、BREAK スイッチ を押下することによってチェック スタートされることなく、再び SRAM タイプの選択メッセージの表示に戻ることができる。

  • そのまま ENTER スイッチが押下されると、いよいよ SRAM チェックがスタートし "ピポッ" と開始ブザー音とともに、 まず次のようなチェック進行メッセージが表示される。
    		"<xxK>    Er:0000"		; xxK 位置に選択された RAM タイプが入る
    		"A:     W:   R:  "
    
          チェック進行中 チェック終了

  • ここで機能の追加を行なった。 機能の追加以前では、例え選択された SRAM タイプと実際にセットされた SRAM が 異なっていても、メモリチェックがスタートされてしまっていた。 この場合に実際にはどんな影響が起こるのか 良く分からないが、極端な場合には IC自体にもかなりのダメージを与えることも想像される。

  • そこでメモリチェックがスタートされてしまう直前に、両者のタイプの整合性をチェックするように機能を追加した。 整合性チェックがOKの場合のみ初めて、上記のようなチェック進行メッセージが表示されて チェックがスタートされる。

  • 整合性チェックがNGの場合には、次のようなタイプミスマッチエラー・メッセージが表示されるとともに、 結果 NG(赤LED) が点灯して同時に "ブッブー" というブザー音を出力して、整合性にエラーがあったことを ユーザに知らせる。
    	      ( "<xxK>   Start?_ " )
    		"Type Mismatch !!"
    


  • エラーを確認後、ENTER スイッチ を押下することによって結果 NG(赤LED) を消灯させ、再び次のスタート促進 メッセージの表示に戻る。 そこで、正しい SRAM タイプの ICをセットし直すか、またはこのスタート促進 メッセージの表示で BREAK スイッチ を押下することによって、再度 SRAM タイプの選択メッセージの表示に戻って、 SRAM タイプの選択からやり直すことになる。
    		"<xxK>   Start?_ "		; xxK 位置に選択された RAM タイプが入る
    		"                "
    


  • ただし、何らかの理由によりこの追加機能がひょっとして邪魔な場面があるかもしれない。 そのための考慮として、 ENTER スイッチを押下しながら POWER スイッチをONした場合 には、整合性チェックは一切機能しない。

  • 一方、メモリチェックがスタートされると上記のチェック進行メッセージが表示され、A: はアドレス を、 W: は書き込みデータ を、R: は読み出しデータ をそれぞれ表し、":" の後にその内容が表示されてチェックの 進行にしたがって刻々と変化をして行く。 これらはすべて16進数で表示され、通常は A:xxxx、W:xx、R:xx の形式で表示されるが、128K タイプの SRAM に限ってはそのアドレスは Axxxxx と表示される。 これはアドレスが 17 ビットあり16進数4桁では表示できないためである。

  • また、Er: はそのときまでに起こったエラー数 を表示し、16進数4桁表示であるが最大数を超えた場合には オーバーフローして、また "0" からカウントをし直す。(16進数4桁で表示し切れないようなものは、 あきらかに異常な SRAM でありそのエラーの絶対数には、あまり意味を成さないためである)

  • ただし、これらのチェック進行メッセージの内容表示がされるのは、LCD PASS スイッチ(SW6: DIP スイッチの内の左端)が OFF に設定されている場合であり、ON に設定されている場合にはその内容表示はされない。 これは液晶(LCD)に 表示するのに多くの時間を要し、メモリ容量の大きな SRAM では極端に時間がかかってしまうために、LCD PASS スイッチを設けたものである。 ただし、エラー数表示に関しては LCD PASS スイッチの ON/OFF に係わらず、 エラーがあった場合には常に更新表示される。

  • また、SRAM をチェックするのに4つの方法が用意されており、それぞれ SELECT 1, 0 スイッチ(SW5: DIP スイッチの内の真中、SW4: 右端)の設定で、自由に選択が可能である。(それらの方法については 下記 プログラム の項を参照のこと)

  • この SRAM のチェックの進行中にエラーが多発したような場合で、もうこれ以上チェックを続行させても無駄と 判断した場合には、BREAK スイッチ を押下することによって、いつでもチェックを中断し終了させることも可能である。 ただし、エラーが起こってなくても BREAK スイッチを押下すれば、やはりチェックは中断終了してしまうので そのスイッチの扱いには十分注意を要する。

  • 一方、次のチェックのスタート促進メッセージが表示されているときに、PAUSE (←(LEFT)スイッチと兼用) スイッチを押しながら ENTER スイッチを押下した場合 には、エラー発生時に ポーズ動作 を行なう。 すなわち、エラーが発生した場合には、その時点での A: アドレス、W: 書き込みデータ、R:読み出しデータの内容、 および Er: エラー数が表示された状態で、一時的にチェックの進行が中断される。このとき、結果 NG(赤LED) が 点灯するとともに "ブー" というブザー音も出力してエラー表示を行ない、ポーズ状態に入ったことをユーザに知らせる。
    		"<xxK>   Start?_ "		; xxK 位置に選択された RAM タイプが入る
    		"                "
    


  • したがって、そのときの液晶(LCD)に表示されている内容を確認した後、CONTINUE (→(RIGHT)スイッチと兼用) スイッチ を押下すると、結果 NG(赤LED) が消灯してこのポーズ状態から抜けチェックが続行される。 この CONTINUE スイッチで続行しても、再度エラーが発生すれば再びポーズ状態に移行することになる。 また、続行を中断したい場合には BREAK スイッチ を押下すれば、やはりチェックは中断し終了処理に移行する。

  • 下記 プログラム の項のように、4つのチェック方法の相違によって、チェックから終了処理に至るまでの過程は違うものの、 やがてプログラミングされた予定の処理に終了を迎えた場合、または上記のように BREAK スイッチによって 強制的に中断終了させた場合に、終了処理に移行する。

  • 終了処理では、まず SRAM チェックの総合結果を LED の表示とブザー音の出力でユーザに知らせる。 エラーがなく 正常に終了した場合( BREAK 終了も含む)には、結果 OK(緑LED) が点灯して同時に "ポッポッポッポッ" というブザー音を出力して正常終了をユーザに知らせる。 また、エラーが1件以上あって終了した場合には、 結果 NG(赤LED) が点灯して同時に "ブッブー" というブザー音を出力してエラー終了をユーザに知らせる。

  • これでとりあえず1つの SRAM のチェックが終了したことになるが、続いて他の同タイプの SRAM のチェックを 行ないたい場合には、ここで ENTER スイッチ を押下すれば、再び以下のスタート促進メッセージが表示されるとともに、 "ピポッ" とブザー音を出力してユーザの注意を喚起する。 したがって、他の SRAM に交換して新たにチェックを行なう。
    		"<xxK>   Start?_ "		; xxK 位置に選択された RAM タイプが入る
    		"                "
    


  • また、他のタイプの SRAM のチェックを行ないたい場合には、上記のスタート促進メッセージが表示されているときに BREAK スイッチ を押下すれば、再び SRAM タイプの選択メッセージの表示に戻ることができる。


機能追加 ( 2018/7/7 更新 )

  • 上写真のようにチェックのスタート促進メッセージが表示されているときに、CONTINUE (→(RIGHT)スイッチと兼用) スイッチを押しながら ENTER スイッチ を押下した場合 には、SELECT 1, 0 スイッチ(SW5: DIP スイッチの内の真中、SW4: 右端)の 指定にかかわらず、4つあるチェックパタンが (1) b'00'、(2) b'01'、(3) b'10'、(4) b'11' の順に、すべてを自動的に実行する。

  • ただし、1つのチェックパタンが終了すると、その1つごとの総合的なチェック結果を表示し、ユーザー確認のために進行はそこで一時停止するので、 次のチェックパタンに移行するためにはユーザーの介入を要する。 すなわち、CONTINUE (→(RIGHT)スイッチ) スイッチ を押下することで次のチェックパタンに移行する。 また、このとき何らかの理由により、次のチェックパタンに移行したくないときには BREAK スイッチ を押下することで、自動実行を中止してスタート促進メッセージの表示に戻ることができる。

  • なお、チェック進行メッセージの表示中には、SELECT 1, 0 スイッチを見ればわかるので、今まではどのチェックパタンを実行しているのか LCD に表示がなかったが、全チェックパタンの自動実行の場合には(通常の動作の場合も含めて)、次の写真のようにその区別を 1 〜 4 の番号で LCD に表示するように改めた。
    		"<xxK,x>  Er:0000"		; xxK 位置に選択された RAM タイプ、,x の位置にチェックパタン番号が入る
    		"A:     W:   R:  "
    


  • ここでまとめておくと、チェックのスタート促進メッセージが表示されているときには、次の3つのキー操作方法がある。
    	ENTER スイッチ					  ..........	通常の動作
    	PAUSE (←(LEFT)) スイッチ + ENTER スイッチ	  ..........	エラー発生時にポーズ動作
    	CONTINUE (→(RIGHT)) スイッチ + ENTER スイッチ ..........	全チェックパタンの自動実行
          

| ページトップ |

■ プログラム ■

実際に RAM をチェックするに当たって、具体的にはどのようなことを行なえばいいのか、実のところ 良くわかっていません。 基本的には、ある番地に書き込んだ内容を一定時間後に読み出してみて、両者の内容が比較一致すれば 問題はない ―― と判断をしました。 200n Sec の基準クロックで動作しているPICで RAM のアクセスタイムがどうの ・・・ と言っても始まりません。 そこでとりあえず次の4つの方法を考えてみました。 高級言語風のプログラムらしきものは、 チェックする方法の考え方の概要を表します。 実際には SELECT_1,0 スイッチの指定でどの方法でも選択できるように、 それぞれのチェックパタンを割り当てています。

(1) sel_sw = b'00' の場合

1つのメモリアドレスに付き、まず h'00' のデータを書き込んで次にすぐ読み出し、両者のデータ内容を比較して一致すれば OK で、 次にデータを h'01' にして同様チェックをし、次々にデータを1ずつインクリメントしながら h'FF' まで繰り返す。 h'00' から h'FF' までの 256 種類の全データパタンが終了したなら、次に、1つインクリメントした次のメモリアドレスについて同様チェックを 行なう。 ・・・ これを 0 番地から MAX 番地までの全アドレスについて行なう、というものです。
		for ADDRESS = 0 to max
			for W_DATA = 0 to 'ff'
				(write)
				(read)
				if R_DATA = W_DATA then
					OK
				else
					NG
				endif
			next
		next
(2) sel_sw = b'01' の場合

1つの同一のデータパタンを、まず 0 番地から MAX 番地までの全アドレスについて一気に書き込みます。次にまた 0 番地に戻って、 その内容を読み出し先に書き込んだ内容と比較して一致すれば OK で、1ずつインクリメントした次々のメモリアドレスについて 同様チェックを行ないます。 MAX 番地までの全アドレスについて比較チェックが済んだなら、次にデータを1つインクリメントして 同様、全アドレスについてチェックを行ないます。このようにデータ内容を h'00' から h'FF' までの 256 種類の全データパタンに ついて繰り返しチェックします。
		for W_DATA = 0 to 'ff'
			for ADDRESS = 0 to max
				(write)
			next
			for ADDRESS = 0 to max
				(read)
				if R_DATA = W_DATA then
					OK
				else
					NG
				endif
			next
		next
(3) sel_sw = b'10' の場合

基本的には (2) のチェック方法と同じですが、書き込むデータ内容が異なっています。(2) ではアドレスのループ内で扱うデータ 内容は一定ですが、この (3) ではアドレスのループ内で扱うデータは常に1ずつインクリメントしています。要するに、隣同士の アドレスでは扱っているデータの内容が1ずつ異なっています。
		for wk = 0 to 'ff'
			W_DATA = wk
			for ADDRESS = 0 to max
				(write)
				W_DATA = W_DATA + 1
			next
			W_DATA = wk
			for ADDRESS = 0 to max
				(read)
				if R_DATA = W_DATA then
					OK
				else
					NG
				endif
				W_DATA = W_DATA + 1
			next
		next
(4) sel_sw = b'11' の場合

(1) と同様に、まず1つのメモリアドレスに着目しながら、 0 番地から MAX 番地までの全アドレスについてチェックを行なって いく方法をとりますが、書き込むデータパタンが異なっています。 (1) のように全データパタンは書き込みません。ある人の 意見を取り入れたものですが、全データパタンを書き込まなくても、 h'01', h'02', h'04', h'08', h'10', h'20', h'40', h'80', h'00' の9つのパタンだけで十分と言うものです。 h'FF', h'55', h'AA' については私が付け加えたものです。
		for ADDRESS = 0 to max
			for W_DATA = '01','02','04','08','10','20','40','80','00','ff','55','aa'
				(write)
				(read)
				if R_DATA = W_DATA then
					OK
				else
					NG
				endif
			next
		next
SRAM タイプの事前整合性チェック(機能追加)

初めはチェックする SRAM が最もメモリ容量の大きなもの、すなわちICピン数が最も多いものと仮定してチェックを行い、書き読みの 結果がNGだった場合には、順次、次のメモリ容量のもの・・・というように仮定するメモリ容量を変更しながら試験をしていきます。 これはICの Vcc ピンが最も外側に配されていることを考慮したもので、不用意に Vcc ピン以外に電源を繋がないようにと 配慮をしたためです。

チェックの内容は、それぞれの SRAM タイプにしたがった最終アドレスに、h'FF' のデータを書き込み、次に同アドレスを読み出して、 その内容が h'00' 以外であれば、とりあえず書き読みができたものとしてループを抜け出し、次にその整合性の判定をします。 すなわち、仮定した SRAM タイプと実際にセットした SRAM タイプが一致していれば整合性はOKとなる訳です。

ただし、最終アドレスだけの単純な方法ではそれぞれのタイプの区別がつきません。そこで一工夫を凝らして区別がつくようにサイズ別に 考慮をしています。(詳細はプログラムリストを参照のこと)
		for Ram = 128K, 64K, 32K, 8K, 2K
			if Ram < Type
				exit for
			endif
			ADDRESS = max
			W_DATA = 'ff'
			(write)
			(read)
			if R_DATA <> '00' then
				if Ram <> 2K
					(A11 bit check)
					select case Ram
						case 128K
							(A16 bit check)
						case 64K
							(A15 bit check)
						case 32K
							(A13 bit check)
						case else
							exit for
					end select
					if R_DATA <> '00' then
						exit for
					endif
				else
					exit for
				endif
			endif
		next
		if Ram >= 2K then
			if Ram = Type
				OK
			else
				NG
			endif
		else
			NG
		endif

重大なプログラムバグを修正 (Ver. 1.05) ( 2018/6/19 更新 )

 先日、本機 S-RAM チェッカーと同種(似ている)の回路図、およびプログラムを作成していて、本機には重大な誤りがある事に気が付きました。

 それは、そもそも本機では当初の設計では PIC の PORTB と SRAM の DATA バス間の接続には、間に PPI 8255A を挟んで専用の入力ポートと出力ポートに分けて制御するつもりでいたのですが、 その制御が面倒になることが予測されたので PPI 8255A の使用は止めて、入出力データをまとめて PIC の PORTB と直結してしまったことが一因で、また、74HC574(データ出力)用と 74HC541(データ入力)用の2個の ICを制御するために、インバータで反転してはいますが同一の信号(PC4)で行っていることに起因しています。

 次のリストは、その重大な誤りがあった部分をプログラムリスト(修正前の rdata_lcd_ram サブルーチン)から抜き出したものに、より分かりやすくするために Flip_Flop_Set マクロ命令を展開した命令群を コメントとして付け加えたものです。 そして、リストの一番右側に記した(データ衝突−1)から(データ衝突−4)の4か所の部分でデータ衝突を起こしています。
	---(修正前リスト)---
				:
	 			:

		movlw	ramOE
		xorlw	h'ff'
		andwf	ram_cont,F	;SRAM /OE だけを 'L' にする
		Flip_Flop_Set	ram_cont,  PC5,2	;bit5: 74HC273(コントロール) CK
		;;	movf	ram_cont,W	;;   ┐
		;;	movwf	SRAM		;;   │
		;;	bsf	CONT,PC5	;; (マクロ展開) 	SRAM が Read モードになる	..... (1)	;;  ┐
		;;	nop			;;   │									;;  │
		;;	bcf	CONT,PC5	;;   ┘									;;  │(データ衝突−1)
															;;  │	
		bsf	CONT,PC4	;74HC541(データ入力) /G1,/G2 有効, 74HC574(データ出力) /OE 無効	..... (2)	;;  ┤
															;;  │
		bcf	STATUS,RP1	;バンク 1									;;  │(データ衝突−2)
		bsf	STATUS,RP0											;;  │
		movlw	b'11111111'											;;  │
		movwf	TRIS_RAM	;RB7-0: 入力 の設定						..... (3)	;;  ┘
	;	bcf	STATUS,RP1	;バンク 0
		bcf	STATUS,RP0

		movf	SRAM,W		;SRAM データの読み出し
		movwf	ram_data_i	;SRAM の 入力データ

	;	bcf	STATUS,RP1	;バンク 1
		bsf	STATUS,RP0
		clrf	TRIS_RAM	;RB7-0: 出力 の設定						..... (4)	;;  ┐
	;	bcf	STATUS,RP1	;バンク 0									;;  │
		bcf	STATUS,RP0											;;  │(データ衝突−3)
															;;  │
		bcf	CONT,PC4	;74HC541(データ入力) /G1,/G2 無効, 74HC574(データ出力) /OE 有効	..... (5)	;;  ┤
															;;  │
		movlw	ramOE												;;  │
		iorwf	ram_cont,F	;SRAM /OE を再び 'H' にする (SRAM を Write モードにする)  			;;  │(データ衝突−4)
		Flip_Flop_Set	ram_cont,  PC5,2	;bit5: 74HC273(コントロール) CK					;;  │
		;;	movf	ram_cont,W	;;   ┐									;;  │
		;;	movwf	SRAM		;;   │									;;  │
		;;	bsf	CONT,PC5	;; (マクロ展開) 	SRAM が Write モードになる	..... (6)	;;  ┘
		;;	nop			;;   │
		;;	bcf	CONT,PC5	;;   ┘

				:
	 			:
 (データ衝突−1)では、命令(1)の実行直後に SRAM が Read モードになるため、その SRAM からの出力データと 74HC574(データ出力)の出力データとが衝突し合います。 その衝突状態は命令(2)が実行されて 74HC574(データ出力)の出力が High Z(impedance) になるまで続きます。

 しかし、命令(2)が実行されると今度は 74HC541(データ入力)の High Z が解かれて、その出力データと PIC の SRAM (PORTB) ポートからの出力データとが(データ衝突−2)を起こします。 その衝突状態は命令(3)が実行されて PIC の SRAM (PORTB) ポートが入力設定されるまで続きます。

 また、(データ衝突−3)では、命令(4)の実行直後に PIC の SRAM (PORTB) ポートが再び出力設定されるため、(データ衝突−2)と同じ状態に戻ってしまいます。 その衝突状態は命令(5)が実行されて 74HC541(データ入力)の出力が High Z になるまで続きます。

 ところが、命令(5)が実行されると今度は 74HC574(データ出力)の High Z が解かれて、その出力データと SRAM からの出力データとが衝突し合って、再び(データ衝突−1)と同じ状態になります。 その衝突状態は命令(6)が実行されて SRAM が Write モードになるまで続きます。

 これらの不具合が発生する関係を概略回路図で表したものが左下の図で、今回その不具合を修正したものが右下の図となっていますが、それには下リストに示すようにプログラムも修正する必要があります。

 両者の回路で大きく異なっている点は 74HC541(データ入力)を制御する信号で、左図では 74HC574(データ出力)用の制御信号 RC4 をインバートした信号で制御をしているのに対して、 右図では独立した制御信号 RC7 をインバートした信号で制御をしています。 これは左図では RC7 がたまたま空きポートになっていたために、右図で使用することができました。

 これによって、74HC574(データ出力)と 74HC541(データ入力)の各 ICを制御するタイミングが連動していたのを、それぞれ独自のタイミングで決めることができるようになり、 左図回路での不具合を回避できるようになりました。  また、これらのデータ衝突は個々には数命令分が実行する間の時間で、ほんの一瞬であるかもしれないですが、1アドレスにつき4回、かつ、全データパタン(h'00' 〜 h'ff')の 256 回起こります。 たとえば、2K バイトの SRAM の場合には 4 x 2,048 x 256 = 2,097,152 回も起こり、何と 128K バイトの SRAM の場合には 4 x 131,072 x 256 = 134,217,728 回も起こることになります。 いや、現実に起こっていたのです。 最悪でした。

 以下に各 ICの真理値表を示しておきます。 (真理値表の内 74HC574、74HC541、74HC273については東芝の、また CXK5864B については SONY の各データシートより抜粋)
    74HC574 74HC541 74HC273 CXK5864B  (8K バイト SRAM の例)
 次の修正後リストは、上述したように回路を右側の概略回路図に示すように修正した上で、リストの該当する不具合部分を修正したものです。 各 ICを制御するタイミングが 修正前リストとはまったく異なっているのが分かると思います。 そして、この修正を行ったことによって、もうデータ衝突が起こるようなことはありません。
	---(修正後リスト)---
				:
	 			:

		bsf	CONT,PC4	;74HC574(データ出力) /OE 無効 (High Z)

		movlw	ramOE
		xorlw	h'ff'
		andwf	ram_cont,F	;SRAM /OE だけを 'L' にする (SRAM を Read モードにする)
		Flip_Flop_Set	ram_cont,  PC5,2	;bit5: 74HC273(コントロール) CK

		bcf	STATUS,RP1	;バンク 1
		bsf	STATUS,RP0
		movlw	b'11111111'
		movwf	TRIS_RAM	;RB7-0: 入力 の設定
	;	bcf	STATUS,RP1	;バンク 0
		bcf	STATUS,RP0

		bsf	CONT,PC7	;74HC541(データ入力) /G1,/G2 有効 (PC7:インバータ出力)
		movf	SRAM,W		;SRAM データの読み出し
		movwf	ram_data_i	;SRAM の 入力データ
		bcf	CONT,PC7	;74HC541(データ入力) /G1,/G2 無効 (High Z)

	;	bcf	STATUS,RP1	;バンク 1
		bsf	STATUS,RP0
		clrf	TRIS_RAM	;RB7-0: 出力 の設定
	;	bcf	STATUS,RP1	;バンク 0
		bcf	STATUS,RP0

		movlw	ramOE
		iorwf	ram_cont,F	;SRAM /OE を再び 'H' にする (SRAM を Write モードにする)
		Flip_Flop_Set	ram_cont,  PC5,2	;bit5: 74HC273(コントロール) CK

		bcf	CONT,PC4	;74HC574(データ出力) /OE 有効

				:
	 			:
 データ衝突というものは ICにとってどの程度のダメージを与えるものなのでしょうか。 もちろん、そのデータ衝突の起こり方などの条件にもよるとは思うのですが。

 電源をオンすると同時にデータ衝突状態となり、電源をオフするまでの長時間にわたってその状態が続くような場合。 本機のように SRAM からデータを読み出すときだけに、しかも、 全体からするとほんの一瞬のみのデータ衝突状態ですが、SRAM の全アドレス全データパタンにわたってその状態を繰り返すような場合。 当然、条件は大きく異なってきます。

 本機でチェックをしたときにダメージを受ける対象となる ICは4個。 PIC16F877A、74HC574(データ出力)、74HC541(データ入力)、それとチェックをする SRAM です。 SRAM についてはその個体のチェックをするときだけで済みますが、他の ICたちは本機を運用する度にダメージを受けることになります。 本機を製作した直後、私が所有している SRAM の全数(約 350個)すべてについてチェックを実施しました。

 このことから、SRAM はともかく、本機内の3個の ICたちが受けたダメージは相当なものであったことと想像されますが、一応現在でも個々の ICとしての正常な動作を維持している(らしい)ので、 結果として ICが破壊されるような大事には至らなかったようです。

 いずれにしても、たとえ一瞬にしろ本機がデータ衝突状態を起こしていたのは事実のことです。 本機を製作してから8年余り(ホームページに公開してから5年)、 その間今までは一度も内容までの見直しなどはしたことがなかったのですが、今回、ひょんなことからこの不具合を発見することになって、作者の私としてはそんな不具合を含んだまま 8年間も放置していた恥ずかしさと、それを遅まきながら修正することができてホッとした安堵感が入り混じった気持ちです。


チェック時間短縮の小改善の試み (Ver. 1.06) ( 2018/6/23 更新 )

 上記したように 重大なプログラムバグを修正 (Ver. 1.05) を実施後に、チェックにかかるその所要時間を測定したところ、LCD を表示させた場合には数秒ですが多く要する ようになってしまいました。 具体的には、代表として 2K バイトと 8K バイトの2個の SRAM について、それぞれ2回ずつ測定をしてみたのが次表に示すような結果(Ver. 1.05: 黄色で示した部分)で、 8年前に測定した結果(Ver. 1.04: 水色で示した部分)とを見比べてみてください。

 (Ver. 1.04)から(Ver. 1.05)に修正した部分は、上記したように rdata_lcd_ram サブルーチン( SRAM から読み出し)内のみで、各命令の並び順は変更をしてありますが、新たに2命令
				:
	 			:
		bsf	CONT,PC7	;74HC541(データ入力) /G1,/G2 有効 (PC7:インバータ出力)
				:
	 			:
		bcf	CONT,PC7	;74HC541(データ入力) /G1,/G2 無効 (High Z)
				:
	 			:
を追加しただけで、他に命令の増減はありません。

 本機では 20MHz のセラロックを使用のため基準クロックは ( 1 / 20MHz ) x 4 = 0.2μS となります。 したがって、この2命令が全体の所要時間に影響をもたらすのは、SRAM の種類別、およびチェック方法別で 考察をしてみると、
	2K バイト SRAM では、チェック方法 (1) b'00'、(2) b'01'、(3) b'10' ..... 0.2μS x 2,048(アドレス)x 256(データ)x 2(命令)= 209,715.2μS = 0.2097152 秒 ≒ 0.21 秒
	                     チェック方法 (4) b'11'                       ..... 0.2μS x 2,048(アドレス)x  12(データ)x 2(命令)=   9,830.4μS = 0.0098304 秒 ≒ 0.01 秒

	8K バイト SRAM では、チェック方法 (1) b'00'、(2) b'01'、(3) b'10' ..... 0.2μS x 8,192(アドレス)x 256(データ)x 2(命令)= 838,860.8μS = 0.8388608 秒 ≒ 0.84 秒
	                     チェック方法 (4) b'11'                       ..... 0.2μS x 8,192(アドレス)x  12(データ)x 2(命令)=  39,321.6μS = 0.0393216 秒 ≒ 0.04 秒
となり、これらの値がそれぞれ(Ver. 1.04)の所要時間にプラスされることになります。 次表の(Ver. 1.04)と(Ver. 1.05)の実測値を比べてみると、LCD を非表示にした場合で チェック方法が (1) b'00'、(2) b'01'、(3) b'10' の場合には、ぴたっと計算値通りになっているのが分かります。

 しかし、LCD を非表示にした場合でチェック方法 (4) b'11' の場合の実測値では、2K バイト SRAM で 0.14 秒、8K バイト SRAM で 0.45 秒の差となっており、計算値よりも 10倍以上の値で、 この点についてはどうも納得がいかない* ところです。 ( 2018/7/3 追記  * については、後述 を参照 )
      サイズ 型名 メーカー 外形   バージョン 実施日 (1) b'00' (2) b'01' (3) b'10' (4) b'11'
      LCD 非 LCD 表示 LCD 非 LCD 表示 LCD 非 LCD 表示 LCD 非 LCD 表示
      2K バイト HM6116LP-3 日立 DIP-24P   (Ver.1.04) 2010/07/25 00' 09''02 02' 11''28 00' 18''74 05' 44''09 00' 19''16 05' 47''75 00' 00''79 00' 05''72
        (Ver.1.05) 2018/06/21 00' 09''23 02' 12''18 00' 18''95 05' 46''75 00' 19''37 05' 49''28 00' 00''93 00' 07''29
        2018/06/21 00' 09''23 02' 12''18 00' 18''95 05' 46''81 00' 19''37 05' 49''27 00' 00''93 00' 07''29
        (Ver.1.06) 2018/06/21 00' 08''91 02' 12''18 00' 18''64 05' 50''34 00' 19''05 05' 48''29 00' 00''91 00' 07''37
        2018/06/21 00' 08''91 02' 12''18 00' 18''64 05' 50''47 00' 19''05 05' 48''32 00' 00''91 00' 07''36
      8K バイト CXK5864BSP-10L ソニー DIP-28PS   (Ver.1.04) 2010/07/25 00' 35''68 08' 43''64 01' 17''08 23' 09''42 01' 18''76 23' 22''38 00' 01''97 00' 21''45
      CXK5864BSP-70L   (Ver.1.05) 2018/06/21 00' 36''52 08' 47''44 01' 17''92 23' 15''39 01' 19''59 23' 28''78 00' 02''52 00' 27''61
        2018/06/21 00' 36''52 08' 47''43 01' 17''92 23' 16''07 01' 19''59 23' 29''25 00' 02''52 00' 27''61
        (Ver.1.06) 2018/06/21 00' 34''01 08' 47''29 01' 15''41 23' 08''65 01' 17''08 23' 19''18 00' 02''40 00' 28''20
        2018/06/21 00' 34''01 08' 47''30 01' 15''41 23' 08''56 01' 17''08 23' 19''26 00' 02''40 00' 28''20
また、LCD に表示した場合には、すべてのチェック方法で数秒のオーダーでの増加となっています。 確かに PIC と LCD とのインターフェースでは、 通信速度が一定ではなく PIC が LCD に待たされる部分がある(LCD からのビジーフラグをチェックしている(lcd_busy サブルーチン))ので、ある程度は納得ができます。
			; LCD へコマンドを出力
	lcd_cmd
			bcf	LCD,_RS		;RS = 0  (コマンドモードに設定)
			goto	lcd01

			; LCD へデータを出力
	lcd_data
			bsf	LCD,_RS		;RS = 1  (データモードに設定)
			nop

	lcd01		bcf	LCD,_RW		;R/W = 0 (書き込みモードに設定)
			call	lcd_out		;上位4ビットを転送

			swapf	lcdtmp,W	;一時保存データの上位下位入れ替え
			call	lcd_out		;下位4ビットを転送

			call	lcd_busy	;LCD ビジーチェック					;; LCD ビジーチェック
			return

			; 4ビット一回の送出
	lcd_out
			movwf	lcdtmp		;コマンド/データを一時保存
			movlw	h'0f'		;下位4ビットの
			andwf	LCD,F		;コントロールポートの内容を残し
			movlw	h'f0'		;上位4ビットデータ
			andwf	lcdtmp,W	;を取り出して
			iorwf	LCD,F		;コントロールとOR

			bsf	LCD,_E		;E = 1   (動作起動信号の設定:Hでストローブ)
			nop			;E のパルス幅を220ns以上確保するため
			bcf	LCD,_E		;E = 0   (動作起動信号の設定:Lに戻す)
			return
	
			; LCD ビジーチェック
	lcd_busy
			bsf	STATUS,RP0	;バンク 1
			movlw	b'11110000'	;上位4ビットを入力ポート
			iorwf	TRIS_LCD,F
			bcf	STATUS,RP0	;バンク 0
			bcf	LCD,_RS		;RS = 0  (コマンドモードに設定)
			nop
			bsf	LCD,_RW		;R/W = 1 (読み出しモードに設定)

	lcd_busy01	bsf	LCD,_E		;E = 1   (動作起動信号の設定:Hでストローブ)		;; ─┐
			movf	LCD,W		;DDRAM からのデータ(上位4ビット)の読み出し		;;  │
			bcf	LCD,_E		;E = 0   (動作起動信号の設定:Lに戻す)			;;  │
	;		andlw	h'f0'		;上位4ビット						;   │
			movwf	lcdtmp		;読み出しデータを一時保存				;;  │
	;		swapf	lcdtmp,F	;下位4ビットに移動					;   │
													; この部分が何度も繰り返される
			bsf	LCD,_E		;E = 1   (動作起動信号の設定:Hでストローブ)		;;(ビジーフラグ _BF = 0 
			movf	LCD,W		;DDRAM からのデータ(下位4ビット)の読み出し		;; になるまでループする)
			bcf	LCD,_E		;E = 0   (動作起動信号の設定:Lに戻す)			;;  │
	;		andlw	h'f0'		;上位4ビット						;   │
	;		iorwf	lcdtmp,F	;上位4ビット + 下位4ビット				;   │
	;		swapf	lcdtmp,F	;上位4ビットと下位4ビットを入れ替え			;   │
			btfsc	lcdtmp,_BF	;ビジーフラグのチェック (読み出しデータの7ビット目)	;;  │
			goto	lcd_busy01	;_BF=0 になるまでループ					;; ─┘

			bcf	LCD,_RW		;R/W = 0  (書き込みモードに設定)
			bsf	STATUS,RP0	;バンク 1
			movlw	b'11110000'	;上位4ビットを出力ポートに戻す
			xorwf	TRIS_LCD,F
			bcf	STATUS,RP0	;バンク 0
			return
 なお、所要時間の測定には、(Ver. 1.04)のときに使用した "長時間ストップウオッチ/タイマー" と同じものですが、1年ちょっと前にプログラム変更を 行ってはいますが、ストップウオッチに使用している LCD 表示の内、秒と秒以下( 1 / 100 秒 )の区切り記号の ":(コロン)" を ".(ピリオド)" に変更しただけで他の変更はありません。  そのような訳で、(Ver. 1.05)になって余分に費やしてしまう時間を、何とか取り戻すことができないものかと試みたのが、次に示す(Ver. 1.06)のリストで、 全アドレスにわたって 必ず実行されるのが、次の wdata_lcd_ram サブルーチン(SRAM への書き込み)と rdata_lcd_ram サブルーチン(SRAM から読み出し)です。

 wdata_lcd_ram サブルーチン内では、(Ver. 1.05)で5命令だったのを(Ver. 1.06)では2命令にして計マイナス3命令、ただし、2K バイトの SRAM だけはこのルーチンを通らないのでプラスマイナス零です。 また、rdata_lcd_ram サブルーチン内では、すべての SRAM の種類において5命令だったのを2命令にして計マイナス3命令となり、したがって、両者を合わせると全体では 2K バイト SRAM ではマイナス3命令、 それ以外の SRAM ではマイナス6命令となります。

 この命令数を減らしたことによる全体の所要時間に影響をもたらす効果を、上記の場合と同様に SRAM の種類別、およびチェック方法別で考察をしてみると、
	2K バイト SRAM では、チェック方法 (1) b'00'、(2) b'01'、(3) b'10' ..... 0.2μS x 2,048(アドレス)x 256(データ)x -3(命令)=   -314,572.8μS = -0.3145728 秒 ≒ -0.31 秒
	                     チェック方法 (4) b'11'                       ..... 0.2μS x 2,048(アドレス)x  12(データ)x -3(命令)=    -14,745.6μS = -0.0147456 秒 ≒ -0.01 秒

	8K バイト SRAM では、チェック方法 (1) b'00'、(2) b'01'、(3) b'10' ..... 0.2μS x 8,192(アドレス)x 256(データ)x -6(命令)= -2,516,582.4μS = -2.5165824 秒 ≒ -2.52 秒
	                     チェック方法 (4) b'11'                       ..... 0.2μS x 8,192(アドレス)x  12(データ)x -6(命令)=   -117,964.8μS = -0.1179648 秒 ≒ -0.12 秒
となります。 この計算値を上表の LCD を非表示にした場合の(Ver. 1.05: 黄色で示した部分)と(Ver. 1.06: 緑色で示した部分)の実測値の差と比べてみると、 すべてのチェック方法において見事に一致しますので、上式で示すだけの効果が現れていることが分かります。
					:
		 			:
	ramOEb		equ	1		;SRAM /OE: アウトプットイネーブルのビット位置		;;(Ver.1.06 で追加)
	ramWEb		equ	2		;SRAM /WE: ライトイネーブルのビット位置			;;
	ramOE		equ	h'02'		;SRAM /OE: アウトプットイネーブル
	ramWE		equ	h'04'		;SRAM /WE: ライトイネーブル
					:
		 			:

	wdata_lcd_ram				; SRAM 書き込み
					:
		 			:
	wdata02	;;	movlw	ramWE									;;(Ver.1.06 で変更)
		;;	xorlw	h'ff'									;;
		;;	andwf	ram_cont,F	;SRAM /WE だけを 'L' にする				;;
			bcf	ram_cont,ramWEb								;;
					:
		 			:
		;;	movlw	ramWE									;;(Ver.1.06 で変更)
		;;	iorwf	ram_cont,F	;SRAM /WE を再び 'H' にする				;;
			bsf	ram_cont,ramWEb								;;
					:
		 			:

	rdata_lcd_ram				; SRAM 読み出し
					:
		 			:
		;;	movlw	ramOE									;;(Ver.1.06 で変更)
		;;	xorlw	h'ff'									;;
		;;	andwf	ram_cont,F	;SRAM /OE だけを 'L' にする (SRAM を Read モードにする)	;;
			bcf	ram_cont,ramOEb								;;
					:
		 			:
		;;	movlw	ramOE									;;(Ver.1.06 で変更)
		;;	iorwf	ram_cont,F	;SRAM /OE を再び 'H' にする (SRAM を Write モードにする);;
			bsf	ram_cont,ramOEb								;;
					:
		 			:
 なお、依然として納得がいかない点は、上記でも述べたように LCD を非表示にした場合でチェック方法が (4) b'11' のときの実測値が、(Ver. 1.04)と(Ver. 1.05)では 計算値のようにはならず 10倍以上の値を示していることです。 計算値では rdata_lcd_ram サブルーチン(SRAM から読み出し)の命令数の増加だけで計算をしていますが、 その他にも私の考慮不足な要素* が実際にはあるのでしょうか。 ( * これについては、次の追記を参照 )

( 2018/7/3 追記 )

 原因が分かりました。 バックアップをしてある(Ver. 1.04)と(Ver. 1.05)以降の各ソースファイルの、チェック方法が (4) b'11' のときの該当する部分を見比べてみると、
	---(Ver. 1.04)---

		;;;;;;; チェックパタン '11' の場合

	ptn_tbl		dt	h'01',h'02',h'04',h'08',h'10',h'20',h'40',h'80'
			dt	h'00',h'ff',h'55',h'aa'
					:
		 			:
	chk15		call	tbl_read	;テーブルデータの読み出し
					:
		 			:
			movf	ram_data_o,F						;;相違部分
			btfss	STATUS,Z	;SRAM の 出力データ = '00' か?
			goto	chk15		;No
					:
		 			:

	---(Ver. 1.05),(Ver. 1.06)---

		;;;;;;; チェックパタン '11' の場合

	ptn_tbl		dt	h'01',h'02',h'04',h'08',h'10',h'20',h'40',h'80'
			dt	h'00',h'ff',h'55',h'aa'
					:
		 			:
	chk15		call	tbl_read	;テーブルデータの読み出し
					:
		 			:
			movlw	h'aa'							;;相違部分
			subwf	ram_data_o,W						;;
			btfss	STATUS,Z	;SRAM の 出力データ = 終了'aa' か?
			goto	chk15		;No
					:
		 			:
と両者では異なっていました。 書き込みデータの定義としてはどちらも同じで 12 個並んでいますが、その読み出しを(Ver. 1.04)では h'00' で打ち切ってしまって、残りの h'ff'、h'55'、h'aa' についてはチェックを行っていません。 それに対して(Ver. 1.05)以降ではすべてのチェックを行っていて、この3個のデータ数の違いが両者でのチェックに要する時間の差となって表れているのです。

 勿論、(Ver. 1.05)以降のリストの方が意図することを行っていて正しいのですが、これは(Ver. 1.04)から8年経った今回のプログラム修正で直したものではありません。 上の(Ver. 1.04)のファイルは 私のPCのバックアップ用ホルダにあったもので、(Ver. 1.05)および(Ver. 1.06)に更新した最新用のホルダにあった元ファイルとは異なっています。

 どうやら、(Ver. 1.04)でも2種類のファイルがあったようで、既に8年前に上リストのようにテーブルデータの読み出しの終了判断する部分を修正したのに、そのバージョン番号を 更新していなかったようです。 そして、8年前の前回のチェックでは、そのように修正する前のプログラムでチェックの実施をしてしまったようです。 というよりも、チェックの実施後にその間違いに気が付いて プログラムリストの修正だけを行っていたようです。


全チェックパタン自動実行の機能追加 (Ver. 1.07) ( 2018/7/7 更新 )

 データ衝突という重大なプログラムバグを修正( (Ver.1.05)、(Ver.1.06) )したのを機に、現在、私が所有している SRAM の全数のチェックを、もう一度やり直してみたのですが、400 個以上ある SRAM 1個1個に対して (1)〜(4) のすべてのチェック方法を実施するために、SELECT 1, 0 スイッチ( DIP スイッチ)で切り替え指定をするだけでも大変な作業でした。

 そこで、すべてのチェック方法を実施する場合には、DIP スイッチを操作することなくタクトスイッチの簡単な操作だけで、すべてのチェック方法を自動的に実施できる機能を追加しました。 具体的には、チェックのスタート促進メッセージが表示されているときに、CONTINUE (→(RIGHT)スイッチと兼用) スイッチを押しながら ENTER スイッチ を押すだけでその機能を実現できます。 (詳細は、機能概要と使用法 の項の 機能追加 と、次のプログラムのソースファイルを参照してください。)


現在の最新バージョン: Ver. 1.07

| ページトップ |

■ S-RAM サイズ別ピンアサイン ■

今回チェックの対象としたスタティック RAM の、サイズ別のピンアサインを次に示します。 これは上記 回路図 の該当部分を拡大して再掲したものです。

ピン端子の信号名
A0-A16: (Address Inputs) アドレス入力
D0-D7: (Data Inputs/Outputs) データ入出力
CS,CS1,CS2: (Chip Select Inputs) チップセレクト入力
WE: (Write Enable Input) リードライト制御入力
OE: (Output Enable Input) アウトプットイネーブル入力
Vcc: (Power Supply) 電源
Vss: (Ground) グランド
NC: (No Connection) 空端子

| ページトップ |

■ プリント基板パターン図 (部品面) ■

 中央右に位置するゼロプレッシャーソケットですが、右写真では ARIES社の 28P が写っています。 これは今手持ちには 28P のものしか ないためで、本来は 64K バイト以上の RAMに対応するためには、32P のものが必要です。 ところが、秋月電子通商では 32P のものを扱っていません。

 言い遅れましたが、左のパターン図に示すように、プリント基板上には 32P の通常の丸ピンソケットがハンダ付けしてあります。 その上に ARIES社の 32P のゼロプレッシャーソケットを積んで使用するつもりでした。 実は TEXTOOL社の 32P の製品なら手持ちがあるのですが、足ピンの形状が幅広のため この丸ピンソケットに嵌りません。

 本機を作製当時は、ARIES社の 32P のゼロプレッシャーソケットが、すぐ入手できるものと思っていたためで失敗でした。 初めから TEXTOOL社の 32P の製品を、 直接プリント基板にハンダ付けをして使用すればよかった、と思います。

 ( 2016/1/26 追加 )

 プリント基板をケースに収納することによって、基板の上部に取り付けてあった "長時間ストップウオッチ/タイマー" に接続するための、BUSY 信号端子と電源端子がL型端子のため、共に使用できなくなってしまいました。 そこで下パターン図に示すように、 LCDの下の僅かな空きスペースにもう1組の垂直端子を取り付けました。

 なお、右の2枚の写真は変更前のもので差し替えを行っていないため、その改造が反映されていないので注意を願います。(下のハンダ面の写真も同)  ( 2018/6/23 差し替え済み )

| プリント基板パターン図 (部品面) (StaticRamCheckerPC.CE3) | ページトップ |

■ プリント基板パターン図 (ハンダ面) ■

| プリント基板パターン図 (ハンダ面) (StaticRamCheckerPC1.CE3) | ページトップ |

■ ケース加工図 ■

 使用したケースは、"フリーケース A5 L8998 (サナダ精工株式会社)" というもので、サイズ:幅241 x 奥行167 x 高さ39 mm、材質:ポリプロピレン です。

| ケース加工図 (StaticRamCheckerCS.CE3) | ページトップ |

■ チェック結果 ■

その昔、正規(?)に販売店で購入したものが数十個と、最近 Yahoo!オークションで落札し、いつの間にか溜まった SRAM メモリの数が、合わせて約300個。これら全数(SOP を除く)について今回 ( 2010/07 )、本装置でメモリチェックを行なってみました。

下の表がその結果です。 (1)〜(4) が上記 プログラム の項で説明したチェック方法で、各方法とも左欄は 液晶(LCD)に表示するのをパスしたときで、右欄は進行状況を液晶(LCD)に表示したときのチェック所要時間を表しています。

表中左欄 すなわち液晶(LCD)に表示するのをパスした方法については、今回メモリIC全数について (1)〜(4) のすべてを実施しました。 右欄の進行状況を液晶(LCD)に表示した方法については、それぞれの型名の中で代表的に1固体についてのみの実施です。

これらを見ると明かに大きな時間差が出ており、右欄では本来のチェック時間よりも、その殆どが液晶(LCD)の表示に費やしている ことが分かります。また、どの方法においても左欄の本来のチェック所要時間では、同固体を数回チェックしてみましたがバラつきは まず見られませんでしたが、右欄の進行状況を液晶(LCD)に表示したときには、その所要時間にはかなりのバラつきがありました。

しかも、32K バイトサイズの SRAM の測定時で数十秒台のバラつきがありましたので、これらの表中には一応秒以下の値まで書き入れてはありますが、 その絶対値にはあまり意味がありません。したがって、右欄の測定値の十秒台以下はあくまでも参考程度です。

また、方法 (4) ではさすがにその所要時間が短くて、容量の大きな SRAM でもあまり気にはなりませんが、その他の方法では 容量が大きくなるにつれて、進行状況を液晶(LCD)に表示したときには、デモンストレーションとしてはいいけれど実用的ではありません。 せいぜい2Kバイトまでがいいところでしょう。

なお、これらの時間測定には今回専用に開発した、"長時間ストップウオッチ/タイマー" を使用しました。

サイズ 型名 メーカー 外形 個数   実施日 (1) b'00' (2) b'01' (3) b'10' (4) b'11' OK数 NG数
2K バイト CXK5816PN-15L ソニー DIP-24P 36   2010/07/21 09''02 02' 11''30 18''74 05' 44''66 19''16 05' 47''45 00''79 05''71 36 0
HM6116LP-3 日立 DIP-24P 13   2010/07/25 09''02 02' 11''19 18''74 05' 44''04 19''16 05' 47''80 00''79 05''72 13 0
HM6116P-3 日立 DIP-24P 6   2010/07/22 09''02 02' 11''28 18''74 05' 44''09 19''16 05' 47''75 00''79 05''72 6 0
LC3517BL-12 三洋 DIP-24P 43   2010/07/22 09''02 02' 11''17 18''74 05' 44''18 19''16 05' 48''00 00''79 05''74 43 0
M58725P 三菱 DIP-24P 25   2010/07/21 09''02 02' 11''25 18''74 05' 44''42 19''16 05' 47''54 00''79 05''70 25 0
TMM2016P-2 東芝 DIP-24P 13   2010/07/26 09''02 02' 11''32 18''74 05' 45''21 19''16 05' 47''53 00''79 05''68 9 4
( 合計 )   136     132 4
8K バイト CXK5864BSP-10L ソニー DIP-28PS 10   2010/07/25 35''68 08' 43''64 01' 17''08 23' 09''42 01' 18''76 23' 22''38 01''97 21''45 10 0
HM6264ALSP-10 日立 DIP-28PS 12   2010/07/21 35''68 08' 43''42 01' 17''08 23' 09''22 01' 18''76 23' 22''27 01''97 21''34 12 0
HM6264ALSP-12 日立 DIP-28PS 20   2010/07/22 35''68 08' 43''54 01' 17''08 23' 10''47 01' 18''76 23' 22''91 01''97 21''41 20 0
HM6264AP-10 日立 DIP-28P 7   2010/07/21 35''68 08' 43''48 01' 17''08 23' 11''58 01' 18''76 23' 22''86 01''97 21''38 7 0
HM6264LP-15 日立 DIP-28P 2   2010/07/22 35''68 08' 43''66 01' 17''08 23' 09''95 01' 18''76 23' 23''08 01''97 21''44 2 0
HM6264P-15 日立 DIP-28P 4   2010/07/22 35''68 08' 43''62 01' 17''08 23' 10''95 01' 18''76 23' 23''39 01''97 21''50 4 0
IS61C64AH-15N ICSI DIP-28PS 15   2010/07/27 35''68 08' 44''06 01' 17''08 23' 07''07 01' 20''29 23' 22''59 01''97 21''56 0 15
LC3664ASL-10 三洋 DIP-28PS 22   2010/07/25 35''68 08' 43''58 01' 17''08 23' 09''91 01' 18''76 23' 22''40 01''97 21''46 22 0
( 合計 )   92     77 15
32K バイト CXK58257ASP-10L ソニー DIP-28PS 10   2010/07/25 02' 21''50 34' 52''80 05' 07''09 01゚ 32' 34''09 05' 13''80 01゚ 33' 30''29 06''65 01' 24''60 10 0
TC55257BPL-10 東芝 DIP-28P 21   2010/07/23 02' 21''50 34' 53''87 05' 07''09 01゚ 32' 33''26 05' 13''79 01゚ 33' 26''58 06''65 01' 24''53 21 0
TC55257BSPL-85L 東芝 DIP-28PS 6   2010/07/22 02' 21''50 34' 53''94 05' 07''08 01゚ 32' 43''66 05' 13''78 01゚ 33' 28''86 06''65 01' 24''59 6 0
W24257AK-15 WINBOND DIP-28PS 4   2010/07/24 02' 21''50 34' 53''95 05' 07''10 01゚ 32' 38''57 05' 13''80 01゚ 33' 30''72 06''65 01' 25''17 2 2
μPD43256AC-10L NEC DIP-28P 13   2010/07/23 02' 21''49 34' 55''45 05' 07''10 01゚ 32' 18''07 05' 13''80 01゚ 32' 57''64 06''65 01' 25''58 13 0
( 合計 )   54     52 2
64K バイト W24512AK-15 WINBOND DIP-32PS 4   2010/07/26 04' 42''58 01゚ 09' 46''74 10' 13''77 03゚ 04' 49''26 10' 27''18 03゚ 06' 46''43 12''90 02' 49''09 4 0
128K バイト μPD431000ACZ-10L NEC DIP-32P 7   2010/07/27 09' 24''83 02゚ 19' 44''63 21' 07''37 07゚ 36' 05''61 21' 34''15 07゚ 38' 00''91 25''46 05' 48''19 7 0
                                 
( 総合計 )   293     272 21

上表の結果についてですが、NG数欄が "0" 以外のエラーが起こったものでは、いずれにも共通点がありました。

それは4つのチェック方法の内、表からは分かりませんが、どれもが (3) の方法のときにエラーが起こっている、ということです。 メモリIC全数について (1)〜(4) のすべてを実施して、(3) 以外の (1) (2) (4) の方法では何ら問題がなかったのに、(3) の方法に限って エラーが起こった、というものです。

しかし、今回 293 個のメモリICをチェックしてみて、その殆どの 272 個のメモリICがOKだったことから、(3) のチェック方法に 問題がある、とは考えられません。

( 2010/9/26 追加 )

また、たくさんの SRAM を入手しました。 2K バイトにしては型名が少々変だと思って調べてみると、オリジナルはどうも INTEL のようで、MILITARY 仕様になっています。

当初、60 個中 3 個エラーになりましたが、全数チェック後に改めてチェックし直すと、何ら問題はありませんでした。 どうやら接触不良のようでした。

サイズ 型名 メーカー 外形 個数   実施日 (1) b'00' (2) b'01' (3) b'10' (4) b'11' OK数 NG数
2K バイト M2128-15 DIP-24P 60   2010/09/25 09''02 02' 11''30 18''74 05' 44''26 19''16 05' 47''58 00''79 05''69 60 0

( 2018/7/3 追加更新 )

データ衝突という重大なプログラムバグを修正( (Ver.1.05)、(Ver.1.06) )したのを機に、また、前回(8年前)のチェック時以降に新たに入手をした SRAM を含めて、 現在、私が所有している SRAM の全数のチェックを、もう一度やり直してみました。

試験方法は前回と同様に行い、表中の各結果の左欄、すなわち液晶(LCD)に表示するのをパスした方法については、今回もメモリIC全数について (1)〜(4) のすべてを実施しました。 右欄の進行状況を液晶(LCD)に表示した方法については、それぞれの型名の中で代表的に1固体についてのみの実施です。

サイズ 型名 メーカー 外形 個数   実施日 (1) b'00' (2) b'01' (3) b'10' (4) b'11' OK数 NG数 不明
LCD 非 LCD 表示 LCD 非 LCD 表示 LCD 非 LCD 表示 LCD 非 LCD 表示
2K バイト CXK5816PN-15L ソニー DIP-24P 36 2018/06/23 08''91 02' 12''20 18''64 05' 50''84 19''05 05' 48''99 00''91 07''36 36 0 -
HM6116LP-3 日立 DIP-24P 13 2018/06/23 08''91 02' 12''28 18''64 05' 51''14 19''05 05' 50''43 00''91 07''36 13 0 -
HM6116P-3 日立 DIP-24P 6 行方不明中                 - - 6
LC3517BL-12 三洋 DIP-24P 43 2018/06/24 08''91 02' 12''13 18''64 05' 49''46 19''05 05' 51''70 00''91 07''27 43 0 -
M2128-15 DIP-24P 60 2018/06/24 08''91 02' 12''98 18''63 05' 52''01 19''05 05' 50''75 00''91 07''37 60 0 -
M58725P 三菱 DIP-24P 25 2018/06/24 08''91 02' 12''37 18''63 05' 50''18 19''05 05' 52''34 00''91 07''30 25 0 -
TMM2016P 東芝 DIP-24P 8 2018/06/28 08''91 02' 12''27 18''64 05' 50''34 19''05 05' 51''74 00''91 07''35 2 6 -
TMM2016P-2 東芝 DIP-24P 4 2018/06/28 08''91 02' 12''27 18''64 05' 50''34 19''05 05' 51''74 00''91 07''35 0 4 -
1 行方不明中                 - - 1
( 小計 )   196   179 10 7
8K バイト CXK5864BSP-10L ソニー DIP-28PS 10 2018/06/24 34''01 08' 47''77 01' 15''41 23' 12''79 01' 17''08 23' 17''34 02''40 27''98 10 0 -
CXK5864BSP-70L ソニー DIP-28PS 10 2018/06/25 34''00 08' 47''71 01' 15''40 23' 11''92 01' 17''08 23' 17''59 02''40 27''92 10 0 -
HM6264ALSP-10 日立 DIP-28PS 12 2018/06/25 34''00 08' 47''78 01' 15''40 23' 11''74 01' 17''08 23' 17''60 02''40 27''97 12 0 -
HM6264ALSP-12 日立 DIP-28PS 20 2018/06/25 34''00 08' 47''88 01' 15''40 23' 11''54 01' 17''08 23' 18''29 02''40 27''86 20 0 -
HM6264AP-10 日立 DIP-28P 7 2018/06/28 34''00 08' 47''39 01' 15''40 23' 10''35 01' 17''08 23' 16''97 02''40 28''11 7 0 -
HM6264LP-15 日立 DIP-28P 2 行方不明中                 - - 2
HM6264P-15 日立 DIP-28P 4 行方不明中                 - - 4
IS61C64AH-15N ICSI DIP-28PS 59 2018/06/30 -- -- -- -- -- -- -- -- 0 59 -
LC3664ASL-10 三洋 DIP-28PS 22 2018/06/25 34''01 08' 47''93 01' 15''40 23' 12''00 01' 17''08 23' 17''60 02''40 28''05 22 0 -
LH5160-10L シャープ DIP-28P 18 2018/06/29 34''00 08' 47''54 01' 15''40 23' 08''76 01' 17''08 23' 17''21 02''40 28''12 18 0 -
LH5164A-10L シャープ DIP-28P 2 2018/06/29 34''00 08' 47''65 01' 15''40 23' 11''76 01' 17''08 23' 17''75 02''40 28''12 2 0 -
( 小計 )   166   101 59 6
32K バイト CXK58257AP-10L ソニー DIP-28P 10 2018/06/23 02' 14''80 35' 08''46 05' 00''39 01゚ 32' 33''85 05' 07''09 01゚ 33' 15''63 08''38 01' 51''57 10 0 -
CXK58257ASP-10L ソニー DIP-28PS 10 2018/06/24 02' 14''79 35' 10''46 05' 00''39 01゚ 32' 49''26 05' 07''09 01゚ 33' 06''36 08''38 01' 50''37 10 0 -
HM62256BLP-7 日立 DIP-28P 6 2018/06/26 02' 14''79 35' 09''72 05' 00''37 01゚ 33' 10''05 05' 07''07 01゚ 33' 09''93 08''38 01' 50''38 6 0 -
TC55257BPL-10 東芝 DIP-28P 21 2018/06/26 02' 14''79 35' 10''58 05' 00''37 01゚ 32' 45''98 05' 07''07 01゚ 33' 11''05 08''38 01' 51''26 21 0 -
TC55257BSPL-85L 東芝 DIP-28PS 6 2018/06/27 02' 14''79 35' 09''48 05' 00''38 01゚ 32' 32''53 05' 07''08 01゚ 33' 10''36 08''38 01' 51''01 6 0 -
W24257AK-15 WINBOND DIP-28PS 4 2018/06/28 02' 14''79 35' 09''60 05' 00''37 01゚ 32' 45''91 05' 07''07 01゚ 33' 10''16 08''38 01' 51''03 4 0 -
μPD43256AC-10L NEC DIP-28P 13 2018/06/27 02' 14''79 35' 09''20 05' 00''38 01゚ 32' 34''38 05' 07''08 01゚ 33' 08''18 08''38 01' 51''19 13 0 -
( 小計 )   70   70 0 0
64K バイト W24512AK-15 WINBOND DIP-32PS 4 2018/06/29 04' 29''17 01゚ 10' 20''18 10' 00''36 03゚ 05' 52''39 10' 13''76 03゚ 06' 18''33 16''35 03' 40''48 4 0 -
( 小計 )   4   4 0 0
128K バイト TC551001CP-70L 東芝 DIP-32P 5 2018/06/28 08' 58''00 02゚ 20' 41''58 20' 40''48 07゚ 36' 15''31 21' 07''33 07゚ 38' 51''15 32''38 07' 35''09 5 0 -
μPD431000ACZ-10L NEC DIP-32P 6 2018/06/30 08' 58''02 02゚ 20' 44''43 20' 40''49 07゚ 36' 22''56 21' 07''31 07゚ 38' 54''89 32''38 07' 33''50 6 0 -
1 行方不明中                 - - 1
( 小計 )   12   11 0 1
( 総合計 )   448     365 69 14

上表が今回のチェック状況の一覧ですが、表を見て、まず目立つのが前回に比べて全体的に SRAM の数量が増えている点と、実施日欄に "行方不明中" と記されたものがある点で、 この "行方不明中" というのは、前回の表にはチェック対象としてその結果があったものですが、今回はその存在を見つけられずチェックをすることができなかったものです。

チェック結果がNGになったものの中で、まず、サイズが 2K バイトの TMM2016P と TMM2016P-2 ですが、前回では両者をまとめて 13 個中 4 個がNGとなっていたもので、今回のチェックでは 1個の "行方不明中" を除いて、両者を合わせると 12 個中 10 個がNGとなってしまいました。 これは確実に ICの劣化が進んでいるということだと思われます。

このメモリICは、私にとっては特別な思い入れがあるもので、30 数年も以前に "秋月電子" で 12 個購入したもので、当時価格として1個 1,750 円であったと記録に残っています。

私の他のページ "8080A CPU コンピュータシステム" で紹介しているものとは違う、セカンド・システム用にと購入をしたもので、プリント基板のソケットに実装 された形で現在に至っていますが、未だそのセカンド・システムは未完成の状態のために本来での通電はしたことがなく、前回のメモリチェックで初めて通電をしたもの(今回が2度目)です。

この ICの劣化とは逆に、32K バイトの W24257AK-15 については、前回のチェックでは 4 個中 2個がNGとなっていたものが、今回のチェックではすべてがOKでNGのものはありませんでした。 不良だったものが8年経って良くなるということは到底考えられませんので、これは、前回のチェックでは ICピンが接触不良を起こしていたのではないかと思います。

この接触不良を起こす― ということはよくあることで、今回も 400 個以上のメモリICを扱っていると、ときどきそんな現象を経験します。 そんなときにはゼロプレッシャーソケットへの着脱を 数回繰り返すことによって大抵の場合には正常に戻ります。 それでもダメな場合には ICピンの目視チェックもした上でメモリICの不良と判断をしています。

サイズが 8K バイトの IS61C64AH-15N については、前回のチェックでも 15 個すべてがNGでしたが、今回は 59 個がチェック対象で、何と、やはりすべてがNGという結果となりました。 もちろん ICピンの接触不良などではなく、間違いなくエラー症状を起こします。 このメモリICは、他のものと違ってアクセスタイムが 15 nS と極端に高速で特別な存在です。 その影響があるのかどうかは分かりませんが、本機でのチェック方法ではだめなのかもしれません。

結局、今回のチェックでは "行方不明中" のもの 14 個を除いて 434 個がチェック対象でしたが、その内、 10 個の TMM2016P(TMM2016P-2 を含む)と 59 個の IS61C64AH-15N でエラーが発生したのですが、 前回( 上述 )のように「4つのチェック方法の内、どれもが (3) の方法に限ってエラーが起こった」というようなことはなく、(1)〜(4) のすべての方法でエラーとなり、 しかも、そのエラーの発生の仕方は単発的に起こるというものではなく、どの場合にも多発的に頻繁に起こって明らかに異常を感じさせました。

そして、そのエラー時の様子を 機能概要と使用法 の項で説明をした ポーズ動作 をさせて調べてみると、たとえば、同一アドレスにも拘らず h'0F' と書き込んだのに h'07' と読み出したり(この場合には bit3 の欠け)、h'09' と書き込んだのに h'08' と読み出したり(この場合には bit0 の欠け)と、そのときの不良ビットがバラバラで定まっていません。

このように、エラーが起こった ICでは、(1)〜(4) のすべてのチェック方法で同様に、バラバラにビットの欠けが生じており、逆のビットの湧き出しは起こっていない様子でした。

また、上表全体においてのチェック所要時間についてですが、SRAM のサイズ別、チェック方法別がもし同一であれば、たとえメーカーや型名が異なっていても実行されるプログラムは同じものですから、 その所要時間についても本来は同一になる筈です。 実際に上表を見てみても液晶(LCD)を非表示にした場合には、最下桁(10m 秒桁)を除いては同一になっています。

この最下桁の僅かな差は周囲の温度差によるものが大きく、実際に部屋のエアコンを入れたときと 切ったときとでは変化することが確認できました。 今は夏場のためエアコンを入れて部屋の温度が下がると 最下桁の値が増加しました。 本機では 20MHz のセラロックを使用のため基準クロックは ( 1 / 20MHz ) x 4 = 0.2μS の筈ですが、実際には温度が下がることによって基準クロックも僅かに増加するもの と思われます。

そして、プログラムの項の チェック時間短縮の小改善の試み で計算値を示して述べたのと同様に、基準クロックの僅かな変化がアドレスの最大値倍になり、かつ、書き込み(読み出し)の データ数倍となって大きなループでプログラムが実行されるため、結果として最下桁(10m 秒桁)に影響を与えることになります。

一方、チェックの進行状況を液晶(LCD)に表示をした場合には、上述 したように PIC と LCD とのインターフェースでは、ループ動作で PIC が LCD に待たされる部分がある (LCD からのビジーフラグをチェックしている(lcd_busy サブルーチン))ために、たとえ SRAM のサイズ別、チェック方法別が同一であっても全体としての命令の実行数が異なってくるために、 上表のように数秒の差が生じるものと思われます。

| ページトップ |

■ 使用部品表 ■

(主要部品: IC, トランジスタ等)

(データシート)
PICマイコン .................... PIC16F877A
HC-MOS IC (NOR Gate) .................... HD74HC27P
HC-MOS IC (D-Type Flip Flop) .................... HD74HC273P
HC-MOS IC (Bus Buffer) .................... HD74HC541P
HC-MOS IC (D-Type Flip Flop) .................... TC74HC574AP
トランジスタ .................... 2SC3669Y
LCDモジュール .................... SC1602BS-B
圧電ブザー .................... PKM13EPY

| 部品表 | Excel ファイル (StaticRamChecker_parts.xls) | ページトップ |

■ 参考サイト ■

2716〜27512,8748,49用 ROMライター   http://rd.vector.co.jp/soft/dos/hardware/se022884.html
WRDOC.DOC:  2716〜27512 ROMライターの製作  (有)アクト電子 下間憲行氏

| ページトップ | ホーム |


Copyright (C) 2010-2023 やまもとみのる
初版:2010年5月16日、初公開:2013年6月17日、最終更新:2023年10月31日