📄 net_nic.c
字号:
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 + -