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