xref: /FreeRTOS-Plus-TCP-v3.1.0/source/portable/NetworkInterface/pic32mzef/BufferAllocation_2.c (revision 37bdfe577f3b728058de714e2e747d3c78803f26)
1 /*
2  * FreeRTOS+TCP V3.1.0
3  * Copyright (C) 2022 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  *
24  * http://aws.amazon.com/freertos
25  * http://www.FreeRTOS.org
26  */
27 
28 /******************************************************************************
29 *
30 * See the following web page for essential buffer allocation scheme usage and
31 * configuration details:
32 * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/Embedded_Ethernet_Buffer_Management.html
33 *
34 ******************************************************************************/
35 
36 /* THIS FILE SHOULD NOT BE USED IF THE PROJECT INCLUDES A MEMORY ALLOCATOR
37  * THAT WILL FRAGMENT THE HEAP MEMORY.  For example, heap_2 must not be used,
38  * heap_4 can be used. */
39 
40 /* Standard includes. */
41 #include <stdint.h>
42 
43 /* FreeRTOS includes. */
44 #include "FreeRTOS.h"
45 #include "task.h"
46 #include "semphr.h"
47 
48 /* FreeRTOS+TCP includes. */
49 #include "FreeRTOS_IP.h"
50 #include "FreeRTOS_UDP_IP.h"
51 #include "FreeRTOS_IP_Private.h"
52 #include "NetworkInterface.h"
53 #include "NetworkBufferManagement.h"
54 
55 #include "tcpip/tcpip.h"
56 #include "tcpip/src/tcpip_private.h"
57 
58 #include "NetworkConfig.h"
59 
60 /* The obtained network buffer must be large enough to hold a packet that might
61  * replace the packet that was requested to be sent. */
62 #if ipconfigUSE_TCP == 1
63     #define baMINIMAL_BUFFER_SIZE    sizeof( TCPPacket_t )
64 #else
65     #define baMINIMAL_BUFFER_SIZE    sizeof( ARPPacket_t )
66 #endif /* ipconfigUSE_TCP == 1 */
67 
68 /*_RB_ This is too complex not to have an explanation. */
69 #if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )
70     #define ASSERT_CONCAT_( a, b )    a ## b
71     #define ASSERT_CONCAT( a, b )     ASSERT_CONCAT_( a, b )
72     #define STATIC_ASSERT( e ) \
73     ; enum { ASSERT_CONCAT( assert_line_, __LINE__ ) = 1 / ( !!( e ) ) }
74 
75     STATIC_ASSERT( ipconfigETHERNET_MINIMUM_PACKET_BYTES <= baMINIMAL_BUFFER_SIZE );
76 #endif
77 
78 /* A list of free (available) NetworkBufferDescriptor_t structures. */
79 static List_t xFreeBuffersList;
80 
81 /* Some statistics about the use of buffers. */
82 static size_t uxMinimumFreeNetworkBuffers;
83 
84 /* Declares the pool of NetworkBufferDescriptor_t structures that are available
85  * to the system.  All the network buffers referenced from xFreeBuffersList exist
86  * in this array.  The array is not accessed directly except during initialisation,
87  * when the xFreeBuffersList is filled (as all the buffers are free when the system
88  * is booted). */
89 static NetworkBufferDescriptor_t xNetworkBufferDescriptors[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ];
90 
91 /* This constant is defined as false to let FreeRTOS_TCP_IP.c know that the
92  * network buffers have a variable size: resizing may be necessary */
93 const BaseType_t xBufferAllocFixedSize = pdFALSE;
94 
95 /* The semaphore used to obtain network buffers. */
96 static SemaphoreHandle_t xNetworkBufferSemaphore = NULL;
97 
98 /*-----------------------------------------------------------*/
99 
100 #ifdef PIC32_USE_ETHERNET
101 
102 /* PIC32 specific stuff */
103 /* */
104 
105 /* MAC packet acknowledgment, once MAC is done with it */
106     static bool PIC32_MacPacketAcknowledge( TCPIP_MAC_PACKET * pPkt,
107                                             const void * param );
108 
109 /* allocates a MAC packet that holds a data buffer that can be used by both: */
110 /*  - the FreeRTOSIP (NetworkBufferDescriptor_t->pucEthernetBuffer) */
111 /*  - the Harmony MAC driver: TCPIP_MAC_PACKET->pDSeg->segLoad */
112 /* from the beginning of the buffer: */
113 /*      - 4 bytes pointer to the network descriptor (FreeRTOS) */
114 /*      - 4 bytes pointer to the MAC packet (pic32_NetworkInterface.c) */
115 /*      - 2 bytes offset from the MAC packet (Harmony MAC driver: segLoadOffset) */
116 /* */
117 /* NOTE: segLoadLen should NOT include: */
118 /*          - the TCPIP_MAC_FRAME_OFFSET (== ipBUFFER_PADDING which should be == 10!) */
119 /*          - the sizeof(TCPIP_MAC_ETHERNET_HEADER) */
120 /*       These are added by the MAC packet allocation! */
121 /* */
PIC32_PktAlloc(uint16_t pktLen,uint16_t segLoadLen,TCPIP_MAC_PACKET_ACK_FUNC ackF,TCPIP_MAC_PACKET ** pPtrPkt)122     static uint8_t * PIC32_PktAlloc( uint16_t pktLen,
123                                      uint16_t segLoadLen,
124                                      TCPIP_MAC_PACKET_ACK_FUNC ackF,
125                                      TCPIP_MAC_PACKET ** pPtrPkt )
126     {
127         uint8_t * pBuff = 0;
128 
129         /* allocate standard packet */
130         TCPIP_MAC_PACKET * pPkt = TCPIP_PKT_PacketAlloc( pktLen, segLoadLen, 0 );
131 
132         /* set the MAC packet pointer in the packet */
133         if( pPkt != 0 )
134         {
135             pBuff = pPkt->pDSeg->segLoad;
136             TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pBuff - PIC32_BUFFER_PKT_PTR_OSSET );
137             configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
138             *ppkt = pPkt; /* store the packet it comes from */
139             pPkt->ackFunc = ackF;
140             pPkt->ackParam = 0;
141         }
142 
143         if( pPtrPkt != 0 )
144         {
145             *pPtrPkt = pPkt;
146         }
147 
148         return pBuff;
149     }
150 
151 
152 
153 /* standard PIC32 MAC allocation function for a MAC packet */
154 /* this packet saves room for the FreeRTOS network descriptor */
155 /* at the beginning of the data buffer */
156 /* see NetworkBufferAllocate */
157 /* Note: flags parameter is ignored since that's used in the Harmony stack only */
PIC32_MacPacketAllocate(uint16_t pktLen,uint16_t segLoadLen,TCPIP_MAC_PACKET_FLAGS flags)158     TCPIP_MAC_PACKET * PIC32_MacPacketAllocate( uint16_t pktLen,
159                                                 uint16_t segLoadLen,
160                                                 TCPIP_MAC_PACKET_FLAGS flags )
161     {
162         TCPIP_MAC_PACKET * pPkt;
163 
164         PIC32_PktAlloc( pktLen, segLoadLen, 0, &pPkt );
165 
166         return pPkt;
167     }
168 
169 /* standard PIC32 MAC packet acknowledgment */
170 /* function called once MAC is done with it */
PIC32_MacPacketAcknowledge(TCPIP_MAC_PACKET * pPkt,const void * param)171     static bool PIC32_MacPacketAcknowledge( TCPIP_MAC_PACKET * pPkt,
172                                             const void * param )
173     {
174         configASSERT( ( pPkt != 0 ) );
175 
176         TCPIP_PKT_PacketFree( pPkt );
177 
178         return false;
179     }
180 
181 /* associates the current MAC packet with a network descriptor */
182 /* mainly for RX packet */
PIC32_MacAssociate(TCPIP_MAC_PACKET * pRxPkt,NetworkBufferDescriptor_t * pxBufferDescriptor,size_t pktLength)183     void PIC32_MacAssociate( TCPIP_MAC_PACKET * pRxPkt,
184                              NetworkBufferDescriptor_t * pxBufferDescriptor,
185                              size_t pktLength )
186     {
187         uint8_t * pPktBuff = pRxPkt->pDSeg->segLoad;
188 
189         pxBufferDescriptor->pucEthernetBuffer = pPktBuff;
190         pxBufferDescriptor->xDataLength = pktLength;
191 
192         /* make sure this is a properly allocated packet */
193         TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pPktBuff - PIC32_BUFFER_PKT_PTR_OSSET );
194 
195         configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
196 
197         if( *ppkt != pRxPkt )
198         {
199             configASSERT( false );
200         }
201 
202         /* set the proper descriptor info */
203         NetworkBufferDescriptor_t ** ppDcpt = ( NetworkBufferDescriptor_t ** ) ( pPktBuff - ipBUFFER_PADDING );
204 
205         configASSERT( ( ( uint32_t ) ppDcpt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
206         *ppDcpt = pxBufferDescriptor;
207     }
208 
209 /* debug functionality */
PIC32_MacPacketOrphan(TCPIP_MAC_PACKET * pPkt)210     void PIC32_MacPacketOrphan( TCPIP_MAC_PACKET * pPkt )
211     {
212         TCPIP_PKT_PacketFree( pPkt );
213         configASSERT( false );
214     }
215 
216 /* FreeRTOS allocation functions */
217 
218 /* allocates a buffer that can be used by both: */
219 /*  - the FreeRTOSIP (NetworkBufferDescriptor_t->pucEthernetBuffer) */
220 /*  - the Harmony MAC driver: TCPIP_MAC_PACKET */
221 /*  See PIC32_PktAlloc for details */
222 /* */
223 /* NOTE: reqLength should NOT include the ipBUFFER_PADDING (which should be == 10!) */
224 /*       or the sizeof(TCPIP_MAC_ETHERNET_HEADER) */
225 /*       These are added by the MAC packet allocation! */
226 /* */
NetworkBufferAllocate(size_t reqLength)227     uint8_t * NetworkBufferAllocate( size_t reqLength )
228     {
229         return PIC32_PktAlloc( sizeof( TCPIP_MAC_PACKET ), reqLength, PIC32_MacPacketAcknowledge, 0 );
230     }
231 
232 /* deallocates a network buffer previously allocated */
233 /* with NetworkBufferAllocate */
NetworkBufferFree(uint8_t * pNetworkBuffer)234     void NetworkBufferFree( uint8_t * pNetworkBuffer )
235     {
236         if( pNetworkBuffer != 0 )
237         {
238             TCPIP_MAC_PACKET ** ppkt = ( TCPIP_MAC_PACKET ** ) ( pNetworkBuffer - PIC32_BUFFER_PKT_PTR_OSSET );
239             configASSERT( ( ( uint32_t ) ppkt & ( sizeof( uint32_t ) - 1 ) ) == 0 );
240             TCPIP_MAC_PACKET * pPkt = *ppkt;
241             configASSERT( ( pPkt != 0 ) );
242 
243             if( pPkt->ackFunc != 0 )
244             {
245                 ( *pPkt->ackFunc )( pPkt, pPkt->ackParam );
246             }
247             else
248             { /* ??? */
249                 PIC32_MacPacketOrphan( pPkt );
250             }
251         }
252     }
253 
254 #endif /* #ifdef PIC32_USE_ETHERNET */
255 
256 /*-----------------------------------------------------------*/
257 
xNetworkBuffersInitialise(void)258 BaseType_t xNetworkBuffersInitialise( void )
259 {
260     BaseType_t xReturn, x;
261 
262     /* Only initialise the buffers and their associated kernel objects if they
263      * have not been initialised before. */
264     if( xNetworkBufferSemaphore == NULL )
265     {
266         xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS, ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS );
267         configASSERT( xNetworkBufferSemaphore );
268 
269         if( xNetworkBufferSemaphore != NULL )
270         {
271             #if ( configQUEUE_REGISTRY_SIZE > 0 )
272                 {
273                     vQueueAddToRegistry( xNetworkBufferSemaphore, "NetBufSem" );
274                 }
275             #endif /* configQUEUE_REGISTRY_SIZE */
276 
277             /* If the trace recorder code is included name the semaphore for viewing
278              * in FreeRTOS+Trace.  */
279             #if ( ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 )
280                 {
281                     extern QueueHandle_t xNetworkEventQueue;
282                     vTraceSetQueueName( xNetworkEventQueue, "IPStackEvent" );
283                     vTraceSetQueueName( xNetworkBufferSemaphore, "NetworkBufferCount" );
284                 }
285             #endif /*  ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS == 1 */
286 
287             vListInitialise( &xFreeBuffersList );
288 
289             /* Initialise all the network buffers.  No storage is allocated to
290              * the buffers yet. */
291             for( x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ )
292             {
293                 /* Initialise and set the owner of the buffer list items. */
294                 xNetworkBufferDescriptors[ x ].pucEthernetBuffer = NULL;
295                 vListInitialiseItem( &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );
296                 listSET_LIST_ITEM_OWNER( &( xNetworkBufferDescriptors[ x ].xBufferListItem ), &xNetworkBufferDescriptors[ x ] );
297 
298                 /* Currently, all buffers are available for use. */
299                 vListInsert( &xFreeBuffersList, &( xNetworkBufferDescriptors[ x ].xBufferListItem ) );
300             }
301 
302             uxMinimumFreeNetworkBuffers = ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS;
303         }
304     }
305 
306     if( xNetworkBufferSemaphore == NULL )
307     {
308         xReturn = pdFAIL;
309     }
310     else
311     {
312         xReturn = pdPASS;
313     }
314 
315     return xReturn;
316 }
317 /*-----------------------------------------------------------*/
318 
pucGetNetworkBuffer(size_t * pxRequestedSizeBytes)319 uint8_t * pucGetNetworkBuffer( size_t * pxRequestedSizeBytes )
320 {
321     uint8_t * pucEthernetBuffer;
322     size_t xSize = *pxRequestedSizeBytes;
323 
324     if( xSize < baMINIMAL_BUFFER_SIZE )
325     {
326         /* Buffers must be at least large enough to hold a TCP-packet with
327          * headers, or an ARP packet, in case TCP is not included. */
328         xSize = baMINIMAL_BUFFER_SIZE;
329     }
330 
331     /* Round up xSize to the nearest multiple of N bytes,
332      * where N equals 'sizeof( size_t )'. */
333     if( ( xSize & ( sizeof( size_t ) - 1u ) ) != 0u )
334     {
335         xSize = ( xSize | ( sizeof( size_t ) - 1u ) ) + 1u;
336     }
337 
338     *pxRequestedSizeBytes = xSize;
339 
340     /* Allocate a buffer large enough to store the requested Ethernet frame size
341      * and a pointer to a network buffer structure (hence the addition of
342      * ipBUFFER_PADDING bytes). */
343 
344     #ifdef PIC32_USE_ETHERNET
345         pucEthernetBuffer = NetworkBufferAllocate( xSize - sizeof( TCPIP_MAC_ETHERNET_HEADER ) );
346     #else
347         pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xSize + ipBUFFER_PADDING );
348     #endif /* #ifdef PIC32_USE_ETHERNET */
349 
350     configASSERT( pucEthernetBuffer );
351 
352     if( pucEthernetBuffer != NULL )
353     {
354         /* Enough space is left at the start of the buffer to place a pointer to
355          * the network buffer structure that references this Ethernet buffer.
356          * Return a pointer to the start of the Ethernet buffer itself. */
357         #ifndef PIC32_USE_ETHERNET
358             pucEthernetBuffer += ipBUFFER_PADDING;
359         #endif /* #ifndef PIC32_USE_ETHERNET */
360     }
361 
362     return pucEthernetBuffer;
363 }
364 /*-----------------------------------------------------------*/
365 
vReleaseNetworkBuffer(uint8_t * pucEthernetBuffer)366 void vReleaseNetworkBuffer( uint8_t * pucEthernetBuffer )
367 {
368     /* There is space before the Ethernet buffer in which a pointer to the
369      * network buffer that references this Ethernet buffer is stored.  Remove the
370      * space before freeing the buffer. */
371     #ifdef PIC32_USE_ETHERNET
372         NetworkBufferFree( pucEthernetBuffer );
373     #else
374         if( pucEthernetBuffer != NULL )
375         {
376             pucEthernetBuffer -= ipBUFFER_PADDING;
377             vPortFree( ( void * ) pucEthernetBuffer );
378         }
379     #endif /* #ifdef PIC32_USE_ETHERNET */
380 }
381 /*-----------------------------------------------------------*/
382 
pxGetNetworkBufferWithDescriptor(size_t xRequestedSizeBytes,TickType_t xBlockTimeTicks)383 NetworkBufferDescriptor_t * pxGetNetworkBufferWithDescriptor( size_t xRequestedSizeBytes,
384                                                               TickType_t xBlockTimeTicks )
385 {
386     NetworkBufferDescriptor_t * pxReturn = NULL;
387     size_t uxCount;
388 
389     if( ( xRequestedSizeBytes != 0u ) && ( xRequestedSizeBytes < ( size_t ) baMINIMAL_BUFFER_SIZE ) )
390     {
391         /* ARP packets can replace application packets, so the storage must be
392          * at least large enough to hold an ARP. */
393         xRequestedSizeBytes = baMINIMAL_BUFFER_SIZE;
394     }
395 
396     #ifdef PIC32_USE_ETHERNET
397         if( xRequestedSizeBytes != 0u )
398         {
399     #endif /* #ifdef PIC32_USE_ETHERNET */
400     xRequestedSizeBytes += 2u;
401 
402     if( ( xRequestedSizeBytes & ( sizeof( size_t ) - 1u ) ) != 0u )
403     {
404         xRequestedSizeBytes = ( xRequestedSizeBytes | ( sizeof( size_t ) - 1u ) ) + 1u;
405     }
406 
407     #ifdef PIC32_USE_ETHERNET
408 }
409     #endif /* #ifdef PIC32_USE_ETHERNET */
410 
411     /* If there is a semaphore available, there is a network buffer available. */
412     if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )
413     {
414         /* Protect the structure as it is accessed from tasks and interrupts. */
415         taskENTER_CRITICAL();
416         {
417             pxReturn = ( NetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
418             uxListRemove( &( pxReturn->xBufferListItem ) );
419         }
420         taskEXIT_CRITICAL();
421 
422         /* Reading UBaseType_t, no critical section needed. */
423         uxCount = listCURRENT_LIST_LENGTH( &xFreeBuffersList );
424 
425         if( uxMinimumFreeNetworkBuffers > uxCount )
426         {
427             uxMinimumFreeNetworkBuffers = uxCount;
428         }
429 
430         /* Allocate storage of exactly the requested size to the buffer. */
431         configASSERT( pxReturn->pucEthernetBuffer == NULL );
432 
433         if( xRequestedSizeBytes > 0 )
434         {
435             /* Extra space is obtained so a pointer to the network buffer can
436              * be stored at the beginning of the buffer. */
437 
438             #ifdef PIC32_USE_ETHERNET
439                 pxReturn->pucEthernetBuffer = NetworkBufferAllocate( xRequestedSizeBytes - sizeof( TCPIP_MAC_ETHERNET_HEADER ) );
440             #else
441                 pxReturn->pucEthernetBuffer = ( uint8_t * ) pvPortMalloc( xRequestedSizeBytes + ipBUFFER_PADDING );
442             #endif /* #ifdef PIC32_USE_ETHERNET */
443 
444             if( pxReturn->pucEthernetBuffer == NULL )
445             {
446                 /* The attempt to allocate storage for the buffer payload failed,
447                  * so the network buffer structure cannot be used and must be
448                  * released. */
449                 vReleaseNetworkBufferAndDescriptor( pxReturn );
450                 pxReturn = NULL;
451             }
452             else
453             {
454                 /* Store a pointer to the network buffer structure in the
455                  * buffer storage area, then move the buffer pointer on past the
456                  * stored pointer so the pointer value is not overwritten by the
457                  * application when the buffer is used. */
458                 #ifdef PIC32_USE_ETHERNET
459                     *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer - ipBUFFER_PADDING ) ) = pxReturn;
460                 #else
461                     *( ( NetworkBufferDescriptor_t ** ) ( pxReturn->pucEthernetBuffer ) ) = pxReturn;
462                     pxReturn->pucEthernetBuffer += ipBUFFER_PADDING;
463                 #endif /* #ifdef PIC32_USE_ETHERNET */
464 
465                 /* Store the actual size of the allocated buffer, which may be
466                  * greater than the original requested size. */
467                 pxReturn->xDataLength = xRequestedSizeBytes;
468 
469                 #if ( ipconfigUSE_LINKED_RX_MESSAGES != 0 )
470                     {
471                         /* make sure the buffer is not linked */
472                         pxReturn->pxNextBuffer = NULL;
473                     }
474                 #endif /* ipconfigUSE_LINKED_RX_MESSAGES */
475             }
476         }
477         else
478         {
479             /* A descriptor is being returned without an associated buffer being
480              * allocated. */
481         }
482     }
483 
484     if( pxReturn == NULL )
485     {
486         iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();
487     }
488     else
489     {
490         iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
491     }
492 
493     return pxReturn;
494 }
495 /*-----------------------------------------------------------*/
496 
vReleaseNetworkBufferAndDescriptor(NetworkBufferDescriptor_t * const pxNetworkBuffer)497 void vReleaseNetworkBufferAndDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer )
498 {
499     BaseType_t xListItemAlreadyInFreeList;
500 
501     /* Ensure the buffer is returned to the list of free buffers before the
502     * counting semaphore is 'given' to say a buffer is available.  Release the
503     * storage allocated to the buffer payload.  THIS FILE SHOULD NOT BE USED
504     * IF THE PROJECT INCLUDES A MEMORY ALLOCATOR THAT WILL FRAGMENT THE HEAP
505     * MEMORY.  For example, heap_2 must not be used, heap_4 can be used. */
506     vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );
507     pxNetworkBuffer->pucEthernetBuffer = NULL;
508 
509     taskENTER_CRITICAL();
510     {
511         xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
512 
513         if( xListItemAlreadyInFreeList == pdFALSE )
514         {
515             vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
516         }
517     }
518     taskEXIT_CRITICAL();
519 
520     /*
521      * Update the network state machine, unless the program fails to release its 'xNetworkBufferSemaphore'.
522      * The program should only try to release its semaphore if 'xListItemAlreadyInFreeList' is false.
523      */
524     if( xListItemAlreadyInFreeList == pdFALSE )
525     {
526         if( xSemaphoreGive( xNetworkBufferSemaphore ) == pdTRUE )
527         {
528             iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
529         }
530     }
531     else
532     {
533         iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
534     }
535 }
536 /*-----------------------------------------------------------*/
537 
538 /*
539  * Returns the number of free network buffers
540  */
uxGetNumberOfFreeNetworkBuffers(void)541 UBaseType_t uxGetNumberOfFreeNetworkBuffers( void )
542 {
543     return listCURRENT_LIST_LENGTH( &xFreeBuffersList );
544 }
545 /*-----------------------------------------------------------*/
546 
uxGetMinimumFreeNetworkBuffers(void)547 UBaseType_t uxGetMinimumFreeNetworkBuffers( void )
548 {
549     return uxMinimumFreeNetworkBuffers;
550 }
551 /*-----------------------------------------------------------*/
552 
pxResizeNetworkBufferWithDescriptor(NetworkBufferDescriptor_t * pxNetworkBuffer,size_t xNewSizeBytes)553 NetworkBufferDescriptor_t * pxResizeNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * pxNetworkBuffer,
554                                                                  size_t xNewSizeBytes )
555 {
556     size_t xOriginalLength;
557     uint8_t * pucBuffer;
558 
559     #ifdef PIC32_USE_ETHERNET
560         xOriginalLength = pxNetworkBuffer->xDataLength;
561     #else
562         xOriginalLength = pxNetworkBuffer->xDataLength + ipBUFFER_PADDING;
563         xNewSizeBytes = xNewSizeBytes + ipBUFFER_PADDING;
564     #endif /* #ifdef PIC32_USE_ETHERNET */
565 
566     pucBuffer = pucGetNetworkBuffer( &( xNewSizeBytes ) );
567 
568     if( pucBuffer == NULL )
569     {
570         /* In case the allocation fails, return NULL. */
571         pxNetworkBuffer = NULL;
572     }
573     else
574     {
575         pxNetworkBuffer->xDataLength = xNewSizeBytes;
576 
577         if( xNewSizeBytes > xOriginalLength )
578         {
579             xNewSizeBytes = xOriginalLength;
580         }
581 
582         #ifdef PIC32_USE_ETHERNET
583             memcpy( pucBuffer, pxNetworkBuffer->pucEthernetBuffer, xNewSizeBytes );
584             *( ( NetworkBufferDescriptor_t ** ) ( pucBuffer - ipBUFFER_PADDING ) ) = pxNetworkBuffer;
585         #else
586             memcpy( pucBuffer - ipBUFFER_PADDING, pxNetworkBuffer->pucEthernetBuffer - ipBUFFER_PADDING, xNewSizeBytes );
587         #endif /* #ifdef PIC32_USE_ETHERNET */
588 
589         vReleaseNetworkBuffer( pxNetworkBuffer->pucEthernetBuffer );
590         pxNetworkBuffer->pucEthernetBuffer = pucBuffer;
591     }
592 
593     return pxNetworkBuffer;
594 }
595