Skip to content

Commit

Permalink
Circumvent Qemu MPS2 networking bug (#142)
Browse files Browse the repository at this point in the history
* Add support for MPS2 networking with lan9118/lan9220

* Fix uncrustify errors

* Enable network interrupt handling

* Add network interrupt support to Qemu MPS2 AN385

* Fix function comment

* Fix Uncrustify errors

* Fix Uncrustify errors

* Fix Uncrustify Errors

* Fix typo

* Cirumvent Qemu MPS2 network bug

* Remove commented code, add doxygen comment
  • Loading branch information
alfred2g committed Feb 16, 2021
1 parent 47dd7f9 commit 69b69d3
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 27 deletions.
66 changes: 40 additions & 26 deletions portable/NetworkInterface/MPS2_AN385/NetworkInterface.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@

#define niMAX_TX_ATTEMPTS ( 5 )


/* ============================= Static Prototypes ========================= */
static void rx_task( void * pvParameters );

Expand All @@ -96,15 +95,13 @@ static struct smsc9220_eth_dev_t SMSC9220_ETH_DEV =
static void print_hex( unsigned const char * const bin_data,
size_t len );


/* ============================= Extern Variables ========================== */
/* defined in main_networking.c */
extern uint8_t ucMACAddress[ SMSC9220_HWADDR_SIZE ]; /* 6 bytes */


/* ============================= Static Variables ========================== */
static TaskHandle_t xRxHanderTask = NULL;

static SemaphoreHandle_t xSemaphore = NULL;

/* ============================= Static Functions ========================== */

Expand Down Expand Up @@ -168,10 +165,31 @@ static void set_mac( const uint8_t * addr )
}
}

void EthernetISR( void )
{
const struct smsc9220_eth_dev_t * dev = &SMSC9220_ETH_DEV;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;

configASSERT( xRxHanderTask );

if( smsc9220_get_interrupt( dev,
SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ) )
{
configASSERT( xSemaphore );
xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );

smsc9220_disable_interrupt( dev,
SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL );
smsc9220_clear_interrupt( dev,
SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL );
}

portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

/**
* @brief function to poll the netwrok card(qemu emulation) as we faced some
* problems with the network interrupt being fired for no reason at
* a very high rate which made the program not progress
* @brief function to wait on a semaphore from the interrupt handler of the
* network card when data is available
*/
static void rx_task( void * pvParameters )
{
Expand All @@ -184,20 +202,13 @@ static void rx_task( void * pvParameters )

for( ; ; )
{
if( ( smsc9220_get_interrupt( dev,
SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL ) ) )
{ /* data received */
smsc9220_clear_interrupt( dev,
SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL );
xResult = pdPASS;
}
else
{
vTaskDelay( xBlockTime );
continue;
}
configASSERT( xSemaphore );
xSemaphoreTake( xSemaphore,
portMAX_DELAY );

packet_rx();
smsc9220_clear_interrupt( dev,
SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL );
smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL );
}
}
Expand All @@ -210,9 +221,8 @@ static void packet_rx()
uint32_t data_read;

FreeRTOS_debug_printf( ( "Enter\n" ) );
data_read = low_level_input( &pxNetworkBuffer );

if( data_read > 0 )
while( ( data_read = low_level_input( &pxNetworkBuffer ) ) )
{
xRxEvent.pvData = ( void * ) pxNetworkBuffer;

Expand All @@ -234,7 +244,7 @@ static uint32_t low_level_input( NetworkBufferDescriptor_t ** pxNetworkBuffer )

FreeRTOS_debug_printf( ( "Enter\n" ) );

message_length = smsc9220_peek_next_packet_size( dev );
message_length = smsc9220_peek_next_packet_size2( dev );

if( message_length != 0 )
{
Expand All @@ -245,11 +255,11 @@ static uint32_t low_level_input( NetworkBufferDescriptor_t ** pxNetworkBuffer )
{
( *pxNetworkBuffer )->xDataLength = message_length;

received_bytes = smsc9220_receive_by_chunks( dev,
( *pxNetworkBuffer )->pucEthernetBuffer,
message_length ); /* not used */
received_bytes = smsc9220_receive_by_chunks2( dev,
( *pxNetworkBuffer )->pucEthernetBuffer,
message_length ); /* not used */
( *pxNetworkBuffer )->xDataLength = received_bytes;
FreeRTOS_debug_printf( ( "incoming data < < < < < < < < < < read: %d length: %d\n",
FreeRTOS_debug_printf( ( "Incoming data < < < < < < < < < < read: %d length: %d\n",
received_bytes,
message_length ) );
print_hex( ( *pxNetworkBuffer )->pucEthernetBuffer,
Expand All @@ -273,6 +283,8 @@ BaseType_t xNetworkInterfaceInitialise( void )
enum smsc9220_error_t err;

FreeRTOS_debug_printf( ( "Enter\n" ) );
xSemaphore = xSemaphoreCreateBinary();
configASSERT( xSemaphore );

if( xRxHanderTask == NULL )
{
Expand All @@ -283,6 +295,7 @@ BaseType_t xNetworkInterfaceInitialise( void )
configMAX_PRIORITIES - 4,
&xRxHanderTask );
configASSERT( xReturn != 0 );
configASSERT( xRxHanderTask );
}

err = smsc9220_init( dev, wait_ms_function );
Expand All @@ -307,6 +320,7 @@ BaseType_t xNetworkInterfaceInitialise( void )
set_mac( ucMACAddress );
NVIC_SetPriority( ETHERNET_IRQn, configMAC_INTERRUPT_PRIORITY );
smsc9220_enable_interrupt( dev, SMSC9220_INTERRUPT_RX_STATUS_FIFO_LEVEL );
NVIC_EnableIRQ( ETHERNET_IRQn );
}

FreeRTOS_debug_printf( ( "Exit\n" ) );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,9 @@ enum rx_fifo_status_bits_t
*/
enum irq_cfg_bits_t
{
IRQ_CFG_IRQ_EN_INDEX = 8U
IRQ_CFG_IRQ_TYPE = 0U,
IRQ_CFG_IRQ_POL = 4U,
IRQ_CFG_IRQ_EN_INDEX = 8U,
};

#define IRQ_CFG_INT_DEAS_MASK 0xFFU
Expand Down Expand Up @@ -718,6 +720,8 @@ void smsc9220_init_irqs( const struct smsc9220_eth_dev_t * dev )
IRQ_CFG_INT_DEAS_POS, IRQ_CFG_INT_DEAS_10US );

/* enable interrupts */
SET_BIT( register_map->irq_cfg, IRQ_CFG_IRQ_TYPE );
SET_BIT( register_map->irq_cfg, IRQ_CFG_IRQ_POL );
SET_BIT( register_map->irq_cfg, IRQ_CFG_IRQ_EN_INDEX );
}

Expand Down Expand Up @@ -1198,6 +1202,55 @@ uint32_t smsc9220_receive_by_chunks( const struct smsc9220_eth_dev_t * dev,
return packet_length_byte;
}

/*!
* @brief second version to circumvent a <a href="https://bugs.launchpad.net/qemu/+bug/1904954">bug</a>
* in quemu where the peeked message
* size is different than the actual message size
*/
uint32_t smsc9220_receive_by_chunks2( const struct smsc9220_eth_dev_t * dev,
char * data,
uint32_t dlen )
{
uint32_t rxfifo_inf = 0;
uint32_t rxfifo_stat = 0;
/*uint32_t packet_length_byte = 0; */
struct smsc9220_eth_reg_map_t * register_map =
( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;

if( !data )
{
return 0; /* Invalid input parameter, cannot read */
}

dev->data->current_rx_size_words = dlen;

empty_rx_fifo( dev, ( uint8_t * ) data, dlen );
dev->data->current_rx_size_words = 0;
return dlen;
}

/*!
* @brief second version to circumvent a <a href="https://bugs.launchpad.net/qemu/+bug/1904954">bug</a>
* in quemu where the peeked message
* size is different than the actual message size
*/
uint32_t smsc9220_peek_next_packet_size2( const struct
smsc9220_eth_dev_t * dev )
{
uint32_t packet_size = 0;
struct smsc9220_eth_reg_map_t * register_map =
( struct smsc9220_eth_reg_map_t * ) dev->cfg->base;

if( smsc9220_get_rxfifo_data_used_space( dev ) )
{
packet_size = GET_BIT_FIELD( register_map->rx_status_port,
RX_FIFO_STATUS_PKT_LENGTH_MASK,
RX_FIFO_STATUS_PKT_LENGTH_POS );
}

return packet_size;
}

uint32_t smsc9220_peek_next_packet_size( const struct
smsc9220_eth_dev_t * dev )
{
Expand Down

0 comments on commit 69b69d3

Please sign in to comment.