Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
lwip_slipif.c
Go to the documentation of this file.
00001 /** 00002 * @file 00003 * SLIP Interface 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 00012 * modification, are permitted provided that the following conditions 00013 * are met: 00014 * 1. Redistributions of source code must retain the above copyright 00015 * notice, this list of conditions and the following disclaimer. 00016 * 2. Redistributions in binary form must reproduce the above copyright 00017 * notice, this list of conditions and the following disclaimer in the 00018 * documentation and/or other materials provided with the distribution. 00019 * 3. Neither the name of the Institute nor the names of its contributors 00020 * may be used to endorse or promote products derived from this software 00021 * without specific prior written permission. 00022 * 00023 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00024 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00025 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00026 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00027 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00028 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00029 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00030 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00031 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00032 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00033 * SUCH DAMAGE. 00034 * 00035 * This file is built upon the file: src/arch/rtxc/netif/sioslip.c 00036 * 00037 * Author: Magnus Ivarsson <magnus.ivarsson(at)volvo.com> 00038 * Simon Goldschmidt 00039 */ 00040 00041 00042 /** 00043 * @defgroup slipif SLIP netif 00044 * @ingroup addons 00045 * 00046 * This is an arch independent SLIP netif. The specific serial hooks must be 00047 * provided by another file. They are sio_open, sio_read/sio_tryread and sio_send 00048 * 00049 * Usage: This netif can be used in three ways:\n 00050 * 1) For NO_SYS==0, an RX thread can be used which blocks on sio_read() 00051 * until data is received.\n 00052 * 2) In your main loop, call slipif_poll() to check for new RX bytes, 00053 * completed packets are fed into netif->input().\n 00054 * 3) Call slipif_received_byte[s]() from your serial RX ISR and 00055 * slipif_process_rxqueue() from your main loop. ISR level decodes 00056 * packets and puts completed packets on a queue which is fed into 00057 * the stack from the main loop (needs SYS_LIGHTWEIGHT_PROT for 00058 * pbuf_alloc to work on ISR level!). 00059 * 00060 */ 00061 00062 #include "netif/slipif.h" 00063 #include "lwip/opt.h" 00064 00065 #include "lwip/def.h" 00066 #include "lwip/pbuf.h" 00067 #include "lwip/stats.h" 00068 #include "lwip/snmp.h" 00069 #include "lwip/sys.h" 00070 #include "lwip/sio.h" 00071 00072 #define SLIP_END 0xC0 /* 0300: start and end of every packet */ 00073 #define SLIP_ESC 0xDB /* 0333: escape start (one byte escaped data follows) */ 00074 #define SLIP_ESC_END 0xDC /* 0334: following escape: original byte is 0xC0 (END) */ 00075 #define SLIP_ESC_ESC 0xDD /* 0335: following escape: original byte is 0xDB (ESC) */ 00076 00077 /** Maximum packet size that is received by this netif */ 00078 #ifndef SLIP_MAX_SIZE 00079 #define SLIP_MAX_SIZE 1500 00080 #endif 00081 00082 /** Define this to the interface speed for SNMP 00083 * (sio_fd is the sio_fd_t returned by sio_open). 00084 * The default value of zero means 'unknown'. 00085 */ 00086 #ifndef SLIP_SIO_SPEED 00087 #define SLIP_SIO_SPEED(sio_fd) 0 00088 #endif 00089 00090 enum slipif_recv_state { 00091 SLIP_RECV_NORMAL, 00092 SLIP_RECV_ESCAPE 00093 }; 00094 00095 struct slipif_priv { 00096 sio_fd_t sd; 00097 /* q is the whole pbuf chain for a packet, p is the current pbuf in the chain */ 00098 struct pbuf *p, *q; 00099 u8_t state; 00100 u16_t i, recved; 00101 #if SLIP_RX_FROM_ISR 00102 struct pbuf *rxpackets; 00103 #endif 00104 }; 00105 00106 /** 00107 * Send a pbuf doing the necessary SLIP encapsulation 00108 * 00109 * Uses the serial layer's sio_send() 00110 * 00111 * @param netif the lwip network interface structure for this slipif 00112 * @param p the pbuf chain packet to send 00113 * @return always returns ERR_OK since the serial layer does not provide return values 00114 */ 00115 static err_t 00116 slipif_output(struct netif *netif, struct pbuf *p) 00117 { 00118 struct slipif_priv *priv; 00119 struct pbuf *q; 00120 u16_t i; 00121 u8_t c; 00122 00123 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00124 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00125 LWIP_ASSERT("p != NULL", (p != NULL)); 00126 00127 LWIP_DEBUGF(SLIP_DEBUG, ("slipif_output(%"U16_F"): sending %"U16_F" bytes\n", (u16_t)netif->num, p->tot_len)); 00128 priv = (struct slipif_priv *)netif->state; 00129 00130 /* Send pbuf out on the serial I/O device. */ 00131 /* Start with packet delimiter. */ 00132 sio_send(SLIP_END, priv->sd); 00133 00134 for (q = p; q != NULL; q = q->next) { 00135 for (i = 0; i < q->len; i++) { 00136 c = ((u8_t *)q->payload)[i]; 00137 switch (c) { 00138 case SLIP_END: 00139 /* need to escape this byte (0xC0 -> 0xDB, 0xDC) */ 00140 sio_send(SLIP_ESC, priv->sd); 00141 sio_send(SLIP_ESC_END, priv->sd); 00142 break; 00143 case SLIP_ESC: 00144 /* need to escape this byte (0xDB -> 0xDB, 0xDD) */ 00145 sio_send(SLIP_ESC, priv->sd); 00146 sio_send(SLIP_ESC_ESC, priv->sd); 00147 break; 00148 default: 00149 /* normal byte - no need for escaping */ 00150 sio_send(c, priv->sd); 00151 break; 00152 } 00153 } 00154 } 00155 /* End with packet delimiter. */ 00156 sio_send(SLIP_END, priv->sd); 00157 return ERR_OK; 00158 } 00159 00160 #if LWIP_IPV4 00161 /** 00162 * Send a pbuf doing the necessary SLIP encapsulation 00163 * 00164 * Uses the serial layer's sio_send() 00165 * 00166 * @param netif the lwip network interface structure for this slipif 00167 * @param p the pbuf chain packet to send 00168 * @param ipaddr the ip address to send the packet to (not used for slipif) 00169 * @return always returns ERR_OK since the serial layer does not provide return values 00170 */ 00171 static err_t 00172 slipif_output_v4(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr) 00173 { 00174 LWIP_UNUSED_ARG(ipaddr); 00175 return slipif_output(netif, p); 00176 } 00177 #endif /* LWIP_IPV4 */ 00178 00179 #if LWIP_IPV6 00180 /** 00181 * Send a pbuf doing the necessary SLIP encapsulation 00182 * 00183 * Uses the serial layer's sio_send() 00184 * 00185 * @param netif the lwip network interface structure for this slipif 00186 * @param p the pbuf chain packet to send 00187 * @param ipaddr the ip address to send the packet to (not used for slipif) 00188 * @return always returns ERR_OK since the serial layer does not provide return values 00189 */ 00190 static err_t 00191 slipif_output_v6(struct netif *netif, struct pbuf *p, const ip6_addr_t *ipaddr) 00192 { 00193 LWIP_UNUSED_ARG(ipaddr); 00194 return slipif_output(netif, p); 00195 } 00196 #endif /* LWIP_IPV6 */ 00197 00198 /** 00199 * Handle the incoming SLIP stream character by character 00200 * 00201 * @param netif the lwip network interface structure for this slipif 00202 * @param c received character (multiple calls to this function will 00203 * return a complete packet, NULL is returned before - used for polling) 00204 * @return The IP packet when SLIP_END is received 00205 */ 00206 static struct pbuf* 00207 slipif_rxbyte(struct netif *netif, u8_t c) 00208 { 00209 struct slipif_priv *priv; 00210 struct pbuf *t; 00211 00212 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00213 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00214 00215 priv = (struct slipif_priv *)netif->state; 00216 00217 switch (priv->state) { 00218 case SLIP_RECV_NORMAL: 00219 switch (c) { 00220 case SLIP_END: 00221 if (priv->recved > 0) { 00222 /* Received whole packet. */ 00223 /* Trim the pbuf to the size of the received packet. */ 00224 pbuf_realloc(priv->q, priv->recved); 00225 00226 LINK_STATS_INC(link.recv); 00227 00228 LWIP_DEBUGF(SLIP_DEBUG, ("slipif: Got packet (%"U16_F" bytes)\n", priv->recved)); 00229 t = priv->q; 00230 priv->p = priv->q = NULL; 00231 priv->i = priv->recved = 0; 00232 return t; 00233 } 00234 return NULL; 00235 case SLIP_ESC: 00236 priv->state = SLIP_RECV_ESCAPE; 00237 return NULL; 00238 default: 00239 break; 00240 } /* end switch (c) */ 00241 break; 00242 case SLIP_RECV_ESCAPE: 00243 /* un-escape END or ESC bytes, leave other bytes 00244 (although that would be a protocol error) */ 00245 switch (c) { 00246 case SLIP_ESC_END: 00247 c = SLIP_END; 00248 break; 00249 case SLIP_ESC_ESC: 00250 c = SLIP_ESC; 00251 break; 00252 default: 00253 break; 00254 } 00255 priv->state = SLIP_RECV_NORMAL; 00256 break; 00257 default: 00258 break; 00259 } /* end switch (priv->state) */ 00260 00261 /* byte received, packet not yet completely received */ 00262 if (priv->p == NULL) { 00263 /* allocate a new pbuf */ 00264 LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: alloc\n")); 00265 priv->p = pbuf_alloc(PBUF_LINK, (PBUF_POOL_BUFSIZE - PBUF_LINK_HLEN - PBUF_LINK_ENCAPSULATION_HLEN), PBUF_POOL); 00266 00267 if (priv->p == NULL) { 00268 LINK_STATS_INC(link.drop); 00269 LWIP_DEBUGF(SLIP_DEBUG, ("slipif_input: no new pbuf! (DROP)\n")); 00270 /* don't process any further since we got no pbuf to receive to */ 00271 return NULL; 00272 } 00273 00274 if (priv->q != NULL) { 00275 /* 'chain' the pbuf to the existing chain */ 00276 pbuf_cat(priv->q, priv->p); 00277 } else { 00278 /* p is the first pbuf in the chain */ 00279 priv->q = priv->p; 00280 } 00281 } 00282 00283 /* this automatically drops bytes if > SLIP_MAX_SIZE */ 00284 if ((priv->p != NULL) && (priv->recved <= SLIP_MAX_SIZE)) { 00285 ((u8_t *)priv->p->payload)[priv->i] = c; 00286 priv->recved++; 00287 priv->i++; 00288 if (priv->i >= priv->p->len) { 00289 /* on to the next pbuf */ 00290 priv->i = 0; 00291 if (priv->p->next != NULL && priv->p->next->len > 0) { 00292 /* p is a chain, on to the next in the chain */ 00293 priv->p = priv->p->next; 00294 } else { 00295 /* p is a single pbuf, set it to NULL so next time a new 00296 * pbuf is allocated */ 00297 priv->p = NULL; 00298 } 00299 } 00300 } 00301 return NULL; 00302 } 00303 00304 /** Like slipif_rxbyte, but passes completed packets to netif->input 00305 * 00306 * @param netif The lwip network interface structure for this slipif 00307 * @param c received character 00308 */ 00309 static void 00310 slipif_rxbyte_input(struct netif *netif, u8_t c) 00311 { 00312 struct pbuf *p; 00313 p = slipif_rxbyte(netif, c); 00314 if (p != NULL) { 00315 if (netif->input(p, netif) != ERR_OK) { 00316 pbuf_free(p); 00317 } 00318 } 00319 } 00320 00321 #if SLIP_USE_RX_THREAD 00322 /** 00323 * The SLIP input thread. 00324 * 00325 * Feed the IP layer with incoming packets 00326 * 00327 * @param nf the lwip network interface structure for this slipif 00328 */ 00329 static void 00330 slipif_loop_thread(void *nf) 00331 { 00332 u8_t c; 00333 struct netif *netif = (struct netif *)nf; 00334 struct slipif_priv *priv = (struct slipif_priv *)netif->state; 00335 00336 while (1) { 00337 if (sio_read(priv->sd, &c, 1) > 0) { 00338 slipif_rxbyte_input(netif, c); 00339 } 00340 } 00341 } 00342 #endif /* SLIP_USE_RX_THREAD */ 00343 00344 /** 00345 * SLIP netif initialization 00346 * 00347 * Call the arch specific sio_open and remember 00348 * the opened device in the state field of the netif. 00349 * 00350 * @param netif the lwip network interface structure for this slipif 00351 * @return ERR_OK if serial line could be opened, 00352 * ERR_MEM if no memory could be allocated, 00353 * ERR_IF is serial line couldn't be opened 00354 * 00355 * @note netif->num must contain the number of the serial port to open 00356 * (0 by default). If netif->state is != NULL, it is interpreted as an 00357 * u8_t pointer pointing to the serial port number instead of netif->num. 00358 * 00359 */ 00360 err_t 00361 slipif_init(struct netif *netif) 00362 { 00363 struct slipif_priv *priv; 00364 u8_t sio_num; 00365 00366 LWIP_DEBUGF(SLIP_DEBUG, ("slipif_init: netif->num=%"U16_F"\n", (u16_t)netif->num)); 00367 00368 /* Allocate private data */ 00369 priv = (struct slipif_priv *)mem_malloc(sizeof(struct slipif_priv)); 00370 if (!priv) { 00371 return ERR_MEM; 00372 } 00373 00374 netif->name[0] = 's'; 00375 netif->name[1] = 'l'; 00376 #if LWIP_IPV4 00377 netif->output = slipif_output_v4; 00378 #endif /* LWIP_IPV4 */ 00379 #if LWIP_IPV6 00380 netif->output_ip6 = slipif_output_v6; 00381 #endif /* LWIP_IPV6 */ 00382 netif->mtu = SLIP_MAX_SIZE; 00383 00384 /* netif->state or netif->num contain the port number */ 00385 if (netif->state != NULL) { 00386 sio_num = *(u8_t*)netif->state; 00387 } else { 00388 sio_num = netif->num; 00389 } 00390 /* Try to open the serial port. */ 00391 priv->sd = sio_open(sio_num); 00392 if (!priv->sd) { 00393 /* Opening the serial port failed. */ 00394 mem_free(priv); 00395 return ERR_IF; 00396 } 00397 00398 /* Initialize private data */ 00399 priv->p = NULL; 00400 priv->q = NULL; 00401 priv->state = SLIP_RECV_NORMAL; 00402 priv->i = 0; 00403 priv->recved = 0; 00404 #if SLIP_RX_FROM_ISR 00405 priv->rxpackets = NULL; 00406 #endif 00407 00408 netif->state = priv; 00409 00410 /* initialize the snmp variables and counters inside the struct netif */ 00411 MIB2_INIT_NETIF(netif, snmp_ifType_slip, SLIP_SIO_SPEED(priv->sd)); 00412 00413 #if SLIP_USE_RX_THREAD 00414 /* Create a thread to poll the serial line. */ 00415 sys_thread_new(SLIPIF_THREAD_NAME, slipif_loop_thread, netif, 00416 SLIPIF_THREAD_STACKSIZE, SLIPIF_THREAD_PRIO); 00417 #endif /* SLIP_USE_RX_THREAD */ 00418 return ERR_OK; 00419 } 00420 00421 /** 00422 * Polls the serial device and feeds the IP layer with incoming packets. 00423 * 00424 * @param netif The lwip network interface structure for this slipif 00425 */ 00426 void 00427 slipif_poll(struct netif *netif) 00428 { 00429 u8_t c; 00430 struct slipif_priv *priv; 00431 00432 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00433 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00434 00435 priv = (struct slipif_priv *)netif->state; 00436 00437 while (sio_tryread(priv->sd, &c, 1) > 0) { 00438 slipif_rxbyte_input(netif, c); 00439 } 00440 } 00441 00442 #if SLIP_RX_FROM_ISR 00443 /** 00444 * Feeds the IP layer with incoming packets that were receive 00445 * 00446 * @param netif The lwip network interface structure for this slipif 00447 */ 00448 void 00449 slipif_process_rxqueue(struct netif *netif) 00450 { 00451 struct slipif_priv *priv; 00452 SYS_ARCH_DECL_PROTECT(old_level); 00453 00454 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00455 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00456 00457 priv = (struct slipif_priv *)netif->state; 00458 00459 SYS_ARCH_PROTECT(old_level); 00460 while (priv->rxpackets != NULL) { 00461 struct pbuf *p = priv->rxpackets; 00462 #if SLIP_RX_QUEUE 00463 /* dequeue packet */ 00464 struct pbuf *q = p; 00465 while ((q->len != q->tot_len) && (q->next != NULL)) { 00466 q = q->next; 00467 } 00468 priv->rxpackets = q->next; 00469 q->next = NULL; 00470 #else /* SLIP_RX_QUEUE */ 00471 priv->rxpackets = NULL; 00472 #endif /* SLIP_RX_QUEUE */ 00473 SYS_ARCH_UNPROTECT(old_level); 00474 if (netif->input(p, netif) != ERR_OK) { 00475 pbuf_free(p); 00476 } 00477 SYS_ARCH_PROTECT(old_level); 00478 } 00479 } 00480 00481 /** Like slipif_rxbyte, but queues completed packets. 00482 * 00483 * @param netif The lwip network interface structure for this slipif 00484 * @param data Received serial byte 00485 */ 00486 static void 00487 slipif_rxbyte_enqueue(struct netif *netif, u8_t data) 00488 { 00489 struct pbuf *p; 00490 struct slipif_priv *priv = (struct slipif_priv *)netif->state; 00491 SYS_ARCH_DECL_PROTECT(old_level); 00492 00493 p = slipif_rxbyte(netif, data); 00494 if (p != NULL) { 00495 SYS_ARCH_PROTECT(old_level); 00496 if (priv->rxpackets != NULL) { 00497 #if SLIP_RX_QUEUE 00498 /* queue multiple pbufs */ 00499 struct pbuf *q = p; 00500 while (q->next != NULL) { 00501 q = q->next; 00502 } 00503 q->next = p; 00504 } else { 00505 #else /* SLIP_RX_QUEUE */ 00506 pbuf_free(priv->rxpackets); 00507 } 00508 { 00509 #endif /* SLIP_RX_QUEUE */ 00510 priv->rxpackets = p; 00511 } 00512 SYS_ARCH_UNPROTECT(old_level); 00513 } 00514 } 00515 00516 /** 00517 * Process a received byte, completed packets are put on a queue that is 00518 * fed into IP through slipif_process_rxqueue(). 00519 * 00520 * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. 00521 * 00522 * @param netif The lwip network interface structure for this slipif 00523 * @param data received character 00524 */ 00525 void 00526 slipif_received_byte(struct netif *netif, u8_t data) 00527 { 00528 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00529 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00530 slipif_rxbyte_enqueue(netif, data); 00531 } 00532 00533 /** 00534 * Process multiple received byte, completed packets are put on a queue that is 00535 * fed into IP through slipif_process_rxqueue(). 00536 * 00537 * This function can be called from ISR if SYS_LIGHTWEIGHT_PROT is enabled. 00538 * 00539 * @param netif The lwip network interface structure for this slipif 00540 * @param data received character 00541 * @param len Number of received characters 00542 */ 00543 void 00544 slipif_received_bytes(struct netif *netif, u8_t *data, u8_t len) 00545 { 00546 u8_t i; 00547 u8_t *rxdata = data; 00548 LWIP_ASSERT("netif != NULL", (netif != NULL)); 00549 LWIP_ASSERT("netif->state != NULL", (netif->state != NULL)); 00550 00551 for (i = 0; i < len; i++, rxdata++) { 00552 slipif_rxbyte_enqueue(netif, *rxdata); 00553 } 00554 } 00555 #endif /* SLIP_RX_FROM_ISR */
Generated on Sun Jul 17 2022 08:25:25 by 1.7.2