]> git.sur5r.net Git - freertos/blobdiff - Demo/ColdFire_MCF52233_Eclipse/RTOSDemo/webserver/FEC.c
Continue work on MCF52233 demo.
[freertos] / Demo / ColdFire_MCF52233_Eclipse / RTOSDemo / webserver / FEC.c
index cd704ed04ffcf0fd6cc402579b8aa5bdde93e925..5e82b8223f682a4910e5b8fc93493b29c06e9096 100644 (file)
@@ -60,31 +60,35 @@ infinite. */
 #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
@@ -319,7 +323,7 @@ unsigned portCHAR *pcBufPointer;
        /* 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
@@ -341,11 +345,10 @@ unsigned portCHAR *pcBufPointer;
        }\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
@@ -360,6 +363,7 @@ const unsigned portCHAR ucMACAddress[6] =
 \r
        /* Create the semaphore used by the ISR to wake the uIP task. */\r
        vSemaphoreCreateBinary( xFECSemaphore );\r
+       vSemaphoreCreateBinary( xTxSemaphore );\r
 \r
        prvInitialiseFECBuffers();\r
 \r
@@ -517,7 +521,8 @@ unsigned portBASE_TYPE ux;
        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
@@ -527,6 +532,38 @@ unsigned portBASE_TYPE ux;
 }\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
@@ -562,37 +599,31 @@ void vDiscardRxData( void )
 \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
@@ -600,9 +631,14 @@ portLONG l;
                                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
@@ -623,8 +659,7 @@ portBASE_TYPE xHighPriorityTaskWoken = pdFALSE;
        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
@@ -633,12 +668,14 @@ portBASE_TYPE xHighPriorityTaskWoken = pdFALSE;
                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
@@ -651,5 +688,5 @@ void __attribute__ ((interrupt)) __cs3_isr_interrupt_96( void ) { vFEC_ISR(); }
 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