void vReleaseNetworkBufferAndDescriptor( xNetworkBufferDescriptor_t * const pxNetworkBuffer ) { BaseType_t xListItemAlreadyInFreeList; #if( ipconfigIP_TASK_KEEPS_MESSAGE_BUFFER != 0 ) if( pxNetworkBuffer == pxIpTaskMessageBuffer ) return; #endif if( !bIsValidNetworkDescriptor ( pxNetworkBuffer ) ) { FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: Invalid buffer %p\n", pxNetworkBuffer ) ); return ; } /* Ensure the buffer is returned to the list of free buffers before the counting semaphore is 'given' to say a buffer is available. */ /* taskENTER_CRITICAL(); */ ipconfigBUFFER_ALLOC_LOCK(); { { xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); if( xListItemAlreadyInFreeList == pdFALSE ) { vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); } } /* configASSERT( xListItemAlreadyInFreeList == pdFALSE ); */ } ipconfigBUFFER_ALLOC_UNLOCK(); /* taskEXIT_CRITICAL(); */ if( xListItemAlreadyInFreeList ) { FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: %p ALREADY RELEASED (now %lu)\n", pxNetworkBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) ); } if( !xListItemAlreadyInFreeList ) { xSemaphoreGive( xNetworkBufferSemaphore ); showWarnings(); if( xTCPWindowLoggingLevel > 3 ) FreeRTOS_debug_printf( ( "BUF_PUT[%ld]: %p (%p) (now %lu)\n", bIsValidNetworkDescriptor( pxNetworkBuffer ), pxNetworkBuffer, pxNetworkBuffer->pucEthernetBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) ); } iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); }
void vCheckBuffersAndQueue( void ) { static UBaseType_t uxLastMinBufferCount = 0; #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 ) static UBaseType_t uxLastMinQueueSpace; #endif static UBaseType_t uxCurrentCount; #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 ) { uxCurrentCount = uxGetMinimumIPQueueSpace(); if( uxLastMinQueueSpace != uxCurrentCount ) { /* The logging produced below may be helpful while tuning +TCP: see how many buffers are in use. */ uxLastMinQueueSpace = uxCurrentCount; FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) ); } } #endif /* ipconfigCHECK_IP_QUEUE_SPACE */ uxCurrentCount = uxGetMinimumFreeNetworkBuffers(); if( uxLastMinBufferCount != uxCurrentCount ) { /* The logging produced below may be helpful while tuning +TCP: see how many buffers are in use. */ uxLastMinBufferCount = uxCurrentCount; FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n", uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) ); } }
static void prvShowWarnings( void ) { UBaseType_t uxCount = uxGetNumberOfFreeNetworkBuffers( ); if( ( ( cIsLow == 0 ) && ( uxCount <= WARN_LOW ) ) || ( ( cIsLow != 0 ) && ( uxCount >= WARN_HIGH ) ) ) { cIsLow = !cIsLow; FreeRTOS_debug_printf( ( "*** Warning *** %s %lu buffers left\n", cIsLow ? "only" : "now", uxCount ) ); } }
void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer ) { BaseType_t xListItemAlreadyInFreeList; if( bIsValidNetworkDescriptor( pxNetworkBuffer ) == pdFALSE_UNSIGNED ) { FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: Invalid buffer %p\n", pxNetworkBuffer ) ); return ; } /* Ensure the buffer is returned to the list of free buffers before the counting semaphore is 'given' to say a buffer is available. */ ipconfigBUFFER_ALLOC_LOCK(); { { xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); if( xListItemAlreadyInFreeList == pdFALSE ) { vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); } } } ipconfigBUFFER_ALLOC_UNLOCK(); if( xListItemAlreadyInFreeList ) { FreeRTOS_debug_printf( ( "vReleaseNetworkBufferAndDescriptor: %p ALREADY RELEASED (now %lu)\n", pxNetworkBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) ); } if( xListItemAlreadyInFreeList == pdFALSE ) { xSemaphoreGive( xNetworkBufferSemaphore ); prvShowWarnings(); if( xTCPWindowLoggingLevel > 3 ) FreeRTOS_debug_printf( ( "BUF_PUT[%ld]: %p (%p) (now %lu)\n", bIsValidNetworkDescriptor( pxNetworkBuffer ), pxNetworkBuffer, pxNetworkBuffer->pucEthernetBuffer, uxGetNumberOfFreeNetworkBuffers( ) ) ); } iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); }
static uint32_t prvEMACRxPoll( void ) { unsigned char *pucUseBuffer; uint32_t ulReceiveCount, ulResult, ulReturnValue = 0; static NetworkBufferDescriptor_t *pxNextNetworkBufferDescriptor = NULL; const UBaseType_t xMinDescriptorsToLeave = 2UL; const TickType_t xBlockTime = pdMS_TO_TICKS( 100UL ); static IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; for( ;; ) { /* If pxNextNetworkBufferDescriptor was not left pointing at a valid descriptor then allocate one now. */ if( ( pxNextNetworkBufferDescriptor == NULL ) && ( uxGetNumberOfFreeNetworkBuffers() > xMinDescriptorsToLeave ) ) { pxNextNetworkBufferDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xBlockTime ); } if( pxNextNetworkBufferDescriptor != NULL ) { /* Point pucUseBuffer to the buffer pointed to by the descriptor. */ pucUseBuffer = ( unsigned char* ) ( pxNextNetworkBufferDescriptor->pucEthernetBuffer - ipconfigPACKET_FILLER_SIZE ); } else { /* As long as pxNextNetworkBufferDescriptor is NULL, the incoming messages will be flushed and ignored. */ pucUseBuffer = NULL; } /* Read the next packet from the hardware into pucUseBuffer. */ ulResult = gmac_dev_read( &gs_gmac_dev, pucUseBuffer, ipTOTAL_ETHERNET_FRAME_SIZE, &ulReceiveCount ); if( ( ulResult != GMAC_OK ) || ( ulReceiveCount == 0 ) ) { /* No data from the hardware. */ break; } if( pxNextNetworkBufferDescriptor == NULL ) { /* Data was read from the hardware, but no descriptor was available for it, so it will be dropped. */ iptraceETHERNET_RX_EVENT_LOST(); continue; } iptraceNETWORK_INTERFACE_RECEIVE(); pxNextNetworkBufferDescriptor->xDataLength = ( size_t ) ulReceiveCount; xRxEvent.pvData = ( void * ) pxNextNetworkBufferDescriptor; /* Send the descriptor to the IP task for processing. */ if( xSendEventStructToIPTask( &xRxEvent, xBlockTime ) != pdTRUE ) { /* The buffer could not be sent to the stack so must be released again. */ vReleaseNetworkBufferAndDescriptor( pxNextNetworkBufferDescriptor ); iptraceETHERNET_RX_EVENT_LOST(); FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) ); } /* Now the buffer has either been passed to the IP-task, or it has been released in the code above. */ pxNextNetworkBufferDescriptor = NULL; ulReturnValue++; } return ulReturnValue; }