]> begriffs open source - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/portable/BufferManagement/BufferAllocation_1.c
Clarify license blurb at the top of the FreeRTOS+UDP and FreeRTOS+CLI source files.
[freertos] / FreeRTOS-Plus / Source / FreeRTOS-Plus-UDP / portable / BufferManagement / BufferAllocation_1.c
1 /*\r
2  * FreeRTOS+UDP V1.0.0 (C) 2013 Real Time Engineers ltd.\r
3  *\r
4  * This file is part of the FreeRTOS+UDP distribution.  The FreeRTOS+UDP license\r
5  * terms are different to the FreeRTOS license terms.\r
6  *\r
7  * FreeRTOS+UDP uses a dual license model that allows the software to be used\r
8  * under a pure GPL open source license (as opposed to the modified GPL license\r
9  * under which FreeRTOS is distributed) or a commercial license.  Details of\r
10  * both license options follow:\r
11  *\r
12  * - Open source licensing -\r
13  * FreeRTOS+UDP is a free download and may be used, modified, evaluated and\r
14  * distributed without charge provided the user adheres to version two of the\r
15  * GNU General Public License (GPL) and does not remove the copyright notice or\r
16  * this text.  The GPL V2 text is available on the gnu.org web site, and on the\r
17  * following URL: http://www.FreeRTOS.org/gpl-2.0.txt.\r
18  *\r
19  * - Commercial licensing -\r
20  * Businesses and individuals that for commercial or other reasons cannot comply\r
21  * with the terms of the GPL V2 license must obtain a commercial license before \r
22  * incorporating FreeRTOS+UDP into proprietary software for distribution in any \r
23  * form.  Commercial licenses can be purchased from http://shop.freertos.org/udp \r
24  * and do not require any source files to be changed.\r
25  *\r
26  * FreeRTOS+UDP is distributed in the hope that it will be useful.  You cannot\r
27  * use FreeRTOS+UDP unless you agree that you use the software 'as is'.\r
28  * FreeRTOS+UDP is provided WITHOUT ANY WARRANTY; without even the implied\r
29  * warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
30  * PURPOSE. Real Time Engineers Ltd. disclaims all conditions and terms, be they\r
31  * implied, expressed, or statutory.\r
32  *\r
33  * 1 tab == 4 spaces!\r
34  *\r
35  * http://www.FreeRTOS.org\r
36  * http://www.FreeRTOS.org/udp\r
37  *\r
38  */\r
39 \r
40 \r
41 /******************************************************************************\r
42  *\r
43  * See the following web page for essential buffer allocation scheme usage and\r
44  * configuration details:\r
45  * http://www.FreeRTOS.org/FreeRTOS-Plus/FreeRTOS_Plus_UDP/Embedded_Ethernet_Buffer_Management.shtml\r
46  *\r
47  ******************************************************************************/\r
48 \r
49 \r
50 /* Standard includes. */\r
51 #include <stdint.h>\r
52 \r
53 /* FreeRTOS includes. */\r
54 #include "FreeRTOS.h"\r
55 #include "task.h"\r
56 #include "semphr.h"\r
57 \r
58 /* FreeRTOS+UDP includes. */\r
59 #include "FreeRTOS_UDP_IP.h"\r
60 #include "NetworkInterface.h"\r
61 \r
62 /* For an Ethernet interrupt to be able to obtain a network buffer there must\r
63 be at least this number of buffers available. */\r
64 #define ipINTERRUPT_BUFFER_GET_THRESHOLD        ( 3 )\r
65 \r
66 /* A list of free (available) xNetworkBufferDescriptor_t structures. */\r
67 static xList xFreeBuffersList;\r
68 \r
69 /* Declares the pool of xNetworkBufferDescriptor_t structures that are available to the\r
70 system.  All the network buffers referenced from xFreeBuffersList exist in this\r
71 array.  The array is not accessed directly except during initialisation, when\r
72 the xFreeBuffersList is filled (as all the buffers are free when the system is\r
73 booted). */\r
74 static xNetworkBufferDescriptor_t xNetworkBuffers[ ipconfigNUM_NETWORK_BUFFERS ];\r
75 \r
76 /* The semaphore used to obtain network buffers. */\r
77 static xSemaphoreHandle xNetworkBufferSemaphore = NULL;\r
78 \r
79 /*-----------------------------------------------------------*/\r
80 \r
81 portBASE_TYPE xNetworkBuffersInitialise( void )\r
82 {\r
83 portBASE_TYPE xReturn, x;\r
84 \r
85         /* Only initialise the buffers and their associated kernel objects if they\r
86         have not been initialised before. */\r
87         if( xNetworkBufferSemaphore == NULL )\r
88         {\r
89                 xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFERS, ipconfigNUM_NETWORK_BUFFERS );\r
90                 configASSERT( xNetworkBufferSemaphore );\r
91 \r
92                 if( xNetworkBufferSemaphore != NULL )\r
93                 {\r
94                         vListInitialise( &xFreeBuffersList );\r
95 \r
96                         /* Initialise all the network buffers.  The buffer storage comes\r
97                         from the network interface, and different hardware has different\r
98                         requirements. */\r
99                         vNetworkInterfaceAllocateRAMToBuffers( xNetworkBuffers );\r
100                         for( x = 0; x < ipconfigNUM_NETWORK_BUFFERS; x++ )\r
101                         {\r
102                                 /* Initialise and set the owner of the buffer list items. */\r
103                                 vListInitialiseItem( &( xNetworkBuffers[ x ].xBufferListItem ) );\r
104                                 listSET_LIST_ITEM_OWNER( &( xNetworkBuffers[ x ].xBufferListItem ), &xNetworkBuffers[ x ] );\r
105 \r
106                                 /* Currently, all buffers are available for use. */\r
107                                 vListInsert( &xFreeBuffersList, &( xNetworkBuffers[ x ].xBufferListItem ) );\r
108                         }\r
109                 }\r
110         }\r
111 \r
112         if( xNetworkBufferSemaphore == NULL )\r
113         {\r
114                 xReturn = pdFAIL;\r
115         }\r
116         else\r
117         {\r
118                 xReturn = pdPASS;\r
119         }\r
120 \r
121         return xReturn;\r
122 }\r
123 /*-----------------------------------------------------------*/\r
124 \r
125 xNetworkBufferDescriptor_t *pxNetworkBufferGet( size_t xRequestedSizeBytes, portTickType xBlockTimeTicks )\r
126 {\r
127 xNetworkBufferDescriptor_t *pxReturn = NULL;\r
128 \r
129         /*_RB_ The current implementation only has a single size memory block, so\r
130         the requested size parameter is not used (yet). */\r
131         ( void ) xRequestedSizeBytes;\r
132 \r
133         /* If there is a semaphore available, there is a network buffer available. */\r
134         if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )\r
135         {\r
136                 /* Protect the structure as it is accessed from tasks and interrupts. */\r
137                 taskENTER_CRITICAL();\r
138                 {\r
139                         pxReturn = ( xNetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );\r
140                         uxListRemove( &( pxReturn->xBufferListItem ) );\r
141                 }\r
142                 taskEXIT_CRITICAL();\r
143                 iptraceNETWORK_BUFFER_OBTAINED( pxReturn );\r
144         }\r
145         else\r
146         {\r
147                 iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();\r
148         }\r
149 \r
150         return pxReturn;\r
151 }\r
152 /*-----------------------------------------------------------*/\r
153 \r
154 xNetworkBufferDescriptor_t *pxNetworkBufferGetFromISR( size_t xRequestedSizeBytes )\r
155 {\r
156 xNetworkBufferDescriptor_t *pxReturn = NULL;\r
157 unsigned portBASE_TYPE uxSavedInterruptStatus;\r
158 \r
159         /*_RB_ The current implementation only has a single size memory block, so\r
160         the requested size parameter is not used (yet). */\r
161         ( void ) xRequestedSizeBytes;\r
162 \r
163         /* If there is a semaphore available then there is a buffer available, but,\r
164         as this is called from an interrupt, only take a buffer if there are at\r
165         least ipINTERRUPT_BUFFER_GET_THRESHOLD buffers remaining.  This prevents,\r
166         to a certain degree at least, a rapidly executing interrupt exhausting\r
167         buffer and in so doing preventing tasks from continuing. */\r
168         if( uxQueueMessagesWaitingFromISR( ( xQueueHandle ) xNetworkBufferSemaphore ) > ipINTERRUPT_BUFFER_GET_THRESHOLD )\r
169         {\r
170                 if( xSemaphoreTakeFromISR( xNetworkBufferSemaphore, NULL ) == pdPASS )\r
171                 {\r
172                         /* Protect the structure as it is accessed from tasks and interrupts. */\r
173                         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
174                         {\r
175                                 pxReturn = ( xNetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );\r
176                                 uxListRemove( &( pxReturn->xBufferListItem ) );\r
177                         }\r
178                         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
179 \r
180                         iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR( pxReturn );\r
181                 }\r
182         }\r
183 \r
184         if( pxReturn == NULL )\r
185         {\r
186                 iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR();\r
187         }\r
188 \r
189         return pxReturn;\r
190 }\r
191 /*-----------------------------------------------------------*/\r
192 \r
193 portBASE_TYPE vNetworkBufferReleaseFromISR( xNetworkBufferDescriptor_t * const pxNetworkBuffer )\r
194 {\r
195 unsigned portBASE_TYPE uxSavedInterruptStatus;\r
196 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
197 \r
198         /* Ensure the buffer is returned to the list of free buffers before the\r
199         counting semaphore is 'given' to say a buffer is available. */\r
200         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
201         {\r
202                 vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
203         }\r
204         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
205 \r
206         xSemaphoreGiveFromISR( xNetworkBufferSemaphore, &xHigherPriorityTaskWoken );\r
207         iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );\r
208 \r
209         return xHigherPriorityTaskWoken;\r
210 }\r
211 /*-----------------------------------------------------------*/\r
212 \r
213 void vNetworkBufferRelease( xNetworkBufferDescriptor_t * const pxNetworkBuffer )\r
214 {\r
215 portBASE_TYPE xListItemAlreadyInFreeList;\r
216 \r
217         /* Ensure the buffer is returned to the list of free buffers before the\r
218         counting semaphore is 'given' to say a buffer is available. */\r
219         taskENTER_CRITICAL();\r
220         {\r
221                 xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
222 \r
223                 if( xListItemAlreadyInFreeList == pdFALSE )\r
224                 {\r
225                         vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
226                 }\r
227 \r
228                 configASSERT( xListItemAlreadyInFreeList == pdFALSE );\r
229         }\r
230         taskEXIT_CRITICAL();\r
231 \r
232         xSemaphoreGive( xNetworkBufferSemaphore );\r
233         iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );\r
234 }\r
235 /*-----------------------------------------------------------*/\r
236 \r
237 #if( ipconfigINCLUDE_TEST_CODE == 1 )\r
238 \r
239 unsigned portBASE_TYPE uxGetNumberOfFreeNetworkBuffers( void )\r
240 {\r
241         return listCURRENT_LIST_LENGTH( &xFreeBuffersList );\r
242 }\r
243 \r
244 #endif /* ipconfigINCLUDE_TEST_CODE */\r