lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-users] usage of ethernetif_input in a single-threaded environment


From: samyuktar
Subject: [lwip-users] usage of ethernetif_input in a single-threaded environment with NO_SYS=0
Date: Mon, 25 Nov 2019 13:41:51 -0700 (MST)

Hello,

I am using a CC1352P1 TI launchpad interfaced with an ENC28J60 SPI-Ethernet
bridge. I saw the driver for the ethernet interface and have inserted my
functions into the interface. I have NO_SYS = 0 and am using threads in my
environment. One of the threads will be responsible only for lwIP functions,
and the other thread will be completely unrelated. I am unclear on a few
things:

As of now, I have set netif_add with the input function as ethernet_input.
netif->input is called within ethernetif_input. I have initialized the
interface as follows: 


IP4_ADDR(&gw, 192,168,1,1);
  IP4_ADDR(&ip_addr, 192,168,1,10);
  IP4_ADDR(&netmask, 255,255,255,0);
  IP4_ADDR(&dest_ip, 192,168,1,11);
  /* First add the interface - ethernetif_init is defined in ethernetif.c,
for NO_SYS=0 input function is ethernetif_input */
  /* set this netif as the default */
  netif_set_default(netif_add(&mynetif, &ip_addr, &netmask,
                              &gw, NULL, (netif_init_fn) ethernetif_init,
ethernetif_input));
  /* Bring the interface up */
  netif_set_up(&mynetif);

  /* Bring the link up */
  netif_set_link_up(&mynetif);


ethernetif_input calls low_level_input, which calls my ethernet drivers to
transmit and receive. I am able to transmit and receive raw ethernet frames
without lwIP if I directly insert the MAC address - in ethernetif.c, I
believe I am supposed to insert my low level driver functions, which I did.
Here's my ethernetif_input: 



/**
 * This function should be called when a packet is ready to be read
 * from the interface. It uses the function low_level_input() that
 * should handle the actual reception of bytes from the network
 * interface. Then the type of the received packet is determined and
 * the appropriate input function is called.
 * I will have to decide when to call this function
 * @param netif the lwip network interface structure for this ethernetif
 */
void
ethernetif_input(struct netif *netif)
{
  struct ethernetif *ethernetif;
  struct eth_hdr *ethhdr;
  struct pbuf *p;

  ethernetif = netif->state;

  Display_printf(display, 0, 0, "I'm in ethernetif input function: %s", p);
  /* move received packet into a new pbuf */
  p = low_level_input(netif); 
  Display_printf(display, 0, 0, "Out of the low_level_input function: %s",
p);
  /* if no packet could be read, silently ignore this */
  if (p != NULL) {
    /* pass all packets to ethernet_input, which decides what packets it
supports */
    if (netif->input(p, netif) != ERR_OK) {   // netif->input here would be
ethernet_input
        status_blink_gr_LED();
      LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: IP input error\n"));
      pbuf_free(p);
      p = NULL;
    }
  }
}



and my low_level_input looks like the following : 

/**
 * Should allocate a pbuf and transfer the bytes of the incoming
 * packet from the interface into the pbuf.
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @return a pbuf filled with the received packet (including MAC header)
 *         NULL on memory error
 */
static struct pbuf *
low_level_input(struct netif *netif)
{
  struct ethernetif *ethernetif = netif->state;
  struct pbuf *p, *q;
  u16_t len;

  /* Obtain the size of the packet and put it into the "len"
     variable. */
  uint8_t header[6];
  len = ethernet_getRecvLength(header);   // my own low level enc28j60
ethernet drivr fn to get packet length
#if ETH_PAD_SIZE 
  len += ETH_PAD_SIZE; /* allow room for Ethernet padding */
#endif

  /* We allocate a pbuf chain of pbufs from the pool. */
  p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL);

  if (p != NULL) {

#if ETH_PAD_SIZE
    pbuf_remove_header(p, ETH_PAD_SIZE); /* drop the padding word */
#endif

    /* We iterate over the pbuf chain until we have read the entire
     * packet into the pbuf. */
    for (q = p; q != NULL; q = q->next) {
      /* Read enough bytes to fill this pbuf in the chain. The
       * available data in the pbuf is given by the q->len
       * variable.
       * This does not necessarily have to be a memcpy, you can also
preallocate
       * pbufs for a DMA-enabled MAC and after receiving truncate it to the
       * actually received size. In this case, ensure the tot_len member of
the
       * pbuf is the sum of the chained pbuf len members.
       */
//      read data into(q->payload, q->len);
        ethernet_packetReceive(q->payload, q->len); // my own low level enc28j60
ethernet drivr fn to read the received packet
        Display_printf(display, 0, 0, "Data being input: %s, len: %d\n",
q->payload, q->len);
    }   
//    Not sure what to put in here - maybe I can write a read ack function
//    acknowledge that packet has been read();
   Display_printf(display, 0, 0, "Received data\n");
   //status_blink_LED();
    MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
    if (((u8_t *)p->payload)[0] & 1) {
      /* broadcast or multicast packet*/
      MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
    } else {
      /* unicast packet*/
      MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
    }
#if ETH_PAD_SIZE
    pbuf_add_header(p, ETH_PAD_SIZE); /* reclaim the padding word */
#endif

    LINK_STATS_INC(link.recv);
  } else {
    
//    What is the drop_packet function here? Write a function to drop a
packet
//    drop packet();
    LINK_STATS_INC(link.memerr);
    LINK_STATS_INC(link.drop);
    MIB2_STATS_NETIF_INC(netif, ifindiscards);
  }

  Display_printf(display, 0, 0, "Print p: %s", p);
  return p;
}


and in the netif thread, I poll a register on the ENC28J60 which indicates
that a packet has been received. When that packet has been received, or when
the register returns a positive value, I call ethernetif_input function with
my initialized interface.

Currently, there's only this single thread running in my code. Even so, My
code gets stuck as soon as it says a packet has been received and I believe
it gets stuck in the ethernet_input function. Am I understanding something
completely wrong?

I read elsewhere that I can say NO_SYS=0 for a system where there's an RTOS
and I am using threads, which is my system. It also says that I should use
tcpip_init and tcpip_input() in that initialization, but I am unable to see
where I would put in my low level ethernet_receive function in that case.
There's no slot to enter my low level driver function, like there is in
ethernetif_input.

Is ethernetif_input to be used with NO_SYS=1 or NO_SYS=0?





--
Sent from: http://lwip.100.n7.nabble.com/lwip-users-f3.html



reply via email to

[Prev in Thread] Current Thread [Next in Thread]