From 69b69d38f4763b8266a53d7ee1f71d960bf83eb0 Mon Sep 17 00:00:00 2001
From: alfred gedeon <28123637+alfred2g@users.noreply.github.com>
Date: Mon, 15 Feb 2021 17:51:51 -0800
Subject: [PATCH] Circumvent Qemu MPS2 networking bug (#142)
* 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
---
.../MPS2_AN385/NetworkInterface.c | 66 +++++++++++--------
.../ether_lan9118/smsc9220_eth_drv.c | 55 +++++++++++++++-
2 files changed, 94 insertions(+), 27 deletions(-)
diff --git a/portable/NetworkInterface/MPS2_AN385/NetworkInterface.c b/portable/NetworkInterface/MPS2_AN385/NetworkInterface.c
index c3169fc20..1cfa0ef74 100644
--- a/portable/NetworkInterface/MPS2_AN385/NetworkInterface.c
+++ b/portable/NetworkInterface/MPS2_AN385/NetworkInterface.c
@@ -72,7 +72,6 @@
#define niMAX_TX_ATTEMPTS ( 5 )
-
/* ============================= Static Prototypes ========================= */
static void rx_task( void * pvParameters );
@@ -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 ========================== */
@@ -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 )
{
@@ -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 );
}
}
@@ -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;
@@ -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 )
{
@@ -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,
@@ -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 )
{
@@ -283,6 +295,7 @@ BaseType_t xNetworkInterfaceInitialise( void )
configMAX_PRIORITIES - 4,
&xRxHanderTask );
configASSERT( xReturn != 0 );
+ configASSERT( xRxHanderTask );
}
err = smsc9220_init( dev, wait_ms_function );
@@ -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" ) );
diff --git a/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c b/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c
index 8a8305b1a..5980d791e 100644
--- a/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c
+++ b/portable/NetworkInterface/MPS2_AN385/ether_lan9118/smsc9220_eth_drv.c
@@ -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
@@ -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 );
}
@@ -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 bug
+ * 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 bug
+ * 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 )
{