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

📄 net_nic.c

📁 Micrium专门针对AT91SAM7X256发布的网卡驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    CPU_INT32U  MCK_frq;
    CPU_INT32U  link_speed;
    CPU_INT32U  link_duplex;


    AT91C_BASE_PMC->PMC_PCER     = (1 << AT91C_ID_PIOA);                /* Ensure the clock for PIOA is enabled                 */
    AT91C_BASE_PMC->PMC_PCER     = (1 << AT91C_ID_PIOB);                /* Ensure the clock for PIOB is enabled                 */
    AT91C_BASE_PMC->PMC_PCER     = (1 << AT91C_ID_EMAC);                /* Enable the peripheral clock for the EMAC             */

    EMAC_RxDis();                                                       /* Disable the EMAC receiver                            */
    EMAC_TxDis();                                                       /* Disable the EMAC transmitter                         */

    NetBSP_Phy_HW_Init();                                               /* User implemented in net_bsp.c, reset / init the PHY  */
                                                                        /* and configure the necessary IO pins that it req's    */

    AT91C_BASE_EMAC->EMAC_NCR   |=  AT91C_EMAC_MPE;                     /* Enable the management port. Comm between EMAC/PHY    */

    MCK_frq                      =  BSP_CPU_ClkFreq();                  /* Get the MCK frequency                                */

    if (MCK_frq        <= 20000) {                                      /* If MCK <= 20MHZ, set MDC to MCK / 8                  */
        MCK_frq                  =  AT91C_EMAC_CLK_HCLK_8;
    } else if (MCK_frq <= 40000) {                                      /* If 20MHZ < MCK <= 40MHZ, set MDC to MCK / 16         */
        MCK_frq                  =  AT91C_EMAC_CLK_HCLK_16;
    } else if (MCK_frq <= 80000) {                                      /* If 40MHZ < MCK <= 80MHZ, set MDC to MCK / 32         */
        MCK_frq                  =  AT91C_EMAC_CLK_HCLK_32;
    } else {                                                            /* If 80MHZ < MCK <= 160MHZ, set MDC to MCK / 64        */
        MCK_frq                  =  AT91C_EMAC_CLK_HCLK_64;
    }

    AT91C_BASE_EMAC->EMAC_NCFGR  =  MCK_frq;                            /* Set the MDC CLk divider                              */
    AT91C_BASE_EMAC->EMAC_NCFGR |=  AT91C_EMAC_DRFCS;                   /* Do NOT copy the FCS to memory during DMA transfer    */

    NetNIC_PhyInit(perr);                                               /* Configure the PHY & get the link state (net_phy.c)   */

    NetNIC_LinkUp();                                                    /* Regardless of the actual link state, inform the      */
                                                                        /* stack that the link is up so that it will be ready   */
                                                                        /* to transmit and receive packets when the comes up    */
#ifdef RMII
    AT91C_BASE_EMAC->EMAC_USRIO    =   AT91C_EMAC_RMII | (0x02);        /* Enable RMII mode and RMII clk on ERFCK               */
#else
    AT91C_BASE_EMAC->EMAC_USRIO    =  (0x02);                           /* Enable MII mode, and clk ERXCK and ETXCK             */
#endif

    EMAC_RxBufInit();                                                   /* Init Rx buffer descriptors                           */
    EMAC_TxBufInit();                                                   /* Init Tx buffer descriptors                           */

    link_speed                     =   NetPHY_GetLinkSpeed(perr);       /* Read the PHY's current link speed                    */
    link_duplex                    =   NetPHY_GetLinkDuplex(perr);      /* Read the PHY's current link duplex mode              */

    NetBSP_EMAC_Settings_Update (link_speed, link_duplex);              /* Inform the EMAC about the current PHY settings       */

                                                                        /* Init MAC Address                                     */
                                                                        /* See Note #3.                                         */
                                                                        /* MAC address is fetched from EMAC EEPROM.             */
#if (EMAC_CFG_MAC_ADDR_SEL == EMAC_CFG_MAC_ADDR_SEL_EEPROM)
    reg_val = AT91C_BASE_EMAC->EMAC_SA1L;
    NetIF_MAC_Addr[0]            =   ((reg_val >>  0) & 0xFF);
    NetIF_MAC_Addr[1]            =   ((reg_val >>  8) & 0xFF);
    NetIF_MAC_Addr[2]            =   ((reg_val >> 16) & 0xFF);
    NetIF_MAC_Addr[3]            =   ((reg_val >> 24) & 0xFF);

    reg_val = AT91C_BASE_EMAC->EMAC_SA4H;
    NetIF_MAC_Addr[4]            =   ((reg_val >>  0) & 0xFF);
    NetIF_MAC_Addr[5]            =   ((reg_val >>  8) & 0xFF);
#else                                                                   /* MAC address is application-configured.               */
    AT91C_BASE_EMAC->EMAC_SA1L   =    (NetIF_MAC_Addr[3] << 24) |
                                      (NetIF_MAC_Addr[2] << 16) |
                                      (NetIF_MAC_Addr[1] <<  8) |
                                      (NetIF_MAC_Addr[0]);
    AT91C_BASE_EMAC->EMAC_SA1H   =    (NetIF_MAC_Addr[5] <<  8) |
                                      (NetIF_MAC_Addr[4]);
#endif

    NetIF_MAC_AddrValid          =     DEF_YES;

                                                                        /* Clear receive status register                        */
    AT91C_BASE_EMAC->EMAC_RSR    =    (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);

    NetNIC_IntInit();                                                   /* Configure and enable AIC, not EMAC interrupts        */
                                                                        /* EMAC int's are enabled by NetInit -> NetNIC_IntEn    */

    EMAC_TxEn();                                                        /* Enable the EMAC transmitter                          */
    EMAC_RxEn();                                                        /* Enable the EMAC receiver                             */

    NIC_RxNRdyCtr                 =     0;                              /* No packets require servicing yet                     */

    *perr                         =     NET_NIC_ERR_NONE;               /* If we made it this far, then no fatal errors         */
}

/*
*********************************************************************************************************
*                                            EMAC_RxBufInit()
*
* Description: Initializes the Rx buffer descriptors
*
* Parameters : None
*
* Returns    : None
*
* Notes      : 1) Buffer descriptors MUST start on a 32-byte boundary.
*********************************************************************************************************
*/

static  void  EMAC_RxBufInit (void)
{
    CPU_INT16U     i;
    NIC_BUF_DESC  *pbufdesc;


    pbufdesc                    = (NIC_BUF_DESC *)(((CPU_INT32U)&NIC_RxBufDesc[0] + 32) & 0xFFFFFFE0);
    NIC_RxBufDescPtrStart       = pbufdesc;
    NIC_ExpectedFrameStart      = pbufdesc;

    for (i = 0; i < NIC_RX_N_BUFS; i++) {                               /* Initialize Rx descriptor ring                        */
        pbufdesc->addr          = (((CPU_INT32U)&NIC_RxBuf[i * NIC_RX_BUF_SIZE] + 32) & 0xFFFFFFE0);
        pbufdesc->addr         &= ~EMAC_RXBUF_SW_OWNED;
        pbufdesc->status        =  0;
        pbufdesc++;
    }

    NIC_RxBufDescPtrEnd         =  pbufdesc;                            /* Get the last buffer descriptor in the ring (plus 1)  */
    pbufdesc--;                                                         /* Move back to the last descriptor                     */
    pbufdesc->addr             |=  EMAC_RXBUF_ADD_WRAP;                 /* Set the Wrap bit on the last descriptor in the ring  */

    AT91C_BASE_EMAC->EMAC_RBQP  = (CPU_INT32U)NIC_RxBufDescPtrStart;    /* Configure the EMAC's Rx Descriptor Pointer Register  */
}

/*
*********************************************************************************************************
*                                             EMAC_TxBufInit()
*
* Description: Initializes the Tx buffer descriptors
*
* Parameters : None
*
* Returns    : None
*
* Notes      : 1) Buffer descriptors MUST start on a 32-byte boundary.
*********************************************************************************************************
*/

static  void  EMAC_TxBufInit (void)
{
    NIC_TxBufDescPtr            = (NIC_BUF_DESC *)(((CPU_INT32U)&NIC_TxBufDesc[0] + 32) & 0xFFFFFFE0);

    NIC_TxBufDescPtr->status   |=  EMAC_TXBUF_STATUS_USED;              /* The descriptor is ready for software use after init  */
    NIC_TxBufDescPtr->status   |=  EMAC_TXBUF_ADD_WRAP;                 /* Set the Wrap bit on the last (only) descriptor       */

    AT91C_BASE_EMAC->EMAC_TBQP  = (CPU_INT32U)NIC_TxBufDescPtr;         /* Configure the EMAC's Tx Descriptor Pointer Register  */
}

/*
*********************************************************************************************************
*                                        NETWORK INTERRUPT INITIALIZATION
*
* Description : This function is called by EMAC_Init() to to initialize the interrupt for the NIC.
*
* Arguments   : none
*********************************************************************************************************
*/

void  NetNIC_IntInit (void)
{
    AT91C_BASE_AIC->AIC_IDCR                 =  1 << AT91C_ID_EMAC;     /* Ensure interrupts are disabled before init           */
    AT91C_BASE_AIC->AIC_SVR[AT91C_ID_EMAC]   = (INT32U)NetNIC_ISR_Handler;
    AT91C_BASE_AIC->AIC_SMR[AT91C_ID_EMAC]   =  AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | AT91C_AIC_PRIOR_LOWEST;
    AT91C_BASE_AIC->AIC_ICCR                 =  1 << AT91C_ID_EMAC;

    AT91C_BASE_EMAC->EMAC_IDR                =  0x3FFF;                 /* Disable all EMAC interrupts                          */

    AT91C_BASE_AIC->AIC_IECR                 =  1 << AT91C_ID_EMAC;     /* Enable the AIC EMAC Interrupt                        */
}


/*
*********************************************************************************************************
*                                            NetNIC_IntEn()
*
* Description : Enable NIC interrupts.
*
* Argument(s) : none.
*
* Return(s)   : none.
*
* Caller(s)   : Net_Init().
*********************************************************************************************************
*/

void  NetNIC_IntEn (NET_ERR  *perr)
{
    EMAC_RxIntEn();
    EMAC_TxIntEn();

    *perr = NET_NIC_ERR_NONE;
}


/*
*********************************************************************************************************
*                                       EMAC_RxIntEn()
*
* Description : Enable AT91SAM7X256 EMAC Receiver Interrupts.
*
* Argument(s) : none.
*
* Return(s)   : none.
*
* Caller(s)   : NetNIC_IntEn(), NetNIC_RxPktGetSize(), NetNIC_RxPkt().
*
* Note(s)     : none.
*********************************************************************************************************
*/

static  void  EMAC_RxIntEn (void)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
    CPU_SR      cpu_sr;
#endif


    CPU_CRITICAL_ENTER();                                               /* See 'AT91SAM7X256 REGISTERS  Note #5b'.              */
    AT91C_BASE_EMAC->EMAC_IER   |=    (AT91C_EMAC_RCOMP   |             /* Enable 'Reception complete' interrupt.               */
                                       AT91C_EMAC_ROVR);                /* Enable 'Receiver overrun' interrupt.                 */

    CPU_CRITICAL_EXIT();
}

/*
*********************************************************************************************************
*                                       EMAC_TxIntEn()
*
* Description : Enable AT91SAM7X256 EMAC Transmit Interrupts.
*
* Argument(s) : none.
*
* Return(s)   : none.
*
* Caller(s)   : NetNIC_IntEn().
*********************************************************************************************************
*/

static  void  EMAC_TxIntEn (void)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
    CPU_SR      cpu_sr;
#endif


    CPU_CRITICAL_ENTER();                                               /* See 'AT91SAM7X256 REGISTERS  Note #5b'.              */
                                                                        /* Enable Tx complete and Transmit bit used Intr's      */
    AT91C_BASE_EMAC->EMAC_IER   |=   (AT91C_EMAC_TCOMP | AT91C_EMAC_TXUBR);
    CPU_CRITICAL_EXIT();
}


/*
*********************************************************************************************************
*                                        NETWORK INTERRUPT CLEAR
*
* Description : This function is called to clear the interrupt controller associated with the NIC.
*

⌨️ 快捷键说明

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