DS31256 HDLC控制器的配置步驟—橋接模式
本應(yīng)用筆記提供了怎樣配置橋接模式下DS31256 HDLC控制器T1端口的例子。文章提供了一個(gè)實(shí)際例程,以方便最終用戶使用,幫助他們理解怎樣在環(huán)回模式下配置器件,構(gòu)建數(shù)據(jù)包,并進(jìn)行傳送、接收和檢查。
DS31256中的本地總線可以工作在兩種模式下:
- PCI橋接模式
- 配置模式
利用PCI橋接模式,PCI總線上的主機(jī)可以訪問本地總線。PCI總線用于控制并監(jiān)視DS31256,發(fā)送分組數(shù)據(jù)。DS31256將數(shù)據(jù)從PCI總線映射到本地總線(請(qǐng)參考DS31256數(shù)據(jù)資料的11.1.1節(jié),了解詳細(xì)信息)。
關(guān)于使用配置模式的詳細(xì)信息,請(qǐng)參考應(yīng)用筆記2871:“DS31256 HDLC控制器的配置步驟—配置模式”。
圖1.
這一例子具有以下配置:
- | DS31256的端口1是通道化T1端口。所有其他端口都沒有使用。 | |||||||||||||||||||||||||||||||
- | DS31256端口1 DS0的0-3被分配給HDLC通道3。端口1 DS0所有其他端口都沒有分配。 | |||||||||||||||||||||||||||||||
- | DS31256的HDLC通道3被分配給4個(gè)Rx FIFO模塊、4個(gè)Tx FIFO模塊、一個(gè)Rx FIFO高水線3、一個(gè)Tx低水線1。 | |||||||||||||||||||||||||||||||
- | 使用一個(gè)Tx緩沖,一個(gè)Tx描述符,一個(gè)Tx未決隊(duì)列輸入構(gòu)建主機(jī)存儲(chǔ)器中的16字節(jié)數(shù)據(jù)包。由于DS31256處于環(huán)回模式,當(dāng)傳送數(shù)據(jù)包時(shí),DS31256也會(huì)收到它。使用一個(gè)Rx緩沖、一個(gè)Rx描述符,一個(gè)Rx完成隊(duì)列輸入,將接收到的數(shù)據(jù)包寫入主機(jī)存儲(chǔ)器。 | |||||||||||||||||||||||||||||||
- | 主機(jī)存儲(chǔ)器進(jìn)行如下配置:
|
代碼實(shí)例函數(shù)調(diào)用定義
為提高可讀性,這個(gè)例子中的代碼使用了幾個(gè)函數(shù)調(diào)用。這些函數(shù)的定義如下:
- write_reg(address, data)
將指定的數(shù)據(jù)寫入指定的DS31256寄存器地址
輸入:
輸出:無
地址 = 數(shù)據(jù)要寫入的寄存器地址 數(shù)據(jù) = 要寫入到指定寄存器中的數(shù)據(jù)
- read_reg(address, data)
讀取DS31256指定地址寄存器中的內(nèi)容
輸入:
輸出:
地址 = 要讀取的寄存器地址
數(shù)據(jù) = 來自寄存器的數(shù)值
- write_reg_IS(address, data)
將指定的數(shù)據(jù)寫入指定的DS31256間接選擇寄存器,然后,在返回前,等待該寄存器的忙比特被清位。
輸入:
輸出:無
地址 = 數(shù)據(jù)要寫入的間接選擇寄存器 數(shù)據(jù) = 要寫入到指定寄存器的數(shù)據(jù)
函數(shù)代碼:
write_reg(address, data)
bit_check = 0x8000;
while(bit_check & 0x8000)
read_reg(address, bit_check);
- wr_dword(address, data)
將指定的32位數(shù)據(jù)寫入指定的32位主機(jī)存儲(chǔ)器地址
輸入:
輸出:無
地址 = 數(shù)據(jù)要寫入的主機(jī)存儲(chǔ)器地址 數(shù)據(jù) = 要寫入到指定存儲(chǔ)器地址的數(shù)據(jù)
- rd_dword(address, data)
從指定的32位主機(jī)存儲(chǔ)器地址讀取的32位數(shù)據(jù)
輸入:
輸出:
地址 = 要讀取的主機(jī)存儲(chǔ)器地址
數(shù)據(jù) = 從主機(jī)存儲(chǔ)器讀取的32位數(shù)據(jù)
- frame_wait(count)
提供等于幀周期數(shù)的延時(shí),幀周期為125微秒。
輸入:
輸出:無
計(jì)數(shù) = 要等待的幀周期數(shù)
T1配置模式代碼實(shí)例
這一代碼實(shí)例包括以下步驟:
- 復(fù)位DS31256
- 配置DS31256
- 使能HDLC通道
- 使HDLC通道處于環(huán)回模式
- 排列、發(fā)送、接收、檢查數(shù)據(jù)包
下面幾節(jié)提供簡(jiǎn)要說明和代碼實(shí)例,詳細(xì)介紹了這些步驟。采用了寄存器名稱而不是地址,以提高可讀性。DS31256內(nèi)部器件配置寄存器對(duì)應(yīng)的地址/偏移列在相應(yīng)的表格中。此外,縮寫Tx和Rx分別用于表示發(fā)送側(cè)和接收側(cè)。請(qǐng)參考DS31256數(shù)據(jù)資料,了解詳細(xì)信息。
復(fù)位DS31256
復(fù)位DS31256包括三步。首先,必須復(fù)位DS31256內(nèi)部寄存器,然后,DS31256內(nèi)部RAM必須置零,最后,再次復(fù)位DS31256內(nèi)部寄存器。
復(fù)位DS31256內(nèi)部寄存器
使用主復(fù)位寄存器(MRID)可以對(duì)DS31256中的所有寄存器進(jìn)行軟件復(fù)位。當(dāng)MRID寄存器的比特0被設(shè)置為1時(shí),所有內(nèi)部寄存器將被置為默認(rèn)值0。在設(shè)置器件正常工作之前,主機(jī)必須將該位置回0。
Offset/Address | Acronym | Register Name | Data Sheet Section |
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內(nèi)部RAM置零
復(fù)位芯片時(shí),DS31256內(nèi)部配置RAM并沒有被清零,因此,必須手動(dòng)清零。使用適當(dāng)?shù)臄?shù)據(jù)和DS31256間接選擇寄存器,對(duì)DS31256的每一內(nèi)部RAM進(jìn)行一系列寫操作,完成該任務(wù)。本節(jié)詳細(xì)介紹完成該任務(wù)的過程。
Offset/Address | Acronym | Register Name | Data Sheet Section |
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));
}
}
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
復(fù)位DS31256內(nèi)部寄存器
使用主復(fù)位寄存器(MRID)可以對(duì)DS31256中的所有寄存器進(jìn)行軟件復(fù)位。當(dāng)MRID寄存器的比特0被設(shè)置為1時(shí),所有內(nèi)部寄存器將被置為默認(rèn)值0。在設(shè)置器件正常工作之前,主機(jī)必須將該位置回0。
Offset/Address | Acronym | Register Name | Data Sheet Section |
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寄存器
下面幾節(jié)詳細(xì)介紹了配置這些寄存器設(shè)置。采用了幾個(gè)變量來提高可讀性,提供計(jì)算能力更強(qiáng)的代碼結(jié)構(gòu)。下面的代碼對(duì)這些變量進(jìn)行初始化:
// 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總線上的主機(jī)對(duì)本地總線進(jìn)行訪問。PCI總線用于控制和監(jiān)視DS31256,傳送分組數(shù)據(jù)。DS31256將數(shù)據(jù)從PCI總線映射到本地總線(請(qǐng)參考DS31256數(shù)據(jù)資料第10節(jié))。
Offset/Address | Acronym | Register Name | Data Sheet Section |
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層控制器,完成以下幾項(xiàng)功能,包括:
- 為輸入和輸出數(shù)據(jù)分配HDLC通道號(hào)
- 通道化本地和網(wǎng)絡(luò)環(huán)回
- 64kps、56kps、或者沒有數(shù)據(jù)通道化選擇
- 通道化發(fā)送DS0通道填充全1
- 向BERT發(fā)送和接收數(shù)據(jù)
- 將數(shù)據(jù)送入V.54環(huán)路碼型探測(cè)器
通過RP[n]CR、TP[n]CR、CP[n]RD和CP[n]RDIS寄存器,在端口上完成1層配置,其中,n是要配置的端口。
Offset/Address | Acronym | Register Name | Data Sheet Section |
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含有一個(gè)256通道HDLC控制器,完成2層功能。該控制器完成的功能包括:
- 零填充和去填充
- 標(biāo)志探測(cè)和字節(jié)對(duì)齊
- CRC產(chǎn)生和校驗(yàn)
- 數(shù)據(jù)置反和位反轉(zhuǎn)
通過RHCD、RHCDIS、THCD和THCDIS寄存器,在通道上配置HDLC控制器。
Offset/Address | Acronym | Register Name | Data Sheet Section |
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含有一個(gè)16kB發(fā)送FIFO和一個(gè)16kB接收FIFO。每一FIFO按照4 dword或者16字節(jié)被分成1024個(gè)模塊。在HDLC通道基礎(chǔ)上分配FIFO存儲(chǔ)器??梢栽O(shè)置分配給每一HDLC通道的FIFO存儲(chǔ)器的數(shù)量,最少是4個(gè)模塊,最多為1024個(gè)模塊。建立圓形鏈表,列出一組模塊,每一模塊指向鏈中的下一模塊,最后一個(gè)模塊指向第一個(gè),這樣,將FIFO存儲(chǔ)器分配給HDLC通道。鏈表中的一個(gè)模塊分配給該通道的FIFO起始模塊指針,將FIFO模塊鏈表分配給指定的HDLC通道。
在這個(gè)例子中,4個(gè)Tx FIFO模塊和4個(gè)Rx FIFO模塊被分配給HDLC通道。這個(gè)例子還使用了一個(gè)Rx FIFO高水線3,以及Tx FIFO低水線1。Rx FHFO高水線指示HDLC引擎在DMA開始向PCI總線發(fā)送數(shù)據(jù)之前,應(yīng)該將多少模塊寫入Rx FIFO。高水線設(shè)置必須在一個(gè)模塊以及相關(guān)某一通道鏈表模塊之間。Tx FIFO低水線指示在DMA開始從PCI總線獲取大量數(shù)據(jù)之前,有多少模塊應(yīng)留在Tx FIFO中。HDLC通道用于防止出現(xiàn)傳送下溢以及接收上溢所需要的FIFO存儲(chǔ)器、Rx FIFO高水線和Tx FIFO低水線數(shù)量取決于應(yīng)用程序。通過下表列出的寄存器,在HDLC通道基礎(chǔ)上,單獨(dú)配置DS31256的Tx FIFO和Rx FIFO。
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
Offset/Address | Acronym | Register Name | Data Sheet Section |
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模塊處理分組數(shù)據(jù)在FIFO模塊和PCI模塊之間的傳送。PCI模塊控制數(shù)據(jù)在DS31256和外部PCI總線之間的傳送。主機(jī)定義為CPU或者位于PCI總線上的智能控制器,由它指示DS31256怎樣處理輸入輸出數(shù)據(jù)。
這通過使用描述符來實(shí)現(xiàn),描述符定義為從主機(jī)傳送給DMA模塊以及由DMA模塊傳送給主機(jī)并經(jīng)過格式化預(yù)處理的消息。通過這些描述符,主機(jī)告知DMA要傳送的分組數(shù)據(jù)的位置和狀態(tài),把接收到的分組數(shù)據(jù)放到哪里。DMA使用這些描述符告知主機(jī),已經(jīng)傳送的分組數(shù)據(jù)的狀態(tài),以及接收到的分組數(shù)據(jù)的狀態(tài)和位置。
在接收側(cè),主機(jī)寫入自由隊(duì)列描述符,告知DMA在哪里可以放置到達(dá)分組數(shù)據(jù)。與每一自由隊(duì)列輸入相關(guān)的是接收數(shù)據(jù)緩沖位置和數(shù)據(jù)包描述符。DS31256使用接收自由隊(duì)列輸入來將接收到的分組數(shù)據(jù)寫入主機(jī)存儲(chǔ)器,它在Rx完成隊(duì)列中建立輸入。這些Rx完成隊(duì)列輸入告知主機(jī)接收到的數(shù)據(jù)的位置和狀態(tài)。請(qǐng)參考DS31256數(shù)據(jù)資料,了解詳細(xì)信息。主機(jī)必須通過寫入下表列出的所有寄存器來配置Rx DMA:
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
在發(fā)送側(cè),主機(jī)將寫入未決隊(duì)列,告知DMA哪一通道有準(zhǔn)備要發(fā)送的分組數(shù)據(jù)。與每一未決隊(duì)列描述符相關(guān)的是一個(gè)或者多個(gè)發(fā)送數(shù)據(jù)包描述符鏈表,由它描述了分組數(shù)據(jù)。每一發(fā)送數(shù)據(jù)包描述符還有一個(gè)發(fā)送數(shù)據(jù)緩沖指針,含有HDLC數(shù)據(jù)包的實(shí)際數(shù)據(jù)負(fù)載。
DS31256處理發(fā)送未決隊(duì)列描述符輸入時(shí),它建立發(fā)送完成隊(duì)列描述符隊(duì)列輸入。完成發(fā)送一個(gè)完整的數(shù)據(jù)包或者DS31256所配置的數(shù)據(jù)緩沖后,DMA將寫入完成隊(duì)列。通過這些完成隊(duì)列描述符,DMA告知主機(jī)關(guān)于輸出分組數(shù)據(jù)的狀態(tài)。請(qǐng)參考DS31256數(shù)據(jù)資料,了解詳細(xì)信息。主機(jī)必須通過寫入下表列出的所有寄存器來配置Tx DMA:
Offset/Address | Acronym | Register Name | Data Sheet Section |
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通道。除了已經(jīng)闡述的配置步驟之外,必須完成以下步驟來使能DS31256數(shù)據(jù)包傳送和接收:
- 使能端口Tx和Rx配置RAM中的HDLC通道(使能HDLC通道)
- 初始化Rx自由隊(duì)列(裝入DMA描述符)
- 針對(duì)DS31256使能Tx DMA和Rx DMA (使能DMA)
- 使能HDLC通道Tx和Rx DMA
- 使能1層的端口數(shù)據(jù)傳送(打開HDLC通道)
使能端口Tx和Rx配置RAM中的HDLC通道
Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
}
初始化Rx自由隊(duì)列
在DS31256將DMA接收到的數(shù)據(jù)包從其內(nèi)部FIFO發(fā)送到主機(jī)存儲(chǔ)器之前,主機(jī)必須告知DS31256把數(shù)據(jù)放到哪里。這通過Rx自由隊(duì)列完成。Rx自由隊(duì)列中的每一輸入都含有指向Rx數(shù)據(jù)緩沖和Rx數(shù)據(jù)包描述符索引的指針。這一例子使用了一個(gè)Rx自由隊(duì)列輸入。該輸入含有一個(gè)Rx自由隊(duì)列大緩沖和一個(gè)Rx數(shù)據(jù)包描述符。DS31256 Rx大數(shù)據(jù)緩沖容量被設(shè)置為256字節(jié)(RLBS = 256)。此外,DS31256被配置為使用4字節(jié)CRC,將Rx CRC寫入Rx數(shù)據(jù)緩沖。因此,一個(gè)Rx大數(shù)據(jù)緩沖可以支持252字節(jié)的分組數(shù)據(jù)。
Offset/Address | Acronym | Register Name | Data Sheet Section |
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 Tx和Rx DMA
Offset/Address | Acronym | Register Name | Data Sheet Section |
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通道Tx和Rx
Offset/Address | Acronym | Register Name | Data Sheet Section |
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層的端口數(shù)據(jù)傳輸
Offset/Address | Acronym | Register Name | Data Sheet Section |
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通道進(jìn)入環(huán)回模式
完成通道配置后,使能它需要大約5個(gè)幀周期,即625μs,使DS31256內(nèi)部邏輯完成向新配置的轉(zhuǎn)換。轉(zhuǎn)換完成后,HDLC通道可以進(jìn)入環(huán)回模式,這樣,通道上傳送的所有數(shù)據(jù)也會(huì)在該通道上接收到。在5個(gè)幀等待周期之前使HDLC通道進(jìn)入環(huán)回模式會(huì)導(dǎo)致無用數(shù)據(jù)寫入通道的Rx FIFO。Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
排列、發(fā)送、接收、檢查數(shù)據(jù)包
完成DS31256初始化之后,可以開始發(fā)送和接收數(shù)據(jù)。由于DS31256處于環(huán)回模式,HDLC通道傳送的所有數(shù)據(jù)也會(huì)在該通道上接收到。本節(jié)將討論構(gòu)建主機(jī)存儲(chǔ)器中數(shù)據(jù)包的過程,以及數(shù)據(jù)的發(fā)送、接收和結(jié)果檢查。下面幾節(jié)詳細(xì)介紹這一過程。構(gòu)建主機(jī)存儲(chǔ)器中的數(shù)據(jù)包
這一個(gè)例子將發(fā)送一個(gè)16字節(jié)數(shù)據(jù)包。在數(shù)據(jù)包發(fā)送之前,必須在主機(jī)存儲(chǔ)器中構(gòu)建它。此外,也必須在主機(jī)存儲(chǔ)器中構(gòu)建對(duì)應(yīng)的Tx數(shù)據(jù)包描述符。下面的代碼詳細(xì)介紹了這些任務(wù)。// 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);
數(shù)據(jù)包發(fā)送和接收
為完成數(shù)據(jù)包發(fā)送,Tx描述符必須放在發(fā)送未決隊(duì)列中,然后,必須遞增發(fā)送未決隊(duì)列寫指針(TPQWP)。當(dāng)DS31256探測(cè)到未決隊(duì)列不空(TPQWP不等于TPQRP)時(shí),它將開始處理隊(duì)列輸入,并發(fā)送數(shù)據(jù)包。Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
}
檢查結(jié)果
等待足夠的時(shí)間周期以完成數(shù)據(jù)包發(fā)送和接收后,可以進(jìn)行幾項(xiàng)檢查,確定數(shù)據(jù)包發(fā)送和接收是否成功。以下代碼詳細(xì)說明了這幾項(xiàng)檢查。Offset/Address | Acronym | Register Name | Data Sheet Section |
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);
評(píng)論
查看更多