こちら花小金井3丁目  Last update:2002/02/28
[TopPage] [FMTOWNS] [Hardware] [Freesoft] [怪飲料] [CHAT兼掲示板] [LINK・etc] [About]

_
_ ■ AVRの外部データバスを使う ■

 AVRは単体でもさまざまな制御が出来ますが、難しいインターフェイスの場合は専用ICを繋いで制御を任せます。今回は、ポート数が多く外部SRAMが使用可能なAT90S8515を例に、AVRの外部バスにデバイスをぶらさげます。

 AT90S8515は40pinのAVRで、PORT-A〜Dの各8本、計32本のI/Oポートを持っています。また、外部SRAMをサポートしており、内蔵SRAMと同様の扱いが出来ます。また、SRAMと同じくパラレルなバスでデバイスを接続することが出来ます。外部SRAMを繋ぐ場合は、PORT-Aがアドレス下位8bitと8bitデータバスのマルチプレックスバスとして、PORT-Dがアドレス上位8bitとして動作します。よって、任意アドレス幅のSRAMでデータ8bitバス幅のデバイスを直接繋げられます。


_ ■ USBN9603の接続例 ■

 USBノードコントローラ USBN9603 を例にとって接続してみます。

 USBN9603は、National Semiconductor社製のUSB 1.1規格準拠のUSBノードコントローラです。これを使用してUSBデバイスを作ることが出来ます。今なら入手も容易です。マイコンとの接続インターフェイスとしては、

    ・non-multiplex mode
    ・multiplex mode
    ・MICROWIRE/PLUS mode

 の3つのモードをサポートしています。AT90S8515の外部バスには、multiplexモードを使用します。この場合、通常のSRAMアクセスと同じ感覚で、USBN9603の内部レジスタにアクセスすることが出来ます(これが重要です(^_^))。

 なお、MICROWIRE/PLUSモードは3信号線式の全二重転送方式で、AVRのSPI機能を使うことで接続することが出来ますが、ISPと使用ピン同じなのでスイッチで切り替えでもしないとISP出来ないため、デバッグ効率が落ちてしまいます。I/Oポート数が限られている場合は有効でしょう。PICでも上位機種はMICROWIREインターフェイスを持っています。

 USBN9603とAT90S8515間のピン接続例を以下に示します。アドレスは最上位にマップします。

USBN9603AT90S8515機能
D0〜D7PA0〜PA7(AD0〜AD7)アドレス,データバス
#RDPD7(#RD)読み出し時Lレベル
#WRPD6(#WR)書きこみ時Lレベル
#CSPC7(A15)上位アドレスバス
ALEALEアドレスラッチ時Hレベル

※#CSとA15間にはnot(74HC14など)を入れます。


 接続した上位アドレス線はA15ですので、AVR側からはメモリアドレス0x8000〜にマップされたことになります。A8〜A14までは繋いでいませんので、0x80**〜0xFF**までは同じアドレスへのアクセスになります(^^; 他に繋ぎたいものがあれば、アドレス線に手を加えてデータバスを繋げば良いだけです。後を考えれば、NOTよりもNANDとかのほうが良いかもしれません。

 問題なのは、アドレス線+データ線用に必ず16pin使うことです。ちょっともったいないですね。他にたくさん繋げる場合はいいんですが。


_ ■ AVRASMによるアクセス ■

 AVRの標準アセンブラによるアクセスは簡単です。はじめに手順は必要ですが、ほぼ通常の内蔵SRAMアクセスと同じ感覚でアクセスできます。

 外部SRAMを有効にするには、

    「MCUCR の SRE ビットに 1 を書くだけ」

 です。これで、内蔵SRAMと同じくアクセス可能になり、データバス・アドレスバスの管理がハードウェア側で行われるようになります。

 アセンブラで書くと以下のようになります。

ResetEntry:
	LDI	r16,0xff
	OUT	PORTB,r16
	OUT	PORTD,r16
	
	OUT	DDRA,r16
	OUT	DDRB,r16
	OUT	DDRC,r16
	OUT	DDRD,r16
	
	; SRAM ENABLE
	IN	r16,MCUCR
	ORI	r16,(1<<SRE)
	OUT	MCUCR,r16
	
	LDI	r16,(1<<2)
	STS	0x8000,r16

 この例では、USBN9603のMCTRLレジスタのビット2(VGE)をHにしています。USBN9603のVREG端子から3.3Vが出ていれば、成功です。

 なお、普通のSRAMを繋ぐ場合はスタックを外部SRAM領域に置くことが出来ますが、アクセスにウェイトがかかってしまいます。


_ ■ AVR-GCCによるアクセス ■

 AVR-GCCでは、AVRASMと同じく外部SRAMを有効にして、絶対番地アクセスします。
 ソースを書くと以下のようになります。

	unsigned char *p;
	
	outp( inp(MCUCR)|(1<<SRE) , MCUCR );
	
	p  = (unsigned char *)0x8000;
	*p = (1<<2);

 この例ではAVRASMの場合と同じく、USBN9603のMCTRLレジスタのビット2(VGE)をHにしています。USBN9603のVREG端子から3.3Vが出ていれば、成功です。


 なお、普通のSRAMを繋ぐ場合は変数やスタックを外部SRAM領域に置くことが出来ますが、GCCに自動でそれを使用させるには、makefileやローダスクリプトの変更が必要です。


_ ■ アクセスウェイト ■

 上記の例では、アドレス0x8000にマップされたUSBN9603のアドレス0x0000レジスタにデータを書きこみました。読み込みも正しく動いているか確認してみましょう。次の例では、固定値を返すRevision ID レジスタ(RID)0x0003を読んでみます。普通のUSBN9603では、データシートによれば下位4bitに0b0010を返すはずです。

	unsigned char *p;
	unsigned char dat;
	
	outp( inp(MCUCR)|(1<<SRE) , MCUCR );
	
	p   = (unsigned char *)0x8003;
	dat = (*p & 0x0F);

 ちゃんと、datに0b0010=2が返りましたか? 私はダメでした。場合によっては正しい値が返らないことがあるようです。私の場合は、8.0MHzのAT90S8515ではタイミングの関係でしょうか、うまくいきませんでした。一応、8MHzのAT90S8515に対してUSBN9603は内部48MHzで動作していますので、ウェイトは無くても行けそうな気がするのですが、動かない場合はウェイトを追加します。
 ウェイトを追加するにはSRAMを有効にするとき、一緒にMCUCRレジスタのSRWビットに1を書きます。
	outp( inp(MCUCR)|(1<<SRE)|(1<<SRW) , MCUCR );

 今度はうまくいったと思います。もっと速いAVRの場合はどうなるのか興味あるところです。


_ ■ それでも動かない場合 ■

 例として使ったのが USBN9603 なので、もしかしたら動かない場合があるかもしれません。その場合は以下の点を確認してみてください。

・MODE0,MODE1 ピンは正しくmultiplexモードに設定されていますか?
・ハードウェアリセットピンに正しくHレベルが供給されていますか?
・XTALを使用した場合、XIN-XOUT間に 1MΩ程度の抵抗がありますか?
・どこかにタクトスイッチを付けている場合、チャタリングしていませんか?
・アドレスデコードは正しいですか?  notはかけていますか?

 というのは、ただ単に私が今までに気づかず悩んだことがある点です(^^; たぶんこう書いておけば、また自分が忘れたときに思い出すだろうと言うことで(特に3番目は気づかずに1週間くらい悩んだ)。




もどる