]> git.sur5r.net Git - freertos/commitdiff
Put some belt and braces checks into the updated SmartFusion MAC driver.
authorrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 28 Apr 2011 15:01:40 +0000 (15:01 +0000)
committerrichardbarry <richardbarry@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Thu, 28 Apr 2011 15:01:40 +0000 (15:01 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1396 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

Demo/CORTEX_A2F200_IAR_and_Keil/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c
Demo/CORTEX_A2F200_IAR_and_Keil/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac_user_cfg.h

index 891cb888c812d742e5603d5b1dcef6c6cf863b94..098e1d3b37a54079c80f848c02b35fdf76819275 100644 (file)
@@ -63,7 +63,7 @@ extern "C" {
 /* Allocating this many buffers will always ensure there is one free as, even\r
 though TX_RING_SIZE is set to two, the two Tx descriptors will only ever point\r
 to the same buffer. */\r
-#define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE + 1\r
+#define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE\r
 #define macBUFFER_SIZE 1488\r
 \r
 /***************************************************************/\r
@@ -420,78 +420,94 @@ MSS_MAC_tx_packet
                configASSERT( usLength <= MSS_MAX_PACKET_SIZE );\r
        }\r
 \r
-       /* Check if second descriptor is free, if it is then the first must\r
-       also be free. */\r
-       if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) || ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) )\r
+       taskENTER_CRITICAL();\r
        {\r
-               error = MAC_BUFFER_IS_FULL;\r
+               /* Check both Tx descriptors are free, meaning the double send has completed. */\r
+               if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) || ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) )\r
+               {\r
+                       error = MAC_BUFFER_IS_FULL;\r
+               }\r
        }\r
+       taskEXIT_CRITICAL();\r
 \r
+       configASSERT( ( g_mss_mac.tx_desc_index == 0 ) );\r
        \r
        if( error == MAC_OK )\r
        {\r
+               /* Ensure nothing is going to get sent until both descriptors are ready.\r
+               This is done to prevent a Tx end occurring prior to the second descriptor\r
+               being ready. */\r
+               MAC_BITBAND->CSR6_ST = 0u;\r
+\r
                /* Assumed TX_RING_SIZE == 2.  A #error directive checks this is the\r
                case. */\r
-               for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ )\r
+               taskENTER_CRITICAL();\r
                {\r
-                       g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u;\r
-\r
-                       if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) {\r
-                               g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_AC;\r
-                       }\r
-\r
-                       /* Every buffer can hold a full frame so they are always first and last\r
-                          descriptor */\r
-               g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS | TDES1_IC;\r
-\r
-                       /* set data size */\r
-                       g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= usLength;\r
-\r
-                       /* reset end of ring */\r
-                       g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;\r
-\r
-                       if( usLength > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */\r
+                       for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ )\r
                        {\r
-                               usLength = (uint16_t)MSS_TX_BUFF_SIZE;\r
-                       }\r
-\r
-                       /* The data buffer is assigned to the Tx descriptor. */\r
-                       g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1 = ( unsigned long ) uip_buf;\r
-\r
-                       /* update counters */\r
-                       desc = g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0;\r
-                       if( (desc & TDES0_LO) != 0u ) {\r
-                               g_mss_mac.statistics.tx_loss_of_carrier++;\r
-                       }\r
-                       if( (desc & TDES0_NC) != 0u ) {\r
-                               g_mss_mac.statistics.tx_no_carrier++;\r
-                       }\r
-                       if( (desc & TDES0_LC) != 0u ) {\r
-                               g_mss_mac.statistics.tx_late_collision++;\r
-                       }\r
-                       if( (desc & TDES0_EC) != 0u ) {\r
-                               g_mss_mac.statistics.tx_excessive_collision++;\r
-                       }\r
-                       if( (desc & TDES0_UF) != 0u ) {\r
-                               g_mss_mac.statistics.tx_underflow_error++;\r
-                       }\r
-                       g_mss_mac.statistics.tx_collision_count +=\r
-                               (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;\r
-\r
-                       /* Give ownership of descriptor to the MAC */\r
-                       g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0 = RDES0_OWN;\r
-                       \r
-                       g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE;\r
-                       \r
-                       MAC_start_transmission();\r
-                       MAC->CSR1 = 1u;\r
-               }               \r
+                               g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u;\r
+       \r
+                               if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) {\r
+                                       g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_AC;\r
+                               }\r
+       \r
+                               /* Every buffer can hold a full frame so they are always first and last\r
+                                  descriptor */\r
+                               g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS;\r
+       \r
+                               /* set data size */\r
+                               g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= usLength;\r
+       \r
+                               /* reset end of ring */\r
+                               g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;\r
+       \r
+                               if( usLength > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */\r
+                               {\r
+                                       usLength = (uint16_t)MSS_TX_BUFF_SIZE;\r
+                               }\r
+       \r
+                               /* The data buffer is assigned to the Tx descriptor. */\r
+                               g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1 = ( unsigned long ) uip_buf;\r
+       \r
+                               /* update counters */\r
+                               desc = g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0;\r
+                               if( (desc & TDES0_LO) != 0u ) {\r
+                                       g_mss_mac.statistics.tx_loss_of_carrier++;\r
+                               }\r
+                               if( (desc & TDES0_NC) != 0u ) {\r
+                                       g_mss_mac.statistics.tx_no_carrier++;\r
+                               }\r
+                               if( (desc & TDES0_LC) != 0u ) {\r
+                                       g_mss_mac.statistics.tx_late_collision++;\r
+                               }\r
+                               if( (desc & TDES0_EC) != 0u ) {\r
+                                       g_mss_mac.statistics.tx_excessive_collision++;\r
+                               }\r
+                               if( (desc & TDES0_UF) != 0u ) {\r
+                                       g_mss_mac.statistics.tx_underflow_error++;\r
+                               }\r
+                               g_mss_mac.statistics.tx_collision_count +=\r
+                                       (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;\r
+       \r
+                               /* Give ownership of descriptor to the MAC */\r
+                               g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0 = TDES0_OWN;\r
+                               \r
+                               g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE;\r
+                       }               \r
+               }\r
+               taskEXIT_CRITICAL();\r
     }\r
        \r
     if (error == MAC_OK)\r
     {\r
         error = (int32_t)usLength;\r
                \r
+               /* Start sending now both descriptors are set up.  This is done to\r
+               prevent a Tx end occurring prior to the second descriptor being\r
+               ready. */\r
+               MAC_BITBAND->CSR6_ST = 1u;\r
+               MAC->CSR1 = 1u;\r
+               \r
                /* The buffer pointed to by uip_buf is now assigned to a Tx descriptor.\r
                Find anothere free buffer for uip_buf. */\r
                uip_buf = MAC_obtain_buffer();\r
@@ -594,8 +610,7 @@ MSS_MAC_rx_packet
  * will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING\r
  * value is given as time_out, function will wait for the reception to complete.\r
  *\r
- * @param instance      Pointer to a MAC_instance_t structure\r
- * @param pacData       The pointer to the packet data.\r
+  * @param pacData       The pointer to the packet data.\r
  * @param time_out      Time out value in milli seconds for receiving.\r
  *                                         if value is #MSS_MAC_BLOCKING, there will be no time out.\r
  *                                         if value is #MSS_MAC_NONBLOCKING, function will return immediately\r
@@ -1057,8 +1072,7 @@ MSS_MAC_prepare_rx_descriptor
                (desc & (CSR8_MFO_MASK|CSR8_MFC_MASK));\r
 \r
        /* Give ownership of descriptor to the MAC */\r
-       g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 =\r
-               RDES0_OWN;\r
+       g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 = RDES0_OWN;\r
        g_mss_mac.rx_desc_index = (g_mss_mac.rx_desc_index + 1u) % RX_RING_SIZE;\r
 \r
        /* Start receive */\r
@@ -1431,10 +1445,19 @@ static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n)
  */\r
 void MSS_MAC_FreeTxBuffers( void )\r
 {\r
-       if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == 0 ) && ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == 0 ) )\r
+       /* Check the buffers have not already been freed in the first of the\r
+       two Tx interrupts - which could potentially happen if the second Tx completed\r
+       during the interrupt for the first Tx. */\r
+       if( g_mss_mac.tx_descriptors[ 0 ].buffer_1 != NULL )\r
        {\r
-               MAC_release_buffer( ( unsigned char * ) g_mss_mac.tx_descriptors[ 0 ].buffer_1 );\r
-               MAC_release_buffer( ( unsigned char * ) g_mss_mac.tx_descriptors[ 1 ].buffer_1 );\r
+               if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == 0 ) && ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == 0 ) )\r
+               {\r
+                       configASSERT( g_mss_mac.tx_descriptors[ 0 ].buffer_1 == g_mss_mac.tx_descriptors[ 1 ].buffer_1 );\r
+                       MAC_release_buffer( ( unsigned char * ) g_mss_mac.tx_descriptors[ 0 ].buffer_1 );\r
+                       \r
+                       /* Just to mark the fact that the buffer has already been released. */\r
+                       g_mss_mac.tx_descriptors[ 0 ].buffer_1 == NULL;\r
+               }\r
        }\r
 }\r
 \r
@@ -1447,19 +1470,72 @@ void MSS_MAC_FreeTxBuffers( void )
  */\r
 unsigned char *MAC_obtain_buffer( void )\r
 {\r
-long lIndex;\r
+long lIndex, lAttempt = 0, lDescriptor, lBufferIsInUse;\r
 unsigned char *pcReturn = NULL;\r
+unsigned char *pcBufferAddress;\r
 \r
        /* Find and return the address of a buffer that is not being used.  Mark\r
        the buffer as now in use. */\r
-       for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )\r
+       while( ( lAttempt <= 1 ) && ( pcReturn == NULL ) )\r
        {\r
-               if( ucMACBufferInUse[ lIndex ] == pdFALSE )\r
+               for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )\r
                {\r
-                       pcReturn = &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] );\r
-                       ucMACBufferInUse[ lIndex ] = pdTRUE;\r
-                       break;\r
+                       if( ucMACBufferInUse[ lIndex ] == pdFALSE )\r
+                       {\r
+                               pcReturn = &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] );\r
+                               ucMACBufferInUse[ lIndex ] = pdTRUE;\r
+                               break;\r
+                       }\r
+               }\r
+               \r
+               if( pcReturn == NULL )\r
+               {\r
+                       /* Did not find a buffer.  That should not really happen, but could if\r
+                       an interrupt was missed.  See if any buffers are marked as in use, but\r
+                       are not actually in use. */\r
+                       for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )\r
+                       {\r
+                               pcBufferAddress = &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] );\r
+                               lBufferIsInUse = pdFALSE;\r
+                               \r
+                               /* Is the buffer used by an Rx descriptor? */\r
+                               for( lDescriptor = 0; lDescriptor < RX_RING_SIZE; lDescriptor++ )\r
+                               {\r
+                                       if( g_mss_mac.rx_descriptors[ lDescriptor ].buffer_1 == ( uint32_t ) pcBufferAddress )\r
+                                       {\r
+                                               /* The buffer is in use by an Rx descriptor. */\r
+                                               lBufferIsInUse = pdTRUE;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               \r
+                               if( lBufferIsInUse != pdTRUE )\r
+                               {\r
+                                       /* Is the buffer used by an Tx descriptor? */\r
+                                       for( lDescriptor = 0; lDescriptor < TX_RING_SIZE; lDescriptor++ )\r
+                                       {\r
+                                               if( g_mss_mac.tx_descriptors[ lDescriptor ].buffer_1 == ( uint32_t ) pcBufferAddress )\r
+                                               {\r
+                                                       /* The buffer is in use by an Tx descriptor. */\r
+                                                       lBufferIsInUse = pdTRUE;\r
+                                                       break;\r
+                                               }\r
+                                       }                       \r
+                               }\r
+                               \r
+                               /* If the buffer was not found to be in use by either a Tx or an\r
+                               Rx descriptor, but the buffer is marked as in use, then mark the\r
+                               buffer to be in it's correct state of "not in use". */\r
+                               if( ( lBufferIsInUse == pdFALSE ) && ( ucMACBufferInUse[ lIndex ] == pdTRUE ) )\r
+                               {\r
+                                       ucMACBufferInUse[ lIndex ] = pdFALSE;\r
+                               }\r
+                       }\r
                }\r
+                                                                                                                                       \r
+               /* If any buffer states were changed it might be that a buffer can now\r
+               be obtained.  Try again, but only one more time. */\r
+               lAttempt++;\r
        }\r
        \r
        configASSERT( pcReturn );\r
index d4d2cc4dfe1186a4f642ed9464c0313969d3fb18..8711243f4f5efeff4fe8ecf845ea4cdbe724ad99 100644 (file)
@@ -1,6 +1,6 @@
 /*******************************************************************************\r
  * (c) Copyright 2007 Actel Corporation.  All rights reserved.\r
- * \r
+ *\r
  * Actel:Firmware:MSS_Ethernet_MAC_Driver:2.0.103 configuration.\r
  *\r
  */\r
@@ -17,7 +17,7 @@
 \r
 #define BUS_ARBITRATION_SCHEME 0\r
 #define PROGRAMMABLE_BURST_LENGTH 0\r
-#define RX_RING_SIZE 4\r
+#define RX_RING_SIZE 5\r
 #define SETUP_FRAME_TIME_OUT 10000\r
 #define STATE_CHANGE_TIME_OUT 10000\r
 #define TX_RING_SIZE 2\r