Some quick code to use UDP-only (no TCP) with mBed. Echos received packets and sends packets when a button is pressed
sys.c
00001 /** 00002 * @file 00003 * lwIP Operating System abstraction 00004 * 00005 */ 00006 00007 /* 00008 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00009 * All rights reserved. 00010 * 00011 * Redistribution and use in source and binary forms, with or without modification, 00012 * are permitted provided that the following conditions are met: 00013 * 00014 * 1. Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright notice, 00017 * this list of conditions and the following disclaimer in the documentation 00018 * and/or other materials provided with the distribution. 00019 * 3. The name of the author may not be used to endorse or promote products 00020 * derived from this software without specific prior written permission. 00021 * 00022 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00023 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00025 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00026 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00027 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00028 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00029 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00030 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00031 * OF SUCH DAMAGE. 00032 * 00033 * This file is part of the lwIP TCP/IP stack. 00034 * 00035 * Author: Adam Dunkels <adam@sics.se> 00036 * 00037 */ 00038 00039 #include "lwip/opt.h" 00040 00041 #if (NO_SYS == 0) /* don't build if not configured for use in lwipopts.h */ 00042 00043 #include "lwip/sys.h" 00044 #include "lwip/def.h" 00045 #include "lwip/memp.h" 00046 #include "lwip/tcpip.h" 00047 00048 /** 00049 * Struct used for sys_sem_wait_timeout() to tell wether the time 00050 * has run out or the semaphore has really become available. 00051 */ 00052 struct sswt_cb 00053 { 00054 s16_t timeflag; 00055 sys_sem_t *psem; 00056 }; 00057 00058 /** 00059 * Wait (forever) for a message to arrive in an mbox. 00060 * While waiting, timeouts (for this thread) are processed. 00061 * 00062 * @param mbox the mbox to fetch the message from 00063 * @param msg the place to store the message 00064 */ 00065 void 00066 sys_mbox_fetch(sys_mbox_t mbox, void **msg) 00067 { 00068 u32_t time_needed; 00069 struct sys_timeouts *timeouts; 00070 struct sys_timeo *tmptimeout; 00071 sys_timeout_handler h; 00072 void *arg; 00073 00074 again: 00075 timeouts = sys_arch_timeouts(); 00076 00077 if (!timeouts || !timeouts->next) { 00078 UNLOCK_TCPIP_CORE(); 00079 time_needed = sys_arch_mbox_fetch(mbox, msg, 0); 00080 LOCK_TCPIP_CORE(); 00081 } else { 00082 if (timeouts->next->time > 0) { 00083 UNLOCK_TCPIP_CORE(); 00084 time_needed = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time); 00085 LOCK_TCPIP_CORE(); 00086 } else { 00087 time_needed = SYS_ARCH_TIMEOUT; 00088 } 00089 00090 if (time_needed == SYS_ARCH_TIMEOUT) { 00091 /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message 00092 could be fetched. We should now call the timeout handler and 00093 deallocate the memory allocated for the timeout. */ 00094 tmptimeout = timeouts->next; 00095 timeouts->next = tmptimeout->next; 00096 h = tmptimeout->h; 00097 arg = tmptimeout->arg; 00098 memp_free(MEMP_SYS_TIMEOUT, tmptimeout); 00099 if (h != NULL) { 00100 LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", (void*)&h, arg)); 00101 h(arg); 00102 } 00103 00104 /* We try again to fetch a message from the mbox. */ 00105 goto again; 00106 } else { 00107 /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout 00108 occured. The time variable is set to the number of 00109 milliseconds we waited for the message. */ 00110 if (time_needed < timeouts->next->time) { 00111 timeouts->next->time -= time_needed; 00112 } else { 00113 timeouts->next->time = 0; 00114 } 00115 } 00116 } 00117 } 00118 00119 /** 00120 * Wait (forever) for a semaphore to become available. 00121 * While waiting, timeouts (for this thread) are processed. 00122 * 00123 * @param sem semaphore to wait for 00124 */ 00125 void 00126 sys_sem_wait(sys_sem_t sem) 00127 { 00128 u32_t time_needed; 00129 struct sys_timeouts *timeouts; 00130 struct sys_timeo *tmptimeout; 00131 sys_timeout_handler h; 00132 void *arg; 00133 00134 again: 00135 00136 timeouts = sys_arch_timeouts(); 00137 00138 if (!timeouts || !timeouts->next) { 00139 sys_arch_sem_wait(sem, 0); 00140 } else { 00141 if (timeouts->next->time > 0) { 00142 time_needed = sys_arch_sem_wait(sem, timeouts->next->time); 00143 } else { 00144 time_needed = SYS_ARCH_TIMEOUT; 00145 } 00146 00147 if (time_needed == SYS_ARCH_TIMEOUT) { 00148 /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message 00149 could be fetched. We should now call the timeout handler and 00150 deallocate the memory allocated for the timeout. */ 00151 tmptimeout = timeouts->next; 00152 timeouts->next = tmptimeout->next; 00153 h = tmptimeout->h; 00154 arg = tmptimeout->arg; 00155 memp_free(MEMP_SYS_TIMEOUT, tmptimeout); 00156 if (h != NULL) { 00157 LWIP_DEBUGF(SYS_DEBUG, ("ssw h=%p(%p)\n", (void*)&h, (void *)arg)); 00158 h(arg); 00159 } 00160 00161 /* We try again to fetch a message from the mbox. */ 00162 goto again; 00163 } else { 00164 /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout 00165 occured. The time variable is set to the number of 00166 milliseconds we waited for the message. */ 00167 if (time_needed < timeouts->next->time) { 00168 timeouts->next->time -= time_needed; 00169 } else { 00170 timeouts->next->time = 0; 00171 } 00172 } 00173 } 00174 } 00175 00176 /** 00177 * Create a one-shot timer (aka timeout). Timeouts are processed in the 00178 * following cases: 00179 * - while waiting for a message using sys_mbox_fetch() 00180 * - while waiting for a semaphore using sys_sem_wait() or sys_sem_wait_timeout() 00181 * - while sleeping using the inbuilt sys_msleep() 00182 * 00183 * @param msecs time in milliseconds after that the timer should expire 00184 * @param h callback function to call when msecs have elapsed 00185 * @param arg argument to pass to the callback function 00186 */ 00187 void 00188 sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg) 00189 { 00190 struct sys_timeouts *timeouts; 00191 struct sys_timeo *timeout, *t; 00192 00193 timeout = memp_malloc(MEMP_SYS_TIMEOUT); 00194 if (timeout == NULL) { 00195 LWIP_ASSERT("sys_timeout: timeout != NULL", timeout != NULL); 00196 return; 00197 } 00198 timeout->next = NULL; 00199 timeout->h = h; 00200 timeout->arg = arg; 00201 timeout->time = msecs; 00202 00203 timeouts = sys_arch_timeouts(); 00204 00205 LWIP_DEBUGF(SYS_DEBUG, ("sys_timeout: %p msecs=%"U32_F" h=%p arg=%p\n", 00206 (void *)timeout, msecs, (void*)&h, (void *)arg)); 00207 00208 if (timeouts == NULL) { 00209 LWIP_ASSERT("sys_timeout: timeouts != NULL", timeouts != NULL); 00210 return; 00211 } 00212 00213 if (timeouts->next == NULL) { 00214 timeouts->next = timeout; 00215 return; 00216 } 00217 00218 if (timeouts->next->time > msecs) { 00219 timeouts->next->time -= msecs; 00220 timeout->next = timeouts->next; 00221 timeouts->next = timeout; 00222 } else { 00223 for(t = timeouts->next; t != NULL; t = t->next) { 00224 timeout->time -= t->time; 00225 if (t->next == NULL || t->next->time > timeout->time) { 00226 if (t->next != NULL) { 00227 t->next->time -= timeout->time; 00228 } 00229 timeout->next = t->next; 00230 t->next = timeout; 00231 break; 00232 } 00233 } 00234 } 00235 } 00236 00237 /** 00238 * Go through timeout list (for this task only) and remove the first matching 00239 * entry, even though the timeout has not triggered yet. 00240 * 00241 * @note This function only works as expected if there is only one timeout 00242 * calling 'h' in the list of timeouts. 00243 * 00244 * @param h callback function that would be called by the timeout 00245 * @param arg callback argument that would be passed to h 00246 */ 00247 void 00248 sys_untimeout(sys_timeout_handler h, void *arg) 00249 { 00250 struct sys_timeouts *timeouts; 00251 struct sys_timeo *prev_t, *t; 00252 00253 timeouts = sys_arch_timeouts(); 00254 00255 if (timeouts == NULL) { 00256 LWIP_ASSERT("sys_untimeout: timeouts != NULL", timeouts != NULL); 00257 return; 00258 } 00259 if (timeouts->next == NULL) { 00260 return; 00261 } 00262 00263 for (t = timeouts->next, prev_t = NULL; t != NULL; prev_t = t, t = t->next) { 00264 if ((t->h == h) && (t->arg == arg)) { 00265 /* We have a match */ 00266 /* Unlink from previous in list */ 00267 if (prev_t == NULL) 00268 timeouts->next = t->next; 00269 else 00270 prev_t->next = t->next; 00271 /* If not the last one, add time of this one back to next */ 00272 if (t->next != NULL) 00273 t->next->time += t->time; 00274 memp_free(MEMP_SYS_TIMEOUT, t); 00275 return; 00276 } 00277 } 00278 return; 00279 } 00280 00281 /** 00282 * Timeout handler function for sys_sem_wait_timeout() 00283 * 00284 * @param arg struct sswt_cb* used to signal a semaphore and end waiting. 00285 */ 00286 static void 00287 sswt_handler(void *arg) 00288 { 00289 struct sswt_cb *sswt_cb = (struct sswt_cb *) arg; 00290 00291 /* Timeout. Set flag to TRUE and signal semaphore */ 00292 sswt_cb->timeflag = 1; 00293 sys_sem_signal(*(sswt_cb->psem)); 00294 } 00295 00296 /** 00297 * Wait for a semaphore with timeout (specified in ms) 00298 * 00299 * @param sem semaphore to wait 00300 * @param timeout timeout in ms (0: wait forever) 00301 * @return 0 on timeout, 1 otherwise 00302 */ 00303 int 00304 sys_sem_wait_timeout(sys_sem_t sem, u32_t timeout) 00305 { 00306 struct sswt_cb sswt_cb; 00307 00308 sswt_cb.psem = &sem; 00309 sswt_cb.timeflag = 0; 00310 00311 /* If timeout is zero, then just wait forever */ 00312 if (timeout > 0) { 00313 /* Create a timer and pass it the address of our flag */ 00314 sys_timeout(timeout, sswt_handler, &sswt_cb); 00315 } 00316 sys_sem_wait(sem); 00317 /* Was it a timeout? */ 00318 if (sswt_cb.timeflag) { 00319 /* timeout */ 00320 return 0; 00321 } else { 00322 /* Not a timeout. Remove timeout entry */ 00323 sys_untimeout(sswt_handler, &sswt_cb); 00324 return 1; 00325 } 00326 } 00327 00328 /** 00329 * Sleep for some ms. Timeouts are processed while sleeping. 00330 * 00331 * @param ms number of milliseconds to sleep 00332 */ 00333 void 00334 sys_msleep(u32_t ms) 00335 { 00336 sys_sem_t delaysem = sys_sem_new(0); 00337 00338 sys_sem_wait_timeout(delaysem, ms); 00339 00340 sys_sem_free(delaysem); 00341 } 00342 00343 00344 #endif /* NO_SYS */
Generated on Tue Jul 12 2022 19:17:24 by 1.7.2