LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 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 
360 err_t sys_mutex_new( sys_mutex_t *pxMutex )
361 {
362 err_t xReturn = ERR_MEM;
363 
364  *pxMutex = xSemaphoreCreateMutex();
365 
366  if( *pxMutex != NULL )
367  {
368  xReturn = ERR_OK;
369  SYS_STATS_INC_USED( mutex );
370  }
371  else
372  {
373  SYS_STATS_INC( mutex.err );
374  }
375 
376  return xReturn;
377 }
378 
381 void sys_mutex_lock( sys_mutex_t *pxMutex )
382 {
383  while( xSemaphoreTake( *pxMutex, portMAX_DELAY ) != pdPASS );
384 }
385 
389 {
390  xSemaphoreGive( *pxMutex );
391 }
392 
393 
396 void sys_mutex_free( sys_mutex_t *pxMutex )
397 {
398  SYS_STATS_DEC( mutex.used );
399  vQueueDelete( *pxMutex );
400 }
401 
402 
403 /*---------------------------------------------------------------------------*
404  * Routine: sys_sem_signal
405  *---------------------------------------------------------------------------*
406  * Description:
407  * Signals (releases) a semaphore
408  * Inputs:
409  * sys_sem_t sem -- Semaphore to signal
410  *---------------------------------------------------------------------------*/
411 void sys_sem_signal( sys_sem_t *pxSemaphore )
412 {
413  xSemaphoreGive( *pxSemaphore );
414 }
415 
416 /*---------------------------------------------------------------------------*
417  * Routine: sys_sem_free
418  *---------------------------------------------------------------------------*
419  * Description:
420  * Deallocates a semaphore
421  * Inputs:
422  * sys_sem_t sem -- Semaphore to free
423  *---------------------------------------------------------------------------*/
424 void sys_sem_free( sys_sem_t *pxSemaphore )
425 {
426  SYS_STATS_DEC(sem.used);
427  vQueueDelete( *pxSemaphore );
428 }
429 
430 /*---------------------------------------------------------------------------*
431  * Routine: sys_init
432  *---------------------------------------------------------------------------*
433  * Description:
434  * Initialize sys arch
435  *---------------------------------------------------------------------------*/
436 void sys_init(void)
437 {
438 }
439 
441 {
442  return xTaskGetTickCount();
443 }
444 
445 /*---------------------------------------------------------------------------*
446  * Routine: sys_thread_new
447  *---------------------------------------------------------------------------*
448  * Description:
449  * Starts a new thread with priority "prio" that will begin its
450  * execution in the function "thread()". The "arg" argument will be
451  * passed as an argument to the thread() function. The id of the new
452  * thread is returned. Both the id and the priority are system
453  * dependent.
454  * Inputs:
455  * char *name -- Name of thread
456  * void (* thread)(void *arg) -- Pointer to function to run.
457  * void *arg -- Argument passed into function
458  * int stacksize -- Required stack amount in bytes
459  * int prio -- Thread priority
460  * Outputs:
461  * sys_thread_t -- Pointer to per-thread timeouts.
462  *---------------------------------------------------------------------------*/
463 sys_thread_t sys_thread_new( const char *pcName, void( *pxThread )( void *pvParameters ), void *pvArg, int iStackSize, int iPriority )
464 {
465 xTaskHandle xCreatedTask;
466 portBASE_TYPE xResult;
467 sys_thread_t xReturn;
468 
469  xResult = xTaskCreate( pxThread, ( signed char * ) pcName, iStackSize, pvArg, iPriority, &xCreatedTask );
470 
471  if( xResult == pdPASS )
472  {
473  xReturn = xCreatedTask;
474  }
475  else
476  {
477  xReturn = NULL;
478  }
479 
480  return xReturn;
481 }
482 
483 /*---------------------------------------------------------------------------*
484  * Routine: sys_arch_protect
485  *---------------------------------------------------------------------------*
486  * Description:
487  * This optional function does a "fast" critical region protection and
488  * returns the previous protection level. This function is only called
489  * during very short critical regions. An embedded system which supports
490  * ISR-based drivers might want to implement this function by disabling
491  * interrupts. Task-based systems might want to implement this by using
492  * a mutex or disabling tasking. This function should support recursive
493  * calls from the same task or interrupt. In other words,
494  * sys_arch_protect() could be called while already protected. In
495  * that case the return value indicates that it is already protected.
496  *
497  * sys_arch_protect() is only required if your port is supporting an
498  * operating system.
499  * Outputs:
500  * sys_prot_t -- Previous protection level (not used here)
501  *---------------------------------------------------------------------------*/
503 {
504  vPortEnterCritical();
505  return ( sys_prot_t ) 1;
506 }
507 
508 /*---------------------------------------------------------------------------*
509  * Routine: sys_arch_unprotect
510  *---------------------------------------------------------------------------*
511  * Description:
512  * This optional function does a "fast" set of critical region
513  * protection to the value specified by pval. See the documentation for
514  * sys_arch_protect() for more information. This function is only
515  * required if your port is supporting an operating system.
516  * Inputs:
517  * sys_prot_t -- Previous protection level (not used here)
518  *---------------------------------------------------------------------------*/
520 {
521  (void) xValue;
522  taskEXIT_CRITICAL();
523 }
524 
525 /*
526  * Prints an assertion messages and aborts execution.
527  */
528 void sys_assert( const char *pcMessage )
529 {
530  (void) pcMessage;
531 
532  for (;;)
533  {
534  }
535 }
536 /*-------------------------------------------------------------------------*
537  * End of File: sys_arch.c
538  *-------------------------------------------------------------------------*/
539 
540 #endif
541 
542 /*-----------------------------------------------------------------------------------*/