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 /* system includes */
34 #include <stdlib.h>
35
36 #include "aos/kernel.h"
37
38 /* lwIP includes. */
39 #include "lwip/opt.h"
40 #include "lwip/debug.h"
41 #include "lwip/def.h"
42 #include "lwip/sys.h"
43 #include "lwip/mem.h"
44 #include "arch/sys_arch.h"
45
46 static aos_mutex_t sys_arch_mutex;
47 static aos_mutex_t reenter_mutex;
48
49 //#define NET_TASK_NUME 2
50 //#define NET_TASK_STACK_SIZE 1024
51
52 //ktask_t g_net_task[NET_TASK_NUME];
53 //cpu_stack_t g_net_task_stack[NET_TASK_NUME][NET_TASK_STACK_SIZE];
54
55 /*-----------------------------------------------------------------------------------*/
56 /*
57 err_t sys_sem_new(sys_sem_t *sem, u8_t count)
58 Creates a new semaphore.
59 */
sys_sem_new(sys_sem_t * sem,u8_t count)60 err_t sys_sem_new(sys_sem_t *sem, u8_t count)
61 {
62 err_t ret = ERR_MEM;
63 int stat = aos_sem_new(sem,count);
64
65 if (stat == 0) {
66 ret = ERR_OK;
67 }
68 return ret;
69 }
70
71 /*-----------------------------------------------------------------------------------*/
72 /*
73 void sys_sem_free(sys_sem_t *sem)
74
75 Deallocates a semaphore.
76 */
sys_sem_free(sys_sem_t * sem)77 void sys_sem_free(sys_sem_t *sem)
78 {
79 if ((sem != NULL)) {
80 aos_sem_free(sem);
81 }
82 }
83
84
85 /*-----------------------------------------------------------------------------------*/
86 /*
87 void sys_sem_signal(sys_sem_t *sem)
88
89 Signals a semaphore.
90 */
sys_sem_signal(sys_sem_t * sem)91 void sys_sem_signal(sys_sem_t *sem)
92 {
93 aos_sem_signal(sem);
94 }
95
96
97 /*-----------------------------------------------------------------------------------*/
98 /*
99 Blocks the thread while waiting for the semaphore to be
100 signaled. If the "timeout" argument is non-zero, the thread should
101 only be blocked for the specified time (measured in
102 milliseconds).
103
104 If the timeout argument is non-zero, the return value is the number of
105 milliseconds spent waiting for the semaphore to be signaled. If the
106 semaphore wasn't signaled within the specified time, the return value is
107 SYS_ARCH_TIMEOUT. If the thread didn't have to wait for the semaphore
108 (i.e., it was already signaled), the function may return zero.
109
110 Notice that lwIP implements a function with a similar name,
111 sys_sem_wait(), that uses the sys_arch_sem_wait() function.
112 */
sys_arch_sem_wait(sys_sem_t * sem,u32_t timeout)113 u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
114 {
115 u32_t begin_ms, end_ms, elapsed_ms;
116 u32_t ret;
117
118 if (sem == NULL)
119 return SYS_ARCH_TIMEOUT;
120
121 begin_ms = sys_now();
122
123 if( timeout != 0UL ) {
124 ret = aos_sem_wait(sem,timeout);
125 if(ret == 0) {
126 end_ms = sys_now();
127
128 elapsed_ms = end_ms - begin_ms;
129
130 ret = elapsed_ms;
131 } else {
132 ret = SYS_ARCH_TIMEOUT;
133 }
134 } else {
135 while( !(aos_sem_wait(sem, AOS_WAIT_FOREVER) == 0));
136 end_ms = sys_now();
137
138 elapsed_ms = end_ms - begin_ms;
139
140 if( elapsed_ms == 0UL ) {
141 elapsed_ms = 1UL;
142 }
143
144 ret = elapsed_ms;
145 }
146
147 return ret;
148 }
149
150 #ifndef LWIP_MAILBOX_QUEUE
151
152 /*-----------------------------------------------------------------------------------*/
153 /*
154 err_t sys_mbox_new(sys_mbox_t *mbox, int size)
155
156 Creates an empty mailbox for maximum "size" elements.
157 */
sys_mbox_new(sys_mbox_t * mb,int size)158 err_t sys_mbox_new(sys_mbox_t *mb, int size)
159 {
160 struct sys_mbox *mbox;
161 LWIP_UNUSED_ARG(size);
162
163 mbox = (struct sys_mbox *)malloc(sizeof(struct sys_mbox));
164 if (mbox == NULL) {
165 return ERR_MEM;
166 }
167 memset(mbox, 0, sizeof(struct sys_mbox));
168
169 mbox->first = mbox->last = 0;
170 sys_sem_new(&mbox->not_empty, 0);
171 sys_sem_new(&mbox->not_full, 0);
172 sys_sem_new(&mbox->mutex, 1);
173 mbox->wait_send = 0;
174
175 *mb = mbox;
176 return ERR_OK;
177 }
178
179 /*-----------------------------------------------------------------------------------*/
180 /*
181 Deallocates a mailbox. If there are messages still present in the
182 mailbox when the mailbox is deallocated, it is an indication of a
183 programming error in lwIP and the developer should be notified.
184 */
sys_mbox_free(sys_mbox_t * mb)185 void sys_mbox_free(sys_mbox_t *mb)
186 {
187 if ((mb != NULL) && (*mb != SYS_MBOX_NULL)) {
188 struct sys_mbox *mbox = *mb;
189
190 sys_arch_sem_wait(&mbox->mutex, 0);
191
192 sys_sem_free(&mbox->not_empty);
193 sys_sem_free(&mbox->not_full);
194 sys_sem_free(&mbox->mutex);
195 /* LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */
196 free(mbox);
197 }
198 }
199
200 /*-----------------------------------------------------------------------------------*/
201 /*
202 void sys_mbox_post(sys_mbox_t *mbox, void *msg)
203
204 Posts the "msg" to the mailbox. This function have to block until the "msg" is really posted.
205 */
sys_mbox_post(sys_mbox_t * mb,void * msg)206 void sys_mbox_post(sys_mbox_t *mb, void *msg)
207 {
208 u8_t first;
209 struct sys_mbox *mbox;
210 LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL));
211 mbox = *mb;
212
213 sys_arch_sem_wait(&mbox->mutex, 0);
214
215 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mbox, (void *)msg));
216
217 while ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
218 mbox->wait_send++;
219 sys_sem_signal(&mbox->mutex);
220 sys_arch_sem_wait(&mbox->not_full, 0);
221 sys_arch_sem_wait(&mbox->mutex, 0);
222 mbox->wait_send--;
223 }
224
225 mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
226
227 if (mbox->last == mbox->first) {
228 first = 1;
229 } else {
230 first = 0;
231 }
232
233 mbox->last++;
234
235 if (first) {
236 sys_sem_signal(&mbox->not_empty);
237 }
238
239 sys_sem_signal(&mbox->mutex);
240 }
241
242 /*
243 err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
244
245 Try to post the "msg" to the mailbox. Returns ERR_MEM if this one is full, else, ERR_OK if the "msg" is posted.
246 */
sys_mbox_trypost(sys_mbox_t * mb,void * msg)247 err_t sys_mbox_trypost(sys_mbox_t *mb, void *msg)
248 {
249 u8_t first;
250 struct sys_mbox *mbox;
251 LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL));
252 mbox = *mb;
253
254 sys_arch_sem_wait(&mbox->mutex, 0);
255
256 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n",
257 (void *)mbox, (void *)msg));
258
259 if ((mbox->last + 1) >= (mbox->first + SYS_MBOX_SIZE)) {
260 sys_sem_signal(&mbox->mutex);
261 return ERR_MEM;
262 }
263
264 mbox->msgs[mbox->last % SYS_MBOX_SIZE] = msg;
265
266 if (mbox->last == mbox->first) {
267 first = 1;
268 } else {
269 first = 0;
270 }
271
272 mbox->last++;
273
274 if (first) {
275 sys_sem_signal(&mbox->not_empty);
276 }
277
278 sys_sem_signal(&mbox->mutex);
279 return ERR_OK;
280 }
281
282 /*-----------------------------------------------------------------------------------*/
283 /*
284 Blocks the thread until a message arrives in the mailbox, but does
285 not block the thread longer than "timeout" milliseconds (similar to
286 the sys_arch_sem_wait() function). The "msg" argument is a result
287 parameter that is set by the function (i.e., by doing "*msg =
288 ptr"). The "msg" parameter maybe NULL to indicate that the message
289 should be dropped.
290
291 The return values are the same as for the sys_arch_sem_wait() function:
292 Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
293 timeout.
294
295 Note that a function with a similar name, sys_mbox_fetch(), is
296 implemented by lwIP.
297 */
sys_arch_mbox_fetch(sys_mbox_t * mb,void ** msg,u32_t timeout)298 u32_t sys_arch_mbox_fetch(sys_mbox_t *mb, void **msg, u32_t timeout)
299 {
300 u32_t time_needed = 0;
301 struct sys_mbox *mbox;
302 LWIP_ASSERT("invalid mbox", (mb != NULL));
303 mbox = *mb;
304
305 /* The mutex lock is quick so we don't bother with the timeout
306 stuff here. */
307 sys_arch_sem_wait(&mbox->mutex, 0);
308
309 while (mbox->first == mbox->last) {
310 sys_sem_signal(&mbox->mutex);
311
312 /* We block while waiting for a mail to arrive in the mailbox. We
313 must be prepared to timeout. */
314 if (timeout != 0) {
315 time_needed = sys_arch_sem_wait(&mbox->not_empty, timeout);
316
317 if (time_needed == SYS_ARCH_TIMEOUT) {
318 return SYS_ARCH_TIMEOUT;
319 }
320 } else {
321 sys_arch_sem_wait(&mbox->not_empty, 0);
322 }
323
324 sys_arch_sem_wait(&mbox->mutex, 0);
325 }
326
327 if (msg != NULL) {
328 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mbox, *msg));
329 *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
330 } else {
331 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mbox));
332 }
333
334 mbox->first++;
335
336 if (mbox->wait_send) {
337 sys_sem_signal(&mbox->not_full);
338 }
339
340 sys_sem_signal(&mbox->mutex);
341
342 return time_needed;
343 }
344
345 /*
346 u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
347
348 similar to sys_arch_mbox_fetch, however if a message is not present in the mailbox,
349 it immediately returns with the code SYS_MBOX_EMPTY.
350 */
sys_arch_mbox_tryfetch(sys_mbox_t * mb,void ** msg)351 u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mb, void **msg)
352 {
353 struct sys_mbox *mbox;
354 LWIP_ASSERT("invalid mbox", (mb != NULL) && (*mb != NULL));
355 mbox = *mb;
356
357 sys_arch_sem_wait(&mbox->mutex, 0);
358
359 if (mbox->first == mbox->last) {
360 sys_sem_signal(&mbox->mutex);
361 return SYS_MBOX_EMPTY;
362 }
363
364 if (msg != NULL) {
365 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mbox, *msg));
366 *msg = mbox->msgs[mbox->first % SYS_MBOX_SIZE];
367 } else {
368 LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mbox));
369 }
370
371 mbox->first++;
372
373 if (mbox->wait_send) {
374 sys_sem_signal(&mbox->not_full);
375 }
376
377 sys_sem_signal(&mbox->mutex);
378
379 return 0;
380 }
381 #else
382
383 /*-----------------------------------------------------------------------------------*/
384 /*
385 err_t sys_mbox_new(sys_mbox_t *mbox, int size)
386
387 Creates an empty mailbox for maximum "size" elements.
388 */
sys_mbox_new(sys_mbox_t * mb,int size)389 err_t sys_mbox_new(sys_mbox_t *mb, int size)
390 {
391 void *msg_start;
392 err_t ret = ERR_MEM;
393 size_t ptr_size = sizeof(void *);
394
395 msg_start = malloc(size * ptr_size);
396 if (msg_start == NULL) {
397 return ERR_MEM;
398 }
399
400 int stat = aos_queue_new(mb,msg_start,size * ptr_size,ptr_size);
401
402 if (stat == 0) {
403 ret = ERR_OK;
404 } else {
405 ret = ERR_MEM;
406 free(msg_start);
407 }
408 return ret;
409 }
410
411 /*-----------------------------------------------------------------------------------*/
412 /*
413 Deallocates a mailbox. If there are messages still present in the
414 mailbox when the mailbox is deallocated, it is an indication of a
415 programming error in lwIP and the developer should be notified.
416 */
sys_mbox_free(sys_mbox_t * mb)417 void sys_mbox_free(sys_mbox_t *mb)
418 {
419 void *start;
420
421 if ((mb != NULL)) {
422 start = aos_queue_buf_ptr(mb);
423 if(start != NULL)
424 free(start);
425 aos_queue_free(mb);
426 }
427 }
428
429 /*-----------------------------------------------------------------------------------*/
430 /*
431 void sys_mbox_post(sys_mbox_t *mbox, void *msg)
432
433 Posts the "msg" to the mailbox. This function have to block until the "msg" is really posted.
434 */
sys_mbox_post(sys_mbox_t * mb,void * msg)435 void sys_mbox_post(sys_mbox_t *mb, void *msg)
436 {
437 aos_queue_send(mb,&msg,sizeof(void*));
438 }
439
440 /*
441 err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg)
442
443 Try to post the "msg" to the mailbox. Returns ERR_MEM if this one is full, else, ERR_OK if the "msg" is posted.
444 */
sys_mbox_trypost(sys_mbox_t * mb,void * msg)445 err_t sys_mbox_trypost(sys_mbox_t *mb, void *msg)
446 {
447 if (aos_queue_send(mb,&msg,sizeof(void*)) != 0)
448 return ERR_MEM;
449 else
450 return ERR_OK;
451 }
452
453 /*-----------------------------------------------------------------------------------*/
454 /*
455 Blocks the thread until a message arrives in the mailbox, but does
456 not block the thread longer than "timeout" milliseconds (similar to
457 the sys_arch_sem_wait() function). The "msg" argument is a result
458 parameter that is set by the function (i.e., by doing "*msg =
459 ptr"). The "msg" parameter maybe NULL to indicate that the message
460 should be dropped.
461
462 The return values are the same as for the sys_arch_sem_wait() function:
463 Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
464 timeout.
465
466 Note that a function with a similar name, sys_mbox_fetch(), is
467 implemented by lwIP.
468 */
sys_arch_mbox_fetch(sys_mbox_t * mb,void ** msg,u32_t timeout)469 u32_t sys_arch_mbox_fetch(sys_mbox_t *mb, void **msg, u32_t timeout)
470 {
471 u32_t begin_ms, end_ms, elapsed_ms;
472 u32_t len;
473 u32_t ret;
474
475 if (mb == NULL)
476 return SYS_ARCH_TIMEOUT;
477
478 begin_ms = sys_now();
479
480 if( timeout != 0UL ) {
481
482 if(aos_queue_recv(mb,timeout,msg,(unsigned int *)&len) == 0) {
483 end_ms = sys_now();
484 elapsed_ms = end_ms - begin_ms;
485 ret = elapsed_ms;
486 } else {
487 ret = SYS_ARCH_TIMEOUT;
488 }
489 } else {
490 while(aos_queue_recv(mb,AOS_WAIT_FOREVER,msg,(unsigned int*)&len) != 0);
491 end_ms = sys_now();
492 elapsed_ms = end_ms - begin_ms;
493
494 if( elapsed_ms == 0UL ) {
495 elapsed_ms = 1UL;
496 }
497
498 ret = elapsed_ms;
499 }
500
501 return ret;
502 }
503
504 /*
505 u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg)
506
507 similar to sys_arch_mbox_fetch, however if a message is not present in the mailbox,
508 it immediately returns with the code SYS_MBOX_EMPTY.
509 */
sys_arch_mbox_tryfetch(sys_mbox_t * mb,void ** msg)510 u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mb, void **msg)
511 {
512 u32_t len;
513
514 if(aos_queue_recv(mb,0u,msg,(unsigned int*)&len) != 0 ) {
515 return SYS_MBOX_EMPTY;
516 } else {
517 return ERR_OK;
518 }
519 }
520 #endif
521
522 /** Create a new mutex
523 * @param mutex pointer to the mutex to create
524 * @return a new mutex
525 *
526 **/
sys_mutex_new(sys_mutex_t * mutex)527 err_t sys_mutex_new(sys_mutex_t *mutex)
528 {
529 err_t ret = ERR_MEM;
530 int stat = aos_mutex_new(mutex);
531
532 if (stat == 0) {
533 ret = ERR_OK;
534 }
535 return ret;
536 }
537
538 /** Lock a mutex
539 * @param mutex the mutex to lock
540 **/
sys_mutex_lock(sys_mutex_t * mutex)541 void sys_mutex_lock(sys_mutex_t *mutex)
542 {
543 aos_mutex_lock(mutex,AOS_WAIT_FOREVER);
544 }
545
546 /** Unlock a mutex
547 * @param mutex the mutex to unlock */
sys_mutex_unlock(sys_mutex_t * mutex)548 void sys_mutex_unlock(sys_mutex_t *mutex)
549 {
550 aos_mutex_unlock(mutex);
551 }
552
553
554 /** Delete a semaphore
555 * @param mutex the mutex to delete
556 **/
sys_mutex_free(sys_mutex_t * mutex)557 void sys_mutex_free(sys_mutex_t *mutex)
558 {
559 aos_mutex_free(mutex);
560 }
561
562 /*
563 u32_t sys_now(void)
564
565 This optional function returns the current time in milliseconds (don't care for wraparound,
566 this is only used for time diffs).
567 */
sys_now(void)568 u32_t sys_now(void)
569 {
570 return aos_now_ms();
571 }
572
573 /*
574 u32_t sys_jiffies(void)
575 This optional function returns the current time in milliseconds (don't care for wraparound,
576 this is only used for time diffs).
577 */
578
sys_jiffies(void)579 u32_t sys_jiffies(void)
580 {
581 return aos_now();
582 }
583
sys_thread_new(const char * name,lwip_thread_fn thread,void * arg,int stacksize,int prio)584 sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio)
585 {
586 aos_task_t task_handle;
587
588 aos_task_new_ext(&task_handle,name,thread,arg,stacksize,prio);
589
590 return (sys_thread_t)task_handle;
591 }
592
593 #if SYS_LIGHTWEIGHT_PROT
594 /*
595 This optional function does a "fast" critical region protection and returns
596 the previous protection level. This function is only called during very short
597 critical regions. An embedded system which supports ISR-based drivers might
598 want to implement this function by disabling interrupts. Task-based systems
599 might want to implement this by using a mutex or disabling tasking. This
600 function should support recursive calls from the same task or interrupt. In
601 other words, sys_arch_protect() could be called while already protected. In
602 that case the return value indicates that it is already protected.
603
604 sys_arch_protect() is only required if your port is supporting an operating
605 system.
606 */
sys_arch_protect(void)607 sys_prot_t sys_arch_protect(void)
608 {
609 aos_mutex_lock(&sys_arch_mutex, AOS_WAIT_FOREVER);
610 return 0;
611 }
612
613 /*
614 This optional function does a "fast" set of critical region protection to the
615 value specified by pval. See the documentation for sys_arch_protect() for
616 more information. This function is only required if your port is supporting
617 an operating system.
618 */
sys_arch_unprotect(sys_prot_t pval)619 void sys_arch_unprotect(sys_prot_t pval)
620 {
621 aos_mutex_unlock(&sys_arch_mutex);
622 }
623
reenter_protect(void)624 sys_prot_t reenter_protect(void)
625 {
626 aos_mutex_lock(&reenter_mutex, AOS_WAIT_FOREVER);
627 return 0;
628 }
629
reenter_unprotect(sys_prot_t pval)630 void reenter_unprotect(sys_prot_t pval)
631 {
632 aos_mutex_unlock(&reenter_mutex);
633 }
634
635 #endif
636 /*
637 * Prints an assertion messages and aborts execution.
638 */
sys_arch_assert(const char * file,int line)639 void sys_arch_assert(const char *file, int line)
640 {
641 }
642
643 /******************************************************/
644 /*
645 void sys_init(void)
646
647 Is called to initialize the sys_arch layer.
648 */
sys_init(void)649 void sys_init(void)
650 {
651 aos_mutex_new(&sys_arch_mutex);
652 aos_mutex_new(&reenter_mutex);
653 }
654
655