]> begriffs open source - freertos/blob - FreeRTOS-Plus/Source/FreeRTOS-Plus-UDP/portable/BufferManagement/BufferAllocation_1.c
Add FreeRTOS-Plus directory with new directory structure so it matches the FreeRTOS...
[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  * 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
8  *\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
15  *\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
23  *\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
30  *\r
31  * 1 tab == 4 spaces!\r
32  *\r
33  * http://www.FreeRTOS.org\r
34  * http://www.FreeRTOS.org/udp\r
35  *\r
36  */\r
37 \r
38 \r
39 /******************************************************************************\r
40  *\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
44  *\r
45  ******************************************************************************/\r
46 \r
47 \r
48 /* Standard includes. */\r
49 #include <stdint.h>\r
50 \r
51 /* FreeRTOS includes. */\r
52 #include "FreeRTOS.h"\r
53 #include "task.h"\r
54 #include "semphr.h"\r
55 \r
56 /* FreeRTOS+UDP includes. */\r
57 #include "FreeRTOS_UDP_IP.h"\r
58 #include "NetworkInterface.h"\r
59 \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
63 \r
64 /* A list of free (available) xNetworkBufferDescriptor_t structures. */\r
65 static xList xFreeBuffersList;\r
66 \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
71 booted). */\r
72 static xNetworkBufferDescriptor_t xNetworkBuffers[ ipconfigNUM_NETWORK_BUFFERS ];\r
73 \r
74 /* The semaphore used to obtain network buffers. */\r
75 static xSemaphoreHandle xNetworkBufferSemaphore = NULL;\r
76 \r
77 /*-----------------------------------------------------------*/\r
78 \r
79 portBASE_TYPE xNetworkBuffersInitialise( void )\r
80 {\r
81 portBASE_TYPE xReturn, x;\r
82 \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
86         {\r
87                 xNetworkBufferSemaphore = xSemaphoreCreateCounting( ipconfigNUM_NETWORK_BUFFERS, ipconfigNUM_NETWORK_BUFFERS );\r
88                 configASSERT( xNetworkBufferSemaphore );\r
89 \r
90                 if( xNetworkBufferSemaphore != NULL )\r
91                 {\r
92                         vListInitialise( &xFreeBuffersList );\r
93 \r
94                         /* Initialise all the network buffers.  The buffer storage comes\r
95                         from the network interface, and different hardware has different\r
96                         requirements. */\r
97                         vNetworkInterfaceAllocateRAMToBuffers( xNetworkBuffers );\r
98                         for( x = 0; x < ipconfigNUM_NETWORK_BUFFERS; x++ )\r
99                         {\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
103 \r
104                                 /* Currently, all buffers are available for use. */\r
105                                 vListInsert( &xFreeBuffersList, &( xNetworkBuffers[ x ].xBufferListItem ) );\r
106                         }\r
107                 }\r
108         }\r
109 \r
110         if( xNetworkBufferSemaphore == NULL )\r
111         {\r
112                 xReturn = pdFAIL;\r
113         }\r
114         else\r
115         {\r
116                 xReturn = pdPASS;\r
117         }\r
118 \r
119         return xReturn;\r
120 }\r
121 /*-----------------------------------------------------------*/\r
122 \r
123 xNetworkBufferDescriptor_t *pxNetworkBufferGet( size_t xRequestedSizeBytes, portTickType xBlockTimeTicks )\r
124 {\r
125 xNetworkBufferDescriptor_t *pxReturn = NULL;\r
126 \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
130 \r
131         /* If there is a semaphore available, there is a network buffer available. */\r
132         if( xSemaphoreTake( xNetworkBufferSemaphore, xBlockTimeTicks ) == pdPASS )\r
133         {\r
134                 /* Protect the structure as it is accessed from tasks and interrupts. */\r
135                 taskENTER_CRITICAL();\r
136                 {\r
137                         pxReturn = ( xNetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );\r
138                         uxListRemove( &( pxReturn->xBufferListItem ) );\r
139                 }\r
140                 taskEXIT_CRITICAL();\r
141                 iptraceNETWORK_BUFFER_OBTAINED( pxReturn );\r
142         }\r
143         else\r
144         {\r
145                 iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER();\r
146         }\r
147 \r
148         return pxReturn;\r
149 }\r
150 /*-----------------------------------------------------------*/\r
151 \r
152 xNetworkBufferDescriptor_t *pxNetworkBufferGetFromISR( size_t xRequestedSizeBytes )\r
153 {\r
154 xNetworkBufferDescriptor_t *pxReturn = NULL;\r
155 unsigned portBASE_TYPE uxSavedInterruptStatus;\r
156 \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
160 \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
167         {\r
168                 if( xSemaphoreTakeFromISR( xNetworkBufferSemaphore, NULL ) == pdPASS )\r
169                 {\r
170                         /* Protect the structure as it is accessed from tasks and interrupts. */\r
171                         uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();\r
172                         {\r
173                                 pxReturn = ( xNetworkBufferDescriptor_t * ) listGET_OWNER_OF_HEAD_ENTRY( &xFreeBuffersList );\r
174                                 uxListRemove( &( pxReturn->xBufferListItem ) );\r
175                         }\r
176                         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
177 \r
178                         iptraceNETWORK_BUFFER_OBTAINED_FROM_ISR( pxReturn );\r
179                 }\r
180         }\r
181 \r
182         if( pxReturn == NULL )\r
183         {\r
184                 iptraceFAILED_TO_OBTAIN_NETWORK_BUFFER_FROM_ISR();\r
185         }\r
186 \r
187         return pxReturn;\r
188 }\r
189 /*-----------------------------------------------------------*/\r
190 \r
191 portBASE_TYPE vNetworkBufferReleaseFromISR( xNetworkBufferDescriptor_t * const pxNetworkBuffer )\r
192 {\r
193 unsigned portBASE_TYPE uxSavedInterruptStatus;\r
194 portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;\r
195 \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
199         {\r
200                 vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
201         }\r
202         portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );\r
203 \r
204         xSemaphoreGiveFromISR( xNetworkBufferSemaphore, &xHigherPriorityTaskWoken );\r
205         iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );\r
206 \r
207         return xHigherPriorityTaskWoken;\r
208 }\r
209 /*-----------------------------------------------------------*/\r
210 \r
211 void vNetworkBufferRelease( xNetworkBufferDescriptor_t * const pxNetworkBuffer )\r
212 {\r
213 portBASE_TYPE xListItemAlreadyInFreeList;\r
214 \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
218         {\r
219                 xListItemAlreadyInFreeList = listIS_CONTAINED_WITHIN( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
220 \r
221                 if( xListItemAlreadyInFreeList == pdFALSE )\r
222                 {\r
223                         vListInsertEnd( &xFreeBuffersList, &( pxNetworkBuffer->xBufferListItem ) );\r
224                 }\r
225 \r
226                 configASSERT( xListItemAlreadyInFreeList == pdFALSE );\r
227         }\r
228         taskEXIT_CRITICAL();\r
229 \r
230         xSemaphoreGive( xNetworkBufferSemaphore );\r
231         iptraceNETWORK_BUFFER_RELEASED( pxNetworkBuffer );\r
232 }\r
233 /*-----------------------------------------------------------*/\r
234 \r
235 #if( ipconfigINCLUDE_TEST_CODE == 1 )\r
236 \r
237 unsigned portBASE_TYPE uxGetNumberOfFreeNetworkBuffers( void )\r
238 {\r
239         return listCURRENT_LIST_LENGTH( &xFreeBuffersList );\r
240 }\r
241 \r
242 #endif /* ipconfigINCLUDE_TEST_CODE */\r