| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

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