#define MAC_TIME_OUT (-6)\r
#define MAC_TOO_SMALL_PACKET (-7)\r
\r
+/* 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\r
+#define macBUFFER_SIZE 1500\r
+\r
/***************************************************************/\r
MAC_instance_t g_mss_mac;\r
\r
static MAC_instance_t* NULL_instance;\r
static uint8_t* NULL_buffer;\r
static MSS_MAC_callback_t NULL_callback;\r
+unsigned char *uip_buf = NULL;\r
\r
/**************************** INTERNAL FUNCTIONS ******************************/\r
\r
static void MAC_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n);\r
static void MAC_memset_All(MAC_instance_t *s, uint32_t c);\r
\r
+static unsigned char *MAC_obtain_buffer( void );\r
+static void MAC_release_buffer( unsigned char *pcBufferToRelease );\r
+\r
+#if( TX_RING_SIZE != 2 )\r
+ #error This uIP Ethernet driver required TX_RING_SIZE to be set to 2\r
+#endif\r
+\r
+/* Buffers that will dynamically be allocated to/from the Tx and Rx descriptors. */\r
+static unsigned char ucMACBuffers[ macNUM_BUFFERS ][ macBUFFER_SIZE ];\r
+\r
+/* Each array position indicated whether or not the buffer of the same index\r
+is currently allocated to a descriptor (pdFALSE) or is free for use (pdTRUE). */\r
+static unsigned char ucMACBufferFree[ macNUM_BUFFERS ];\r
+\r
/***************************************************************************//**\r
* Initializes the Ethernet Controller.\r
* This function will prepare the Ethernet Controller for first time use in a\r
const uint8_t mac_address[6] = { DEFAULT_MAC_ADDRESS };\r
int32_t a;\r
\r
+ /* To start with all buffers are free. */\r
+ for( a = 0; a < macNUM_BUFFERS; a++ )\r
+ {\r
+ ucMACBufferFree[ a ] = pdTRUE;\r
+ }\r
+ \r
/* Try to reset chip */\r
MAC_BITBAND->CSR0_SWR = 1u;\r
\r
/* Give the ownership to the MAC */\r
g_mss_mac.rx_descriptors[a].descriptor_0 = RDES0_OWN;\r
g_mss_mac.rx_descriptors[a].descriptor_1 = (MSS_RX_BUFF_SIZE << RDES1_RBS1_OFFSET);\r
- g_mss_mac.rx_descriptors[a].buffer_1 = (uint32_t)g_mss_mac.rx_buffers[a];\r
+ \r
+ /* Allocate a buffer to the descriptor, then mark the buffer as in use\r
+ (not free). */\r
+ g_mss_mac.rx_descriptors[a].buffer_1 = ( unsigned long ) &( ucMACBuffers[ a ][ 0 ] );\r
+ ucMACBufferFree[ a ] = pdFALSE;\r
}\r
g_mss_mac.rx_descriptors[RX_RING_SIZE-1].descriptor_1 |= RDES1_RER;\r
\r
for( a = 0; a < TX_RING_SIZE; a++ )\r
{\r
- 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. */\r
+ /* Buffers only get allocated to the Tx buffers when something is\r
+ actually tranmitted. */\r
+ g_mss_mac.tx_descriptors[a].buffer_1 = ( unsigned long ) NULL;\r
}\r
g_mss_mac.tx_descriptors[TX_RING_SIZE - 1].descriptor_1 |= TDES1_TER;\r
\r
\r
\r
/***************************************************************************//**\r
- Sends a packet to the Ethernet Controller.\r
+ Sends a packet from the uIP stack to the Ethernet Controller.\r
The MSS_MAC_tx_packet() function is used to send a packet to the MSS Ethernet\r
- MAC. This function writes pacLen bytes of the packet contained in pacData into\r
+ MAC. This function writes uip_len bytes of the packet contained in uip_buf into\r
the transmit FIFO and then activates the transmitter for this packet. If space\r
- is available in the FIFO, the function will return once pacLen bytes of the\r
+ is available in the FIFO, the function will return once pac_len bytes of the\r
packet have been placed into the FIFO and the transmitter has been started.\r
- This function will not wait for the transmission to complete. If space is not\r
- available in FIFO, the function will keep trying until time_out expires. The\r
- function will wait for the transmission to complete when the time_out parameter\r
- is set to MSS_MAC_BLOCKING.\r
- \r
- @param pacData\r
- The pacData parameter is a pointer to the packet data to be transmitted.\r
- \r
- @param pacLen\r
- The pacLen parameter is the number of bytes in the packet to be transmitted.\r
- \r
- @param time_out\r
- The time_out parameter is the timeout value for the transmission in milliseconds.\r
- The time_out parameter value can be one of the following values:\r
- \95 Unsigned integer greater than 0 and less than 0x01000000\r
- \95 MSS_MAC_BLOCKING \96 there will be no timeout. \r
- \95 MSS_MAC_NONBLOCKING \96 the function will return immediately if the MSS Ethernet\r
- MAC does not have any available transmit descriptor. This would happen when\r
- several packets are already queued into the MSS Ethernet MAC transmit descriptor FIFO.\r
+ This function will not wait for the transmission to complete. \r
\r
@return\r
The function returns zero if a timeout occurs otherwise it returns size of the packet.\r
int32_t\r
MSS_MAC_tx_packet\r
(\r
- const uint8_t *pacData,\r
- uint16_t pacLen,\r
- uint32_t time_out\r
+ unsigned short usLength\r
)\r
{\r
uint32_t desc;\r
+ unsigned long ulDescriptor;\r
int32_t error = MAC_OK;\r
+ extern unsigned char *uip_buf;\r
\r
ASSERT( MAC_test_instance() == MAC_OK );\r
\r
- ASSERT( pacData != NULL_buffer );\r
+ ASSERT( uip_buf != NULL_buffer );\r
\r
- ASSERT( pacLen >= 12 );\r
+ ASSERT( usLength >= 12 );\r
\r
if( (g_mss_mac.flags & FLAG_EXCEED_LIMIT) == 0u )\r
{\r
- ASSERT( pacLen <= MSS_MAX_PACKET_SIZE );\r
+ ASSERT( usLength <= MSS_MAX_PACKET_SIZE );\r
}\r
\r
- ASSERT( (time_out == MSS_MAC_BLOCKING) ||\r
- (time_out == MSS_MAC_NONBLOCKING) ||\r
- ((time_out >= 1) && (time_out <= 0x01000000uL)) );\r
-\r
- if( time_out == MSS_MAC_NONBLOCKING )\r
- {\r
- /* Check if current descriptor is free */\r
- if(((g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0) & TDES0_OWN) == TDES0_OWN )\r
- {\r
- error = MAC_BUFFER_IS_FULL;\r
- }\r
- }\r
- else\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[ 1 ].descriptor_0) & TDES0_OWN) == TDES0_OWN )\r
{\r
- /* Wait until descriptor is free */\r
- if( time_out != MSS_MAC_BLOCKING ) {\r
- MAC_set_time_out( time_out );\r
- }\r
- \r
- while( (((g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0) & TDES0_OWN) == TDES0_OWN )\r
- && (error == MAC_OK) )\r
- {\r
- /* transmit poll demand */\r
- MAC->CSR1 = 1u;\r
- \r
- if(time_out != MSS_MAC_BLOCKING){\r
- if(MAC_get_time_out() == 0u) {\r
- error = MAC_TIME_OUT;\r
- }\r
- }\r
- }\r
+ error = MAC_BUFFER_IS_FULL;\r
}\r
\r
if( error == MAC_OK ) {\r
+ /* Assumed TX_RING_SIZE == 2. */\r
+ for( ulDescriptor = 0; ulDescriptor < TX_RING_SIZE; ulDescriptor++ )\r
+ {\r
+ g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 = 0u;\r
\r
- g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 = 0u;\r
+ if( (g_mss_mac.flags & FLAG_CRC_DISABLE) != 0u ) {\r
+ g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= TDES1_AC;\r
+ }\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
+ /* Every buffer can hold a full frame so they are always first and last\r
+ descriptor */\r
+ g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= TDES1_LS | TDES1_FS;\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
+ /* set data size */\r
+ g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= usLength;\r
\r
- /* set data size */\r
- g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= pacLen;\r
+ /* reset end of ring */\r
+ g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;\r
\r
- /* reset end of ring */\r
- g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;\r
+ if( usLength > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */\r
+ {\r
+ usLength = (uint16_t)MSS_TX_BUFF_SIZE;\r
+ }\r
\r
- /* copy data into buffer */\r
- if( pacLen > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */\r
- {\r
- pacLen = (uint16_t)MSS_TX_BUFF_SIZE;\r
- }\r
+ /* The data buffer is assigned to the Tx descriptor. */\r
+ g_mss_mac.tx_descriptors[ ulDescriptor ].buffer_1 = ( unsigned long ) uip_buf;\r
\r
- g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].buffer_1 = ( unsigned long ) pacData;\r
+ /* update counters */\r
+ desc = g_mss_mac.tx_descriptors[ ulDescriptor ].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
- /* 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
+ /* Give ownership of descriptor to the MAC */\r
+ g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_0 = TDES0_OWN;\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
+ g_mss_mac.tx_desc_index = 0; \r
+ }\r
+ }\r
\r
- g_mss_mac.tx_desc_index = (g_mss_mac.tx_desc_index + 1u) % (uint32_t)TX_RING_SIZE;\r
+ /* Start transmission */\r
+ MAC_start_transmission();\r
\r
- /* Start transmission */\r
- MAC_start_transmission();\r
+ /* transmit poll demand */\r
+ MAC->CSR1 = 1u;\r
\r
- /* transmit poll demand */\r
- MAC->CSR1 = 1u;\r
- }\r
- \r
+ \r
+ \r
if (error == MAC_OK)\r
{\r
- error = (int32_t)pacLen;\r
+ /* The buffer uip_buf was pointing to is now under the control of the \r
+ MAC (it is being transmitted). Set uip_buf to point to a free buffer. */\r
+ uip_buf = MAC_obtain_buffer();\r
+ error = (int32_t)usLength;\r
}\r
else\r
{\r
\r
\r
/***************************************************************************//**\r
- * Receives a packet from the Ethernet Controller.\r
+ * Receives a packet from the Ethernet Controller into the uIP stack.\r
* This function reads a packet from the receive FIFO of the controller and\r
- * places it into pacData. If time_out parameter is zero the function will return\r
- * immediately (after the copy operation if data is available. Otherwise the function\r
- * 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 pacLen The pacLen parameter is the size in bytes of the pacData\r
- * buffer where the received data will be copied.\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
- * if there is no packet waiting.\r
- * Otherwise value must be greater than 0 and smaller than\r
- * 0x01000000.\r
- * @return Size of packet if packet fits in pacData.\r
+ * places it into uip_buf.\r
+ \r
+ * @return Size of packet if packet fits in uip_buf.\r
* 0 if there is no received packet.\r
* @see MAC_rx_pckt_size()\r
* @see MAC_tx_packet()\r
int32_t\r
MSS_MAC_rx_packet\r
(\r
- unsigned char **pacData,\r
- uint16_t pacLen,\r
- uint32_t time_out\r
+ void\r
)\r
{\r
uint16_t frame_length=0u;\r
- int8_t exit=0;\r
\r
ASSERT( MAC_test_instance() == MAC_OK );\r
- ASSERT( (time_out == MSS_MAC_BLOCKING) ||\r
- (time_out == MSS_MAC_NONBLOCKING) ||\r
- ((time_out >= 1) && (time_out <= 0x01000000UL)) );\r
-\r
+ \r
MAC_dismiss_bad_frames();\r
\r
- /* wait for a packet */\r
- if( time_out != MSS_MAC_BLOCKING ) {\r
- if( time_out == MSS_MAC_NONBLOCKING ) {\r
- MAC_set_time_out( 0u );\r
- } else {\r
- MAC_set_time_out( time_out );\r
- }\r
- }\r
-\r
- while( ((g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 &\r
- RDES0_OWN) != 0u) && (exit == 0) )\r
- {\r
- if( time_out != MSS_MAC_BLOCKING )\r
- {\r
- if( MAC_get_time_out() == 0u ) {\r
- exit = 1;\r
- }\r
- }\r
- }\r
-\r
- if(exit == 0)\r
+ if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u )\r
{\r
frame_length = ( (\r
g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 >>\r
/* strip crc */\r
frame_length -= 4u;\r
\r
- if( frame_length > pacLen ) {\r
+ if( frame_length > macBUFFER_SIZE ) {\r
return MAC_NOT_ENOUGH_SPACE;\r
}\r
\r
- *pacData = ( unsigned char * ) g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1;\r
+ /* uip_buf is about to point to the buffer that contains the received\r
+ data, mark the buffer that uip_buf is currently pointing to as free\r
+ again. */\r
+ MAC_release_buffer( uip_buf );\r
+ uip_buf = ( unsigned char * ) g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1;\r
+ \r
+ /* The buffer the Rx descriptor was pointing to is now in use by the\r
+ uIP stack - allocate a new buffer to the Rx descriptor. */\r
+ g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].buffer_1 = ( unsigned long ) MAC_obtain_buffer();\r
\r
MSS_MAC_prepare_rx_descriptor();\r
- \r
}\r
return ((int32_t)frame_length);\r
}\r
MAC_memset( s->mac_address, (uint8_t)c, 6u );\r
MAC_memset( s->mac_filter_data, (uint8_t)c, 90u );\r
s->phy_address = (uint8_t)c;\r
- for(count = 0; count<RX_RING_SIZE ;count++)\r
- {\r
- MAC_memset(s->rx_buffers[count], (uint8_t)c, (MSS_RX_BUFF_SIZE + 4u) );\r
- }\r
+// for(count = 0; count<RX_RING_SIZE ;count++)\r
+// {\r
+// MAC_memset(s->rx_buffers[count], (uint8_t)c, (MSS_RX_BUFF_SIZE + 4u) );\r
+// }\r
s->rx_desc_index =c;\r
for(count = 0; count<RX_RING_SIZE ;count++)\r
{\r
s->statistics.tx_no_carrier = c;\r
s->statistics.tx_underflow_error = c;\r
s->time_out_value = c;\r
- for(count = 0; count < TX_RING_SIZE ;count++)\r
- {\r
- MAC_memset( s->tx_buffers[count], (uint8_t)c, MSS_TX_BUFF_SIZE );\r
- }\r
+// for(count = 0; count < TX_RING_SIZE ;count++)\r
+// {\r
+// MAC_memset( s->tx_buffers[count], (uint8_t)c, MSS_TX_BUFF_SIZE );\r
+// }\r
s->tx_desc_index = c;\r
for(count = 0; count < TX_RING_SIZE ;count++)\r
{\r
}\r
}\r
\r
+void MSS_MAC_TxBufferCompleted( void )\r
+{\r
+unsigned char *pxTransmittedBuffer;\r
+\r
+ /* Was it the second transmission that has completed? */\r
+ if( ( g_mss_mac.tx_descriptors[ 1 ].descriptor_0 & TDES0_OWN ) == 0UL )\r
+ {\r
+ pxTransmittedBuffer = ( unsigned char * ) g_mss_mac.tx_descriptors[ 1 ].buffer_1;\r
+\r
+ /* The buffer has been transmitted and is no longer in use. */\r
+ MAC_release_buffer( pxTransmittedBuffer );\r
+ }\r
+}\r
+\r
+static unsigned char *MAC_obtain_buffer( void )\r
+{\r
+long lIndex;\r
+unsigned char *pcReturn = NULL;\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
+ {\r
+ if( ucMACBufferFree[ lIndex ] == pdTRUE )\r
+ {\r
+ pcReturn = &( ucMACBuffers[ lIndex ][ 0 ] );\r
+ break;\r
+ }\r
+ }\r
+ \r
+ configASSERT( pcReturn );\r
+ return pcReturn;\r
+}\r
+\r
+void MAC_release_buffer( unsigned char *pucBufferToRelease )\r
+{\r
+long lIndex;\r
+\r
+ /* uip_buf is going to point to a different buffer - first ensure the buffer\r
+ it is currently pointing to is marked as being free again. */\r
+ for( lIndex = 0; lIndex < macNUM_BUFFERS; lIndex++ )\r
+ {\r
+ if( pucBufferToRelease == &( ucMACBuffers[ lIndex ][ 0 ] ) )\r
+ {\r
+ /* This is the buffer in use, mark it as being free. */\r
+ ucMACBufferFree[ lIndex ] = pdTRUE;\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+\r
+\r
#ifdef __cplusplus\r
}\r
#endif\r
\r
\r
/***************************************************************************//**\r
- * Sends a packet to the Ethernet Controller.\r
- * This function writes pacLen bytes of the packet contained in pacData into the\r
- * transmit FIFO of the controller and then activates the transmitter for this\r
- * packet. If space is available in FIFO, the function will return once lBufLen\r
- * bytes of the packet have been placed into the FIFO and the transmitter has been\r
- * started. The function will not wait for the transmission to complete. If space\r
- * is not available in FIFO, the function will keep trying till time_out expires,\r
- * if MSS_MAC_BLOCKING value is given as time_out, function will wait for the\r
- * transmission to complete.\r
- *\r
- * @param pacData the pointer to the packet data to be transmitted.\r
- * @param pacLen number of bytes in the packet to be transmitted.\r
- * @param time_out Time out value for transmision.\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
- * on buffer full case.\r
- * Otherwise value must be greater than 0 and smaller than \r
- * 0x01000000.\r
- * @return Returns 0 if time out occurs otherwise returns size \r
- * of the packet.\r
- * @see MAC_rx_packet()\r
+ Sends a packet from the uIP stack to the Ethernet Controller.\r
+ The MSS_MAC_tx_packet() function is used to send a packet to the MSS Ethernet\r
+ MAC. This function writes uip_len bytes of the packet contained in uip_buf into\r
+ the transmit FIFO and then activates the transmitter for this packet. If space\r
+ is available in the FIFO, the function will return once pac_len bytes of the\r
+ packet have been placed into the FIFO and the transmitter has been started.\r
+ This function will not wait for the transmission to complete.\r
+\r
+ @return\r
+ The function returns zero if a timeout occurs otherwise it returns size of the packet.\r
+\r
+ @see MAC_rx_packet()\r
*/\r
+\r
int32_t\r
MSS_MAC_tx_packet\r
(\r
- const uint8_t *pacData,\r
- uint16_t pacLen,\r
- uint32_t time_out\r
+ unsigned short usLength\r
);\r
\r
-\r
/***************************************************************************//**\r
* Returns available packet's size.\r
*\r
);\r
\r
/***************************************************************************//**\r
- * Receives a packet from the Ethernet Controller.\r
+ * Receives a packet from the Ethernet Controller into the uIP stack.\r
* This function reads a packet from the receive FIFO of the controller and\r
- * places it into pacData. If time_out parameter is zero the function will return \r
- * immediately (after the copy operation if data is available. Otherwise the function\r
- * 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 pacData The pointer to the buffer where received packet data will\r
- * be copied. Memory for the buffer should be allocated prior \r
- * to calling this function.\r
- * @param pacLen Size of the buffer, which the received data will be copied in,\r
- * given in number of bytes.\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
- * if there is no packet waiting.\r
- * Otherwise value must be greater than 0 and smaller than \r
- * 0x01000000.\r
- * @return Size of packet if packet fits in pacData.\r
+ * places it into uip_buf.\r
+\r
+ * @return Size of packet if packet fits in uip_buf.\r
* 0 if there is no received packet.\r
* @see MAC_rx_pckt_size()\r
* @see MAC_tx_packet()\r
int32_t\r
MSS_MAC_rx_packet\r
(\r
- uint8_t **pacData,\r
- uint16_t pacLen,\r
- uint32_t time_out\r
+ void\r
);\r
\r
\r
mss_mac_statistics_id_t stat_id\r
);\r
\r
+/*\r
+ * Ensure uip_buf is pointing to a valid and free buffer before any transmissions\r
+ * initiated by the uIP stack occur.
+ */\r
+unsigned char *MSS_MAC_GetTxDescriptor( void );\r
+\r
+/*\r
+ * A buffer is no longer required by the application. Hand it back to the\r
+ * control of the MAC hardware.
+ */\r
+void MSS_MAC_ReleaseBuffer( unsigned char *pucBuffer );\r
+\r
+/*\r
+ * The double Tx has completed. Hand back the Tx buffer to the control of\r
+ * the MAC hardware.
+ */\r
+void MSS_MAC_TxBufferCompleted( void );\r
#ifdef __cplusplus\r
}\r
#endif\r
\r
/* The buffer used by the uIP stack to both receive and send. This points to\r
one of the Ethernet buffers when its actually in use. */\r
-unsigned char *uip_buf = NULL;\r
+extern unsigned char *uip_buf;\r
\r
static const unsigned char ucMACAddress[] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 };\r
\r
\r
void vEMACWrite( void );\r
\r
-unsigned long ulEMACRead( void );\r
long lEMACWaitForLink( void );\r
\r
/*\r
\r
void vuIP_Task( void *pvParameters )\r
{\r
-portBASE_TYPE i, xDoneSomething;\r
+portBASE_TYPE i;\r
unsigned long ulNewEvent;\r
\r
( void ) pvParameters;\r
\r
for( ;; )\r
{\r
- xDoneSomething = pdFALSE;\r
- \r
- /* Is there received data ready to be processed? */\r
- uip_len = ( unsigned short ) ulEMACRead();\r
- \r
- if( ( uip_len > 0 ) && ( uip_buf != NULL ) )\r
+ if( ( ulUIP_Events & uipETHERNET_TX_EVENT ) != 0UL )\r
{\r
- /* Standard uIP loop taken from the uIP manual. */\r
- if( xHeader->type == htons( UIP_ETHTYPE_IP ) )\r
- {\r
- uip_arp_ipin();\r
- uip_input();\r
+ ulUIP_Events &= ~uipETHERNET_TX_EVENT;\r
+ MSS_MAC_TxBufferCompleted();\r
+ }\r
\r
- /* If the above function invocation resulted in data that\r
- should be sent out on the network, the global variable\r
- uip_len is set to a value > 0. */\r
- if( uip_len > 0 )\r
+ if( ( ulUIP_Events & uipETHERNET_RX_EVENT ) != 0UL )\r
+ {\r
+ ulUIP_Events &= ~uipETHERNET_RX_EVENT;\r
+\r
+ /* Is there received data ready to be processed? */\r
+ uip_len = MSS_MAC_rx_packet();\r
+\r
+ if( ( uip_len > 0 ) && ( uip_buf != NULL ) )\r
+ {\r
+ /* Standard uIP loop taken from the uIP manual. */\r
+ if( xHeader->type == htons( UIP_ETHTYPE_IP ) )\r
{\r
- uip_arp_out();\r
- vEMACWrite();\r
+ uip_arp_ipin();\r
+ uip_input();\r
+\r
+ /* If the above function invocation resulted in data that\r
+ should be sent out on the network, the global variable\r
+ uip_len is set to a value > 0. */\r
+ if( uip_len > 0 )\r
+ {\r
+ uip_arp_out();\r
+ vEMACWrite();\r
+ }\r
}\r
- \r
- xDoneSomething = pdTRUE;\r
- }\r
- else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) )\r
- {\r
- uip_arp_arpin();\r
-\r
- /* If the above function invocation resulted in data that\r
- should be sent out on the network, the global variable\r
- uip_len is set to a value > 0. */\r
- if( uip_len > 0 )\r
+ else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) )\r
{\r
- vEMACWrite();\r
+ uip_arp_arpin();\r
+\r
+ /* If the above function invocation resulted in data that\r
+ should be sent out on the network, the global variable\r
+ uip_len is set to a value > 0. */\r
+ if( uip_len > 0 )\r
+ {\r
+ vEMACWrite();\r
+ }\r
}\r
- \r
- xDoneSomething = pdTRUE;\r
}\r
}\r
\r
- if( ( ( ulUIP_Events & uipPERIODIC_TIMER_EVENT ) != 0UL ) && ( uip_buf != NULL ) )\r
+ if( ( ulUIP_Events & uipPERIODIC_TIMER_EVENT ) != 0UL )\r
{\r
ulUIP_Events &= ~uipPERIODIC_TIMER_EVENT;\r
\r
vEMACWrite();\r
}\r
}\r
+ }\r
\r
- /* Call the ARP timer function every 10 seconds. */\r
- if( ( ulUIP_Events & uipARP_TIMER_EVENT ) != 0 )\r
- {\r
- ulUIP_Events &= ~uipARP_TIMER_EVENT;\r
- uip_arp_timer();\r
- }\r
- \r
- xDoneSomething = pdTRUE;\r
+ /* Call the ARP timer function every 10 seconds. */\r
+ if( ( ulUIP_Events & uipARP_TIMER_EVENT ) != 0 )\r
+ {\r
+ ulUIP_Events &= ~uipARP_TIMER_EVENT;\r
+ uip_arp_timer();\r
}\r
- \r
- if( xDoneSomething == pdFALSE )\r
+\r
+ if( ulUIP_Events == pdFALSE )\r
{\r
xQueueReceive( xEMACEventQueue, &ulNewEvent, portMAX_DELAY );\r
ulUIP_Events |= ulNewEvent;\r
\r
if( ( ulISREvents & MSS_MAC_EVENT_PACKET_SEND ) != 0UL )\r
{\r
- /* Handle send event. */\r
- ulUIPEvents |= uipETHERNET_TX_EVENT;\r
+ ulUIP_Events |= uipETHERNET_TX_EVENT;\r
}\r
\r
if( ( ulISREvents & MSS_MAC_EVENT_PACKET_RECEIVED ) != 0UL )\r
{\r
/* Wake the uIP task as new data has arrived. */\r
ulUIPEvents |= uipETHERNET_RX_EVENT;\r
+ }\r
+\r
+ if( ulUIPEvents != 0UL )\r
+ {\r
xQueueSendFromISR( xEMACEventQueue, &ulUIPEvents, &lHigherPriorityTaskWoken );\r
}\r
\r
\r
static void prvInitEmac( void )\r
{\r
-unsigned long ulMACCfg;\r
const unsigned char ucPHYAddress = 1;\r
\r
MSS_MAC_init( ucPHYAddress );\r
\r
void vEMACWrite( void )\r
{\r
- MSS_MAC_tx_packet( uip_buf, uip_len, 0 );\r
-}\r
-/*-----------------------------------------------------------*/\r
+const long lMaxAttempts = 10;\r
+long lAttempt;\r
+const portTickType xShortDelay = ( 10 / portTICK_RATE_MS );\r
\r
-unsigned long ulEMACRead( void )\r
-{\r
- return MSS_MAC_rx_packet( &uip_buf, ( MSS_RX_BUFF_SIZE + 4 ), 0UL );\r
+ for( lAttempt = 0; lAttempt < lMaxAttempts; lAttempt++ )\r
+ {\r
+ if( MSS_MAC_tx_packet( uip_len ) != 0 )\r
+ {\r
+ break;\r
+ }\r
+ else\r
+ {\r
+ vTaskDelay( xShortDelay );\r
+ }\r
+ }\r
}\r
/*-----------------------------------------------------------*/\r
\r