Hello,
I'm using a version of lwip 1.4.1 ported to an NXP LPC18xx, the demo code
of which can be had here
<http://www.lpcware.com/content/nxpfile/lwip-lpc-port-file-v110>. I'm
essentially replicating their 'sa_tcpecho' project with my own
project/board. So far, everything is working great except for transmission,
and I had somewhat of a general question on transmit pbuf usage. This
chip/example uses a DMA to fill pre-allocated pbufs with data.
The chip I'm using has a fast section of memory where receive pbufs are
preallocated in lwipopts and my driver, and the example code above runs
well executing a TCP echo. However, for the transmit function they simply
pass it the receive pbuf (duh, echo). I'm wondering, if I have an array
somewhere in slow memory that I want to transmit in response to the
reception (call it Xmt.Data[100] with a length of Xmt.Length), how do I go
about doing this? Do I use pbuf_alloc(PBUF_RAW, (u16_t) EMAC_ETH_MAX_FLEN,
PBUF_POOL) and copy the data into this new pbuf from slow memory? If I've
already got a pool, do I need to allocate/deallocate anything? Any demo
code using a transmit pbuf or any personal experience would help me out a
great deal in understanding transmit pbuf usage. Thanks in advance, and
sorry for the text-full question.
enum echo_states
{
ES_NONE = 0,
ES_ACCEPTED,
ES_RECEIVED,
ES_CLOSING
};
struct echo_state
{
u8_t state;
u8_t retries;
struct tcp_pcb *pcb;
/* pbuf (chain) to recycle */
struct pbuf *p;
};
err_t
echo_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
struct echo_state *es;
err_t ret_err;
LWIP_ASSERT("arg != NULL",arg != NULL);
es = (struct echo_state *)arg;
if (p == NULL)
{
/* remote host closed connection */
es->state = ES_CLOSING;
if(es->p == NULL)
{
/* we're done sending, close it */
echo_close(tpcb, es);
}
else
{
/* we're not done yet */
tcp_sent(tpcb, echo_sent);
echo_send(tpcb, es);
}
ret_err = ERR_OK;
}
else if(err != ERR_OK)
{
/* cleanup, for unkown reason */
if (p != NULL)
{
es->p = NULL;
pbuf_free(p);
}
ret_err = err;
}
else if(es->state == ES_ACCEPTED)
{
/* first data chunk in p->payload */
es->state = ES_RECEIVED;
/* store reference to incoming pbuf (chain) */
es->p = p;
/* install send completion notifier */
tcp_sent(tpcb, echo_sent);
/* *******NEED TO BUILD DIFFERENT XMT MESSAGE HERE AND PASS CORRECT PBUF TO
echo_send() ***** */
echo_send(tpcb, es);
ret_err = ERR_OK;
}
else if (es->state == ES_RECEIVED)
{
/* read some more data */
if(es->p == NULL)
{
es->p = p;
tcp_sent(tpcb, echo_sent);
echo_send(tpcb, es);
}
else
{
struct pbuf *ptr;
/* chain pbufs to the end of what we recv'ed previously */
ptr = es->p;
pbuf_chain(ptr,p);
}
ret_err = ERR_OK;
}
else if(es->state == ES_CLOSING)
{
/* odd case, remote side closing twice, trash data */
tcp_recved(tpcb, p->tot_len);
es->p = NULL;
pbuf_free(p);
ret_err = ERR_OK;
}
else
{
/* unkown es->state, trash data */
tcp_recved(tpcb, p->tot_len);
es->p = NULL;
pbuf_free(p);
ret_err = ERR_OK;
}
return ret_err;
}
void
echo_send(struct tcp_pcb *tpcb, struct echo_state *es)
{
struct pbuf *ptr;
err_t wr_err = ERR_OK;
while ((wr_err == ERR_OK) &&
(es->p != NULL) &&
(es->p->len <= tcp_sndbuf(tpcb)))
{
ptr = es->p;
/* enqueue data for transmission */
wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);
if (wr_err == ERR_OK)
{
u16_t plen;
u8_t freed;
plen = ptr->len;
/* continue with next pbuf in chain (if any) */
es->p = ptr->next;
if(es->p != NULL)
{
/* new reference! */
pbuf_ref(es->p);
}
/* chop first pbuf from chain */
do
{
/* try hard to free pbuf */
freed = pbuf_free(ptr);
}
while(freed == 0);
/* we can read more data now */
tcp_recved(tpcb, plen);
}
else if(wr_err == ERR_MEM)
{
/* we are low on memory, try later / harder, defer to poll */
es->p = ptr;
}
else
{
/* other problem ?? */
}
}
}
- Justin
_______________________________________________
lwip-users mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/lwip-users