前回の記事「
レトロマイコンZ80ボードの構想(その7)SDカード2」でSDカードのアクセス方法が確認できたので外部メモリ制御のためにPIC24FJ64GAのパラレルマスターポート(PMP)機能について実験してみました。
PICに実装されているPMP機能については「
レトロマイコンZ80ボードの構想(その2)」の記事でも少し書いていますがPIC24FJ64GA004では外部メモリ制御のためのアドレス信号はPMA10(アドレス信号合計で11本)までです。
PICのピンアサインに関しては「
レトロマイコンZ80ボードの構想(その5)ピンアサイン」を参照してください。
今回使用したメモリは HM628128で128KBytesのDIPパッケージの5V動作のスタティックRAMです(アクセスタイム:70ns)。
今回の評価実験回路については
- アドレス線
Z80のメモリ空間は64KBytesなのA16はGNDに固定。またCS2は5Vに接続
- チップセレクト(CS1/)
Z80からのバス切替時などにlowになると最悪メモリ内容が破壊される可能性もあるので5Vにプルアップし、PIC側のPMCS1はオープンドレインに設定
- アドレスの上位ビット
A14、A15はとりあえず、PIC側のAD13に接続
- PMWR
実験的にPIC内でプルアップ設定
としています。
メモリ書込み時のロジアナ波形が下図です。
PMPではメモリアクセス時のタイミングをPMMODE(パラレルマスタポート モードレジスタ)で設定でき、今回は
- WAITB : 0
- WAITM : 1
- WAITE : 0
で設定しています(パラメータ名の末尾はそれぞれ Begin,Middle,End の意味だと思う)
ライトストローブの後にCS1/がdisableになるまでの時間が長め(WAITEで調整)ですが最短設定にしています。
データ線は読込み時にPIC側が入力状態になりますが、一部5Vトレラントでないポートがあります。時間的には一瞬なのでこのために壊れることはまずないと思いますが抵抗を入れる等、考慮した方がいいかも。
アドレス線など、他の信号に関してはPIC側からの出力信号であり、3.3V駆動のPIC側の信号でもメモリ側の規格範囲内(Input high voltage Min 2.2V)です。
メモリ書込み/読込み時の波形が下図です。
0x0000アドレスから開始(アドレスは自動インクリメント)して0xa5と0x5aの2つのデータを書込んだだ後、書込んだデータを読み出している波形です。
読み出し時にデータ線がバタついている部分がありますが、PIC側もメモリ側も入力状態なのでフローティング状態のためです。
バタつくのは良くないのでデータ線に関してはPIC側でプルアップ設定することでバタツキ対処をする予定です。
★2018/02/13 修正 {
3.3V電源が2.9Vの状態でした^^; 3.3Vにするとデータリード時のバタツキは発生しなくなりました(電源電圧が低くスレッショルド付近であったためバタツキ易くなっていたものと思います)。ロジアナのキャプチャも3.3Vのものに差し換えました。
}
★2018/02/12 追記
メモリテスト中のロジアナ波形を追加しておきます。数十分間連続動作させましたがエラーは検出されませんでした。
今回の実験で作ったソースを末尾に貼っておきます。
PMCS1はPMA14(アドレス線)と兼用なのでネット上で見つかる例はチップセレクトとしてPIC24FJ64GA004には無いPMCS2を使うものが殆どで、今回のようにPMCS1を使っている例は見つかりませんでした(海外等をじっくり探せば例があると思うけど探すより試した方が面白い)。
メモリライトを2回行った後、メモリリードを2回行っていますが、最初のリードはPMPがメモリリードシーケンスを開始するためのトリガなので読込んだデータは前回のリード動作で読んだ値になっています。(n個のデータを読むためには(n+1)回の、PMDIN1レジスタの読込みが必要)
また、init()の最後で実験的にPMWRをプルアップ設定してみたところ予想通り、PMPをdisableにした後も信号レベルはhighを保持する(ポート入力機能以外でもPullUp設定は有効)ようになりました。
PMP機能の実験用に作ったソース(picle言語)
:l
1:# PMP test for PIC24FJ64004
2:# ver 0.01 2018/02/10 by skyriver
3:
4:var REG,_REG;
5:var PMCON,PMMODE,PMADDR,PMDAT,PMAEN,PMSTAT;
6:var Pmcon, Pmmode;
7:
8:# print value
9:proc PrnVal( str, val ) {
10: PrnStr_( str );
11: PrnHex_( val );
12:}
13:
14:
15:proc ChkBsy() {
16: while ( PMMODE[0] & $8000 ) {}
17:}
18:
19:
20:proc SetAdr( adr ) {
21: ChkBsy();
22: PMADDR[0] = adr | $4000;
23:}
24:
25:
26:proc MemWr( dat ) {
27: ChkBsy();
28: PMDAT[0] = dat;
29:}
30:
31:
32:func MemRd() {
33: ChkBsy();
34: return = PMDAT[0];
35:}
36:
37:
38:proc init() {
39: var pre,cen,post;
40: PMCON = $0600; # PMMODE[1], PMADDR[2]
41: PMMODE = $0602;
42: PMADDR = $0604;
43: PMDAT = $0608;
44: PMAEN = $060c;
45: PMSTAT = $060e;
46:# PADCFG1 = $02fc;
47:
48: Pmcon = $8380; # 1000 0011 1000 0000
49: PMCON[0] = Pmcon;
50:
51: pre = 0; # 2bit
52: cen = 1; # 4 bit 0:31.25ns 1:62.5ns 2:125ns
53: post = 0; # 2bit
54: Pmmode = $0a00|(pre*64)|(cen*4)|(post); # 00xx x010 xxxx xxxx
55: PMMODE[0] = Pmmode;
56:
57: PMAEN[0] = $47ff; # PMAEN 0100 0111 1111 1111
58:# PADCFG1[0] = $0000; # default
59:
60: asm_( $A8E2CF ); # bset ODCB,#15
61: REG = $02c8; # TRISB
62: REG[2] = 0; # LATB
63: REG[0] = $fff8; # AD11-13
64:
65: REG = $0068; # CNPU1
66: REG[0] = $1000; # pull up CN16 PMWR
67:}
68:
69:
70:proc main() {
71: var dat;
72: init();
73:
74: SetAdr( 0 ); # set addr
75: MemWr( $a5 );
76: MemWr( $5A );
77:
78: SetAdr( 0 ); # set addr
79: dat = MemRd();
80: dat = MemRd();
81:
82: PMCON[0] = $0380; # PMP disable
83: PrnVal( "\npmcon : ", Pmcon );
84: PrnVal( "\npmode : ", Pmmode );
85:}
86:
:run
pmcon : 8380
pmode : 0A04
:
|
[TOP] [ 前へ ] 連載記事
[ 次へ ]
posted by skyriver at 12:14|
Comment(0)
|
Z80
|

|