⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adam.c

📁 altera epxa1的例子程序
💻 C
📖 第 1 页 / 共 2 页
字号:
// file: adam.c
//
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "..\..\stripe.h"
#include "mode_ctrl00.h"
#include "adam.h"

#include "serial.h"     // for readtimeXs()
#include "utils.h"      // only for debug, dump_pkt(), decode_pkt()



//============================================

int eth_descriptor_initialise(type_eth_descriptors *eth);

//============================================
// globals
// this buffer is used to copy a fragmented received packet into so that
// a single buffer can be passed up the stack
UCHAR rbuf[2000];
//UCHAR rbuf[1518];
//============================================



int eth_config(type_eth_descriptors *eth)
{
    int i;

/*
    debug
    00 - none
    01 - T/R
    02 - T: tbuf = 0x01234567, tlen = 0x1234 / R: ...
    04 - dump buffer
    08 - decode buffer
*/
    eth->debug = 0x0;

    // special multicast address for control frames
    eth->macaddr[0] = 0x01;
    eth->macaddr[1] = 0x80;
    eth->macaddr[2] = 0xc2;
    eth->macaddr[3] = 0x00;
    eth->macaddr[4] = 0x00;
    eth->macaddr[5] = 0x01;

    // local MAC address
    eth->macaddr[6] = 0x00;
    eth->macaddr[7] = 0xe8;
    eth->macaddr[8] = 0xca;
    eth->macaddr[9] = 0x11;
    eth->macaddr[10] = 0xba;
    eth->macaddr[11] = 0x01;

    // default pause frame
    eth->macaddr[0x78] = 0x88;   // special MAC control type_len field
    eth->macaddr[0x79] = 0x08;
    eth->macaddr[0x7a] = 0x00;   // pause op_code, 0001
    eth->macaddr[0x7b] = 0x01;
    eth->macaddr[0x7c] = 0x12;   // pause duration, 1234
    eth->macaddr[0x7d] = 0x34;
    eth->macaddr[0x7e] = 0x00;
    eth->macaddr[0x7f] = 0x00;

    for (i=12; i<0x78; i++) eth->macaddr[i] = 0;
    eth->nummacs  = 2;
//    eth->arcmode = UNICAST | BROADCAST;
    eth->arcmode = UNICAST | BROADCAST | MULTICAST;
//    eth->arcmode = BROADCAST | PROMISCUOUS | MULTICAST | UNICAST;
    eth->fullduplex = 1;


    eth->tx_desc = TX_DESC;
    eth->tx_desc_done = TX_DESC;
    eth->rx_bl_desc = RX_BL_DESC;
    eth->rx_fda_desc = RX_FDA_DESC;

    eth->tx_desc_base = TX_DESC;
    eth->tx_num_descs = NUM_TX_DESC;
    eth->tx_num_buffs = NUM_TX_BUFFS;

    eth->rx_bl_desc_base = RX_BL_DESC;
    eth->rx_buffer_base = RX_BUFFER;
    eth->rx_buffer_length = RX_BUFFER_LEN;
    eth->rx_num_descs = NUM_RX_DESC;
    eth->rx_num_buffs = NUM_RX_BUFFS;

    eth->rx_fda_desc_base = RX_FDA_DESC;
    eth->rx_fda_limit = RX_FDA_LIMIT;

    return 0;
}

int eth_init(type_eth_descriptors * eth)
{
    int i;
    ULONG mask;

    eth_descriptor_initialise(eth);

    // set up ARC
    for (i=0; i<0x80; i+=4)
    {
        write_csr(MAC_ARC_ADDR, i);
        write_csr(MAC_ARC_DATA, ((eth->macaddr[i+0] & 0xff) << 24) | ((eth->macaddr[i+1] & 0xff) << 16) | ((eth->macaddr[i+2] & 0xff) << 8) | ((eth->macaddr[i+3] & 0xff) << 0));
    }
    // seup up MC#1, MC#2
    for (i=0x80; i<0x84; i+=4)
    {
        write_csr(MAC_ARC_ADDR, i);
        write_csr(MAC_ARC_DATA, 0x00000000);
    }
    mask = 0;
    for (i=0; i<eth->nummacs; i++)
        mask = (mask << 1) | 1;
    write_csr(MAC_ARC_ENA, mask);
    write_csr(MAC_ARC_CTL, eth->arcmode);

    // set up mac
    write_csr(MAC_MAC_CTL,     0x00000100 | ((eth->fullduplex) ? 8 : 0));        // default + duplex
    write_csr(MAC_TX_CTL,      0x00007f01);         // set TxEN, enable all interrupts
    write_csr(MAC_RX_CTL,      0x00006f91);         // set RxEN, enable all interrupts, strip crc, disable LenErr

    // set up dma
   //HB write_csr(DMA_CTL,         0x00000020);         // burst length = 8 cycles
    write_csr(DMA_CTL,         0x00000040);         // burst length = 16 cycles
    write_csr(DMA_TX_THRESH,   0x00000020);
    write_csr(DMA_TX_TPOLLCTR, 0x00000001);
    write_csr(DMA_RX_FRAGSIZE, 0x00000000);
    write_csr(DMA_INT_EN,      0x00000fff);
    write_csr(DMA_FDA_BASE,    eth->rx_fda_desc_base);
    write_csr(DMA_FDA_LIMIT,   eth->rx_fda_limit - (0x10 + (8*(0x600/RX_BUFFER_LEN))));  // max # buffers req'd for packet

    // enable irq - must be in supervisor mode ...
    __asm{mrs     r0,CPSR};
    __asm{bic     r0, r0, #0x80};
    __asm{msr     CPSR_c, r0};

    // This kicks off TxPro, so set up other registers first.
    write_csr(DMA_TX_FRMPTR, eth->tx_desc_base);        // transmit frame pointer

    // This kicks off RxCon, so set up other registers first.
    write_csr(DMA_BLFRMPTR, eth->rx_bl_desc_base);      // buffer list frame pointer

	return 0;
}



int eth_descriptor_initialise(type_eth_descriptors *eth)
{
    ULONG   rxbuff;
    int i,j;

    // set up the tx descriptors
    eth->tx_desc = eth->tx_desc_base;
    // initialise all NUM_TX_DESC frame descriptors, retain own bit
    for (i=0; i<eth->tx_num_descs; i++)
    {
        // initialise the frame descriptor
        *(volatile ULONG *)(eth->tx_desc+0x00) = eth->tx_desc+0x10 + (8*eth->tx_num_buffs);         // fdnext
        *(volatile ULONG *)(eth->tx_desc+0x04) = 0x00000000;       // fdsystem[32] - not used
        *(volatile ULONG *)(eth->tx_desc+0x08) = 0x00000000;       // fdstat
        *(volatile ULONG *)(eth->tx_desc+0x0c) = 0x00010000;       // fdctl[16], (fdlength[16] not used on tx)

        // no need to initialise the transmit buffer descriptors here
        // this is done by the send_packet routine

        // there may be NUM_TX_BUFFS buffers per descriptor
        eth->tx_desc += 0x10 + (8*eth->tx_num_buffs);
    }
    // create a loop in the descriptors
    *(volatile ULONG *)(eth->tx_desc-(0x10 + (8*eth->tx_num_buffs))) = eth->tx_desc_base;           // fdnext

    // no need to initialise transmit buffers



    // set up the rx ram
    eth->rx_bl_desc = eth->rx_bl_desc_base;
    rxbuff = eth->rx_buffer_base;

    // initialise all NUM_RX_DESC frame descriptors
    for (i=0; i<eth->rx_num_descs; i++)
    {
        // free buffer descriptor
        *(volatile ULONG *)(eth->rx_bl_desc+0x00) = eth->rx_bl_desc+0x10 + (8*eth->rx_num_buffs);   // fdnext
        *(volatile ULONG *)(eth->rx_bl_desc+0x04) = eth->rx_bl_desc;                                // fdsystem - identify descriptor
        *(volatile ULONG *)(eth->rx_bl_desc+0x08) = 0x00000000;                                     // fdstat
        *(volatile ULONG *)(eth->rx_bl_desc+0x0c) = 0x80000000 | eth->rx_num_buffs;                 // fdctl_fdlength

        // free buffer list
        for (j=0; j<eth->rx_num_buffs; j++)
        {
            *(volatile ULONG *)(eth->rx_bl_desc+0x10+(8*j)) = rxbuff;
            *(volatile ULONG *)(eth->rx_bl_desc+0x14+(8*j)) = 0x80000000 | eth->rx_buffer_length;
            rxbuff += eth->rx_buffer_length;
        }

        // there may be NUM_RX_BUFFS buffers per descriptor
        eth->rx_bl_desc += 0x10 + (8*eth->rx_num_buffs);
    }
    // create a loop in the descriptors
    *(volatile ULONG *)(eth->rx_bl_desc-(0x10 + (8*eth->rx_num_buffs))) = eth->rx_bl_desc_base;     // fdnext



    // initialise the fda descriptors
    eth->rx_fda_desc = eth->rx_fda_desc_base;
    for (i=0; i<eth->rx_fda_limit; i+=4)
    {
        *(volatile ULONG *)(eth->rx_fda_desc+i) = 0xffffffff;
    }

    // these are global - make sure they start at the beginning
    eth->tx_desc = eth->tx_desc_base;
    eth->tx_desc_done = eth->tx_desc_base;
    eth->rx_fda_desc = eth->rx_fda_desc_base;
    return 0;
}







int eth_transmit(type_eth_descriptors *eth, void *tbuf, int tlen, int wait)
{
	ULONG rdata;
	ULONG tstart, tnow;

    if (eth->debug & 0x01) printf("T");
    if (eth->debug & 0x02) printf("T: tbuf = 0x%08lx, tlen = 0x%x, eth->tx_desc = 0x%08lx\n",(ULONG)tbuf, tlen, eth->tx_desc);
    if (eth->debug & 0x04) dump_pkt((pkt_type *)tbuf, tlen);
    if (eth->debug & 0x08) decode_pkt((pkt_type *)tbuf, tlen);

    readtimeus();

    // check for line plugged in ????

    // check status of any previously transmitted packets
    eth_transmit_status(eth);

    // check descriptor is not owned by core
    if (*(volatile ULONG *)(eth->tx_desc+0x0c) & 0x80000000)
    {
//        printf("*** TX_DESCRIPTOR_QUEUE FULL - dropping packet, eth->tx_desc=%lx, eth->tx_desc[0x0c]=%lx ***", eth->tx_desc, *(volatile ULONG *)(eth->tx_desc+0x0c));
        return -1;
    }

    // set up the transmit descriptors
    // use only 1 buffer per packet
    *(volatile ULONG *)(eth->tx_desc+0x10) = (ULONG)tbuf;                 // set pointer to data
    *(volatile ULONG *)(eth->tx_desc+0x14) = 0x80000000 | tlen;           // set own bit, set data length
    *(volatile ULONG *)(eth->tx_desc+0x18) = (ULONG)0;                    // set pointer to data
    *(volatile ULONG *)(eth->tx_desc+0x1c) = 0x80000000 | 0;              // set own bit, set data length

    // transmit frame descriptor - must be aligned on 16 byte boundaries
    *(volatile ULONG *)(eth->tx_desc+0x0c) = 0x80010000;                  // set own bit, set 1 buffer descriptors
    // move on the frame descriptor
    eth->tx_desc = *(volatile ULONG *)(eth->tx_desc + 0x00);

    // give the core a kick, rather than wait for the polling
    rdata = read_csr(DMA_CTL);
    write_csr(DMA_CTL, (rdata & 0xffffffff) | 0x00010000);

    // !! beware that buffer should not be freed until packet has actually been transmitted
    // or at least been read by the DMA controller

    // be afraid of re-using tx buffers ...

    // could wait for desc to be read by dma..
    tstart = readtimems();
    tnow = readtimems() - tstart;
    // timeout after 100ms
    if (wait)
    {
        while (eth_transmit_status(eth) && (tnow < 100)) tnow = readtimems() - tstart;
        if (tnow >= 100) printf("*** eth_transmit() - transmit timeout ***\n");
    }

	return 0;
}



// we need a routine to check the status of transmitted packets
// the eth_transmit() routine sets the own bit
// the controller clears it, and sets the tx_status
// we need to monitor this and check the status

// when should this be called ???
// - could call it from tx_completed interrupt
// - could call it before sending a packet
// - could call it after sending a packet

int eth_transmit_status(type_eth_descriptors *eth)
{
    ULONG stat;

    // check if the q is empty
    while (eth->tx_desc_done != eth->tx_desc)
    {
        // check the own bit
        if (!(*(volatile ULONG *)(eth->tx_desc_done+0x0c) & 0x80000000))
        {
            // get the status
            stat = *(volatile ULONG *)(eth->tx_desc_done+0x08);
            if (stat & 0x1350)
            {
                printf("\n*** tx error ***\n");
                printf("MAC_TX_STAT = %08lx\n", stat);
                if (stat & 0x0010) printf("*** excessive collisions ***\n");
                if (stat & 0x0040) printf("*** paused ***\n");
                if (stat & 0x0100) printf("*** underrun ***\n");
                if (stat & 0x0200) printf("*** excessive deferrals ***\n");
                if (stat & 0x1000) printf("*** late collision ***\n");
                if (stat & 0x10000) printf("*** MAC control packet ***\n");
                if (stat & 0x20000) printf("*** MAC control PAUSE packet ***\n");
            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -