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

📄 5272fec.c

📁 NXPl788上lwip的无操作系统移植,基于Embest开发板
💻 C
📖 第 1 页 / 共 2 页
字号:
        {
            mcf5272->txbd_a[i].flags = (u16_t) (MCF5272_FEC_TX_BD_R |
                                                (mcf5272->txbd_a[i].flags & MCF5272_FEC_TX_BD_W) |
                               ((i == tx_insert_eof) ? (MCF5272_FEC_TX_BD_L | MCF5272_FEC_TX_BD_TC) : 0));
            if (i != tx_insert_sof)
                DEC_TX_BD_INDEX(i);
            else
                break;
        } while (1);
        INC_TX_BD_INDEX(tx_insert_eof);
        mcf5272->tx_insert = tx_insert_eof;
#ifdef LINK_STATS
        lwip_stats.link.xmit++;
#endif        
	/* Indicate that there has been a transmit buffer produced */
	MCF5272_WR_FEC_TDAR(imm,1);
        sys_arch_unprotect(old_level);
    }
    return ERR_OK;
}

/*-----------------------------------------------------------------------------------*/
static void
eth_input(struct pbuf *p, struct netif *netif)
{
    /* Ethernet protocol layer */
    struct eth_hdr *ethhdr;
    mcf5272if_t *mcf5272 = netif->state;

    ethhdr = p->payload;
    
    switch (htons(ethhdr->type)) {
      case ETHTYPE_IP:
        etharp_ip_input(netif, p);
        pbuf_header(p, -14);
        netif->input(p, netif);
        break;
      case ETHTYPE_ARP:
        etharp_arp_input(netif, mcf5272->ethaddr, p);
        break;
      default:
        pbuf_free(p);
        break;
    }
}

/*-----------------------------------------------------------------------------------*/
static void
arp_timer(void *arg)
{
  etharp_tmr();
  sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
}

/*-----------------------------------------------------------------------------------*
 * Function called by receive LISR to disable fec rx interrupt
 *-----------------------------------------------------------------------------------*/
static void
mcf5272_dis_rx_int(void)
{
    mcf5272if_t *mcf5272 = mcf5272if;
    MCF5272_IMM *imm = mcf5272->imm;
    u32_t value;

    value = MCF5272_RD_FEC_IMR(imm);
    /* Clear rx interrupt bit */
    MCF5272_WR_FEC_IMR(imm, (value & ~MCF5272_FEC_IMR_RXFEN));
    return;
}

/*-----------------------------------------------------------------------------------*/
static void
mcf5272fec_rx(void)
{
    /* This is the receive ISR. It is written to be a high-level ISR. */
    u32_t old_level;
    mcf5272if_t *mcf5272 = mcf5272if;
    MCF5272_IMM *imm = mcf5272->imm;
    u32_t value;
    u16_t flags;
    unsigned int rx_remove_sof;
    unsigned int rx_remove_eof;
    struct pbuf *p;
    

    rx_remove_sof = rx_remove_eof = mcf5272->rx_remove;

    /* Loop, looking for filled buffers at eof */
    while ((((flags = mcf5272->rxbd_a[rx_remove_eof].flags) & MCF5272_FEC_RX_BD_E) == 0) &&
           (mcf5272->rx_pbuf_a[rx_remove_eof] != 0))
    {
        /* See if this is last buffer in frame */
        if ((flags & MCF5272_FEC_RX_BD_L) != 0)
        {
            /* This frame is ready to go. Start at first descriptor in frame. */
            p = 0;
            do
            {
                /* Adjust pbuf length if this is last buffer in frame */
                if (rx_remove_sof == rx_remove_eof)
                {
                    mcf5272->rx_pbuf_a[rx_remove_sof]->tot_len =
                        mcf5272->rx_pbuf_a[rx_remove_sof]->len = (u16_t)
                        (mcf5272->rxbd_a[rx_remove_sof].data_len - (p ? p->tot_len : 0));
                }
                else
                    mcf5272->rx_pbuf_a[rx_remove_sof]->len =
                        mcf5272->rx_pbuf_a[rx_remove_sof]->tot_len = mcf5272->rxbd_a[rx_remove_sof].data_len;
                
                /* Chain pbuf */
                if (p == 0)
                {
                    p = mcf5272->rx_pbuf_a[rx_remove_sof];       // First in chain
                    p->tot_len = p->len;                        // Important since len might have changed
                } else {
                    pbuf_chain(p, mcf5272->rx_pbuf_a[rx_remove_sof]);
                    pbuf_free(mcf5272->rx_pbuf_a[rx_remove_sof]);
                }
                
                /* Clear pointer to mark descriptor as free */
                mcf5272->rx_pbuf_a[rx_remove_sof] = 0;
                mcf5272->rxbd_a[rx_remove_sof].p_buf = 0;
                
                if (rx_remove_sof != rx_remove_eof)
                    INC_RX_BD_INDEX(rx_remove_sof);
                else
                    break;
               
            } while (1);
            INC_RX_BD_INDEX(rx_remove_sof);

            /* Check error status of frame */
            if (flags & (MCF5272_FEC_RX_BD_LG |
                         MCF5272_FEC_RX_BD_NO |
                         MCF5272_FEC_RX_BD_CR |
                         MCF5272_FEC_RX_BD_OV))
            {
#ifdef LINK_STATS
                lwip_stats.link.drop++;
                if (flags & MCF5272_FEC_RX_BD_LG)
                    lwip_stats.link.lenerr++;                //Jumbo gram
                else
                    if (flags & (MCF5272_FEC_RX_BD_NO | MCF5272_FEC_RX_BD_OV))
                        lwip_stats.link.err++;
                    else
                        if (flags & MCF5272_FEC_RX_BD_CR)
                            lwip_stats.link.chkerr++;        // CRC errors
#endif
                /* Drop errored frame */
                pbuf_free(p);
            } else {
                /* Good frame. increment stat */
#ifdef LINK_STATS
                lwip_stats.link.recv++;
#endif                
                eth_input(p, mcf5272->netif);
            }
        }
        INC_RX_BD_INDEX(rx_remove_eof);
    }
    mcf5272->rx_remove = rx_remove_sof;
    
    /* clear interrupt status for rx interrupt */
    old_level = sys_arch_protect();
    MCF5272_WR_FEC_EIR(imm, MCF5272_FEC_EIR_RXF);
    value = MCF5272_RD_FEC_IMR(imm);
    /* Set rx interrupt bit again */
    MCF5272_WR_FEC_IMR(imm, (value | MCF5272_FEC_IMR_RXFEN));
    /* Now we can re-enable higher priority interrupts again */
    sys_arch_unprotect(old_level);

    /* Fill up empty descriptor rings */
    fill_rx_ring(mcf5272);
    /* Tell fec that we have filled up her ring */
    MCF5272_WR_FEC_RDAR(imm, 1);

    return;
}

            

/*-----------------------------------------------------------------------------------*/
static void
low_level_init(struct netif *netif)
{
    mcf5272if_t *mcf5272;
    MCF5272_IMM *imm;
    VOID        (*old_lisr)(INT);   /* old LISR */
    u32_t value;
    u32_t old_level;
    struct pbuf *p;
    int i;

    mcf5272 = netif->state;
    imm = mcf5272->imm;

    /* Initialize our ethernet address */
    sys_get_eth_addr(mcf5272->ethaddr);
    
    /* First disable fec */
    disable_fec(mcf5272);

    /* Plug appropriate low level interrupt vectors */
    sys_setvect(MCF5272_VECTOR_ERx, mcf5272fec_rx, mcf5272_dis_rx_int);
    sys_setvect(MCF5272_VECTOR_ETx, mcf5272fec_tx_hisr, mcf5272_dis_tx_int);
    //sys_setvect(MCF5272_VECTOR_ENTC, mcf5272fec_ntc);

    /* Set the I_MASK register to enable only rx & tx frame interrupts */
    MCF5272_WR_FEC_IMR(imm, MCF5272_FEC_IMR_TXFEN | MCF5272_FEC_IMR_RXFEN);

    /* Clear I_EVENT register */
    MCF5272_WR_FEC_EIR(imm,0xFFFFFFFF);

    /* Set up the appropriate interrupt levels */
    /* Disable interrupts, since this is a read/modify/write operation */
    old_level = sys_arch_protect();
    value = MCF5272_RD_SIM_ICR3(imm);
    MCF5272_WR_SIM_ICR3(imm, value | MCF5272_SIM_ICR_ERX_IL(FEC_LEVEL) |
                        MCF5272_SIM_ICR_ETX_IL(FEC_LEVEL));
    sys_arch_unprotect(old_level);
    
    /* Set the source address for the controller */
    MCF5272_WR_FEC_MALR(imm,0 
                        | (mcf5272->ethaddr->addr[0] <<24) 
                        | (mcf5272->ethaddr->addr[1] <<16)	
                        | (mcf5272->ethaddr->addr[2] <<8) 
                        | (mcf5272->ethaddr->addr[3] <<0)); 
    MCF5272_WR_FEC_MAUR(imm,0
                        | (mcf5272->ethaddr->addr[4] <<24)
                        | (mcf5272->ethaddr->addr[5] <<16));
    
    /* Initialize the hash table registers */
    /* We are not supporting multicast addresses */
    MCF5272_WR_FEC_HTUR(imm,0);
    MCF5272_WR_FEC_HTLR(imm,0);

    /* Set Receive Buffer Size. We subtract 16 because the start of the receive
    *  buffer MUST be divisible by 16, so depending on where the payload really
    *  starts in the pbuf, we might be increasing the start point by up to 15 bytes.
    *  See the alignment code in fill_rx_ring() */
    /* There might be an offset to the payload address and we should subtract
     * that offset */
    p = pbuf_alloc(PBUF_RAW, PBUF_POOL_BUFSIZE, PBUF_POOL);
    i = 0;
    if (p)
    {
        struct pbuf *q = p;
        
        while ((q = q->next) != 0)
            i += q->len;
        mcf5272->rx_buf_len = PBUF_POOL_BUFSIZE-16-i;
        pbuf_free(p);
    }
    
    
    MCF5272_WR_FEC_EMRBR(imm, (u16_t) mcf5272->rx_buf_len);

    /* Point to the start of the circular Rx buffer descriptor queue */
    MCF5272_WR_FEC_ERDSR(imm, ((u32_t) &mcf5272->rxbd_a[0]));

    /* Point to the start of the circular Tx buffer descriptor queue */
    MCF5272_WR_FEC_ETDSR(imm, ((u32_t) &mcf5272->txbd_a[0]));
    
    /* Set the tranceiver interface to MII mode */
    MCF5272_WR_FEC_RCR(imm, 0
                       | MCF5272_FEC_RCR_MII_MODE
                       | MCF5272_FEC_RCR_DRT); 	/* half duplex */

    /* Only operate in half-duplex, no heart beat control */
    MCF5272_WR_FEC_TCR(imm, 0);

    /* Set the maximum frame length (MTU) */
    MCF5272_WR_FEC_MFLR(imm, MTU_FEC);

    /* Set MII bus speed */
    MCF5272_WR_FEC_MSCR(imm, 0x0a);

    /* Enable fec i/o pins */
    value = MCF5272_RD_GPIO_PBCNT(imm);
    MCF5272_WR_GPIO_PBCNT(imm, ((value & 0x0000ffff) | 0x55550000));

    /* Clear MII interrupt status */
    MCF5272_WR_FEC_EIR(imm, MCF5272_FEC_IMR_MIIEN);
        
/*     /\* Read phy ID *\/ */
/*     MCF5272_WR_FEC_MMFR(imm, 0x600a0000); */
/*     while (1) */
/*     { */
/*         value = MCF5272_RD_FEC_EIR(imm); */
/*         if ((value & MCF5272_FEC_IMR_MIIEN) != 0) */
/*         { */
/*             MCF5272_WR_FEC_EIR(imm, MCF5272_FEC_IMR_MIIEN); */
/*             break; */
/*         } */
/*     } */
/*     phy = MCF5272_RD_FEC_MMFR(imm); */
    
    /* Enable FEC */
    enable_fec(mcf5272);

    /* THIS IS FOR LEVEL ONE/INTEL PHY ONLY!!! */
    /* Program Phy LED 3 to tell us transmit status */
    MCF5272_WR_FEC_MMFR(imm, 0x50520412);

}

/*-----------------------------------------------------------------------------------*
 * etharp timer thread
 * It's only job is to initialize the timer, create a semaphore and wait on it
 * forever. We need a special task to handle the arp timer.
 *-----------------------------------------------------------------------------------*/
static void
etharp_timer_thread(void *arg)
{
    sys_sem_t *psem = (sys_sem_t *) arg;
    
    /* Create timeout timer */
    sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
    /* Signal previous task that it can go */
    sys_sem_signal(*psem);

    tx_sem = sys_sem_new(0);

    while (1)
    {
        sys_sem_wait(tx_sem);
        mcf5272fec_tx_cleanup();
    }
}


    
/*-----------------------------------------------------------------------------------*/
static void
etharp_timer_init(void *arg)
{
    sys_thread_new(DEFAULT_THREAD_NAME, (void *)etharp_timer_thread, arg, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
}


/*-----------------------------------------------------------------------------------*/
/*
 * mcf5272fecif_init(struct netif *netif):
 *
 * Should be called at the beginning of the program to set up the
 * network interface. It calls the function low_level_init() to do the
 * actual setup of the hardware.
 *
 * Note that there is only one fec in a 5272!
 *
 */
err_t
mcf5272fecif_init(struct netif *netif)
{
    sys_sem_t sem;
    
    /* Allocate our interface control block */
    /* IMPORTANT NOTE: This works for 5272, but if you are using a cpu with data cache
     * then you need to make sure you get this memory from non-cachable memory. */
    mcf5272if = (mcf5272if_t *) calloc(1, sizeof(mcf5272if_t));
    if (mcf5272if)
    {
        netif->state = mcf5272if;
        mcf5272if->netif = netif;
        netif->name[0] = IFNAME0;
        netif->name[1] = IFNAME1;
        netif->output = etharp_output;
        netif->linkoutput = low_level_output;
        netif->mtu = MTU_FEC - 18;      // mtu without ethernet header and crc
        mcf5272if->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
        netif->hwaddr_len = 6; /* Ethernet interface */
        mcf5272if->imm = mcf5272_get_immp();
        
        low_level_init(netif);

        etharp_init();
        sem = sys_sem_new(0);
        etharp_timer_init(&sem);
        sys_sem_wait(sem);
        sys_sem_free(sem);
        
        return ERR_OK;
    }
    else
        return ERR_MEM;
}

/*-----------------------------------------------------------------------------------*/

⌨️ 快捷键说明

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