[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lwip-users] Deinitializing the LwIP stack
From: |
OK2NMZ |
Subject: |
[lwip-users] Deinitializing the LwIP stack |
Date: |
Wed, 21 Aug 2013 14:21:24 -0700 (PDT) |
Hello everyone,
I have been struggling for several days making work LwIP stack HEAD version
with CoOS RTOS from CooCox on LPC1768 NXP microcontroller.
After many problems with memory allocation and SRAM fragmentation (I have
only 32+32kB of memory) I decided to use POOLs in my system.
Nevertheless, sometimes, when I send a lot of traffic to my device, ICMP
echoes (PING) stops to work... The interesting thing is, that my telnet
server keeps running (I can disconnect, connect etc...). I have noticed,
that the problem occurrs SOMETIMES when my system runs low on memory. I
suspect the function low_level_output to somehow badly allocate and free the
pbufs, but I cant figure out how...
Since I really need something robust (the problem occurs really rarely, but
it does), I have for now implemented the LwIP deinitialization. Here is what
I basicaly do:
- I disable ethernet interrupt, I deinit the MCU MAC interface.
- I send a message to a "manager" thread, where I then kill the thread where
the uni-threaded version (NO_OS) is running.
- I clear all pointers to TCP connections to NULL (I added this to
tcp_init() function, which is being called on lwip init)
- during memp_init(), I clear entirely the memp pools.
The system is capable of reseting many times, each time it restarts with no
problem...
The beautiful thing I appreciate in this approach is, that I dont need to
reset the whole MCU, other tasks can keep running. I only kill and restart
the TCP/IP stack if needed.
Do you think, that my lwip "deinit" is correct? Should I add something?
Thank you for your suggestions, if you are trying to implement something
simillar, I can share some code with you.
I attach the lpc_low_level_output() function, which I suspect from bad
behavior (sometimes, rarely):
Thank you,
Marek
static err_t lpc_low_level_output(struct netif *netif, struct pbuf *p) {
struct lpc_enetdata *lpc_enetif = netif->state;
struct pbuf *q;
u8_t *dst;
u32_t idx, sz = 0;
err_t err = ERR_OK;
struct pbuf *np;
u32_t dn, notdmasafe = 0;
/* Zero-copy TX buffers may be fragmented across mutliple payload
chains. Determine the number of descriptors needed for the
transfer. The pbuf chaining can be a mess! */
dn = (u32_t) pbuf_clen(p);
/* Test to make sure packet addresses are DMA safe. A DMA safe
address is once that uses external memory or periphheral RAM.
IRAM and FLASH are not safe! */
for (q = p; q != NULL; q = q->next)
notdmasafe += lpc_packet_addr_notsafe(q->payload);
#if LPC_TX_PBUF_BOUNCE_EN==1
/* If the pbuf is not DMA safe, a new bounce buffer (pbuf) will be
created that will be used instead. This requires an copy from the
non-safe DMA region to the new pbuf */
if (notdmasafe) {
/* Allocate a pbuf in DMA memory */
np = pbuf_alloc(PBUF_RAW, p->tot_len, PBUF_RAM);
if (np == NULL)
return ERR_MEM;
/* This buffer better be contiguous! */
LWIP_ASSERT("lpc_low_level_output: New transmit pbuf is
chained",
(pbuf_clen(np) == 1));
/* Copy to DMA safe pbuf */
dst = (u8_t *) np->payload;
for (q = p; q != NULL; q = q->next) {
/* Copy the buffer to the descriptor's buffer */
MEMCPY(dst, (u8_t *) q->payload, q->len);
dst += q->len;
}
np->len = p->tot_len;
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
("lpc_low_level_output: Switched to DMA safe
buffer, old=%p, new=%p\n",
q, np));
/* use the new buffer for descrptor queueing. The original pbuf
will
be de-allocated outsuide this driver. */
p = np;
dn = 1;
}
#else
if (notdmasafe)
LWIP_ASSERT("lpc_low_level_output: Not a DMA safe pbuf", (notdmasafe ==
0));
#endif
/* Wait until enough descriptors are available for the transfer. */
/* THIS WILL BLOCK UNTIL THERE ARE ENOUGH DESCRIPTORS AVAILABLE */
while (dn > lpc_tx_ready(netif))
#if NO_SYS == 0
sys_arch_sem_wait(&(lpc_enetif->xTXDCountSem), 0);
#else
msDelay(1);
#endif
/* Get free TX buffer index */
idx = LPC_EMAC->TxProduceIndex;
#if NO_SYS == 0
/* Get exclusive access */
sys_mutex_lock(&lpc_enetif->TXLockMutex);
#endif
/* Prevent LWIP from de-allocating this pbuf. The driver will
free it once it's been transmitted. */
if (!notdmasafe)
pbuf_ref(p);
/* Setup transfers */
q = p;
while (dn > 0) {
dn--;
/* Only save pointer to free on last descriptor */
if (dn == 0) {
/* Save size of packet and signal it's ready */
lpc_enetif->ptxd[idx].control = (q->len - 1) |
EMAC_TCTRL_INT
| EMAC_TCTRL_LAST;
lpc_enetif->txb[idx] = q;
} else {
/* Save size of packet, descriptor is not last */
lpc_enetif->ptxd[idx].control = (q->len - 1) |
EMAC_TCTRL_INT;
lpc_enetif->txb[idx] = NULL;
}
LWIP_DEBUGF(UDP_LPC_EMAC | LWIP_DBG_TRACE,
("lpc_low_level_output: pbuf packet(%p) sent,
chain#=%d,"
" size = %d (index=%d)\n",
q->payload, dn, q->len, idx));
lpc_enetif->ptxd[idx].packet = (u32_t) q->payload;
q = q->next;
idx++;
if (idx >= LPC_NUM_BUFF_TXDESCS)
idx = 0;
}
LPC_EMAC->TxProduceIndex = idx;
LINK_STATS_INC(link.xmit);
#if NO_SYS == 0
/* Restore access */
sys_mutex_unlock(&lpc_enetif->TXLockMutex);
#endif
return ERR_OK;
}
--
View this message in context:
http://lwip.100.n7.nabble.com/Deinitializing-the-LwIP-stack-tp21803.html
Sent from the lwip-users mailing list archive at Nabble.com.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [lwip-users] Deinitializing the LwIP stack,
OK2NMZ <=