STM32F769IDiscovery  1.00
uDANTE Audio Networking with STM32F7 DISCO board
sys_arch.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 
33 /* lwIP includes. */
34 #include "lwip/debug.h"
35 #include "lwip/def.h"
36 #include "lwip/sys.h"
37 #include "lwip/mem.h"
38 #include "lwip/stats.h"
39 #include "FreeRTOS.h"
40 #include "task.h"
41 
42 //xTaskHandle xTaskGetCurrentTaskHandle( void ) PRIVILEGED_FUNCTION;
43 
44 /* This is the number of threads that can be started with sys_thread_new() */
45 #define SYS_THREAD_MAX 10 //6
46 
47 static u16_t s_nextthread = 0;
48 
49 
50 /*-----------------------------------------------------------------------------------*/
51 // Creates an empty mailbox.
52 err_t sys_mbox_new(sys_mbox_t *mbox, int size)
53 {
54  (void ) size;
55 
56  *mbox = xQueueCreate( archMESG_QUEUE_LENGTH, sizeof( void * ) );
57 
58 #if SYS_STATS
59  ++lwip_stats.sys.mbox.used;
60  if (lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used) {
61  lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
62  }
63 #endif /* SYS_STATS */
64  if (*mbox == NULL)
65  return ERR_MEM;
66 
67  return ERR_OK;
68 }
69 
70 /*-----------------------------------------------------------------------------------*/
71 /*
72  Deallocates a mailbox. If there are messages still present in the
73  mailbox when the mailbox is deallocated, it is an indication of a
74  programming error in lwIP and the developer should be notified.
75 */
77 {
78  if( uxQueueMessagesWaiting( *mbox ) )
79  {
80  /* Line for breakpoint. Should never break here! */
81  portNOP();
82 #if SYS_STATS
83  lwip_stats.sys.mbox.err++;
84 #endif /* SYS_STATS */
85 
86  // TODO notify the user of failure.
87  }
88 
89  vQueueDelete( *mbox );
90 
91 #if SYS_STATS
92  --lwip_stats.sys.mbox.used;
93 #endif /* SYS_STATS */
94 }
95 
96 /*-----------------------------------------------------------------------------------*/
97 // Posts the "msg" to the mailbox.
98 void sys_mbox_post(sys_mbox_t *mbox, void *data)
99 {
100  while ( xQueueSendToBack(*mbox, &data, portMAX_DELAY ) != pdTRUE ){}
101 }
102 
103 
104 /*-----------------------------------------------------------------------------------*/
105 // Try to post the "msg" to the mailbox.
107 {
108 err_t result;
109 
110  if ( xQueueSend( *mbox, &msg, 0 ) == pdPASS )
111  {
112  result = ERR_OK;
113  }
114  else {
115  // could not post, queue must be full
116  result = ERR_MEM;
117 
118 #if SYS_STATS
119  lwip_stats.sys.mbox.err++;
120 #endif /* SYS_STATS */
121 
122  }
123 
124  return result;
125 }
126 
127 /*-----------------------------------------------------------------------------------*/
128 /*
129  Blocks the thread until a message arrives in the mailbox, but does
130  not block the thread longer than "timeout" milliseconds (similar to
131  the sys_arch_sem_wait() function). The "msg" argument is a result
132  parameter that is set by the function (i.e., by doing "*msg =
133  ptr"). The "msg" parameter maybe NULL to indicate that the message
134  should be dropped.
135 
136  The return values are the same as for the sys_arch_sem_wait() function:
137  Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
138  timeout.
139 
140  Note that a function with a similar name, sys_mbox_fetch(), is
141  implemented by lwIP.
142 */
143 u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
144 {
145 void *dummyptr;
146 portTickType StartTime, EndTime, Elapsed;
147 
148  StartTime = xTaskGetTickCount();
149 
150  if ( msg == NULL )
151  {
152  msg = &dummyptr;
153  }
154 
155  if ( timeout != 0 )
156  {
157  if ( pdTRUE == xQueueReceive( *mbox, &(*msg), timeout / portTICK_RATE_MS ) )
158  {
159  EndTime = xTaskGetTickCount();
160  Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
161 
162  return ( Elapsed );
163  }
164  else // timed out blocking for message
165  {
166  *msg = NULL;
167 
168  return SYS_ARCH_TIMEOUT;
169  }
170  }
171  else // block forever for a message.
172  {
173  while( pdTRUE != xQueueReceive( *mbox, &(*msg), portMAX_DELAY ) ){} // time is arbitrary
174  EndTime = xTaskGetTickCount();
175  Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
176 
177  return ( Elapsed ); // return time blocked TODO test
178  }
179 }
180 
181 /*-----------------------------------------------------------------------------------*/
182 /*
183  Similar to sys_arch_mbox_fetch, but if message is not ready immediately, we'll
184  return with SYS_MBOX_EMPTY. On success, 0 is returned.
185 */
187 {
188 void *dummyptr;
189 
190  if ( msg == NULL )
191  {
192  msg = &dummyptr;
193  }
194 
195  if ( pdTRUE == xQueueReceive( *mbox, &(*msg), 0 ) )
196  {
197  return ERR_OK;
198  }
199  else
200  {
201  return SYS_MBOX_EMPTY;
202  }
203 }
204 /*----------------------------------------------------------------------------------*/
206 {
207  if (*mbox == SYS_MBOX_NULL)
208  return 0;
209  else
210  return 1;
211 }
212 /*-----------------------------------------------------------------------------------*/
214 {
215  *mbox = SYS_MBOX_NULL;
216 }
217 
218 /*-----------------------------------------------------------------------------------*/
219 // Creates a new semaphore. The "count" argument specifies
220 // the initial state of the semaphore.
222 {
223  vSemaphoreCreateBinary(*sem );
224  if(*sem == NULL)
225  {
226 #if SYS_STATS
227  ++lwip_stats.sys.sem.err;
228 #endif /* SYS_STATS */
229  return ERR_MEM;
230  }
231 
232  if(count == 0) // Means it can't be taken
233  {
234  xSemaphoreTake(*sem,1);
235  }
236 
237 #if SYS_STATS
238  ++lwip_stats.sys.sem.used;
239  if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) {
240  lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
241  }
242 #endif /* SYS_STATS */
243 
244  return ERR_OK;
245 }
246 
247 /*-----------------------------------------------------------------------------------*/
248 /*
249  Blocks the thread while waiting for the semaphore to be
250  signaled. If the "timeout" argument is non-zero, the thread should
251  only be blocked for the specified time (measured in
252  milliseconds).
253 
254  If the timeout argument is non-zero, the return value is the number of
255  milliseconds spent waiting for the semaphore to be signaled. If the
256  semaphore wasn't signaled within the specified time, the return value is
257  SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
258  (i.e., it was already signaled), the function may return zero.
259 
260  Notice that lwIP implements a function with a similar name,
261  sys_sem_wait(), that uses the sys_arch_sem_wait() function.
262 */
264 {
265 portTickType StartTime, EndTime, Elapsed;
266 
267  StartTime = xTaskGetTickCount();
268 
269  if( timeout != 0)
270  {
271  if( xSemaphoreTake( *sem, timeout / portTICK_RATE_MS ) == pdTRUE )
272  {
273  EndTime = xTaskGetTickCount();
274  Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
275 
276  return (Elapsed); // return time blocked TODO test
277  }
278  else
279  {
280  return SYS_ARCH_TIMEOUT;
281  }
282  }
283  else // must block without a timeout
284  {
285  while( xSemaphoreTake(*sem, portMAX_DELAY) != pdTRUE){}
286  EndTime = xTaskGetTickCount();
287  Elapsed = (EndTime - StartTime) * portTICK_RATE_MS;
288 
289  return ( Elapsed ); // return time blocked
290 
291  }
292 }
293 
294 /*-----------------------------------------------------------------------------------*/
295 // Signals a semaphore
297 {
298  xSemaphoreGive(*sem);
299 }
300 
301 /*-----------------------------------------------------------------------------------*/
302 // Deallocates a semaphore
304 {
305 #if SYS_STATS
306  --lwip_stats.sys.sem.used;
307 #endif /* SYS_STATS */
308 
309  vQueueDelete(*sem);
310 }
311 /*-----------------------------------------------------------------------------------*/
313 {
314  if (*sem == SYS_SEM_NULL)
315  return 0;
316  else
317  return 1;
318 }
319 
320 /*-----------------------------------------------------------------------------------*/
322 {
323  *sem = SYS_SEM_NULL;
324 }
325 
326 /*-----------------------------------------------------------------------------------*/
327 // Initialize sys arch
328 void sys_init(void)
329 {
330  // keep track of how many threads have been created
331  s_nextthread = 0;
332 }
333 /*-----------------------------------------------------------------------------------*/
334  /* Mutexes*/
335 /*-----------------------------------------------------------------------------------*/
336 /*-----------------------------------------------------------------------------------*/
337 #if LWIP_COMPAT_MUTEX == 0
338 /* Create a new mutex*/
340 
341  *mutex = xSemaphoreCreateMutex();
342  if(*mutex == NULL)
343  {
344 #if SYS_STATS
345  ++lwip_stats.sys.mutex.err;
346 #endif /* SYS_STATS */
347  return ERR_MEM;
348  }
349 
350 #if SYS_STATS
351  ++lwip_stats.sys.mutex.used;
352  if (lwip_stats.sys.mutex.max < lwip_stats.sys.mutex.used) {
353  lwip_stats.sys.mutex.max = lwip_stats.sys.mutex.used;
354  }
355 #endif /* SYS_STATS */
356  return ERR_OK;
357 }
358 /*-----------------------------------------------------------------------------------*/
359 /* Deallocate a mutex*/
361 {
362 #if SYS_STATS
363  --lwip_stats.sys.mutex.used;
364 #endif /* SYS_STATS */
365 
366  vQueueDelete(*mutex);
367 }
368 /*-----------------------------------------------------------------------------------*/
369 /* Lock a mutex*/
371 {
372  sys_arch_sem_wait(mutex, 0);
373 }
374 
375 /*-----------------------------------------------------------------------------------*/
376 /* Unlock a mutex*/
378 {
379  xSemaphoreGive(*mutex);
380 }
381 #endif /*LWIP_COMPAT_MUTEX*/
382 /*-----------------------------------------------------------------------------------*/
383 // TODO
384 /*-----------------------------------------------------------------------------------*/
385 /*
386  Starts a new thread with priority "prio" that will begin its execution in the
387  function "thread()". The "arg" argument will be passed as an argument to the
388  thread() function. The id of the new thread is returned. Both the id and
389  the priority are system dependent.
390 */
391 sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread , void *arg, int stacksize, int prio)
392 {
393 xTaskHandle CreatedTask;
394 int result;
395 
396  if ( s_nextthread < SYS_THREAD_MAX )
397  {
398  result = xTaskCreate( thread, name, stacksize, arg, prio, &CreatedTask );
399 
400  // For each task created, store the task handle (pid) in the timers array.
401  // This scheme doesn't allow for threads to be deleted
402  //s_timeoutlist[s_nextthread++].pid = CreatedTask;
403 
404  if(result == pdPASS)
405  {
406  return CreatedTask;
407  }
408  else
409  {
410  return NULL;
411  }
412  }
413  else
414  {
415  return NULL;
416  }
417 }
418 
419 /*
420  This optional function does a "fast" critical region protection and returns
421  the previous protection level. This function is only called during very short
422  critical regions. An embedded system which supports ISR-based drivers might
423  want to implement this function by disabling interrupts. Task-based systems
424  might want to implement this by using a mutex or disabling tasking. This
425  function should support recursive calls from the same task or interrupt. In
426  other words, sys_arch_protect() could be called while already protected. In
427  that case the return value indicates that it is already protected.
428 
429  sys_arch_protect() is only required if your port is supporting an operating
430  system.
431 */
433 {
435  return 1;
436 }
437 
438 /*
439  This optional function does a "fast" set of critical region protection to the
440  value specified by pval. See the documentation for sys_arch_protect() for
441  more information. This function is only required if your port is supporting
442  an operating system.
443 */
445 {
446  ( void ) pval;
448 }
449 
450 /*
451  * Prints an assertion messages and aborts execution.
452  */
453 void sys_assert( const char *msg )
454 {
455  ( void ) msg;
456  /*FSL:only needed for debugging
457  printf(msg);
458  printf("\n\r");
459  */
461  for(;;)
462  ;
463 }
#define pdTRUE
Definition: projdefs.h:83
void sys_sem_free(sys_sem_t *sem)
Definition: sys_arch.c:303
#define portMAX_DELAY
Definition: portmacro.h:106
void vQueueDelete(QueueHandle_t xQueue) PRIVILEGED_FUNCTION
Definition: queue.c:1738
#define SYS_SEM_NULL
Definition: sys_arch.h:41
#define archMESG_QUEUE_LENGTH
Definition: sys_arch.h:65
err_t sys_sem_new(sys_sem_t *sem, u8_t count)
Definition: sys_arch.c:221
void sys_sem_set_invalid(sys_sem_t *sem)
Definition: sys_arch.c:321
u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
Definition: sys_arch.c:263
#define SYS_ARCH_TIMEOUT
Definition: sys.h:82
#define portTickType
Definition: FreeRTOS.h:804
#define portTICK_RATE_MS
Definition: FreeRTOS.h:817
osThreadId sys_thread_t
Definition: sys_arch.h:47
osMessageQId sys_mbox_t
Definition: sys_arch.h:46
err_t sys_mbox_new(sys_mbox_t *mbox, int size)
Definition: sys_arch.c:52
void vPortEnterCritical(void)
Definition: port.c:391
void sys_init(void)
Definition: sys_arch.c:328
#define SYS_MBOX_NULL
Definition: sys_arch.h:40
#define xQueueReceive(xQueue, pvBuffer, xTicksToWait)
Definition: queue.h:814
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
Definition: sys_arch.c:143
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
Definition: sys_arch.c:106
#define NULL
Definition: usbd_def.h:53
unsigned long u32_t
Definition: cc.h:42
#define SYS_MBOX_EMPTY
Definition: sys.h:87
void sys_mutex_lock(sys_mutex_t *mutex)
Definition: sys_arch.c:370
sys_prot_t sys_arch_protect(void)
Definition: sys_arch.c:432
TickType_t xTaskGetTickCount(void) PRIVILEGED_FUNCTION
Definition: tasks.c:1764
void(* lwip_thread_fn)(void *arg)
Definition: sys.h:93
#define xTaskHandle
Definition: FreeRTOS.h:805
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
Definition: sys_arch.c:186
#define ERR_OK
Definition: err.h:52
err_t sys_mutex_new(sys_mutex_t *mutex)
Definition: sys_arch.c:339
s8_t err_t
Definition: err.h:47
void sys_sem_signal(sys_sem_t *sem)
Definition: sys_arch.c:296
osSemaphoreId sys_sem_t
Definition: sys_arch.h:44
#define pdPASS
Definition: projdefs.h:85
int sys_prot_t
Definition: cc.h:45
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
Definition: sys_arch.c:391
#define xQueueSend(xQueue, pvItemToQueue, xTicksToWait)
Definition: queue.h:421
void sys_mbox_set_invalid(sys_mbox_t *mbox)
Definition: sys_arch.c:213
#define portNOP()
Definition: portmacro.h:203
int sys_mbox_valid(sys_mbox_t *mbox)
Definition: sys_arch.c:205
#define xSemaphoreGive(xSemaphore)
Definition: semphr.h:423
void sys_mutex_unlock(sys_mutex_t *mutex)
Definition: sys_arch.c:377
void sys_mbox_post(sys_mbox_t *mbox, void *data)
Definition: sys_arch.c:98
#define xSemaphoreTake(xSemaphore, xBlockTime)
Definition: semphr.h:252
void sys_mutex_free(sys_mutex_t *mutex)
Definition: sys_arch.c:360
#define SYS_THREAD_MAX
Definition: sys_arch.c:45
int sys_sem_valid(sys_sem_t *sem)
Definition: sys_arch.c:312
UBaseType_t uxQueueMessagesWaiting(const QueueHandle_t xQueue) PRIVILEGED_FUNCTION
Definition: queue.c:1692
void sys_arch_unprotect(sys_prot_t pval)
Definition: sys_arch.c:444
unsigned char u8_t
Definition: cc.h:38
void sys_assert(const char *msg)
Definition: sys_arch.c:453
#define vSemaphoreCreateBinary(xSemaphore)
Definition: semphr.h:131
#define xQueueCreate(uxQueueLength, uxItemSize)
Definition: queue.h:173
#define xTaskCreate(pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask)
Definition: task.h:345
#define ERR_MEM
Definition: err.h:53
#define xSemaphoreCreateMutex()
Definition: semphr.h:693
#define xQueueSendToBack(xQueue, pvItemToQueue, xTicksToWait)
Definition: queue.h:337
unsigned short u16_t
Definition: cc.h:40
void sys_mbox_free(sys_mbox_t *mbox)
Definition: sys_arch.c:76
osSemaphoreId sys_mutex_t
Definition: sys_arch.h:45
void vPortExitCritical(void)
Definition: port.c:408