unsigned long ulGetEMACRxData( void ) { unsigned long ulLen = 0; long lIndex; if( EMAC->RxProduceIndex != EMAC->RxConsumeIndex ) { /* Mark the current buffer as free as uip_buf is going to be set to the buffer that contains the received data. */ prvReturnBuffer( uip_buf ); ulLen = ( RX_STAT_INFO( EMAC->RxConsumeIndex ) & RINFO_SIZE ) - 3; uip_buf = ( unsigned char * ) RX_DESC_PACKET( EMAC->RxConsumeIndex ); /* Allocate a new buffer to the descriptor. */ RX_DESC_PACKET( EMAC->RxConsumeIndex ) = ( unsigned long ) prvGetNextBuffer(); /* Move the consume index onto the next position, ensuring it wraps to the beginning at the appropriate place. */ lIndex = EMAC->RxConsumeIndex; lIndex++; if( lIndex >= NUM_RX_FRAG ) { lIndex = 0; } EMAC->RxConsumeIndex = lIndex; } return ulLen; }
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(); }
unsigned long ulEMACRead( void ) { unsigned long ulBytesReceived; ulBytesReceived = prvCheckRxFifoStatus(); if( ulBytesReceived > 0 ) { /* Mark the pxDescriptor buffer as free as uip_buf is going to be set to the buffer that contains the received data. */ prvReturnBuffer( uip_buf ); /* Point uip_buf to the data about ot be processed. */ uip_buf = ( void * ) pxCurrentRxDesc->buf_p; /* Allocate a new buffer to the descriptor, as uip_buf is now using it's old descriptor. */ pxCurrentRxDesc->buf_p = prvGetNextBuffer(); /* Prepare the descriptor to go again. */ pxCurrentRxDesc->status &= ~( FP1 | FP0 ); pxCurrentRxDesc->status |= ACT; /* Move onto the next buffer in the ring. */ pxCurrentRxDesc = pxCurrentRxDesc->next; if( EDMAC.EDRRR.LONG == 0x00000000L ) { /* Restart Ethernet if it has stopped */ EDMAC.EDRRR.LONG = 0x00000001L; } } return ulBytesReceived; }
long lEMACInit( void ) { long lReturn = pdPASS; unsigned long ulID1, ulID2; /* Reset peripherals, configure port pins and registers. */ prvSetupEMACHardware(); /* Check the PHY part number is as expected. */ ulID1 = prvReadPHY( PHY_REG_IDR1, &lReturn ); ulID2 = prvReadPHY( PHY_REG_IDR2, &lReturn ); if( ( (ulID1 << 16UL ) | ( ulID2 & 0xFFFFUL ) ) == KS8721_ID ) { /* Set the Ethernet MAC Address registers */ EMAC->SA0 = ( configMAC_ADDR0 << 8 ) | configMAC_ADDR1; EMAC->SA1 = ( configMAC_ADDR2 << 8 ) | configMAC_ADDR3; EMAC->SA2 = ( configMAC_ADDR4 << 8 ) | configMAC_ADDR5; /* Initialize Tx and Rx DMA Descriptors */ prvInitDescriptors(); /* Receive broadcast and perfect match packets */ EMAC->RxFilterCtrl = RFC_UCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN; /* Setup the PHY. */ prvConfigurePHY(); } else { lReturn = pdFAIL; } /* Check the link status. */ if( lReturn == pdPASS ) { lReturn = prvSetupLinkStatus(); } if( lReturn == pdPASS ) { /* Initialise uip_buf to ensure it points somewhere valid. */ uip_buf = prvGetNextBuffer(); /* Reset all interrupts */ EMAC->IntClear = ( INT_RX_OVERRUN | INT_RX_ERR | INT_RX_FIN | INT_RX_DONE | INT_TX_UNDERRUN | INT_TX_ERR | INT_TX_FIN | INT_TX_DONE | INT_SOFT_INT | INT_WAKEUP ); /* Enable receive and transmit mode of MAC Ethernet core */ EMAC->Command |= ( CR_RX_EN | CR_TX_EN ); EMAC->MAC1 |= MAC1_REC_EN; } return lReturn; }
void vEMACWrite( void ) { long x; /* Wait until the second transmission of the last packet has completed. */ for( x = 0; x < emacTX_WAIT_ATTEMPTS; x++ ) { if( ( xTxDescriptors[ 1 ].status & ACT ) != 0 ) { /* Descriptor is still active. */ vTaskDelay( emacTX_WAIT_DELAY_ms ); } else { break; } } /* Is the descriptor free after waiting for it? */ if( ( xTxDescriptors[ 1 ].status & ACT ) != 0 ) { /* Something has gone wrong. */ prvResetEverything(); } /* Setup both descriptors to transmit the frame. */ xTxDescriptors[ 0 ].buf_p = ( char * ) uip_buf; xTxDescriptors[ 0 ].bufsize = uip_len; xTxDescriptors[ 1 ].buf_p = ( char * ) uip_buf; xTxDescriptors[ 1 ].bufsize = uip_len; /* uip_buf is being sent by the Tx descriptor. Allocate a new buffer for use by the stack. */ uip_buf = prvGetNextBuffer(); /* Clear previous settings and go. */ xTxDescriptors[0].status &= ~( FP1 | FP0 ); xTxDescriptors[0].status |= ( FP1 | FP0 | ACT ); xTxDescriptors[1].status &= ~( FP1 | FP0 ); xTxDescriptors[1].status |= ( FP1 | FP0 | ACT ); EDMAC.EDTRR.LONG = 0x00000001; }
void vEMACWrite( void ) { long x; /* Wait until the second transmission of the last packet has completed. */ for( x = 0; x < emacTX_WAIT_ATTEMPTS; x++ ) { if( ( xTxDescriptors[ 1 ].status & TX_BD_R ) != 0 ) { /* Descriptor is still active. */ vTaskDelay( emacTX_WAIT_DELAY_ms ); } else { break; } } /* Is the descriptor free after waiting for it? */ if( ( xTxDescriptors[ 1 ].status & TX_BD_R ) != 0 ) { /* Something has gone wrong. */ prvResetEverything(); } /* Setup both descriptors to transmit the frame. */ xTxDescriptors[ 0 ].data = ( uint8_t * ) __REV( ( unsigned long ) uip_buf ); xTxDescriptors[ 0 ].length = __REVSH( uip_len ); xTxDescriptors[ 1 ].data = ( uint8_t * ) __REV( ( unsigned long ) uip_buf ); xTxDescriptors[ 1 ].length = __REVSH( uip_len ); /* uip_buf is being sent by the Tx descriptor. Allocate a new buffer for use by the stack. */ uip_buf = prvGetNextBuffer(); /* Clear previous settings and go. */ xTxDescriptors[ 0 ].status |= ( TX_BD_R | TX_BD_L ); xTxDescriptors[ 1 ].status |= ( TX_BD_R | TX_BD_L ); /* Start the Tx. */ ENET_TDAR = ENET_TDAR_TDAR_MASK; }
unsigned short usEMACRead( void ) { unsigned short usBytesReceived; usBytesReceived = prvCheckRxStatus(); usBytesReceived = __REVSH( usBytesReceived ); if( usBytesReceived > 0 ) { /* Mark the pxDescriptor buffer as free as uip_buf is going to be set to the buffer that contains the received data. */ prvReturnBuffer( uip_buf ); /* Point uip_buf to the data about to be processed. */ uip_buf = ( void * ) pxCurrentRxDesc->data; uip_buf = ( void * ) __REV( ( unsigned long ) uip_buf ); /* Allocate a new buffer to the descriptor, as uip_buf is now using it's old descriptor. */ pxCurrentRxDesc->data = ( uint8_t * ) prvGetNextBuffer(); pxCurrentRxDesc->data = ( uint8_t* ) __REV( ( unsigned long ) pxCurrentRxDesc->data ); /* Prepare the descriptor to go again. */ pxCurrentRxDesc->status |= RX_BD_E; /* Move onto the next buffer in the ring. */ ulRxDescriptorIndex++; if( ulRxDescriptorIndex >= emacNUM_RX_DESCRIPTORS ) { ulRxDescriptorIndex = 0UL; } pxCurrentRxDesc = &( xRxDescriptors[ ulRxDescriptorIndex ] ); /* Restart Ethernet if it has stopped */ ENET_RDAR = ENET_RDAR_RDAR_MASK; } return usBytesReceived; }