Adapted to Lora Semtech + Nucleo

Dependencies:   DebugLib

Dependents:   LoRaWAN-lmic-app LoRaWAN-lmic-app LoRaWAN-test-10secs LoRaPersonalizedDeviceForEverynet ... more

Fork of lwip_ppp_ethernet by Donatien Garnier

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sys_arch.cpp Source File

sys_arch.cpp

00001 /* sysarch.cpp */
00002 /*
00003 Copyright (C) 2012 ARM Limited.
00004 
00005 Permission is hereby granted, free of charge, to any person obtaining a copy of
00006 this software and associated documentation files (the "Software"), to deal in
00007 the Software without restriction, including without limitation the rights to
00008 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
00009 of the Software, and to permit persons to whom the Software is furnished to do
00010 so, subject to the following conditions:
00011 
00012 The above copyright notice and this permission notice shall be included in all
00013 copies or substantial portions of the Software.
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00018 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00021 SOFTWARE.
00022 */
00023 
00024 #define __DEBUG__ 0
00025 #ifndef __MODULE__
00026 #define __MODULE__ "sys_arch.cpp"
00027 #endif
00028 
00029 extern "C"
00030 {
00031 #include "lwip/opt.h"
00032 #include "lwip/def.h"
00033 #include "lwip/sys.h"
00034 #include "lwip/arch.h"
00035 #include "cc.h"
00036 #include "sys_arch.h"
00037 }
00038 
00039 #include "core/fwk.h"
00040 #include "rtos.h"
00041 #include "mbed.h" //From mbed library
00042 
00043 /*
00044 From http://lwip.wikia.com/wiki/Porting_for_an_OS:
00045 
00046 The sys_arch provides semaphores and mailboxes to lwIP. For the full
00047 lwIP functionality, multiple threads support can be implemented in the
00048 sys_arch, but this is not required for the basic lwIP functionality.
00049 */
00050 
00051 extern "C" 
00052 /*
00053 The file is .cpp to be able to use the C++ abstraction of Mutexes, Semaphores, etc.
00054 however it should be linked in a C-fashion
00055 */
00056 {
00057 
00058 #if SYS_LIGHTWEIGHT_PROT == 0
00059 #error "SYS_LIGHTWEIGHT_PROT must be set"
00060 #endif
00061 
00062 #if SYS_LIGHTWEIGHT_PROT
00063 //Critical regions protection
00064 static Mutex sys_arch_protect_mtx;
00065 
00066 sys_prot_t sys_arch_protect(void)
00067 {
00068 
00069   sys_arch_protect_mtx.lock();
00070 
00071   return 0;
00072 }
00073 
00074 void sys_arch_unprotect(sys_prot_t pval)
00075 {
00076 
00077   LWIP_UNUSED_ARG(pval);
00078   sys_arch_protect_mtx.unlock();
00079 
00080 }
00081 #endif
00082 
00083 //Mutexes
00084 
00085 /** Create a new mutex
00086  * @param mutex pointer to the mutex to create
00087  * @return a new mutex */
00088 err_t sys_mutex_new(sys_mutex_t *pMtx)
00089 {
00090 
00091   SYS_ARCH_DECL_PROTECT(lev);
00092   DBG("Trying to create new mutex");
00093 
00094   SYS_ARCH_PROTECT(lev); //Protect this section
00095   pMtx->pMtx = new Mutex();
00096   SYS_ARCH_UNPROTECT(lev);
00097 
00098   if(pMtx->pMtx == NULL)
00099   {
00100     DBG("No mem");
00101 
00102     return ERR_MEM;
00103   }
00104 
00105   pMtx->valid = true;
00106 
00107   DBG("mutex created OK");
00108 
00109   return ERR_OK; //Return the semaphore
00110 }
00111 
00112 /** Lock a mutex
00113  * @param mutex the mutex to lock */
00114 void sys_mutex_lock(sys_mutex_t *pMtx)
00115 {
00116 
00117   ((Mutex*)(pMtx->pMtx))->lock();
00118 
00119 }
00120 
00121 /** Unlock a mutex
00122  * @param mutex the mutex to unlock */
00123 void sys_mutex_unlock(sys_mutex_t *pMtx)
00124 {
00125 
00126   ((Mutex*)(pMtx->pMtx))->unlock();
00127 
00128 }
00129 
00130 /** Delete a mutex
00131  * @param mutex the mutex to delete */
00132 void sys_mutex_free(sys_mutex_t *pMtx)
00133 {
00134 
00135   SYS_ARCH_DECL_PROTECT(lev);
00136   SYS_ARCH_PROTECT(lev); //Protect this section
00137   delete ((Mutex*)(pMtx->pMtx));
00138   SYS_ARCH_UNPROTECT(lev);
00139 
00140 }
00141 
00142 /** Check if a mutex is valid/allocated: return 1 for valid, 0 for invalid */
00143 int sys_mutex_valid(sys_mutex_t *pMtx)
00144 {
00145 
00146   if (pMtx->pMtx != NULL)
00147   {
00148 
00149     return pMtx->valid;
00150   }
00151 
00152   return false;
00153 }
00154 
00155 /** Set a mutex invalid so that sys_mutex_valid returns 0 */
00156 void sys_mutex_set_invalid(sys_mutex_t *pMtx)
00157 {
00158 
00159   pMtx->valid = false;
00160 
00161 }
00162 
00163 //Semaphores
00164 
00165 /*
00166 The implementation reserves a pool of semaphores that can be used by
00167 LwIP in order to only use static allocation
00168 */
00169 
00170 //static sys_sem sys_sem_pool[LWIP_SEMAPHORES_COUNT] = { 0 };
00171 
00172 /*
00173 Creates and returns a new semaphore. The count argument specifies the
00174 initial state of the semaphore. Returns the semaphore, or SYS_SEM_NULL
00175 on error.
00176 */
00177 err_t sys_sem_new_mul(sys_sem_t *pSem, u8_t size, u8_t count)
00178 {
00179 
00180   SYS_ARCH_DECL_PROTECT(lev);
00181   DBG("Trying to create new semaphore of size=%d", size);
00182 
00183   SYS_ARCH_PROTECT(lev); //Protect this section
00184   pSem->pSphre = new Semaphore(size);
00185   SYS_ARCH_UNPROTECT(lev);
00186   if(pSem->pSphre == NULL)
00187   {
00188     ERR("Failed!");
00189     return ERR_MEM;
00190   }
00191 
00192   while(count < size)
00193   {
00194     ((Semaphore*)(pSem->pSphre))->wait();
00195     count++;
00196   }
00197   pSem->valid = true;
00198 
00199 
00200   return ERR_OK; //Return the semaphore
00201 }
00202 
00203 
00204 /*
00205 Creates and returns a new semaphore. The count argument specifies the
00206 initial state of the semaphore. Returns the semaphore, or SYS_SEM_NULL
00207 on error.
00208 */
00209 err_t sys_sem_new(sys_sem_t *pSem, u8_t count)
00210 {
00211 
00212   SYS_ARCH_DECL_PROTECT(lev);
00213   DBG("Trying to create new semaphore of count=%d", count);
00214 
00215   SYS_ARCH_PROTECT(lev); //Protect this section
00216   pSem->pSphre = new Semaphore(1);
00217   SYS_ARCH_UNPROTECT(lev);
00218   if(pSem->pSphre == NULL)
00219   {
00220     ERR("Failed!");
00221     return ERR_MEM;
00222   }
00223 
00224   if(!count)
00225   {
00226     ((Semaphore*)(pSem->pSphre))->wait();
00227   }
00228   pSem->valid = true;
00229 
00230 
00231   return ERR_OK; //Return the semaphore
00232 }
00233 
00234 /*
00235 Frees a semaphore created by sys_sem_new. Since these two functions
00236 provide the entry and exit point for all semaphores used by lwIP, you
00237 have great flexibility in how these are allocated and deallocated (for
00238 example, from the heap, a memory pool, a semaphore pool, etc).
00239 */
00240 void sys_sem_free(sys_sem_t *pSem)
00241 {
00242   SYS_ARCH_DECL_PROTECT(lev);
00243   DBG("Deleting semaphore");
00244   SYS_ARCH_PROTECT(lev); //Protect this section
00245   delete ((Semaphore*)(pSem->pSphre));
00246   SYS_ARCH_UNPROTECT(lev);
00247 
00248 }
00249 
00250 /*
00251 Signals (or releases) a semaphore.
00252 */
00253 void sys_sem_signal(sys_sem_t* pSem)
00254 {
00255 
00256   ((Semaphore*)(pSem->pSphre))->release(); //Produce (i.e. release) a resource
00257 
00258 }
00259 
00260 /*
00261 Blocks the thread while waiting for the semaphore to be signaled. The
00262 timeout parameter specifies how many milliseconds the function should
00263 block before returning; if the function times out, it should return
00264 SYS_ARCH_TIMEOUT. If timeout=0, then the function should block
00265 indefinitely. If the function acquires the semaphore, it should return
00266 how many milliseconds expired while waiting for the semaphore. The
00267 function may return 0 if the semaphore was immediately available.
00268 */
00269 u32_t sys_arch_sem_wait(sys_sem_t* pSem, u32_t timeout)
00270 {
00271 
00272   int ret;  
00273   Timer t;
00274   uint32_t timeout_sphre;
00275   int time_spent;
00276   
00277   timeout_sphre = (timeout != 0) ? timeout : osWaitForever /*block indefinitely*/;
00278   
00279   t.start();
00280   ret = ((Semaphore*)(pSem->pSphre))->wait(timeout_sphre);
00281   if(ret == 0)
00282   {
00283 
00284     return SYS_ARCH_TIMEOUT;
00285   }
00286   time_spent = t.read_ms();
00287 
00288   return time_spent; 
00289 }
00290 
00291 /** Check if a sempahore is valid/allocated: return 1 for valid, 0 for invalid */
00292 int sys_sem_valid(sys_sem_t *pSem)
00293 {
00294 
00295   if (pSem->pSphre != NULL)
00296   {
00297 
00298     return (pSem->valid);
00299   }
00300 
00301   return false;
00302 }
00303 
00304 /** Set a semaphore invalid so that sys_sem_valid returns 0 */
00305 void sys_sem_set_invalid(sys_sem_t *pSem)
00306 {
00307 
00308   pSem->valid = false;
00309 
00310 }
00311 
00312 //Mailboxes
00313 
00314 /*
00315 The implementation reserves a pool of mailboxes of generic (void*) type that can be used by
00316 LwIP in order to only use static allocation
00317 */
00318 
00319 #define QUEUE_SIZE 8
00320 #define SYS_MBOX_SIZE QUEUE_SIZE
00321 #if 0
00322 /*
00323 Returns a new mailbox, or SYS_MBOX_NULL on error.
00324 */
00325 err_t sys_mbox_new(sys_mbox_t *pMbox, int size)
00326 {
00327 
00328   SYS_ARCH_DECL_PROTECT(lev);
00329   ERR("Trying to create new queue of size %d", size);
00330 
00331   SYS_ARCH_PROTECT(lev); //Protect this section
00332   if(size > QUEUE_SIZE)
00333   {
00334     ERR("Queue size > QUEUE_SIZE");
00335   }
00336   pMbox->pQueue = new Queue<void,QUEUE_SIZE>();
00337   SYS_ARCH_UNPROTECT(lev);
00338   if(pMbox->pQueue == NULL)
00339   {
00340 
00341     return ERR_MEM;
00342   }
00343   pMbox->valid = true;
00344 
00345 
00346   return ERR_OK; //Return the mailbox
00347 }
00348 
00349 /*
00350 Deallocates a mailbox. If there are messages still present in the
00351 mailbox when the mailbox is deallocated, it is an indication of a
00352 programming error in lwIP and the developer should be notified.
00353 */
00354 void sys_mbox_free(sys_mbox_t* pMbox)
00355 {
00356   ERR("WHY??");
00357 
00358   SYS_ARCH_DECL_PROTECT(lev);
00359   SYS_ARCH_PROTECT(lev); //Protect this section
00360   delete ((Queue<void,QUEUE_SIZE>*)(pMbox->pQueue));
00361   SYS_ARCH_UNPROTECT(lev);
00362 
00363 }
00364 
00365 /*
00366 Posts the "msg" to the mailbox.
00367 */
00368 void sys_mbox_post(sys_mbox_t* pMbox, void *msg)
00369 {
00370 
00371   if(msg == NULL)
00372   {
00373     ERR("NULL");
00374     Thread::wait(100);
00375   }
00376 
00377   ((Queue<void,QUEUE_SIZE>*)(pMbox->pQueue))->put(msg, osWaitForever);
00378 
00379 }
00380 
00381 /*
00382 Blocks the thread until a message arrives in the mailbox, but does not
00383 block the thread longer than timeout milliseconds (similar to the
00384 sys_arch_sem_wait() function). The msg argument is a pointer to the
00385 message in the mailbox and may be NULL to indicate that the message
00386 should be dropped. This should return either SYS_ARCH_TIMEOUT or the
00387 number of milliseconds elapsed waiting for a message.
00388 */
00389 u32_t sys_arch_mbox_fetch(sys_mbox_t* pMbox, void **msg, u32_t timeout)
00390 {
00391   Timer t;
00392   uint32_t timeout_queue;
00393   int time_spent;
00394   osEvent evt;
00395   
00396   timeout_queue = (timeout != 0) ? timeout : osWaitForever /*block indefinitely*/;
00397   
00398   t.start();
00399   evt = ((Queue<void,QUEUE_SIZE>*)(pMbox->pQueue))->get(timeout_queue);
00400   if(evt.status != osEventMessage)
00401   {
00402     return SYS_ARCH_TIMEOUT;
00403   }
00404   time_spent = t.read_ms();
00405   if(msg!=NULL)
00406   {
00407     *msg = evt.value.p;
00408   }
00409   else
00410   {
00411     ERR("Dropped");
00412     Thread::wait(100);
00413   }
00414   return time_spent; 
00415 }
00416 
00417 /*
00418 This is similar to sys_arch_mbox_fetch, however if a message is not
00419 present in the mailbox, it immediately returns with the code
00420 SYS_MBOX_EMPTY. On success 0 is returned with msg pointing to the
00421 message retrieved from the mailbox.
00422 */
00423 u32_t sys_arch_mbox_tryfetch(sys_mbox_t* pMbox, void **msg)
00424 {
00425 
00426   osEvent evt;
00427 
00428   evt = ((Queue<void,QUEUE_SIZE>*)(pMbox->pQueue))->get(0);
00429   if(evt.status != osEventMessage)
00430   {
00431     return SYS_MBOX_EMPTY;
00432   }
00433   if(msg!=NULL)
00434   {
00435     *msg = evt.value.p;
00436   }
00437   else
00438   {
00439     ERR("Dropped");
00440     Thread::wait(100);
00441   }
00442 
00443   return ERR_OK; 
00444 }
00445 
00446 /*
00447 Tries to post a message to mbox by polling (no timeout).
00448 */
00449 #define X() do{(*((volatile uint32_t *)0x40024048))=__LINE__;}while(0)
00450 #define D(d) do{(*((volatile uint32_t *)0x4002404C))=d;}while(0)
00451 err_t sys_mbox_trypost(sys_mbox_t* pMbox, void *msg)
00452 {
00453   int ret;
00454 
00455   if(msg == NULL)
00456   {
00457     ERR("NULL");
00458     Thread::wait(100);
00459   }
00460 
00461   ret = ((Queue<void,QUEUE_SIZE>*)(pMbox->pQueue))->put(msg,0);
00462   if(ret != osOK)
00463   {
00464     ERR("FULL");
00465     return ERR_MEM; 
00466   }
00467 
00468   return ERR_OK;
00469 }
00470 
00471 /** Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid */
00472 int sys_mbox_valid(sys_mbox_t *pMbox)
00473 {
00474 
00475   if (pMbox->pQueue != NULL)
00476   {
00477 
00478     return (pMbox->valid);
00479   }
00480 
00481   return false;
00482 }
00483 
00484 /** Set an mbox invalid so that sys_mbox_valid returns 0 */
00485 void sys_mbox_set_invalid(sys_mbox_t *pMbox)
00486 {
00487 
00488   pMbox->valid = false;
00489 
00490 }
00491 #else
00492 
00493 /** Check if an mbox is valid/allocated: return 1 for valid, 0 for invalid */
00494 int sys_mbox_valid(sys_mbox_t *pMbox)
00495 {
00496   return (pMbox->valid);
00497 }
00498 
00499 /** Set an mbox invalid so that sys_mbox_valid returns 0 */
00500 void sys_mbox_set_invalid(sys_mbox_t *pMbox)
00501 {
00502   pMbox->valid = false;
00503 }
00504 
00505 /*-----------------------------------------------------------------------------------*/
00506 err_t
00507 sys_mbox_new(sys_mbox_t* mb, int size)
00508 {
00509   LWIP_UNUSED_ARG(size);
00510 
00511   mb->first = mb->last = 0;
00512   sys_sem_new(&mb->not_empty, 0);
00513   sys_sem_new(&mb->not_full, 0);
00514   sys_sem_new(&mb->mutex, 1);
00515   mb->wait_send = 0;
00516   mb->valid=true;
00517 
00518   return ERR_OK;
00519 }
00520 /*-----------------------------------------------------------------------------------*/
00521 void
00522 sys_mbox_free(sys_mbox_t* mb)
00523 {
00524   if ((mb != NULL)) {
00525     sys_arch_sem_wait(&mb->mutex, 0);
00526 
00527     sys_sem_free(&mb->not_empty);
00528     sys_sem_free(&mb->not_full);
00529     sys_sem_free(&mb->mutex);
00530     //mb->not_empty = mb->not_full = mb->mutex = NULL;
00531     mb->valid=false;
00532     /*  LWIP_DEBUGF("sys_mbox_free: mbox 0x%lx\n", mbox); */
00533   }
00534 }
00535 /*-----------------------------------------------------------------------------------*/
00536 err_t
00537 sys_mbox_trypost(sys_mbox_t* mb, void *msg)
00538 {
00539   u8_t first;
00540   LWIP_ASSERT("invalid mbox", (mb != NULL) );
00541 
00542   sys_arch_sem_wait(&mb->mutex, 0);
00543 
00544   LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_trypost: mbox %p msg %p\n",
00545                           (void *)mb, (void *)msg));
00546 
00547   if ((mb->last + 1) >= (mb->first + SYS_MBOX_SIZE)) {
00548     sys_sem_signal(&mb->mutex);
00549     return ERR_MEM;
00550   }
00551 
00552   mb->msgs[mb->last % SYS_MBOX_SIZE] = msg;
00553 
00554   if (mb->last == mb->first) {
00555     first = 1;
00556   } else {
00557     first = 0;
00558   }
00559 
00560   mb->last++;
00561 
00562   if (first) {
00563     sys_sem_signal(&mb->not_empty);
00564   }
00565 
00566   sys_sem_signal(&mb->mutex);
00567 
00568   return ERR_OK;
00569 }
00570 /*-----------------------------------------------------------------------------------*/
00571 void
00572 sys_mbox_post(sys_mbox_t* mb, void *msg)
00573 {
00574   u8_t first;
00575   LWIP_ASSERT("invalid mbox", (mb != NULL));
00576 
00577   sys_arch_sem_wait(&mb->mutex, 0);
00578 
00579   LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_post: mbox %p msg %p\n", (void *)mb, (void *)msg));
00580 
00581   while ((mb->last + 1) >= (mb->first + SYS_MBOX_SIZE)) {
00582     mb->wait_send++;
00583     sys_sem_signal(&mb->mutex);
00584     sys_arch_sem_wait(&mb->not_full, 0);
00585     sys_arch_sem_wait(&mb->mutex, 0);
00586     mb->wait_send--;
00587   }
00588 
00589   mb->msgs[mb->last % SYS_MBOX_SIZE] = msg;
00590 
00591   if (mb->last == mb->first) {
00592     first = 1;
00593   } else {
00594     first = 0;
00595   }
00596 
00597   mb->last++;
00598 
00599   if (first) {
00600     sys_sem_signal(&mb->not_empty);
00601   }
00602 
00603   sys_sem_signal(&mb->mutex);
00604 }
00605 /*-----------------------------------------------------------------------------------*/
00606 u32_t
00607 sys_arch_mbox_tryfetch(sys_mbox_t* mb, void **msg)
00608 {
00609   LWIP_ASSERT("invalid mbox", (mb != NULL));
00610 
00611   sys_arch_sem_wait(&mb->mutex, 0);
00612 
00613   if (mb->first == mb->last) {
00614     sys_sem_signal(&mb->mutex);
00615     return SYS_MBOX_EMPTY;
00616   }
00617 
00618   if (msg != NULL) {
00619     LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p msg %p\n", (void *)mb, *msg));
00620     *msg = mb->msgs[mb->first % SYS_MBOX_SIZE];
00621   }
00622   else{
00623     LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_tryfetch: mbox %p, null msg\n", (void *)mb));
00624   }
00625 
00626   mb->first++;
00627 
00628   if (mb->wait_send) {
00629     sys_sem_signal(&mb->not_full);
00630   }
00631 
00632   sys_sem_signal(&mb->mutex);
00633 
00634   return 0;
00635 }
00636 /*-----------------------------------------------------------------------------------*/
00637 u32_t
00638 sys_arch_mbox_fetch(sys_mbox_t* mb, void **msg, u32_t timeout)
00639 {
00640   u32_t time_needed = 0;
00641   LWIP_ASSERT("invalid mbox", (mb != NULL));
00642 
00643   /* The mutex lock is quick so we don't bother with the timeout
00644      stuff here. */
00645   sys_arch_sem_wait(&mb->mutex, 0);
00646 
00647   while (mb->first == mb->last) {
00648     sys_sem_signal(&mb->mutex);
00649 
00650     /* We block while waiting for a mail to arrive in the mailbox. We
00651        must be prepared to timeout. */
00652     if (timeout != 0) {
00653       time_needed = sys_arch_sem_wait(&mb->not_empty, timeout);
00654 
00655       if (time_needed == SYS_ARCH_TIMEOUT) {
00656         return SYS_ARCH_TIMEOUT;
00657       }
00658     } else {
00659       sys_arch_sem_wait(&mb->not_empty, 0);
00660     }
00661     sys_arch_sem_wait(&mb->mutex, 0);
00662   }
00663 
00664   if (msg != NULL) {
00665     LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p msg %p\n", (void *)mb, *msg));
00666     *msg = mb->msgs[mb->first % SYS_MBOX_SIZE];
00667   }
00668   else{
00669     LWIP_DEBUGF(SYS_DEBUG, ("sys_mbox_fetch: mbox %p, null msg\n", (void *)mb));
00670   }
00671 
00672   mb->first++;
00673 
00674   if (mb->wait_send) {
00675     sys_sem_signal(&mb->not_full);
00676   }
00677 
00678   sys_sem_signal(&mb->mutex);
00679 
00680   return time_needed;
00681 }
00682 
00683 #endif
00684 
00685 //Threads and timeout lists
00686 
00687 /*
00688 The implementation reserves a pool of threads that can be used by
00689 LwIP in order to only use static allocation
00690 */
00691 
00692 //sys_thread_t* lwip_system_threads = NULL; //Linked list of active threads
00693 //struct sys_timeo* lwip_system_timeouts = NULL; // Default timeouts list for lwIP
00694 
00695 /*
00696 Instanciates a thread for LwIP:
00697 name is the thread name. thread(arg) is the call made as the thread's
00698 entry point. stacksize is the recommended stack size for this thread.
00699 prio is the priority that lwIP asks for. Stack size(s) and priority(ies)
00700 are defined in lwipopts.h.
00701 */
00702 
00703 struct sys_thread
00704 {
00705   Thread* pTask;
00706   //struct sys_timeo* timeouts;
00707   struct sys_thread* next;
00708 };
00709 struct sys_thread* lwip_system_threads = NULL; //Linked list of active threads
00710 
00711 sys_thread_t sys_thread_new(const char *name, lwip_thread_fn fn, void *arg, int stacksize, int prio)
00712 {
00713   SYS_ARCH_DECL_PROTECT(lev);
00714   SYS_ARCH_PROTECT(lev); //Protect this section
00715   struct sys_thread* pT = new struct sys_thread;
00716   SYS_ARCH_UNPROTECT(lev);
00717   if(pT==NULL)
00718   {
00719     ERR("No mem");
00720     return;
00721   }
00722 
00723   SYS_ARCH_PROTECT(lev); //Protect this section
00724 
00725   //Link in list
00726   pT->next = lwip_system_threads;
00727   lwip_system_threads = pT;
00728 
00729 
00730   SYS_ARCH_UNPROTECT(lev); //Protect this section
00731 
00732   DBG("Trying to create new thread of stacksize %d and prio %d", stacksize, prio);
00733 
00734   //Must be done at the very end because the task will start immediately
00735   SYS_ARCH_PROTECT(lev);
00736   pT->pTask = new Thread((void (*)(void const *argument))fn, arg, (osPriority)prio /*FIXME*/, stacksize);
00737   SYS_ARCH_UNPROTECT(lev);
00738 
00739   DBG("pT->pTask=%p", pT->pTask);
00740   if(pT->pTask == NULL)
00741   {
00742     SYS_ARCH_PROTECT(lev);
00743 
00744     //Unlink
00745     if(pT == lwip_system_threads)
00746     {
00747       lwip_system_threads = pT->next;
00748     }
00749     else
00750     {
00751       struct sys_thread* pLT = lwip_system_threads;
00752       while(pLT->next != pT)
00753       {
00754         pLT = pLT->next;
00755       }
00756       pLT->next = pT->next;
00757     }
00758     SYS_ARCH_UNPROTECT(lev); //Release protection
00759     SYS_ARCH_PROTECT(lev);
00760     delete pT;
00761     SYS_ARCH_UNPROTECT(lev);
00762     ERR("No mem");
00763     return;
00764   }
00765 
00766   DBG("Thread OK");
00767   return; //Return the thread
00768 }
00769 #if 0
00770 struct sys_timeouts *sys_arch_timeouts(void) {
00771   struct sys_timeo* timeouts;
00772   
00773   SYS_ARCH_DECL_PROTECT(lev);
00774   
00775   timeouts = &lwip_system_timeouts; //If there is no match, just return the system-wide default version
00776   
00777   SYS_ARCH_PROTECT(lev); //Protect this section
00778   
00779   sys_thread_t pT = lwip_system_threads;
00780 
00781   // Search the threads list for the thread that is currently running
00782   for ( ; pT!=NULL; pT=pT->next)
00783   {
00784      if ( Task::isCurrent(pT->pTask) )
00785      {
00786       timeouts = pT->timeouts;
00787      }
00788   }
00789   
00790   SYS_ARCH_UNPROTECT(lev); //Release protection
00791 
00792   return timeouts;
00793 }
00794 #endif
00795 /*
00796 Architecture-specific initialization.
00797 */
00798 static Timer sys_jiffies_timer;
00799 
00800 void sys_init(void)
00801 {
00802   sys_jiffies_timer.start();
00803 }
00804 
00805 /*
00806 Used by PPP as a timestamp-ish value.
00807 */
00808 u32_t sys_jiffies(void)
00809 {
00810   static u32_t jiffies = 0;
00811   jiffies += 1 + sys_jiffies_timer.read_ms()/10;
00812   sys_jiffies_timer.reset();
00813 
00814   return jiffies;
00815 }
00816 
00817 /**
00818  * Sleep for some ms. Timeouts are NOT processed while sleeping.
00819  *
00820  * @param ms number of milliseconds to sleep
00821  */
00822 //Change DG, arch specific
00823 void
00824 sys_msleep(u32_t ms)
00825 {
00826   Thread::wait(ms);
00827 }
00828 
00829 } //extern "C"