リンク層 – ソフトウェアドライバ

jp
tcpip_layer1

インターネット・プロトコル・スイート

リンク層とインターネット層を接続するLow-level APIを実装します。Low-level APIは、FPGAに実装されたEthernet MAC CoreとLocal Memoryをアクセスし、Ethernet Frameの送受信を行います。

APIの仕様

Ethernet Frameの送信
void ether_write_frame(int flen,unsigned char *fbuf);
  • 説明
    • fbufに格納された、長さflenのByteデータをEthernet Frameとして送信します。
  • 戻り値
    • なし
Ethernet Frameの受信
int ether_read_frame(unsigned char *fbuf);
  • 説明
    • 受信したEthernet Frameを、fbufにByteデータとして格納します。
  • 戻り値
    • fbufに格納したByteデータの長さ。

Ethernet Frameの送信フロー

Ethernet Frameの送信は、以下の手順で行います。

  1. FrameデータをCPUからFPGA内Local Memoryに転送
  2. Ethernet MAC CoreのMode RegisterのTXEN bitを1に設定
  3. Ethernet MAC CoreのTx Buffer DescriptorのTXPNTに、Frameデータを格納したLocal Memoryのアドレスを設定
  4. Tx Buffer DescriptorのRD bitを1に設定
  5. 送信完了のインタラプトを待つ
  6. インタラプトを解除
ether_pic2

Ethernet Frameの送信フロー

FrameのCRCは、Ethernet MAC CoreからPHYへの転送時に計算されて付加されます。Tx Buffer Descriptorが有効化されると、Ethernet MAC CoreはTx Buffer Descriptorレジスタの設定に従って、送信データをLocal Memoryから読み出し、Ethernet FrameとしてPHYに出力します。

送信用API ether_write_frameの実装

コード実装は以下の通りです。

void ether_write_frame(int flen,unsigned char *fbuf) {
     int i, flush;
     struct st_txdesc_l txl;
     unsigned int a;
     // Tx Buffer Descriptorの設定
     txl.LONG = 0;
     txl.IRQ = 1; // Interrupt Request Enable
     txl.PAD = 1; // PAD Enable
     txl.CRC = 1; // CRC Enable
     txl.WR = 1; // Wrap 
     // 送信データの設定
     a = ETHER_BUF_TX_BASE; // Local Memoryの先頭アドレス
     for (i=0; i< flen;i++) {
         if (((a+i) % 4) == 3) flush = 1;
         else flush = 0;
         if (i == (flen -1)) flush = 1; // final data
         ether_write_byte(a+i, fbuf[i], flush); // Byte単位でFrameデータをLocal Memoryにセット
     }

     // set TxBD ready for descriptor 0
     txl.RD = 1; // Tx Buffer Descriptorを有効化
     (*(volatile unsigned int *)(ETHER_BD_BASE)) = txl.LONG;
 }

Ethernet Frameの受信フロー

Ethernet Frameの受信は、以下の手順で行います。

  1. Ethernet MAC CoreのMode RegisterのRXEN bitを1に設定
  2. Ethernet MAC CoreのRx Buffer DescriptorのRXPNTに、Frameデータを格納するLocal Memoryのアドレスを設定
  3. Ethernet MAC CoreのRx Buffer DescriptorのE(Empty)bitを1に設定
  4. 受信完了インタラプトを待つ
  5. インタラプトを解除
  6. FrameデータをLocal MemoryからCPUに転送
ether_pic3

Ethernet Frameの受信フロー

PHYからEthernet Frameを受信すると、Ethernet MAC CoreはRx Buffer Descriptorレジスタの設定に従って、Ethernet FrameをLocal Memoryに格納します。受信Frameは、Rx Buffer DescriptorのRXPNTが示すLocal Memoryのアドレスに格納されます。FrameのCRCは、Local Memoryへの格納時に削除されます。

受信用API ether_read_frameの実装

コード実装は以下の通りです。

 int ether_read_frame(unsigned char *fbuf) {
     int i,j,p, size,s;
     unsigned int x;
     struct st_rxdesc_l rxl;

     rxl.LONG = (*(volatile unsigned int *)(ETHER_BD_RX_BASE+ether_cur_rx_bd*8));
     size = rxl.LEN; // 受信FrameのByte長を獲得
     p =0;
     s = size /4;
     if ((size %4 ) != 0) s++;
     for (i = 0; i< s; i++) { // 32bit単位でLocal Memoryからデータをリード
         x =(*(volatile unsigned int *)(ETHER_BUF_RX_BASE+ether_cur_rx_bd*ETHER_BUFFER_SIZE+i*4));
         for (j=0;j <4; j++) {
             fbuf[p] = (x > (3-j)*8)&0xff; // fbufにByte単位で格納
             p++;
         }
     }

     rxl.LEN = 0;
     rxl.E = 1; // Rx Buffer DescriptorのEmpty bitをセット

     (*(volatile unsigned int *)(ETHER_BD_RX_BASE+ether_cur_rx_bd*8)) = rxl.LONG;

     if (ether_cur_rx_bd == (ETHER_MAX_RX_BD-1))
         ether_cur_rx_bd = 0;
     else
         ether_cur_rx_bd++;

     return size; // Frameのデータサイズを返す
 }

タイトルとURLをコピーしました