diff --git a/source/portable/NetworkInterface/Zynq/x_emacpsif.h b/source/portable/NetworkInterface/Zynq/x_emacpsif.h index cd18fd997e..ba6836148b 100644 --- a/source/portable/NetworkInterface/Zynq/x_emacpsif.h +++ b/source/portable/NetworkInterface/Zynq/x_emacpsif.h @@ -60,7 +60,6 @@ extern XEmacPs_Config mac_configs[ XPAR_XEMACPS_NUM_INSTANCES ]; - void xemacpsif_setmac( uint32_t index, uint8_t * addr ); uint8_t * xemacpsif_getmac( uint32_t index ); @@ -115,7 +114,8 @@ volatile int rxHead, rxTail; volatile int txHead, txTail; - volatile int txBusy; + /* txMutex is replacing the earlier int variable 'txBusy'. */ + SemaphoreHandle_t txMutex; volatile uint32_t isr_events; diff --git a/source/portable/NetworkInterface/Zynq/x_emacpsif_dma.c b/source/portable/NetworkInterface/Zynq/x_emacpsif_dma.c index a9b9e2b03d..66e7d702a6 100644 --- a/source/portable/NetworkInterface/Zynq/x_emacpsif_dma.c +++ b/source/portable/NetworkInterface/Zynq/x_emacpsif_dma.c @@ -221,7 +221,9 @@ void emacps_send_handler( void * arg ) * "isr_events". The task in NetworkInterface will wake-up and do the necessary work. */ xemacpsif->isr_events |= EMAC_IF_TX_EVENT; - xemacpsif->txBusy = pdFALSE; + + /* Give to the mutex so that a new packet can be sent from emacps_send_message(). */ + xSemaphoreGiveFromISR( xemacpsif->txMutex, &xHigherPriorityTaskWoken ); if( xEMACTaskHandles[ xEMACIndex ] != NULL ) { @@ -252,7 +254,6 @@ XStatus emacps_send_message( xemacpsif_s * xemacpsif, int iReleaseAfterSend ) { int txHead = xemacpsif->txHead; - int iHasSent = 0; uint32_t ulBaseAddress = xemacpsif->emacps.Config.BaseAddress; BaseType_t xEMACIndex = get_xEMACIndex( &xemacpsif->emacps ); TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 5000U ); @@ -315,8 +316,6 @@ XStatus emacps_send_message( xemacpsif_s * xemacpsif, { } - iHasSent = pdTRUE; - txHead++; if( txHead == ipconfigNIC_N_TX_DESC ) @@ -328,18 +327,24 @@ XStatus emacps_send_message( xemacpsif_s * xemacpsif, * accessed as little as possible. */ xemacpsif->txHead = txHead; + if( xSemaphoreTake( xemacpsif->txMutex, 200U ) == pdFALSE ) + { + FreeRTOS_printf( ( "emacps_send_message: mutex can not be taken, something is really wrong.\n" ) ); + /* There is no risk in continuing here. */ + } + /* Data Synchronization Barrier */ dsb(); - if( iHasSent == pdTRUE ) { /* Make STARTTX high */ uint32_t ulValue = XEmacPs_ReadReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET ); - /* Start transmit */ - xemacpsif->txBusy = pdTRUE; - XEmacPs_WriteReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET, ( ulValue | XEMACPS_NWCTRL_STARTTX_MASK ) ); + /* Set the Start transmit bit. */ + ulValue |= XEMACPS_NWCTRL_STARTTX_MASK; + XEmacPs_WriteReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET, ulValue ); /* Read back the register to make sure the data is flushed. */ ( void ) XEmacPs_ReadReg( ulBaseAddress, XEMACPS_NWCTRL_OFFSET ); + /* The mutex will be given later on in emacps_send_handler(). */ } dsb(); @@ -685,6 +690,15 @@ XStatus init_dma( xemacpsif_s * xemacpsif ) configASSERT( xTXDescriptorSemaphores[ xEMACIndex ] ); } + if( xemacpsif->txMutex == NULL ) + { + /* txMutex can always be taken, except between sending a packet + * and receiving the TX RX interrupt. */ + xemacpsif->txMutex = xSemaphoreCreateBinary(); + configASSERT( xemacpsif->txMutex != NULL ); + xSemaphoreGive( xemacpsif->txMutex ); + } + /* * Allocate RX descriptors, 1 RxBD at a time. */