]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/ethernet/lwip-1.4.0/ports/win32/sys_arch.c
Update version number to 9.0.0rc2.
[freertos] / FreeRTOS / Demo / Common / ethernet / lwip-1.4.0 / ports / win32 / sys_arch.c
1 /*\r
2  * Copyright (c) 2001-2003 Swedish Institute of Computer Science.\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without modification,\r
6  * are permitted provided that the following conditions are met:\r
7  *\r
8  * 1. Redistributions of source code must retain the above copyright notice,\r
9  *    this list of conditions and the following disclaimer.\r
10  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
11  *    this list of conditions and the following disclaimer in the documentation\r
12  *    and/or other materials provided with the distribution.\r
13  * 3. The name of the author may not be used to endorse or promote products\r
14  *    derived from this software without specific prior written permission.\r
15  *\r
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\r
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\r
19  * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
20  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\r
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING\r
24  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY\r
25  * OF SUCH DAMAGE.\r
26  *\r
27  * This file is part of the lwIP TCP/IP stack.\r
28  *\r
29  * Author: Adam Dunkels <adam@sics.se>\r
30  *\r
31  */\r
32 \r
33 //*****************************************************************************\r
34 //\r
35 // Include OS functionality.\r
36 //\r
37 //*****************************************************************************\r
38 \r
39 /* ------------------------ System architecture includes ----------------------------- */\r
40 #include "arch/sys_arch.h"\r
41 \r
42 /* ------------------------ lwIP includes --------------------------------- */\r
43 #include "lwip/opt.h"\r
44 \r
45 #include "lwip/debug.h"\r
46 #include "lwip/def.h"\r
47 #include "lwip/sys.h"\r
48 #include "lwip/mem.h"\r
49 #include "lwip/stats.h"\r
50 \r
51 /*---------------------------------------------------------------------------*\r
52  * Routine:  sys_mbox_new\r
53  *---------------------------------------------------------------------------*\r
54  * Description:\r
55  *      Creates a new mailbox\r
56  * Inputs:\r
57  *      int size                -- Size of elements in the mailbox\r
58  * Outputs:\r
59  *      sys_mbox_t              -- Handle to new mailbox\r
60  *---------------------------------------------------------------------------*/\r
61 err_t sys_mbox_new( sys_mbox_t *pxMailBox, int iSize )\r
62 {\r
63 err_t xReturn = ERR_MEM;\r
64 \r
65         *pxMailBox = xQueueCreate( iSize, sizeof( void * ) );\r
66 \r
67         if( *pxMailBox != NULL )\r
68         {\r
69                 xReturn = ERR_OK;\r
70                 SYS_STATS_INC_USED( mbox );\r
71         }\r
72 \r
73         return xReturn;\r
74 }\r
75 \r
76 \r
77 /*---------------------------------------------------------------------------*\r
78  * Routine:  sys_mbox_free\r
79  *---------------------------------------------------------------------------*\r
80  * Description:\r
81  *      Deallocates a mailbox. If there are messages still present in the\r
82  *      mailbox when the mailbox is deallocated, it is an indication of a\r
83  *      programming error in lwIP and the developer should be notified.\r
84  * Inputs:\r
85  *      sys_mbox_t mbox         -- Handle of mailbox\r
86  * Outputs:\r
87  *      sys_mbox_t              -- Handle to new mailbox\r
88  *---------------------------------------------------------------------------*/\r
89 void sys_mbox_free( sys_mbox_t *pxMailBox )\r
90 {\r
91 unsigned long ulMessagesWaiting;\r
92 \r
93         ulMessagesWaiting = uxQueueMessagesWaiting( *pxMailBox );\r
94         configASSERT( ( ulMessagesWaiting == 0 ) );\r
95 \r
96         #if SYS_STATS\r
97         {\r
98                 if( ulMessagesWaiting != 0UL )\r
99                 {\r
100                         SYS_STATS_INC( mbox.err );\r
101                 }\r
102 \r
103                 SYS_STATS_DEC( mbox.used );\r
104         }\r
105         #endif /* SYS_STATS */\r
106 \r
107         vQueueDelete( *pxMailBox );\r
108 }\r
109 \r
110 /*---------------------------------------------------------------------------*\r
111  * Routine:  sys_mbox_post\r
112  *---------------------------------------------------------------------------*\r
113  * Description:\r
114  *      Post the "msg" to the mailbox.\r
115  * Inputs:\r
116  *      sys_mbox_t mbox         -- Handle of mailbox\r
117  *      void *data              -- Pointer to data to post\r
118  *---------------------------------------------------------------------------*/\r
119 void sys_mbox_post( sys_mbox_t *pxMailBox, void *pxMessageToPost )\r
120 {\r
121         while( xQueueSendToBack( *pxMailBox, &pxMessageToPost, portMAX_DELAY ) != pdTRUE );\r
122 }\r
123 \r
124 /*---------------------------------------------------------------------------*\r
125  * Routine:  sys_mbox_trypost\r
126  *---------------------------------------------------------------------------*\r
127  * Description:\r
128  *      Try to post the "msg" to the mailbox.  Returns immediately with\r
129  *      error if cannot.\r
130  * Inputs:\r
131  *      sys_mbox_t mbox         -- Handle of mailbox\r
132  *      void *msg               -- Pointer to data to post\r
133  * Outputs:\r
134  *      err_t                   -- ERR_OK if message posted, else ERR_MEM\r
135  *                                  if not.\r
136  *---------------------------------------------------------------------------*/\r
137 err_t sys_mbox_trypost( sys_mbox_t *pxMailBox, void *pxMessageToPost )\r
138 {\r
139 err_t xReturn;\r
140 \r
141         if( xQueueSend( *pxMailBox, &pxMessageToPost, 0UL ) == pdPASS )\r
142         {\r
143                 xReturn = ERR_OK;\r
144         }\r
145         else\r
146         {\r
147                 /* The queue was already full. */\r
148                 xReturn = ERR_MEM;\r
149                 SYS_STATS_INC( mbox.err );\r
150         }\r
151 \r
152         return xReturn;\r
153 }\r
154 \r
155 /*---------------------------------------------------------------------------*\r
156  * Routine:  sys_arch_mbox_fetch\r
157  *---------------------------------------------------------------------------*\r
158  * Description:\r
159  *      Blocks the thread until a message arrives in the mailbox, but does\r
160  *      not block the thread longer than "timeout" milliseconds (similar to\r
161  *      the sys_arch_sem_wait() function). The "msg" argument is a result\r
162  *      parameter that is set by the function (i.e., by doing "*msg =\r
163  *      ptr"). The "msg" parameter maybe NULL to indicate that the message\r
164  *      should be dropped.\r
165  *\r
166  *      The return values are the same as for the sys_arch_sem_wait() function:\r
167  *      Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a\r
168  *      timeout.\r
169  *\r
170  *      Note that a function with a similar name, sys_mbox_fetch(), is\r
171  *      implemented by lwIP.\r
172  * Inputs:\r
173  *      sys_mbox_t mbox         -- Handle of mailbox\r
174  *      void **msg              -- Pointer to pointer to msg received\r
175  *      u32_t timeout           -- Number of milliseconds until timeout\r
176  * Outputs:\r
177  *      u32_t                   -- SYS_ARCH_TIMEOUT if timeout, else number\r
178  *                                  of milliseconds until received.\r
179  *---------------------------------------------------------------------------*/\r
180 u32_t sys_arch_mbox_fetch( sys_mbox_t *pxMailBox, void **ppvBuffer, u32_t ulTimeOut )\r
181 {\r
182 void *pvDummy;\r
183 TickType_t xStartTime, xEndTime, xElapsed;\r
184 unsigned long ulReturn;\r
185 \r
186         xStartTime = xTaskGetTickCount();\r
187 \r
188         if( NULL == ppvBuffer )\r
189         {\r
190                 ppvBuffer = &pvDummy;\r
191         }\r
192 \r
193         if( ulTimeOut != 0UL )\r
194         {\r
195                 if( pdTRUE == xQueueReceive( *pxMailBox, &( *ppvBuffer ), ulTimeOut/ portTICK_PERIOD_MS ) )\r
196                 {\r
197                         xEndTime = xTaskGetTickCount();\r
198                         xElapsed = ( xEndTime - xStartTime ) * portTICK_PERIOD_MS;\r
199 \r
200                         ulReturn = xElapsed;\r
201                 }\r
202                 else\r
203                 {\r
204                         /* Timed out. */\r
205                         *ppvBuffer = NULL;\r
206                         ulReturn = SYS_ARCH_TIMEOUT;\r
207                 }\r
208         }\r
209         else\r
210         {\r
211                 while( pdTRUE != xQueueReceive( *pxMailBox, &( *ppvBuffer ), portMAX_DELAY ) );\r
212                 xEndTime = xTaskGetTickCount();\r
213                 xElapsed = ( xEndTime - xStartTime ) * portTICK_PERIOD_MS;\r
214 \r
215                 if( xElapsed == 0UL )\r
216                 {\r
217                         xElapsed = 1UL;\r
218                 }\r
219 \r
220                 ulReturn = xElapsed;\r
221         }\r
222 \r
223         return ulReturn;\r
224 }\r
225 \r
226 /*---------------------------------------------------------------------------*\r
227  * Routine:  sys_arch_mbox_tryfetch\r
228  *---------------------------------------------------------------------------*\r
229  * Description:\r
230  *      Similar to sys_arch_mbox_fetch, but if message is not ready\r
231  *      immediately, we'll return with SYS_MBOX_EMPTY.  On success, 0 is\r
232  *      returned.\r
233  * Inputs:\r
234  *      sys_mbox_t mbox         -- Handle of mailbox\r
235  *      void **msg              -- Pointer to pointer to msg received\r
236  * Outputs:\r
237  *      u32_t                   -- SYS_MBOX_EMPTY if no messages.  Otherwise,\r
238  *                                  return ERR_OK.\r
239  *---------------------------------------------------------------------------*/\r
240 u32_t sys_arch_mbox_tryfetch( sys_mbox_t *pxMailBox, void **ppvBuffer )\r
241 {\r
242 void *pvDummy;\r
243 unsigned long ulReturn;\r
244 \r
245         if( ppvBuffer== NULL )\r
246         {\r
247                 ppvBuffer = &pvDummy;\r
248         }\r
249 \r
250         if( pdTRUE == xQueueReceive( *pxMailBox, &( *ppvBuffer ), 0UL ) )\r
251         {\r
252                 ulReturn = ERR_OK;\r
253         }\r
254         else\r
255         {\r
256                 ulReturn = SYS_MBOX_EMPTY;\r
257         }\r
258 \r
259         return ulReturn;\r
260 }\r
261 \r
262 /*---------------------------------------------------------------------------*\r
263  * Routine:  sys_sem_new\r
264  *---------------------------------------------------------------------------*\r
265  * Description:\r
266  *      Creates and returns a new semaphore. The "ucCount" argument specifies\r
267  *      the initial state of the semaphore.\r
268  *      NOTE: Currently this routine only creates counts of 1 or 0\r
269  * Inputs:\r
270  *      sys_mbox_t mbox         -- Handle of mailbox\r
271  *      u8_t ucCount              -- Initial ucCount of semaphore (1 or 0)\r
272  * Outputs:\r
273  *      sys_sem_t               -- Created semaphore or 0 if could not create.\r
274  *---------------------------------------------------------------------------*/\r
275 err_t sys_sem_new( sys_sem_t *pxSemaphore, u8_t ucCount )\r
276 {\r
277 err_t xReturn = ERR_MEM;\r
278 \r
279         vSemaphoreCreateBinary( ( *pxSemaphore ) );\r
280 \r
281         if( *pxSemaphore != NULL )\r
282         {\r
283                 if( ucCount == 0U )\r
284                 {\r
285                         xSemaphoreTake( *pxSemaphore, 1UL );\r
286                 }\r
287 \r
288                 xReturn = ERR_OK;\r
289                 SYS_STATS_INC_USED( sem );\r
290         }\r
291         else\r
292         {\r
293                 SYS_STATS_INC( sem.err );\r
294         }\r
295 \r
296         return xReturn;\r
297 }\r
298 \r
299 /*---------------------------------------------------------------------------*\r
300  * Routine:  sys_arch_sem_wait\r
301  *---------------------------------------------------------------------------*\r
302  * Description:\r
303  *      Blocks the thread while waiting for the semaphore to be\r
304  *      signaled. If the "timeout" argument is non-zero, the thread should\r
305  *      only be blocked for the specified time (measured in\r
306  *      milliseconds).\r
307  *\r
308  *      If the timeout argument is non-zero, the return value is the number of\r
309  *      milliseconds spent waiting for the semaphore to be signaled. If the\r
310  *      semaphore wasn't signaled within the specified time, the return value is\r
311  *      SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore\r
312  *      (i.e., it was already signaled), the function may return zero.\r
313  *\r
314  *      Notice that lwIP implements a function with a similar name,\r
315  *      sys_sem_wait(), that uses the sys_arch_sem_wait() function.\r
316  * Inputs:\r
317  *      sys_sem_t sem           -- Semaphore to wait on\r
318  *      u32_t timeout           -- Number of milliseconds until timeout\r
319  * Outputs:\r
320  *      u32_t                   -- Time elapsed or SYS_ARCH_TIMEOUT.\r
321  *---------------------------------------------------------------------------*/\r
322 u32_t sys_arch_sem_wait( sys_sem_t *pxSemaphore, u32_t ulTimeout )\r
323 {\r
324 TickType_t xStartTime, xEndTime, xElapsed;\r
325 unsigned long ulReturn;\r
326 \r
327         xStartTime = xTaskGetTickCount();\r
328 \r
329         if( ulTimeout != 0UL )\r
330         {\r
331                 if( xSemaphoreTake( *pxSemaphore, ulTimeout / portTICK_PERIOD_MS ) == pdTRUE )\r
332                 {\r
333                         xEndTime = xTaskGetTickCount();\r
334                         xElapsed = (xEndTime - xStartTime) * portTICK_PERIOD_MS;\r
335                         ulReturn = xElapsed;\r
336                 }\r
337                 else\r
338                 {\r
339                         ulReturn = SYS_ARCH_TIMEOUT;\r
340                 }\r
341         }\r
342         else\r
343         {\r
344                 while( xSemaphoreTake( *pxSemaphore, portMAX_DELAY ) != pdTRUE );\r
345                 xEndTime = xTaskGetTickCount();\r
346                 xElapsed = ( xEndTime - xStartTime ) * portTICK_PERIOD_MS;\r
347 \r
348                 if( xElapsed == 0UL )\r
349                 {\r
350                         xElapsed = 1UL;\r
351                 }\r
352 \r
353                 ulReturn = xElapsed;\r
354         }\r
355 \r
356         return ulReturn;\r
357 }\r
358 \r
359 /** Create a new mutex\r
360  * @param mutex pointer to the mutex to create\r
361  * @return a new mutex */\r
362 err_t sys_mutex_new( sys_mutex_t *pxMutex )\r
363 {\r
364 err_t xReturn = ERR_MEM;\r
365 \r
366         *pxMutex = xSemaphoreCreateMutex();\r
367 \r
368         if( *pxMutex != NULL )\r
369         {\r
370                 xReturn = ERR_OK;\r
371                 SYS_STATS_INC_USED( mutex );\r
372         }\r
373         else\r
374         {\r
375                 SYS_STATS_INC( mutex.err );\r
376         }\r
377 \r
378         return xReturn;\r
379 }\r
380 \r
381 /** Lock a mutex\r
382  * @param mutex the mutex to lock */\r
383 void sys_mutex_lock( sys_mutex_t *pxMutex )\r
384 {\r
385         while( xSemaphoreTake( *pxMutex, portMAX_DELAY ) != pdPASS );\r
386 }\r
387 \r
388 /** Unlock a mutex\r
389  * @param mutex the mutex to unlock */\r
390 void sys_mutex_unlock(sys_mutex_t *pxMutex )\r
391 {\r
392         xSemaphoreGive( *pxMutex );\r
393 }\r
394 \r
395 \r
396 /** Delete a semaphore\r
397  * @param mutex the mutex to delete */\r
398 void sys_mutex_free( sys_mutex_t *pxMutex )\r
399 {\r
400         SYS_STATS_DEC( mutex.used );\r
401         vQueueDelete( *pxMutex );\r
402 }\r
403 \r
404 \r
405 /*---------------------------------------------------------------------------*\r
406  * Routine:  sys_sem_signal\r
407  *---------------------------------------------------------------------------*\r
408  * Description:\r
409  *      Signals (releases) a semaphore\r
410  * Inputs:\r
411  *      sys_sem_t sem           -- Semaphore to signal\r
412  *---------------------------------------------------------------------------*/\r
413 void sys_sem_signal( sys_sem_t *pxSemaphore )\r
414 {\r
415         xSemaphoreGive( *pxSemaphore );\r
416 }\r
417 \r
418 /*---------------------------------------------------------------------------*\r
419  * Routine:  sys_sem_free\r
420  *---------------------------------------------------------------------------*\r
421  * Description:\r
422  *      Deallocates a semaphore\r
423  * Inputs:\r
424  *      sys_sem_t sem           -- Semaphore to free\r
425  *---------------------------------------------------------------------------*/\r
426 void sys_sem_free( sys_sem_t *pxSemaphore )\r
427 {\r
428         SYS_STATS_DEC(sem.used);\r
429         vQueueDelete( *pxSemaphore );\r
430 }\r
431 \r
432 /*---------------------------------------------------------------------------*\r
433  * Routine:  sys_init\r
434  *---------------------------------------------------------------------------*\r
435  * Description:\r
436  *      Initialize sys arch\r
437  *---------------------------------------------------------------------------*/\r
438 void sys_init(void)\r
439 {\r
440 }\r
441 \r
442 u32_t sys_now(void)\r
443 {\r
444         return xTaskGetTickCount();\r
445 }\r
446 \r
447 /*---------------------------------------------------------------------------*\r
448  * Routine:  sys_thread_new\r
449  *---------------------------------------------------------------------------*\r
450  * Description:\r
451  *      Starts a new thread with priority "prio" that will begin its\r
452  *      execution in the function "thread()". The "arg" argument will be\r
453  *      passed as an argument to the thread() function. The id of the new\r
454  *      thread is returned. Both the id and the priority are system\r
455  *      dependent.\r
456  * Inputs:\r
457  *      char *name              -- Name of thread\r
458  *      void (* thread)(void *arg) -- Pointer to function to run.\r
459  *      void *arg               -- Argument passed into function\r
460  *      int stacksize           -- Required stack amount in bytes\r
461  *      int prio                -- Thread priority\r
462  * Outputs:\r
463  *      sys_thread_t            -- Pointer to per-thread timeouts.\r
464  *---------------------------------------------------------------------------*/\r
465 sys_thread_t sys_thread_new( const char *pcName, void( *pxThread )( void *pvParameters ), void *pvArg, int iStackSize, int iPriority )\r
466 {\r
467 TaskHandle_t xCreatedTask;\r
468 portBASE_TYPE xResult;\r
469 sys_thread_t xReturn;\r
470 \r
471         xResult = xTaskCreate( pxThread, pcName, iStackSize, pvArg, iPriority, &xCreatedTask );\r
472 \r
473         if( xResult == pdPASS )\r
474         {\r
475                 xReturn = xCreatedTask;\r
476         }\r
477         else\r
478         {\r
479                 xReturn = NULL;\r
480         }\r
481 \r
482         return xReturn;\r
483 }\r
484 \r
485 /*---------------------------------------------------------------------------*\r
486  * Routine:  sys_arch_protect\r
487  *---------------------------------------------------------------------------*\r
488  * Description:\r
489  *      This optional function does a "fast" critical region protection and\r
490  *      returns the previous protection level. This function is only called\r
491  *      during very short critical regions. An embedded system which supports\r
492  *      ISR-based drivers might want to implement this function by disabling\r
493  *      interrupts. Task-based systems might want to implement this by using\r
494  *      a mutex or disabling tasking. This function should support recursive\r
495  *      calls from the same task or interrupt. In other words,\r
496  *      sys_arch_protect() could be called while already protected. In\r
497  *      that case the return value indicates that it is already protected.\r
498  *\r
499  *      sys_arch_protect() is only required if your port is supporting an\r
500  *      operating system.\r
501  * Outputs:\r
502  *      sys_prot_t              -- Previous protection level (not used here)\r
503  *---------------------------------------------------------------------------*/\r
504 sys_prot_t sys_arch_protect( void )\r
505 {\r
506         vPortEnterCritical();\r
507         return ( sys_prot_t ) 1;\r
508 }\r
509 \r
510 /*---------------------------------------------------------------------------*\r
511  * Routine:  sys_arch_unprotect\r
512  *---------------------------------------------------------------------------*\r
513  * Description:\r
514  *      This optional function does a "fast" set of critical region\r
515  *      protection to the value specified by pval. See the documentation for\r
516  *      sys_arch_protect() for more information. This function is only\r
517  *      required if your port is supporting an operating system.\r
518  * Inputs:\r
519  *      sys_prot_t              -- Previous protection level (not used here)\r
520  *---------------------------------------------------------------------------*/\r
521 void sys_arch_unprotect( sys_prot_t xValue )\r
522 {\r
523         (void) xValue;\r
524         taskEXIT_CRITICAL();\r
525 }\r
526 \r
527 /*\r
528  * Prints an assertion messages and aborts execution.\r
529  */\r
530 void sys_assert( const char *pcMessage )\r
531 {\r
532         (void) pcMessage;\r
533 \r
534         for (;;)\r
535         {\r
536         }\r
537 }\r
538 /*-------------------------------------------------------------------------*\r
539  * End of File:  sys_arch.c\r
540  *-------------------------------------------------------------------------*/\r
541 \r