From 4013104e2f4de80d4a64fe432e06f28da0df929e Mon Sep 17 00:00:00 2001 From: richardbarry Date: Mon, 18 Apr 2011 18:11:03 +0000 Subject: [PATCH] Continue work on the SmartFusion web server demo. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1365 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../mss_ethernet_mac/mss_ethernet_mac.c | 344 +++++++++--------- .../mss_ethernet_mac/mss_ethernet_mac.h | 82 ++--- .../mss_ethernet_mac/mss_ethernet_mac_regs.h | 4 +- Demo/CORTEX_A2F200_SoftConsole/uIP_Task.c | 120 +++--- 4 files changed, 285 insertions(+), 265 deletions(-) diff --git a/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c b/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c index 014ce512c..3b85fd65b 100644 --- a/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c +++ b/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.c @@ -51,6 +51,12 @@ extern "C" { #define MAC_TIME_OUT (-6) #define MAC_TOO_SMALL_PACKET (-7) +/* 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 +to the same buffer. */ +#define macNUM_BUFFERS RX_RING_SIZE + TX_RING_SIZE +#define macBUFFER_SIZE 1500 + /***************************************************************/ MAC_instance_t g_mss_mac; @@ -75,6 +81,7 @@ static const int8_t ErrorMessages[][MAX_ERROR_MESSAGE_WIDTH] = { static MAC_instance_t* NULL_instance; static uint8_t* NULL_buffer; static MSS_MAC_callback_t NULL_callback; +unsigned char *uip_buf = NULL; /**************************** INTERNAL FUNCTIONS ******************************/ @@ -95,6 +102,20 @@ static void MAC_memset(uint8_t *s, uint8_t c, uint32_t n); static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n); static void MAC_memset_All(MAC_instance_t *s, uint32_t c); +static unsigned char *MAC_obtain_buffer( void ); +static void MAC_release_buffer( unsigned char *pcBufferToRelease ); + +#if( TX_RING_SIZE != 2 ) + #error This uIP Ethernet driver required TX_RING_SIZE to be set to 2 +#endif + +/* Buffers that will dynamically be allocated to/from the Tx and Rx descriptors. */ +static unsigned char ucMACBuffers[ macNUM_BUFFERS ][ macBUFFER_SIZE ]; + +/* Each array position indicated whether or not the buffer of the same index +is currently allocated to a descriptor (pdFALSE) or is free for use (pdTRUE). */ +static unsigned char ucMACBufferFree[ macNUM_BUFFERS ]; + /***************************************************************************//** * Initializes the Ethernet Controller. * This function will prepare the Ethernet Controller for first time use in a @@ -114,6 +135,12 @@ MSS_MAC_init const uint8_t mac_address[6] = { DEFAULT_MAC_ADDRESS }; int32_t a; + /* To start with all buffers are free. */ + for( a = 0; a < macNUM_BUFFERS; a++ ) + { + ucMACBufferFree[ a ] = pdTRUE; + } + /* Try to reset chip */ MAC_BITBAND->CSR0_SWR = 1u; @@ -139,13 +166,19 @@ MSS_MAC_init /* Give the ownership to the MAC */ g_mss_mac.rx_descriptors[a].descriptor_0 = RDES0_OWN; g_mss_mac.rx_descriptors[a].descriptor_1 = (MSS_RX_BUFF_SIZE << RDES1_RBS1_OFFSET); - g_mss_mac.rx_descriptors[a].buffer_1 = (uint32_t)g_mss_mac.rx_buffers[a]; + + /* Allocate a buffer to the descriptor, then mark the buffer as in use + (not free). */ + g_mss_mac.rx_descriptors[a].buffer_1 = ( unsigned long ) &( ucMACBuffers[ a ][ 0 ] ); + ucMACBufferFree[ a ] = pdFALSE; } g_mss_mac.rx_descriptors[RX_RING_SIZE-1].descriptor_1 |= RDES1_RER; for( a = 0; a < TX_RING_SIZE; a++ ) { - g_mss_mac.tx_descriptors[a].buffer_1 = ( unsigned long ) NULL; /* _RB_ used to be "(uint32_t)g_mss_mac.tx_buffers[a];" but set to NULL now to implement a zero copy scheme. */ + /* Buffers only get allocated to the Tx buffers when something is + actually tranmitted. */ + g_mss_mac.tx_descriptors[a].buffer_1 = ( unsigned long ) NULL; } g_mss_mac.tx_descriptors[TX_RING_SIZE - 1].descriptor_1 |= TDES1_TER; @@ -343,31 +376,13 @@ MSS_MAC_get_configuration( void ) /***************************************************************************//** - Sends a packet to the Ethernet Controller. + Sends a packet from the uIP stack to the Ethernet Controller. The MSS_MAC_tx_packet() function is used to send a packet to the MSS Ethernet - MAC. This function writes pacLen bytes of the packet contained in pacData into + MAC. This function writes uip_len bytes of the packet contained in uip_buf into the transmit FIFO and then activates the transmitter for this packet. If space - is available in the FIFO, the function will return once pacLen bytes of the + is available in the FIFO, the function will return once pac_len bytes of the packet have been placed into the FIFO and the transmitter has been started. - This function will not wait for the transmission to complete. If space is not - available in FIFO, the function will keep trying until time_out expires. The - function will wait for the transmission to complete when the time_out parameter - is set to MSS_MAC_BLOCKING. - - @param pacData - The pacData parameter is a pointer to the packet data to be transmitted. - - @param pacLen - The pacLen parameter is the number of bytes in the packet to be transmitted. - - @param time_out - The time_out parameter is the timeout value for the transmission in milliseconds. - The time_out parameter value can be one of the following values: - • Unsigned integer greater than 0 and less than 0x01000000 - • MSS_MAC_BLOCKING – there will be no timeout. - • MSS_MAC_NONBLOCKING – the function will return immediately if the MSS Ethernet - MAC does not have any available transmit descriptor. This would happen when - several packets are already queued into the MSS Ethernet MAC transmit descriptor FIFO. + This function will not wait for the transmission to complete. @return The function returns zero if a timeout occurs otherwise it returns size of the packet. @@ -378,119 +393,101 @@ MSS_MAC_get_configuration( void ) int32_t MSS_MAC_tx_packet ( - const uint8_t *pacData, - uint16_t pacLen, - uint32_t time_out + unsigned short usLength ) { uint32_t desc; + unsigned long ulDescriptor; int32_t error = MAC_OK; + extern unsigned char *uip_buf; ASSERT( MAC_test_instance() == MAC_OK ); - ASSERT( pacData != NULL_buffer ); + ASSERT( uip_buf != NULL_buffer ); - ASSERT( pacLen >= 12 ); + ASSERT( usLength >= 12 ); if( (g_mss_mac.flags & FLAG_EXCEED_LIMIT) == 0u ) { - ASSERT( pacLen <= MSS_MAX_PACKET_SIZE ); + ASSERT( usLength <= MSS_MAX_PACKET_SIZE ); } - ASSERT( (time_out == MSS_MAC_BLOCKING) || - (time_out == MSS_MAC_NONBLOCKING) || - ((time_out >= 1) && (time_out <= 0x01000000uL)) ); - - if( time_out == MSS_MAC_NONBLOCKING ) - { - /* Check if current descriptor is free */ - if(((g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) - { - error = MAC_BUFFER_IS_FULL; - } - } - else + /* Check if second descriptor is free, if it is then the first must + also be free. */ + if(((g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) { - /* Wait until descriptor is free */ - if( time_out != MSS_MAC_BLOCKING ) { - MAC_set_time_out( time_out ); - } - - while( (((g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0) & TDES0_OWN) == TDES0_OWN ) - && (error == MAC_OK) ) - { - /* transmit poll demand */ - MAC->CSR1 = 1u; - - if(time_out != MSS_MAC_BLOCKING){ - if(MAC_get_time_out() == 0u) { - error = MAC_TIME_OUT; - } - } - } + error = MAC_BUFFER_IS_FULL; } if( error == MAC_OK ) { + /* Assumed TX_RING_SIZE == 2. */ + for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ ) + { + g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 = 0u; - g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u; + if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) { + g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= TDES1_AC; + } - if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) { - g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_AC; - } + /* Every buffer can hold a full frame so they are always first and last + descriptor */ + g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= TDES1_LS | TDES1_FS; - /* Every buffer can hold a full frame so they are always first and last - descriptor */ - g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS; + /* set data size */ + g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= usLength; - /* set data size */ - g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= pacLen; + /* reset end of ring */ + g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER; - /* reset end of ring */ - g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER; + if( usLength > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */ + { + usLength = (uint16_t)MSS_TX_BUFF_SIZE; + } - /* copy data into buffer */ - if( pacLen > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */ - { - pacLen = (uint16_t)MSS_TX_BUFF_SIZE; - } + /* The data buffer is assigned to the Tx descriptor. */ + g_mss_mac.tx_descriptors[ ulDescriptor ].buffer_1 = ( unsigned long ) uip_buf; - g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1 = ( unsigned long ) pacData; + /* update counters */ + desc = g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_0; + if( (desc & TDES0_LO) != 0u ) { + g_mss_mac.statistics.tx_loss_of_carrier++; + } + if( (desc & TDES0_NC) != 0u ) { + g_mss_mac.statistics.tx_no_carrier++; + } + if( (desc & TDES0_LC) != 0u ) { + g_mss_mac.statistics.tx_late_collision++; + } + if( (desc & TDES0_EC) != 0u ) { + g_mss_mac.statistics.tx_excessive_collision++; + } + if( (desc & TDES0_UF) != 0u ) { + g_mss_mac.statistics.tx_underflow_error++; + } + g_mss_mac.statistics.tx_collision_count += + (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK; - /* update counters */ - desc = g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0; - if( (desc & TDES0_LO) != 0u ) { - g_mss_mac.statistics.tx_loss_of_carrier++; - } - if( (desc & TDES0_NC) != 0u ) { - g_mss_mac.statistics.tx_no_carrier++; - } - if( (desc & TDES0_LC) != 0u ) { - g_mss_mac.statistics.tx_late_collision++; - } - if( (desc & TDES0_EC) != 0u ) { - g_mss_mac.statistics.tx_excessive_collision++; - } - if( (desc & TDES0_UF) != 0u ) { - g_mss_mac.statistics.tx_underflow_error++; - } - g_mss_mac.statistics.tx_collision_count += - (desc >> TDES0_CC_OFFSET) & TDES0_CC_MASK; + /* Give ownership of descriptor to the MAC */ + g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_0 = TDES0_OWN; - /* 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_desc_index = 0; + } + } - g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE; + /* Start transmission */ + MAC_start_transmission(); - /* Start transmission */ - MAC_start_transmission(); + /* transmit poll demand */ + MAC->CSR1 = 1u; - /* transmit poll demand */ - MAC->CSR1 = 1u; - } - + + if (error == MAC_OK) { - error = (int32_t)pacLen; + /* The buffer uip_buf was pointing to is now under the control of the + MAC (it is being transmitted). Set uip_buf to point to a free buffer. */ + uip_buf = MAC_obtain_buffer(); + error = (int32_t)usLength; } else { @@ -535,24 +532,11 @@ MSS_MAC_rx_pckt_size /***************************************************************************//** - * Receives a packet from the Ethernet Controller. + * Receives a packet from the Ethernet Controller into the uIP stack. * This function reads a packet from the receive FIFO of the controller and - * places it into pacData. If time_out parameter is zero the function will return - * immediately (after the copy operation if data is available. Otherwise the function - * 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. - * - * @param instance Pointer to a MAC_instance_t structure - * @param pacData The pointer to the packet data. - * @param pacLen The pacLen parameter is the size in bytes of the pacData - * buffer where the received data will be copied. - * @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_NONBLOCKING, function will return immediately - * if there is no packet waiting. - * Otherwise value must be greater than 0 and smaller than - * 0x01000000. - * @return Size of packet if packet fits in pacData. + * places it into uip_buf. + + * @return Size of packet if packet fits in uip_buf. * 0 if there is no received packet. * @see MAC_rx_pckt_size() * @see MAC_tx_packet() @@ -560,42 +544,16 @@ MSS_MAC_rx_pckt_size int32_t MSS_MAC_rx_packet ( - unsigned char **pacData, - uint16_t pacLen, - uint32_t time_out + void ) { uint16_t frame_length=0u; - int8_t exit=0; ASSERT( MAC_test_instance() == MAC_OK ); - ASSERT( (time_out == MSS_MAC_BLOCKING) || - (time_out == MSS_MAC_NONBLOCKING) || - ((time_out >= 1) && (time_out <= 0x01000000UL)) ); - + MAC_dismiss_bad_frames(); - /* wait for a packet */ - if( time_out != MSS_MAC_BLOCKING ) { - if( time_out == MSS_MAC_NONBLOCKING ) { - MAC_set_time_out( 0u ); - } else { - MAC_set_time_out( time_out ); - } - } - - while( ((g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & - RDES0_OWN) != 0u) && (exit == 0) ) - { - if( time_out != MSS_MAC_BLOCKING ) - { - if( MAC_get_time_out() == 0u ) { - exit = 1; - } - } - } - - if(exit == 0) + if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u ) { frame_length = ( ( g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >> @@ -604,14 +562,21 @@ MSS_MAC_rx_packet /* strip crc */ frame_length -= 4u; - if( frame_length > pacLen ) { + if( frame_length > macBUFFER_SIZE ) { return MAC_NOT_ENOUGH_SPACE; } - *pacData = ( unsigned char * ) g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1; + /* uip_buf is about to point to the buffer that contains the received + data, mark the buffer that uip_buf is currently pointing to as free + again. */ + MAC_release_buffer( uip_buf ); + uip_buf = ( unsigned char * ) g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1; + + /* The buffer the Rx descriptor was pointing to is now in use by the + uIP stack - allocate a new buffer to the Rx descriptor. */ + g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 = ( unsigned long ) MAC_obtain_buffer(); MSS_MAC_prepare_rx_descriptor(); - } return ((int32_t)frame_length); } @@ -1444,10 +1409,10 @@ static void MAC_memset_All(MAC_instance_t *s, uint32_t c) MAC_memset( s->mac_address, (uint8_t)c, 6u ); MAC_memset( s->mac_filter_data, (uint8_t)c, 90u ); s->phy_address = (uint8_t)c; - for(count = 0; countrx_buffers[count], (uint8_t)c, (MSS_RX_BUFF_SIZE + 4u) ); - } +// for(count = 0; countrx_buffers[count], (uint8_t)c, (MSS_RX_BUFF_SIZE + 4u) ); +// } s->rx_desc_index =c; for(count = 0; countstatistics.tx_no_carrier = c; s->statistics.tx_underflow_error = c; s->time_out_value = c; - for(count = 0; count < TX_RING_SIZE ;count++) - { - MAC_memset( s->tx_buffers[count], (uint8_t)c, MSS_TX_BUFF_SIZE ); - } +// for(count = 0; count < TX_RING_SIZE ;count++) +// { +// MAC_memset( s->tx_buffers[count], (uint8_t)c, MSS_TX_BUFF_SIZE ); +// } s->tx_desc_index = c; for(count = 0; count < TX_RING_SIZE ;count++) { @@ -1505,6 +1470,59 @@ static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n) } } +void MSS_MAC_TxBufferCompleted( void ) +{ +unsigned char *pxTransmittedBuffer; + + /* Was it the second transmission that has completed? */ + if( ( g_mss_mac.tx_descriptors[ 1 ].descriptor_0 & TDES0_OWN ) == 0UL ) + { + pxTransmittedBuffer = ( unsigned char * ) g_mss_mac.tx_descriptors[ 1 ].buffer_1; + + /* The buffer has been transmitted and is no longer in use. */ + MAC_release_buffer( pxTransmittedBuffer ); + } +} + +static unsigned char *MAC_obtain_buffer( void ) +{ +long lIndex; +unsigned char *pcReturn = NULL; + + /* Find and return the address of a buffer that is not being used. Mark + the buffer as now in use. */ + for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ ) + { + if( ucMACBufferFree[ lIndex ] == pdTRUE ) + { + pcReturn = &( ucMACBuffers[ lIndex ][ 0 ] ); + break; + } + } + + configASSERT( pcReturn ); + return pcReturn; +} + +void MAC_release_buffer( unsigned char *pucBufferToRelease ) +{ +long lIndex; + + /* uip_buf is going to point to a different buffer - first ensure the buffer + it is currently pointing to is marked as being free again. */ + for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ ) + { + if( pucBufferToRelease == &( ucMACBuffers[ lIndex ][ 0 ] ) ) + { + /* This is the buffer in use, mark it as being free. */ + ucMACBufferFree[ lIndex ] = pdTRUE; + break; + } + } +} + + + #ifdef __cplusplus } #endif diff --git a/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.h b/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.h index 92729c65b..0757105a5 100644 --- a/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.h +++ b/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac.h @@ -342,37 +342,26 @@ MSS_MAC_get_configuration /***************************************************************************//** - * Sends a packet to the Ethernet Controller. - * This function writes pacLen bytes of the packet contained in pacData into the - * transmit FIFO of the controller and then activates the transmitter for this - * packet. If space is available in FIFO, the function will return once lBufLen - * bytes of the packet have been placed into the FIFO and the transmitter has been - * started. The function will not wait for the transmission to complete. If space - * is not available in FIFO, the function will keep trying till time_out expires, - * if MSS_MAC_BLOCKING value is given as time_out, function will wait for the - * transmission to complete. - * - * @param pacData the pointer to the packet data to be transmitted. - * @param pacLen number of bytes in the packet to be transmitted. - * @param time_out Time out value for transmision. - * If value is #MSS_MAC_BLOCKING, there will be no time out. - * If value is #MSS_MAC_NONBLOCKING, function will return immediately - * on buffer full case. - * Otherwise value must be greater than 0 and smaller than - * 0x01000000. - * @return Returns 0 if time out occurs otherwise returns size - * of the packet. - * @see MAC_rx_packet() + Sends a packet from the uIP stack to the Ethernet Controller. + The MSS_MAC_tx_packet() function is used to send a packet to the MSS Ethernet + MAC. This function writes uip_len bytes of the packet contained in uip_buf into + the transmit FIFO and then activates the transmitter for this packet. If space + is available in the FIFO, the function will return once pac_len bytes of the + packet have been placed into the FIFO and the transmitter has been started. + This function will not wait for the transmission to complete. + + @return + The function returns zero if a timeout occurs otherwise it returns size of the packet. + + @see MAC_rx_packet() */ + int32_t MSS_MAC_tx_packet ( - const uint8_t *pacData, - uint16_t pacLen, - uint32_t time_out + unsigned short usLength ); - /***************************************************************************//** * Returns available packet's size. * @@ -401,25 +390,11 @@ MSS_MAC_prepare_rx_descriptor ); /***************************************************************************//** - * Receives a packet from the Ethernet Controller. + * Receives a packet from the Ethernet Controller into the uIP stack. * This function reads a packet from the receive FIFO of the controller and - * places it into pacData. If time_out parameter is zero the function will return - * immediately (after the copy operation if data is available. Otherwise the function - * 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. - * - * @param pacData The pointer to the buffer where received packet data will - * be copied. Memory for the buffer should be allocated prior - * to calling this function. - * @param pacLen Size of the buffer, which the received data will be copied in, - * given in number of bytes. - * @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_NONBLOCKING, function will return immediately - * if there is no packet waiting. - * Otherwise value must be greater than 0 and smaller than - * 0x01000000. - * @return Size of packet if packet fits in pacData. + * places it into uip_buf. + + * @return Size of packet if packet fits in uip_buf. * 0 if there is no received packet. * @see MAC_rx_pckt_size() * @see MAC_tx_packet() @@ -427,9 +402,7 @@ MSS_MAC_prepare_rx_descriptor int32_t MSS_MAC_rx_packet ( - uint8_t **pacData, - uint16_t pacLen, - uint32_t time_out + void ); @@ -587,6 +560,23 @@ MSS_MAC_get_statistics mss_mac_statistics_id_t stat_id ); +/* + * Ensure uip_buf is pointing to a valid and free buffer before any transmissions + * initiated by the uIP stack occur. + */ +unsigned char *MSS_MAC_GetTxDescriptor( void ); + +/* + * A buffer is no longer required by the application. Hand it back to the + * control of the MAC hardware. + */ +void MSS_MAC_ReleaseBuffer( unsigned char *pucBuffer ); + +/* + * The double Tx has completed. Hand back the Tx buffer to the control of + * the MAC hardware. + */ +void MSS_MAC_TxBufferCompleted( void ); #ifdef __cplusplus } #endif diff --git a/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac_regs.h b/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac_regs.h index 7f03e0adb..380e24163 100644 --- a/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac_regs.h +++ b/Demo/CORTEX_A2F200_SoftConsole/MicroSemi_Code/drivers/mss_ethernet_mac/mss_ethernet_mac_regs.h @@ -65,12 +65,12 @@ typedef struct { /* transmit related info: */ uint32_t tx_desc_index; /**< index of the transmit descriptor getting used*/ - uint8_t tx_buffers[TX_RING_SIZE][MSS_TX_BUFF_SIZE];/**< array of transmit buffers*/ +// uint8_t tx_buffers[TX_RING_SIZE][MSS_TX_BUFF_SIZE];/**< array of transmit buffers*/ MAC_descriptor_t tx_descriptors[TX_RING_SIZE];/**< array of transmit descriptors*/ /* receive related info: */ uint32_t rx_desc_index; /**< index of the receive descriptor getting used*/ - uint8_t rx_buffers[RX_RING_SIZE][MSS_RX_BUFF_SIZE+4];/**< array of receive buffers*/ +// uint8_t rx_buffers[RX_RING_SIZE][MSS_RX_BUFF_SIZE+4];/**< array of receive buffers*/ MAC_descriptor_t rx_descriptors[RX_RING_SIZE];/**< array of receive descriptors*/ uint8_t phy_address; /**< MII address of the connected PHY*/ diff --git a/Demo/CORTEX_A2F200_SoftConsole/uIP_Task.c b/Demo/CORTEX_A2F200_SoftConsole/uIP_Task.c index 41c4b02a7..7e64f3b70 100644 --- a/Demo/CORTEX_A2F200_SoftConsole/uIP_Task.c +++ b/Demo/CORTEX_A2F200_SoftConsole/uIP_Task.c @@ -76,7 +76,7 @@ /* The buffer used by the uIP stack to both receive and send. This points to one of the Ethernet buffers when its actually in use. */ -unsigned char *uip_buf = NULL; +extern unsigned char *uip_buf; static const unsigned char ucMACAddress[] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 }; @@ -131,7 +131,6 @@ static void prvInitEmac( void ); void vEMACWrite( void ); -unsigned long ulEMACRead( void ); long lEMACWaitForLink( void ); /* @@ -163,7 +162,7 @@ clock_time_t clock_time( void ) void vuIP_Task( void *pvParameters ) { -portBASE_TYPE i, xDoneSomething; +portBASE_TYPE i; unsigned long ulNewEvent; ( void ) pvParameters; @@ -176,47 +175,52 @@ unsigned long ulNewEvent; for( ;; ) { - xDoneSomething = pdFALSE; - - /* Is there received data ready to be processed? */ - uip_len = ( unsigned short ) ulEMACRead(); - - if( ( uip_len > 0 ) && ( uip_buf != NULL ) ) + if( ( ulUIP_Events & uipETHERNET_TX_EVENT ) != 0UL ) { - /* Standard uIP loop taken from the uIP manual. */ - if( xHeader->type == htons( UIP_ETHTYPE_IP ) ) - { - uip_arp_ipin(); - uip_input(); + ulUIP_Events &= ~uipETHERNET_TX_EVENT; + MSS_MAC_TxBufferCompleted(); + } - /* If the above function invocation resulted in data that - should be sent out on the network, the global variable - uip_len is set to a value > 0. */ - if( uip_len > 0 ) + if( ( ulUIP_Events & uipETHERNET_RX_EVENT ) != 0UL ) + { + ulUIP_Events &= ~uipETHERNET_RX_EVENT; + + /* Is there received data ready to be processed? */ + uip_len = MSS_MAC_rx_packet(); + + if( ( uip_len > 0 ) && ( uip_buf != NULL ) ) + { + /* Standard uIP loop taken from the uIP manual. */ + if( xHeader->type == htons( UIP_ETHTYPE_IP ) ) { - uip_arp_out(); - vEMACWrite(); + uip_arp_ipin(); + uip_input(); + + /* If the above function invocation resulted in data that + should be sent out on the network, the global variable + uip_len is set to a value > 0. */ + if( uip_len > 0 ) + { + uip_arp_out(); + vEMACWrite(); + } } - - xDoneSomething = pdTRUE; - } - else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) ) - { - uip_arp_arpin(); - - /* If the above function invocation resulted in data that - should be sent out on the network, the global variable - uip_len is set to a value > 0. */ - if( uip_len > 0 ) + else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) ) { - vEMACWrite(); + uip_arp_arpin(); + + /* If the above function invocation resulted in data that + should be sent out on the network, the global variable + uip_len is set to a value > 0. */ + if( uip_len > 0 ) + { + vEMACWrite(); + } } - - xDoneSomething = pdTRUE; } } - if( ( ( ulUIP_Events & uipPERIODIC_TIMER_EVENT ) != 0UL ) && ( uip_buf != NULL ) ) + if( ( ulUIP_Events & uipPERIODIC_TIMER_EVENT ) != 0UL ) { ulUIP_Events &= ~uipPERIODIC_TIMER_EVENT; @@ -233,18 +237,16 @@ unsigned long ulNewEvent; vEMACWrite(); } } + } - /* Call the ARP timer function every 10 seconds. */ - if( ( ulUIP_Events & uipARP_TIMER_EVENT ) != 0 ) - { - ulUIP_Events &= ~uipARP_TIMER_EVENT; - uip_arp_timer(); - } - - xDoneSomething = pdTRUE; + /* Call the ARP timer function every 10 seconds. */ + if( ( ulUIP_Events & uipARP_TIMER_EVENT ) != 0 ) + { + ulUIP_Events &= ~uipARP_TIMER_EVENT; + uip_arp_timer(); } - - if( xDoneSomething == pdFALSE ) + + if( ulUIP_Events == pdFALSE ) { xQueueReceive( xEMACEventQueue, &ulNewEvent, portMAX_DELAY ); ulUIP_Events |= ulNewEvent; @@ -359,14 +361,17 @@ unsigned long ulUIPEvents = 0UL; if( ( ulISREvents & MSS_MAC_EVENT_PACKET_SEND ) != 0UL ) { - /* Handle send event. */ - ulUIPEvents |= uipETHERNET_TX_EVENT; + ulUIP_Events |= uipETHERNET_TX_EVENT; } if( ( ulISREvents & MSS_MAC_EVENT_PACKET_RECEIVED ) != 0UL ) { /* Wake the uIP task as new data has arrived. */ ulUIPEvents |= uipETHERNET_RX_EVENT; + } + + if( ulUIPEvents != 0UL ) + { xQueueSendFromISR( xEMACEventQueue, &ulUIPEvents, &lHigherPriorityTaskWoken ); } @@ -376,7 +381,6 @@ unsigned long ulUIPEvents = 0UL; static void prvInitEmac( void ) { -unsigned long ulMACCfg; const unsigned char ucPHYAddress = 1; MSS_MAC_init( ucPHYAddress ); @@ -391,13 +395,21 @@ const unsigned char ucPHYAddress = 1; void vEMACWrite( void ) { - MSS_MAC_tx_packet( uip_buf, uip_len, 0 ); -} -/*-----------------------------------------------------------*/ +const long lMaxAttempts = 10; +long lAttempt; +const portTickType xShortDelay = ( 10 / portTICK_RATE_MS ); -unsigned long ulEMACRead( void ) -{ - return MSS_MAC_rx_packet( &uip_buf, ( MSS_RX_BUFF_SIZE + 4 ), 0UL ); + for( lAttempt = 0; lAttempt < lMaxAttempts; lAttempt++ ) + { + if( MSS_MAC_tx_packet( uip_len ) != 0 ) + { + break; + } + else + { + vTaskDelay( xShortDelay ); + } + } } /*-----------------------------------------------------------*/ -- 2.39.2