Continue work on the SmartFusion web server demo.

pull/4/head
Richard Barry 14 years ago
parent 9ebdc099d1
commit fd20ed4d17

@ -51,6 +51,12 @@ extern "C" {
#define MAC_TIME_OUT (-6) #define MAC_TIME_OUT (-6)
#define MAC_TOO_SMALL_PACKET (-7) #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; 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 MAC_instance_t* NULL_instance;
static uint8_t* NULL_buffer; static uint8_t* NULL_buffer;
static MSS_MAC_callback_t NULL_callback; static MSS_MAC_callback_t NULL_callback;
unsigned char *uip_buf = NULL;
/**************************** INTERNAL FUNCTIONS ******************************/ /**************************** 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_memcpy(uint8_t *dest, const uint8_t *src, uint32_t n);
static void MAC_memset_All(MAC_instance_t *s, uint32_t c); 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. * Initializes the Ethernet Controller.
* This function will prepare the Ethernet Controller for first time use in a * 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 }; const uint8_t mac_address[6] = { DEFAULT_MAC_ADDRESS };
int32_t a; int32_t a;
/* To start with all buffers are free. */
for( a = 0; a < macNUM_BUFFERS; a++ )
{
ucMACBufferFree[ a ] = pdTRUE;
}
/* Try to reset chip */ /* Try to reset chip */
MAC_BITBAND->CSR0_SWR = 1u; MAC_BITBAND->CSR0_SWR = 1u;
@ -139,13 +166,19 @@ MSS_MAC_init
/* Give the ownership to the MAC */ /* Give the ownership to the MAC */
g_mss_mac.rx_descriptors[a].descriptor_0 = RDES0_OWN; 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].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; g_mss_mac.rx_descriptors[RX_RING_SIZE-1].descriptor_1 |= RDES1_RER;
for( a = 0; a < TX_RING_SIZE; a++ ) 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; 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 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 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. 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 This function will not wait for the transmission to complete.
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.
@return @return
The function returns zero if a timeout occurs otherwise it returns size of the packet. 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 int32_t
MSS_MAC_tx_packet MSS_MAC_tx_packet
( (
const uint8_t *pacData, unsigned short usLength
uint16_t pacLen,
uint32_t time_out
) )
{ {
uint32_t desc; uint32_t desc;
unsigned long ulDescriptor;
int32_t error = MAC_OK; int32_t error = MAC_OK;
extern unsigned char *uip_buf;
ASSERT( MAC_test_instance() == MAC_OK ); 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 ) 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) || /* Check if second descriptor is free, if it is then the first must
(time_out == MSS_MAC_NONBLOCKING) || also be free. */
((time_out >= 1) && (time_out <= 0x01000000uL)) ); if(((g_mss_mac.tx_descriptors[ 1 ].descriptor_0) & TDES0_OWN) == TDES0_OWN )
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
{ {
/* Wait until descriptor is free */ error = MAC_BUFFER_IS_FULL;
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;
}
}
}
} }
if( error == MAC_OK ) { 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 ) { /* Every buffer can hold a full frame so they are always first and last
g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_AC; 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 /* set data size */
descriptor */ g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_1 |= usLength;
g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= TDES1_LS | TDES1_FS;
/* set data size */ /* reset end of ring */
g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_1 |= pacLen; g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER;
/* reset end of ring */ if( usLength > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */
g_mss_mac.tx_descriptors[TX_RING_SIZE-1].descriptor_1 |= TDES1_TER; {
usLength = (uint16_t)MSS_TX_BUFF_SIZE;
}
/* copy data into buffer */ /* The data buffer is assigned to the Tx descriptor. */
if( pacLen > MSS_TX_BUFF_SIZE ) /* FLAG_EXCEED_LIMIT */ g_mss_mac.tx_descriptors[ ulDescriptor ].buffer_1 = ( unsigned long ) uip_buf;
{
pacLen = (uint16_t)MSS_TX_BUFF_SIZE;
}
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 */ /* Give ownership of descriptor to the MAC */
desc = g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0; g_mss_mac.tx_descriptors[ ulDescriptor ].descriptor_0 = TDES0_OWN;
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_desc_index = 0;
g_mss_mac.tx_descriptors[ g_mss_mac.tx_desc_index ].descriptor_0 = RDES0_OWN; }
}
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 */ /* transmit poll demand */
MAC_start_transmission(); MAC->CSR1 = 1u;
/* transmit poll demand */
MAC->CSR1 = 1u;
}
if (error == MAC_OK) 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 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 * 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 * places it into uip_buf.
* 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 * @return Size of packet if packet fits in uip_buf.
* 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.
* 0 if there is no received packet. * 0 if there is no received packet.
* @see MAC_rx_pckt_size() * @see MAC_rx_pckt_size()
* @see MAC_tx_packet() * @see MAC_tx_packet()
@ -560,42 +544,16 @@ MSS_MAC_rx_pckt_size
int32_t int32_t
MSS_MAC_rx_packet MSS_MAC_rx_packet
( (
unsigned char **pacData, void
uint16_t pacLen,
uint32_t time_out
) )
{ {
uint16_t frame_length=0u; uint16_t frame_length=0u;
int8_t exit=0;
ASSERT( MAC_test_instance() == MAC_OK ); 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(); MAC_dismiss_bad_frames();
/* wait for a packet */ if( (g_mss_mac.rx_descriptors[ g_mss_mac.rx_desc_index ].descriptor_0 & RDES0_OWN) == 0u )
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)
{ {
frame_length = ( ( frame_length = ( (
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 >>
@ -604,14 +562,21 @@ MSS_MAC_rx_packet
/* strip crc */ /* strip crc */
frame_length -= 4u; frame_length -= 4u;
if( frame_length > pacLen ) { if( frame_length > macBUFFER_SIZE ) {
return MAC_NOT_ENOUGH_SPACE; 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(); MSS_MAC_prepare_rx_descriptor();
} }
return ((int32_t)frame_length); 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_address, (uint8_t)c, 6u );
MAC_memset( s->mac_filter_data, (uint8_t)c, 90u ); MAC_memset( s->mac_filter_data, (uint8_t)c, 90u );
s->phy_address = (uint8_t)c; s->phy_address = (uint8_t)c;
for(count = 0; count<RX_RING_SIZE ;count++) // for(count = 0; count<RX_RING_SIZE ;count++)
{ // {
MAC_memset(s->rx_buffers[count], (uint8_t)c, (MSS_RX_BUFF_SIZE + 4u) ); // MAC_memset(s->rx_buffers[count], (uint8_t)c, (MSS_RX_BUFF_SIZE + 4u) );
} // }
s->rx_desc_index =c; s->rx_desc_index =c;
for(count = 0; count<RX_RING_SIZE ;count++) for(count = 0; count<RX_RING_SIZE ;count++)
{ {
@ -1475,10 +1440,10 @@ static void MAC_memset_All(MAC_instance_t *s, uint32_t c)
s->statistics.tx_no_carrier = c; s->statistics.tx_no_carrier = c;
s->statistics.tx_underflow_error = c; s->statistics.tx_underflow_error = c;
s->time_out_value = c; s->time_out_value = c;
for(count = 0; count < TX_RING_SIZE ;count++) // for(count = 0; count < TX_RING_SIZE ;count++)
{ // {
MAC_memset( s->tx_buffers[count], (uint8_t)c, MSS_TX_BUFF_SIZE ); // MAC_memset( s->tx_buffers[count], (uint8_t)c, MSS_TX_BUFF_SIZE );
} // }
s->tx_desc_index = c; s->tx_desc_index = c;
for(count = 0; count < TX_RING_SIZE ;count++) 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 #ifdef __cplusplus
} }
#endif #endif

@ -342,37 +342,26 @@ MSS_MAC_get_configuration
/***************************************************************************//** /***************************************************************************//**
* Sends a packet to the Ethernet Controller. Sends a packet from the uIP stack to the Ethernet Controller.
* This function writes pacLen bytes of the packet contained in pacData into the The MSS_MAC_tx_packet() function is used to send a packet to the MSS Ethernet
* transmit FIFO of the controller and then activates the transmitter for this MAC. This function writes uip_len bytes of the packet contained in uip_buf into
* packet. If space is available in FIFO, the function will return once lBufLen the transmit FIFO and then activates the transmitter for this packet. If space
* bytes of the packet have been placed into the FIFO and the transmitter has been is available in the FIFO, the function will return once pac_len bytes of the
* started. The function will not wait for the transmission to complete. If space packet have been placed into the FIFO and the transmitter has been started.
* is not available in FIFO, the function will keep trying till time_out expires, This function will not wait for the transmission to complete.
* if MSS_MAC_BLOCKING value is given as time_out, function will wait for the
* transmission to complete. @return
* The function returns zero if a timeout occurs otherwise it returns size of the packet.
* @param pacData the pointer to the packet data to be transmitted.
* @param pacLen number of bytes in the packet to be transmitted. @see MAC_rx_packet()
* @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()
*/ */
int32_t int32_t
MSS_MAC_tx_packet MSS_MAC_tx_packet
( (
const uint8_t *pacData, unsigned short usLength
uint16_t pacLen,
uint32_t time_out
); );
/***************************************************************************//** /***************************************************************************//**
* Returns available packet's size. * 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 * 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 * places it into uip_buf.
* 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 * @return Size of packet if packet fits in uip_buf.
* 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.
* 0 if there is no received packet. * 0 if there is no received packet.
* @see MAC_rx_pckt_size() * @see MAC_rx_pckt_size()
* @see MAC_tx_packet() * @see MAC_tx_packet()
@ -427,9 +402,7 @@ MSS_MAC_prepare_rx_descriptor
int32_t int32_t
MSS_MAC_rx_packet MSS_MAC_rx_packet
( (
uint8_t **pacData, void
uint16_t pacLen,
uint32_t time_out
); );
@ -587,6 +560,23 @@ MSS_MAC_get_statistics
mss_mac_statistics_id_t stat_id 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 #ifdef __cplusplus
} }
#endif #endif

@ -65,12 +65,12 @@ typedef struct {
/* transmit related info: */ /* transmit related info: */
uint32_t tx_desc_index; /**< index of the transmit descriptor getting used*/ 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*/ MAC_descriptor_t tx_descriptors[TX_RING_SIZE];/**< array of transmit descriptors*/
/* receive related info: */ /* receive related info: */
uint32_t rx_desc_index; /**< index of the receive descriptor getting used*/ 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*/ MAC_descriptor_t rx_descriptors[RX_RING_SIZE];/**< array of receive descriptors*/
uint8_t phy_address; /**< MII address of the connected PHY*/ uint8_t phy_address; /**< MII address of the connected PHY*/

@ -76,7 +76,7 @@
/* The buffer used by the uIP stack to both receive and send. This points to /* 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. */ 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 }; 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 ); void vEMACWrite( void );
unsigned long ulEMACRead( void );
long lEMACWaitForLink( void ); long lEMACWaitForLink( void );
/* /*
@ -163,7 +162,7 @@ clock_time_t clock_time( void )
void vuIP_Task( void *pvParameters ) void vuIP_Task( void *pvParameters )
{ {
portBASE_TYPE i, xDoneSomething; portBASE_TYPE i;
unsigned long ulNewEvent; unsigned long ulNewEvent;
( void ) pvParameters; ( void ) pvParameters;
@ -176,47 +175,52 @@ unsigned long ulNewEvent;
for( ;; ) for( ;; )
{ {
xDoneSomething = pdFALSE; if( ( ulUIP_Events & uipETHERNET_TX_EVENT ) != 0UL )
/* Is there received data ready to be processed? */
uip_len = ( unsigned short ) ulEMACRead();
if( ( uip_len > 0 ) && ( uip_buf != NULL ) )
{ {
/* Standard uIP loop taken from the uIP manual. */ ulUIP_Events &= ~uipETHERNET_TX_EVENT;
if( xHeader->type == htons( UIP_ETHTYPE_IP ) ) MSS_MAC_TxBufferCompleted();
{ }
uip_arp_ipin();
uip_input();
/* If the above function invocation resulted in data that if( ( ulUIP_Events & uipETHERNET_RX_EVENT ) != 0UL )
should be sent out on the network, the global variable {
uip_len is set to a value > 0. */ ulUIP_Events &= ~uipETHERNET_RX_EVENT;
if( uip_len > 0 )
/* 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(); uip_arp_ipin();
vEMACWrite(); 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();
}
} }
else if( xHeader->type == htons( UIP_ETHTYPE_ARP ) )
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 )
{ {
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; ulUIP_Events &= ~uipPERIODIC_TIMER_EVENT;
@ -233,18 +237,16 @@ unsigned long ulNewEvent;
vEMACWrite(); vEMACWrite();
} }
} }
}
/* Call the ARP timer function every 10 seconds. */ /* Call the ARP timer function every 10 seconds. */
if( ( ulUIP_Events & uipARP_TIMER_EVENT ) != 0 ) if( ( ulUIP_Events & uipARP_TIMER_EVENT ) != 0 )
{ {
ulUIP_Events &= ~uipARP_TIMER_EVENT; ulUIP_Events &= ~uipARP_TIMER_EVENT;
uip_arp_timer(); uip_arp_timer();
}
xDoneSomething = pdTRUE;
} }
if( xDoneSomething == pdFALSE ) if( ulUIP_Events == pdFALSE )
{ {
xQueueReceive( xEMACEventQueue, &ulNewEvent, portMAX_DELAY ); xQueueReceive( xEMACEventQueue, &ulNewEvent, portMAX_DELAY );
ulUIP_Events |= ulNewEvent; ulUIP_Events |= ulNewEvent;
@ -359,14 +361,17 @@ unsigned long ulUIPEvents = 0UL;
if( ( ulISREvents & MSS_MAC_EVENT_PACKET_SEND ) != 0UL ) if( ( ulISREvents & MSS_MAC_EVENT_PACKET_SEND ) != 0UL )
{ {
/* Handle send event. */ ulUIP_Events |= uipETHERNET_TX_EVENT;
ulUIPEvents |= uipETHERNET_TX_EVENT;
} }
if( ( ulISREvents & MSS_MAC_EVENT_PACKET_RECEIVED ) != 0UL ) if( ( ulISREvents & MSS_MAC_EVENT_PACKET_RECEIVED ) != 0UL )
{ {
/* Wake the uIP task as new data has arrived. */ /* Wake the uIP task as new data has arrived. */
ulUIPEvents |= uipETHERNET_RX_EVENT; ulUIPEvents |= uipETHERNET_RX_EVENT;
}
if( ulUIPEvents != 0UL )
{
xQueueSendFromISR( xEMACEventQueue, &ulUIPEvents, &lHigherPriorityTaskWoken ); xQueueSendFromISR( xEMACEventQueue, &ulUIPEvents, &lHigherPriorityTaskWoken );
} }
@ -376,7 +381,6 @@ unsigned long ulUIPEvents = 0UL;
static void prvInitEmac( void ) static void prvInitEmac( void )
{ {
unsigned long ulMACCfg;
const unsigned char ucPHYAddress = 1; const unsigned char ucPHYAddress = 1;
MSS_MAC_init( ucPHYAddress ); MSS_MAC_init( ucPHYAddress );
@ -391,13 +395,21 @@ const unsigned char ucPHYAddress = 1;
void vEMACWrite( void ) 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 ) for( lAttempt = 0; lAttempt < lMaxAttempts; lAttempt++ )
{ {
return MSS_MAC_rx_packet( &uip_buf, ( MSS_RX_BUFF_SIZE + 4 ), 0UL ); if( MSS_MAC_tx_packet( uip_len ) != 0 )
{
break;
}
else
{
vTaskDelay( xShortDelay );
}
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

Loading…
Cancel
Save