2 * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
\r
3 * All rights reserved.
\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
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
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
27 * This file is part of the lwIP TCP/IP stack.
\r
29 * Author: Adam Dunkels <adam@sics.se>
\r
33 //*****************************************************************************
\r
35 // Include OS functionality.
\r
37 //*****************************************************************************
\r
39 /* ------------------------ System architecture includes ----------------------------- */
\r
40 #include "arch/sys_arch.h"
\r
42 /* ------------------------ lwIP includes --------------------------------- */
\r
43 #include "lwip/opt.h"
\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
51 /*---------------------------------------------------------------------------*
\r
52 * Routine: sys_mbox_new
\r
53 *---------------------------------------------------------------------------*
\r
55 * Creates a new mailbox
\r
57 * int size -- Size of elements in the mailbox
\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
63 err_t xReturn = ERR_MEM;
\r
65 *pxMailBox = xQueueCreate( iSize, sizeof( void * ) );
\r
67 if( *pxMailBox != NULL )
\r
70 SYS_STATS_INC_USED( mbox );
\r
77 /*---------------------------------------------------------------------------*
\r
78 * Routine: sys_mbox_free
\r
79 *---------------------------------------------------------------------------*
\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
85 * sys_mbox_t mbox -- Handle of mailbox
\r
87 * sys_mbox_t -- Handle to new mailbox
\r
88 *---------------------------------------------------------------------------*/
\r
89 void sys_mbox_free( sys_mbox_t *pxMailBox )
\r
91 unsigned long ulMessagesWaiting;
\r
93 ulMessagesWaiting = uxQueueMessagesWaiting( *pxMailBox );
\r
94 configASSERT( ( ulMessagesWaiting == 0 ) );
\r
98 if( ulMessagesWaiting != 0UL )
\r
100 SYS_STATS_INC( mbox.err );
\r
103 SYS_STATS_DEC( mbox.used );
\r
105 #endif /* SYS_STATS */
\r
107 vQueueDelete( *pxMailBox );
\r
110 /*---------------------------------------------------------------------------*
\r
111 * Routine: sys_mbox_post
\r
112 *---------------------------------------------------------------------------*
\r
114 * Post the "msg" to the mailbox.
\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
121 while( xQueueSendToBack( *pxMailBox, &pxMessageToPost, portMAX_DELAY ) != pdTRUE );
\r
124 /*---------------------------------------------------------------------------*
\r
125 * Routine: sys_mbox_trypost
\r
126 *---------------------------------------------------------------------------*
\r
128 * Try to post the "msg" to the mailbox. Returns immediately with
\r
131 * sys_mbox_t mbox -- Handle of mailbox
\r
132 * void *msg -- Pointer to data to post
\r
134 * err_t -- ERR_OK if message posted, else ERR_MEM
\r
136 *---------------------------------------------------------------------------*/
\r
137 err_t sys_mbox_trypost( sys_mbox_t *pxMailBox, void *pxMessageToPost )
\r
141 if( xQueueSend( *pxMailBox, &pxMessageToPost, 0UL ) == pdPASS )
\r
147 /* The queue was already full. */
\r
149 SYS_STATS_INC( mbox.err );
\r
155 /*---------------------------------------------------------------------------*
\r
156 * Routine: sys_arch_mbox_fetch
\r
157 *---------------------------------------------------------------------------*
\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
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
170 * Note that a function with a similar name, sys_mbox_fetch(), is
\r
171 * implemented by lwIP.
\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
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
183 portTickType xStartTime, xEndTime, xElapsed;
\r
184 unsigned long ulReturn;
\r
186 xStartTime = xTaskGetTickCount();
\r
188 if( NULL == ppvBuffer )
\r
190 ppvBuffer = &pvDummy;
\r
193 if( ulTimeOut != 0UL )
\r
195 if( pdTRUE == xQueueReceive( *pxMailBox, &( *ppvBuffer ), ulTimeOut/ portTICK_RATE_MS ) )
\r
197 xEndTime = xTaskGetTickCount();
\r
198 xElapsed = ( xEndTime - xStartTime ) * portTICK_RATE_MS;
\r
200 ulReturn = xElapsed;
\r
206 ulReturn = SYS_ARCH_TIMEOUT;
\r
211 while( pdTRUE != xQueueReceive( *pxMailBox, &( *ppvBuffer ), portMAX_DELAY ) );
\r
212 xEndTime = xTaskGetTickCount();
\r
213 xElapsed = ( xEndTime - xStartTime ) * portTICK_RATE_MS;
\r
215 if( xElapsed == 0UL )
\r
220 ulReturn = xElapsed;
\r
226 /*---------------------------------------------------------------------------*
\r
227 * Routine: sys_arch_mbox_tryfetch
\r
228 *---------------------------------------------------------------------------*
\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
234 * sys_mbox_t mbox -- Handle of mailbox
\r
235 * void **msg -- Pointer to pointer to msg received
\r
237 * u32_t -- SYS_MBOX_EMPTY if no messages. Otherwise,
\r
239 *---------------------------------------------------------------------------*/
\r
240 u32_t sys_arch_mbox_tryfetch( sys_mbox_t *pxMailBox, void **ppvBuffer )
\r
243 unsigned long ulReturn;
\r
245 if( ppvBuffer== NULL )
\r
247 ppvBuffer = &pvDummy;
\r
250 if( pdTRUE == xQueueReceive( *pxMailBox, &( *ppvBuffer ), 0UL ) )
\r
256 ulReturn = SYS_MBOX_EMPTY;
\r
262 /*---------------------------------------------------------------------------*
\r
263 * Routine: sys_sem_new
\r
264 *---------------------------------------------------------------------------*
\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
270 * sys_mbox_t mbox -- Handle of mailbox
\r
271 * u8_t ucCount -- Initial ucCount of semaphore (1 or 0)
\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
277 err_t xReturn = ERR_MEM;
\r
279 vSemaphoreCreateBinary( ( *pxSemaphore ) );
\r
281 if( *pxSemaphore != NULL )
\r
283 if( ucCount == 0U )
\r
285 xSemaphoreTake( *pxSemaphore, 1UL );
\r
289 SYS_STATS_INC_USED( sem );
\r
293 SYS_STATS_INC( sem.err );
\r
299 /*---------------------------------------------------------------------------*
\r
300 * Routine: sys_arch_sem_wait
\r
301 *---------------------------------------------------------------------------*
\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
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
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
317 * sys_sem_t sem -- Semaphore to wait on
\r
318 * u32_t timeout -- Number of milliseconds until timeout
\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
324 portTickType xStartTime, xEndTime, xElapsed;
\r
325 unsigned long ulReturn;
\r
327 xStartTime = xTaskGetTickCount();
\r
329 if( ulTimeout != 0UL )
\r
331 if( xSemaphoreTake( *pxSemaphore, ulTimeout / portTICK_RATE_MS ) == pdTRUE )
\r
333 xEndTime = xTaskGetTickCount();
\r
334 xElapsed = (xEndTime - xStartTime) * portTICK_RATE_MS;
\r
335 ulReturn = xElapsed;
\r
339 ulReturn = SYS_ARCH_TIMEOUT;
\r
344 while( xSemaphoreTake( *pxSemaphore, portMAX_DELAY ) != pdTRUE );
\r
345 xEndTime = xTaskGetTickCount();
\r
346 xElapsed = ( xEndTime - xStartTime ) * portTICK_RATE_MS;
\r
348 if( xElapsed == 0UL )
\r
353 ulReturn = xElapsed;
\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
364 err_t xReturn = ERR_MEM;
\r
366 *pxMutex = xQueueCreateMutex();
\r
368 if( *pxMutex != NULL )
\r
371 SYS_STATS_INC_USED( mutex );
\r
375 SYS_STATS_INC( mutex.err );
\r
382 * @param mutex the mutex to lock */
\r
383 void sys_mutex_lock( sys_mutex_t *pxMutex )
\r
385 while( xSemaphoreTake( *pxMutex, portMAX_DELAY ) != pdPASS );
\r
389 * @param mutex the mutex to unlock */
\r
390 void sys_mutex_unlock(sys_mutex_t *pxMutex )
\r
392 xSemaphoreGive( *pxMutex );
\r
396 /** Delete a semaphore
\r
397 * @param mutex the mutex to delete */
\r
398 void sys_mutex_free( sys_mutex_t *pxMutex )
\r
400 SYS_STATS_DEC( mutex.used );
\r
401 vQueueDelete( *pxMutex );
\r
405 /*---------------------------------------------------------------------------*
\r
406 * Routine: sys_sem_signal
\r
407 *---------------------------------------------------------------------------*
\r
409 * Signals (releases) a semaphore
\r
411 * sys_sem_t sem -- Semaphore to signal
\r
412 *---------------------------------------------------------------------------*/
\r
413 void sys_sem_signal( sys_sem_t *pxSemaphore )
\r
415 xSemaphoreGive( *pxSemaphore );
\r
418 /*---------------------------------------------------------------------------*
\r
419 * Routine: sys_sem_free
\r
420 *---------------------------------------------------------------------------*
\r
422 * Deallocates a semaphore
\r
424 * sys_sem_t sem -- Semaphore to free
\r
425 *---------------------------------------------------------------------------*/
\r
426 void sys_sem_free( sys_sem_t *pxSemaphore )
\r
428 SYS_STATS_DEC(sem.used);
\r
429 vQueueDelete( *pxSemaphore );
\r
432 /*---------------------------------------------------------------------------*
\r
433 * Routine: sys_init
\r
434 *---------------------------------------------------------------------------*
\r
436 * Initialize sys arch
\r
437 *---------------------------------------------------------------------------*/
\r
438 void sys_init(void)
\r
442 u32_t sys_now(void)
\r
444 return xTaskGetTickCount();
\r
447 /*---------------------------------------------------------------------------*
\r
448 * Routine: sys_thread_new
\r
449 *---------------------------------------------------------------------------*
\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
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
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
467 xTaskHandle xCreatedTask;
\r
468 portBASE_TYPE xResult;
\r
469 sys_thread_t xReturn;
\r
471 xResult = xTaskCreate( pxThread, ( signed char * ) pcName, iStackSize, pvArg, iPriority, &xCreatedTask );
\r
473 if( xResult == pdPASS )
\r
475 xReturn = xCreatedTask;
\r
485 /*---------------------------------------------------------------------------*
\r
486 * Routine: sys_arch_protect
\r
487 *---------------------------------------------------------------------------*
\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
499 * sys_arch_protect() is only required if your port is supporting an
\r
500 * operating system.
\r
502 * sys_prot_t -- Previous protection level (not used here)
\r
503 *---------------------------------------------------------------------------*/
\r
504 sys_prot_t sys_arch_protect( void )
\r
506 vPortEnterCritical();
\r
507 return ( sys_prot_t ) 1;
\r
510 /*---------------------------------------------------------------------------*
\r
511 * Routine: sys_arch_unprotect
\r
512 *---------------------------------------------------------------------------*
\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
519 * sys_prot_t -- Previous protection level (not used here)
\r
520 *---------------------------------------------------------------------------*/
\r
521 void sys_arch_unprotect( sys_prot_t xValue )
\r
524 taskEXIT_CRITICAL();
\r
528 * Prints an assertion messages and aborts execution.
\r
530 void sys_assert( const char *pcMessage )
\r
538 /*-------------------------------------------------------------------------*
\r
539 * End of File: sys_arch.c
\r
540 *-------------------------------------------------------------------------*/
\r