#define netifBLOCK_TIME_WAITING_FOR_INPUT fecLINK_DELAY\r
\r
/* Constants used to delay while waiting for a tx descriptor to be free. */\r
-#define fecMAX_TX_WAIT_ATTEMPTS 4\r
-#define fecTX_BUFFER_WAIT ( 10 / portTICK_RATE_MS )\r
+#define fecTX_BUFFER_WAIT ( 200 / portTICK_RATE_MS )\r
\r
+/* We only use a single Tx descriptor - the duplicate send silicon errata\r
+actually assists in this case. */\r
+#define fecNUM_FEC_TX_BUFFERS ( 1 )\r
+#define fecTX_BUFFER_TO_USE ( 0 )\r
/*-----------------------------------------------------------*/\r
\r
/* The semaphore used to wake the uIP task when data arrives. */\r
-xSemaphoreHandle xFECSemaphore = NULL;\r
+xSemaphoreHandle xFECSemaphore = NULL, xTxSemaphore = NULL;\r
\r
/* The buffer used by the uIP stack. In this case the pointer is used to\r
point to one of the Rx buffers. */\r
unsigned portCHAR *uip_buf;\r
\r
/* The DMA descriptors. This is a char array to allow us to align it correctly. */\r
-static unsigned portCHAR xFECTxDescriptors_unaligned[ ( configNUM_FEC_TX_BUFFERS * sizeof( FECBD ) ) + 16 ];\r
+static unsigned portCHAR xFECTxDescriptors_unaligned[ ( fecNUM_FEC_TX_BUFFERS * sizeof( FECBD ) ) + 16 ];\r
static unsigned portCHAR xFECRxDescriptors_unaligned[ ( configNUM_FEC_RX_BUFFERS * sizeof( FECBD ) ) + 16 ];\r
static FECBD *xFECTxDescriptors;\r
static FECBD *xFECRxDescriptors;\r
\r
/* The DMA buffers. These are char arrays to allow them to be alligned correctly. */\r
static unsigned portCHAR ucFECRxBuffers[ ( configNUM_FEC_RX_BUFFERS * configFEC_BUFFER_SIZE ) + 16 ];\r
-static unsigned portBASE_TYPE uxNextRxBuffer = 0, uxNextTxBuffer = 0, uxIndexToBufferOwner = 0;\r
+static unsigned portBASE_TYPE uxNextRxBuffer = 0, uxIndexToBufferOwner = 0;\r
\r
/*-----------------------------------------------------------*/\r
\r
static void prvEnableFECInterrupts( void );\r
+static void prvResetFEC( portBASE_TYPE xCalledFromISR );\r
\r
/********************************************************************/\r
/*\r
/* Setup the buffers and descriptors. The data member does not point\r
anywhere yet as there is not yet anything to send and a zero copy policy\r
is used. */
- for( ux = 0; ux < configNUM_FEC_TX_BUFFERS; ux++ )\r
+ for( ux = 0; ux < fecNUM_FEC_TX_BUFFERS; ux++ )\r
{\r
xFECTxDescriptors[ ux ].status = TX_BD_TC;\r
xFECTxDescriptors[ ux ].data = NULL;\r
}\r
\r
/* Set the wrap bit in the last descriptors to form a ring. */\r
- xFECTxDescriptors[ configNUM_FEC_TX_BUFFERS - 1 ].status |= TX_BD_W;\r
+ xFECTxDescriptors[ fecNUM_FEC_TX_BUFFERS - 1 ].status |= TX_BD_W;\r
xFECRxDescriptors[ configNUM_FEC_RX_BUFFERS - 1 ].status |= RX_BD_W;\r
\r
uxNextRxBuffer = 0;\r
- uxNextTxBuffer = 0;\r
}\r
/*-----------------------------------------------------------*/\r
\r
\r
/* Create the semaphore used by the ISR to wake the uIP task. */\r
vSemaphoreCreateBinary( xFECSemaphore );\r
+ vSemaphoreCreateBinary( xTxSemaphore );\r
\r
prvInitialiseFECBuffers();\r
\r
MCF_INTC0_IMRH &= ~( MCF_INTC_IMRH_INT_MASK33 | MCF_INTC_IMRH_INT_MASK34 | MCF_INTC_IMRH_INT_MASK35 );\r
MCF_INTC0_IMRL &= ~( MCF_INTC_IMRL_INT_MASK25 | MCF_INTC_IMRL_INT_MASK26 | MCF_INTC_IMRL_INT_MASK27\r
| MCF_INTC_IMRL_INT_MASK28 | MCF_INTC_IMRL_INT_MASK29 | MCF_INTC_IMRL_INT_MASK30\r
- | MCF_INTC_IMRL_INT_MASK31 | MCF_INTC_IMRL_MASKALL );\r
+ | MCF_INTC_IMRL_INT_MASK31 | MCF_INTC_IMRL_INT_MASK23 | MCF_INTC_IMRL_INT_MASK24\r
+ | MCF_INTC_IMRL_MASKALL );\r
\r
/* Clear any pending FEC interrupt events */\r
MCF_FEC_EIR = MCF_FEC_EIR_CLEAR_ALL;\r
}\r
/*-----------------------------------------------------------*/\r
\r
+static void prvResetFEC( portBASE_TYPE xCalledFromISR )\r
+{\r
+portBASE_TYPE x;\r
+\r
+ if( xCalledFromISR == pdFALSE )\r
+ {\r
+ taskENTER_CRITICAL();\r
+ }\r
+\r
+ {\r
+ prvInitialiseFECBuffers();\r
+\r
+ /* Set the Reset bit and clear the Enable bit */\r
+ MCF_FEC_ECR = MCF_FEC_ECR_RESET;\r
+\r
+ /* Wait at least 8 clock cycles */\r
+ for( x = 0; x < 10; x++ )\r
+ {\r
+ asm( "NOP" );\r
+ }\r
+\r
+ MCF_FEC_ECR = MCF_FEC_ECR_ETHER_EN;\r
+ MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;\r
+ }\r
+\r
+ if( xCalledFromISR == pdFALSE )\r
+ {\r
+ taskEXIT_CRITICAL();\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
unsigned short usGetFECRxData( void )\r
{\r
unsigned portSHORT usLen;\r
\r
void vSendBufferToFEC( void )\r
{\r
-portLONG l;\r
-\r
- /* Get a DMA buffer into which we can write the data to send. */\r
- for( l = 0; l < fecMAX_TX_WAIT_ATTEMPTS; l++ )\r
+ /* Ensure no Tx frames are outstanding. */\r
+ if( xSemaphoreTake( xTxSemaphore, fecTX_BUFFER_WAIT ) == pdPASS )\r
{\r
- if( xFECTxDescriptors[ uxNextTxBuffer ].status & TX_BD_R )\r
+ /* Get a DMA buffer into which we can write the data to send. */\r
+ if( xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].status & TX_BD_R )\r
{\r
- /* Wait for the buffer to become available. */\r
- vTaskDelay( fecTX_BUFFER_WAIT );\r
+ /*** ERROR didn't expect this. Sledge hammer error handling. ***/\r
+ prvResetFEC( pdFALSE );\r
+\r
+ /* Make sure we leave the semaphore in the expected state as nothing\r
+ is being transmitted this will not happen in the Tx ISR. */\r
+ xSemaphoreGive( xTxSemaphore );\r
}\r
else\r
{\r
/* Setup the buffer descriptor for transmission. The data being\r
sent is actually stored in one of the Rx descripter buffers,\r
pointed to by uip_buf. */\r
- xFECTxDescriptors[ uxNextTxBuffer ].length = uip_len;\r
- xFECTxDescriptors[ uxNextTxBuffer ].status |= (TX_BD_R | TX_BD_L);\r
- xFECTxDescriptors[ uxNextTxBuffer ].data = uip_buf;\r
-\r
- /* Continue the Tx DMA (in case it was waiting for a new TxBD) */\r
- MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE;\r
+ xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].length = uip_len;\r
+ xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].status |= ( TX_BD_R | TX_BD_L );\r
+ xFECTxDescriptors[ fecTX_BUFFER_TO_USE ].data = uip_buf;\r
\r
/* Remember which Rx descriptor owns the buffer we are sending. */\r
uxIndexToBufferOwner = uxNextRxBuffer;\r
\r
- uxNextTxBuffer++;\r
- if( uxNextTxBuffer >= configNUM_FEC_TX_BUFFERS )\r
- {\r
- uxNextTxBuffer = 0;\r
- }\r
-\r
/* We have finished with this Rx descriptor now. */\r
uxNextRxBuffer++;\r
if( uxNextRxBuffer >= configNUM_FEC_RX_BUFFERS )\r
uxNextRxBuffer = 0;\r
}\r
\r
- break;\r
+ /* Continue the Tx DMA (in case it was waiting for a new TxBD) */\r
+ MCF_FEC_TDAR = MCF_FEC_TDAR_X_DES_ACTIVE;\r
}\r
}\r
+ else\r
+ {\r
+ vDiscardRxData();\r
+ }\r
}\r
/*-----------------------------------------------------------*/\r
\r
if( ulEvent & ( MCF_FEC_EIR_UN | MCF_FEC_EIR_RL | MCF_FEC_EIR_LC | MCF_FEC_EIR_EBERR | MCF_FEC_EIR_BABT | MCF_FEC_EIR_BABR | MCF_FEC_EIR_HBERR ) )\r
{\r
/* Sledge hammer error handling. */\r
- prvInitialiseFECBuffers();\r
- MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;\r
+ prvResetFEC( pdTRUE );\r
}\r
\r
if( ( ulEvent & MCF_FEC_EIR_TXF ) || ( ulEvent & MCF_FEC_EIR_TXB ) )\r
buffer has been sent we can mark the Rx descriptor as free again. */\r
xFECRxDescriptors[ uxIndexToBufferOwner ].status |= RX_BD_E;\r
MCF_FEC_RDAR = MCF_FEC_RDAR_R_DES_ACTIVE;\r
+ xSemaphoreGiveFromISR( xTxSemaphore, &xHighPriorityTaskWoken );\r
}\r
\r
portEND_SWITCHING_ISR( xHighPriorityTaskWoken );\r
}\r
/*-----------------------------------------------------------*/\r
\r
+void __attribute__ ((interrupt)) __cs3_isr_interrupt_87( void ) { vFEC_ISR(); }\r
void __attribute__ ((interrupt)) __cs3_isr_interrupt_88( void ) { vFEC_ISR(); }\r
void __attribute__ ((interrupt)) __cs3_isr_interrupt_89( void ) { vFEC_ISR(); }\r
void __attribute__ ((interrupt)) __cs3_isr_interrupt_90( void ) { vFEC_ISR(); }\r
void __attribute__ ((interrupt)) __cs3_isr_interrupt_97( void ) { vFEC_ISR(); }\r
void __attribute__ ((interrupt)) __cs3_isr_interrupt_98( void ) { vFEC_ISR(); }\r
void __attribute__ ((interrupt)) __cs3_isr_interrupt_99( void ) { vFEC_ISR(); }\r
-void __attribute__ ((interrupt)) __cs3_isr_interrupt_100( void ) { vFEC_ISR(); }\r
+\r
\r