source: S-port/trunk/Middlewares/Third_Party/LwIP/system/OS/sys_arch.c

Last change on this file was 1, checked in by AlexLir, 3 years ago
File size: 14.8 KB
Line 
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
40#if !NO_SYS
41
42#include "cmsis_os.h"
43
44#if defined(LWIP_PROVIDE_ERRNO)
45int errno;
46#endif
47
48/*-----------------------------------------------------------------------------------*/
49// Creates an empty mailbox.
50err_t sys_mbox_new(sys_mbox_t *mbox, int size)
51{
52#if (osCMSIS < 0x20000U)
53 osMessageQDef(QUEUE, size, void *);
54 *mbox = osMessageCreate(osMessageQ(QUEUE), NULL);
55#else
56 *mbox = osMessageQueueNew(size, sizeof(void *), NULL);
57#endif
58#if SYS_STATS
59 ++lwip_stats.sys.mbox.used;
60 if(lwip_stats.sys.mbox.max < lwip_stats.sys.mbox.used)
61 {
62 lwip_stats.sys.mbox.max = lwip_stats.sys.mbox.used;
63 }
64#endif /* SYS_STATS */
65 if(*mbox == NULL)
66 return ERR_MEM;
67
68 return ERR_OK;
69}
70
71/*-----------------------------------------------------------------------------------*/
72/*
73 Deallocates a mailbox. If there are messages still present in the
74 mailbox when the mailbox is deallocated, it is an indication of a
75 programming error in lwIP and the developer should be notified.
76*/
77void sys_mbox_free(sys_mbox_t *mbox)
78{
79#if (osCMSIS < 0x20000U)
80 if(osMessageWaiting(*mbox))
81#else
82 if(osMessageQueueGetCount(*mbox))
83#endif
84 {
85 /* Line for breakpoint. Should never break here! */
86 portNOP();
87#if SYS_STATS
88 lwip_stats.sys.mbox.err++;
89#endif /* SYS_STATS */
90
91 }
92#if (osCMSIS < 0x20000U)
93 osMessageDelete(*mbox);
94#else
95 osMessageQueueDelete(*mbox);
96#endif
97#if SYS_STATS
98 --lwip_stats.sys.mbox.used;
99#endif /* SYS_STATS */
100}
101
102/*-----------------------------------------------------------------------------------*/
103// Posts the "msg" to the mailbox.
104void sys_mbox_post(sys_mbox_t *mbox, void *data)
105{
106#if (osCMSIS < 0x20000U)
107 while(osMessagePut(*mbox, (uint32_t)data, osWaitForever) != osOK);
108#else
109 while(osMessageQueuePut(*mbox, &data, 0, osWaitForever) != osOK);
110#endif
111}
112
113
114/*-----------------------------------------------------------------------------------*/
115// Try to post the "msg" to the mailbox.
116err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
117{
118 err_t result;
119#if (osCMSIS < 0x20000U)
120 if(osMessagePut(*mbox, (uint32_t)msg, 0) == osOK)
121#else
122 if(osMessageQueuePut(*mbox, &msg, 0, 0) == osOK)
123#endif
124 {
125 result = ERR_OK;
126 }
127 else
128 {
129 // could not post, queue must be full
130 result = ERR_MEM;
131
132#if SYS_STATS
133 lwip_stats.sys.mbox.err++;
134#endif /* SYS_STATS */
135 }
136
137 return result;
138}
139
140
141/*-----------------------------------------------------------------------------------*/
142// Try to post the "msg" to the mailbox.
143err_t sys_mbox_trypost_fromisr(sys_mbox_t *mbox, void *msg)
144{
145 return sys_mbox_trypost(mbox, msg);
146}
147
148/*-----------------------------------------------------------------------------------*/
149/*
150 Blocks the thread until a message arrives in the mailbox, but does
151 not block the thread longer than "timeout" milliseconds (similar to
152 the sys_arch_sem_wait() function). The "msg" argument is a result
153 parameter that is set by the function (i.e., by doing "*msg =
154 ptr"). The "msg" parameter maybe NULL to indicate that the message
155 should be dropped.
156
157 The return values are the same as for the sys_arch_sem_wait() function:
158 Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
159 timeout.
160
161 Note that a function with a similar name, sys_mbox_fetch(), is
162 implemented by lwIP.
163*/
164u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout)
165{
166#if (osCMSIS < 0x20000U)
167 osEvent event;
168 uint32_t starttime = osKernelSysTick();
169#else
170 osStatus_t status;
171 uint32_t starttime = osKernelGetTickCount();
172#endif
173 if(timeout != 0)
174 {
175#if (osCMSIS < 0x20000U)
176 event = osMessageGet (*mbox, timeout);
177
178 if(event.status == osEventMessage)
179 {
180 *msg = (void *)event.value.v;
181 return (osKernelSysTick() - starttime);
182 }
183#else
184 status = osMessageQueueGet(*mbox, msg, 0, timeout);
185 if (status == osOK)
186 {
187 return (osKernelGetTickCount() - starttime);
188 }
189#endif
190 else
191 {
192 return SYS_ARCH_TIMEOUT;
193 }
194 }
195 else
196 {
197#if (osCMSIS < 0x20000U)
198 event = osMessageGet (*mbox, osWaitForever);
199 *msg = (void *)event.value.v;
200 return (osKernelSysTick() - starttime);
201#else
202 osMessageQueueGet(*mbox, msg, 0, osWaitForever );
203 return (osKernelGetTickCount() - starttime);
204#endif
205 }
206}
207
208/*-----------------------------------------------------------------------------------*/
209/*
210 Similar to sys_arch_mbox_fetch, but if message is not ready immediately, we'll
211 return with SYS_MBOX_EMPTY. On success, 0 is returned.
212*/
213u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
214{
215#if (osCMSIS < 0x20000U)
216 osEvent event;
217
218 event = osMessageGet (*mbox, 0);
219
220 if(event.status == osEventMessage)
221 {
222 *msg = (void *)event.value.v;
223#else
224 if (osMessageQueueGet(*mbox, msg, 0, 0) == osOK)
225 {
226#endif
227 return ERR_OK;
228 }
229 else
230 {
231 return SYS_MBOX_EMPTY;
232 }
233}
234/*----------------------------------------------------------------------------------*/
235int sys_mbox_valid(sys_mbox_t *mbox)
236{
237 if (*mbox == SYS_MBOX_NULL)
238 return 0;
239 else
240 return 1;
241}
242/*-----------------------------------------------------------------------------------*/
243void sys_mbox_set_invalid(sys_mbox_t *mbox)
244{
245 *mbox = SYS_MBOX_NULL;
246}
247
248/*-----------------------------------------------------------------------------------*/
249// Creates a new semaphore. The "count" argument specifies
250// the initial state of the semaphore.
251err_t sys_sem_new(sys_sem_t *sem, u8_t count)
252{
253#if (osCMSIS < 0x20000U)
254 osSemaphoreDef(SEM);
255 *sem = osSemaphoreCreate (osSemaphore(SEM), 1);
256#else
257 *sem = osSemaphoreNew(UINT16_MAX, count, NULL);
258#endif
259
260 if(*sem == NULL)
261 {
262#if SYS_STATS
263 ++lwip_stats.sys.sem.err;
264#endif /* SYS_STATS */
265 return ERR_MEM;
266 }
267
268 if(count == 0) // Means it can't be taken
269 {
270#if (osCMSIS < 0x20000U)
271 osSemaphoreWait(*sem, 0);
272#else
273 osSemaphoreAcquire(*sem, 0);
274#endif
275 }
276
277#if SYS_STATS
278 ++lwip_stats.sys.sem.used;
279 if (lwip_stats.sys.sem.max < lwip_stats.sys.sem.used) {
280 lwip_stats.sys.sem.max = lwip_stats.sys.sem.used;
281 }
282#endif /* SYS_STATS */
283
284 return ERR_OK;
285}
286
287/*-----------------------------------------------------------------------------------*/
288/*
289 Blocks the thread while waiting for the semaphore to be
290 signaled. If the "timeout" argument is non-zero, the thread should
291 only be blocked for the specified time (measured in
292 milliseconds).
293
294 If the timeout argument is non-zero, the return value is the number of
295 milliseconds spent waiting for the semaphore to be signaled. If the
296 semaphore wasn't signaled within the specified time, the return value is
297 SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
298 (i.e., it was already signaled), the function may return zero.
299
300 Notice that lwIP implements a function with a similar name,
301 sys_sem_wait(), that uses the sys_arch_sem_wait() function.
302*/
303u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
304{
305#if (osCMSIS < 0x20000U)
306 uint32_t starttime = osKernelSysTick();
307#else
308 uint32_t starttime = osKernelGetTickCount();
309#endif
310 if(timeout != 0)
311 {
312#if (osCMSIS < 0x20000U)
313 if(osSemaphoreWait (*sem, timeout) == osOK)
314 {
315 return (osKernelSysTick() - starttime);
316#else
317 if(osSemaphoreAcquire(*sem, timeout) == osOK)
318 {
319 return (osKernelGetTickCount() - starttime);
320#endif
321 }
322 else
323 {
324 return SYS_ARCH_TIMEOUT;
325 }
326 }
327 else
328 {
329#if (osCMSIS < 0x20000U)
330 while(osSemaphoreWait (*sem, osWaitForever) != osOK);
331 return (osKernelSysTick() - starttime);
332#else
333 while(osSemaphoreAcquire(*sem, osWaitForever) != osOK);
334 return (osKernelGetTickCount() - starttime);
335#endif
336 }
337}
338
339/*-----------------------------------------------------------------------------------*/
340// Signals a semaphore
341void sys_sem_signal(sys_sem_t *sem)
342{
343 osSemaphoreRelease(*sem);
344}
345
346/*-----------------------------------------------------------------------------------*/
347// Deallocates a semaphore
348void sys_sem_free(sys_sem_t *sem)
349{
350#if SYS_STATS
351 --lwip_stats.sys.sem.used;
352#endif /* SYS_STATS */
353
354 osSemaphoreDelete(*sem);
355}
356/*-----------------------------------------------------------------------------------*/
357int sys_sem_valid(sys_sem_t *sem)
358{
359 if (*sem == SYS_SEM_NULL)
360 return 0;
361 else
362 return 1;
363}
364
365/*-----------------------------------------------------------------------------------*/
366void sys_sem_set_invalid(sys_sem_t *sem)
367{
368 *sem = SYS_SEM_NULL;
369}
370
371/*-----------------------------------------------------------------------------------*/
372#if (osCMSIS < 0x20000U)
373osMutexId lwip_sys_mutex;
374osMutexDef(lwip_sys_mutex);
375#else
376osMutexId_t lwip_sys_mutex;
377#endif
378// Initialize sys arch
379void sys_init(void)
380{
381#if (osCMSIS < 0x20000U)
382 lwip_sys_mutex = osMutexCreate(osMutex(lwip_sys_mutex));
383#else
384 lwip_sys_mutex = osMutexNew(NULL);
385#endif
386}
387/*-----------------------------------------------------------------------------------*/
388 /* Mutexes*/
389/*-----------------------------------------------------------------------------------*/
390/*-----------------------------------------------------------------------------------*/
391#if LWIP_COMPAT_MUTEX == 0
392/* Create a new mutex*/
393err_t sys_mutex_new(sys_mutex_t *mutex) {
394
395#if (osCMSIS < 0x20000U)
396 osMutexDef(MUTEX);
397 *mutex = osMutexCreate(osMutex(MUTEX));
398#else
399 *mutex = osMutexNew(NULL);
400#endif
401
402 if(*mutex == NULL)
403 {
404#if SYS_STATS
405 ++lwip_stats.sys.mutex.err;
406#endif /* SYS_STATS */
407 return ERR_MEM;
408 }
409
410#if SYS_STATS
411 ++lwip_stats.sys.mutex.used;
412 if (lwip_stats.sys.mutex.max < lwip_stats.sys.mutex.used) {
413 lwip_stats.sys.mutex.max = lwip_stats.sys.mutex.used;
414 }
415#endif /* SYS_STATS */
416 return ERR_OK;
417}
418/*-----------------------------------------------------------------------------------*/
419/* Deallocate a mutex*/
420void sys_mutex_free(sys_mutex_t *mutex)
421{
422#if SYS_STATS
423 --lwip_stats.sys.mutex.used;
424#endif /* SYS_STATS */
425
426 osMutexDelete(*mutex);
427}
428/*-----------------------------------------------------------------------------------*/
429/* Lock a mutex*/
430void sys_mutex_lock(sys_mutex_t *mutex)
431{
432#if (osCMSIS < 0x20000U)
433 osMutexWait(*mutex, osWaitForever);
434#else
435 osMutexAcquire(*mutex, osWaitForever);
436#endif
437}
438
439/*-----------------------------------------------------------------------------------*/
440/* Unlock a mutex*/
441void sys_mutex_unlock(sys_mutex_t *mutex)
442{
443 osMutexRelease(*mutex);
444}
445#endif /*LWIP_COMPAT_MUTEX*/
446/*-----------------------------------------------------------------------------------*/
447// TODO
448/*-----------------------------------------------------------------------------------*/
449/*
450 Starts a new thread with priority "prio" that will begin its execution in the
451 function "thread()". The "arg" argument will be passed as an argument to the
452 thread() function. The id of the new thread is returned. Both the id and
453 the priority are system dependent.
454*/
455sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread , void *arg, int stacksize, int prio)
456{
457#if (osCMSIS < 0x20000U)
458 const osThreadDef_t os_thread_def = { (char *)name, (os_pthread)thread, (osPriority)prio, 0, stacksize};
459 return osThreadCreate(&os_thread_def, arg);
460#else
461 const osThreadAttr_t attributes = {
462 .name = name,
463 .stack_size = stacksize,
464 .priority = (osPriority_t)prio,
465 };
466 return osThreadNew(thread, arg, &attributes);
467#endif
468}
469
470/*
471 This optional function does a "fast" critical region protection and returns
472 the previous protection level. This function is only called during very short
473 critical regions. An embedded system which supports ISR-based drivers might
474 want to implement this function by disabling interrupts. Task-based systems
475 might want to implement this by using a mutex or disabling tasking. This
476 function should support recursive calls from the same task or interrupt. In
477 other words, sys_arch_protect() could be called while already protected. In
478 that case the return value indicates that it is already protected.
479
480 sys_arch_protect() is only required if your port is supporting an operating
481 system.
482
483 Note: This function is based on FreeRTOS API, because no equivalent CMSIS-RTOS
484 API is available
485*/
486sys_prot_t sys_arch_protect(void)
487{
488#if (osCMSIS < 0x20000U)
489 osMutexWait(lwip_sys_mutex, osWaitForever);
490#else
491 osMutexAcquire(lwip_sys_mutex, osWaitForever);
492#endif
493 return (sys_prot_t)1;
494}
495
496
497/*
498 This optional function does a "fast" set of critical region protection to the
499 value specified by pval. See the documentation for sys_arch_protect() for
500 more information. This function is only required if your port is supporting
501 an operating system.
502
503 Note: This function is based on FreeRTOS API, because no equivalent CMSIS-RTOS
504 API is available
505*/
506void sys_arch_unprotect(sys_prot_t pval)
507{
508 ( void ) pval;
509 osMutexRelease(lwip_sys_mutex);
510}
511
512#endif /* !NO_SYS */
Note: See TracBrowser for help on using the repository browser.