X-Git-Url: https://git.sur5r.net/?p=freertos;a=blobdiff_plain;f=FreeRTOS-Plus%2FSource%2FFreeRTOS-Plus-TCP%2Fportable%2FNetworkInterface%2Fpic32mzef%2FBufferAllocation_2.c;fp=FreeRTOS-Plus%2FSource%2FFreeRTOS-Plus-TCP%2Fportable%2FNetworkInterface%2Fpic32mzef%2FBufferAllocation_2.c;h=531e878eafc8e2837e6364281d242bafa746d401;hp=f00ae1fe8297ad4f59a02fd20f769a4420e22952;hb=4fd3a0b144b6aa91eabd79a1eaf9bc0c8397f433;hpb=b15dfacb6026af3b0ba697e5753844923b468d2b diff --git a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/pic32mzef/BufferAllocation_2.c b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/pic32mzef/BufferAllocation_2.c index f00ae1fe8..531e878ea 100644 --- a/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/pic32mzef/BufferAllocation_2.c +++ b/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/pic32mzef/BufferAllocation_2.c @@ -1,620 +1,620 @@ -/* - * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd. - * Authors include Hein Tibosch and Richard Barry - * - ******************************************************************************* - ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE *** - *** *** - *** *** - *** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP *** - *** demos have a dependency on FreeRTOS+FAT, which is only in the Labs *** - *** download): *** - *** *** - *** FreeRTOS+TCP is functional and has been used in commercial products *** - *** for some time. Be aware however that we are still refining its *** - *** design, the source code does not yet quite conform to the strict *** - *** coding and style standards mandated by Real Time Engineers ltd., and *** - *** the documentation and testing is not necessarily complete. *** - *** *** - *** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE *** - *** URL: http://www.FreeRTOS.org/contact Active early adopters may, at *** - *** the sole discretion of Real Time Engineers Ltd., be offered versions *** - *** under a license other than that described below. *** - *** *** - *** *** - ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE *** - ******************************************************************************* - * - * FreeRTOS+TCP can be used under two different free open source licenses. The - * license that applies is dependent on the processor on which FreeRTOS+TCP is - * executed, as follows: - * - * If FreeRTOS+TCP is executed on one of the processors listed under the Special - * License Arrangements heading of the FreeRTOS+TCP license information web - * page, then it can be used under the terms of the FreeRTOS Open Source - * License. If FreeRTOS+TCP is used on any other processor, then it can be used - * under the terms of the GNU General Public License V2. Links to the relevant - * licenses follow: - * - * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license - * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license - * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt - * - * FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot - * use FreeRTOS+TCP unless you agree that you use the software 'as is'. - * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied - * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR - * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they - * implied, expressed, or statutory. - * - * 1 tab == 4 spaces! - * - * http://www.FreeRTOS.org - * http://www.FreeRTOS.org/plus - * http://www.FreeRTOS.org/labs - * - */ - -/****************************************************************************** -* -* See the following web page for essential buffer allocation scheme usage and -* configuration details: -* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html -* -******************************************************************************/ - -/* THIS FILE SHOULD NOT BE USED IF THE PROJECT INCLUDES A MEMORY ALLOCATOR - * THAT WILL FRAGMENT THE HEAP MEMORY. For example, heap_2 must not be used, - * heap_4 can be used. */ - -/* Standard includes. */ -#include - -/* FreeRTOS includes. */ -#include "FreeRTOS.h" -#include "task.h" -#include "semphr.h" - -/* FreeRTOS+TCP includes. */ -#include "FreeRTOS_IP.h" -#include "FreeRTOS_UDP_IP.h" -#include "FreeRTOS_IP_Private.h" -#include "NetworkInterface.h" -#include "NetworkBufferManagement.h" - -#include "tcpip/tcpip.h" -#include "tcpip/src/tcpip_private.h" - -#include "NetworkConfig.h" - -/* The obtained network buffer must be large enough to hold a packet that might - * replace the packet that was requested to be sent. */ -#if ipconfigUSE_TCP == 1 - #define baMINIMAL_BUFFER_SIZE sizeof( TCPPacket_t ) -#else - #define baMINIMAL_BUFFER_SIZE sizeof( ARPPacket_t ) -#endif /* ipconfigUSE_TCP == 1 */ - -/*_RB_ This is too complex not to have an explanation. */ -#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES ) - #define ASSERT_CONCAT_( a, b ) a ## b - #define ASSERT_CONCAT( a, b ) ASSERT_CONCAT_( a, b ) - #define STATIC_ASSERT( e ) \ - ; enum { ASSERT_CONCAT( assert_line_, __LINE__ ) = 1 / ( !!( e ) ) } - - STATIC_ASSERT( ipconfigETHERNET_MINIMUM_PACKET_BYTES <= baMINIMAL_BUFFER_SIZE ); -#endif - -/* A list of free (available) NetworkBufferDescriptor_t structures. */ -static List_t xFreeBuffersList; - -/* Some statistics about the use of buffers. */ -static size_t uxMinimumFreeNetworkBuffers; - -/* Declares the pool of NetworkBufferDescriptor_t structures that are available - * to the system. All the network buffers referenced from xFreeBuffersList exist - * in this array. The array is not accessed directly except during initialisation, - * when the xFreeBuffersList is filled (as all the buffers are free when the system - * is booted). */ -static NetworkBufferDescriptor_t xNetworkBufferDescriptors[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ]; - -/* This constant is defined as false to let FreeRTOS_TCP_IP.c know that the - * network buffers have a variable size: resizing may be necessary */ -const BaseType_t xBufferAllocFixedSize = pdFALSE; - -/* The semaphore used to obtain network buffers. */ -static SemaphoreHandle_t xNetworkBufferSemaphore = NULL; - -/*-----------------------------------------------------------*/ - -#ifdef PIC32_USE_ETHERNET - - /* PIC32 specific stuff */ - /* */ - - /* MAC packet acknowledgment, once MAC is done with it */ - static bool PIC32_MacPacketAcknowledge( TCPIP_MAC_PACKET * pPkt, - const void * param ); - - /* allocates a MAC packet that holds a data buffer that can be used by both: */ - /* - the FreeRTOSIP (NetworkBufferDescriptor_t->pucEthernetBuffer) */ - /* - the Harmony MAC driver: TCPIP_MAC_PACKET->pDSeg->segLoad */ - /* from the beginning of the buffer: */ - /* - 4 bytes pointer to the network descriptor (FreeRTOS) */ - /* - 4 bytes pointer to the MAC packet (pic32_NetworkInterface.c) */ - /* - 2 bytes offset from the MAC packet (Harmony MAC driver: segLoadOffset) */ - /* */ - /* NOTE: segLoadLen should NOT include: */ - /* - the TCPIP_MAC_FRAME_OFFSET (== ipBUFFER_PADDING which should be == 10!) */ - /* - the sizeof(TCPIP_MAC_ETHERNET_HEADER) */ - /* These are added by the MAC packet allocation! */ - /* */ - static uint8_t * PIC32_PktAlloc( uint16_t pktLen, - uint16_t segLoadLen, - TCPIP_MAC_PACKET_ACK_FUNC ackF, - TCPIP_MAC_PACKET ** pPtrPkt ) - { - uint8_t * pBuff = 0; - - /* allocate standard packet */ - TCPIP_MAC_PACKET * pPkt = TCPIP_PKT_PacketAlloc( pktLen, segLoadLen, 0 ); - - /* set the MAC packet pointer in the packet */ - if( pPkt != 0 ) - { - pBuff = pPkt->pDSeg->segLoad; - TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pBuff - PIC32_BUFFER_PKT_PTR_OSSET ); - configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 ); - *ppkt = pPkt; /* store the packet it comes from */ - pPkt->ackFunc = ackF; - pPkt->ackParam = 0; - } - - if( pPtrPkt != 0 ) - { - *pPtrPkt = pPkt; - } - - return pBuff; - } - - - - /* standard PIC32 MAC allocation function for a MAC packet */ - /* this packet saves room for the FreeRTOS network descriptor */ - /* at the beginning of the data buffer */ - /* see NetworkBufferAllocate */ - /* Note: flags parameter is ignored since that's used in the Harmony stack only */ - TCPIP_MAC_PACKET * PIC32_MacPacketAllocate( uint16_t pktLen, - uint16_t segLoadLen, - TCPIP_MAC_PACKET_FLAGS flags ) - { - TCPIP_MAC_PACKET * pPkt; - - PIC32_PktAlloc( pktLen, segLoadLen, 0, &pPkt ); - - return pPkt; - } - - /* standard PIC32 MAC packet acknowledgment */ - /* function called once MAC is done with it */ - static bool PIC32_MacPacketAcknowledge( TCPIP_MAC_PACKET * pPkt, - const void * param ) - { - configASSERT( ( pPkt != 0 ) ); - - TCPIP_PKT_PacketFree( pPkt ); - - return false; - } - - /* associates the current MAC packet with a network descriptor */ - /* mainly for RX packet */ - void PIC32_MacAssociate( TCPIP_MAC_PACKET * pRxPkt, - NetworkBufferDescriptor_t * pxBufferDescriptor, - size_t pktLength ) - { - uint8_t * pPktBuff = pRxPkt->pDSeg->segLoad; - - pxBufferDescriptor->pucEthernetBuffer = pPktBuff; - pxBufferDescriptor->xDataLength = pktLength; - - /* make sure this is a properly allocated packet */ - TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pPktBuff - PIC32_BUFFER_PKT_PTR_OSSET ); - configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 ); - - if( *ppkt != pRxPkt ) - { - configASSERT( false ); - } - - /* set the proper descriptor info */ - NetworkBufferDescriptor_t ** ppDcpt = ( NetworkBufferDescriptor_t ** ) ( pPktBuff - ipBUFFER_PADDING ); - configASSERT( ( ( uint32_t ) ppDcpt & ( sizeof( uint32_t ) - 1 ) ) == 0 ); - *ppDcpt = pxBufferDescriptor; - } - - /* debug functionality */ - void PIC32_MacPacketOrphan( TCPIP_MAC_PACKET * pPkt ) - { - TCPIP_PKT_PacketFree( pPkt ); - configASSERT( false ); - } - - /* FreeRTOS allocation functions */ - - /* allocates a buffer that can be used by both: */ - /* - the FreeRTOSIP (NetworkBufferDescriptor_t->pucEthernetBuffer) */ - /* - the Harmony MAC driver: TCPIP_MAC_PACKET */ - /* See PIC32_PktAlloc for details */ - /* */ - /* NOTE: reqLength should NOT include the ipBUFFER_PADDING (which should be == 10!) */ - /* or the sizeof(TCPIP_MAC_ETHERNET_HEADER) */ - /* These are added by the MAC packet allocation! */ - /* */ - uint8_t * NetworkBufferAllocate( size_t reqLength ) - { - return PIC32_PktAlloc( sizeof( TCPIP_MAC_PACKET ), reqLength, PIC32_MacPacketAcknowledge, 0 ); - } - - /* deallocates a network buffer previously allocated */ - /* with NetworkBufferAllocate */ - void NetworkBufferFree( uint8_t * pNetworkBuffer ) - { - if( pNetworkBuffer != 0 ) - { - TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pNetworkBuffer - PIC32_BUFFER_PKT_PTR_OSSET ); - configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 ); - TCPIP_MAC_PACKET * pPkt = *ppkt; - configASSERT( ( pPkt != 0 ) ); - - if( pPkt->ackFunc != 0 ) - { - ( *pPkt->ackFunc )( pPkt, pPkt->ackParam ); - } - else - { /* ??? */ - PIC32_MacPacketOrphan( pPkt ); - } - } - } - -#endif /* #ifdef PIC32_USE_ETHERNET */ - -/*-----------------------------------------------------------*/ - -BaseType_t xNetworkBuffersInitialise( void ) -{ - BaseType_t xReturn, x; - - /* Only initialise the buffers and their associated kernel objects if they - * have not been initialised before. */ - if( xNetworkBufferSemaphore == NULL ) - { - xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ); - configASSERT( xNetworkBufferSemaphore ); - - if( xNetworkBufferSemaphore != NULL ) - { - #if ( configQUEUE_REGISTRY_SIZE > 0 ) - { - vQueueAddToRegistry( xNetworkBufferSemaphore, "NetBufSem" ); - } - #endif /* configQUEUE_REGISTRY_SIZE */ - - /* If the trace recorder code is included name the semaphore for viewing - * in FreeRTOS+Trace. */ - #if ( ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 ) - { - extern QueueHandle_t xNetworkEventQueue; - vTraceSetQueueName( xNetworkEventQueue, "IPStackEvent" ); - vTraceSetQueueName( xNetworkBufferSemaphore, "NetworkBufferCount" ); - } - #endif /* ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 */ - - vListInitialise( &xFreeBuffersList ); - - /* Initialise all the network buffers. No storage is allocated to - * the buffers yet. */ - for( x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ ) - { - /* Initialise and set the owner of the buffer list items. */ - xNetworkBufferDescriptors[ x ].pucEthernetBuffer = NULL; - vListInitialiseItem( &( xNetworkBufferDescriptors[ x ].xBufferListItem ) ); - listSET_LIST_ITEM_OWNER( &( xNetworkBufferDescriptors[ x ].xBufferListItem ), &xNetworkBufferDescriptors[ x ] ); - - /* Currently, all buffers are available for use. */ - vListInsert( &xFreeBuffersList, &( xNetworkBufferDescriptors[ x ].xBufferListItem ) ); - } - - uxMinimumFreeNetworkBuffers = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; - } - } - - if( xNetworkBufferSemaphore == NULL ) - { - xReturn = pdFAIL; - } - else - { - xReturn = pdPASS; - } - - return xReturn; -} -/*-----------------------------------------------------------*/ - -uint8_t * pucGetNetworkBuffer( size_t * pxRequestedSizeBytes ) -{ - uint8_t * pucEthernetBuffer; - size_t xSize = *pxRequestedSizeBytes; - - if( xSize < baMINIMAL_BUFFER_SIZE ) - { - /* Buffers must be at least large enough to hold a TCP-packet with - * headers, or an ARP packet, in case TCP is not included. */ - xSize = baMINIMAL_BUFFER_SIZE; - } - - /* Round up xSize to the nearest multiple of N bytes, - * where N equals 'sizeof( size_t )'. */ - if( ( xSize & ( sizeof( size_t ) - 1u ) ) != 0u ) - { - xSize = ( xSize | ( sizeof( size_t ) - 1u ) ) + 1u; - } - - *pxRequestedSizeBytes = xSize; - - /* Allocate a buffer large enough to store the requested Ethernet frame size - * and a pointer to a network buffer structure (hence the addition of - * ipBUFFER_PADDING bytes). */ - - #ifdef PIC32_USE_ETHERNET - pucEthernetBuffer = NetworkBufferAllocate( xSize - sizeof( TCPIP_MAC_ETHERNET_HEADER ) ); - #else - pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xSize + ipBUFFER_PADDING ); - #endif /* #ifdef PIC32_USE_ETHERNET */ - - configASSERT( pucEthernetBuffer ); - - if( pucEthernetBuffer != NULL ) - { - /* Enough space is left at the start of the buffer to place a pointer to - * the network buffer structure that references this Ethernet buffer. - * Return a pointer to the start of the Ethernet buffer itself. */ - #ifndef PIC32_USE_ETHERNET - pucEthernetBuffer += ipBUFFER_PADDING; - #endif /* #ifndef PIC32_USE_ETHERNET */ - } - - return pucEthernetBuffer; -} -/*-----------------------------------------------------------*/ - -void vReleaseNetworkBuffer( uint8_t * pucEthernetBuffer ) -{ - /* There is space before the Ethernet buffer in which a pointer to the - * network buffer that references this Ethernet buffer is stored. Remove the - * space before freeing the buffer. */ - #ifdef PIC32_USE_ETHERNET - NetworkBufferFree( pucEthernetBuffer ); - #else - if( pucEthernetBuffer != NULL ) - { - pucEthernetBuffer -= ipBUFFER_PADDING; - vPortFree( ( void * ) pucEthernetBuffer ); - } - #endif /* #ifdef PIC32_USE_ETHERNET */ -} -/*-----------------------------------------------------------*/ - -NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes, - TickType_t xBlockTimeTicks ) -{ - NetworkBufferDescriptor_t * pxReturn = NULL; - size_t uxCount; - - if( ( xRequestedSizeBytes != 0u ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) ) - { - /* ARP packets can replace application packets, so the storage must be - * at least large enough to hold an ARP. */ - xRequestedSizeBytes = baMINIMAL_BUFFER_SIZE; - } - - #ifdef PIC32_USE_ETHERNET - if( xRequestedSizeBytes != 0u ) - { - #endif /* #ifdef PIC32_USE_ETHERNET */ - xRequestedSizeBytes += 2u; - - if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1u ) ) != 0u ) - { - xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1u ) ) + 1u; - } - #ifdef PIC32_USE_ETHERNET - } - #endif /* #ifdef PIC32_USE_ETHERNET */ - - /* If there is a semaphore available, there is a network buffer available. */ - if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS ) - { - /* Protect the structure as it is accessed from tasks and interrupts. */ - taskENTER_CRITICAL(); - { - pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList ); - uxListRemove( &( pxReturn->xBufferListItem ) ); - } - taskEXIT_CRITICAL(); - - /* Reading UBaseType_t, no critical section needed. */ - uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList ); - - if( uxMinimumFreeNetworkBuffers > uxCount ) - { - uxMinimumFreeNetworkBuffers = uxCount; - } - - /* Allocate storage of exactly the requested size to the buffer. */ - configASSERT( pxReturn->pucEthernetBuffer == NULL ); - - if( xRequestedSizeBytes > 0 ) - { - /* Extra space is obtained so a pointer to the network buffer can - * be stored at the beginning of the buffer. */ - - #ifdef PIC32_USE_ETHERNET - pxReturn->pucEthernetBuffer = NetworkBufferAllocate( xRequestedSizeBytes - sizeof( TCPIP_MAC_ETHERNET_HEADER ) ); - #else - pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xRequestedSizeBytes + ipBUFFER_PADDING ); - #endif /* #ifdef PIC32_USE_ETHERNET */ - - if( pxReturn->pucEthernetBuffer == NULL ) - { - /* The attempt to allocate storage for the buffer payload failed, - * so the network buffer structure cannot be used and must be - * released. */ - vReleaseNetworkBufferAndDescriptor( pxReturn ); - pxReturn = NULL; - } - else - { - /* Store a pointer to the network buffer structure in the - * buffer storage area, then move the buffer pointer on past the - * stored pointer so the pointer value is not overwritten by the - * application when the buffer is used. */ - #ifdef PIC32_USE_ETHERNET - *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer - ipBUFFER_PADDING ) ) = pxReturn; - #else - *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer ) ) = pxReturn; - pxReturn->pucEthernetBuffer += ipBUFFER_PADDING; - #endif /* #ifdef PIC32_USE_ETHERNET */ - - /* Store the actual size of the allocated buffer, which may be - * greater than the original requested size. */ - pxReturn->xDataLength = xRequestedSizeBytes; - - #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) - { - /* make sure the buffer is not linked */ - pxReturn->pxNextBuffer = NULL; - } - #endif /* ipconfigUSE_LINKED_RX_MESSAGES */ - } - } - else - { - /* A descriptor is being returned without an associated buffer being - * allocated. */ - } - } - - if( pxReturn == NULL ) - { - iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER(); - } - else - { - iptraceNETWORK_BUFFER_OBTAINED( pxReturn ); - } - - return pxReturn; -} -/*-----------------------------------------------------------*/ - -void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer ) -{ - BaseType_t xListItemAlreadyInFreeList; - - /* Ensure the buffer is returned to the list of free buffers before the - * counting semaphore is 'given' to say a buffer is available. Release the - * storage allocated to the buffer payload. THIS FILE SHOULD NOT BE USED - * IF THE PROJECT INCLUDES A MEMORY ALLOCATOR THAT WILL FRAGMENT THE HEAP - * MEMORY. For example, heap_2 must not be used, heap_4 can be used. */ - vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer ); - pxNetworkBuffer->pucEthernetBuffer = NULL; - - taskENTER_CRITICAL(); - { - xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); - - if( xListItemAlreadyInFreeList == pdFALSE ) - { - vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); - } - } - taskEXIT_CRITICAL(); - - /* - * Update the network state machine, unless the program fails to release its 'xNetworkBufferSemaphore'. - * The program should only try to release its semaphore if 'xListItemAlreadyInFreeList' is false. - */ - if( xListItemAlreadyInFreeList == pdFALSE ) - { - if ( xSemaphoreGive( xNetworkBufferSemaphore ) == pdTRUE ) - { - iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); - } - } - else - { - iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); - } -} -/*-----------------------------------------------------------*/ - -/* - * Returns the number of free network buffers - */ -UBaseType_t uxGetNumberOfFreeNetworkBuffers( void ) -{ - return listCURRENT_LIST_LENGTH( &xFreeBuffersList ); -} -/*-----------------------------------------------------------*/ - -UBaseType_t uxGetMinimumFreeNetworkBuffers( void ) -{ - return uxMinimumFreeNetworkBuffers; -} -/*-----------------------------------------------------------*/ - -NetworkBufferDescriptor_t * pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer, - size_t xNewSizeBytes ) -{ - size_t xOriginalLength; - uint8_t * pucBuffer; - - #ifdef PIC32_USE_ETHERNET - xOriginalLength = pxNetworkBuffer->xDataLength; - #else - xOriginalLength = pxNetworkBuffer->xDataLength + ipBUFFER_PADDING; - xNewSizeBytes = xNewSizeBytes + ipBUFFER_PADDING; - #endif /* #ifdef PIC32_USE_ETHERNET */ - - pucBuffer = pucGetNetworkBuffer( &( xNewSizeBytes ) ); - - if( pucBuffer == NULL ) - { - /* In case the allocation fails, return NULL. */ - pxNetworkBuffer = NULL; - } - else - { - pxNetworkBuffer->xDataLength = xNewSizeBytes; - if( xNewSizeBytes > xOriginalLength ) - { - xNewSizeBytes = xOriginalLength; - } - - #ifdef PIC32_USE_ETHERNET - memcpy( pucBuffer, pxNetworkBuffer->pucEthernetBuffer, xNewSizeBytes ); - *( ( NetworkBufferDescriptor_t ** ) ( pucBuffer - ipBUFFER_PADDING ) ) = pxNetworkBuffer; - #else - memcpy( pucBuffer - ipBUFFER_PADDING, pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING, xNewSizeBytes ); - #endif /* #ifdef PIC32_USE_ETHERNET */ - - vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer ); - pxNetworkBuffer->pucEthernetBuffer = pucBuffer; - } - - return pxNetworkBuffer; -} +/* + * FreeRTOS+TCP Labs Build 160919 (C) 2016 Real Time Engineers ltd. + * Authors include Hein Tibosch and Richard Barry + * + ******************************************************************************* + ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE *** + *** *** + *** *** + *** FREERTOS+TCP IS STILL IN THE LAB (mainly because the FTP and HTTP *** + *** demos have a dependency on FreeRTOS+FAT, which is only in the Labs *** + *** download): *** + *** *** + *** FreeRTOS+TCP is functional and has been used in commercial products *** + *** for some time. Be aware however that we are still refining its *** + *** design, the source code does not yet quite conform to the strict *** + *** coding and style standards mandated by Real Time Engineers ltd., and *** + *** the documentation and testing is not necessarily complete. *** + *** *** + *** PLEASE REPORT EXPERIENCES USING THE SUPPORT RESOURCES FOUND ON THE *** + *** URL: http://www.FreeRTOS.org/contact Active early adopters may, at *** + *** the sole discretion of Real Time Engineers Ltd., be offered versions *** + *** under a license other than that described below. *** + *** *** + *** *** + ***** NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE ******* NOTE *** + ******************************************************************************* + * + * FreeRTOS+TCP can be used under two different free open source licenses. The + * license that applies is dependent on the processor on which FreeRTOS+TCP is + * executed, as follows: + * + * If FreeRTOS+TCP is executed on one of the processors listed under the Special + * License Arrangements heading of the FreeRTOS+TCP license information web + * page, then it can be used under the terms of the FreeRTOS Open Source + * License. If FreeRTOS+TCP is used on any other processor, then it can be used + * under the terms of the GNU General Public License V2. Links to the relevant + * licenses follow: + * + * The FreeRTOS+TCP License Information Page: http://www.FreeRTOS.org/tcp_license + * The FreeRTOS Open Source License: http://www.FreeRTOS.org/license + * The GNU General Public License Version 2: http://www.FreeRTOS.org/gpl-2.0.txt + * + * FreeRTOS+TCP is distributed in the hope that it will be useful. You cannot + * use FreeRTOS+TCP unless you agree that you use the software 'as is'. + * FreeRTOS+TCP is provided WITHOUT ANY WARRANTY; without even the implied + * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they + * implied, expressed, or statutory. + * + * 1 tab == 4 spaces! + * + * http://www.FreeRTOS.org + * http://www.FreeRTOS.org/plus + * http://www.FreeRTOS.org/labs + * + */ + +/****************************************************************************** +* +* See the following web page for essential buffer allocation scheme usage and +* configuration details: +* http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html +* +******************************************************************************/ + +/* THIS FILE SHOULD NOT BE USED IF THE PROJECT INCLUDES A MEMORY ALLOCATOR + * THAT WILL FRAGMENT THE HEAP MEMORY. For example, heap_2 must not be used, + * heap_4 can be used. */ + +/* Standard includes. */ +#include + +/* FreeRTOS includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "semphr.h" + +/* FreeRTOS+TCP includes. */ +#include "FreeRTOS_IP.h" +#include "FreeRTOS_UDP_IP.h" +#include "FreeRTOS_IP_Private.h" +#include "NetworkInterface.h" +#include "NetworkBufferManagement.h" + +#include "tcpip/tcpip.h" +#include "tcpip/src/tcpip_private.h" + +#include "NetworkConfig.h" + +/* The obtained network buffer must be large enough to hold a packet that might + * replace the packet that was requested to be sent. */ +#if ipconfigUSE_TCP == 1 + #define baMINIMAL_BUFFER_SIZE sizeof( TCPPacket_t ) +#else + #define baMINIMAL_BUFFER_SIZE sizeof( ARPPacket_t ) +#endif /* ipconfigUSE_TCP == 1 */ + +/*_RB_ This is too complex not to have an explanation. */ +#if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES ) + #define ASSERT_CONCAT_( a, b ) a ## b + #define ASSERT_CONCAT( a, b ) ASSERT_CONCAT_( a, b ) + #define STATIC_ASSERT( e ) \ + ; enum { ASSERT_CONCAT( assert_line_, __LINE__ ) = 1 / ( !!( e ) ) } + + STATIC_ASSERT( ipconfigETHERNET_MINIMUM_PACKET_BYTES <= baMINIMAL_BUFFER_SIZE ); +#endif + +/* A list of free (available) NetworkBufferDescriptor_t structures. */ +static List_t xFreeBuffersList; + +/* Some statistics about the use of buffers. */ +static size_t uxMinimumFreeNetworkBuffers; + +/* Declares the pool of NetworkBufferDescriptor_t structures that are available + * to the system. All the network buffers referenced from xFreeBuffersList exist + * in this array. The array is not accessed directly except during initialisation, + * when the xFreeBuffersList is filled (as all the buffers are free when the system + * is booted). */ +static NetworkBufferDescriptor_t xNetworkBufferDescriptors[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ]; + +/* This constant is defined as false to let FreeRTOS_TCP_IP.c know that the + * network buffers have a variable size: resizing may be necessary */ +const BaseType_t xBufferAllocFixedSize = pdFALSE; + +/* The semaphore used to obtain network buffers. */ +static SemaphoreHandle_t xNetworkBufferSemaphore = NULL; + +/*-----------------------------------------------------------*/ + +#ifdef PIC32_USE_ETHERNET + + /* PIC32 specific stuff */ + /* */ + + /* MAC packet acknowledgment, once MAC is done with it */ + static bool PIC32_MacPacketAcknowledge( TCPIP_MAC_PACKET * pPkt, + const void * param ); + + /* allocates a MAC packet that holds a data buffer that can be used by both: */ + /* - the FreeRTOSIP (NetworkBufferDescriptor_t->pucEthernetBuffer) */ + /* - the Harmony MAC driver: TCPIP_MAC_PACKET->pDSeg->segLoad */ + /* from the beginning of the buffer: */ + /* - 4 bytes pointer to the network descriptor (FreeRTOS) */ + /* - 4 bytes pointer to the MAC packet (pic32_NetworkInterface.c) */ + /* - 2 bytes offset from the MAC packet (Harmony MAC driver: segLoadOffset) */ + /* */ + /* NOTE: segLoadLen should NOT include: */ + /* - the TCPIP_MAC_FRAME_OFFSET (== ipBUFFER_PADDING which should be == 10!) */ + /* - the sizeof(TCPIP_MAC_ETHERNET_HEADER) */ + /* These are added by the MAC packet allocation! */ + /* */ + static uint8_t * PIC32_PktAlloc( uint16_t pktLen, + uint16_t segLoadLen, + TCPIP_MAC_PACKET_ACK_FUNC ackF, + TCPIP_MAC_PACKET ** pPtrPkt ) + { + uint8_t * pBuff = 0; + + /* allocate standard packet */ + TCPIP_MAC_PACKET * pPkt = TCPIP_PKT_PacketAlloc( pktLen, segLoadLen, 0 ); + + /* set the MAC packet pointer in the packet */ + if( pPkt != 0 ) + { + pBuff = pPkt->pDSeg->segLoad; + TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pBuff - PIC32_BUFFER_PKT_PTR_OSSET ); + configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 ); + *ppkt = pPkt; /* store the packet it comes from */ + pPkt->ackFunc = ackF; + pPkt->ackParam = 0; + } + + if( pPtrPkt != 0 ) + { + *pPtrPkt = pPkt; + } + + return pBuff; + } + + + + /* standard PIC32 MAC allocation function for a MAC packet */ + /* this packet saves room for the FreeRTOS network descriptor */ + /* at the beginning of the data buffer */ + /* see NetworkBufferAllocate */ + /* Note: flags parameter is ignored since that's used in the Harmony stack only */ + TCPIP_MAC_PACKET * PIC32_MacPacketAllocate( uint16_t pktLen, + uint16_t segLoadLen, + TCPIP_MAC_PACKET_FLAGS flags ) + { + TCPIP_MAC_PACKET * pPkt; + + PIC32_PktAlloc( pktLen, segLoadLen, 0, &pPkt ); + + return pPkt; + } + + /* standard PIC32 MAC packet acknowledgment */ + /* function called once MAC is done with it */ + static bool PIC32_MacPacketAcknowledge( TCPIP_MAC_PACKET * pPkt, + const void * param ) + { + configASSERT( ( pPkt != 0 ) ); + + TCPIP_PKT_PacketFree( pPkt ); + + return false; + } + + /* associates the current MAC packet with a network descriptor */ + /* mainly for RX packet */ + void PIC32_MacAssociate( TCPIP_MAC_PACKET * pRxPkt, + NetworkBufferDescriptor_t * pxBufferDescriptor, + size_t pktLength ) + { + uint8_t * pPktBuff = pRxPkt->pDSeg->segLoad; + + pxBufferDescriptor->pucEthernetBuffer = pPktBuff; + pxBufferDescriptor->xDataLength = pktLength; + + /* make sure this is a properly allocated packet */ + TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pPktBuff - PIC32_BUFFER_PKT_PTR_OSSET ); + configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 ); + + if( *ppkt != pRxPkt ) + { + configASSERT( false ); + } + + /* set the proper descriptor info */ + NetworkBufferDescriptor_t ** ppDcpt = ( NetworkBufferDescriptor_t ** ) ( pPktBuff - ipBUFFER_PADDING ); + configASSERT( ( ( uint32_t ) ppDcpt & ( sizeof( uint32_t ) - 1 ) ) == 0 ); + *ppDcpt = pxBufferDescriptor; + } + + /* debug functionality */ + void PIC32_MacPacketOrphan( TCPIP_MAC_PACKET * pPkt ) + { + TCPIP_PKT_PacketFree( pPkt ); + configASSERT( false ); + } + + /* FreeRTOS allocation functions */ + + /* allocates a buffer that can be used by both: */ + /* - the FreeRTOSIP (NetworkBufferDescriptor_t->pucEthernetBuffer) */ + /* - the Harmony MAC driver: TCPIP_MAC_PACKET */ + /* See PIC32_PktAlloc for details */ + /* */ + /* NOTE: reqLength should NOT include the ipBUFFER_PADDING (which should be == 10!) */ + /* or the sizeof(TCPIP_MAC_ETHERNET_HEADER) */ + /* These are added by the MAC packet allocation! */ + /* */ + uint8_t * NetworkBufferAllocate( size_t reqLength ) + { + return PIC32_PktAlloc( sizeof( TCPIP_MAC_PACKET ), reqLength, PIC32_MacPacketAcknowledge, 0 ); + } + + /* deallocates a network buffer previously allocated */ + /* with NetworkBufferAllocate */ + void NetworkBufferFree( uint8_t * pNetworkBuffer ) + { + if( pNetworkBuffer != 0 ) + { + TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pNetworkBuffer - PIC32_BUFFER_PKT_PTR_OSSET ); + configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 ); + TCPIP_MAC_PACKET * pPkt = *ppkt; + configASSERT( ( pPkt != 0 ) ); + + if( pPkt->ackFunc != 0 ) + { + ( *pPkt->ackFunc )( pPkt, pPkt->ackParam ); + } + else + { /* ??? */ + PIC32_MacPacketOrphan( pPkt ); + } + } + } + +#endif /* #ifdef PIC32_USE_ETHERNET */ + +/*-----------------------------------------------------------*/ + +BaseType_t xNetworkBuffersInitialise( void ) +{ + BaseType_t xReturn, x; + + /* Only initialise the buffers and their associated kernel objects if they + * have not been initialised before. */ + if( xNetworkBufferSemaphore == NULL ) + { + xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ); + configASSERT( xNetworkBufferSemaphore ); + + if( xNetworkBufferSemaphore != NULL ) + { + #if ( configQUEUE_REGISTRY_SIZE > 0 ) + { + vQueueAddToRegistry( xNetworkBufferSemaphore, "NetBufSem" ); + } + #endif /* configQUEUE_REGISTRY_SIZE */ + + /* If the trace recorder code is included name the semaphore for viewing + * in FreeRTOS+Trace. */ + #if ( ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 ) + { + extern QueueHandle_t xNetworkEventQueue; + vTraceSetQueueName( xNetworkEventQueue, "IPStackEvent" ); + vTraceSetQueueName( xNetworkBufferSemaphore, "NetworkBufferCount" ); + } + #endif /* ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 */ + + vListInitialise( &xFreeBuffersList ); + + /* Initialise all the network buffers. No storage is allocated to + * the buffers yet. */ + for( x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ ) + { + /* Initialise and set the owner of the buffer list items. */ + xNetworkBufferDescriptors[ x ].pucEthernetBuffer = NULL; + vListInitialiseItem( &( xNetworkBufferDescriptors[ x ].xBufferListItem ) ); + listSET_LIST_ITEM_OWNER( &( xNetworkBufferDescriptors[ x ].xBufferListItem ), &xNetworkBufferDescriptors[ x ] ); + + /* Currently, all buffers are available for use. */ + vListInsert( &xFreeBuffersList, &( xNetworkBufferDescriptors[ x ].xBufferListItem ) ); + } + + uxMinimumFreeNetworkBuffers = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; + } + } + + if( xNetworkBufferSemaphore == NULL ) + { + xReturn = pdFAIL; + } + else + { + xReturn = pdPASS; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + +uint8_t * pucGetNetworkBuffer( size_t * pxRequestedSizeBytes ) +{ + uint8_t * pucEthernetBuffer; + size_t xSize = *pxRequestedSizeBytes; + + if( xSize < baMINIMAL_BUFFER_SIZE ) + { + /* Buffers must be at least large enough to hold a TCP-packet with + * headers, or an ARP packet, in case TCP is not included. */ + xSize = baMINIMAL_BUFFER_SIZE; + } + + /* Round up xSize to the nearest multiple of N bytes, + * where N equals 'sizeof( size_t )'. */ + if( ( xSize & ( sizeof( size_t ) - 1u ) ) != 0u ) + { + xSize = ( xSize | ( sizeof( size_t ) - 1u ) ) + 1u; + } + + *pxRequestedSizeBytes = xSize; + + /* Allocate a buffer large enough to store the requested Ethernet frame size + * and a pointer to a network buffer structure (hence the addition of + * ipBUFFER_PADDING bytes). */ + + #ifdef PIC32_USE_ETHERNET + pucEthernetBuffer = NetworkBufferAllocate( xSize - sizeof( TCPIP_MAC_ETHERNET_HEADER ) ); + #else + pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xSize + ipBUFFER_PADDING ); + #endif /* #ifdef PIC32_USE_ETHERNET */ + + configASSERT( pucEthernetBuffer ); + + if( pucEthernetBuffer != NULL ) + { + /* Enough space is left at the start of the buffer to place a pointer to + * the network buffer structure that references this Ethernet buffer. + * Return a pointer to the start of the Ethernet buffer itself. */ + #ifndef PIC32_USE_ETHERNET + pucEthernetBuffer += ipBUFFER_PADDING; + #endif /* #ifndef PIC32_USE_ETHERNET */ + } + + return pucEthernetBuffer; +} +/*-----------------------------------------------------------*/ + +void vReleaseNetworkBuffer( uint8_t * pucEthernetBuffer ) +{ + /* There is space before the Ethernet buffer in which a pointer to the + * network buffer that references this Ethernet buffer is stored. Remove the + * space before freeing the buffer. */ + #ifdef PIC32_USE_ETHERNET + NetworkBufferFree( pucEthernetBuffer ); + #else + if( pucEthernetBuffer != NULL ) + { + pucEthernetBuffer -= ipBUFFER_PADDING; + vPortFree( ( void * ) pucEthernetBuffer ); + } + #endif /* #ifdef PIC32_USE_ETHERNET */ +} +/*-----------------------------------------------------------*/ + +NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes, + TickType_t xBlockTimeTicks ) +{ + NetworkBufferDescriptor_t * pxReturn = NULL; + size_t uxCount; + + if( ( xRequestedSizeBytes != 0u ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) ) + { + /* ARP packets can replace application packets, so the storage must be + * at least large enough to hold an ARP. */ + xRequestedSizeBytes = baMINIMAL_BUFFER_SIZE; + } + + #ifdef PIC32_USE_ETHERNET + if( xRequestedSizeBytes != 0u ) + { + #endif /* #ifdef PIC32_USE_ETHERNET */ + xRequestedSizeBytes += 2u; + + if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1u ) ) != 0u ) + { + xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1u ) ) + 1u; + } + #ifdef PIC32_USE_ETHERNET + } + #endif /* #ifdef PIC32_USE_ETHERNET */ + + /* If there is a semaphore available, there is a network buffer available. */ + if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS ) + { + /* Protect the structure as it is accessed from tasks and interrupts. */ + taskENTER_CRITICAL(); + { + pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList ); + uxListRemove( &( pxReturn->xBufferListItem ) ); + } + taskEXIT_CRITICAL(); + + /* Reading UBaseType_t, no critical section needed. */ + uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList ); + + if( uxMinimumFreeNetworkBuffers > uxCount ) + { + uxMinimumFreeNetworkBuffers = uxCount; + } + + /* Allocate storage of exactly the requested size to the buffer. */ + configASSERT( pxReturn->pucEthernetBuffer == NULL ); + + if( xRequestedSizeBytes > 0 ) + { + /* Extra space is obtained so a pointer to the network buffer can + * be stored at the beginning of the buffer. */ + + #ifdef PIC32_USE_ETHERNET + pxReturn->pucEthernetBuffer = NetworkBufferAllocate( xRequestedSizeBytes - sizeof( TCPIP_MAC_ETHERNET_HEADER ) ); + #else + pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xRequestedSizeBytes + ipBUFFER_PADDING ); + #endif /* #ifdef PIC32_USE_ETHERNET */ + + if( pxReturn->pucEthernetBuffer == NULL ) + { + /* The attempt to allocate storage for the buffer payload failed, + * so the network buffer structure cannot be used and must be + * released. */ + vReleaseNetworkBufferAndDescriptor( pxReturn ); + pxReturn = NULL; + } + else + { + /* Store a pointer to the network buffer structure in the + * buffer storage area, then move the buffer pointer on past the + * stored pointer so the pointer value is not overwritten by the + * application when the buffer is used. */ + #ifdef PIC32_USE_ETHERNET + *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer - ipBUFFER_PADDING ) ) = pxReturn; + #else + *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer ) ) = pxReturn; + pxReturn->pucEthernetBuffer += ipBUFFER_PADDING; + #endif /* #ifdef PIC32_USE_ETHERNET */ + + /* Store the actual size of the allocated buffer, which may be + * greater than the original requested size. */ + pxReturn->xDataLength = xRequestedSizeBytes; + + #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 ) + { + /* make sure the buffer is not linked */ + pxReturn->pxNextBuffer = NULL; + } + #endif /* ipconfigUSE_LINKED_RX_MESSAGES */ + } + } + else + { + /* A descriptor is being returned without an associated buffer being + * allocated. */ + } + } + + if( pxReturn == NULL ) + { + iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER(); + } + else + { + iptraceNETWORK_BUFFER_OBTAINED( pxReturn ); + } + + return pxReturn; +} +/*-----------------------------------------------------------*/ + +void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer ) +{ + BaseType_t xListItemAlreadyInFreeList; + + /* Ensure the buffer is returned to the list of free buffers before the + * counting semaphore is 'given' to say a buffer is available. Release the + * storage allocated to the buffer payload. THIS FILE SHOULD NOT BE USED + * IF THE PROJECT INCLUDES A MEMORY ALLOCATOR THAT WILL FRAGMENT THE HEAP + * MEMORY. For example, heap_2 must not be used, heap_4 can be used. */ + vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer ); + pxNetworkBuffer->pucEthernetBuffer = NULL; + + taskENTER_CRITICAL(); + { + xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); + + if( xListItemAlreadyInFreeList == pdFALSE ) + { + vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) ); + } + } + taskEXIT_CRITICAL(); + + /* + * Update the network state machine, unless the program fails to release its 'xNetworkBufferSemaphore'. + * The program should only try to release its semaphore if 'xListItemAlreadyInFreeList' is false. + */ + if( xListItemAlreadyInFreeList == pdFALSE ) + { + if ( xSemaphoreGive( xNetworkBufferSemaphore ) == pdTRUE ) + { + iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); + } + } + else + { + iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer ); + } +} +/*-----------------------------------------------------------*/ + +/* + * Returns the number of free network buffers + */ +UBaseType_t uxGetNumberOfFreeNetworkBuffers( void ) +{ + return listCURRENT_LIST_LENGTH( &xFreeBuffersList ); +} +/*-----------------------------------------------------------*/ + +UBaseType_t uxGetMinimumFreeNetworkBuffers( void ) +{ + return uxMinimumFreeNetworkBuffers; +} +/*-----------------------------------------------------------*/ + +NetworkBufferDescriptor_t * pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer, + size_t xNewSizeBytes ) +{ + size_t xOriginalLength; + uint8_t * pucBuffer; + + #ifdef PIC32_USE_ETHERNET + xOriginalLength = pxNetworkBuffer->xDataLength; + #else + xOriginalLength = pxNetworkBuffer->xDataLength + ipBUFFER_PADDING; + xNewSizeBytes = xNewSizeBytes + ipBUFFER_PADDING; + #endif /* #ifdef PIC32_USE_ETHERNET */ + + pucBuffer = pucGetNetworkBuffer( &( xNewSizeBytes ) ); + + if( pucBuffer == NULL ) + { + /* In case the allocation fails, return NULL. */ + pxNetworkBuffer = NULL; + } + else + { + pxNetworkBuffer->xDataLength = xNewSizeBytes; + if( xNewSizeBytes > xOriginalLength ) + { + xNewSizeBytes = xOriginalLength; + } + + #ifdef PIC32_USE_ETHERNET + memcpy( pucBuffer, pxNetworkBuffer->pucEthernetBuffer, xNewSizeBytes ); + *( ( NetworkBufferDescriptor_t ** ) ( pucBuffer - ipBUFFER_PADDING ) ) = pxNetworkBuffer; + #else + memcpy( pucBuffer - ipBUFFER_PADDING, pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING, xNewSizeBytes ); + #endif /* #ifdef PIC32_USE_ETHERNET */ + + vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer ); + pxNetworkBuffer->pucEthernetBuffer = pucBuffer; + } + + return pxNetworkBuffer; +}