要約
このアプリケーションノートでは、HDLCコントローラDS31256のブリッジモードにおいて単一のT1ポートを設定する方法を実例に沿って示します。エンドユーザアプリケーションへの応用が容易になるよう、デバイスの設定、パケットの組立て、送信、受信、およびチェックをループバックモードで行う方法を理解するためのコード例を、ステップバイステップで解説します。
DS31256のローカルバスは、次の2種類のモードで動作可能です。
- PCIブリッジモードPCIブリッジモードでは、PCIバス上のホストがローカルバスにアクセスすることができます。PCIバスはDS31256の制御と監視、およびパケットデータの転送に使用されます。DS31256がPCIバスからのデータをローカルバスにマッピングします(詳細についてはDS31256のデータシートの11.1.1項を参照してください)。
- コンフィギュレーションモード
コンフィギュレーションモードの使い方の詳細については、アプリケーションノート2871 「HDLCコントローラDS31256のステップバイステップの設定—コンフィギュレーションモード」を参照してください。
図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つを使用してホストメモリに書き込まれます。 | |||||||||||||||||||||||||||||||
- | ホストメモリは以下の構成になっています。
|
コード例中の関数呼出しの定義
可読性を向上させるため、この例のコードではいくつかの関数呼出しを使用しています。これらの関数の定義を以下に示します。
- 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)
Count数のフレーム期間に等しいディレイを提供する(1回のフレーム期間は125µs)
入力:
出力:なし
count = 待機するフレーム期間の回数
T1設定モードのコード例
このコード例は、以下のステップで構成されています。
- DS31256のリセット
- DS31256の設定
- HDLCチャネルのイネーブル
- HDLCチャネルのループバックモードへの移行
- データバケットのキュー、送信、受信、およびチェック
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);
オフセット/アドレス | 略号 | レジスタ名 | データシートの項目 |
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);
オフセット/アドレス | 略号 | レジスタ名 | データシートの項目 |
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);
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の設定は、以下のステップで構成されます。
- PCIレジスタの設定
- レイヤ1レジスタの設定
- HDLCレジスタの設定
- FIFOレジスタの設定
- 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レジスタの設定
PCIブリッジモードでは、PCIバス上のホストがローカルバスにアクセスすることができます。PCIバスはDS31256の制御と監視、およびパケットデータの転送に使用されます。DS31256はPCIバスからのデータをローカルバスにマッピングします(DS31256のデータシートの10項を参照してください)。
オフセット/アドレス | 略号 | レジスタ名 | データシートの項目 |
0x004/0A04 | PCMD0 | PCI Command Status 0 | 10.2 |
// Map DS31256 Configuration Registers to a PCI bus base address
write_reg(PDCM, 32'h80000000);
// PCI command/status register 0 - controls DS31256 DMA functionality
// Set Bit 1 = 1 to enable accesses to internal device configuration registers through PCI bus
//(required for Bridge mode)
// Set Bit 2 = 1 to allow the 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 the PSERR pin
write_reg(PCMD0, 32'h00000146);
レイヤ1レジスタの設定
DS31256の各ポートは、以下のようないくつかの機能を実行するレイヤ1コントローラを備えています。
- A入力データおよび出力データに対するHDLCチャネル番号の割り当て
- チャネル化ローカルおよびネットワークループバック
- チャネル化選択(64kps、56kps、またはデータなし)
- チャネル化送信DS0チャネルのオール1フィル
- BERT機能との間におけるデータのルーティング
- V.54ループパターンディテクタへのデータのルーティング
オフセット/アドレス | 略号 | レジスタ名 | データシートの項目 |
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の生成と検査
- データ反転とビット反転
オフセット/アドレス | 略号 | レジスタ名 | データシートの項目 |
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のパケット送受信をイネーブルする必要があります。
- ポート送信および受信設定RAMでのHDLCチャネルのイネーブル(HDLCチャネルイネーブル)
- 受信空きキューの初期化(DMAディスクリプタのロード)
- DS31256の送信DMAおよび受信DMAのイネーブル(DMAのイネーブル)
- HDLCチャネルの送信および受信DMAのイネーブル
- レイヤ1のポートデータ送信のイネーブル(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);
}
受信空きキューの初期化
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)
else
// 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)
else
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)
else
// 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)
else
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)
else
// 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)
else
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)
else
// 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)
else
// 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
// 0x02468ACE
// 0x13579BDF
// 0x05127B09 (4-byte CRC)
byte_count = (rdscr_dword1 >> 16) & 0x00001FFF;
for (addr = rdscr_dword0, addr < rdscr_dword0 + byte_count; addr = addr + 4)
// Advance the Rx done queue read pointer
if (rd_ptr = rdq_end_idx)
else
write_reg(RDQRP, rd_ptr);
結論
このアプリケーションノートでは、DS31256のブリッジモードで単一のT1ポートを設定する方法を示しました。コード例によって、DS31256のプログラム(設定)方法およびデータパケットを送受信する方法を詳細に(ステップバイステップで)示しました。
マキシムのHDLCコントローラ製品について他にも質問がある場合は、テレコムアプリケーションサポートチームまでお問い合わせください。
この記事に関して
製品
{{modalTitle}}
{{modalDescription}}
{{dropdownTitle}}
- {{defaultSelectedText}} {{#each projectNames}}
- {{name}} {{/each}} {{#if newProjectText}}
- {{newProjectText}} {{/if}}
{{newProjectTitle}}
{{projectNameErrorText}}