void vSendEMACTxData( unsigned short usTxDataLen ) { unsigned long ulAttempts = 0UL; /* Check to see if the Tx descriptor is free, indicated by its buffer being NULL. */ while( TX_DESC_PACKET( emacTX_DESC_INDEX ) != ( unsigned long ) NULL ) { /* Wait for the Tx descriptor to become available. */ vTaskDelay( emacBUFFER_WAIT_DELAY ); ulAttempts++; if( ulAttempts > emacBUFFER_WAIT_ATTEMPTS ) { /* Something has gone wrong as the Tx descriptor is still in use. Clear it down manually, the data it was sending will probably be lost. */ prvReturnBuffer( ( unsigned char * ) TX_DESC_PACKET( emacTX_DESC_INDEX ) ); break; } } /* Setup the Tx descriptor for transmission. Remember the length of the data being sent so the second descriptor can be used to send it again from within the ISR. */ usSendLen = usTxDataLen; TX_DESC_PACKET( emacTX_DESC_INDEX ) = ( unsigned long ) uip_buf; TX_DESC_CTRL( emacTX_DESC_INDEX ) = ( usTxDataLen | TCTRL_LAST | TCTRL_INT ); EMAC->TxProduceIndex = ( emacTX_DESC_INDEX + 1 ); /* uip_buf is being sent by the Tx descriptor. Allocate a new buffer. */ uip_buf = prvGetNextBuffer(); }
/** * 送信中のイーサフレームを処理する機会を与えて、送信キューが空くまで待ちます。 * LPC1769の場合は、非同期に更新したディスクリプタの内容から、送信メモリのフラグを更新します。 * @return * 次に書き込むことが出来る送信キュー。 */ static NyLPC_TUInt32 waitForTxEthFrameEmpty(void) { NyLPC_TUInt32 IndexNext; struct NyLPC_TTxBufferHeader *b; void* p; NyLPC_TUInt32 i; //送信キューの決定 IndexNext = (LPC_EMAC->TxProduceIndex + 1)%NUM_TX_FRAG; //送信キューフルが解除されるまで待ち while(IndexNext == LPC_EMAC->TxConsumeIndex) { // NyLPC_cThread_sleep(emacSHORT_DELAY_MS); } //(TxProduceIndex+1)→TxConsumeIndexにあるデータのsentフラグを消去 for(i=IndexNext;i!=LPC_EMAC->TxConsumeIndex;i=(i+1)%NUM_TX_FRAG) { p=(void*)TX_DESC_PACKET(i); if(p!=NULL){ b=NyLPC_TTxBufferHeader_getBufferHeaderAddr(p); b->is_lock=NyLPC_TUInt8_FALSE; TX_DESC_PACKET(i)=0; } } p=(void*)TX_DESC_PACKET(i); if(p!=NULL){ b=NyLPC_TTxBufferHeader_getBufferHeaderAddr(p); b->is_lock=NyLPC_TUInt8_FALSE; TX_DESC_PACKET(i)=0; } return IndexNext; }
void vEMAC_ISR( void ) { unsigned long ulStatus; long lHigherPriorityTaskWoken = pdFALSE; ulStatus = EMAC->IntStatus; /* Clear the interrupt. */ EMAC->IntClear = ulStatus; if( ulStatus & INT_RX_DONE ) { /* Ensure the uIP task is not blocked as data has arrived. */ xSemaphoreGiveFromISR( xEMACSemaphore, &lHigherPriorityTaskWoken ); } if( ulStatus & INT_TX_DONE ) { if( usSendLen > 0 ) { /* Send the data again, using the second descriptor. As there are only two descriptors the index is set back to 0. */ TX_DESC_PACKET( ( emacTX_DESC_INDEX + 1 ) ) = TX_DESC_PACKET( emacTX_DESC_INDEX ); TX_DESC_CTRL( ( emacTX_DESC_INDEX + 1 ) ) = ( usSendLen | TCTRL_LAST | TCTRL_INT ); EMAC->TxProduceIndex = ( emacTX_DESC_INDEX ); /* This is the second Tx so set usSendLen to 0 to indicate that the Tx descriptors will be free again. */ usSendLen = 0UL; } else { /* The Tx buffer is no longer required. */ prvReturnBuffer( ( unsigned char * ) TX_DESC_PACKET( emacTX_DESC_INDEX ) ); TX_DESC_PACKET( emacTX_DESC_INDEX ) = ( unsigned long ) NULL; } } portEND_SWITCHING_ISR( lHigherPriorityTaskWoken ); }
void RequestSend(unsigned short FrameSize) { unsigned int index; index = LPC_EMAC->TxProduceIndex; txptr = (unsigned short *)TX_DESC_PACKET(index); TX_DESC_CTRL(index) = FrameSize | TCTRL_LAST; }
/** * Ethernetパケットを送信します。 * allocTxBufで得たバッファを指定すること。 * <p>関数仕様</p> * この関数は、i_bufが * </div> */ static void sendTxEthFrame(void* i_buf,unsigned short i_size) { NyLPC_TUInt32 IndexNext,Index; struct NyLPC_TTxBufferHeader* bh=NyLPC_TTxBufferHeader_getBufferHeaderAddr(i_buf); //サイズ0なら送信の必要なし if(i_size == 0) { return; } //送信デスクリプタの反映 IndexNext =waitForTxEthFrameEmpty(); //送信対象のメモリブロックを送信中に設定。 // b=(i_buf+1); //送信中のメモリブロックなら無視 if(bh->is_lock){ return; } //送信中にセット bh->is_lock=NyLPC_TUInt8_TRUE; //送信データのセット Index = LPC_EMAC->TxProduceIndex; if (i_size > ETH_FRAG_SIZE){ i_size = ETH_FRAG_SIZE; } //送信処理 TX_DESC_PACKET( Index ) = ( unsigned long )i_buf; //See UM10360.pdf Table 181. Transmit descriptor control word TX_DESC_CTRL( Index ) = ((i_size-1) | TCTRL_LAST | TCTRL_INT ); LPC_EMAC->TxProduceIndex = IndexNext; return; }
void RequestSend(void) { unsigned int idx; idx = TxProduceIndex; tptr = (unsigned short *)TX_DESC_PACKET(idx); }
void RequestSend(void) { unsigned int idx; idx = MAC_TXPRODUCEINDEX; tptr = (unsigned short *)TX_DESC_PACKET(idx); }
err_t LPC24XX_EMAC_lwip_xmit ( struct netif *pNetIf, struct pbuf *pPBuf ) { UINT32 bytes_out,idx; UINT32 * dst; UINT32 * src; LPC24XX_EMAC & ENET = *(LPC24XX_EMAC *)LPC24XX_EMAC::c_EMAC_Base; /* Disable intrrupts */ GLOBAL_LOCK(irq); if (!pNetIf || !pPBuf) { return ERR_ARG; } bytes_out = pPBuf->tot_len; if( bytes_out > ETH_MAX_FLEN ) { debug_printf("LPC24XX_EMAC_xmit - Ehernet Frame truncated"); bytes_out = ETH_MAX_FLEN; /* What's the point of sending less data! */ } idx = ENET.MAC_TXPRODUCEINDEX; /* Check if a Tx descriptor is available */ if ( ENET.MAC_TXCONSUMEINDEX == (idx + 1) ) { /* Tx descriptor not available */ return ERR_IF; } dst = (UINT32 *)TX_DESC_PACKET(idx); while (pPBuf) { /* TODO - can LWIP word align input buffer ? If so we could use FastCopy */ // src = (UINT32 *)pPBuf->payload; // LPC24XX_EMAC_lwip_FastCopy(dst, src, bytes_out); memcpy(dst, pPBuf->payload, pPBuf->len); pPBuf = pPBuf->next; dst += pPBuf->len; } TX_DESC_CTRL(idx) = bytes_out | TCTRL_LAST | TCTRL_INT; idx++; /* Reset the index if last descriptor */ if (idx == NUM_TX_FRAG) { idx = 0; } ENET.MAC_TXPRODUCEINDEX = idx; return ERR_OK; }
/** * 送信デスクリプタを準備します。 */ static void prevTxDescriptor(void) { long x; //デスクリプタの設定 for( x = 0; x < NUM_TX_FRAG; x++ ) { TX_DESC_PACKET( x ) = ( unsigned long ) NULL; TX_DESC_CTRL( x ) = 0; TX_STAT_INFO( x ) = 0; } /* Set LPC_EMAC Transmit Descriptor Registers. */ LPC_EMAC->TxDescriptor =TX_DESC_BASE; LPC_EMAC->TxStatus = TX_STAT_BASE; LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG - 1; }
// Keil: function added to initialize Tx Descriptors void tx_descr_init (void) { unsigned int i; for (i = 0; i < NUM_TX_FRAG; i++) { TX_DESC_PACKET(i) = TX_BUF(i); TX_DESC_CTRL(i) = 0; TX_STAT_INFO(i) = 0; } /* Set EMAC Transmit Descriptor Registers. */ TxDescriptor = TX_DESC_BASE; TxStatus = TX_STAT_BASE; TxDescriptorNumber = NUM_TX_FRAG-1; /* Tx Descriptors Point to 0 */ TxProduceIndex = 0; }
// Keil: function added to initialize Tx Descriptors void tx_descr_init (void) { unsigned int i; for (i = 0; i < NUM_TX_FRAG; i++) { TX_DESC_PACKET(i) = TX_BUF(i); TX_DESC_CTRL(i) = 0; TX_STAT_INFO(i) = 0; } /* Set EMAC Transmit Descriptor Registers. */ MAC_TXDESCRIPTOR = TX_DESC_BASE; MAC_TXSTATUS = TX_STAT_BASE; MAC_TXDESCRIPTORNUM = NUM_TX_FRAG-1;//Minus 1 Encoding /* Tx Descriptors Point to 0 */ MAC_TXPRODUCEINDEX = 0; }
static void tx_descr_init (void) { UNS_32 i; for (i = 0; i < NUM_TX_FRAG; i++) { TX_DESC_PACKET(i) = TX_BUF(i); TX_DESC_CTRL(i) = (1<<31) | (1<<30) | (1<<29) | (1<<28) | (1<<26) | (ETH_FRAG_SIZE-1); TX_STAT_INFO(i) = 0; } /* Set EMAC Transmit Descriptor Registers. */ LPC_EMAC->TxDescriptor = TX_DESC_BASE; LPC_EMAC->TxStatus = TX_STAT_BASE; LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1; /* Tx Descriptors Point to 0 */ LPC_EMAC->TxProduceIndex = 0; }
//! \warning: Not Reentrant virtual void sendFrame( uint8_t const * frame, uint_fast16_t size ) { //TODO: Could be optimized to fill last buffer then wait to increment produce index. while( isTXFull() ) { sem_tx.wait(); } { unsigned int idx; idx = MAC_TXPRODUCEINDEX; TX_DESC_CTRL(idx) = (size-1/*-1 Encoded*/-4/*CRC*/) | TCTRL_CRC | TCTRL_LAST | TCTRL_INT; memcpy((void*)TX_DESC_PACKET(idx), frame, size); if (++idx == NUM_TX_FRAG) idx = 0; MAC_TXPRODUCEINDEX = idx; } }
static void prvInitDescriptors( void ) { long x, lNextBuffer = 0; for( x = 0; x < NUM_RX_FRAG; x++ ) { /* Allocate the next Ethernet buffer to this descriptor. */ RX_DESC_PACKET( x ) = ETH_BUF( lNextBuffer ); RX_DESC_CTRL( x ) = RCTRL_INT | ( ETH_FRAG_SIZE - 1 ); RX_STAT_INFO( x ) = 0; RX_STAT_HASHCRC( x ) = 0; /* The Ethernet buffer is now in use. */ ucBufferInUse[ lNextBuffer ] = pdTRUE; lNextBuffer++; } /* Set EMAC Receive Descriptor Registers. */ EMAC->RxDescriptor = RX_DESC_BASE; EMAC->RxStatus = RX_STAT_BASE; EMAC->RxDescriptorNumber = NUM_RX_FRAG - 1; /* Rx Descriptors Point to 0 */ EMAC->RxConsumeIndex = 0; /* A buffer is not allocated to the Tx descriptors until they are actually used. */ for( x = 0; x < NUM_TX_FRAG; x++ ) { TX_DESC_PACKET( x ) = ( unsigned long ) NULL; TX_DESC_CTRL( x ) = 0; TX_STAT_INFO( x ) = 0; } /* Set EMAC Transmit Descriptor Registers. */ EMAC->TxDescriptor = TX_DESC_BASE; EMAC->TxStatus = TX_STAT_BASE; EMAC->TxDescriptorNumber = NUM_TX_FRAG - 1; /* Tx Descriptors Point to 0 */ EMAC->TxProduceIndex = 0; }
void Init_EthMAC(void) { unsigned int value, phyid1, phyid2; volatile unsigned int loop; unsigned phy_in_use = 0; unsigned phy_linkstatus_reg; unsigned phy_linkstatus_mask; /* Power Up the EMAC controller. */ LPC_SC->PCONP |= (0x1<<30); #if RMII LPC_IOCON->P1_0 &= ~0x07; /* ENET I/O config */ LPC_IOCON->P1_0 |= 0x01; /* ENET_TXD0 */ LPC_IOCON->P1_1 &= ~0x07; LPC_IOCON->P1_1 |= 0x01; /* ENET_TXD1 */ LPC_IOCON->P1_4 &= ~0x07; LPC_IOCON->P1_4 |= 0x01; /* ENET_TXEN */ LPC_IOCON->P1_8 &= ~0x07; LPC_IOCON->P1_8 |= 0x01; /* ENET_CRS */ LPC_IOCON->P1_9 &= ~0x07; LPC_IOCON->P1_9 |= 0x01; /* ENET_RXD0 */ LPC_IOCON->P1_10 &= ~0x07; LPC_IOCON->P1_10 |= 0x01; /* ENET_RXD1 */ LPC_IOCON->P1_14 &= ~0x07; LPC_IOCON->P1_14 |= 0x01; /* ENET_RX_ER */ LPC_IOCON->P1_15 &= ~0x07; LPC_IOCON->P1_15 |= 0x01; /* ENET_REF_CLK */ #else LPC_IOCON->P1_0 &= ~0x07; /* ENET I/O config */ LPC_IOCON->P1_0 |= 0x01; /* ENET_TXD0 */ LPC_IOCON->P1_1 &= ~0x07; LPC_IOCON->P1_1 |= 0x01; /* ENET_TXD1 */ LPC_IOCON->P1_2 &= ~0x07; LPC_IOCON->P1_2 |= 0x01; /* ENET_TXD2 */ LPC_IOCON->P1_3 &= ~0x07; LPC_IOCON->P1_3 |= 0x01; /* ENET_TXD3 */ LPC_IOCON->P1_4 &= ~0x07; LPC_IOCON->P1_4 |= 0x01; /* ENET_TXEN */ LPC_IOCON->P1_5 &= ~0x07; LPC_IOCON->P1_5 |= 0x01; /* ENET_TXER */ LPC_IOCON->P1_6 &= ~0x07; LPC_IOCON->P1_6 |= 0x01; /* ENET_TX_CLK */ LPC_IOCON->P1_7 &= ~0x07; LPC_IOCON->P1_7 |= 0x01; /* ENET_COL */ LPC_IOCON->P1_8 &= ~0x07; LPC_IOCON->P1_8 |= 0x01; /* ENET_CRS */ LPC_IOCON->P1_9 &= ~0x07; LPC_IOCON->P1_9 |= 0x01; /* ENET_RXD0 */ LPC_IOCON->P1_10 &= ~0x07; LPC_IOCON->P1_10 |= 0x01; /* ENET_RXD1 */ LPC_IOCON->P1_11 &= ~0x07; LPC_IOCON->P1_11 |= 0x01; /* ENET_RXD2 */ LPC_IOCON->P1_12 &= ~0x07; LPC_IOCON->P1_12 |= 0x01; /* ENET_RXD3 */ LPC_IOCON->P1_13 &= ~0x07; LPC_IOCON->P1_13 |= 0x01; /* ENET_RX_DV */ LPC_IOCON->P1_14 &= ~0x07; LPC_IOCON->P1_14 |= 0x01; /* ENET_RX_ER */ LPC_IOCON->P1_15 &= ~0x07; LPC_IOCON->P1_15 |= 0x01; /* ENET_RX_CLK/ENET_REF_CLK */ #endif #if 1 LPC_IOCON->P1_16 &= ~0x07; /* ENET/PHY I/O config */ LPC_IOCON->P1_16 |= 0x01; /* ENET_MDC */ LPC_IOCON->P1_17 &= ~0x07; LPC_IOCON->P1_17 |= 0x01; /* ENET_MDIO */ // LPC_IOCON->LOC_ENET_MDIO = 0x01; #endif #if 0 LPC_IOCON->P2_8 &= ~0x07; /* ENET/PHY I/O config */ LPC_IOCON->P2_8 |= 0x04; /* ENET_MDC */ LPC_IOCON->P2_9 &= ~0x07; LPC_IOCON->P2_9 |= 0x04; /* ENET_MDIO */ // LPC_IOCON->LOC_ENET_MDIO = 0x00; #endif // Set up MAC Configuration Register 1 LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX |MAC1_SIM_RES | MAC1_SOFT_RES; // Set up MAC Command Register LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM; // Short delay for (loop = 100; loop; loop--); // Set up MAC Configuration Register 1 to pass all receive frames LPC_EMAC->MAC1 = MAC1_PASS_ALL; // Set up MAC Configuration Register 2 to append CRC and pad out frames LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN; // Set Ethernet Maximum Frame Register LPC_EMAC->MAXF = ETH_MAX_FLEN; // Set Collision Window / Retry Register LPC_EMAC->CLRT = CLRT_DEF; // Set Non Back-to-Back Inter-Packet-Gap Register LPC_EMAC->IPGR = IPGR_DEF; /* Enable Reduced MII interface. */ LPC_EMAC->MCFG = MCFG_CLK_DIV64 | MCFG_RES_MII; for (loop = 100; loop; loop--); LPC_EMAC->MCFG = MCFG_CLK_DIV64; // Set MAC Command Register to enable Reduced MII interface // and prevent runt frames being filtered out LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM | CR_PASS_RX_FILT; // Put PHY into reset mode WriteToPHY (PHY_REG_BMCR, 0x8000); // Loop until hardware reset completes for (loop = 0; loop < 0x100000; loop++) { value = ReadFromPHY (PHY_REG_BMCR); if (!(value & 0x8000)) { // Reset has completed break; } } // Just check this actually is a DP83848C PHY phyid1 = ReadFromPHY (PHY_REG_IDR1); phyid2 = ReadFromPHY (PHY_REG_IDR2); if (((phyid1 << 16) | (phyid2 & 0xFFF0)) == DP83848C_ID) { phy_in_use = DP83848C_ID; } else if (((phyid1 << 16) | (phyid2 & 0xFFF0)) == LAN8720_ID) { phy_in_use = LAN8720_ID; } if (phy_in_use != 0) { // Safe to configure the PHY device // Set PHY to autonegotiation link speed WriteToPHY (PHY_REG_BMCR, PHY_AUTO_NEG); // loop until autonegotiation completes for (loop = 0; loop < 0x100000; loop++) { value = ReadFromPHY (PHY_REG_BMSR); if (value & 0x0020) { // Autonegotiation has completed break; } } } // Now check the link status for (loop = 0; loop < 0x10000; loop++) { value = ReadFromPHY (PHY_REG_BMSR); if (value & 0x04) { /* bit 2 of BSR = 1? Link Up */ // The link is on break; } } // Configure the EMAC with the established parameters switch (phy_in_use) { case DP83848C_ID: value = ReadFromPHY (PHY_REG_STS); /* PHY Extended Status Register */ // Now configure for full/half duplex mode if (value & 0x0004) { // We are in full duplex is enabled mode LPC_EMAC->MAC2 |= MAC2_FULL_DUP; LPC_EMAC->Command |= CR_FULL_DUP; LPC_EMAC->IPGT = IPGT_FULL_DUP; } else { // Otherwise we are in half duplex mode LPC_EMAC->IPGT = IPGT_HALF_DUP; } // Now configure 100MBit or 10MBit mode if (value & 0x0002) { // 10MBit mode LPC_EMAC->SUPP = 0; } else { // 100MBit mode LPC_EMAC->SUPP = SUPP_SPEED; } break; case LAN8720_ID: value = ReadFromPHY (PHY_REG_SCSR); /* PHY Extended Status Register */ // Now configure for full/half duplex mode if (value & (1<<4)) { /* bit 4: 1 = Full Duplex, 0 = Half Duplex */ // We are in full duplex is enabled mode LPC_EMAC->MAC2 |= MAC2_FULL_DUP; LPC_EMAC->Command |= CR_FULL_DUP; LPC_EMAC->IPGT = IPGT_FULL_DUP; }else { // Otherwise we are in half duplex mode LPC_EMAC->IPGT = IPGT_HALF_DUP; } // Now configure 100MBit or 10MBit mode if (value & (1<<3)) { /* bit 3: 1 = 100Mbps, 0 = 10Mbps */ // 100MBit mode LPC_EMAC->SUPP = SUPP_SPEED; }else { // 10MBit mode LPC_EMAC->SUPP = 0; } break; } // Now set the Ethernet MAC Address registers // NOTE - MAC address must be unique on the network! LPC_EMAC->SA0 = (MYMAC_1 << 8) | MYMAC_2; // Station address 0 Reg LPC_EMAC->SA1 = (MYMAC_3 << 8) | MYMAC_4; // Station address 1 Reg LPC_EMAC->SA2 = (MYMAC_5 << 8) | MYMAC_6; // Station address 2 Reg // Now initialise the Rx descriptors for (loop = 0; loop < NUM_RX_FRAG; loop++) { RX_DESC_PACKET(loop) = RX_BUF(loop); RX_DESC_CTRL(loop) = RCTRL_INT | (ETH_FRAG_SIZE-1); RX_STAT_INFO(loop) = 0; RX_STAT_HASHCRC(loop) = 0; } // Set up the Receive Descriptor Base address register LPC_EMAC->RxDescriptor = RX_DESC_BASE; // Set up the Receive Status Base address register LPC_EMAC->RxStatus = RX_STAT_BASE; // Setup the Receive Number of Descriptor register LPC_EMAC->RxDescriptorNumber = NUM_RX_FRAG-1; // Set Receive Consume Index register to 0 LPC_EMAC->RxConsumeIndex = 0; // Now initialise the Tx descriptors for (loop = 0; loop < NUM_TX_FRAG; loop++) { TX_DESC_PACKET(loop) = TX_BUF(loop); TX_DESC_CTRL(loop) = 0; TX_STAT_INFO(loop) = 0; } // Set up the Transmit Descriptor Base address register LPC_EMAC->TxDescriptor = TX_DESC_BASE; // Set up the Transmit Status Base address register LPC_EMAC->TxStatus = TX_STAT_BASE; // Setup the Transmit Number of Descriptor register LPC_EMAC->TxDescriptorNumber = NUM_TX_FRAG-1; // Set Transmit Consume Index register to 0 LPC_EMAC->TxProduceIndex = 0; // Receive Broadcast and Perfect Match Packets LPC_EMAC->RxFilterCtrl = RFC_BCAST_EN | RFC_PERFECT_EN; // Enable interrupts MAC Module Control Interrupt Enable Register LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE; // Reset all ethernet interrupts in MAC module LPC_EMAC->IntClear = 0xFFFF; // Finally enable receive and transmit mode in ethernet core LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN); LPC_EMAC->MAC1 |= MAC1_REC_EN; }
BOOL LPC24XX_EMAC_lwip_init ( struct netif *pNetIf ) { UINT32 i; LPC24XX_EMAC & ENET = *(LPC24XX_EMAC *)LPC24XX_EMAC::c_EMAC_Base; /* Power Up the EMAC controller. */ LPC24XX::SYSCON().PCONP |= LPC24XX_SYSCON::ENABLE_ENET; /* Connect EMAC pins */ LPC24XX_EMAC_lwip_setpins( ENET_PHY_lwip_get_MII_mode() ); /* Reset EMAC */ ENET.MAC_MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES; ENET.MAC_COMMAND = CR_REG_RES | CR_TX_RES | CR_RX_RES; HAL_Time_Sleep_MicroSeconds(1); /* Initialize MAC control registers. */ ENET.MAC_MAC1 = 0; ENET.MAC_MAC2 = MAC2_CRC_EN | MAC2_PAD_EN; ENET.MAC_MAXF = ETH_MAX_FLEN; ENET.MAC_CLRT = CLRT_DEF; ENET.MAC_IPGR = IPGR_DEF; if ( !ENET_PHY_lwip_get_MII_mode() ) { /* Enable RMII mode in MAC command register */ ENET.MAC_COMMAND = ENET.MAC_COMMAND | CR_RMII; } /* Reset MII Management hardware */ ENET.MAC_MCFG = MCFG_RES_MII; HAL_Time_Sleep_MicroSeconds(1); /* Set MDC Clock divider */ ENET.MAC_MCFG = ENET_PHY_lwip_get_MDC_Clk_Div() & MCFG_CLK_SEL; /* Initialiaze external ethernet Phy */ if ( !ENET_PHY_lwip_init() ) { return FALSE; } /* Set the Ethernet MAC Address registers */ ENET.MAC_SA2 = (pNetIf->hwaddr[1] << 8) | pNetIf->hwaddr[0]; ENET.MAC_SA1 = (pNetIf->hwaddr[3] << 8) | pNetIf->hwaddr[2]; ENET.MAC_SA0 = (pNetIf->hwaddr[5] << 8) | pNetIf->hwaddr[4]; /* Setup the Rx DMA Descriptors */ for (i = 0; i < NUM_RX_FRAG; i++) { RX_DESC_PACKET(i) = RX_BUF(i); RX_DESC_CTRL(i) = RCTRL_INT | (ETH_FRAG_SIZE-1); RX_STAT_INFO(i) = 0; RX_STAT_HASHCRC(i) = 0; } /* Set the EMAC Rx Descriptor Registers. */ ENET.MAC_RXDESCRIPTOR = RX_DESC_BASE; ENET.MAC_RXSTATUS = RX_STAT_BASE; ENET.MAC_RXDESCRIPTORNUM = NUM_RX_FRAG-1; ENET.MAC_RXCONSUMEINDEX = 0; /* Setup the Tx DMA Descriptors */ for (i = 0; i < NUM_TX_FRAG; i++) { TX_DESC_PACKET(i) = TX_BUF(i); TX_DESC_CTRL(i) = 0; TX_STAT_INFO(i) = 0; } /* Set the EMAC Tx Descriptor Registers. */ ENET.MAC_TXDESCRIPTOR = TX_DESC_BASE; ENET.MAC_TXSTATUS = TX_STAT_BASE; ENET.MAC_TXDESCRIPTORNUM = NUM_TX_FRAG-1; ENET.MAC_TXPRODUCEINDEX = 0; /* Receive Broadcast and Perfect Match Packets */ ENET.MAC_RXFILTERCTRL = RFC_PERFECT_EN | RFC_BCAST_EN; /* Enable EMAC interrupts. */ ENET.MAC_INTENABLE = INT_RX_DONE | INT_TX_DONE | INT_TX_UNDERRUN | INT_RX_OVERRUN; /* Reset all interrupts */ ENET.MAC_INTCLEAR = 0xFFFF; /* Enable receive and transmit */ ENET.MAC_COMMAND |= (CR_RX_EN | CR_TX_EN); ENET.MAC_MAC1 |= MAC1_REC_EN; return TRUE; }