[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lwip-users] usage of ethernetif_input in a single-threaded environm
From: |
address@hidden |
Subject: |
Re: [lwip-users] usage of ethernetif_input in a single-threaded environment with NO_SYS=0 |
Date: |
Wed, 27 Nov 2019 20:19:41 +0100 |
User-agent: |
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Thunderbird/60.9.1 |
Am 25.11.2019 um 21:41 schrieb samyuktar:
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));
This is wrong. The input function passed here is the one your driver
input function will call. This has to be 'ethernet_input' without an OS
or 'tcpip_input' with an OS (unless you know better).
In contrast to this, 'ethernetif_input' is your driver input function.
You'll have to take care of calling this, e.g. after an interrupt or via
some kind of polling.
/* 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
How can that be ethernet_input when you passed ethernetif_input above
(as argument to netif_add)?
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 guess you mean ethernetif_input here? I think you have a recursive
call loop: your ethernetif_input calls itself again because netif->input
== ethernetif_input.
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?
And again you seem to confuse ethernet_input with ethernetif_input?
Regards,
Simon