Ethernet for Nucleo and Disco board STM32F746 works with gcc and arm. IAC is untested

Dependencies:   mbed-rtos

Dependents:   IMU_ethernet

Fork of F7_Ethernet by Dieter Graef

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ethernetif.c Source File

ethernetif.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  * Ethernet Interface Skeleton
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 /*
00040  * This file is a skeleton for developing Ethernet network interface
00041  * drivers for lwIP. Add code to the low_level functions and do a
00042  * search-and-replace for the word "ethernetif" to replace it with
00043  * something that better describes your network interface.
00044  */
00045 
00046 #include "lwip/opt.h"
00047 
00048 #if 0 /* don't build, this is only a skeleton, see previous comment */
00049 
00050 #include "lwip/def.h"
00051 #include "lwip/mem.h"
00052 #include "lwip/pbuf.h"
00053 #include <lwip/stats.h>
00054 #include <lwip/snmp.h>
00055 #include "netif/etharp.h"
00056 #include "netif/ppp_oe.h"
00057 
00058 /* Define those to better describe your network interface. */
00059 #define IFNAME0 'e'
00060 #define IFNAME1 'n'
00061 
00062 /**
00063  * Helper struct to hold private data used to operate your ethernet interface.
00064  * Keeping the ethernet address of the MAC in this struct is not necessary
00065  * as it is already kept in the struct netif.
00066  * But this is only an example, anyway...
00067  */
00068 struct ethernetif {
00069   struct eth_addr *ethaddr;
00070   /* Add whatever per-interface state that is needed here. */
00071 };
00072 
00073 /* Forward declarations. */
00074 static void  ethernetif_input(struct netif *netif);
00075 
00076 /**
00077  * In this function, the hardware should be initialized.
00078  * Called from ethernetif_init().
00079  *
00080  * @param netif the already initialized lwip network interface structure
00081  *        for this ethernetif
00082  */
00083 static void
00084 low_level_init(struct netif *netif)
00085 {
00086   struct ethernetif *ethernetif = netif->state;
00087   
00088   /* set MAC hardware address length */
00089   netif->hwaddr_len = ETHARP_HWADDR_LEN;
00090 
00091   /* set MAC hardware address */
00092   netif->hwaddr[0] = ;
00093   ...
00094   netif->hwaddr[5] = ;
00095 
00096   /* maximum transfer unit */
00097   netif->mtu = 1500;
00098   
00099   /* device capabilities */
00100   /* don't set NETIF_FLAG_ETHARP if this device is not an ethernet one */
00101   netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
00102  
00103   /* Do whatever else is needed to initialize interface. */  
00104 }
00105 
00106 /**
00107  * This function should do the actual transmission of the packet. The packet is
00108  * contained in the pbuf that is passed to the function. This pbuf
00109  * might be chained.
00110  *
00111  * @param netif the lwip network interface structure for this ethernetif
00112  * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
00113  * @return ERR_OK if the packet could be sent
00114  *         an err_t value if the packet couldn't be sent
00115  *
00116  * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
00117  *       strange results. You might consider waiting for space in the DMA queue
00118  *       to become availale since the stack doesn't retry to send a packet
00119  *       dropped because of memory failure (except for the TCP timers).
00120  */
00121 
00122 static err_t
00123 low_level_output(struct netif *netif, struct pbuf *p)
00124 {
00125   struct ethernetif *ethernetif = netif->state;
00126   struct pbuf *q;
00127 
00128   initiate transfer();
00129   
00130 #if ETH_PAD_SIZE
00131   pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
00132 #endif
00133 
00134   for(q = p; q != NULL; q = q->next) {
00135     /* Send the data from the pbuf to the interface, one pbuf at a
00136        time. The size of the data in each pbuf is kept in the ->len
00137        variable. */
00138     send data from(q->payload, q->len);
00139   }
00140 
00141   signal that packet should be sent();
00142 
00143 #if ETH_PAD_SIZE
00144   pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
00145 #endif
00146   
00147   LINK_STATS_INC(link.xmit);
00148 
00149   return ERR_OK;
00150 }
00151 
00152 /**
00153  * Should allocate a pbuf and transfer the bytes of the incoming
00154  * packet from the interface into the pbuf.
00155  *
00156  * @param netif the lwip network interface structure for this ethernetif
00157  * @return a pbuf filled with the received packet (including MAC header)
00158  *         NULL on memory error
00159  */
00160 static struct pbuf *
00161 low_level_input(struct netif *netif)
00162 {
00163   struct ethernetif *ethernetif = netif->state;
00164   struct pbuf *p, *q;
00165   u16_t len;
00166 
00167   /* Obtain the size of the packet and put it into the "len"
00168      variable. */
00169   len = ;
00170 
00171 #if ETH_PAD_SIZE
00172   len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
00173 #endif
00174 
00175   /* We allocate a pbuf chain of pbufs from the pool. */
00176   p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);
00177   
00178   if (p != NULL) {
00179 
00180 #if ETH_PAD_SIZE
00181     pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */
00182 #endif
00183 
00184     /* We iterate over the pbuf chain until we have read the entire
00185      * packet into the pbuf. */
00186     for(q = p; q != NULL; q = q->next) {
00187       /* Read enough bytes to fill this pbuf in the chain. The
00188        * available data in the pbuf is given by the q->len
00189        * variable.
00190        * This does not necessarily have to be a memcpy, you can also preallocate
00191        * pbufs for a DMA-enabled MAC and after receiving truncate it to the
00192        * actually received size. In this case, ensure the tot_len member of the
00193        * pbuf is the sum of the chained pbuf len members.
00194        */
00195       read data into(q->payload, q->len);
00196     }
00197     acknowledge that packet has been read();
00198 
00199 #if ETH_PAD_SIZE
00200     pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
00201 #endif
00202 
00203     LINK_STATS_INC(link.recv);
00204   } else {
00205     drop packet();
00206     LINK_STATS_INC(link.memerr);
00207     LINK_STATS_INC(link.drop);
00208   }
00209 
00210   return p;  
00211 }
00212 
00213 /**
00214  * This function should be called when a packet is ready to be read
00215  * from the interface. It uses the function low_level_input() that
00216  * should handle the actual reception of bytes from the network
00217  * interface. Then the type of the received packet is determined and
00218  * the appropriate input function is called.
00219  *
00220  * @param netif the lwip network interface structure for this ethernetif
00221  */
00222 static void
00223 ethernetif_input(struct netif *netif)
00224 {
00225   struct ethernetif *ethernetif;
00226   struct eth_hdr *ethhdr;
00227   struct pbuf *p;
00228 
00229   ethernetif = netif->state;
00230 
00231   /* move received packet into a new pbuf */
00232   p = low_level_input(netif);
00233   /* no packet could be read, silently ignore this */
00234   if (p == NULL) return;
00235   /* points to packet payload, which starts with an Ethernet header */
00236   ethhdr = p->payload;
00237 
00238   switch (htons(ethhdr->type)) {
00239   /* IP or ARP packet? */
00240   case ETHTYPE_IP:
00241   case ETHTYPE_ARP:
00242 #if PPPOE_SUPPORT
00243   /* PPPoE packet? */
00244   case ETHTYPE_PPPOEDISC:
00245   case ETHTYPE_PPPOE:
00246 #endif /* PPPOE_SUPPORT */
00247     /* full packet send to tcpip_thread to process */
00248     if (netif->input(p, netif)!=ERR_OK)
00249      { LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
00250        pbuf_free(p);
00251        p = NULL;
00252      }
00253     break;
00254 
00255   default:
00256     pbuf_free(p);
00257     p = NULL;
00258     break;
00259   }
00260 }
00261 
00262 /**
00263  * Should be called at the beginning of the program to set up the
00264  * network interface. It calls the function low_level_init() to do the
00265  * actual setup of the hardware.
00266  *
00267  * This function should be passed as a parameter to netif_add().
00268  *
00269  * @param netif the lwip network interface structure for this ethernetif
00270  * @return ERR_OK if the loopif is initialized
00271  *         ERR_MEM if private data couldn't be allocated
00272  *         any other err_t on error
00273  */
00274 err_t
00275 ethernetif_init(struct netif *netif)
00276 {
00277   struct ethernetif *ethernetif;
00278 
00279   LWIP_ASSERT("netif != NULL", (netif != NULL));
00280     
00281   ethernetif = mem_malloc(sizeof(struct ethernetif));
00282   if (ethernetif == NULL) {
00283     LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_init: out of memory\n"));
00284     return ERR_MEM;
00285   }
00286 
00287 #if LWIP_NETIF_HOSTNAME
00288   /* Initialize interface hostname */
00289   netif->hostname = "lwip";
00290 #endif /* LWIP_NETIF_HOSTNAME */
00291 
00292   /*
00293    * Initialize the snmp variables and counters inside the struct netif.
00294    * The last argument should be replaced with your link speed, in units
00295    * of bits per second.
00296    */
00297   NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, LINK_SPEED_OF_YOUR_NETIF_IN_BPS);
00298 
00299   netif->state = ethernetif;
00300   netif->name[0] = IFNAME0;
00301   netif->name[1] = IFNAME1;
00302   /* We directly use etharp_output() here to save a function call.
00303    * You can instead declare your own function an call etharp_output()
00304    * from it if you have to do some checks before sending (e.g. if link
00305    * is available...) */
00306   netif->output = etharp_output;
00307   netif->linkoutput = low_level_output;
00308   
00309   ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
00310   
00311   /* initialize the hardware */
00312   low_level_init(netif);
00313 
00314   return ERR_OK;
00315 }
00316 
00317 #endif /* 0 */