Put some belt and braces checks into the updated SmartFusion MAC driver.

pull/4/head
Richard Barry 14 years ago
parent d23df3d0af
commit f6879be327

@ -63,7 +63,7 @@ extern "C" {
/* Allocating this many buffers will always ensure there is one free as, even /* Allocating this many buffers will always ensure there is one free as, even
though TX_RING_SIZE is set to two, the two Tx descriptors will only ever point though TX_RING_SIZE is set to two, the two Tx descriptors will only ever point
to the same buffer. */ to the same buffer. */
#define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE + 1 #define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE
#define macBUFFER_SIZE 1488 #define macBUFFER_SIZE 1488
/***************************************************************/ /***************************************************************/
@ -420,18 +420,29 @@ MSS_MAC_tx_packet
configASSERT( usLength <= MSS_MAX_PACKET_SIZE ); configASSERT( usLength <= MSS_MAX_PACKET_SIZE );
} }
/* Check if second descriptor is free, if it is then the first must taskENTER_CRITICAL();
also be free. */ {
/* Check both Tx descriptors are free, meaning the double send has completed. */
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 ) ) 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 ) )
{ {
error = MAC_BUFFER_IS_FULL; error = MAC_BUFFER_IS_FULL;
} }
}
taskEXIT_CRITICAL();
configASSERT( ( g_mss_mac.tx_desc_index == 0 ) );
if( error == MAC_OK ) if( error == MAC_OK )
{ {
/* Ensure nothing is going to get sent until both descriptors are ready.
This is done to prevent a Tx end occurring prior to the second descriptor
being ready. */
MAC_BITBAND->CSR6_ST = 0u;
/* Assumed TX_RING_SIZE == 2. A #error directive checks this is the /* Assumed TX_RING_SIZE == 2. A #error directive checks this is the
case. */ case. */
taskENTER_CRITICAL();
{
for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ ) for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ )
{ {
g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u; g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u;
@ -442,7 +453,7 @@ MSS_MAC_tx_packet
/* Every buffer can hold a full frame so they are always first and last /* Every buffer can hold a full frame so they are always first and last
descriptor */ descriptor */
g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS | TDES1_IC; g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS;
/* set data size */ /* set data size */
g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= usLength; g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= usLength;
@ -479,19 +490,24 @@ MSS_MAC_tx_packet
(desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK; (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK;
/* Give ownership of descriptor to the MAC */ /* Give ownership of descriptor to the MAC */
g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0 = RDES0_OWN; g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0 = TDES0_OWN;
g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE; g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE;
MAC_start_transmission();
MAC->CSR1 = 1u;
} }
} }
taskEXIT_CRITICAL();
}
if (error == MAC_OK) if (error == MAC_OK)
{ {
error = (int32_t)usLength; error = (int32_t)usLength;
/* Start sending now both descriptors are set up. This is done to
prevent a Tx end occurring prior to the second descriptor being
ready. */
MAC_BITBAND->CSR6_ST = 1u;
MAC->CSR1 = 1u;
/* The buffer pointed to by uip_buf is now assigned to a Tx descriptor. /* The buffer pointed to by uip_buf is now assigned to a Tx descriptor.
Find anothere free buffer for uip_buf. */ Find anothere free buffer for uip_buf. */
uip_buf = MAC_obtain_buffer(); uip_buf = MAC_obtain_buffer();
@ -594,7 +610,6 @@ MSS_MAC_rx_packet
* will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING * will keep trying to read till time_out expires or data is read, if MSS_MAC_BLOCKING
* value is given as time_out, function will wait for the reception to complete. * value is given as time_out, function will wait for the reception to complete.
* *
* @param instance Pointer to a MAC_instance_t structure
* @param pacData The pointer to the packet data. * @param pacData The pointer to the packet data.
* @param time_out Time out value in milli seconds for receiving. * @param time_out Time out value in milli seconds for receiving.
* if value is #MSS_MAC_BLOCKING, there will be no time out. * if value is #MSS_MAC_BLOCKING, there will be no time out.
@ -1057,8 +1072,7 @@ MSS_MAC_prepare_rx_descriptor
(desc & (CSR8_MFO_MASK|CSR8_MFC_MASK)); (desc & (CSR8_MFO_MASK|CSR8_MFC_MASK));
/* Give ownership of descriptor to the MAC */ /* Give ownership of descriptor to the MAC */
g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 = g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 = RDES0_OWN;
RDES0_OWN;
g_mss_mac.rx_desc_index = (g_mss_mac.rx_desc_index + 1u) % RX_RING_SIZE; g_mss_mac.rx_desc_index = (g_mss_mac.rx_desc_index + 1u) % RX_RING_SIZE;
/* Start receive */ /* Start receive */
@ -1431,10 +1445,19 @@ static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n)
*/ */
void MSS_MAC_FreeTxBuffers( void ) void MSS_MAC_FreeTxBuffers( void )
{ {
/* 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( g_mss_mac.tx_descriptors[ 0 ].buffer_1 != NULL )
{
if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == 0 ) && ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == 0 ) ) if( ( ( (g_mss_mac.tx_descriptors[ 0 ].descriptor_0) & TDES0_OWN) == 0 ) && ( ( (g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == 0 ) )
{ {
configASSERT( g_mss_mac.tx_descriptors[ 0 ].buffer_1 == g_mss_mac.tx_descriptors[ 1 ].buffer_1 );
MAC_release_buffer( ( unsigned char * ) g_mss_mac.tx_descriptors[ 0 ].buffer_1 ); MAC_release_buffer( ( unsigned char * ) g_mss_mac.tx_descriptors[ 0 ].buffer_1 );
MAC_release_buffer( ( unsigned char * ) g_mss_mac.tx_descriptors[ 1 ].buffer_1 );
/* Just to mark the fact that the buffer has already been released. */
g_mss_mac.tx_descriptors[ 0 ].buffer_1 == NULL;
}
} }
} }
@ -1447,11 +1470,14 @@ void MSS_MAC_FreeTxBuffers( void )
*/ */
unsigned char *MAC_obtain_buffer( void ) unsigned char *MAC_obtain_buffer( void )
{ {
long lIndex; long lIndex, lAttempt = 0, lDescriptor, lBufferIsInUse;
unsigned char *pcReturn = NULL; unsigned char *pcReturn = NULL;
unsigned char *pcBufferAddress;
/* Find and return the address of a buffer that is not being used. Mark /* Find and return the address of a buffer that is not being used. Mark
the buffer as now in use. */ the buffer as now in use. */
while( ( lAttempt <= 1 ) && ( pcReturn == NULL ) )
{
for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ ) for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
{ {
if( ucMACBufferInUse[ lIndex ] == pdFALSE ) if( ucMACBufferInUse[ lIndex ] == pdFALSE )
@ -1462,6 +1488,56 @@ unsigned char *pcReturn = NULL;
} }
} }
if( pcReturn == NULL )
{
/* Did not find a buffer. That should not really happen, but could if
an interrupt was missed. See if any buffers are marked as in use, but
are not actually in use. */
for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )
{
pcBufferAddress = &( xMACBuffers.ucBuffer[ lIndex ][ 0 ] );
lBufferIsInUse = pdFALSE;
/* Is the buffer used by an Rx descriptor? */
for( lDescriptor = 0; lDescriptor < RX_RING_SIZE; lDescriptor++ )
{
if( g_mss_mac.rx_descriptors[ lDescriptor ].buffer_1 == ( uint32_t ) pcBufferAddress )
{
/* The buffer is in use by an Rx descriptor. */
lBufferIsInUse = pdTRUE;
break;
}
}
if( lBufferIsInUse != pdTRUE )
{
/* Is the buffer used by an Tx descriptor? */
for( lDescriptor = 0; lDescriptor < TX_RING_SIZE; lDescriptor++ )
{
if( g_mss_mac.tx_descriptors[ lDescriptor ].buffer_1 == ( uint32_t ) pcBufferAddress )
{
/* The buffer is in use by an Tx descriptor. */
lBufferIsInUse = pdTRUE;
break;
}
}
}
/* If the buffer was not found to be in use by either a Tx or an
Rx descriptor, but the buffer is marked as in use, then mark the
buffer to be in it's correct state of "not in use". */
if( ( lBufferIsInUse == pdFALSE ) && ( ucMACBufferInUse[ lIndex ] == pdTRUE ) )
{
ucMACBufferInUse[ lIndex ] = pdFALSE;
}
}
}
/* If any buffer states were changed it might be that a buffer can now
be obtained. Try again, but only one more time. */
lAttempt++;
}
configASSERT( pcReturn ); configASSERT( pcReturn );
return pcReturn; return pcReturn;
} }

@ -17,7 +17,7 @@
#define BUS_ARBITRATION_SCHEME 0 #define BUS_ARBITRATION_SCHEME 0
#define PROGRAMMABLE_BURST_LENGTH 0 #define PROGRAMMABLE_BURST_LENGTH 0
#define RX_RING_SIZE 4 #define RX_RING_SIZE 5
#define SETUP_FRAME_TIME_OUT 10000 #define SETUP_FRAME_TIME_OUT 10000
#define STATE_CHANGE_TIME_OUT 10000 #define STATE_CHANGE_TIME_OUT 10000
#define TX_RING_SIZE 2 #define TX_RING_SIZE 2

Loading…
Cancel
Save