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(); }
void vEMAC_ISR_Handler( void ) { unsigned long ul = EDMAC.EESR.LONG; long lHigherPriorityTaskWoken = pdFALSE; extern xSemaphoreHandle xEMACSemaphore; static long ulTxEndInts = 0; /* Has a Tx end occurred? */ if( ul & emacTX_END_INTERRUPT ) { ++ulTxEndInts; if( ulTxEndInts >= 2 ) { /* Only return the buffer to the pool once both Txes have completed. */ prvReturnBuffer( ( void * ) xTxDescriptors[ 0 ].buf_p ); ulTxEndInts = 0; } EDMAC.EESR.LONG = emacTX_END_INTERRUPT; } /* Has an Rx end occurred? */ if( ul & emacRX_END_INTERRUPT ) { /* Make sure the Ethernet task is not blocked waiting for a packet. */ xSemaphoreGiveFromISR( xEMACSemaphore, &lHigherPriorityTaskWoken ); portYIELD_FROM_ISR( lHigherPriorityTaskWoken ); EDMAC.EESR.LONG = emacRX_END_INTERRUPT; } }
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; }
unsigned long ulEMACRead( void ) { unsigned long ulBytesReceived; ulBytesReceived = prvCheckRxFifoStatus(); if( ulBytesReceived > 0 ) { xCurrentRxDesc->status &= ~( FP1 | FP0 ); xCurrentRxDesc->status |= ACT; if( EDMAC.EDRRR.LONG == 0x00000000L ) { /* Restart Ethernet if it has stopped */ EDMAC.EDRRR.LONG = 0x00000001L; } /* 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 ); uip_buf = ( void * ) xCurrentRxDesc->buf_p; /* Move onto the next buffer in the ring. */ xCurrentRxDesc = xCurrentRxDesc->next; } return ulBytesReceived; }
__interrupt void vEMAC_ISR_Handler( void ) { unsigned long ul = EDMAC.EESR.LONG; long lHigherPriorityTaskWoken = pdFALSE; extern xQueueHandle xEMACEventQueue; const unsigned long ulRxEvent = uipETHERNET_RX_EVENT; __enable_interrupt(); /* Has a Tx end occurred? */ if( ul & emacTX_END_INTERRUPT ) { /* Only return the buffer to the pool once both Txes have completed. */ prvReturnBuffer( ( void * ) xTxDescriptors[ 0 ].buf_p ); EDMAC.EESR.LONG = emacTX_END_INTERRUPT; } /* Has an Rx end occurred? */ if( ul & emacRX_END_INTERRUPT ) { /* Make sure the Ethernet task is not blocked waiting for a packet. */ xQueueSendFromISR( xEMACEventQueue, &ulRxEvent, &lHigherPriorityTaskWoken ); portYIELD_FROM_ISR( lHigherPriorityTaskWoken ); EDMAC.EESR.LONG = emacRX_END_INTERRUPT; } }
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 vEMAC_TxISRHandler( void ) { /* Clear the interrupt. */ ENET_EIR = ENET_EIR_TXF_MASK; /* Check the buffers have not already been freed in the first of the two Tx interrupts - which could potentially happen if the second Tx completed during the interrupt for the first Tx. */ if( xTxDescriptors[ 0 ].data != NULL ) { if( ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) && ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) ) { configASSERT( xTxDescriptors[ 0 ].data == xTxDescriptors[ 1 ].data ); xTxDescriptors[ 0 ].data = ( uint8_t* ) __REV( ( unsigned long ) xTxDescriptors[ 0 ].data ); prvReturnBuffer( xTxDescriptors[ 0 ].data ); /* Just to mark the fact that the buffer has already been released. */ xTxDescriptors[ 0 ].data = NULL; } } }
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; }