アプリケーションノート 2871

HDLCコントローラDS31256のステップバイステップの設定-コンフィギュレーションモード


要約: このアプリケーションノートでは、HDLCコントローラDS31256のコンフィギュレーションモードにおいて単一のT1ポートを設定する方法を実例に沿って示します。エンドユーザアプリケーションへの応用が容易になるよう、デバイスの設定、パケットの組立て、送信、受信、およびチェックをループバックモードで行う方法を理解するためのコード例を、ステップバイステップで解説します。

はじめに

このアプリケーションノートでは、コンフィギュレーションモードで動作中のDS31256で単一のT1ポートを設定する方法を、実例に沿って示します。さらに、この例では当該ポート上におけるパケットの構築、送信、受信、およびチェックをループバックモードで行う方法も示しています。このアプリケーションノートは、エンドユーザアプリケーションに容易に応用可能なコーディング例を提供します。

DS31256のローカルバスは、次の2種類のモードで動作可能です。
-PCIブリッジモード
-コンフィギュレーションモード
コンフィギュレーションモードでは、ローカルバスはDS31256の制御と監視にのみ使用され、HDLCパケットデータはPCIバスを介して転送されます。このモードでは、ローカルバスからPCIバスにデータを渡すことはできません(詳細についてはDS31256のデータシートの11.1.2の項を参照してください)。

PCIブリッジモードの使い方の詳細については、アプリケーションノート2872 「HDLCコントローラDS31256のステップバイステップの設定-ブリッジモード」を参照してください。

Figure 1.
図1.

この例では、以下の構成を使用しています。
- DS31256のポート1は、チャネル化されたT1ポートです。他のすべてのポートは使用されていません。
- DS31256のポート1 DS0の0-3は、HDLCチャネル3に割り当てられます。他の全てのポート1 DS0には割り当てられていません。
- DS31256のHDLCチャネル3には、受信FIFOブロック4つ、送信FIFOブロック4つ、受信FIFOの高水位として3、送信FIFOの低水位として1が割り当てられています。
- 送信バッファ1つ、送信ディスクリプタ1つ、および送信待ちキューエントリ1つを使用して、16バイトのパケットをホストメモリ内で組み立てます。DS31256はループバックモードになっているため、パケットが送信される際にはDS31256によって受信も行われます。受信パケットは、受信バッファ1つ、受信ディスクリプタ1つ、および受信済みキューエントリ1つを使用してホストメモリに書き込まれます。
- ホストメモリは以下の構成になっています。
受信側:

受信空きキューのベースアドレス(RFQBA1/0)
= 0x10000000

受信済みキューのベースアドレス(RDQBA1/0)
= 0x10000100

受信ディスクリプタのベースアドレス(RDBA1/0)
= 0x10000200

受信バッファのベースアドレス
= 0x10001000
送信側:

送信待ちキューのベースアドレス(TPQBA1/0)
= 0x10000300

送信済みキューのベースアドレス(TDQBA1/0)
= 0x10000400

送信ディスクリプタのベースアドレス(TDBA1/0)
= 0x10000500

送信バッファのベースアドレス
= 0x10002000

コード例中の関数呼出しの定義

可読性を向上させるため、この例のコードではいくつかの関数呼出しを使用しています。これらの関数の定義を以下に示します。

- write_reg(address、data)
指定したデータを指定したDS31256レジスタアドレスに書き込む

入力:
address = データを書き込むレジスタのアドレス
data = 指定したレジスタに書き込むデータ

出力:なし

- read_reg(address、data)
指定したアドレスのDS31256レジスタの内容を読み取る

入力:
address = 読み取るレジスタアドレス

出力:
data = レジスタから読み取った値

- write_reg_IS(address、data)
指定したデータを指定したDS31256間接選択レジスタに書き込み、そのレジスタのビジービットがクリアされるのを待ってリターンする

入力:
address = データを書き込む間接選択レジスタ
data = 指定したレジスタに書き込むデータ

出力:なし

関数のコード:
write_reg(address、data)
bit_check = 0x8000;
while(bit_check & 0x8000)
read_reg(address, bit_check);

- wr_dword(address、data)
指定した32ビットのデータ値を指定した32ビットのホストメモリアドレスに書き込む

入力:
address = データを書き込むホストメモリアドレス
data = 指定したメモリアドレスに書き込むデータ

出力:なし

- rd_dword(address、data)
32ビットのデータ値を指定した32ビットのホストメモリアドレスから読み取る

入力:
address = 読み取るホストメモリアドレス

出力:
data = ホストメモリから読み取った32ビットのデータ値


- frame_wait(count)
Pcount回数のフレーム期間に等しいディレイを提供する(1回のフレーム期間は125µs)

入力:
count = 待機するフレーム期間の回数

出力:なし

T1設定モードのコード例

このコード例は、以下のステップで構成されています。
1. DS31256のリセット
2. DS31256の設定
3. HDLCチャネルのイネーブル
4. HDLCチャネルのループバックモードへの移行
5. データバケットのキュー、送信、受信、およびチェック


以下の各項では、簡単な解説とコード例によってこれらの各ステップの詳細を示します。可読性を向上させるため、アドレスの代わりにレジスタ名を使用します。対応するDS31256の内部デバイス設定レジスタのアドレス/オフセットを、添付の各表に示します。さらに、送信側と受信側を表すために、それぞれTxとRxという略号を使用します。詳細についてはDS31256のデータシートを参照してください。

DS31256のリセット
DS31256のリセットは、3つのステップで構成されます。最初にDS31256の内部レジスタをリセットし、次にDS31256の内蔵RAMをゼロクリアした後、再びDS31256の内部レジスタをリセットする必要があります。

DS31256内部レジスタのリセット
マスタリセットレジスタ(MRID)を使用して、DS31256のすべてのレジスタについてソフトウェアリセットを実行することができます。MRIDレジスタのビット0に1をセットすると、すべての内部レジスタにデフォルト値の0がセットされます。通常動作のためのデバイスのプログラムを行うには、その前にホストがこのビットを0に戻す必要があります。

オフセット/アドレス 略号 レジスタ名 データシートの項目
0000 MRID Master Reset & ID Register 5.1

//Reset DS31256 using MRID registers master reset bit.
write_reg(MRID, 0x0001);
write_reg(MRID, 0x0000);

DS31256内蔵RAMのゼロクリア
DS31256の内蔵コンフィギュレーションRAMはチップをリセットしてもクリアされないため、手動でゼロクリアする必要があります。適切なデータとDS31256の間接選択レジスタを使用して、DS31256内の各内蔵RAMに対して一連の書込みを実行することによって、この作業を達成することができます。この項では、この作業を達成するための手順を詳しく示します。

オフセット/アドレス 略号 レジスタ名 データシートの項目
03xx CP[n]RDIS Channelized Port n Register Data Indirect Select 6.3
03xx CP[n]RD Channelized Port n Register Data 6.3

// Zero Rx configuration and Tx configuration RAM's for all ports
for(port = 0; port < 16; port = port + 1)
{

write_reg(CP[0]RD + 8 * port, 0x0000);

for(ds0 = 0; ds0 < 128; ds0 = ds0 + 1)

{

// Set bits 9-8 = 01 to select Rx Configuration RAM

// Set bits 9-8 = 10 to select Tx Configuration RAM

write_reg_IS(CP[0]RDIS + 8 * port, (0x0100 + ds0));

write_reg_IS(CP[0]RDIS + 8 * port, (0x0200 + ds0));

}
}

オフセット/アドレス 略号 レジスタ名 データシートの項目
0400 RHCDIS Receive HDLC Channel Definition Indirect Select 7.2
0404 RHCD Receive HDLC Channel Definition 7.2

// Zero the Rx HDLC channel definition RAM
write_reg(RHCD, 0x0000);
for(channel = 0; channel < 256; channel = channel + 1)
write_reg_IS(RHCDIS, channel);

オフセット/アドレス 略号 レジスタ名 データシートの項目
0480 THCDIS Transmit HDLC Channel Definition Indirect Select 7.2
0484 THCD Transmit HDLC Channel Definition 7.2

// Zero the Tx HDLC channel definition RAM
write_reg(THCD, 0x0000);
for(channel = 0; channel < 256; channel = channel + 1)
write_reg_IS(THCDIS, channel);

オフセット/アドレス 略号 レジスタ名 データシートの項目
0770 RDMACIS Receive DMA Configuration Indirect Select 9.3.5
0774 RDMAC Receive DMA Configuration 9.3.5

// Zero the Rx DMA configuration RAM
write_reg(RDMAC, 0x0000);
for(channel = 0; channel < 256; channel = channel + 1)
write_reg_IS(RDMACIS, 0x0400 + channel);

オフセット/アドレス 略号 レジスタ名 データシートの項目
0870 TDMACIS Transmit DMA Configuration Indirect Select 9.3.5
0874 TDMAC Transmit DMA Configuration 9.3.5

// Zero the Tx DMA configuration RAM
write_reg(TDMAC, 0x0000);
for(channel = 0; channel < 256; channel = channel + 1)
write_reg_IS(TDMACIS, 0x0200 + channel);

オフセット/アドレス 略号 レジスタ名 データシートの項目
0900 RFSBPIS Receive FIFO Starting Block Pointer Indirect Select 8.2
0904 RFSBP Receive FIFO Starting Block Pointer 8.2

// Zero the Rx FIFO Starting Block Pointer RAM
write_reg(RFSBP, 0x0000);
for(channel = 0; channel < 256; channel = channel + 1)
write_reg_IS(RFSBPIS, channel);

オフセット/アドレス 略号 レジスタ名 データシートの項目
0910 RFBPIS Receive FIFO Block Pointer Indirect Select 8.2
0914 RFBP Receive FIFO Block Pointer 8.2

// Zero the Rx FIFO Block Pointer RAM
write_reg(RFBP, 0x0000);
for(channel = 0; channel < 256; channel = channel + 1)
write_reg_IS(RFBPIS, channel);

オフセット/アドレス 略号 レジスタ名 データシートの項目
0920 RFHWMIS Receive FIFO High Watermark Indirect Select 8.2
0924 RFHWM Receive FIFO High Watermark 8.2

// Zero the Rx FIFO High Watermark RAM
write_reg(RFHWM, 0x0000);
for(channel = 0; channel < 256; channel = channel + 1)
write_reg_IS(RFHWMIS, channel);

オフセット/アドレス 略号 レジスタ名 データシートの項目
0980 TFSBPIS Transmit FIFO Starting Block Pointer Indirect Select 8.2
0984 TFSBP Transmit FIFO Starting Block Pointer 8.2

// Zero the Tx FIFO Starting Block Pointer registers
write_reg(TFSBP, 0x0000);
for(channel = 0; channel < 256; channel = channel + 1)
write_reg_IS(TFSBPIS, channel);

オフセット/アドレス 略号 レジスタ名 データシートの項目
0990 TFBPIS Transmit FIFO Block Pointer Indirect Select 8.2
0994 TFBP Transmit FIFO Block Pointer 8.2

// Zero the Tx FIFO Block Pointer RAM
write_reg(TFBP, 0x0000);
for(channel = 0; channel < 256; channel = channel + 1)
write_reg_IS(TFBPIS, channel);

オフセット/アドレス 略号 レジスタ名 データシートの項目
09A0 TFLWMIS Transmit FIFO Low Watermark Indirect Select 8.2
09A4 TFLWM Transmit FIFO Low Watermark 8.2

// Zero the Tx FIFO Low Watermark RAM
write_reg(TFLWM, 0x0000);
for(channel = 0; channel < 256; channel = channel + 1)
write_reg_IS(TFLWMIS, channel);

DS31256内部レジスタのリセット
マスタリセットレジスタ(MRID)を使用して、DS31256のすべてのレジスタについてソフトウェアリセットを実行することができます。MRIDレジスタのビット0に1をセットすると、すべての内部レジスタにデフォルト値の0がセットされます。通常動作のためのデバイスのプログラムを行うには、その前にホストがこのビットを0に戻す必要があります。

オフセット/アドレス 略号 レジスタ名 データシートの項目
0000 MRID Master Reset and ID Register 5.1

// Reset DS31256 using MRID registers master reset bit.
write_reg(MRID, 0x0001);
write_reg(MRID, 0x0000);

DS31256の設定
DS31256の設定は、以下のステップで構成されます。
1. PCIレジスタの設定
2. レイヤ1レジスタの設定
3. HDLCレジスタの設定
4. FIFOレジスタの設定
5. DMAレジスタの設定


以下の各項では、これらのレジスタセットのそれぞれの設定について詳しく示します。可読性を向上させ、よりアルゴリズム的なコード構造とするため、いくつかの変数を使用します。次のコードは、それらの変数を初期化するものです。

// This example uses port 1 channel 3
port = 1;
channel = 3;

// Rx free queue base address
rfq_base_addr = 0x10000000;

// Rx free queue end address
// Rx free queue size = 16
rfq_end_idx = 0x000F;

// Rx done queue base address
rdq_base_addr = 0x10000100;

// Rx done queue end address
// Rx done queue size = 16
rdq_end_idx = 0x000F;

// Rx descriptor base address
// Rx descriptor table size = 256
rdscr_base_addr = 0x10000200;

// Rx data buffer base address
rx_buf_base_addr = 0x10001000;

// Tx pending queue base address
tpq_base_addr = 0x10000300;

// Tx pending queue end address
// Tx pending queue size = 16
tpq_end_idx = 0x000F;

// Tx done queue base address
tdq_base_addr = 0x10000400;

// Tx done queue end address
// Tx done queue size = 16
tdq_end_idx = 0x000F;
// Tx descriptor base address
// Tx descriptor table size = 256
tdscr_base_addr = 0x10000500;

// Tx data buffer base address
tx_buf_base_addr = 0x10002000;

PCIレジスタの設定
コンフィギュレーションモードでは、DMA動作を実行する際にDS31256がどのようにPCIバスとインタフェースするかをPCIレジスタによって制御します。PCIレジスタの設定はシステム依存であり、したがって特定のユーザアプリケーションをサポートするために以下のコード例の修正が必要になる可能性があります。

オフセット/アドレス 略号 レジスタ名 データシートの項目
0x004/0A04 PCMD0 PCI Command Status 0 10.2

// PCI command/status register 0 - controls DS31256 DMA functionality
// Set Bit 2 = 1 to allow device operation as bus master on PCI bus (required for DMA)
// Set bit 6 = 1 to act on parity errors
// Set bit 8 = 1 to enable PSERR pin
write_reg(PCMD0, 0x0144);

レイヤ1レジスタの設定
DS31256の各ポートは、以下のようないくつかの機能を実行するレイヤ1コントローラを備えています。
- 入力および出力データに対するHDLCチャネル番号の割当て
- チャネル化ローカルおよびネットワークループバック
- チャネル化選択(64kps、56kps、またはデータなし)
- チャネル化送信DS0チャネルのオール1フィル
- BERT機能との間におけるデータのルーティング
- V.54ループパターンディテクタへのデータのルーティング


レイヤ1の設定は、RP[n]CR、TP[n]CR、CP[n]RD、およびCP[n]RDISの各レジスタ(nは設定対象のポート)を通して、ポート単位で行います。

オフセット/アドレス 略号 レジスタ名 データシートの項目
01xx RP[n]CR Receive Port n Control Register 6.2
02xx TP[n]CR Transmit Port n Control Register 6.2
03xx CP[n]RDIS Channelized Port n Register Data Indirect Select 6.3
03xx CP[n]RD Channelized Port n Register Data 6.3

// Set RX Port Control Register
// Set bits 2-0 = 000 for clock, data and sync are not inverted
// Set bits 5-4 = 00 for sync pulse 0 clocks early
// Set bits 7-6 = 00 for T1 mode
// Set bit 10 = 0 to disable local loopback
write_reg(RP[0]CR + 4 * port, 0x0000);

// Set Tx Port Control Register
// Set bit 2-0 = 000 for clock, data and sync are not inverted
// Set bit 3 = 0 to force all data at TD to be 1
// Set bits 5-4 = 00 for sync pulse 0 clocks early
// Set bits 7-6 = 0 for T1 mode
write_reg(TP[0]CR + 4 * port, 0x0000);

// RX Port Configuration Registers
// DS0's 0-3 disabled, assigned to HDLC channel
// CP[n]RDIS bits 9-8 = 01 for Receive Configuration
write_reg(CP[0]RD + 8 * port, 0x0000 + channel);
for(ds0 = 0; ds0 < 4; ds0 = ds0 + 1)
write_reg_IS(CP[0]RDIS + 8 * port, 0x0100 + ds0);

// Tx Port Configuration Registers
// DS0's 0-3 disabled, assigned to HDLC channel
// CP[n]RDIS bits 9-8 = 10 for Transmit Configuration
write_reg(CP[0]RD + 8 * port, 0x0000 + channel);
for(ds0 = 0; ds0 < 4; ds0 = ds0 + 1)
write_reg_IS(CP[0]RDIS + 8 * port, 0x0200 + ds0);

HDLCレジスタの設定
DS31256は、レイヤ2の機能を実行する256チャネルのHDLCコントローラを内蔵しています。このコントローラによって実行される機能は、以下の通りです。

- ゼロスタッフィングとデスタッフィング
- フラグ検出とバイトアラインメント
- CRCの生成と検査
- データ反転とビット反転


HDLCコントローラの設定は、RHCD、RHCDIS、THCD、およびTHCDISの各レジスタを通して、チャネル単位で行います。

オフセット/アドレス 略号 レジスタ名 データシートの項目
0400 RHCDIS Receive HDLC Channel Definition Indirect Select 7.2
0404 RHCD Receive HDLC Channel Definition 7.2
0480 THCDIS Transmit HDLC Channel Definition Indirect Select 7.2
0484 THCD Transmit HDLC Channel Definition 7.2

// RX HDLC configuration
// Set bits 3-2 = 10 for 32-bit CRC
write_reg(RHCD, 0x0008);
write_reg_IS(RHCDIS, channel);

// Tx HDLC configuration
// Set bit 1= 0 to select an interfill byte of 7E
// Set bits 3-2 = 10 for 32-bit CRC
// Set bits 11-8 = 1000 for closing flag/no interfill bytes/opening flag
write_reg(THCD, 0x0108);
write_reg_IS(THCDIS, channel);

FIFOレジスタの設定
DS31256は、16kBの送信FIFOと16kBの受信FIFOを内蔵しています。各FIFOは、4dword (16バイト) x 1024ブロックに分割されています。FIFOメモリは、HDLCチャネルごとに割り当てられます。各HDLCチャネルに割り当てるFIFOメモリの量は設定可能であり、最小で4ブロックから最大で1024ブロックまでです。FIFOメモリをHDLCチャネルに割り当てる際には、ブロックのグループから循環リンクリストを作成して、各ブロックがチェイン内の次のブロックを指し、最後のブロックは先頭のブロックを指すようにします。このFIFOブロックのリンクリストを特定のHDLCチャネルに割り当てるには、リンクリスト中の1つのブロックをそのチャネルのFIFO先頭ブロックポインタに割り当てます。

この例では、4つの送信FIFOブロックと4つの受信FIFOブロックをHDLCチャネルに割り当てています。また、この例では受信FIFOの高水位として3を、送信FIFOの低水位として1を使用しています。受信FHFOの高水位はDMAによるPCIバスへのデータ送信が開始されるための、HDLCエンジンによって受信FIFOに書き込まれるべきブロック数を示します。高水位の設定は、1ブロックから、関係する特定チャネルのリンクリストチェイン内のブロック数以下の間にする必要があります。送信FIFOの低水位はDMAによるPCIバスからさらにデータ取得を開始するための、送信FIFO内に残すべきブロック数を示します。送信アンダフローと受信オーバフローの発生を防ぐためにHDLCチャネルが必要とするFIFOメモリの量、受信FIFOの高水位、および送信FIFOの低水位は、アプリケーションに依存します。DS31256の送信FIFOと受信FIFOは、以下の表に示すレジスタを通してHDLCチャネルごとに独立して設定します。

オフセット/アドレス 略号 レジスタ名 データシートの項目
0910 RFBPIS Receive FIFO Block Pointer Indirect Select 8.2
0914 RFBP Receive FIFO Block Pointer 8.2

// Build the Rx FIFO block linked list
// 0->1->2->3->0
for (block = 0; block < 4; block = block + 1)
{
// Bits 9-0 in RFBP register indicate which block is next in the linked list
write_reg(RFBP, block + 1);
write_reg_IS(RFBPIS, block);
}

// The last block points to the first block to create a circular linked list
write_reg(RFBP, 0x0000);
write_reg_IS(RFBPIS, 0x0003);

// Assign the circular linked list to a specific channel
write_reg(RFSBP, 0x0000);
write_reg_IS(RFSBPIS, channel);

オフセット/アドレス 略号 レジスタ名 データシートの項目
0920 RFHWMIS Receive FIFO High Watermark Indirect Select 8.2
0924 RFHWM Receive FIFO High Watermark 8.2

// Set RX FIFO high watermark for channel to 3
write_reg(RFHWM, 0x0003);
write_reg_IS(RFHWMIS, channel);

オフセット/アドレス 略号 レジスタ名 データシートの項目
0990 TFBPIS Transmit FIFO Block Pointer Indirect Select 8.2
0994 TFBP Transmit FIFO Block Pointer 8.2

// Tx FIFO block linked list
// 0->1->2->3->0
for (block = 0; block < 4; block = block + 1)
{
// Bits 9-0 in TFBP register indicate which block is next in the linked list
write_reg(TFBP, block + 1);
write_reg_IS(TFBPIS, block);
}

// The last block points to the first block to create a circular linked list
write_reg(TFBP, 0x0000);
write_reg_IS(TFBPIS, 0x0003);

オフセット/アドレス 略号 レジスタ名 データシートの項目
0980 TFSBPIS Transmit FIFO Starting Block Pointer Indirect Select 8.2
0984 TFSBP Transmit FIFO Starting Block Pointer 8.2

// Assign the circular linked list to a specific channel
write_reg(TFSBP, 0x0000);
write_reg_IS(TFSBPIS, channel);

オフセット/アドレス 略号 レジスタ名 データシートの項目
09A0 TFLWMIS Transmit FIFO Low Watermark Indirect Select 8.2
09A4 TFLWM Transmit FIFO Low Watermark 8.2

// Set Tx FIFO low watermark for channel to 1
write_reg(TFLWM, 0x0001);
write_reg_IS(TFLWMIS, channel);

DMAレジスタの設定
DMAブロックは、FIFOブロックとPCIブロックの間のパケットデータの転送を処理します。PCIブロックは、DS31256と外部PCIバスの間のデータ転送を制御します。ホスト(PCIバス上に位置するCPUまたはインテリジェントコントローラ)が、DS31256に対して入出力データの処理方法を指示します。

これには、ディスクリプタ(ホストとDMAブロックの間で送受されるフォーマット済みのメッセージ)を使用します。ホストはこれらのディスクリプタを通して、送信するパケットデータの位置と状態、および受信したパケットデータを格納する位置をDMAに通知します。DMAはこれらのディスクリプタを使用して、送信したパケットデータの状態、および受信したパケットデータの位置と状態をホストに伝えます。

受信側では、ホストが空きキューディスクリプタに書込みを行うことで、入力パケットデータをどこに格納すれば良いかをDMAに知らせます。個々の空きキューエントリに、受信データバッファの位置とパケットディスクリプタが関連づけられます。DS31256は、受信したパケットデータをホストメモリに書き込むために、受信空きキューエントリを使用して同時に、受信済みキューにエントリを作成します。これらの受信済みキューエントリによって、受信したデータの位置と状態がホストに通知されます。詳細についてはDS31256のデータシートを参照してください。ホストは、以下の表に示すすべてのレジスタに書込みを行うことによって、受信DMAの設定を行う必要があります。

オフセット/アドレス 略号 レジスタ名 データシートの項目
0700 RFQBA0 Receive Free Queue Base Address 0 (lower word) 9.2.3
0704 RFQBA1 Receive Free Queue Base Address 1 (upper word) 9.2.3
0708 RFQEA Receive Free Queue end Address 9.2.3
070C RFQSBSA Receive Free Small Buffer Start Address 9.2.3
0710 RFQLBWP Receive Free Queue Large Buffer Host Write Pointer 9.2.3
0714 RFQSBWP Receive Free Queue Small Buffer Host Write Pointer 9.2.3
0718 RFQLBRP Receive Free Queue Large Buffer DMA Read Pointer 9.2.3
071C RFQSBRP Receive Free Queue Small Buffer DMA Read Pointer 9.2.3
0730 RDQBA0 Receive Done Queue Base Address 0 (lower word) 9.2.4
0734 RDQBA1 Receive Done Queue Base Address 1 (upper word) 9.2.4
0738 RDQEA Receive Done Queue end Address 9.2.4
073C RDQRP Receive Done Queue Host Read Pointer 9.2.4
0740 RDQWP Receive Done Queue DMA Write Pointer 9.2.4
0750 RDBA0 Receive Descriptor Base Address 0 (lower word) 9.2.2
0754 RDBA1 Receive Descriptor Base Address 1 (upper word) 9.2.2
0770 RDMACIS Receive DMA Configuration Indirect Select 9.3.5
0774 RDMAC Receive DMA Configuration 9.3.5
0790 RLBS Receive Large Buffer Size 9.2.1

// Rx large buffer size = 256 bytes
write_reg(RLBS, 0x0100);

// Rx free queue base address
write_reg(RFQBA0, rfq_base_addr & 0x0000FFFF);
write_reg(RFQBA1, (rfq_base_addr >> 16) & 0x0000FFFF);

// Rx free queue large buffer read and write pointers = 0
write_reg(RFQLBRP, 0x0000);
write_reg(RFQLBWP, 0x0000);

// Rx free queue small buffer start address = 16
write_reg(RFQSBSA, rfq_end_idx);

// Rx free queue small buffer read and write pointers = 0
write_reg(RFQSBRP, 0x0000);
write_reg(RFQSBWP, 0x0000);

// Rx free queue end address
write_reg(RFQEA, rfq_end_idx);

// Rx done queue base address
write_reg(RDQBA0, rdq_base_addr & 0x0000FFFF);
write_reg(RDQBA1, (rdq_base_addr >> 16) & 0x0000FFFF);

// Rx done queue read and write pointers = 0
write_reg(RDQRP, 0x0000);
write_reg(RDQWP, 0x0000);

// Rx done queue end address
write_reg(RDQEA, rdq_end_idx);

// Rx descriptor base address
write_reg(RDBA0, rdscr_base_addr & 0x0000FFFF);
write_reg(RDBA1, (rdscr_base_addr >> 16) & 0x0000FFFF);

// Rx DMA Channel Configuration
// The data in RDMAC register is written to or read from the Receive Configuration RAM
// Set bit 0 = 0 to disable the HDLC Channel
// Set bit 201 = 00 for large buffers only
// Set bit 6-3 = 0000 for 0 byte offset from the data buffer address of the first data buffer
// Set Bit 9-7 = 000 for DMA write to the Done Queue only after packet reception is complete
// Set the HDLC Channel Number by RDMACIS register
write_reg(RDMAC, 0x0000);
write_reg_IS(RDMACIS, 0x0400 + channel);

送信側では、ホストが送信待ちキューに書込みを行うことによって、どのチャネルに送信準備のできたパケットデータが存在するかをDMAに通知します。それぞれの送信待ちキューディスクリプタには、パケットデータについて記述した1つ以上の送信パケットディスクリプタからなるリンクリストが関連づけられます。これらの各送信パケットディスクリプタには、HDLCパケットの実際のデータペイロードが格納された送信データバッファを指すポインタも格納されています。

DS31256は、送信待ちキューのディスクリプタエントリを処理するのと同時に、送信済みキューにディスクリプタキューエントリを作成していきます。DMAは、DS31256の設定内容に応じて、パケット全体またはデータバッファ全体の送信を完了したとき送信済みキューに書込みを行います。これらの送信済みキューディスクリプタを通して、DMAはホストに出力パケットデータの状態を通知します。詳細についてはDS31256のデータシートを参照してください。ホストは、以下の表に示すすべてのレジスタに書込みを行うことによって、送信DMAの設定を行う必要があります。

オフセット/アドレス 略号 レジスタ名 データシートの項目
0800 TPQBA0 Transmit Pending Queue Base Address 0 (lower word) 9.3.3
0804 TPQBA1 Transmit Pending Queue Base Address 1 (upper word) 9.3.3
0808 TPQEA Transmit Pending Queue end Address 9.3.3
080C TPQWP Transmit Pending Queue Host Write Pointer 9.3.3
0810 TPQRP Transmit Pending Queue DMA Read Pointer 9.3.3
0830 TDQBA0 Transmit Done Queue Base Address 0 (lower word) 9.3.4
0834 TDQBA1 Transmit Done Queue Base Address 1 (upper word) 9.3.4
0838 TDQEA Transmit Done Queue end Address 9.3.4
083C TDQRP Transmit Done Queue Host Read Pointer 9.3.4
0840 TDQWP Transmit Done Queue DMA Write Pointer 9.3.4
0850 TDBA0 Transmit Descriptor Base Address 0 (lower word) 9.3.2
0854 TDBA1 Transmit Descriptor Base Address 1 (upper word) 9.3.2
0870 TDMACIS Transmit DMA Configuration Indirect Select 9.3.5
0874 TDMAC Transmit DMA Configuration 9.3.5

// Tx pending queue base address
write_reg(TPQBA0, tpq_base_addr & 0x0000FFFF);
write_reg(TPQBA1, (tpq_base_addr >> 16) & 0x0000FFFF);

// Tx pending queue read and write pointers = 0
write_reg(TPQRP, 0x0000);
write_reg(TPQWP, 0x0000);

// Tx pending queue end address
write_reg(TPQEA, tpq_end_idx);

// Tx done queue base address
write_reg(TDQBA0, tdq_base_addr & 0x0000FFFF);
write_reg(TDQBA1, (tdq_base_addr >> 16) & 0x0000FFFF);

// Tx done queue read and write pointers = 0
write_reg(TDQRP, 0x0000);
write_reg(TDQWP, 0x0000);

// Tx done queue end address
write_reg(TDQEA, tdq_end_idx);

// Tx descriptor base address
write_reg(TDBA0, tdscr_base_addr & 0x0000FFFF);
write_reg(TDBA1, (tdscr_base_addr >> 16) & 0x0000FFFF);

// Tx DMA Channel Configuration
// The data in TDMAC register is written to or read from the Transmit Configuration RAM
// Set bit 0 = 0 to disable HDLC Channel
// Set bit 1 = 0 for write done queue after packet transmitted
// Set the HDLC Channel Number by TDMACIS register
write_reg(TDMAC, 0x0000);
write_reg_IS(TDMACIS, 0x0200 + channel);

HDLCチャネルのイネーブル
DS31256の初期化が完了した後、次のステップはHDLCチャネルのイネーブルです。すでに説明した設定ステップに加えて、以下のステップを実行してDS31256のパケット送受信をイネーブルする必要があります。

1. ポート送信および受信設定RAMでのHDLCチャネルのイネーブル(HDLCチャネルイネーブル)
2. 受信空きキューの初期化(DMAディスクリプタのロード)
3. DS31256の送信DMAおよび受信DMAのイネーブル(DMAのイネーブル)
4. HDLCチャネルの送信および受信DMAのイネーブル
5. レイヤ1のポートデータ送信のイネーブル(HDLCチャネルオン)


ポート送信および受信設定RAMでのHDLCチャネルのイネーブル
オフセット/アドレス 略号 レジスタ名 データシートの項目
03xx CP[n]RDIS Channelized Port n Register Data Indirect Select 6.3
03xx TPQBA1 Channelized Port n Register Data 6.3

// Enable packet reception in port layer 1 Rx configuration RAM
for (ds0 = 0; ds0 < 4; ds0 = ds0 + 1)
{
// Read the current data value from the Rx Configuration RAM
// Set CP[n]RDIS bits 6-0 = DS0
// Set CP[n]RDIS bit 14 = 1 to read data from the RAM
// Set CP[n]RDIS bits 9-8 = 01 to select Rx configuration RAM
write_reg_IS(CP[0]RDIS + 8 * port, 0x4100 + ds0);
read_reg(CP[0]RD + 8 * port, data);

// Update memory with new value
// Set CP[n]RDIS bits 6-0 = DS0
// Set CP[n]RDIS bit 14 = 0 to write data to the RAM
// Set CP[n]RDIS bits 9-8 = 01 to select Rx configuration RAM
// Enable DS0 by setting bit 15 = 1 in CP[0]RD register
write_reg(CP[0]RD + 8 * port, data | 0x8000);
write_reg_IS(CP[0]RDIS + 8 * port, 0x0100 + ds0);
}

// Enable packet transmission in Port Layer 1 Tx configuration RAM
for (ds0 = 0; ds0 < 4; ds0 = ds0 + 1)
{
// Read the current data value from the Tx Configuration RAM
// Set CP[n]RDIS bits 6-0 = DS0
// Set CP[n]RDIS bit 14 = 1 to read data from the RAM
// Set CP[n]RDIS bits 9-8 = 10 to select Tx configuration RAM
write_reg_IS(CP[0]RDIS + 8 * port, 0x4200 + ds0);
read_reg(CP[0]RD + 8 * port, bit_check);

// Update memory with new value
// Set CP[n]RDIS bits 6-0 = DS0
// Set CP[n]RDIS bit 14 = 0 to write data to the RAM
// Set CP[n]RDIS bits 9-8 = 10 to select Tx configuration RAM
// Enable DS0 by setting bit 15 = 1 in CP[0]RD register
write_reg(CP[0]RD + 8 * port, bit_check | 0x8000);
write_reg_IS(CP[0]RDIS + 8 * port, 0x0200 + ds0);
}

受信空きキューの初期化
DS31256が受信したパケットを内部FIFOからホストメモリにDMA転送するためには、その前にホストがDS31256にデータの格納場所を指示する必要があります。これは受信空きキューを通して行います。受信空きキューの各エントリには、受信データバッファへのポインタと受信パケットディスクリプタのインデックスが格納されます。この例では、受信空きキューエントリを1つ使用しています。このエントリには、受信空きキューラージバッファ1つと受信パケットディスクリプタ1つが格納されています。DS31256の受信ラージデータバッファのサイズは256バイトに設定されています(RLBS = 256)。さらに、4バイトのCRCを使用して、受信CRCを受信データバッファに書き込むようにDS31256の設定が行われています。したがって、1つの受信ラージデータバッファに、最大252バイトのパケットデータを格納することができます。

オフセット/アドレス 略号 レジスタ名 データシートの項目
0710 RFQLBWP Receive Free Queue Large Buffer Host Write Pointer 9.2.3
0718 RFQLBRP Receive Free Queue Large Buffer DMA Read Pointer 9.2.3

// check for space in Rx large free queue
read_reg(RFQLBWP, wr_ptr);
read_reg(RFQLBRP, rd_ptr);
if (rd_ptr > wr_ptr)

cnt = rd_ptr - wr_ptr - 1;
else

cnt = rfq_end_idx - wr_ptr + rd_ptr;

// If room in Rx free queue then put 1 entry in the queue
// dword 0 = Rx data buffer address (use Rx data buffer starting at Rx buffer area base address)
// dword 1 = corresponding Rx descriptor index (use Rx descriptor table index 0)
if (cnt > 0)
rx_dscr_idx = 0;
wr_dword(rfq_base_addr + wr_ptr * 8, rx_buf_base_addr);
wr_dword(rfq_base_addr + wr_ptr * 8 + 4, rx_dscr_idx);

// Advance the Rx free queue large buffer write pointer by 1
if (wr_ptr = rfq_end_idx)

wr_ptr = 0;
else

wr_ptr = wr_ptr + 1;
write_reg(RFQLBWP, wr_ptr);
}

DS31256の送信および受信DMAのイネーブル
オフセット/アドレス 略号 レジスタ名 データシートの項目
0010 MC Master Configuration 5.2

// Enable Tx and Rx DMA in the DS31256 master configuration register
// Set bit 0 = 1 to enable Receive DMA
// Set bits 2-1 = 00 to burst length maximum is 32 dwords
// Set bit 3 = 1 to enable Transmit DMA
// Set bits 6 = 1 for HDLC packet data on PCI bus is big endian
// Set bits 11-7 = 00000 to select Port 0 has the dedicated resources of the BERT
write_reg(MC, 0x0049);

HDLCチャネルの送信および受信のイネーブル
オフセット/アドレス 略号 レジスタ名 データシートの項目
0770 RDMACIS Receive DMA Configuration Indirect Select Register 9.3.5
0774 RDMAC Receive DMA Configuration Register 9.3.5
0870 TDMACIS Transmit DMA Configuration Indirect Select Register 9.3.5
0874 TDMAC Transmit DMA Configuration Register 9.3.5

// Read the current channel value from the Rx DMA Configuration RAM
// Set RDMACIS bits 7-0 = channel
// Set RDMACIS bits 10-8 = 100 to read lower word of dword 2
// Set RDMACIS bit 14 = 1 to read from RAM
write_reg_IS(RDMACIS, 0x4400 + channel);
read_reg(RDMAC, data);

// Enable channel Rx DMA
// Update RAM with new value
// Set RDMAC bit 0 = 1 to enable the HDLC channel
// Set RDMACIS bits 7-0 = channel
// Set RDMACIS bits 10-8 = 100 to read lower word of dword 2
// Set RDMACIS bit 14 = 1 to read from RAM
write_reg(RDMAC, data | 0x0001);
write_reg_IS(RDMACIS, 0x0400 + channel);

// Read the current channel value from the Tx DMA Configuration RAM
// Set TDMACIS bits 7-0 = channel
// Set TDMACIS bits 11-8 = 0010 to read lower word of dword 1
// Set TDMACIS bit 14 = 1 to read from RAM
write_reg_IS(TDMACIS, 0x4200 + channel);
read_reg(TDMAC, data);

// Enable channel Tx DMA
// Update RAM with new value
// Set TDMAC bit 0 = 1 to enable the HDLC channel
// Set TDMACIS bits 7-0 = channel
// Set TDMACIS bits 11-8 = 0010 to read lower word of dword 1
// Set TDMACIS bit 14 = 0 to write to RAM
write_reg((TDMAC, data | 0x0001);
write_reg_IS(TDMACIS, 0x0200, + channel);

レイヤ1のポートデータ送信イネーブル
オフセット/アドレス 略号 レジスタ名 データシートの項目
02xx TP[n]CR Transmit Port n Control Register 6.2

// Tx port control register
// Set Bit 3 TFDA1 = 1 to allow data to be transmitted normally
read_reg(TP[0]CR + 4 * port, data);
write_reg(TP[0]CR + 4 * port, data | 0x0008);

HDLCチャネルのループバックモードへの移行
チャネルの設定とイネーブルを行った後、DS31256の内部ロジックが新しい設定への遷移を完了するのに約5フレーム (625µs)かかります。この遷移が完了した後、HDLCチャネルはループバックモードに移行し、チャネル上で送信したすべてのデータを同じチャネルで受信することができるようになります。5フレームの待ち時間よりも前にHDLCチャネルをループバックモードに移行させた場合は、そのチャネルの受信FIFOにゴミデータが書き込まれる可能性があります。

オフセット/アドレス 略号 レジスタ名 データシートの項目
01xx RP[n]CR Receive Port n Control Register 6.2

// Wait for at least 5 frame periods for the internal DS31256 initialization to complete
frame_wait(5);

// Set Bit 10 = 1 to enable loopback - routes transmit data back to the receive port
read_reg(RP[0]CR + 4 * port, data);
write_reg(RP[0]CR + 4 * port, data | 0x0400);

データバケットのキュー、送信、受信、およびチェック
DS31256の初期化が完了した後は、データの送信と受信を行うことができます。DS31256はループバックモードになっているため、HDLCチャネル上で送信されるすべてのデータは、そのチャネル上で受信もされることになります。この項では、ホストメモリ上でデータパケットを構築し、そのパケットの送信と受信を行い、結果をチェックする方法について説明します。以下の各項で、このプロセスについて詳細に示します。

ホストメモリ内でのパケットの構築

この例では、16バイトのデータパケットを送信します。パケットを送信するためには、まずホストメモリ内でそのパケットを構築する必要があります。さらに、対応する送信パケットディスクリプタもホストメモリ内で構築する必要があります。これらの各タスクを以下のコードで詳しく示します。

// Create a 16-byte data packet in memory in a Tx buffer whose start address is the Tx buffer area base
// address
wr_dword(tx_buf_base_addr, 0x01234567);
wr_dword(tx_buf_base_addr + 4, 0x89ABCDEF);
wr_dword(tx_buf_base_addr + 8, 0x02468ACE);
wr_dword(tx_buf_base_addr + 12, 0x13579BDF);

// Create a Tx descriptor (4 dwords) for the packet at Tx descriptor
// Tx descriptor table index 0
// dword0 = Tx buffer address
// dword1 = EOF, CV, byte count, next descriptor pointer
// dowrd2 = HDLC channel
// dword3 = PV, next pending descriptor pointer (set to 0)
tx_dscr_idx = 0;
wr_dword(tdscr_base_addr + tx_dscr_idx * 16, tx_buf_base_addr);
wr_dword(tdscr_base_addr + tx_dscr_idx * 16 + 4, 0x80100000);
wr_dword(tdscr_base_addr + tx_dscr_idx * 16 + 8, 0x00000000 + channel);
wr_dword(tdscr_base_addr + tx_dscr_idx * 16 + 12, 0x00000000);

パケットの送信と受信

パケットを送信するためには、送信ディスクリプタを送信待ちキューに格納した上で、送信待ちキュー書込みポインタ(TPQWP)をインクリメントする必要があります。送信待ちキューが空ではない(TPQWPはTPQRPと等しくない)ことを検出したDS31256はキューエントリの処理を開始し、パケットが送信されます。

オフセット/アドレス 略号 レジスタ名 データシートの項目
0028 SDMA Status Register for DMA 5.3.2
080C TPQWP Transmit Pending Queue Host Write Pointer 9.3.3
0810 TPQRP Transmit Pending Queue DMA Read Pointer 9.3.3

// Read SDMA register to clear any previously set status bits
read_reg(SDMA, data);

// check free space in Tx pending queue
read_reg(TPQWP, wr_ptr);
read_reg(TPQRP, rd_ptr)
if (rd_ptr > wr_ptr)

cnt = rd_ptr - wr_ptr - 1;
else

cnt = rfq_end_idx - wr_ptr + rd_ptr;

// If room in the Tx pending queue create an entry for the packet
if (cnt > 0)
{
wr_dword(tpq_base_addr + wr_ptr * 4, 0x0000000 + (channel << 16));

// Advance the Tx pending queue write pointer
if (wr_ptr = tpq_end_idx)

wr_ptr = 0;
else

wr_ptr = wr_ptr + 1;
write_reg(TPQWP, wr_ptr);
}

結果のチェック

パケットの送信と受信が行われるための十分な時間だけ待機した後、いくつかのチェックを実行してパケットの送信と受信が成功したかどうかを判定することができます。以下のコードは、これらのチェックの詳細を示すものです。

オフセット/アドレス 略号 レジスタ名 データシートの項目
0028 SDMA Status Register for DMA 5.3.2
0710 RFQLBWP Receive Free Queue Large Buffer Host Write Pointer 9.2.3
0718 RFQLBRP Receive Free Queue Large Buffer DMA Read Pointer 9.2.3
073C RDQRP Receive Done Queue Host Read Pointer 9.2.4
0740 RFQLBRP Receive Done Queue DMA Write Pointer 9.2.4
083C TDQRP Transmit Done Queue Host Read Pointer 9.3.4
0840 TDQWP Transmit Done Queue DMA Write Pointer 9.3.4

// wait 2 frame periods for packet to be transmitted/received
frame_wait(2);

// Check SDMA register
// Expected value = 0x6440, if not, it means there was error
read_reg(SDMA, data);

// Check to see how many entries are in the Tx done queue (distance from TDQRP to TDQWP)
// Expected value is 1 - one entry in the Tx done queue corresponding to the packet that was sent
read_reg(TDQRP, rd_ptr);
read_reg(TDQWP, wr_ptr);
if (wr_ptr >= rd_ptr)

cnt = wr_ptr - rd_ptr;
else

cnt = tdq_end_idx + 1 - rd_ptr + wr_ptr;

// Check Tx done queue descriptor
// Expected value = 0x0003000
// Bits 15-0 indicates the descriptor pointer
// Bits 23-16 indicate the channel number, it should be 3 in this example
// Bits 28-26 indicate the packet status, all 0 means the packet transmission is complete and the
// descriptor pointer field corresponds to the first descriptor in the HDLC packet that has been
// transmitted
rd_dword(tdq_base_addr + rd_ptr*4, tdq_entry);

// Advance the Tx done queue read pointer
if (wr_ptr = tdq_end_idx)

wr_ptr = 0;
else

wr_ptr = wr_ptr + 1;
write_reg(TDQRP, wr_ptr);

// Check the Rx large free queue to see how many Rx buffers are in the queue (distance from
// RFQLBRP to RFQLBWP)
// Expected number is 0 since the queue had 1 buffer before the packet was received and packet
// reception required 1 buffer
read_reg(RFQLBRP, rd_ptr);
read_reg(RFQLBWP, wr_ptr);
if (wr_ptr >= rd_ptr)

cnt = wr_ptr - rd_ptr;
else

cnt = rfq_end_idx + 1 - rd_ptr + wr_ptr;

// Check Rx done queue to see if any packets were received (distance from RDQRP to RDQWP)
// Expected value is 1 - one entry in the Rx done queue entry corresponding to the one packet that
// should have been received
read_reg(RDQRP, rd_ptr);
read_reg(RDQWP, wr_ptr);
if (wr_ptr >= rd_ptr)

cnt = wr_ptr - rd_ptr;
else

cnt = rdq_end_idx + 1 - rd_ptr + wr_ptr;

// Check the Rx done queue descriptor
// Expected value = 0x40030000,
// Bits 15-0 indicates the descriptor pointer
// Bits 23-16 indicate the channel number, it should be 3 in this example
// Bits 26-24 indicate the buffer count, all 0 means that a complete packet has been received
rd_dword(rdq_base_addr + 8 * rd_ptr, rdq_entry);

// Check the corresponding Rx descriptor (4 dwords)
// dword 0 expected value = 0x10001000 the Rx buffer address
// dword 1 expected value = 0x80140000
// Bits 15-0 is the next descriptor pointer
// Bits 28-16 is the number of bytes stored in the data buffer
// Bits 31-29 indicates buffer status
// dword 2 excepted value = 0x000B7503
// Bits 7-0 indicates HDLC channel number (should match TDQ entry channel)
// Bits 31-8 indicates the timestamp (can vary)
rdscr_idx = rdq_entry & 0x0000FFFF;
rd_dword(rdscr_base_addr + 16 * rdscr_idx, rdscr_dword0);
rd_dword(rdscr_base_addr + 16 * rdscr_idx + 4, rdscr_dword1);
rd_dword(rdscr_base_addr + 16 * rdscr_idx + 8, rdscr_dword2);

// Check the data in the Rx buffer
// 16 bytes of data + 4-byte CRC
// Expected values = 0x01234567
// 0x89ABCDEF
// 0x02468ACE
// 0x13579BDF
// 0x05127B09 (4-byte CRC)
byte_count = (rdscr_dword1 >> 16) & 0x00001FFF;
for (addr = rdscr_dword0, addr < rdscr_dword0 + byte_count; addr = addr + 4)

rd_dword(addr, data);

// Advance the Rx done queue read pointer
if (rd_ptr = rdq_end_idx)

rd_ptr = 0;
else

rd_ptr = rd_ptr + 1;
write_reg(RDQRP, rd_ptr);

結論

このアプリケーションノートでは、DS31256のコンフィギュレーションモードで単一のT1ポートを設定する方法を示しました。コード例によって、DS31256のプログラム(設定)方法およびデータパケットを送受信する方法を詳細に(ステップバイステップで)示しました。

当社のHDLCコントローラ製品について他にも質問がある場合は、テレコムアプリケーションサポートチームまでお問い合わせください。