2 * FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.
\r
4 * FreeRTOS+UDP is an add-on component to FreeRTOS. It is not, in itself, part
\r
5 * of the FreeRTOS kernel. FreeRTOS+UDP is licensed separately from FreeRTOS,
\r
6 * and uses a different license to FreeRTOS. FreeRTOS+UDP uses a dual license
\r
7 * model, information on which is provided below:
\r
9 * - Open source licensing -
\r
10 * FreeRTOS+UDP is a free download and may be used, modified and distributed
\r
11 * without charge provided the user adheres to version two of the GNU General
\r
12 * Public license (GPL) and does not remove the copyright notice or this text.
\r
13 * The GPL V2 text is available on the gnu.org web site, and on the following
\r
14 * URL: http://www.FreeRTOS.org/gpl-2.0.txt
\r
16 * - Commercial licensing -
\r
17 * Businesses and individuals who wish to incorporate FreeRTOS+UDP into
\r
18 * proprietary software for redistribution in any form must first obtain a
\r
19 * (very) low cost commercial license - and in-so-doing support the maintenance,
\r
20 * support and further development of the FreeRTOS+UDP product. Commercial
\r
21 * licenses can be obtained from http://shop.freertos.org and do not require any
\r
22 * source files to be changed.
\r
24 * FreeRTOS+UDP is distributed in the hope that it will be useful. You cannot
\r
25 * use FreeRTOS+UDP unless you agree that you use the software 'as is'.
\r
26 * FreeRTOS+UDP is provided WITHOUT ANY WARRANTY; without even the implied
\r
27 * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
\r
28 * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they
\r
29 * implied, expressed, or statutory.
\r
31 * 1 tab == 4 spaces!
\r
33 * http://www.FreeRTOS.org
\r
34 * http://www.FreeRTOS.org/udp
\r
39 /******************************************************************************
\r
41 * See the following web page for essential buffer allocation scheme usage and
\r
42 * configuration details:
\r
43 * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Buffer_Management.shtml
\r
45 ******************************************************************************/
\r
48 /* Standard includes. */
\r
51 /* FreeRTOS includes. */
\r
52 #include "FreeRTOS.h"
\r
56 /* FreeRTOS+UDP includes. */
\r
57 #include "FreeRTOS_UDP_IP.h"
\r
58 #include "NetworkInterface.h"
\r
60 /* For an Ethernet interrupt to be able to obtain a network buffer there must
\r
61 be at least this number of buffers available. */
\r
62 #define ipINTERRUPT_BUFFER_GET_THRESHOLD ( 3 )
\r
64 /* A list of free (available) xNetworkBufferDescriptor_t structures. */
\r
65 static xList xFreeBuffersList;
\r
67 /* Declares the pool of xNetworkBufferDescriptor_t structures that are available to the
\r
68 system. All the network buffers referenced from xFreeBuffersList exist in this
\r
69 array. The array is not accessed directly except during initialisation, when
\r
70 the xFreeBuffersList is filled (as all the buffers are free when the system is
\r
72 static xNetworkBufferDescriptor_t xNetworkBuffers[ ipconfigNUM_NETWORK_BUFFERS ];
\r
74 /* The semaphore used to obtain network buffers. */
\r
75 static xSemaphoreHandle xNetworkBufferSemaphore = NULL;
\r
77 /*-----------------------------------------------------------*/
\r
79 portBASE_TYPE xNetworkBuffersInitialise( void )
\r
81 portBASE_TYPE xReturn, x;
\r
83 /* Only initialise the buffers and their associated kernel objects if they
\r
84 have not been initialised before. */
\r
85 if( xNetworkBufferSemaphore == NULL )
\r
87 xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFERS, ipconfigNUM_NETWORK_BUFFERS );
\r
88 configASSERT( xNetworkBufferSemaphore );
\r
90 if( xNetworkBufferSemaphore != NULL )
\r
92 vListInitialise( &xFreeBuffersList );
\r
94 /* Initialise all the network buffers. The buffer storage comes
\r
95 from the network interface, and different hardware has different
\r
97 vNetworkInterfaceAllocateRAMToBuffers( xNetworkBuffers );
\r
98 for( x = 0; x < ipconfigNUM_NETWORK_BUFFERS; x++ )
\r
100 /* Initialise and set the owner of the buffer list items. */
\r
101 vListInitialiseItem( &( xNetworkBuffers[ x ].xBufferListItem ) );
\r
102 listSET_LIST_ITEM_OWNER( &( xNetworkBuffers[ x ].xBufferListItem ), &xNetworkBuffers[ x ] );
\r
104 /* Currently, all buffers are available for use. */
\r
105 vListInsert( &xFreeBuffersList, &( xNetworkBuffers[ x ].xBufferListItem ) );
\r
110 if( xNetworkBufferSemaphore == NULL )
\r
121 /*-----------------------------------------------------------*/
\r
123 xNetworkBufferDescriptor_t *pxNetworkBufferGet( size_t xRequestedSizeBytes, portTickType xBlockTimeTicks )
\r
125 xNetworkBufferDescriptor_t *pxReturn = NULL;
\r
127 /*_RB_ The current implementation only has a single size memory block, so
\r
128 the requested size parameter is not used (yet). */
\r
129 ( void ) xRequestedSizeBytes;
\r
131 /* If there is a semaphore available, there is a network buffer available. */
\r
132 if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )
\r
134 /* Protect the structure as it is accessed from tasks and interrupts. */
\r
135 taskENTER_CRITICAL();
\r
137 pxReturn = ( xNetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
\r
138 uxListRemove( &( pxReturn->xBufferListItem ) );
\r
140 taskEXIT_CRITICAL();
\r
141 iptraceNETWORK_BUFFER_OBTAINED( pxReturn );
\r
145 iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();
\r
150 /*-----------------------------------------------------------*/
\r
152 xNetworkBufferDescriptor_t *pxNetworkBufferGetFromISR( size_t xRequestedSizeBytes )
\r
154 xNetworkBufferDescriptor_t *pxReturn = NULL;
\r
155 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
157 /*_RB_ The current implementation only has a single size memory block, so
\r
158 the requested size parameter is not used (yet). */
\r
159 ( void ) xRequestedSizeBytes;
\r
161 /* If there is a semaphore available then there is a buffer available, but,
\r
162 as this is called from an interrupt, only take a buffer if there are at
\r
163 least ipINTERRUPT_BUFFER_GET_THRESHOLD buffers remaining. This prevents,
\r
164 to a certain degree at least, a rapidly executing interrupt exhausting
\r
165 buffer and in so doing preventing tasks from continuing. */
\r
166 if( uxQueueMessagesWaitingFromISR( ( xQueueHandle ) xNetworkBufferSemaphore ) > ipINTERRUPT_BUFFER_GET_THRESHOLD )
\r
168 if( xSemaphoreTakeFromISR( xNetworkBufferSemaphore, NULL ) == pdPASS )
\r
170 /* Protect the structure as it is accessed from tasks and interrupts. */
\r
171 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
173 pxReturn = ( xNetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );
\r
174 uxListRemove( &( pxReturn->xBufferListItem ) );
\r
176 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
178 iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR( pxReturn );
\r
182 if( pxReturn == NULL )
\r
184 iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR();
\r
189 /*-----------------------------------------------------------*/
\r
191 portBASE_TYPE vNetworkBufferReleaseFromISR( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
\r
193 unsigned portBASE_TYPE uxSavedInterruptStatus;
\r
194 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
\r
196 /* Ensure the buffer is returned to the list of free buffers before the
\r
197 counting semaphore is 'given' to say a buffer is available. */
\r
198 uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
\r
200 vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
\r
202 portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
\r
204 xSemaphoreGiveFromISR( xNetworkBufferSemaphore, &xHigherPriorityTaskWoken );
\r
205 iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
\r
207 return xHigherPriorityTaskWoken;
\r
209 /*-----------------------------------------------------------*/
\r
211 void vNetworkBufferRelease( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
\r
213 portBASE_TYPE xListItemAlreadyInFreeList;
\r
215 /* Ensure the buffer is returned to the list of free buffers before the
\r
216 counting semaphore is 'given' to say a buffer is available. */
\r
217 taskENTER_CRITICAL();
\r
219 xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
\r
221 if( xListItemAlreadyInFreeList == pdFALSE )
\r
223 vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );
\r
226 configASSERT( xListItemAlreadyInFreeList == pdFALSE );
\r
228 taskEXIT_CRITICAL();
\r
230 xSemaphoreGive( xNetworkBufferSemaphore );
\r
231 iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );
\r
233 /*-----------------------------------------------------------*/
\r
235 #if( ipconfigINCLUDE_TEST_CODE == 1 )
\r
237 unsigned portBASE_TYPE uxGetNumberOfFreeNetworkBuffers( void )
\r
239 return listCURRENT_LIST_LENGTH( &xFreeBuffersList );
\r
242 #endif /* ipconfigINCLUDE_TEST_CODE */
\r